android进程保活总结

3 篇文章 0 订阅
0 篇文章 0 订阅

最近在做一个需要进程保活的项目,所以来总结一下。

这里给出了我的进程保活方法和一些技巧,最后附源码

主要步骤如下:

  1. 总体来说就是5.0以下开启定时器来启动Service,5.0以上开启JobService来开启Service。
  2. 然后监听系统的锁屏和解锁广播,来开启一个1像素的Activity。
  3. 监听系统的开机广播或第三方推送广播来启动Service。
  4. 对与我们的Service开启一个通知栏通知提升为前台进程,并使其为无感知。
  5. 引导用户开启应用自启动来使app在被手动或自动杀死后能从新被拉起来。

下面进行详细的描述:

 1. 5.0以下开启定时器来启动Service,5.0以上开启JobService来开启Service。

       5.0一下在Application中开启定时器

private fun startLongConn() {
        val systemService = getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val intent = Intent(this, LongConnService::class.java)
        val pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
        val realtime = SystemClock.elapsedRealtime()
        systemService.setRepeating(AlarmManager.RTC_WAKEUP,realtime,60*1000,pendingIntent)
    }

    5.0以上使用JobService,并在其中接收屏幕解锁和锁屏的广播,来实现1像素Activity的开关,JobService的作用简单来说就是开启一个可以在5.0以上使用的定时器,在间隔时间执行一次onStartJob方法。但是当被用户杀死或在系统内存严重不足时也会被杀死,被系统标记为stopped,从而无法启动。(解决办法看下面的自启动)

      ps:锁屏和解锁广播要动态注册,静态注册无效。若不清楚JobService的用法请自行百度

class JobLongConnService:JobService() {

    companion object {
        private const val TAG = "JobLongConnService:"
        const val jobId = 1
    }

    lateinit var myServiceBroadcast: MyServiceBroadcast

    override fun onCreate() {
        super.onCreate()
        myServiceBroadcast = MyServiceBroadcast()
        val intentFilter = IntentFilter()
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF)
        intentFilter.addAction(Intent.ACTION_SCREEN_ON)
        registerReceiver(myServiceBroadcast, intentFilter)

    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        println("start$TAG")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
            val builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                println("7.0走15分钟间隔$TAG")
                JobInfo.Builder(jobId, ComponentName(applicationContext, JobLongConnService::class.java))
                        .setPeriodic(15 * 60 * 1000, 5 * 60 * 1000)
                        .setRequiresCharging(true)
                        .setRequiresDeviceIdle(true)
                        .setPersisted(true)
            } else {
                println("走2分钟间隔$TAG")
                JobInfo.Builder(jobId, ComponentName(applicationContext, JobLongConnService::class.java))
                        .setPeriodic(30 * 1000)
                        .setRequiresCharging(true)
                        .setRequiresDeviceIdle(true)
                        .setPersisted(true)
            }
            if (jobScheduler.schedule(builder.build()) == JobScheduler.RESULT_SUCCESS) {
                println("工作成功$TAG")
            } else {
                println("工作失败$TAG")
            }
        }
        return Service.START_STICKY
    }

    override fun onStartJob(params: JobParameters?): Boolean {
        println("job启动$TAG")
        if (!ServiceUtils.isServiceRunning(this, "com.example.ring.LongConnService")) {
            val serviceIntent = Intent(this, LongConnService::class.java)
            this.startService(serviceIntent)
        } else {
            if (BleManager.getInstance().allConnectedDevice.size == 0) {
                val serviceIntent = Intent(this, LongConnService::class.java)
                this.startService(serviceIntent)
            }
        }
        return false
    }

    override fun onStopJob(params: JobParameters?): Boolean {
        println("job停止$TAG")
        if (!ServiceUtils.isServiceRunning(this, "com.example.ring.LongConnService")) {
            val serviceIntent = Intent(this, LongConnService::class.java)
            this.startService(serviceIntent)
        } else {
            if (BleManager.getInstance().allConnectedDevice.size == 0) {
                val serviceIntent = Intent(this, LongConnService::class.java)
                this.startService(serviceIntent)
            }
        }
        return false
    }

    override fun onDestroy() {
        super.onDestroy()
        val intent = Intent("com.example.ring.destroy")
        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
        sendBroadcast(intent)
        unregisterReceiver(myServiceBroadcast)
    }

    inner class MyServiceBroadcast : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            when (intent!!.action) {
                Intent.ACTION_SCREEN_OFF -> {
                    KeepLiveManager.startKeepLiveActivity(this@JobLongConnService)
                }
                Intent.ACTION_SCREEN_ON -> {
                    KeepLiveManager.finishKeepLiveActivity()
                }
            }
        }
    }
}

   对于我们自己的Service为了实现不轻易被杀死,我们开启为前台进程,提高优先级,在开启无感知

