日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

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

發布時間:2023/12/20 Android 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 8.0以上系统应用如何保活 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近在做一個埋點的sdk,由于埋點是分批上傳的,不是每次都上傳,所以會有個進程保活的機制,這也是自研推送的實現技術之一:如何保證Android進程的存活。

對于Android來說,?;钪饕幸韵乱恍┓椒?#xff1a;

  • 開啟前臺Service(效果好,推薦)
  • Service中循環播放一段無聲音頻(效果較好,但耗電量高,謹慎使用)
  • 雙進程守護(Android 5.0前有效)
  • JobScheduler(Android 5.0后引入,8.0后失效)
  • 1 像素activity?;罘桨?#xff08;不推薦)
  • 廣播鎖屏、自定義鎖屏(不推薦)
  • 第三方推送SDK喚醒(效果好,缺點是第三方接入)

下面是具體的實現方案:

1.監聽鎖屏廣播,開啟1個像素的Activity

最早見到這種方案的時候是2015年,有個FM的app為了向投資人展示月活,在Android應用中開啟一個1像素的Activity。

由于Activity的級別是比較高的,所以開啟1個像素的Activity的方式就可以保證進程是不容易被殺掉的。

具體來說,定義一個1像素的Activity,在該Activity中動態注冊自定義的廣播。

class OnePixelActivity : AppCompatActivity() {private lateinit var br: BroadcastReceiveroverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)//設定一像素的activityval window = windowwindow.setGravity(Gravity.LEFT or Gravity.TOP)val params = window.attributesparams.x = 0params.y = 0params.height = 1params.width = 1window.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 PowerManagerval isScreenOn = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {pm.isInteractive} else {pm.isScreenOn}if (isScreenOn) {finish()}} }

2, 雙進程守護

雙進程守護,在Android 5.0前是有效的,5.0之后就不行了。首先,我們定義定義一個本地服務,在該服務中播放無聲音樂,并綁定遠程服務

class LocalService : Service() {private var mediaPlayer: MediaPlayer? = nullprivate var mBilder: MyBilder? = nulloverride 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)//聲音設置為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 &amp;&amp; !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 &amp;&amp; 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? = nulloverride 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,JobScheduler

JobScheduler是Android從5.0增加的支持一種特殊的任務調度機制,可以用它來實現進程?;?#xff0c;不過在Android8.0系統中,此種方法也失效。

首先,我們定義一個JobService,開啟本地服務和遠程服務。

@SuppressWarnings(value = ["unchecked", "deprecation"]) @RequiresApi(Build.VERSION_CODES.LOLLIPOP) class JobHandlerService : JobService() {private var mJobScheduler: JobScheduler? = nulloverride 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,提高Service優先級

在onStartCommand()方法中開啟一個通知,提高進程的優先級。注意:從Android 8.0(API級別26)開始,所有通知必須要分配一個渠道,對于每個渠道,可以單獨設置視覺和聽覺行為。然后用戶可以在設置中修改這些設置,根據應用程序來決定哪些通知可以顯示或者隱藏。

首先,定義一個通知工具類,此工具欄兼容Android 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? = nullcompanion object {@SuppressLint("StaticFieldLeak")private var notificationUtils: NotificationUtils? = nullfun 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)}}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方式

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@Overridepublic 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);}

關于WorkManager,可以通過下面的文章來詳細了解:WorkManager淺談

總結

以上是生活随笔為你收集整理的Android 8.0以上系统应用如何保活的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。