diff --git a/app/build.gradle b/app/build.gradle index fab637d..1e683b3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,7 +13,7 @@ android { targetSdkVersion 30 versionCode 1 versionName "1.0" - + multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -34,6 +34,11 @@ android { dependencies { + api project(':exorecord') + implementation 'com.google.android.exoplayer:exoplayer:2.13.3' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8' + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d59d79c..a4e3f4c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,17 +2,20 @@ + + android:theme="@style/Theme.ExoRecord" + android:fullBackupContent="true"> + - diff --git a/app/src/main/java/dev/brookmg/exorecord/App.kt b/app/src/main/java/dev/brookmg/exorecord/App.kt new file mode 100644 index 0000000..0ca204e --- /dev/null +++ b/app/src/main/java/dev/brookmg/exorecord/App.kt @@ -0,0 +1,17 @@ +package dev.brookmg.exorecord + +import android.app.Application +import dev.brookmg.exorecord.lib.ExoRecord + +class App : Application() { + + companion object { + lateinit var instance: App + val exoRecordInstance: ExoRecord by lazy { ExoRecord(instance) } + } + + override fun onCreate() { + super.onCreate() + instance = this + } +} \ No newline at end of file diff --git a/app/src/main/java/dev/brookmg/exorecord/MainActivity.kt b/app/src/main/java/dev/brookmg/exorecord/MainActivity.kt index 3523128..c590c76 100644 --- a/app/src/main/java/dev/brookmg/exorecord/MainActivity.kt +++ b/app/src/main/java/dev/brookmg/exorecord/MainActivity.kt @@ -1,11 +1,108 @@ package dev.brookmg.exorecord -import androidx.appcompat.app.AppCompatActivity +import android.content.Context +import android.net.Uri import android.os.Bundle +import android.util.Log +import android.widget.Button +import androidx.appcompat.app.AppCompatActivity +import com.google.android.exoplayer2.DefaultRenderersFactory +import com.google.android.exoplayer2.MediaItem +import com.google.android.exoplayer2.SimpleExoPlayer +import com.google.android.exoplayer2.audio.* +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory +import com.google.android.exoplayer2.source.MediaSource +import com.google.android.exoplayer2.source.ProgressiveMediaSource +import com.google.android.exoplayer2.source.hls.HlsExtractorFactory +import com.google.android.exoplayer2.source.hls.HlsMediaSource +import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector +import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory +import com.google.android.exoplayer2.upstream.DefaultHttpDataSource +import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class MainActivity : AppCompatActivity() { + + companion object { + const val FORMAT_MP3 = "mp3" + const val FORMAT_MP4 = "mp4" + const val FORMAT_M3U = "m3u" + const val FORMAT_M3U8 = "m3u8" + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + val streamUrl = "https://stream.live.vc.bbcmedia.co.uk/bbc_radio_one?s=1619514803&e=1619529203&h=f378f4ca18759ebfa5fd1d674c794cfc" + + val mainMediaSource: MediaSource + val uri = Uri.parse(streamUrl) + val lastPath = uri.lastPathSegment + + val bandwidthMeter = DefaultBandwidthMeter.Builder(applicationContext).build() + val trackSelectionFactory = AdaptiveTrackSelection.Factory() + val httpDataSourceFactory = DefaultHttpDataSourceFactory( + "-- Audio Test --", + bandwidthMeter, + DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, + DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, + true + ) + + val dataSourceFactory = DefaultDataSourceFactory(this, bandwidthMeter, httpDataSourceFactory) + + if (lastPath == null || lastPath.isEmpty()) return + mainMediaSource = if (lastPath.contains(FORMAT_M3U8) || + lastPath.contains(FORMAT_M3U)) { + HlsMediaSource.Factory(dataSourceFactory) + .setAllowChunklessPreparation(true) + .setExtractorFactory(HlsExtractorFactory.DEFAULT) + .createMediaSource(MediaItem.fromUri(uri)) + } else { + ProgressiveMediaSource.Factory(dataSourceFactory, DefaultExtractorsFactory()).createMediaSource( + MediaItem.fromUri(uri) + ) + } + + val renderersFactory = object : DefaultRenderersFactory(this) { + override fun buildAudioSink( + context: Context, enableFloatOutput: Boolean, + enableAudioTrackPlaybackParams: Boolean, enableOffload: Boolean + ): AudioSink { + return DefaultAudioSink( + AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES, + DefaultAudioSink.DefaultAudioProcessorChain(App.exoRecordInstance.exoRecordProcessor), + enableFloatOutput, enableAudioTrackPlaybackParams, enableOffload + ) + } + } + + val trackSelector = DefaultTrackSelector(applicationContext, trackSelectionFactory) + val exoPlayer = SimpleExoPlayer.Builder(applicationContext, renderersFactory) + .setTrackSelector(trackSelector) + .setBandwidthMeter(bandwidthMeter) + .build() + + exoPlayer.setMediaSource(mainMediaSource) + exoPlayer.prepare() + + findViewById