android启动Service和ForegroundService

最近有个需求需求"开启前台服务,然后进行持续定位" 没有用过特此记录一下

之前用的都是Service

class SocketService : Service() {
    private var webSockethandler: WebSocketHandler? = null
    private var pushObserve: Observer<String>? = null

    private var taskLog: Int = 0

    private var isConnecting: Boolean = false

    //
    var msgType: String = ""

    // 发送消息标识
    var msgUuid: String = ""
    var msgRole: String = ""

 override fun onCreate() {
        super.onCreate()
        //单例模式变量赋值
        instance = this
    }

  override fun onBind(intent: Intent?): IBinder? {
        ("Backserver init on onBind").loge("websocket")
        intent?.let {
          
            if (token.isNotBlank()) {
                userToken = token
              
            }
        }
        return MyBinder()
    }

 class MyBinder : Binder() {
        fun getMyService(): SocketService {
            return getInstance()
        }

        fun getSocketStatus() {
            getMyService().webSockethandler?.getStatus()
        }
    }

 override fun onDestroy() {
        super.onDestroy()
        "Backserver init on onDestroy".loge("websocket")
        pushObserve?.let {
            LiveEventBus.get(Constant.IN_DRIVER_TRIP, String::class.java)
                .removeObserver(it)
        }
        webSockethandler?.close()
    }

 companion object {
        private lateinit var instance: SocketService

        fun getInstance(): SocketService {
            return instance
        }
    }

}

 其实如果不使用Binder 可以直接传null

然后注册

 <service android:name=".SocketService"
        android:enabled="true"
        android:exported="true"/>

注册完就启动service

  // 使用binder 示例
  var myService: SocketService? = null
    var mServiceConnection: ServiceConnection? = null

    private fun startService(context: Context, token: String) {
        if (mServiceConnection == null) {

            mServiceConnection = object : ServiceConnection {
                override fun onServiceConnected(name: ComponentName, service: IBinder) {
                    myService = (service as SocketService.MyBinder).getMyService()
                    "ServiceConnection  onServiceConnected:${name}".loge("websocket")
                }

                override fun onServiceDisconnected(name: ComponentName) {}
            }
            "socket BackService启动".loge("websocket")
            val intent = Intent(context, SocketService::class.java)
            intent.putExtra(USER_TOKEN, token)
            context.bindService(intent, mServiceConnection!!, Context.BIND_AUTO_CREATE)
        } else {
            "socket BackService启动 onBind".loge("websocket")
            myService?.reConnect(token)
        }
    }

    fun finishService(context: Context) {
        mServiceConnection?.let {
            context.unbindService(it)
        }

    }

// 普通的
     val intent = Intent(context, SocketService::class.java)
                intent.putExtra(USER_TOKEN, token)
     startService(intent)

说完service

前台service 代码

只需要在里面添加Notification 调用

class LocationService : Service() {
    private var TAG: String = LocationService::class.java.getSimpleName()


    override fun onBind(intent: Intent?): IBinder? {
        Log.d(TAG, "onBind()")
        return null
    }

    override fun onCreate() {
        super.onCreate()
        Log.d(TAG, "onCreate()");
    }


 @RequiresApi(Build.VERSION_CODES.O)
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d(TAG, "onStartCommand()");
          

       var  notification =  setChannelAndNotification(this)

        startForeground(123, notification)
        return super.onStartCommand(intent, flags, startId)

}



    //安卓8.0以上需要创建channel
    fun setChannelAndNotification(context: Context): Notification {
        //创建channel
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //通过一个唯一的channel ID ,对用户可见的channel name,通知重要程度importance level构建一个通知渠道。
            //可选的使用setDescription()指定用户在系统设置页面看到的关于通知的相关描述。
            //通过createNotificationChannel()注册通知渠道。
            //IMPORTANCE_DEFAULT: 默认notification importance,可以在任何地方显示,有声音。
            //IMPORTANCE_HIGH:可以在任何地方显示,有声音.
            //IMPORTANCE_LOW:可以在任何地方显示,没有声音.
            //IMPORTANCE_MAX:重要程度最高,可以在任何地方显示,有声音,可以在用户当前屏幕上显示通知,可以使用full screen intents.比如来电。
            //IMPORTANCE_MIN:无声音,不会出现在状态栏中。
            //IMPORTANCE_NONE:在任何地方都不会显示,被阻塞。
            //IMPORTANCE_UNSPECIFIED:表示用户没有表示重要性的值。这个值是为了持久的首选项,并且永远不应该与实际的通知相关联。
            val notificationManager =
                context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            val channel = NotificationChannel(
                context.getString(R.string.channel_id),
                context.getString(R.string.notification_title),
                NotificationManager.IMPORTANCE_HIGH
            )
            notificationManager.createNotificationChannel(channel)
        }
        val builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationCompat.Builder(context, context.getString(R.string.channel_id))
        } else {
            NotificationCompat.Builder(context)
        }
        //创建notification
        return builder
             //设置下拉列表里的标题
             .setContentTitle("下拉列表中的Title") 
             .setContentText(context.getString(R.string.notification_text))
            // 设置上下文内容
              .setContentText("要显示的内容") 
            //设置状态栏内的小图标
             .setSmallIcon(R.drawable.ic_launcher)
             // 设置下拉列表中的图标(大图标)
             .setLargeIcon(
                BitmapFactory.decodeResource(
                    this.getResources(),
                    R.mipmap.ic_launcher
                )
            )
             // 设置该通知发生的时间
            .setWhen(System.currentTimeMillis());
            //用户触摸时,自动关闭
            .setAutoCancel(false)
            //设置处于运行状态
           // .setOngoing(true) 
            .build()
    }


}

清单注册service

最后启动service

 var mMonitorService = Intent(this, LocationService::class.java)

        // Android 8.0使用startForegroundService在前台启动新服务
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            startForegroundService(mMonitorService);
        }
        else{
           startService(mMonitorService);
        }

 最后使用的时候报错 Context.startForegroundService() did not then call Service.startForeground?

是忘记写startForeground()导致

参考地址 (四十二)Context.startForegroundService() did not then call Service.startForeground?_i加加的博客-CSDN博客

最后发现google推荐将service改为JobService 参考如下

Android8.0利用JobScheduler实现服务的运行

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值