android 8.1 监控省电模式,触发各种开关

1.流程,思路

    首先监听一个系统开机广播,开机完成后启动一个服务去注册我们要监听的系统广播,接收到之后做具体处理,

在这个流程中,遇到几个头疼的问题,第一就是监听开机广播后服务启动问题,在Android8.0(26) 以后,主要为了性能的提升,比如省电,对APP(targetsdk >= 26)的控制加强了很多。

比如不能监听大部分静态注册(在Manifest里配置)的系统广播,APP层自己的静态广播也不允许了,只能动态注册(在代码里注册),不过官网也推荐可以使用JobScheduler 代替静态广播,也是不错的方法;

还有就是启动服务也有很大的限制,APP(targetsdk >= 26)不在前台的时候再也不能启动后台服务(startService), 只能启动前台服务(两种情况,第一种是APP本身处于前台即可见状态,第二种是直接

startForegroundService),这样也是为了让用户知道有服务在运行,对于APP(targetsdk < 26)的可以正常使用,但是Settings也可以对其进行相同的控制,官网建议都用前台服务代替。

2. 具体步骤

public class BootCompleteReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if(Intent.ACTION_BOOT_COMPLETED.equals(action)) {
            Intent service = new Intent(context, RegisterService.class);
            context.startService(service);
        }
    }
}

 

public class RegisterService extends Service {

    @Override
    public void onCreate() {
        registerB();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void registerB() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
        registerReceiver(new BatterySaverGlobalReceiver(), intentFilter);
    }
}

 

 

public class BatterySaverGlobalReceiver extends BroadcastReceiver {

    private static final String TAG = "BatterySaverGlobalReceiver";
    private static final boolean DEBUG = true;
    private static final String SHARED_PREF_NAME_POWER_SAVE_MODE = "power_save_mode_settings";
    private static final String PREF_KEY_SCREEN_OFF_TIMEOUT = "screen_off_timeout";
    private Context mContext;

    private static final String PREF_KEY_LOCATION_MODE = "location_mode";
    private static final String PREF_KEY_BLUETOOTH_ENABLED = "bt_enabled";
    private static final String PREF_KEY_WIFI_ENABLED = "wifi_enabled";
    private static final String PREF_KEY_WIFI_AP_ENABLED = "wifi_ap_enabled";
    private static final String PREF_KEY_NFC_ENABLED = "nfc_enabled";
    private static final String PREF_KEY_MOBILE_DATA_ENABLED= "mobile_data_enabled";
    private BluetoothAdapter mBlueToothAdapter;
    private WifiManager mWifiManager;
    private NfcAdapter mNfcAdapter;
    private ConnectivityManager mConnManager;
    private TelephonyManager mTelephonyManager;

