@@ -3,16 +3,23 @@ package com.skyd.anivu.ui.mpv.service
3
3
import android.app.Application
4
4
import android.app.ForegroundServiceStartNotAllowedException
5
5
import android.app.Notification
6
+ import android.app.PendingIntent
6
7
import android.app.Service
8
+ import android.content.BroadcastReceiver
9
+ import android.content.Context
7
10
import android.content.Intent
11
+ import android.content.IntentFilter
8
12
import android.content.pm.ServiceInfo
13
+ import android.media.AudioManager
9
14
import android.net.Uri
10
15
import android.os.Binder
11
16
import android.os.Build
12
17
import android.os.IBinder
13
18
import android.support.v4.media.session.MediaSessionCompat
14
19
import android.support.v4.media.session.PlaybackStateCompat
15
20
import androidx.core.app.ServiceCompat
21
+ import androidx.core.content.ContextCompat
22
+ import com.skyd.anivu.BuildConfig
16
23
import com.skyd.anivu.appContext
17
24
import com.skyd.anivu.model.bean.MediaPlayHistoryBean
18
25
import com.skyd.anivu.model.repository.PlayerRepository
@@ -40,12 +47,13 @@ class PlayerService : Service() {
40
47
41
48
private val lifecycleScope = CoroutineScope (Dispatchers .Main )
42
49
50
+ private val playerNotificationReceiver = PlayerNotificationReceiver ()
43
51
private val binder = PlayerServiceBinder ()
44
52
var uri: Uri = Uri .EMPTY
45
53
private set
54
+ val player = MPVPlayer .getInstance(appContext as Application )
46
55
private val sessionManager = MediaSessionManager (appContext, createMediaSessionCallback())
47
56
private val notificationManager = PlayerNotificationManager (appContext, sessionManager)
48
- val player = MPVPlayer .getInstance(appContext as Application )
49
57
val playerState get() = sessionManager.playerState
50
58
51
59
private val observers = mutableSetOf<Observer >()
@@ -110,7 +118,11 @@ class PlayerService : Service() {
110
118
override fun event (eventId : Int ) {
111
119
when (eventId) {
112
120
MPVLib .mpvEventId.MPV_EVENT_SEEK -> sendEvent(PlayerEvent .Seek )
113
- MPVLib .mpvEventId.MPV_EVENT_END_FILE -> sendEvent(PlayerEvent .EndFile )
121
+ MPVLib .mpvEventId.MPV_EVENT_END_FILE -> {
122
+ sendEvent(PlayerEvent .EndFile )
123
+ savePosition()
124
+ }
125
+
114
126
MPVLib .mpvEventId.MPV_EVENT_FILE_LOADED -> {
115
127
sendEvent(PlayerEvent .FileLoaded )
116
128
sendEvent(PlayerEvent .Paused (player.paused))
@@ -137,6 +149,18 @@ class PlayerService : Service() {
137
149
138
150
override fun onCreate () {
139
151
super .onCreate()
152
+
153
+ ContextCompat .registerReceiver(
154
+ this ,
155
+ playerNotificationReceiver,
156
+ IntentFilter ().apply {
157
+ addAction(PLAY_ACTION )
158
+ addAction(AudioManager .ACTION_AUDIO_BECOMING_NOISY )
159
+ addAction(CLOSE_ACTION )
160
+ },
161
+ ContextCompat .RECEIVER_NOT_EXPORTED ,
162
+ )
163
+
140
164
addObserver(sessionManager)
141
165
MPVLib .addObserver(mpvObserver)
142
166
notificationManager.createNotificationChannel()
@@ -159,6 +183,8 @@ class PlayerService : Service() {
159
183
notificationManager.cancel()
160
184
removeAllObserver()
161
185
lifecycleScope.cancel()
186
+
187
+ unregisterReceiver(playerNotificationReceiver)
162
188
super .onDestroy()
163
189
}
164
190
@@ -203,7 +229,7 @@ class PlayerService : Service() {
203
229
if (keepOpen && eofReached) {
204
230
seek(0 )
205
231
} else if (isIdling) {
206
- command.uri.resolveUri(this @PlayerService)?.let { loadFile(it) }
232
+ command.uri!! .resolveUri(this @PlayerService)?.let { loadFile(it) }
207
233
}
208
234
}
209
235
paused = command.paused
@@ -287,7 +313,35 @@ class PlayerService : Service() {
287
313
}
288
314
}
289
315
316
+ inner class PlayerNotificationReceiver : BroadcastReceiver () {
317
+ override fun onReceive (context : Context ? , intent : Intent ? ) {
318
+ if (intent == null ) return
319
+
320
+ when (intent.action) {
321
+ AudioManager .ACTION_AUDIO_BECOMING_NOISY ->
322
+ onCommand(PlayerCommand .Paused (true , null ))
323
+
324
+ PLAY_ACTION -> onCommand(PlayerCommand .PlayOrPause )
325
+ CLOSE_ACTION -> {
326
+ onCommand(PlayerCommand .Destroy )
327
+ context?.sendBroadcast(Intent (FINISH_PLAY_ACTIVITY_ACTION ))
328
+ }
329
+ }
330
+ }
331
+ }
332
+
290
333
companion object {
291
334
private val scope = CoroutineScope (Dispatchers .IO )
335
+
336
+ const val PLAY_ACTION = BuildConfig .APPLICATION_ID + " .PlayerPlay"
337
+ const val CLOSE_ACTION = BuildConfig .APPLICATION_ID + " .PlayerClose"
338
+ const val FINISH_PLAY_ACTIVITY_ACTION = BuildConfig .APPLICATION_ID + " .FinishPlayActivity"
339
+
340
+ fun createIntent (context : Context , action : String ): PendingIntent {
341
+ val intent = Intent (action).apply {
342
+ setPackage(BuildConfig .APPLICATION_ID )
343
+ }
344
+ return PendingIntent .getBroadcast(context, 0 , intent, PendingIntent .FLAG_IMMUTABLE )
345
+ }
292
346
}
293
347
}
0 commit comments