当AlarmManager启动Activity时,PowerManager不会触发

时间:2018-03-25 14:13:03

标签: android alarmmanager android-powermanager

我是一名艺术家,我正在使用几款Android智能手机进行安装。我不是Java / Android编程方面的专家。我只是边做边学,stackoverflow非常有帮助。我正在使用具有不同Android版本的不同设备(2.3-4.4)。这些设备通过USB持续供电。该应用程序应该只在展览的开放时间运行,并在第二天自动进行。为了安排我正在使用AlarmManager。目前我在某些设备上自动重启时遇到问题,而其他设备则按预期工作。

以下是一些重要的调度表:

在AndroidManifest.xml中,我设置了以下权限:

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

其中包括WAKE_LOCK权限。

onCreate以:

开头
    @Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_start);
    pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    if (android.os.Build.VERSION.SDK_INT > 12) {
        if (pm != null) {
            wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK| PowerManager.ACQUIRE_CAUSES_WAKEUP
                    | PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
        }
    }else {
        // unlock screen and switch screen back light on
        // for Android 2.3 - disable for higher Versions
        KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        final KeyguardManager.KeyguardLock kl;
        if (km != null) {
            kl = km.newKeyguardLock("MyKeyguardLock");
            kl.disableKeyguard();
        }
        if (pm != null) {
            wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK| PowerManager.ACQUIRE_CAUSES_WAKEUP
                    | PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
        }
    }
    wakeLock.acquire();
    Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this));

使用了PowerManager.ACQUIRE_CAUSES_WAKEUP,根据我的理解,应该将屏幕设置为与其状态无关。

在onDestroy我正在使用:

        PendingIntent pendingIntent = PendingIntent.getActivity(MyApplication.getInstance().getBaseContext(),0,intent,PendingIntent.FLAG_ONE_SHOT );

        AlarmManager alarmManager = (AlarmManager) MyApplication.getInstance().getBaseContext().getSystemService(Context.ALARM_SERVICE);

        if (alarmManager != null) {
            alarmManager.set(AlarmManager.RTC_WAKEUP , System.currentTimeMillis()+delayInMillis,pendingIntent);
            Date date = new Date(System.currentTimeMillis()+delayInMillis);
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy ' 'HH:mm:ss.SSS");
            Log.i("** restart at **",dateFormat.format(date));
        }

由于“达到展览结束时间”,因此在调用finish()时执行此片段。如上所述,这适用于大多数设备。在应用程序似乎不会自动重启的那些设备上,应用程序会在屏幕打开后立即启动,例如通过按电源按钮或断开USB连接(例如连接笔记本电脑以读取logcat。)在logcat中我发现类似的东西(LG P-875 Android 4.1.3应该从14:00开始:xx)

03-25 14:00:53.516 677-748/? I/ActivityManager: START {flg=0x14000004 cmp=eu.karin_daum.daum.reality/.Start (has extras) u=0} from pid -1
03-25 14:00:53.546 677-748/? I/ActivityManager: Start proc eu.karin_daum.daum.reality for activity eu.karin_daum.daum.reality/.Start: pid=31324 uid=10099 gids={3003, 1015, 1028}

对我而言,这看起来像o.k.,但是PowerManager没有做出反应。在这个例子中,PowerManager在我断开usb连接笔记本电脑的那一刻起作出反应:

03-25 14:04:13.986 677-691/? D/PowerManagerService: userActivity mLastEventTime=201702573 time=201861160 mUserActivityAllowed=true mUserState=0x0 mWakeLockState=0x0 mProximitySensorActive=false timeoutOverride=-1 force=false
03-25 14:04:13.986 677-691/? D/PowerManagerService: setPowerState: mPowerState=0x0 newState=0x7 noChangeLights=false reason=2
03-25 14:04:13.986 677-691/? D/PowerManagerService: setPowerState: mPowerState=0 newState=7 noChangeLights=false
03-25 14:04:13.996 677-691/? D/PowerManagerService: setTimeoutLocked now=201861160 timeoutOverride=-1 nextState=3 when=201862660
03-25 14:04:14.006 677-747/? D/PowerManagerService: Perflock acquired: 7, 1
03-25 14:04:14.006 677-750/? D/PowerManagerService: offMask=0x0 dimMask=0x0 onMask=0x0 difference=0x1 realDifference=0x0 forceState=0x1
03-25 14:04:14.096 677-1038/? D/PowerManagerService: pid=31324 tag=MyWakeLock mAcquireCausesWakeupTime=201861278 diffTime=149932030
03-25 14:04:14.096 677-1038/? D/PowerManagerService: setPowerState: mPowerState=0x7 newState=0x7 noChangeLights=false reason=3

在第二行但最后一行,我在onCreate中发送的请求似乎被处理(tag = MyWakeLock)

在写作过程中,我意识到PowerManager在下一次测试中确实会自动做出反应,但只能延迟大约10分钟w.r.t. AlarmManager动作。

我做错了什么?我是否必须在onDestroy中发布WakeLock?这个问题有解决方案吗?

1 个答案:

答案 0 :(得分:0)

问题解决了。有两个原因导致它无法按预期在所有设备上运行:

  1. 我正在遵循多个线程中使用PendingIntent.getActivity直接启动活动而不是使用 BroadcastReceiver 的提案。显然这样做并不能保证在屏幕上获得控制权。在再次阅读Android Developer页面上的信息后,我实现了BroadcastReceiver:

    public class StartupReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent!=null){
            PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    
            PowerManager.WakeLock wl;
            if (android.os.Build.VERSION.SDK_INT < 13) {
                wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP
                    | PowerManager.ON_AFTER_RELEASE, "**StartupReceiver**");
                KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
                final KeyguardManager.KeyguardLock kl;
                if (km != null) {
                    kl = km.newKeyguardLock("MyKeyguardLock");
                    kl.disableKeyguard();
                }
    
            } else {wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP
                | PowerManager.ON_AFTER_RELEASE, "**StartupReceiver**");
            }
            wl.acquire();
    
    
            Intent i = new Intent(context, Start.class);
            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(i);
            wl.release();
        }
    }}
    

    这适用于所有使用SDK&lt; 19

  2. 的设备
  3. 为了让它也适用于SDK = 19,我必须将alarmManager.set更改为alarmManager.setExact,即

        Intent intent1 = new Intent(this,StartupReceiver.class);
        PendingIntent pendingIntent1 = PendingIntent.getBroadcast(MyApplication.getInstance().getBaseContext(),0,intent1,PendingIntent.FLAG_ONE_SHOT);
        AlarmManager alarmManager = (AlarmManager) MyApplication.getInstance().getBaseContext().getSystemService(Context.ALARM_SERVICE);
    
        if (alarmManager != null) {
            if(android.os.Build.VERSION.SDK_INT<19) {
                alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayInMillis, pendingIntent1);
            }else{
                alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayInMillis, pendingIntent1);
    
            }
            Date date = new Date(System.currentTimeMillis()+delayInMillis);
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy ' 'HH:mm:ss.SSS");
            Log.i("** restart at **",dateFormat.format(date));
        }
    
  4. 这些变化解决了问题