大安区网站建设,网站页头图片,推广网发布的信息准确吗,查询做导员的网站物联网环境#xff0c;为了解决不同厂商、不同设备、不同网络情况下使用顺畅#xff0c;同时也考虑到节约成本#xff0c;缩小应用体积的好处#xff0c;我们需要一个服务应用一直存在系统中#xff0c;保活它以提供服务给其他客户端调用。 开机自启动#xff0c;通过广播…
物联网环境为了解决不同厂商、不同设备、不同网络情况下使用顺畅同时也考虑到节约成本缩小应用体积的好处我们需要一个服务应用一直存在系统中保活它以提供服务给其他客户端调用。 开机自启动通过广播通信
必要权限 !--允许查看所有未启动的应用--uses-permission android:nameandroid.permission.QUERY_ALL_PACKAGEStools:ignoreQueryAllPackagesPermission /!--// 添加接收开机广播的权限--uses-permission android:nameandroid.permission.RECEIVE_BOOT_COMPLETED /!--前台服务--uses-permission android:nameandroid.permission.FOREGROUND_SERVICE/开机自启动Service相关代码
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch/*** date 2023/2/28* email L2279833535163.com* author 小红妹* package com.xxx.xxx.receiver* describe 接收开机广播、开机自启动Service* copyright*/
class BootBroadcastReceiver : BroadcastReceiver() {private val ACTION_BOOT android.intent.action.BOOT_COMPLETEDoverride fun onReceive(context: Context?, intent: Intent?) {if (intent?.action ACTION_BOOT) {GlobalScope.launch(Dispatchers.Main) {delay(20000L)val intent Intent()intent.component ComponentName(com.xxx.xxx.end, com.xxx.xxx.end.DeviceService)if (Build.VERSION.SDK_INT Build.VERSION_CODES.O) {context?.startForegroundService(intent)} else {context?.startService(intent)}}}}}import android.app.*
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Color
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import com.ccbft.pda.reader.RfidUHF
import com.krd.ricemachine.uits.ShareUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch/*** date 2023/3/16* email L2279833535163.com* author 小红妹* package com.xxx.xxx.end* describe* copyright*/
class DeviceService : Service() {private lateinit var deviceBroadcastReceiver : DeviceBroadcastReceiverprivate lateinit var mContext: Contextprivate val TAG DeviceService/** 标记服务是否启动 */private var serviceIsLive false/** 唯一前台通知ID */private val NOTIFICATION_ID 1000override fun onCreate() {super.onCreate()mContext this//前台显示服务// 获取服务通知val notification: Notification createForegroundNotification()//将服务置于启动状态 ,NOTIFICATION_ID指的是创建的通知的IDstartForeground(NOTIFICATION_ID, notification)}override fun onBind(p0: Intent?): IBinder? {return null}override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {CoroutineScope(Dispatchers.Main).launch {//delay(1000L)//阻塞时间//receiverRegist()RfidUHF.initUHF()ShareUtil.putString(AES_key, intent?.getStringExtra(key), mContext)Log.e(TAG, onStartCommand: intent?.getStringExtra(key))}// 标记前台服务启动serviceIsLive truereturn super.onStartCommand(intent, flags, startId)}private fun receiverRegist() {deviceBroadcastReceiver DeviceBroadcastReceiver()val filter IntentFilter()filter.addAction(deviceCall)registerReceiver(deviceBroadcastReceiver, filter)}/*** 创建前台服务通知*/private fun createForegroundNotification(): Notification {val notificationManager getSystemService(NOTIFICATION_SERVICE) as NotificationManager// 唯一的通知通道的id.val notificationChannelId notification_channel_id_01// Android8.0以上的系统新建消息通道if (Build.VERSION.SDK_INT Build.VERSION_CODES.O) {//用户可见的通道名称val channelName Foreground Service Notification//通道的重要程度val importance NotificationManager.IMPORTANCE_HIGHval notificationChannel NotificationChannel(notificationChannelId, channelName, importance)notificationChannel.description Channel description//LED灯notificationChannel.enableLights(true)notificationChannel.lightColor Color.RED//震动notificationChannel.vibrationPattern longArrayOf(0, 1000, 500, 1000)notificationChannel.enableVibration(true)notificationManager?.createNotificationChannel(notificationChannel)}val builder NotificationCompat.Builder(this, notificationChannelId)//通知小图标builder.setSmallIcon(R.mipmap.ic_launcher)//通知标题builder.setContentTitle(AndroidServer)//通知内容builder.setContentText(AndroidServer服务正在运行中)//设定通知显示的时间builder.setWhen(System.currentTimeMillis())//设定启动的内容val activityIntent Intent(this, MainActivity::class.java)val pendingIntent PendingIntent.getActivity(this,1,activityIntent,PendingIntent.FLAG_IMMUTABLE) /*FLAG_UPDATE_CURRENT*/builder.setContentIntent(pendingIntent)//创建通知并返回return builder.build()}override fun onDestroy() {//unregisterReceiver(deviceBroadcastReceiver)super.onDestroy()// 标记服务关闭serviceIsLive false// 移除通知stopForeground(true)}注意 1、Android 8.0后台运行服务需要开启前台显示服务 2、Android 8.0 不再允许后台进程直接通过startService方式去启动服务改为startForegroundService方式启动。 对应错误提示如下
Context.startForegroundService() did not then call Service.startForeground():
ServiceRecord{24fafff u0 com.xxx.xxx.end/.DeviceService}3、Android O 后台应用想启动服务调用调用startForegroundService()后 切记调用startForeground()这个时候会有一个Notification常驻也就是上面说的1。 权限提示
Permission Denial: startForeground from pid2406, uid10134 requires
android.permission.FOREGROUND_SERVICE4、Android 11以上启动服务不能只是这样简单的调用//context?.startService(Intent(context, DeviceService::class.java)) 不然会报错
Process: com.xuanyi.webserver, PID: 2455
java.lang.IllegalStateException: Not allowed to start service Intent { cmpcom.xxx.xxx/.service.WebService }: app is in background uid UidRecord{103aaa1 u0a138 CEM idle change:cached procs:1 seq(0,0,0)}at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1715)at android.app.ContextImpl.startService(ContextImpl.java:1670)at android.content.ContextWrapper.startService(ContextWrapper.java:720)at android.content.ContextWrapper.startService(ContextWrapper.java:720)at com.xxx.xxx.receiver.BootBroadcastReceiver$onReceive$1.invokeSuspend(BootBroadcastReceiver.kt:26)at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}e0016fc, Dispatchers.Default]5、Android 12 四大组件含有 intent-filter /intent-filter 的需要添加android:exported“true”更多情况情况着这篇文章 Android 12适配安全组件导出设置android:exported 指定显式值”
6、Android 11引入了包可见性 要么添加QUERY_ALL_PACKAGES权限要么这样写
queries//你要交互的service的包名package android:namecom.XXX.XXX ///...等等包名
/queries
广播通信的前提1.应用APP要启动过一次2、要有至少有一个activity 3、注册广播方式 这就是为什么我们需要服务的意思首先需要开机自启动服务这会我们可以在启动的服务中动态注册广播测试静态注册也可以。 对了广播的静态注册效果随着版本的升高效果大打折扣为了防止小人作弊系统把君子和小人都设防了。
若是用户手动从后台杀掉应用程序那么广播无法再次启动服务哈哈哈哈哈哈那就想办法让用户无法删除服务吧