资料总结 资料总结
首页
go
java
云原生
  • mysql
  • redis
  • MongoDB
  • 设计模式详解
  • 数据结构与算法
  • 前端
  • 项目
  • 理论基础
  • 运营
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

linghui Wu

一只努力学飞的鱼
首页
go
java
云原生
  • mysql
  • redis
  • MongoDB
  • 设计模式详解
  • 数据结构与算法
  • 前端
  • 项目
  • 理论基础
  • 运营
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • java-se

  • jvm

  • mybatis

  • Netty

  • 爬虫 webmagic

  • spring

  • spring-cloud

  • 中间件

  • flowable

  • idea工具

  • maven

  • ms

  • java部署

  • 原生安卓

    • 自定义启动预览页
    • 后台运行
      • 用Service加返回到桌面
      • 用am startservice 命令
      • 用自定义广播+前台服务来实现
      • 用自定义广播+JobScheduler来实现
      • 最终业务方妥协
        • 总结
        • 参考资料
    • app自定义图标
  • java
  • 原生安卓
wulinghui
2025-02-27
目录

后台运行

# 背景

用户有个需求:要求用命令行,打开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

启动指令:

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
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
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)开始,后台应用对于网络访问、位置信息和其他一些服务的访问受到了限制。因此,实现完全的静默后台运行可能比较困难。

然而,你可以尝试以下方法来实现静默后台运行:

  1. 使用JobScheduler:JobScheduler是安卓提供的一种用于在后台执行任务的API。你可以在应用程序中创建一个JobService,并使用JobScheduler来安排任务。这种方式可以在一定程度上实现静默后台运行。
  2. 使用WorkManager:WorkManager是安卓提供的一种用于处理后台任务的库。它可以在设备空闲时执行任务,而不需要用户交互。你可以使用WorkManager来安排后台任务,从而实现静默运行。
  3. 使用Foreground Service:Foreground Service是一种安卓服务,即使应用程序不在前台,它也可以继续运行。你可以在服务中执行后台任务,并通过创建一个Notification来让用户知道服务正在运行。虽然这不是完全的静默运行,但用户通常不会注意到Notification。
  4. 使用隐式广播接收器:你可以创建一个隐式广播接收器来监听系统广播,例如设备启动、网络连接等。当接收到相应的广播时,你可以在后台执行任务。请注意,安卓对于隐式广播接收器的使用有一定的限制,因此这种方法可能不适用于所有情况。

请注意,由于安卓系统的限制和安全考虑,建议你在设计和实现后台任务时充分考虑用户体验和系统资源。尽量避免在后台执行耗时或频繁的任务,以免对设备性能产生负面影响。

  • 上述的业务需要在高版本中是实现不了的。
  • 即使是厂商也是突破不了这个限制,除非对安卓操作系统源码做了对应的修改。

# 参考资料

  • adb shell中的am pm命令、常用命令总结 (opens new window)
编辑 (opens new window)
上次更新: 2023/10/07, 22:24:48
自定义启动预览页
app自定义图标

← 自定义启动预览页 app自定义图标→

最近更新
01
架构升级踩坑之路
02-27
02
总结
02-27
03
语法学习
02-27
更多文章>
| Copyright © 2021-2025 Wu lingui |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式