uk.ac.ucl.excites.sapelli.shared.util.android.DeviceControl.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.ucl.excites.sapelli.shared.util.android.DeviceControl.java

Source

/**
 * Sapelli data collection platform: http://sapelli.org
 * 
 * Copyright 2012-2016 University College London - ExCiteS group
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package uk.ac.ucl.excites.sapelli.shared.util.android;

import java.io.File;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Vibrator;
import android.provider.Settings;
import android.support.v4.content.ContextCompat;
import android.telephony.TelephonyManager;
import android.util.Log;

/**
 * @author Michalis Vitos, mstevens
 * 
 */
public final class DeviceControl {

    protected static final String TAG = "DeviceControl";
    protected static final String SAMSUNG_S7710_SD_PATH = "/storage/extSdCard";

    /**
     * Check if the device is connected to the Internet.
     * 
     * @param context
     * @return
     */
    public static boolean isOnline(Context context) {
        return isOnline(context, null);
    }

    /**
     * Check if the device is connected to the Internet via Wi-Fi.
     * 
     * @param context
     * @return
     */
    public static boolean isWifiOnline(Context context) {
        return isOnline(context, ConnectivityManager.TYPE_WIFI);
    }

    /**
     * Check if the device is connected to the Internet via mobile/cellular data (2G/3G/4G).
     * 
     * @param cntext
     * @return
     */
    public static boolean isMobileOnline(Context context) {
        return isOnline(context, ConnectivityManager.TYPE_MOBILE);
    }

    private static boolean isOnline(Context context, Integer networkType) {
        try {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo netInfo = networkType != null ? cm.getNetworkInfo(networkType) : cm.getActiveNetworkInfo();
            return netInfo != null && netInfo.isConnected();
        } catch (Exception e) {
            Log.e(DeviceControl.class.getSimpleName(), "isOnline()", e);
        }
        return false;
    }

    /**
     * Number of seconds to wait after exiting the Airplane Mode for GSM to be connected
     */
    public static final int POST_AIRPLANE_MODE_WAITING_TIME_S = 30;

    /**
     * class should not be instantiated
     */
    private DeviceControl() {
    }

    /**
     * @param context
     * @return one of the TelephoneManager#PHONE_TYPE_* values
     */
    public static int getPhoneType(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return tm.getPhoneType();
    }

    public static boolean isGSM(Context context) {
        return getPhoneType(context) == TelephonyManager.PHONE_TYPE_GSM;
    }

    public static boolean isCDMA(Context context) {
        return getPhoneType(context) == TelephonyManager.PHONE_TYPE_CDMA;
    }

    public static String getSimCountryISOCode(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return tm.getSimCountryIso();
    }

    public static String getNetworkCountryISOCode(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return tm.getNetworkCountryIso();
    }

    /**
     * Check to see if the phone is in AirplaneMode
     * 
     * @return true if it is
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    @SuppressWarnings("deprecation")
    public static boolean inAirplaneMode(Context context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
            return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0;
        else
            return Settings.Global.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
    }

    /**
     * Disable AirplaneMode and wait for {@code waitingSeconds} seconds for the device to exit
     */
    public static void disableAirplaneModeAndWait(Context context, int waitingSeconds) {
        disableAirplaneMode(context);

        // Wait
        try {
            Thread.sleep(waitingSeconds * 1000);
        } catch (Exception e) {
            Debug.e(e);
        }
    }

    /**
     * Disable AirplaneMode (Take device out of AirplaneMode)
     */
    public static void disableAirplaneMode(Context context) {
        setAirplaneMode(context, false);
    }

    /**
     * Enable AirplaneMode (Set the device in AirplaneMode)
     */
    public static void enableAirplaneMode(Context context) {
        setAirplaneMode(context, true);
    }

