欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > Android进程保活:如何让app一直运行

Android进程保活:如何让app一直运行

2024/10/25 19:33:24 来源:https://blog.csdn.net/qq_40853919/article/details/140857390  浏览:    关键词:Android进程保活:如何让app一直运行

目录

1)为什么需要进行进程保活呢?需求是什么?
2)进程分类
3)进程的优先级
4)如何提高进程优先级
5)如何进行进程保活

一、为什么需要进行进程保活呢?需求是什么?

比如:

  1. app在运行过程中,可能会因为各种原因导致闪退,报错或者被杀死等,尤其是一些自动售卖机,安装了android系统,如果这个时候app闪退了,那么就无法售卖了,我们需要能让程序运行起来。
  2. 如果用中有后台服务需要一直运行,例如音乐播放器、即时通讯等。
  3. 应用可能需要接收推送消息并及时展示给用户。为了实这个功能,需要保证应用进程直处于活跃状态,以便能够及时处理和显示推送消息。
  4. 有些应用需要执行定时任务,例如定时更新数据、定时发送统计信息等。通过保持进程活跃,可以确保这些任务按时执行。
  5. 某些应用需要在屏幕上显示悬浮窗口,例如悬浮球、悬浮菜单等

就需要通过进程保活来防止系统将其杀死,今天我们就来讲讲,进程保活。

二、进程分类

进程会被杀死,那么什么进程会被杀死呢?

1)前台进程(Foreground Process):前台进程是指当前正在与用户进行交互的app进程。例如,用户正在使用某个app或者app正在展示一个前台界面时;在前台运行的 Service 服务 , Service 调用了 startForeground,该app所在的进程就被认为是前台进程。前台进程拥有最高的优先级,不容易被系统杀死。

2)可见进程(Visible Process)可见进程是指虽然没有处于前台,但是对用户可见的app进程。例如,当一个Activity被另一个Activity或Dialog部分遮挡时,被遮挡的Activity所在的进程就被认为是可见进程。可见进程的优先级较高,相比后台进程更不容易被系统杀死。Activity 组件调用 onPause 生命周期函数。

3)服务进程(Service Process)调用 startService 方法启动的 Service 进程组件 , 就是服务进程 , 其没有与 Activity 组件绑定 , 因此该 Service 组件的优先级要降低一个等级 , 称为服务进程 ;

4)后台进程(Background Process):后台进程是指已经失去用户焦点且不可见的app进程。例如,当用户按Home键回到桌面时,app进入后台状态。后台进程的优先级较低,当系统内存不足时可能会被系统杀死以释放资源。

5)空进程(Empty Process):空进程是指没有任何活动组件(如Activity、Service等)的应用进程。这进程通常只是为了缓存应用的数据而保留,当需要重新启动应用时可以快速恢复。空进程的优先级最低,是系统内存不足时首先被杀死的对象。

三、那么,如何才能清楚的确认,究竟是那种进程呢?

通过oom_adj值.

oom_adj值是Linux内核为每个进程分配的,用于反映进程的优先级。在Android系统中,当内存不足需要杀死进程以回收内存时,系统会根据oom_adj值来决定是否回收该进程。oom_adj值越大,对应的进程优先级越低,越有可能被系统回收。

以下是一些oom_adj值对应的进程优先级(注意:这些值可能会因Android版本的不同而有所变化,以下信息基于参考文章提供的信息):

oom_adj值进程优先级描述
-16SYSTEM_ADJ:系统进程,具有最高优先级
0FOREGROUND_APP_ADJ:前台进程,用户当前正在交互的进程
1VISIBLE_APP_ADJ:可见进程,虽然不在前台但用户仍然可以看到(如锁屏界面上的应用)
2PERCEPTIBLE_APP_ADJ:可感知进程,如后台播放音乐、铃声、震动等
3BACKUP_APP_ADJ:进入后台的进程,按下Menu键可查看
5SERVICE_ADJ:服务进程,持有应用服务的进程

如何查看oom_adj值

在 Android Studio 中 , 可以看到该运行的程序的进程号 PID 为 30575
进入 adb shell 命令行 , su 获取 root 权限 , 使用如下命令cat /proc/30575/oom_adj
, 查询指定 PID 的 oom_adj 值就可以看到,为0就是前台进程。

那么,内存不足,多少才算不足呀?

在这里插入图片描述
这些数字,其单位是 4 K B , 80640 , 乘以 4 K B \rm 4KB 4KB , 除以1024 , 最后得到 315MB
内存不足时杀进程的优先顺序 :

18432 : 内存小于 18432 × 4 K B \rm 18432 \times 4KB 18432×4KB 时 , 杀 " 前台进程 " ;
23040 : 内存小于 23040 × 4 K B \rm 23040 \times 4KB 23040×4KB 时 , 杀 " 可见进程 " ;
27648 : 内存小于 27648 × 4 K B \rm 27648 \times 4KB 27648×4KB 时 , 杀 " 服务进程进程 " ;
32256 : 内存小于 32256 × 4 K B \rm 32256 \times 4KB 32256×4KB 时 , 杀 " 后台进程 " ;
55296 : 内存小于 55296 × 4 K B \rm 55296 \times 4KB 55296×4KB 时 , 杀 " ContentProvider 进程 " ;
80640 : 内存小于 80640 × 4 K B \rm 80640 \times 4KB 80640×4KB 时 , 杀 " 空进程 " ;

