diff --git a/android/build.gradle b/android/build.gradle
index ca21270..f17abde 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -33,9 +33,9 @@ android {
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
versionCode 1
versionName "1.0"
-
+
}
-
+
buildTypes {
release {
minifyEnabled false
@@ -127,4 +127,5 @@ dependencies {
// noinspection GradleDynamicVersion
api 'com.facebook.react:react-native:+'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ implementation "com.google.android.exoplayer:exoplayer:2.12.0"
}
diff --git a/android/reactnativeradioplayer.iml b/android/reactnativeradioplayer.iml
new file mode 100644
index 0000000..2b3dfb4
--- /dev/null
+++ b/android/reactnativeradioplayer.iml
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index f6a9621..605dec9 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -1,4 +1,5 @@
+
diff --git a/android/src/main/java/com/reactnativeradioplayer/RadioPlayerModule.kt b/android/src/main/java/com/reactnativeradioplayer/RadioPlayerModule.kt
index 8bdbd75..c5964ff 100644
--- a/android/src/main/java/com/reactnativeradioplayer/RadioPlayerModule.kt
+++ b/android/src/main/java/com/reactnativeradioplayer/RadioPlayerModule.kt
@@ -1,24 +1,116 @@
package com.reactnativeradioplayer
-import com.facebook.react.bridge.ReactApplicationContext
-import com.facebook.react.bridge.ReactContextBaseJavaModule
-import com.facebook.react.bridge.ReactMethod
-import com.facebook.react.bridge.Promise
+import android.util.Log
+import com.facebook.react.bridge.*
+import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
+import com.google.android.exoplayer2.C.WAKE_MODE_NETWORK
+import com.google.android.exoplayer2.MediaItem
+import com.google.android.exoplayer2.Player
+import com.google.android.exoplayer2.SimpleExoPlayer
+import com.google.android.exoplayer2.metadata.Metadata
+import com.google.android.exoplayer2.metadata.MetadataOutput
+import com.google.android.exoplayer2.metadata.icy.IcyInfo
+import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
+import com.google.android.exoplayer2.util.EventLogger
-class RadioPlayerModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
+
+class RadioPlayerModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext), Player.EventListener, MetadataOutput {
+
+ private val context = reactContext
+ private var player: SimpleExoPlayer = SimpleExoPlayer.Builder(reactContext).build()
override fun getName(): String {
return "RadioPlayer"
}
- // Example method
- // See https://facebook.github.io/react-native/docs/native-modules-android
+ init {
+ UiThreadUtil.runOnUiThread {
+ player.addAnalyticsListener(EventLogger(DefaultTrackSelector(this.context)))
+ player.addMetadataOutput(this)
+ player.setThrowsWhenUsingWrongThread(true)
+ player.setWakeMode(WAKE_MODE_NETWORK)
+ player.addListener(this)
+ }
+ }
+
@ReactMethod
- fun multiply(a: Int, b: Int, promise: Promise) {
-
- promise.resolve(a * b)
-
+ fun radioURL(uri: String) {
+ UiThreadUtil.runOnUiThread {
+ val item: MediaItem = MediaItem.fromUri(uri)
+ player.setMediaItem(item)
+ player.prepare()
+ player.play()
+ //play()
+ }
}
-
+ @ReactMethod
+ fun play() {
+ UiThreadUtil.runOnUiThread {
+ if (player.isPlaying) {
+ player.stop()
+ }
+ player.prepare()
+ player.play()
+ }
+ }
+
+ @ReactMethod
+ fun stop() {
+ UiThreadUtil.runOnUiThread { player.stop() }
+ }
+
+ override fun onPlaybackStateChanged(state: Int) {
+ var stateString = "unknown"
+ var playbackStateString = "unknown"
+ when (state) {
+ Player.STATE_IDLE, Player.STATE_ENDED -> {
+ stateString = "loadingFinished"
+ playbackStateString = "stopped"
+ }
+ Player.STATE_BUFFERING -> {
+ stateString = "loading"
+ playbackStateString = "paused"
+ }
+ Player.STATE_READY -> {
+ stateString = "loadingFinished"
+ playbackStateString = "playing"
+ }
+ }
+ val stateMap = WritableNativeMap()
+ stateMap.putString("state", stateString)
+ sendEvent(this.context, "StateDidChange", stateMap)
+
+ val playbackStateMap = WritableNativeMap()
+ playbackStateMap.putString("playbackState", playbackStateString)
+ sendEvent(this.context, "PlaybackStateDidChange", playbackStateMap)
+ }
+
+ private fun sendEvent(reactContext: ReactContext,
+ eventName: String,
+ params: NativeMap) {
+ reactContext
+ .getJSModule(RCTDeviceEventEmitter::class.java)
+ .emit(eventName, params)
+ }
+
+ override fun onMetadata(metadata: Metadata) {
+ Log.i("RadioPlayerMetadata", metadata.toString())
+ var artistName = "Unknown"
+ var trackName = "Unknown"
+ for (i in 1..metadata.length()) {
+ val entry: Metadata.Entry = metadata.get(i-1)
+ if (entry is IcyInfo) {
+ if (entry.title != null) {
+ val parts: List = entry.title!!.split(" - ")
+ artistName = parts[0]
+ trackName = parts[1]
+ }
+ }
+ }
+ val metadataMap = WritableNativeMap()
+ metadataMap.putString("artistName", artistName)
+ metadataMap.putString("trackName", trackName)
+ sendEvent(this.context, "MetadataDidChange", metadataMap)
+ }
}
diff --git a/example/android/RadioPlayerExample.iml b/example/android/RadioPlayerExample.iml
new file mode 100644
index 0000000..de23780
--- /dev/null
+++ b/example/android/RadioPlayerExample.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/android/app/app.iml b/example/android/app/app.iml
new file mode 100644
index 0000000..3a8d517
--- /dev/null
+++ b/example/android/app/app.iml
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
index bbcb2dc..7d450dc 100644
--- a/example/android/app/build.gradle
+++ b/example/android/app/build.gradle
@@ -132,6 +132,7 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
+ multiDexEnabled true
}
splits {
abi {
@@ -210,6 +211,8 @@ dependencies {
}
implementation project(':reactnativeradioplayer')
+ implementation 'com.android.support:multidex:1.0.3'
+
}
// Run this once to be able to run the application with BUCK
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index ecd3b04..8713c64 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -2,6 +2,7 @@
package="com.example.reactnativeradioplayer">
+
();
React.useEffect(() => {
- RadioPlayerEvents.addListener('StateDidChange', setPlayerState);
- RadioPlayerEvents.addListener(
- 'PlaybackStateDidChange',
- setPlayerPlaybackState
- );
+ RadioPlayerEvents.addListener('StateDidChange', (eventObject) => {
+ setPlayerState(eventObject.state);
+ });
+ RadioPlayerEvents.addListener('PlaybackStateDidChange', (eventObject) => {
+ setPlayerPlaybackState(eventObject.playbackState);
+ });
return () => {
- RadioPlayerEvents.removeListener('StateDidChange', setPlayerState);
+ RadioPlayerEvents.removeListener('StateDidChange', (eventObject) => {
+ setPlayerState(eventObject.state);
+ });
RadioPlayerEvents.removeListener(
'PlaybackStateDidChange',
- setPlayerPlaybackState
+ (eventObject) => {
+ setPlayerPlaybackState(eventObject.playbackState);
+ }
);
};
}, []);
@@ -28,7 +33,7 @@ export default function App() {
RadioPlayerEvents.addListener('MetadataDidChange', setMetadata);
React.useEffect(() => {
- RadioPlayer.radioURL('https://stream.fr.morow.com/morow_med.aacp');
+ RadioPlayer.radioURL('http://stream.fr.morow.com/morow_med.aacp');
return () => {
RadioPlayer.stop();
};
diff --git a/ios/RadioPlayer.swift b/ios/RadioPlayer.swift
index 38fcb4d..3c163f7 100644
--- a/ios/RadioPlayer.swift
+++ b/ios/RadioPlayer.swift
@@ -79,7 +79,7 @@ class RadioPlayer: RCTEventEmitter, FRadioPlayerDelegate {
}
print("player \(player) player state did change to \(stateString ?? "Unknown")")
if (hasListeners) {
- sendEvent(withName: "StateDidChange", body: stateString)
+ sendEvent(withName: "StateDidChange", body: ["state": stateString])
}
}
@@ -95,7 +95,7 @@ class RadioPlayer: RCTEventEmitter, FRadioPlayerDelegate {
}
print("player \(player) playback state did change to \(playbackStateString ?? "Unknown")")
if (hasListeners) {
- sendEvent(withName: "PlaybackStateDidChange", body: playbackStateString)
+ sendEvent(withName: "PlaybackStateDidChange", body: ["playbackState": playbackStateString])
}
}