    /**
     * Set AirplaneMode
     * 
     * @param context
     * @param enabled pass {@code true} to put the device in airplane mode, and {@code false} to leave airplane mode
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    @SuppressWarnings("deprecation")
    private static void setAirplaneMode(Context context, boolean enabled) {
        try {
            // If airplane mode is on, value 0, else value is 1
            if (canSetAirplaneMode()) {
                Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
                        enabled ? 1 : 0);

                // Reload when the mode is changed each time by sending Intent
                Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
                intent.putExtra("state", enabled);
                context.sendBroadcast(intent);

                Debug.d("Airplane mode is: " + (enabled ? "ON" : "OFF"));
            }
        } catch (Exception e) {
            Debug.e("Error upon toggling airplane more.", e);
        }
    }

    public static boolean canSetAirplaneMode() {
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1;
    }

    public static void vibrate(Context context, int durationMS) {
        Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        vibrator.vibrate(durationMS);
    }

    /**
     * Returns the current battery level as a percentage.
     * 
     * @param context
     * @return
     */
    public static float getBatteryLevel(Context context) {
        Intent batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

        // Error checking just in case.
        if (level == -1 || scale == -1) {
            return 50.0f;
        }

        return ((float) level / (float) scale) * 100.0f;
    }

    /**
     * Increases the Media Volume
     * 
     * @param context
     */
    public static void increaseMediaVolume(Context context) {
        // Get the AudioManager
        final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        // Set the volume
        audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0);
    }

    /**
     * Decreases the Media Volume
     * 
     * @param context
     */
    public static void decreaseMediaVolume(Context context) {
        // Get the AudioManager
        final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        // Set the volume
        audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, 0);
    }

    /**
     * Decreases the Media Volume only up to half of the device's max volume
     * 
     * @param context
     */
    public static void safeDecreaseMediaVolume(Context context) {
        // Get the volume
        final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        final int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        final int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        final int minVolume = maxVolume / 2;

        Debug.d("currentVolume: " + currentVolume);
        Debug.d("maxVolume: " + maxVolume);
        Debug.d("minVolume: " + minVolume);

        if (currentVolume > minVolume)
            decreaseMediaVolume(context);
    }

    /**
     * Returns absolute paths to application-specific directories on all external storage devices where the application can place persistent files it owns as in
     * {@link ContextCompat#getExternalFilesDirs(Context, String)}. This method also hard-codes the SD Card path for devices that are not supported in Android
     * i.e. Samsung Xcover 2
     * 
     * @param context
     * @param type
     * @return
     */
    public static File[] getExternalFilesDirs(Context context, String type) {
        // Get the paths ContextCompat
        File[] paths = ContextCompat.getExternalFilesDirs(context, type);

        String manufacturer = android.os.Build.MANUFACTURER;
        String model = android.os.Build.MODEL;

        // Check if Device is Samsung GT-S7710 (a.k.a. Samsung Galaxy Xcover 2)
        if (compare(manufacturer, "Samsung") && compare(model, "GT-S7710")) {
            // Hard code the path of the external SD Card
            paths = addPath(paths, getSdCardFilesDir(context, SAMSUNG_S7710_SD_PATH));
        }

        return paths;
    }

    /**
     * Return a file with a absolute path to the application-specific directory on the external sd card. The format is
     * <code>/sdCardPath/Android/data/application package name/files</code>
     * 
     * @param context
     * @param sdCardPath
     * @return
     */
    private static File getSdCardFilesDir(Context context, String sdCardPath) {
        // Assemble the dir path
        File sdCardFile = new File(sdCardPath + File.separator + "Android/data" + File.separator
                + context.getApplicationContext().getPackageName() + File.separator + "files" + File.separator);

        // Create the path
        sdCardFile.mkdirs();

        return sdCardFile;
    }

    /**
     * Compare if two strings are equal and also perform <code>null</code> and <code>isEmpty()</code> checks
     * 
     * @param firstString
     * @param secondString
     * @return
     */
    private static boolean compare(String firstString, String secondString) {
        return firstString != null && secondString != null && !firstString.isEmpty() && !secondString.isEmpty()
                && firstString.equalsIgnoreCase(secondString);
    }

    /**
     * Add an element to the end of a File array
     * 
     * @param paths
     * @param path
     * @return
     */
    public static File[] addPath(File[] paths, File path) {
        // Create a new paths array
        File[] newPaths = new File[paths.length + 1];
        // Copy the old paths and add the new one at the end of the array
        System.arraycopy(paths, 0, newPaths, 0, paths.length);
        newPaths[paths.length] = path;

        return newPaths;
    }

}