    @Override
    public void onReceive(Context context, Intent intent) {
        mContext = context;
        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        String action = intent.getAction();
        android.util.Log.d(TAG, "onReceive action : " + action);
        initValues();
        if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
            final boolean mode = pm.isPowerSaveMode();
            if(DEBUG) {
                android.util.Log.d(TAG, "onPowerSaveModeChanged isPowerSaveMode :" + mode);
            }
            if(mode) {
                saveSettings();
                setScreenOffTimeout(30*1000);
                setLocationMode(Settings.Secure.LOCATION_MODE_OFF);
                setBtEnabled(false);
                mWifiManager.setWifiEnabled(false);
                setWifiApEnabled(false);
                setNfcEnabled(false);
                mTelephonyManager.setDataEnabled(false);
            } else {
                restoreSettings();
            }
        }
    }

    private void initValues() {
        if (mBlueToothAdapter == null) {
            mBlueToothAdapter = BluetoothAdapter.getDefaultAdapter();
        }
        if (mWifiManager == null) {
            mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
        }
        if (mNfcAdapter == null) {
            mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
        }
        if (mConnManager == null) {
            mConnManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        }
        if (mTelephonyManager == null) {
            mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        }
    }

    private void saveSettings() {
        if(DEBUG) {
            android.util.Log.d(TAG, "saveSettings");
        }
        int timeout = 0;
        int locationMode = -1;
        try {
            timeout = Settings.System.getInt(mContext.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT);
            locationMode = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.LOCATION_MODE);
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
        boolean isBtEnabled = mBlueToothAdapter.isEnabled();
        boolean isWifiEnabled = mWifiManager.isWifiEnabled();
        boolean isWifiApEnabled = mWifiManager.isWifiApEnabled();
        boolean isNfcEnabled = mNfcAdapter.isEnabled();
        boolean isMobileDataEnabled = mTelephonyManager.isDataEnabled();
        SharedPreferences sharedPref = getPowerSaveModeSharedPref();
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putInt(PREF_KEY_SCREEN_OFF_TIMEOUT, timeout);
        editor.putInt(PREF_KEY_LOCATION_MODE, locationMode);
        editor.putBoolean(PREF_KEY_BLUETOOTH_ENABLED, isBtEnabled);
        editor.putBoolean(PREF_KEY_WIFI_ENABLED, isWifiEnabled);
        editor.putBoolean(PREF_KEY_WIFI_AP_ENABLED, isWifiApEnabled);
        editor.putBoolean(PREF_KEY_NFC_ENABLED, isNfcEnabled);
        editor.putBoolean(PREF_KEY_MOBILE_DATA_ENABLED, isMobileDataEnabled);
        editor.commit();
        if(DEBUG) {
            android.util.Log.d(TAG, "timeout :" + timeout +
                    " ,locationMode : " + locationMode + ", isBtEnabled : " + isBtEnabled +
                    ", isWifiEnabled : " + isWifiEnabled + " ,isNfcEnabled : " + isNfcEnabled +
                    ", isMobileDataEnabled : " + isMobileDataEnabled + ", isWifiApEnabled : " + isWifiApEnabled);
        }

    }

    private void restoreSettings() {
        SharedPreferences sharedPref = getPowerSaveModeSharedPref();
        int timeout = sharedPref.getInt(PREF_KEY_SCREEN_OFF_TIMEOUT, 1*60*1000);
        setScreenOffTimeout(timeout);
        if(DEBUG) {
            android.util.Log.d(TAG, "restoreSettings timeout :" + timeout);
        }
        int locationMode = sharedPref.getInt(PREF_KEY_LOCATION_MODE, -1);
        setLocationMode(locationMode);
        boolean isBtEnabled = sharedPref.getBoolean(PREF_KEY_BLUETOOTH_ENABLED, false);
        setBtEnabled(isBtEnabled);
        boolean isWifiEnabled = sharedPref.getBoolean(PREF_KEY_WIFI_ENABLED, false);
        mWifiManager.setWifiEnabled(isWifiEnabled);
        boolean isWifiApEnabled = sharedPref.getBoolean(PREF_KEY_WIFI_AP_ENABLED, false);
        setWifiApEnabled(isWifiApEnabled);
        boolean isNfcEnabled = sharedPref.getBoolean(PREF_KEY_NFC_ENABLED, false);
        setNfcEnabled(isNfcEnabled);
        boolean isMobileDataEnabled = sharedPref.getBoolean(PREF_KEY_MOBILE_DATA_ENABLED, false);
        mTelephonyManager.setDataEnabled(isMobileDataEnabled);
    }

    private SharedPreferences getPowerSaveModeSharedPref() {
        return mContext.getSharedPreferences(SHARED_PREF_NAME_POWER_SAVE_MODE, Context.MODE_PRIVATE);
    }

    private void setScreenOffTimeout(int timeout) {
        Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, timeout);
    }

    private void setLocationMode(int mode) {
        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.LOCATION_MODE, mode);
    }

    private void setBtEnabled(boolean enabled) {
        if(enabled) {
            mBlueToothAdapter.enable();
        } else {
            mBlueToothAdapter.disable();
        }
    }

    private void setNfcEnabled(boolean enabled) {
        if (enabled) {
            mNfcAdapter.enable();
        } else {
            mNfcAdapter.disable();
        }
    }

    private void setWifiApEnabled(boolean enabled) {
        if (enabled) {
            mConnManager.startTethering(ConnectivityManager.TETHERING_WIFI,
                    true, new OnStartTetheringCallback());
        } else {
            mConnManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
        }
    }

    private static final class OnStartTetheringCallback
                                 extends ConnectivityManager.OnStartTetheringCallback {

        @Override
        public void onTetheringStarted() {
            if(DEBUG) {
                android.util.Log.d(TAG, "onTetheringStarted");
            }
        }

        @Override
        public void onTetheringFailed() {
            if(DEBUG) {
                android.util.Log.d(TAG, "onTetheringFailed");
            }
        }
    }
}

posted @ 2018-05-31 16:36  Jokeyyu  阅读(3860)  评论(0编辑  收藏  举报