首页 > 编程知识 正文

安卓电视mkv播放器,安卓汽车视频播放器

时间:2023-05-05 21:13:33 阅读:280938 作者:2618

安卓开发,除了我们经常写的Activity、Fragment等显示给用户的控件外,我们还可能需要程序在退出到后台的时候,继续给用户提供服务的功能,这里就需要用到Android的服务Service。
安卓服务是对用户不可见的,它没有界面,只是开启了一个在后台持续运行的线程,就算用户退出到后台,只要不停止服务,服务就可以继续为用户提供服务。不像Activity会有固定的生命周期,当用户把程序退出到后台,程序失去焦点之后,Activity就必须调用onStop方法,失去与用户的交互关系。
下面我们就来实现一个在后台播放的服务:
其实,我想大家学习服务其实都会有一个理解误区,就是服务Service和Activity到底的区别在哪里?是没有界面,还是会一直执行onStartCommand方法,让线程在后台持续执行?
也就是说,只要我们手动的stratService或者bindService来开启服务之后,这个我们继承自系统的Service的服务就会一直持续不断的调用onStartCommand方法,直到我们手动的调用stopService或者调用服务的stopSelf结束服务才会停止运行。
我想大家一定也会和我一样存在上面的误区,但是我们可以来做个实验:

class DifferentSpeedPlayerService : Service() { private var playerType: String? = null private val mMediaResoureceOne = "https://qiniu.fjreading.com/summary/audio/73cd583f9822fde89936ed5dc59317dc" private val mMediaResoureceTwo = "https://qiniu.fjreading.com/summary/audio/b76d0070f7a77ad96f1e3d53c62306d0" private val mMediaResoureceThere = "https://qiniu.fjreading.com/summary/audio/04df5b8d56d050e981beeb2b7aefaed7" override fun onBind(intent: Intent?): IBinder? { LogUtils.e(">>>>>>>>>>>>>>>","绑定服务,返回IBinder对象") //获取传递过来的参数来返回不同的播放器对象 if(ObjectUtils.isNotEmpty(intent)){ val bundle = intent?.extras playerType = bundle?.getString("player_type") LogUtils.e(">>>>>>>>>>>>>>>>", "palyer_type:$playerType") } return LocalBinder() } /** * 客户端 Binder 对应的类 */ inner class LocalBinder : Binder() { internal// 返回 LocalService 的实例,客户端可以调用其中的公共方法 val service: DifferentSpeedPlayerService get() = this@DifferentSpeedPlayerService } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { LogUtils.e(">>>>>>>>>>>>>>>","onStartCommand Int:"+Int+"startId:"+startId) return super.onStartCommand(intent, flags, startId) } fun getDifferentPlayerByPLayerType(): IPlayerWapper?{ var player= DifferentSpeedPlayer.getSpeedPlayerInstance() player?.initPlayer(baseContext) player?.prepareDataSource(mMediaResoureceTwo,250) return player as IPlayerWapper } override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) LogUtils.e(">>>>>>>>>>>>>>>", "newConfig:$newConfig") } override fun onRebind(intent: Intent?) { super.onRebind(intent) LogUtils.e(">>>>>>>>>>>>>>>", "onRebind") } override fun dump(fd: FileDescriptor?, writer: PrintWriter?, args: Array<out String>?) { super.dump(fd, writer, args) LogUtils.e(">>>>>>>>>>>>>>>", "dump") } override fun onCreate() { super.onCreate() LogUtils.e(">>>>>>>>>>>>>>>", "onCreate") } override fun onLowMemory() { super.onLowMemory() LogUtils.e(">>>>>>>>>>>>>>>", "onLowMemory") } override fun onTaskRemoved(rootIntent: Intent?) { super.onTaskRemoved(rootIntent) LogUtils.e(">>>>>>>>>>>>>>>", "onTaskRemoved") } override fun onTrimMemory(level: Int) { super.onTrimMemory(level) LogUtils.e(">>>>>>>>>>>>>>>", "level:$level") } override fun onUnbind(intent: Intent?): Boolean { LogUtils.e(">>>>>>>>>>>>>>>", "intent:$intent") return super.onUnbind(intent) } override fun onDestroy() { super.onDestroy() LogUtils.e(">>>>>>>>>>>>>>>", "onDestroy") }

上面的服务重写了Service类的所有的方法,下面就来测试一下,startService和bindService方法开启服务的不同点在于调用的Service的方法不同。
startService方法开启服务会调用服务的onCreate方法来创建一个服务,然后再调用服务的onStartCommand方法来运行服务,值得注意的是:onCreatef方法只会调用一次,onStartCommand方法在你重复调用startService方法会重复执行。
但是这里你已经得到了开启服务的效果,如果是播放音乐,无论手机是熄屏还是App退出到后台,你播放音乐的服务线程不会受到影响,这里你只要不手动调用stopService方法,服务就会持续运行在后台。
调用bindService方法来开启服务,首先也会调用服务的onCreate方法,然后调用服务的onBind方法,来返回一个继承自Binder对象的子类。我们可以在绑定服务的时候用继承ServiceConnection的子类链接对象里面获取到Service里面定义的LocalBinder对象,然后通过这个LocalBinder对象获取Service对象。这样我们就可以拿到定义在服务里面的成员变量,这里这个成员变量可以是一个播放器和可以是一个在后台运行的线程。

class DifferentSpeedServiceConnection : ServiceConnection{ var mDifferentSpeedPlayer: DifferentSpeedPlayer? = null override fun onServiceDisconnected(name: ComponentName?) { LogUtils.e(">>>>>>>>>>>>>>>", "onServiceDisconnected:$name") } override fun onServiceConnected(name: ComponentName?, service: IBinder?) { try { val localBinder = service as DifferentSpeedPlayerService.LocalBinder val articlePlayerService = localBinder.service mDifferentSpeedPlayer = articlePlayerService.getDifferentPlayerByPLayerType() as DifferentSpeedPlayer? mDifferentSpeedPlayer?.startPlay() LogUtils.e(">>>>>>>>>>>>>>>", "组件名称:$name" + "绑定的服务:" + service) LogUtils.e(">>>>>>>>>>>>>>>", "mDifferentSpeedPlayer" +mDifferentSpeedPlayer) }catch (e: Exception){ Log.e(">>>>>>>>>>>>>>", "绑定服务异常:$e") } } }

这里获取我们可以思考一下,为什么我们不能直接通过ServiceConnection对象来获取Service对象,而是需要在Service里面定义一个Binder对象的子类,然后通过onBindf方法来返回到ServiceConnection的onServiceConnected(name: ComponentName?, service: IBinder?) 方法呢?这里我们会发现了共同对象IBinder,然后发现IBinder对象是一个接口,这就说明服务和组件或者界面绑定是通过public interface IBinder {}接口来实现绑定的。
我们解绑时需要传递一个ServiceConnection对象来取消绑定。
但是,有时候我们可能会用到一些第三方服务,比如百度语音合成、百度定位等,这些第三方服务其实都是有自己的服务,所以就不需要再自己去开启一个服务来处理逻辑,只需要按照第三方的开发文档进行集成就行?根据按照开发经验,如果播放器没有开启后台服务,程序退出到后台,调用第三方的服务也会经常报错,所以说明安卓客户端如果需要实现一个播放器,就需要在后台开启一个后台服务来实现后台播放功能。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。