写点什么

Android 应用保活实践,做了 6 年的 Android

用户头像
Android架构
关注
发布于: 8 小时前

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 && !mediaPlayer!!.isPlaying) {mediaPlayer?.start()}}


private inner class MyBilder : GuardAidl.Stub() {


@Throws(RemoteException::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 && KeepLive.foregroundNotification != null) {val guardAidl = GuardAidl.Stub.asInterface(service)guardAidl.wakeUp(KeepLive.foregroundNotification?.getTitle(), KeepLive.foregroundNotification?.getDescription(), KeepLive.foregroundNotification!!.getIconRes())}} catch (e: RemoteException) {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(RemoteException::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_NOTIFICATIONval 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) {}}


}


/**


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


  • 通知栏点击广播接受者*/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.JobSchedulerJobScheduler 和 JobService 是安卓在 api 21 中增加的接口,用于在某些指定条件下执行后台任务。


定义一个 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 = startIdstartService(this)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {mJobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobSchedulerval 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_NOTIFICATIONval 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 = falseval activityManager = ctx.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManagerval 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.播放无声音乐这里使用的是有声的 mp3 文件,只是在代码中把声音设置成了 0;如果使用真正的无声的音乐文件,在 oppo 手机上按下返回键会被立刻杀死,并且在三星手机,华为 nova2s 强制杀死也会被杀死,所有使用了有声的文件。


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


定义一个通知工具类,兼容 8.0


class NotificationUtils(context: Context) : ContextWrapper(context) {


private var manager: NotificationManager? = nullprivate var id: String = context.packageName + "51"private var name: String = context.packageNameprivate var context: Context = contextprivate 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? = nullnotification = 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)}

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android应用保活实践,做了6年的Android