Android 应用保活实践,字节跳动 Android 研发岗这些知识点内部泄露出来了
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {//播放无声音乐 if (mediaPlayer == null) {mediaPlayer = MediaPlayer.create(this, R.raw.novioce)//声音设置为 0mediaPlayer?.setVolume(0f, 0f)mediaPlayer?.isLooping = true//循环播放 play()}//启用前台服务,提升优先级 if (KeepLive.foregroundNotification != null) {val intent2 = Intent(applicationContext, NotificationClickReceiver::class.java)intent2.action = NotificationClickReceiver.CLICK_NOTIFICATIONval 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 && !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) {}}
}
/**
通知栏点击广播接受者*/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 chan
nel: 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 {
评论