Android 8.0以上系统应用如何保活

Android 8.0以上系统应用如何保活,第1张

概述 对于Android来说,保活主要有以下一些方法:开启前台Service(效果好,推荐)Service中循环播放一段无声音频(效果较好,但耗电量高,谨慎使用)双进程守护(Android5.0前有效)JobScheduler(Android5.0后引入,8.0后失效)1像素activity保活方案(不推荐)广播锁屏、自定义锁屏(不推荐)第三方推送SDK

 对于AndroID来说,保活主要有以下一些方法:

@H_502_2@开启前台Service(效果好,推荐)Service中循环播放一段无声音频(效果较好,但耗电量高,谨慎使用)双进程守护(AndroID 5.0前有效)JobScheduler(AndroID 5.0后引入,8.0后失效)1 像素activity保活方案(不推荐)广播锁屏、自定义锁屏(不推荐)第三方推送SDK唤醒(效果好,缺点是第三方接入)

下面是具体的实现方案:

1.监听锁屏广播,开启1个像素的Activity@H_502_21@

最早见到这种方案的时候是2015年,有个FM的app为了向投资人展示月活,在AndroID应用中开启一个1像素的Activity。

由于Activity的级别是比较高的,所以开启1个像素的Activity的方式就可以保证进程是不容易被杀掉的。

具体来说,定义一个1像素的Activity,在该Activity中动态注册自定义的广播。

