内容简介:将在在
Service
将 DaemonService 设置为前台服务,主要为了减小 oom_adj 值(oom_adj越小优先级越高),增加应用存活几率。在API为18或更高的版本,此方法会显示可见通知。为避免打扰用户,一般会启动另一个Service把出现的通知移除。最终达到通知栏没有常驻通知,但是oom_adj值减少的目的。
class DaemonService : Service() { override fun onCreate() { super.onCreate() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { val builder = Notification.Builder(this) builder.setSmallIcon(R.mipmap.ic_launcher) builder.setContentTitle(TAG) builder.setContentText(DESCRIPTION) startForeground(NOTIFICATION_ID, builder.build()) startService(Intent(this, CancelNoticeService::class.java)) } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { startForeground(NOTIFICATION_ID, Notification()) } } // 返回START_STICKY override fun onStartCommand(intent: Intent?, flags: Int, startId: Int) = START_STICKY override fun onDestroy() { super.onDestroy() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager manager.cancel(NOTIFICATION_ID) } startService(Intent(applicationContext, DaemonService::class.java)) } override fun onBind(intent: Intent?) = null companion object { const val TAG = "DaemonService" const val NOTIFICATION_ID = 1024 const val NOTIFICATION_ID_STR = "DaemonService" const val DESCRIPTION = "DaemonService is running." } }
在 DaemonService 启动后会触发 CancelNoticeService 的启动。 CancelNoticeService 会在子线程中通过相同 NotificationId 移除已经出现的通知栏,达到隐藏的效果。由于通知栏出现和隐藏的时间间隔很短,所以用户一般不会察觉。
class CancelNoticeService : Service() { override fun onBind(intent: Intent?) = null override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) { val builder = Notification.Builder(this) builder.setSmallIcon(R.mipmap.ic_launcher) startForeground(DaemonService.NOTIFICATION_ID, builder.build()) Thread(Runnable { stopForeground(true) val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager manager.cancel(DaemonService.NOTIFICATION_ID) // 结束服务 stopSelf() }).start() } return super.onStartCommand(intent, flags, startId) } }
调用
在 AndroidManifest.xml 注册以上两个Service。 DaemonService 要放在主进程,通过 DaemonService 的前台可见属性提升主进程优先级。
<service android:name=".services.DaemonService" android:enabled="true" android:exported="true" /> <service android:name=".services.CancelNoticeService" android:enabled="true" android:exported="true" />
在 MainActivity 启动 DaemonService
val i = Intent(this, DaemonService::class.java) ContextCompat.startForegroundService(this, i)
结果
根据实际测试,以上方法只能在 Android 7.0 或以下版本使用。 Android 7.1.1 真机和模拟器测试通知均会出现,可知该方法从 Android 7.1.1 开始不起效。
以下结果在 Android 5.0 上测试:
user@MacBook-Pro:/ # adb shell shell@generic_x86:/ # su root@generic_x86:/ # ps | grep playground u0_a55 2919 1263 1283232 45972 SyS_epoll_ b7377fa5 S com.phantomvk.playground
应用进入后台,Service尚未启动
root@generic_x86:/ # cat /proc/2919/oom_adj 6
应用对用户可见,并启动Service。前台界面对用户可见就为0,不受Service影响。
root@generic_x86:/ # cat /proc/2919/oom_adj 0
应用进入后台,Activity所在进程 oom_adj 从6变为1
root@generic_x86:/ # cat /proc/2919/oom_adj 1
经过一段时间测试,虽然主进程 oom_adj 能保持1,但在设备可用内存低时,还是出现应用被回收的现象。不过,对比没有保护的应用,使用以上方法后被杀的时间点明显延后很多。
以上所述就是小编给大家介绍的《开启前台Service》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据结构与算法分析(C++版)(第3版)
Clifford A. Shaffer / 张铭、刘晓丹、等译 / 电子工业出版社 / 2013 / 59.00元
本书采用当前流行的面向对象的C++程序设计语言来描述数据结构和算法, 因为C++语言是程序员最广泛使用的语言。因此, 程序员可以把本书中的许多算法直接应用于将来的实际项目中。尽管数据结构和算法在设计本质上还是很底层的东西, 并不像大型软件工程项目开发那样, 对面向对象方法具有直接的依赖性, 因此有人会认为并不需要采用高层次的面向对象技术来描述底层算法。 但是采用C++语言能更好地体现抽象数据类型的......一起来看看 《数据结构与算法分析(C++版)(第3版)》 这本书的介绍吧!
SHA 加密
SHA 加密工具
HEX HSV 转换工具
HEX HSV 互换工具