class LongConnService: Service() {
   
    private val TAG = "LongConnService"


    inner class LocalBinder :Binder(){
        fun getService():LongConnService {
            return LongConnService()
        }
    }

    override fun onBind(intent: Intent?): IBinder? {
        println("$TAG 返回binder")
        return null
    }

    override fun onUnbind(intent: Intent?): Boolean {
        println("$TAG 返回onUnbind")
        return super.onUnbind(intent)
    }

    //第一次创建的时候调用
    override fun onCreate() {
        super.onCreate()
        println("$TAG onCreate")
    }

    //每次startService的时候调用
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        println("$TAG onStartCommand")
        if (Build.VERSION.SDK_INT<18){
            this.startForeground(1000,  getNotification())
        }else if (Build.VERSION.SDK_INT<25){
            this.startForeground(1000,  getNotification())
            this.startService(android.content.Intent(this,InnerService::class.java))
        }else{
            this.startForeground(1000,  getNotification())
        }

        //做自己的处理

        return START_STICKY
    }

   
    override fun onDestroy() {
        println("$TAG onDestroy")
        stopForeground(true)
        val intent = Intent("com.example.ring.destroy")
        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
        sendBroadcast(intent)
        super.onDestroy()
    }

    private fun getNotification(): Notification {
        val intent = Intent(this, MainActivity::class.java)
        val pi = PendingIntent.getActivity(this, 0, intent, 0)
        return NotificationCompat.Builder(this)
                .setContentTitle("Ring")
                .setContentText("Ring service is running")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.ic_launcher_round)
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .setAutoCancel(false)
                .build()
    }

    //是为了让用户无感知
    companion object {
         class InnerService:Service(){
            override fun onBind(intent: Intent?): IBinder? {
                return null
            }

            override fun onCreate() {
                super.onCreate()
                try {
                    println("开启内部InnerService")
                    val intent = Intent(this, MainActivity::class.java)
                    val pi = PendingIntent.getActivity(this, 0, intent, 0)
                    val notification = NotificationCompat.Builder(this)
                            .setContentTitle("Ring")
                            .setContentText("Ring service is running")
                            .setWhen(System.currentTimeMillis())
                            .setSmallIcon(R.drawable.ic_launcher_round)
                            .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
                            .setContentIntent(pi)
                            .setAutoCancel(false)
                            .build()
                    startForeground(1000,notification)
                }catch (throwable:Throwable){
                    throwable.printStackTrace()
                }
                stopSelf()
            }
        }
    }

}

  1像素Activity和其manager代码

class KeepLiveActivity:AppCompatActivity() {

    lateinit var broadcast:MyBroadcast

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        KeepLiveManager.keepLiveActivity = this
        window.setGravity(Gravity.START)
        window.attributes.run {
            x=0
            y=0
            width=1
            height=1
        }
    }
object KeepLiveManager {
    var keepLiveActivity:KeepLiveActivity?=null