class OnePixelActivity : AppCompatActivity() {    private lateinit var br: broadcastReceiver    overrIDe fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        //设定一像素的activity        val window = window        window.setGravity(Gravity.left or Gravity.top)        val params = window.attributes        params.x = 0        params.y = 0        params.height = 1        params.wIDth = 1        window.attributes = params        //在一像素activity里注册广播接受者    接受到广播结束掉一像素        br = object : broadcastReceiver() {            overrIDe fun onReceive(context: Context, intent: Intent) {                finish()            }        }        registerReceiver(br, IntentFilter("finish activity"))        checkScreenOn()    }    overrIDe fun onResume() {        super.onResume()        checkScreenOn()    }    overrIDe fun onDestroy() {        try {            //销毁的时候解锁广播            unregisterReceiver(br)        } catch (e: IllegalArgumentException) {        }        super.onDestroy()    }    /**     * 检查屏幕是否点亮     */    private fun checkScreenOn() {        val pm = this@OnePixelActivity.getSystemService(Context.POWER_SERVICE) as PowerManager        val isScreenOn = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {            pm.isInteractive        } else {            pm.isScreenOn        }        if (isScreenOn) {            finish()        }    }}
2, 双进程守护@H_502_21@

双进程守护,在AndroID 5.0前是有效的,5.0之后就不行了。首先,我们定义定义一个本地服务,在该服务中播放无声音乐,并绑定远程服务

class LocalService : Service() {    private var mediaPlayer: MediaPlayer? = null    private var mBilder: MyBilder? = null    overrIDe fun onCreate() {        super.onCreate()        if (mBilder == null) {            mBilder = MyBilder()        }    }    overrIDe fun onBind(intent: Intent): IBinder? {        return mBilder    }    overrIDe fun onStartCommand(intent: Intent, flags: Int, startID: Int): Int {        //播放无声音乐        if (mediaPlayer == null) {            mediaPlayer = MediaPlayer.create(this, R.raw.novioce)            //声音设置为0            mediaPlayer?.setVolume(0f, 0f)            mediaPlayer?.isLooPing = true//循环播放            play()        }        //启用前台服务,提升优先级        if (Keeplive.foregroundNotification != null) {            val intent2 = Intent(applicationContext, NotificationClickReceiver::class.java)            intent2.action = NotificationClickReceiver.CliCK_NOTIFICATION            val notification = NotificationUtils.createNotification(this, Keeplive.foregroundNotification!!.getTitle(), Keeplive.foregroundNotification!!.getDescription(), Keeplive.foregroundNotification!!.getIconRes(), intent2)            startForeground(13691, notification)        }        //绑定守护进程        try {            val intent3 = Intent(this, RemoteService::class.java)            this.bindService(intent3, connection, Context.BIND_ABOVE_CLIENT)        } catch (e: Exception) {        }        //隐藏服务通知        try {            if (Build.VERSION.SDK_INT < 25) {                startService(Intent(this, HIDeForegroundService::class.java))            }        } catch (e: Exception) {        }        if (Keeplive.keepliveService != null) {            Keeplive.keepliveService!!.onWorking()        }        return Service.START_STICKY    }    private fun play() {        if (mediaPlayer != null &amp;&amp; !mediaPlayer!!.isPlaying) {            mediaPlayer?.start()        }    }    private inner class MyBilder : GuardAIDl.Stub() {        @Throws(@R_301_1613@::class)        overrIDe fun wakeUp(Title: String, discription: String, iconRes: Int) {        }    }    private val connection = object : ServiceConnection {        overrIDe fun onServicedisconnected(name: Componentname) {            val remoteService = Intent(this@LocalService,                    RemoteService::class.java)            this@LocalService.startService(remoteService)            val intent = Intent(this@LocalService, RemoteService::class.java)            this@LocalService.bindService(intent, this,                    Context.BIND_ABOVE_CLIENT)        }        overrIDe fun onServiceConnected(name: Componentname, service: IBinder) {            try {                if (mBilder != null &amp;&amp; Keeplive.foregroundNotification != null) {                    val guardAIDl = GuardAIDl.Stub.asInterface(service)                    guardAIDl.wakeUp(Keeplive.foregroundNotification?.getTitle(), Keeplive.foregroundNotification?.getDescription(), Keeplive.foregroundNotification!!.getIconRes())                }            } catch (e: @R_301_1613@) {                e.printstacktrace()            }        }    }    overrIDe fun onDestroy() {        super.onDestroy()        unbindService(connection)        if (Keeplive.keepliveService != null) {            Keeplive.keepliveService?.onStop()        }    }}

然后再定义一个远程服务,绑定本地服务。

class RemoteService : Service() {    private var mBilder: MyBilder? = null    overrIDe fun onCreate() {        super.onCreate()        if (mBilder == null) {            mBilder = MyBilder()        }    }    overrIDe fun onBind(intent: Intent): IBinder? {        return mBilder    }    overrIDe fun onStartCommand(intent: Intent, flags: Int, startID: Int): Int {        try {            this.bindService(Intent(this@RemoteService, LocalService::class.java),                    connection, Context.BIND_ABOVE_CLIENT)        } catch (e: Exception) {        }        return Service.START_STICKY    }    overrIDe fun onDestroy() {        super.onDestroy()        unbindService(connection)    }    private inner class MyBilder : GuardAIDl.Stub() {        @Throws(@R_301_1613@::class)        overrIDe fun wakeUp(Title: String, discription: String, iconRes: Int) {            if (Build.VERSION.SDK_INT < 25) {                val intent = Intent(applicationContext, NotificationClickReceiver::class.java)                intent.action = NotificationClickReceiver.CliCK_NOTIFICATION                val notification = NotificationUtils.createNotification(this@RemoteService, Title, discription, iconRes, intent)                this@RemoteService.startForeground(13691, notification)            }        }    }    private val connection = object : ServiceConnection {        overrIDe fun onServicedisconnected(name: Componentname) {            val remoteService = Intent(this@RemoteService,                    LocalService::class.java)            this@RemoteService.startService(remoteService)            this@RemoteService.bindService(Intent(this@RemoteService,                    LocalService::class.java), this, Context.BIND_ABOVE_CLIENT)        }        overrIDe fun onServiceConnected(name: Componentname, service: IBinder) {}    }}/** * 通知栏点击广播接受者 */class NotificationClickReceiver : broadcastReceiver() {    companion object {        const val CliCK_NOTIFICATION = "CliCK_NOTIFICATION"    }    overrIDe fun onReceive(context: Context, intent: Intent) {        if (intent.action == NotificationClickReceiver.CliCK_NOTIFICATION) {            if (Keeplive.foregroundNotification != null) {                if (Keeplive.foregroundNotification!!.getForegroundNotificationClickListener() != null) {                    Keeplive.foregroundNotification!!.getForegroundNotificationClickListener()?.foregroundNotificationClick(context, intent)                }            }        }    }}
3,JobScheduler@H_502_21@

JobScheduler是AndroID从5.0增加的支持一种特殊的任务调度机制,可以用它来实现进程保活,不过在Android8.0系统中,此种方法也失效。

首先,我们定义一个JobService,开启本地服务和远程服务。

@SuppressWarnings(value = ["unchecked", "deprecation"])@RequiresAPI(Build.VERSION_CODES.LolliPOP)class JobHandlerService : JobService() {    private var mJobScheduler: JobScheduler? = null    overrIDe fun onStartCommand(intent: Intent?, flags: Int, startID: Int): Int {        var startID = startID        startService(this)        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LolliPOP) {            mJobScheduler = getSystemService(Context.JOB_SCHEDulER_SERVICE) as JobScheduler            val builder = JobInfo.Builder(startID++,                    Componentname(packagename, JobHandlerService::class.java.name))            if (Build.VERSION.SDK_INT >= 24) {                builder.setMinimumLatency(JobInfo.DEFAulT_INITIAL_BACKOFF_MILliS) //执行的最小延迟时间                builder.setoverrIDeDeadline(JobInfo.DEFAulT_INITIAL_BACKOFF_MILliS)  //执行的最长延时时间                builder.setMinimumLatency(JobInfo.DEFAulT_INITIAL_BACKOFF_MILliS)                builder.setBackoffCriteria(JobInfo.DEFAulT_INITIAL_BACKOFF_MILliS, JobInfo.BACKOFF_POliCY_liNEAR)//线性重试方案            } else {                builder.setPeriodic(JobInfo.DEFAulT_INITIAL_BACKOFF_MILliS)            }            builder.setrequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)            builder.setRequiresCharging(true) // 当插入充电器,执行该任务            mJobScheduler?.schedule(builder.build())        }        return Service.START_STICKY    }    private fun startService(context: Context) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            if (Keeplive.foregroundNotification != null) {                val intent = Intent(applicationContext, NotificationClickReceiver::class.java)                intent.action = NotificationClickReceiver.CliCK_NOTIFICATION                val notification = NotificationUtils.createNotification(this, Keeplive.foregroundNotification!!.getTitle(), Keeplive.foregroundNotification!!.getDescription(), Keeplive.foregroundNotification!!.getIconRes(), intent)                startForeground(13691, notification)            }        }        //启动本地服务        val localintent = Intent(context, LocalService::class.java)        //启动守护进程        val guardIntent = Intent(context, RemoteService::class.java)        startService(localintent)        startService(guardIntent)    }    overrIDe fun onStartJob(jobParameters: JobParameters): Boolean {        if (!isServiceRunning(applicationContext, "com.xiyang51.keeplive.service.LocalService") || !isServiceRunning(applicationContext, "$packagename:remote")) {            startService(this)        }        return false    }    overrIDe fun onStopJob(jobParameters: JobParameters): Boolean {        if (!isServiceRunning(applicationContext, "com.xiyang51.keeplive.service.LocalService") || !isServiceRunning(applicationContext, "$packagename:remote")) {            startService(this)        }        return false    }    private fun isServiceRunning(ctx: Context, classname: String): Boolean {        var isRunning = false        val activityManager = ctx                .getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager        val servicesList = activityManager                .getRunningServices(Integer.MAX_VALUE)        val l = servicesList.iterator()        while (l.hasNext()) {            val si = l.next()            if (classname == si.service.classname) {                isRunning = true            }        }        return isRunning    }}
4,提高Service优先级@H_502_21@

在onStartCommand()方法中开启一个通知,提高进程的优先级。注意:从AndroID 8.0(API级别26)开始,所有通知必须要分配一个渠道,对于每个渠道,可以单独设置视觉和听觉行为。然后用户可以在设置中修改这些设置,根据应用程序来决定哪些通知可以显示或者隐藏。

首先,定义一个通知工具类,此工具栏兼容AndroID 8.0。

class NotificationUtils(context: Context) : Contextwrapper(context) {    private var manager: notificationmanager? = null    private var ID: String = context.packagename + "51"    private var name: String = context.packagename    private var context: Context = context    private var channel: NotificationChannel? = null    companion object {        @Suppresslint("StaticFIEldLeak")        private var notificationUtils: NotificationUtils? = null        fun createNotification(context: Context, Title: String, content: String, icon: Int, intent: Intent): Notification? {            if (notificationUtils == null) {                notificationUtils = NotificationUtils(context)            }            var notification: Notification? = null            notification = if (Build.VERSION.SDK_INT >= 26) {                notificationUtils?.createNotificationChannel()                notificationUtils?.getChannelNotification(Title, content, icon, intent)?.build()            } else {                notificationUtils?.getNotification_25(Title, content, icon, intent)?.build()            }            return notification        }    }    @RequiresAPI(API = Build.VERSION_CODES.O)    fun createNotificationChannel() {        if (channel == null) {            channel = NotificationChannel(ID, name, notificationmanager.importANCE_MIN)            channel?.enablelights(false)            channel?.enableVibration(false)            channel?.vibrationPattern = longArrayOf(0)            channel?.setSound(null, null)            getManager().createNotificationChannel(channel)        }    }    private fun getManager(): notificationmanager {        if (manager == null) {            manager = getSystemService(Context.NOTIFICATION_SERVICE) as notificationmanager        }        return manager!!    }    @RequiresAPI(API = Build.VERSION_CODES.O)    fun getChannelNotification(Title: String, content: String, icon: Int, intent: Intent): Notification.Builder {        //PendingIntent.FLAG_UPDATE_CURRENT 这个类型才能传值        val pendingIntent = PendingIntent.getbroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)        return Notification.Builder(context, ID)                .setContentTitle(Title)                .setContentText(content)                .setSmallicon(icon)                .setautoCancel(true)                .setContentIntent(pendingIntent)    }    fun getNotification_25(Title: String, content: String, icon: Int, intent: Intent): NotificationCompat.Builder {        val pendingIntent = PendingIntent.getbroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)        return NotificationCompat.Builder(context, ID)                .setContentTitle(Title)                .setContentText(content)                .setSmallicon(icon)                .setautoCancel(true)                .setVibrate(longArrayOf(0))                .setSound(null)                .setlights(0, 0, 0)                .setContentIntent(pendingIntent)    }}

 

5,Workmanager方式@H_502_21@

Workmanager是AndroID JetPac中的一个API,借助Workmanager,我们可以用它来实现应用饿保活。使用前,我们需要依赖Workmanager库,如下:

implementation "androID.arch.work:work-runtime:1.0.0-Alpha06"

Worker是一个抽象类,用来指定需要执行的具体任务。

public class KeepliveWork extends Worker {    private static final String TAG = "KeepliveWork";    @NonNull    @OverrIDe    public WorkerResult doWork() {        Log.d(TAG, "keep-> doWork: startKeepService");        //启动job服务        startJobService();        //启动相互绑定的服务        startKeepService();        return WorkerResult.SUCCESS;    }}

 

然后,启动keepWork方法,

    public voID startKeepWork() {        WorkManager.getInstance().cancelAllWorkByTag(TAG_KEEP_WORK);        Log.d(TAG, "keep-> dowork startKeepWork");        OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(KeepliveWork.class)                .setBackoffCriteria(BackoffPolicy.liNEAR, 5, TimeUnit.SECONDS)                .addTag(TAG_KEEP_WORK)                .build();        WorkManager.getInstance().enqueue(oneTimeWorkRequest);    }

 

总结

以上是内存溢出为你收集整理的Android 8.0以上系统应用如何保活全部内容,希望文章能够帮你解决Android 8.0以上系统应用如何保活所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1059440.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存