四、如何提高进程优先级

了解了这么多,我们知道前台进程不容易被杀死,假如我们变成了其他进程,那么如何才能提高他的优先级呢?

4.1 前台 Service

(1)service

import android.app.Notification  
import android.app.NotificationChannel  
import android.app.NotificationManager  
import android.app.Service  
import android.content.Context  
import android.content.Intent  
import android.os.Build  
import android.os.IBinder  class MyForegroundService : Service() {  private val NOTIFICATION_ID = 1  private val CHANNEL_ID = "ForegroundServiceChannel"  override fun onCreate() {  super.onCreate()  val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager  // 创建通知渠道(Android 8.0+)  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {  val channel = NotificationChannel(  CHANNEL_ID,  "Foreground Service Channel",  NotificationManager.IMPORTANCE_LOW  )  notificationManager.createNotificationChannel(channel)  }  // 启动前台服务  startForeground(NOTIFICATION_ID, getNotification("服务正在运行..."))  }  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {  // 处理从Activity传递过来的数据(如果有的话)  return START_STICKY  }  override fun onBind(intent: Intent?): IBinder? {  return null  }  private fun getNotification(contentText: String): Notification {  val builder = Notification.Builder(this, CHANNEL_ID)  .setSmallIcon(R.drawable.ic_notification) // 设置图标,确保你有这个资源  .setContentTitle("前台服务示例")  .setContentText(contentText)  .setPriority(Notification.PRIORITY_LOW)  // 可以在这里添加其他通知设置,如声音、振动等  return builder.build()  }  
}

(2)注册服务

<application  ...  >  ...  <service  android:name=".MyForegroundService"  android:enabled="true"  android:exported="false" />  ...  
</application>

(3)activity

import android.content.Intent  
import android.os.Bundle  
import androidx.appcompat.app.AppCompatActivity  class MainActivity : AppCompatActivity() {  override fun onCreate(savedInstanceState: Bundle?) {  super.onCreate(savedInstanceState)  setContentView(R.layout.activity_main)  // 启动前台服务  val serviceIntent = Intent(this, MyForegroundService::class.java)  startService(serviceIntent)  }  // 其他方法...  
}

好了,我们可以运行程序看看,比如按home键,然后再读取oom_adj值,看看有没有生效。

五、如何进行进程保活

通过上述信息,那么我们就可以知道,我们现在的进程究竟是什么?为我们接下来要进行进程保活做铺垫。进程保活是指在Android系统,通过一些手段和技术手段来确保应用进程持续运行的一种机制。

5.1 双进程保活

进程之间相互监听销毁的状态,从而重新启动对方。通过ServiceConnection 来进行监听。

(1)activity

startService(Intent(this, AService.java))
startService(Intent(this, BService.java))

(2)service


public class AService extends Service {private Connection connection;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();// 启动前台进程startService();}private void startService() {// 创建通知通道NotificationChannel channel = new NotificationChannel("service","service", NotificationManager.IMPORTANCE_NONE);channel.setLightColor(Color.BLUE);channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// 正式创建service.createNotificationChannel(channel);NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "service");Notification notification = builder.setOngoing(true).setSmallIcon(R.mipmap.ic_launcher).setPriority(PRIORITY_MIN).setCategory(Notification.CATEGORY_SERVICE).build();startForeground(10, notification);}/*** 绑定 另外一个 服务*/private void bindService() {// 创建连接对象connection = new Connection();// 创建本地前台进程组件意图Intent bindIntent = new Intent(this, BService.class);// 绑定进程操作bindService(bindIntent, connection, BIND_AUTO_CREATE);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 绑定另外一个服务bindService();return START_STICKY; // 尝试在系统杀死服务后重新创建它}class Connection implements ServiceConnection {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// 服务绑定成功时回调}@Overridepublic void onServiceDisconnected(ComponentName name) {// 再次启动前台进程startService();// 绑定另外一个远程进程bindService();}}}

(3)service


public class BService extends Service {private Connection connection;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();// 启动前台进程startService();}private void startService(){// 创建通知通道NotificationChannel channel = new NotificationChannel("service","service", NotificationManager.IMPORTANCE_NONE);channel.setLightColor(Color.BLUE);channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// 正式创建service.createNotificationChannel(channel);NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "service");Notification notification = builder.setOngoing(true).setSmallIcon(R.mipmap.ic_launcher).setPriority(PRIORITY_MIN).setCategory(Notification.CATEGORY_SERVICE).build();startForeground(10, notification);}/*** 绑定 另外一个 服务*/private void bindService(){// 创建连接对象connection = new Connection();// 创建本地前台进程组件意图Intent bindIntent = new Intent(this, AService.class);// 绑定进程操作bindService(bindIntent, connection, BIND_AUTO_CREATE);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 绑定另外一个服务bindService();return START_STICKY; // 尝试在系统杀死服务后重新创建它}class Connection implements ServiceConnection {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// 服务绑定成功时回调}@Overridepublic void onServiceDisconnected(ComponentName name) {// 再次启动前台进程startService();// 绑定另外一个远程进程bindService();}}}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com