android 11 kotlin创建service

1. 启动服务, 判断下android版本调用不同的启动函数

	   // TestService: Service() 假设服务类叫TestService
        fun startService(context: Context) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(Intent(context, TestService::class.java))
            } else {
                context.startService(Intent(context, TestService::class.java))
            }
        }

不然可能会在使用startService时出现运行出错:

java.lang.IllegalStateException: Not allowed to start service Intent xxxx app is in background uid UidRecord

原因是安卓8开始无法创建后台服务,解决方法是使用startForegroundService创建前台服务。

2. 加权限,设置服务名

AndroidManifest.xml
加上

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application>
    <service  android:name=".TestService"/>
</application>

不然使用startForegroundService创建前台服务出错

java.lang.SecurityException: Permission Denial: startForeground from pid=25141, uid=10167 requires android.permission.FOREGROUND_SERVICE

3. 配置system权限

这步不细说了,加系统权限,就是用系统中的秘钥给apk签名

否则会出错

java.lang.RuntimeException: Unable to start service TestService@15e1549 with Intent { cmp=.TestService }: android.view.WindowManager B a d T o k e n E x c e p t i o n : U n a b l e t o a d d w i n d o w a n d r o i d . v i e w . V i e w R o o t I m p l BadTokenException: Unable to add window android.view.ViewRootImpl BadTokenException:Unabletoaddwindowandroid.view.ViewRootImplW@3e10f50 – permission denied for window type 2038
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4433)

4. 在service中的onCreate中设置一个notification的channelId

    private fun setForceGround() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 在android8.0后, 无法创建后台服务,需要调用startForeground(id, notification)创建前台服务, 另需要给notification设置一个channel id
            val channelId = "default"
            val channel = NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_DEFAULT)
            val nm = getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
            nm?.let {
                if (it.getNotificationChannel(channelId) == null) {//没有创建
                    it.createNotificationChannel(channel)//则先创建
                }
            }
            val notification: Notification
            val builder = Notification.Builder(this, channelId)
                .setContentTitle("")
                .setContentText("")
            notification = builder.build()
            startForeground(1, notification)
        }
    }

不然会在运行5秒后崩溃掉:
android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{49b053a u0

作者:帅得不敢出门

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