android 11 kotlin创建service

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

作者:帅得不敢出门

Android中,Kotlin编写的服务(Service)和Activity之间的通信主要是通过几种机制: 1. **BroadcastReceiver**:服务可以通过发送广播(Broadcast)来通知Activity更新信息,Activity可以注册BroadcastReceiver监听特定的广播事件。 ```kotlin val intent = Intent(this, YourService::class.java) startService(intent) // 在Service中发送广播 val broadcastIntent = Intent() broadcastIntent.setAction("com.example.YOUR_ACTION") sendBroadcast(broadcastIntent) ``` 2. **AIDL (Android Interface Definition Language)**:如果需要更复杂的数据传输,可以使用AIDL来创建跨进程的接口,然后通过Binder进行通信。 3. **LocalBroadcastManager**:对于同一个应用内部的轻量级通信,LocalBroadcastManager也是常用的选择。 4. **Handler/MessageQueue**: 如果服务需要定期向Activity推送数据,可以使用Handler和MessageQueue,Service可以在适当的时候发送消息给关联的Handler。 ```kotlin val handler = Handler(Looper.getMainLooper()) handler.post(Runnable { // 在主线程更新UI val data = service.getData() activity.updateView(data) }) // Service侧发送消息 val message = Message.obtain() message.what = UPDATE_DATA message.obj = data handler.sendMessage(message) ``` 5. **LiveData/ViewModel**: 使用Android Data Binding框架时,Service可以通过LiveData持有数据,并将其绑定到ViewModel供Activity获取。 6. **FragmentInteraction**: 如果Activity包含Fragment,可以直接在Service里操作Fragment的数据并调用其方法进行通信。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值