后台运行
# 背景
用户有个需求:要求用命令行,打开apk后,就在后台运行,尽量不要让用户感知,且需要后台常驻。
# 过程
# 用Service加返回到桌面
// 在MainActivity中编码。
// 启动CounterService ,改成直接后端执行。
startService(new Intent(this, BackgroundService.class));
// 返回到桌面
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
homeIntent.addCategory(Intent.CATEGORY_HOME);
homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
启动指令:
adb shell am start -n com.my.android/com.my.android.MainActivity
1
效果:有些机器会闪一下,有些机器不会闪动。用户反馈接受不了这些闪动。
# 用am startservice 命令
adb shell am startservice -n com.my.android/com.my.android.BackgroundService
1
- Requires permission not exported from uid 问题 (opens new window)
- 在Android 8.0(API级别26)之后,后台进程无法再通过startService方式启动服务 (opens new window)
- 低版本的启动了但是没有报错,功能没有生效。
# 用自定义广播+前台服务来实现
<!--AndroidManifest.xml-->
<application >
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MY_BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.MY_BOOT_COMPLETED")) {
// 代码1.在这里添加你的代码来处理设备启动后的操作
//...
// 代码2.创建并启动一个前台Service
Intent serviceIntent = new Intent(context, MyForegroundService.class);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(serviceIntent);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
adb shell am broadcast -a android.intent.action.MY_BOOT_COMPLETED -n com.puhua.android/com.puhua.android.MyBroadcastReceiver &
1
- 代码1程序好像不稳定,运行一会就自动被kill掉了
- 代码2在Android 8.0(API级别26)及以上版本中被引入,以限制应用在后台启动Service的行为:会报错 android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent
- 也就是说高版本也是实现不了前台服务的。
- 如果是系统应用的话,可以做到设备启动后来执行对应的广播(而不需要使用命令行啦)
# 用自定义广播+JobScheduler来实现
- 同上报错。
# 最终业务方妥协
采用Foreground Service加返回到桌面,和音乐一样。
是的,如果安卓的Foreground Service应用被杀死,它仍然可以在后台运行。
在安卓系统中,Foreground Service是一种特殊类型的服务,即使应用被杀死,服务也可以在后台运行。但是,如果系统需要恢复内存,该服务则会被操作系统终止。
需要注意的是,这种行为可能因安卓版本和设备类型而略有不同。
# 总结
首先,安卓系统为了优化性能和电池寿命,对于后台应用程序的运行有一定的限制。自Android 6.0(API级别23)开始,后台应用对于网络访问、位置信息和其他一些服务的访问受到了限制。因此,实现完全的静默后台运行可能比较困难。
然而,你可以尝试以下方法来实现静默后台运行:
- 使用JobScheduler:JobScheduler是安卓提供的一种用于在后台执行任务的API。你可以在应用程序中创建一个JobService,并使用JobScheduler来安排任务。这种方式可以在一定程度上实现静默后台运行。
- 使用WorkManager:WorkManager是安卓提供的一种用于处理后台任务的库。它可以在设备空闲时执行任务,而不需要用户交互。你可以使用WorkManager来安排后台任务,从而实现静默运行。
- 使用Foreground Service:Foreground Service是一种安卓服务,即使应用程序不在前台,它也可以继续运行。你可以在服务中执行后台任务,并通过创建一个Notification来让用户知道服务正在运行。虽然这不是完全的静默运行,但用户通常不会注意到Notification。
- 使用隐式广播接收器:你可以创建一个隐式广播接收器来监听系统广播,例如设备启动、网络连接等。当接收到相应的广播时,你可以在后台执行任务。请注意,安卓对于隐式广播接收器的使用有一定的限制,因此这种方法可能不适用于所有情况。
请注意,由于安卓系统的限制和安全考虑,建议你在设计和实现后台任务时充分考虑用户体验和系统资源。尽量避免在后台执行耗时或频繁的任务,以免对设备性能产生负面影响。
- 上述的业务需要在高版本中是实现不了的。
- 即使是厂商也是突破不了这个限制,除非对安卓操作系统源码做了对应的修改。
# 参考资料
编辑 (opens new window)
上次更新: 2023/10/07, 22:24:48