@javascriptcommon/react-native-track-player 1.2.9 → 1.2.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +61 -4
- package/android/src/main/AndroidManifest.xml +2 -4
- package/android/src/main/ic_home-playstore.png +0 -0
- package/android/src/main/ic_repeat-playstore.png +0 -0
- package/android/src/main/ic_repeat_50-playstore.png +0 -0
- package/android/src/main/ic_shuffle-playstore.png +0 -0
- package/android/src/main/ic_shuffle_50-playstore.png +0 -0
- package/android/src/main/ic_shuffle_sm-playstore.png +0 -0
- package/android/src/main/ic_stop-playstore.png +0 -0
- package/android/src/main/ic_test-playstore.png +0 -0
- package/android/src/main/java/com/guichaguri/trackplayer/{service/HeadlessJsMediaService.java → HeadlessJsMediaService.java} +84 -33
- package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.kt +25 -0
- package/android/src/main/java/com/guichaguri/trackplayer/extensions/AudioPlayerStateExt.kt +19 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/EventHolder.kt +30 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/NotificationEventHolder.kt +20 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/PlayerEventHolder.kt +111 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AAMediaSessionCallback.kt +10 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioContentType.kt +10 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItem.kt +66 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItemTransitionReason.kt +33 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioPlayerState.kt +30 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/BufferConfig.kt +8 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/CacheConfig.kt +17 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/Capability.kt +19 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/FocusChangeData.kt +3 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/MediaSessionCallback.kt +17 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationConfig.kt +43 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationMetadata.kt +8 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationState.kt +8 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayWhenReadyChangeData.kt +5 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackEndedReason.kt +5 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackError.kt +6 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackMetadata.kt +200 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerConfig.kt +33 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerOptions.kt +9 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PositionChangedReason.kt +39 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/QueuedPlayerOptions.kt +49 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/notification/NotificationManager.kt +678 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/AudioPlayer.kt +10 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/BaseAudioPlayer.kt +864 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/QueuedAudioPlayer.kt +269 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/MediaSourceExt.kt +35 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/PlayerCache.kt +26 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/utils/Utils.kt +12 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/MetadataAdapter.kt +224 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/State.kt +13 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/Track.kt +120 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/TrackAudioItem.kt +19 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/TrackType.kt +11 -0
- package/android/src/main/java/com/guichaguri/trackplayer/module/AutoConnectionDetector.kt +151 -0
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.kt +66 -0
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.kt +1177 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/BundleUtils.kt +117 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.kt +31 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.kt +347 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.kt +1254 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.kt +228 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.kt +141 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.kt +396 -0
- package/android/src/main/res/drawable-hdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_home.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/raw/silent_5_seconds.mp3 +0 -0
- package/android/src/main/res/strings.xml +6 -0
- package/android/src/main/res/values/strings.xml +6 -0
- package/index.d.ts +62 -1
- package/lib/index.js +10 -9
- package/package.json +1 -1
- package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.java +0 -28
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.java +0 -55
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.java +0 -298
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.java +0 -47
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.java +0 -383
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.java +0 -271
- package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.java +0 -243
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.java +0 -148
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.java +0 -379
- package/android/src/main/java/com/guichaguri/trackplayer/service/models/Track.java +0 -141
- package/android/src/main/java/com/guichaguri/trackplayer/service/models/TrackType.java +0 -35
- package/android/src/main/res/drawable-hdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_logo.png +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
package com.guichaguri.trackplayer.model
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.net.Uri
|
|
5
|
+
import android.os.Bundle
|
|
6
|
+
import android.support.v4.media.MediaDescriptionCompat
|
|
7
|
+
import android.support.v4.media.MediaMetadataCompat
|
|
8
|
+
import android.support.v4.media.RatingCompat
|
|
9
|
+
import android.support.v4.media.session.MediaSessionCompat
|
|
10
|
+
import android.util.Log
|
|
11
|
+
import com.guichaguri.trackplayer.kotlinaudio.models.AudioItemOptions
|
|
12
|
+
import com.guichaguri.trackplayer.kotlinaudio.models.MediaType
|
|
13
|
+
import com.guichaguri.trackplayer.service.Utils
|
|
14
|
+
import com.guichaguri.trackplayer.service.Utils.bundleToJson
|
|
15
|
+
import org.json.JSONObject
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @author Guichaguri
|
|
19
|
+
*/
|
|
20
|
+
class Track(context: Context?, bundle: Bundle, ratingType: Int) {
|
|
21
|
+
var url: String = ""
|
|
22
|
+
var id: String?
|
|
23
|
+
var resourceId: Int? = null // leave it null, not 0
|
|
24
|
+
var type = MediaType.DEFAULT
|
|
25
|
+
var contentType: String?
|
|
26
|
+
var userAgent: String?
|
|
27
|
+
var artwork: Uri? = null
|
|
28
|
+
var title: String? = null
|
|
29
|
+
var artist: String? = null
|
|
30
|
+
var album: String? = null
|
|
31
|
+
var date: String? = null
|
|
32
|
+
var genre: String? = null
|
|
33
|
+
var duration: Long = 0
|
|
34
|
+
var originalItem: Bundle?
|
|
35
|
+
var json: JSONObject
|
|
36
|
+
var rating: RatingCompat? = null
|
|
37
|
+
var headers: MutableMap<String, String>? = null
|
|
38
|
+
val queueId: Long
|
|
39
|
+
|
|
40
|
+
init {
|
|
41
|
+
id = bundle.getString("mediaId")
|
|
42
|
+
val trackType = bundle.getString("type", "default")
|
|
43
|
+
for (t in MediaType.values()) {
|
|
44
|
+
if (t.name.equals(trackType, ignoreCase = true)) {
|
|
45
|
+
type = t
|
|
46
|
+
break
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (bundle.getString("sourceData") != null) {
|
|
50
|
+
url = bundle.getString("sourceData").toString()
|
|
51
|
+
}
|
|
52
|
+
contentType = bundle.getString("contentType")
|
|
53
|
+
userAgent = bundle.getString("userAgent")
|
|
54
|
+
val httpHeaders = bundle.getBundle("headers")
|
|
55
|
+
if (httpHeaders != null) {
|
|
56
|
+
headers = HashMap()
|
|
57
|
+
for (header in httpHeaders.keySet()) {
|
|
58
|
+
(headers as HashMap<String, String?>)[header] = httpHeaders.getString(header)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
setMetadata(context, bundle, ratingType)
|
|
62
|
+
queueId = System.currentTimeMillis()
|
|
63
|
+
json = bundleToJson(bundle)
|
|
64
|
+
originalItem = bundle
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fun setMetadata(context: Context?, bundle: Bundle, ratingType: Int) {
|
|
68
|
+
artwork = context?.let { Utils.getUri(it, bundle, "artwork") }
|
|
69
|
+
title = bundle.getString("title")
|
|
70
|
+
artist = bundle.getString("artist")
|
|
71
|
+
album = bundle.getString("album")
|
|
72
|
+
date = bundle.getString("date")
|
|
73
|
+
genre = bundle.getString("genre")
|
|
74
|
+
duration = try {
|
|
75
|
+
Utils.toMillis(bundle.getDouble("duration", 0.0))
|
|
76
|
+
} catch (ex: Exception) {
|
|
77
|
+
val durationInt = bundle.getInt("duration", 0)
|
|
78
|
+
Utils.toMillis(durationInt.toDouble())
|
|
79
|
+
}
|
|
80
|
+
rating = Utils.getRating(bundle, "rating", ratingType)
|
|
81
|
+
if (originalItem != null && originalItem != bundle) originalItem!!.putAll(bundle)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fun toMediaMetadata(): MediaMetadataCompat.Builder {
|
|
85
|
+
val builder = MediaMetadataCompat.Builder()
|
|
86
|
+
builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
|
|
87
|
+
builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
|
|
88
|
+
builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, album)
|
|
89
|
+
builder.putString(MediaMetadataCompat.METADATA_KEY_DATE, date)
|
|
90
|
+
builder.putString(MediaMetadataCompat.METADATA_KEY_GENRE, genre)
|
|
91
|
+
//builder.putString(METADATA_KEY_MEDIA_URI, uri.toString());
|
|
92
|
+
builder.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, id)
|
|
93
|
+
if (duration > 0) {
|
|
94
|
+
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration)
|
|
95
|
+
}
|
|
96
|
+
// if (artwork != null) {
|
|
97
|
+
// builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, artwork.toString())
|
|
98
|
+
// }
|
|
99
|
+
if (rating != null) {
|
|
100
|
+
builder.putRating(MediaMetadataCompat.METADATA_KEY_RATING, rating)
|
|
101
|
+
}
|
|
102
|
+
return builder
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fun toQueueItem(): MediaSessionCompat.QueueItem {
|
|
106
|
+
val descr = MediaDescriptionCompat.Builder()
|
|
107
|
+
.setTitle(title)
|
|
108
|
+
.setSubtitle(artist)
|
|
109
|
+
.setMediaId(id) //.setMediaUri(uri)
|
|
110
|
+
.setIconUri(artwork)
|
|
111
|
+
.build()
|
|
112
|
+
return MediaSessionCompat.QueueItem(descr, queueId)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
fun toAudioItem(): TrackAudioItem {
|
|
116
|
+
return TrackAudioItem(this, type, url, artist, title, album, artwork.toString(), duration,
|
|
117
|
+
AudioItemOptions(headers, userAgent, resourceId)
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package com.guichaguri.trackplayer.model
|
|
2
|
+
|
|
3
|
+
import android.graphics.Bitmap
|
|
4
|
+
import com.guichaguri.trackplayer.kotlinaudio.models.AudioItem
|
|
5
|
+
import com.guichaguri.trackplayer.kotlinaudio.models.AudioItemOptions
|
|
6
|
+
import com.guichaguri.trackplayer.kotlinaudio.models.MediaType
|
|
7
|
+
|
|
8
|
+
data class TrackAudioItem(
|
|
9
|
+
val track: Track,
|
|
10
|
+
override val type: MediaType,
|
|
11
|
+
override var audioUrl: String,
|
|
12
|
+
override var artist: String? = null,
|
|
13
|
+
override var title: String? = null,
|
|
14
|
+
override var albumTitle: String? = null,
|
|
15
|
+
override val artwork: String? = null,
|
|
16
|
+
override val duration: Long = 0,
|
|
17
|
+
override val options: AudioItemOptions? = null,
|
|
18
|
+
override var artworkBitmap: Bitmap? = null
|
|
19
|
+
): AudioItem
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
package com.guichaguri.trackplayer.module
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.AsyncQueryHandler
|
|
5
|
+
import android.content.BroadcastReceiver
|
|
6
|
+
import android.content.ContentResolver
|
|
7
|
+
import android.content.Context
|
|
8
|
+
import android.content.Intent
|
|
9
|
+
import android.content.IntentFilter
|
|
10
|
+
import android.database.Cursor
|
|
11
|
+
import android.net.Uri
|
|
12
|
+
import android.os.Build
|
|
13
|
+
import com.facebook.react.bridge.Arguments
|
|
14
|
+
import com.facebook.react.bridge.ReactContext
|
|
15
|
+
import com.facebook.react.bridge.WritableMap
|
|
16
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
17
|
+
|
|
18
|
+
class AutoConnectionDetector(
|
|
19
|
+
val context: ReactContext,
|
|
20
|
+
private val onConnectionChange: ((Boolean) -> Unit)? = null
|
|
21
|
+
) {
|
|
22
|
+
|
|
23
|
+
companion object {
|
|
24
|
+
const val TAG = "AutoConnectionDetector"
|
|
25
|
+
|
|
26
|
+
// columnName for provider to query on connection status
|
|
27
|
+
const val CAR_CONNECTION_STATE = "CarConnectionState"
|
|
28
|
+
|
|
29
|
+
// auto app on your phone will send broadcast with this action when connection state changes
|
|
30
|
+
const val ACTION_CAR_CONNECTION_UPDATED = "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED"
|
|
31
|
+
|
|
32
|
+
// phone is not connected to car
|
|
33
|
+
const val CONNECTION_TYPE_NOT_CONNECTED = 0
|
|
34
|
+
|
|
35
|
+
// phone is connected to Automotive OS
|
|
36
|
+
const val CONNECTION_TYPE_NATIVE = 1
|
|
37
|
+
|
|
38
|
+
// phone is connected to Android Auto
|
|
39
|
+
const val CONNECTION_TYPE_PROJECTION = 2
|
|
40
|
+
|
|
41
|
+
private const val QUERY_TOKEN = 42
|
|
42
|
+
|
|
43
|
+
private const val CAR_CONNECTION_AUTHORITY = "androidx.car.app.connection"
|
|
44
|
+
|
|
45
|
+
private val PROJECTION_HOST_URI = Uri.Builder().scheme("content").authority(CAR_CONNECTION_AUTHORITY).build()
|
|
46
|
+
|
|
47
|
+
private const val CAR_CONNECTION_UPDATE = "car-connection-update"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
var isCarConnected = false
|
|
51
|
+
|
|
52
|
+
private val carConnectionReceiver = CarConnectionBroadcastReceiver()
|
|
53
|
+
private val carConnectionQueryHandler = CarConnectionQueryHandler(context.contentResolver, context, this, onConnectionChange)
|
|
54
|
+
private var isReceiverRegistered = false
|
|
55
|
+
|
|
56
|
+
fun registerCarConnectionReceiver() {
|
|
57
|
+
if (!isReceiverRegistered) {
|
|
58
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
59
|
+
context.registerReceiver(carConnectionReceiver, IntentFilter(ACTION_CAR_CONNECTION_UPDATED), Context.RECEIVER_NOT_EXPORTED)
|
|
60
|
+
} else @SuppressLint("UnspecifiedRegisterReceiverFlag") {
|
|
61
|
+
context.registerReceiver(carConnectionReceiver, IntentFilter(ACTION_CAR_CONNECTION_UPDATED))
|
|
62
|
+
}
|
|
63
|
+
isReceiverRegistered = true
|
|
64
|
+
}
|
|
65
|
+
queryForState()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fun unRegisterCarConnectionReceiver() {
|
|
69
|
+
if (isReceiverRegistered) {
|
|
70
|
+
context.unregisterReceiver(carConnectionReceiver)
|
|
71
|
+
isReceiverRegistered = false
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private fun queryForState() {
|
|
76
|
+
carConnectionQueryHandler.startQuery(
|
|
77
|
+
QUERY_TOKEN,
|
|
78
|
+
null,
|
|
79
|
+
PROJECTION_HOST_URI,
|
|
80
|
+
arrayOf(CAR_CONNECTION_STATE),
|
|
81
|
+
null,
|
|
82
|
+
null,
|
|
83
|
+
null
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
inner class CarConnectionBroadcastReceiver : BroadcastReceiver() {
|
|
88
|
+
// query for connection state every time the receiver receives the broadcast
|
|
89
|
+
override fun onReceive(context: Context?, intent: Intent?) {
|
|
90
|
+
queryForState()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
internal class CarConnectionQueryHandler(
|
|
95
|
+
resolver: ContentResolver?,
|
|
96
|
+
private val context: ReactContext?,
|
|
97
|
+
private val autoConnectionDetector: AutoConnectionDetector,
|
|
98
|
+
private val onConnectionChange: ((Boolean) -> Unit)? = null,
|
|
99
|
+
) : AsyncQueryHandler(resolver) {
|
|
100
|
+
|
|
101
|
+
private fun emitConnectionUpdate(params: WritableMap) {
|
|
102
|
+
context?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)?.emit(
|
|
103
|
+
CAR_CONNECTION_UPDATE, params
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private fun notifyCarConnected() {
|
|
108
|
+
autoConnectionDetector.isCarConnected = true
|
|
109
|
+
val params = Arguments.createMap()
|
|
110
|
+
params.putBoolean("connected", true)
|
|
111
|
+
emitConnectionUpdate(params)
|
|
112
|
+
onConnectionChange?.invoke(true)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private fun notifyCarDisconnected() {
|
|
116
|
+
autoConnectionDetector.isCarConnected = false
|
|
117
|
+
val params = Arguments.createMap()
|
|
118
|
+
params.putBoolean("connected", false)
|
|
119
|
+
emitConnectionUpdate(params)
|
|
120
|
+
onConnectionChange?.invoke(false)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// notify new queryed connection status when query complete
|
|
124
|
+
override fun onQueryComplete(token: Int, cookie: Any?, response: Cursor?) {
|
|
125
|
+
if (response == null) {
|
|
126
|
+
// Null response from content provider when checking connection to the car, treating as disconnected
|
|
127
|
+
notifyCarDisconnected()
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
val carConnectionTypeColumn = response.getColumnIndex(CAR_CONNECTION_STATE)
|
|
131
|
+
if (carConnectionTypeColumn < 0) {
|
|
132
|
+
// Connection to car response is missing the connection type, treating as disconnected
|
|
133
|
+
notifyCarDisconnected()
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
if (!response.moveToNext()) {
|
|
137
|
+
// Connection to car response is empty, treating as disconnected
|
|
138
|
+
notifyCarDisconnected()
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
val connectionState = response.getInt(carConnectionTypeColumn)
|
|
142
|
+
if (connectionState == CONNECTION_TYPE_NOT_CONNECTED) {
|
|
143
|
+
// Android Auto disconnected
|
|
144
|
+
notifyCarDisconnected()
|
|
145
|
+
} else {
|
|
146
|
+
// Android Auto connected
|
|
147
|
+
notifyCarConnected()
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
package com.guichaguri.trackplayer.module
|
|
2
|
+
|
|
3
|
+
import android.content.BroadcastReceiver
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import com.facebook.react.bridge.Arguments
|
|
7
|
+
import com.facebook.react.bridge.ReactContext
|
|
8
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @author Milen Pivchev @mpivchev
|
|
12
|
+
*/
|
|
13
|
+
class MusicEvents(private val reactContext: ReactContext) : BroadcastReceiver() {
|
|
14
|
+
override fun onReceive(context: Context, intent: Intent) {
|
|
15
|
+
val event = intent.getStringExtra("event")
|
|
16
|
+
val data = intent.getBundleExtra("data")
|
|
17
|
+
val map = if (data != null) Arguments.fromBundle(data) else null
|
|
18
|
+
reactContext.getJSModule(RCTDeviceEventEmitter::class.java).emit(
|
|
19
|
+
event!!, map
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
companion object {
|
|
24
|
+
// Media Control Events
|
|
25
|
+
const val BUTTON_PLAY = "remote-play"
|
|
26
|
+
const val BUTTON_PLAY_FROM_ID = "remote-play-id"
|
|
27
|
+
const val SEARCH = "remote-search"
|
|
28
|
+
const val BUTTON_PLAY_FROM_SEARCH = "remote-play-search"
|
|
29
|
+
const val BUTTON_PLAY_FROM_QUEUE = "remote-play-queue"
|
|
30
|
+
const val BUTTON_PAUSE = "remote-pause"
|
|
31
|
+
const val BUTTON_STOP = "remote-stop"
|
|
32
|
+
const val BUTTON_SKIP = "remote-skip"
|
|
33
|
+
const val BUTTON_SKIP_NEXT = "remote-next"
|
|
34
|
+
const val BUTTON_SKIP_PREVIOUS = "remote-previous"
|
|
35
|
+
const val BUTTON_SEEK_TO = "remote-seek"
|
|
36
|
+
const val BUTTON_SET_RATING = "remote-set-rating"
|
|
37
|
+
const val BUTTON_JUMP_FORWARD = "remote-jump-forward"
|
|
38
|
+
const val BUTTON_JUMP_BACKWARD = "remote-jump-backward"
|
|
39
|
+
const val BUTTON_DUCK = "remote-duck"
|
|
40
|
+
const val BUTTON_BROWSE = "remote-browse"
|
|
41
|
+
const val BUTTON_SHUFFLE = "remote-shuffle"
|
|
42
|
+
const val BUTTON_REPEAT = "remote-repeat"
|
|
43
|
+
const val BUTTON_TRACK_STATUS = "remote-track-status"
|
|
44
|
+
|
|
45
|
+
// Playback Events
|
|
46
|
+
const val PLAYBACK_PLAY_WHEN_READY_CHANGED = "playback-play-when-ready-changed"
|
|
47
|
+
const val PLAYBACK_STATE = "playback-state"
|
|
48
|
+
const val PLAYBACK_TRACK_CHANGED = "playback-track-changed"
|
|
49
|
+
const val PLAYBACK_ACTIVE_TRACK_CHANGED = "playback-active-track-changed"
|
|
50
|
+
const val PLAYBACK_QUEUE_ENDED = "playback-queue-ended"
|
|
51
|
+
const val PLAYBACK_METADATA = "playback-metadata-received"
|
|
52
|
+
const val PLAYBACK_PROGRESS_UPDATED = "playback-progress-updated"
|
|
53
|
+
const val PLAYBACK_ERROR = "playback-error"
|
|
54
|
+
|
|
55
|
+
// Metadata Events
|
|
56
|
+
const val METADATA_CHAPTER_RECEIVED = "metadata-chapter-received"
|
|
57
|
+
const val METADATA_TIMED_RECEIVED = "metadata-timed-received"
|
|
58
|
+
const val METADATA_COMMON_RECEIVED = "metadata-common-received"
|
|
59
|
+
const val METADATA_PAYLOAD_KEY = "metadata"
|
|
60
|
+
|
|
61
|
+
// Other
|
|
62
|
+
const val PLAYER_ERROR = "player-error"
|
|
63
|
+
|
|
64
|
+
const val EVENT_INTENT = "com.doublesymmetry.trackplayer.event"
|
|
65
|
+
}
|
|
66
|
+
}
|