    fun startKeepLiveActivity(context: Context){
        println("创建KeepLive")
        val intent = Intent(context, KeepLiveActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        context.startActivity(intent)
    }

    fun finishKeepLiveActivity(){
        println("finish KeepLive")
        keepLiveActivity?.finish()
    }
}

另外在创建一个BroadcastReceiver来接收系统注册静态广播或第三方广播,来启动Service

class MyReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        println("广播:"+intent.action)
        when {
            intent.action == "com.example.ring.destroy" -> {
                println("longService服务挂了...")
                checkRunning(context)
            }
            intent.action == Intent.ACTION_BOOT_COMPLETED->{
                println("手机开机了...")
                checkRunning(context)
            }
            Intent.ACTION_USER_PRESENT == intent.action->{
                println("手机解锁了...")
                checkRunning(context)
            }
            intent.action == "cn.jpush.android.intent.DaemonService"->{
                println("极光推送拉起...")
                checkRunning(context)
            }
        }
    }

    private fun checkRunning(context: Context){
        if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.LOLLIPOP){
            if (!ServiceUtils.isServiceRunning(context,"com.example.ring.JobLongConnService")){
                val serviceIntent = Intent(context, JobLongConnService::class.java)
                context.startService(serviceIntent)
            }
        }else{
            if (!ServiceUtils.isServiceRunning(context,"com.example.ring.LongConnService")){
                val serviceIntent = Intent(context, LongConnService::class.java)
                context.startService(serviceIntent)
            }
        }
    }
}

最后为了在app被手动kill掉之后还能起来,我们需要引导用户开启自启动

object SettingUtils {

    fun enterWhiteListSetting(context: Context) {
        try {
            context.startActivity(getSettingIntent())
        } catch (e: Exception) {
            context.startActivity(Intent(Settings.ACTION_SETTINGS))
        }
    }

    private fun getSettingIntent(): Intent {

        var componentName: ComponentName? = null

        val brand = android.os.Build.BRAND

        when (brand.toLowerCase()) {
            "samsung" -> componentName = ComponentName("com.samsung.android.sm",
                    "com.samsung.android.sm.app.dashboard.SmartManagerDashBoardActivity")
            "huawei" -> componentName = ComponentName("com.huawei.systemmanager",
                    "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity")
            "xiaomi" -> componentName = ComponentName("com.miui.securitycenter",
                    "com.miui.permcenter.autostart.AutoStartManagementActivity")
            "vivo" -> componentName = ComponentName("com.iqoo.secure",
                    "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")
            "oppo" -> componentName = ComponentName("com.coloros.oppoguardelf",
                    "com.coloros.powermanager.fuelgaue.PowerUsageModelActivity")
            "360" -> componentName = ComponentName("com.yulong.android.coolsafe",
                    "com.yulong.android.coolsafe.ui.activity.autorun.AutoRunListActivity")
            "meizu" -> componentName = ComponentName("com.meizu.safe",
                    "com.meizu.safe.permission.SmartBGActivity")
            "oneplus" -> componentName = ComponentName("com.oneplus.security",
                    "com.oneplus.security.chainlaunch.view.ChainLaunchAppListActivity")
            "nubia"->{
                componentName = ComponentName("cn.nubia.security2",
                        "cn.nubia.security.appmanage.selfstart.ui.SelfStartActivity")
            }
            else -> {
            }
        }

        val intent = Intent()
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        if (componentName != null) {
            intent.component = componentName
        } else {
            intent.action = Settings.ACTION_SETTINGS
        }
        return intent
    }
}

然后你就会发现若是不关闭自启动,app是杀不死的,kill了之后一会儿又会起来。(你们看微信也是开启了自启动)

上面开启自启动的适合大部分机型,少部分没有的可以自己添加,手机进入自启动界面,然后使用adb命令获取路径

完整代码已上传至github:https://github.com/zhongyiqwer/Ring

参考文章:

https://blog.csdn.net/findsafety/article/details/80388430

https://blog.csdn.net/cspecialy/article/details/80161258

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值