Android系统休眠对程序的影响以及处理

Android系统在用户长时间不操作时,为了节省资源,系统会选择休眠。在休眠过程中自定义的Timer、Handler、Thread、Service等都会暂停。而有时候这种机制会影响到我们程序的正常运行。

1、获取电源锁,并在执行完毕释放电源锁

public class WakeLockUtil
{
    public static WakeLock wakeLock = null;
 
    public static void acquireWakeLock(Activity myActivity)
    {
        if (null == wakeLock)
        {
            PowerManager pm = (PowerManager) myActivity.getSystemService(Context.POWER_SERVICE);
            wakeLock = pm.newWakeLock(PowerManager.ON_AFTER_RELEASE | PowerManager.PARTIAL_WAKE_LOCK, "wakeLockUtil");
            // PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的 -- 最常用,保持CPU运转
            // SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
            // SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
            // FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
            // ACQUIRE_CAUSES_WAKEUP:强制使屏幕亮起,这种锁主要针对一些必须通知用户的操作.
            // ON_AFTER_RELEASE:当锁被释放时,保持屏幕亮起一段时间
            if (null != wakeLock)
            {
                wakeLock.acquire(); // 立即获取电源锁
                // wakeLock.acquire(2000); // 2秒后获取电源锁
            }
        }
    }
 
    public static void releaseWakeLock(Activity myActivity)
    {
        if (null != wakeLock)
        {
            wakeLock.release();
            wakeLock = null;
        }
    }
}

2、利用系统闹钟定时启动service
在service的onStartCommand方法中,定时10分钟后启动自己。
如果该service进程被系统杀死,闹钟事件可能不会触发,所以将此service设置为独立进程,并加入系统自启动中。

 <service
        android:name=".LocationService"
        android:enabled="true"
        android:exported="true"
        android:process=":remote"
        android:label="LocationService">
    </service>

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.e("LocationService","onStartCommand");
   AlarmManager alarmService = (AlarmManager) getSystemService(ALARM_SERVICE);
    Intent alarmIntent = new Intent(this, LocationService.class);
    //四个参数Flags:Flags为0代表该PendingIntent不带数据
    //Flags为FLAG_CANCEL_CURRENT :如果AlarmManager管理的PendingIntent已经存在,那么将会取消当前的PendingIntent,从而创建一  个新的PendingIntent
    //Flags为PendingIntent.FLAG_UPDATE_CURRENT,要通过extra数据来区分intent,应采用PendingIntent.FLAG_UPDATE_CURRENT,且每次num不一样
    PendingIntent intentService = PendingIntent.getService(this, REQUESTCODE, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
   //(1)set(int type,long startTime,PendingIntent pi);该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟执行时间,第三个参数表示闹钟响应动作。
   //(2)setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);该方法用于设置重复闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间,第三个参数表示闹钟两次执行的间隔时间,第三个参数表示闹钟响应动作。
   //(3)setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);该方法也用于设置重复闹钟,与第二个方法相似,不过其两个闹钟执行的间隔时间不是固定的而已。
    alarmService.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+10*60*1000,intentService);
   // startLoc();
    return super.onStartCommand(intent, flags, startId);
}

type: 闹钟的类型,有五种:

AlarmManager.ELAPSED_REALTIME表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始);

AlarmManager.ELAPSED_REALTIME_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间;

AlarmManager.RTC表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间(
让定时任务的触发时间从1970年1月1日0点开始算起);

AlarmManager.RTC_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0;

AlarmManager.POWER_OFF_WAKEUP表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间;不过本状态好像受SDK版本影响,某些版本并不支持;

intervalTime:闹钟的第一次执行时间,以毫秒为单位,它必须和type相对应,比如type是AlarmManager.ELAPSED_REALTIME_WAKEUP类型,代表是使用的是相对时间,所以intervalTime必须也得是相对时间:

SystemClock.elapsedRealtime()。

SystemClock.elapsedRealtime()方法可以获取到系统开机至今所经历时间的毫秒数,

System.currentTimeMillis()方法可以获取到1970年1月1日0点至今所经历时间的毫秒数

同时定义开机广播接收和网络状态改变广播接收,启动service,来确保关机等因素导致闹钟动作不执行

<receiver android:name=".BootCompleteReceiver" >
                         <intent-filter>
                             <action android:name="android.intent.action.BOOT_COMPLETED" />
                         </intent-filter>
                     </receiver>
        <receiver android:name=".NetworkConnectChangedReceiver">
            <intent-filter>
                <action android:name="android.NET.conn.CONNECTIVITY_CHANGE" />
                <action android:name="android.Net.wifi.WIFI_STATE_CHANGED" />
                <action android:name="android.net.wifi.STATE_CHANGE" />
            </intent-filter>
        </receiver>

public class BootCompleteReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //收到开机广播
        Intent intentService = new Intent();
        intentService.setClass(context,LocationService.class);
        context.startService(intentService);
    }
}
public class NetworkConnectChangedReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            ConnectivityManager manager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            Log.e("ConnectChangedReceiver", "CONNECTIVITY_ACTION");

            NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
            if (activeNetwork != null) { // connected to the internet
                if (activeNetwork.isConnected()) {
                    if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                        // connected to wifi
                        Log.e("ConnectChangedReceiver", "当前WiFi连接可用 ");
                        FileHelper fHelper = new FileHelper(context);
                        fHelper.writeTxtToFile("当前为WiFi连接", "快递定位/", "location.txt");
                        Intent intentService = new Intent();
                        intentService.setClass(context,LocationService.class);
                        context.startService(intentService);
                    } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                        // connected to the mobile provider's data plan
                        Log.e("ConnectChangedReceiver", "当前移动网络连接可用 ");
                        FileHelper fHelper = new FileHelper(context);
                        fHelper.writeTxtToFile("当前移动网络连接", "快递定位/", "location.txt");
                        Intent intentService = new Intent();
                        intentService.setClass(context,LocationService.class);
                        context.startService(intentService);
                    }
                } else {
                    Log.e("ConnectChangedReceiver", "当前没有网络连接,请确保你已经打开网络 ");
                    FileHelper fHelper = new FileHelper(context);
                    fHelper.writeTxtToFile("当前没有网络连接", "快递定位/", "location.txt");
                }
                Log.e("ConnectChangedReceiver", "info.getTypeName()" + activeNetwork.getTypeName());
                Log.e("ConnectChangedReceiver", "getSubtypeName()" + activeNetwork.getSubtypeName());
                Log.e("ConnectChangedReceiver", "getState()" + activeNetwork.getState());
                Log.e("ConnectChangedReceiver", "getDetailedState()"
                        + activeNetwork.getDetailedState().name());
                Log.e("ConnectChangedReceiver", "getDetailedState()" + activeNetwork.getExtraInfo());
                Log.e("ConnectChangedReceiver", "getType()" + activeNetwork.getType());
            } else {   // not connected to the internet
                Log.e("ConnectChangedReceiver", "当前没有网络连接,请确保你已经打开网络 ");
                FileHelper fHelper = new FileHelper(context);
                fHelper.writeTxtToFile("当前没有网络连接", "快递定位/", "location.txt");
            }

        }
    }
}

猜你喜欢

转载自blog.csdn.net/xdy1120/article/details/85002698
今日推荐