0

我是一名艺术家,我正在使用几部 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 I找到类似的东西(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}

对我来说,这看起来不错,但是 PowerManager 没有反应。在本例中,几分钟后我断开 USB 连接以连接笔记本电脑时,PowerManager 做出了反应:

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 分钟的 AlarmManager 动作。

我究竟做错了什么?我必须在 onDestroy 中释放 WakeLock 吗?有解决问题的方法吗?

4

1 回答 1

0

问题解决了。它在所有设备上都没有按我预期的那样工作有两个原因:

  1. 我正在遵循几个线程中提出的建议,使用PendingIntent.getActivity直接启动活动而不是使用广播接收器。显然这样做并不能保证在屏幕上获得控制权。再次阅读 Android 开发者页面上的信息后,我实现了一个 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<19 的设备

  2. 为了让它也能在 SDK=19 上工作,我不得不更改alarmManager.setalarmManager.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));
        }
    

这些改变解决了问题

于 2018-04-03T08:04:00.027 回答