我是一名艺术家,我正在使用几款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?这个问题有解决方案吗?
答案 0 :(得分:0)
问题解决了。有两个原因导致它无法按预期在所有设备上运行:
我正在遵循多个线程中使用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
为了让它也适用于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));
}
这些变化解决了问题