Android 唤醒锁问题

Posted

技术标签:

【中文标题】Android 唤醒锁问题【英文标题】:Android wakeLock issue 【发布时间】:2020-08-02 13:28:42 【问题描述】:

我有前台服务。

清单包含此权限:

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

在 Splash 活动中,我请求此权限一次:

Intent intent = new Intent();
        String packageName = context.getPackageName();
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if (!pm.isIgnoringBatteryOptimizations(packageName)) 
            intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
            intent.setData(Uri.parse("package:" + packageName));
        
        context.startActivity(intent);

在 onCreate 服务方法中我调用 createAlarm 方法:

private void createAlarm() 
    wakeupIntent = PendingIntent.getBroadcast(getBaseContext(), 0, new Intent("com.android.internal.location.ALARM_WAKEUP"), 0);
    powerManager = (PowerManager) getSystemService(POWER_SERVICE);
    wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getPackageName() + ":TrackService");
    wakeLock.acquire();

    dozeHandler = new Handler();
    Runnable heartbeat = new Runnable() 
        @Override
        public void run() 
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
                try 
                    if (powerManager != null && powerManager.isDeviceIdleMode()) 
                        try 
                            Log.d("MainService", "In IDLE MODE");
                            wakeupIntent.send();
                         catch (SecurityException | PendingIntent.CanceledException e) 
                            Log.d("MainService", "Heartbeat location manager keep-alive failed", e);
                        
                     else if (!powerManager.isDeviceIdleMode()) 
                        Log.d("MainService", "Device alive");
                    
                 finally 
                    if (dozeHandler != null)
                        dozeHandler.postDelayed(this, 5000);
                
        
    ;
    heartbeat.run();

    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(this, MyWakefulReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
    if (Build.VERSION.SDK_INT >= 23) 
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, 30000, pendingIntent);
     else 
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, 30000, pendingIntent);
    

在所有初始化调用 setWakeLock 之后:

@SuppressLint("WakelockTimeout")
public void setWakeMode(Context context, int mode) 
    boolean wasHeld = false;
    if (wakeLock != null) 
        if (wakeLock.isHeld()) 
            wasHeld = true;
            wakeLock.release();
        
        wakeLock = null;
    
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    wakeLock = pm.newWakeLock(mode | PowerManager.ON_AFTER_RELEASE, MainService.class.getName());
    wakeLock.setReferenceCounted(false);
    if (wasHeld) 
        wakeLock.acquire();
    

我对这些功能感到困惑,因此我没有醒来,请帮助我。

【问题讨论】:

【参考方案1】:
boolean wasHeld = false;
if (wakeLock != null) 
    if (wakeLock.isHeld()) 
        wasHeld = true;
        wakeLock.release();
    
    wakeLock = null;

只有在“wakeLock.isHeld()”时才将“wasHeld”设置为 true。只有在 'wasHeld' 为真时才调用获取:

if (wasHeld) 
    wakeLock.acquire();

取出 'if (wasHeld)...' 并调用 acquire 无论如何,我猜 wasHeld 总是假的,所以永远不会调用 acquire。

如果它仍然不起作用,根据 AndroidStudio 文档,您可以:

PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
        "MyApp::MyWakelockTag");
wakeLock.acquire();

并调用

wakeLock.release();

完成后。

【讨论】:

以上是关于Android 唤醒锁问题的主要内容,如果未能解决你的问题,请参考以下文章

在 android 应用程序中访问唤醒锁统计信息

Android 唤醒锁强制关闭

Webview行为唤醒锁android

在 Android 1.5 服务中使用唤醒锁

Android 电源管理器唤醒锁

部分唤醒锁不适用于 android wear