安卓系统:后台进程在几分钟后停止,因为即使在使用唤醒锁时设备也会休眠



我正在开发一款应用程序来控制led灯泡(Mi Light、limitlessLed等)。该应用程序的目的是产生用户可以选择并让其无限期运行的效果。例如,"烛光"效果可能会在黄色和红色之间随意改变灯泡的颜色,直到用户决定停止。

快速背景信息:这些灯泡的控制方式是通过WiFi网络发送的UDP包。因此,即使设备处于睡眠状态,我也需要该应用程序继续发送此类UDP包。

经过一点研究,我最终使用了唤醒锁,让设备即使在睡觉时也能通过WiFi网络广播UDP包(请告诉我,以防有更好的方法我没有发现)。

在几分钟内(可能是10?),一切都很好,直到设备似乎进入某种深度睡眠模式,并停止通过网络发送包裹。

我该如何防止这种情况发生?更普遍地说,为了实现上述目标,我应该采取什么样的好方法?

仅供参考,这里有一个代码示例片段,它只是在7种颜色的数组中旋转:

[...]
private static boolean animationRunning = false;
private Timer timer = new Timer();
private PowerManager mgr = (PowerManager)getReactApplicationContext().getSystemService(Context.POWER_SERVICE);
private PowerManager.WakeLock wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
[...]
public void startAnimation(final int step) {
animationRunning = true;
wakeLock.acquire();
final int[] steps = { 0, 66, 99, 122, 166, 199, 255 };
resetTimer();
timer.scheduleAtFixedRate(new TimerTask(){
int curstep = 0;
@Override
public void run(){
byte[] Bytes = {64, (byte)steps[curstep], 85};
try {sendUdp(Bytes);} catch(IOException e) {};
curstep = curstep + 1;
if(curstep == steps.length) {
curstep = 1;
}
}
},0,1000);
}

我最终实现了前台服务(startForeground()),如下所述

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
_acquireWakelock();
_showNotification();
[do your thing]
return START_REDELIVER_INTENT;
}
private void _showNotification() {
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction("com.lightcontrollerrn2.action.main");
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Light Controller")
.setTicker("Light Controller")
.setContentText("Light effects are running")
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
startForeground(1337,
notification);
}

一路上我发现了一些可能对其他人也有帮助的事情:

  1. 前台服务仍然需要唤醒锁,以便在设备空闲时继续运行;

  2. 你可能会遇到类似问题的另一个原因是Android 6.0中引入的新Doze模式(https://developer.android.com/training/monitoring-device-state/doze-standby.html)。不过,在我的情况下,这项服务似乎可以持续运行足够长的时间,而我不需要处理进入瞌睡模式的设备(我用了大约一个小时的时间进行了测试,我对此感到满意)编辑:为了完成,我也处理了这个问题。以下是您(在服务本身内)的操作方法:

    @Override
    public void onCreate() {
    super.onCreate();
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    String packageName = getPackageName();
    if (Build.VERSION.SDK_INT >= 23 && !pm.isIgnoringBatteryOptimizations(packageName)) {
    Intent intent = new Intent();
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
    intent.setData(Uri.parse("package:" + packageName));
    startActivity(intent);
    }
    }
    

我可以想出两种方法来满足您的需求。

  1. 如果您可以将应用程序保持在前台,则可以通过在活动中添加android:keepScreenOn="true"来防止设备进入睡眠状态(有关更多信息,请参阅https://developer.android.com/training/scheduling/wakelock.html)。

  2. 第二种方法是假装你的应用程序在后台播放音乐,因此不会被操作系统杀死。你只需播放一个存储在应用程序本地的无声mp3,并无限时间重复播放。操作系统永远不会杀死你的应用程序,直到电池耗尽:)

希望能有所帮助。

相关内容

最新更新