Skip to content

Commit

Permalink
add audio foreground service for ExoPlayer
Browse files Browse the repository at this point in the history
  • Loading branch information
Monthira Chayabanjonglerd committed Jul 30, 2018
1 parent 93f05ce commit 4911665
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 36 deletions.
Binary file modified .idea/caches/build_file_checksums.ser
Binary file not shown.
5 changes: 4 additions & 1 deletion app/src/main/AndroidManifest.xml
Expand Up @@ -2,21 +2,24 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mikkipastel.exoplayer18">

<uses-permission android:name="android.permission.INTERNET "/>
<uses-permission android:name="android.permission.INTERNET"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/PlayerTheme">

<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service android:name=".AudioPlayerService"/>
</application>

</manifest>
108 changes: 108 additions & 0 deletions app/src/main/java/com/mikkipastel/exoplayer18/AudioPlayerService.kt
@@ -0,0 +1,108 @@
package com.mikkipastel.exoplayer18

import android.app.Notification
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.graphics.Bitmap
import android.os.IBinder
import com.google.android.exoplayer2.ExoPlayerFactory
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.source.ConcatenatingMediaSource
import com.google.android.exoplayer2.source.ExtractorMediaSource
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util
import com.mikkipastel.exoplayer18.C.PLAYBACK_CHANNEL_ID
import com.mikkipastel.exoplayer18.C.PLAYBACK_NOTIFICATION_ID
import com.mikkipastel.exoplayer18.Samples.SAMPLES

class AudioPlayerService: Service() {

lateinit var player: SimpleExoPlayer

lateinit var playerNotificationManager: PlayerNotificationManager

override fun onCreate() {
super.onCreate()
val context = this

player = ExoPlayerFactory.newSimpleInstance(context, DefaultTrackSelector())

val dataSourceFactory = DefaultDataSourceFactory(
context,
Util.getUserAgent(context, "AudioDemo")
)

val concatenatingMediaSource = ConcatenatingMediaSource()
for (sample in SAMPLES) {
val mediaSource = ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(sample.uri)
concatenatingMediaSource.addMediaSource(mediaSource)
}

player.prepare(concatenatingMediaSource)
player.playWhenReady = true

playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
context,
PLAYBACK_CHANNEL_ID,
R.string.playback_channel_name,
PLAYBACK_NOTIFICATION_ID,
object: PlayerNotificationManager.MediaDescriptionAdapter {
override fun getCurrentContentTitle(player: Player?): String {
return SAMPLES[player!!.currentWindowIndex].title
}

override fun createCurrentContentIntent(player: Player?): PendingIntent? {
return PendingIntent.getActivity(
context,
0,
Intent(context, MainActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT
)
}

override fun getCurrentContentText(player: Player?): String? {
return SAMPLES[player!!.currentWindowIndex].description
}

override fun getCurrentLargeIcon(player: Player?, callback: PlayerNotificationManager.BitmapCallback?): Bitmap? {
return Samples.getBitmap(
context, SAMPLES[player!!.currentWindowIndex].bitmapResource)
}

})

playerNotificationManager.apply {
setNotificationListener(object: PlayerNotificationManager.NotificationListener {
override fun onNotificationStarted(notificationId: Int, notification: Notification?) {
startForeground(notificationId, notification)
}

override fun onNotificationCancelled(notificationId: Int) {
stopSelf()
}

})
setPlayer(player)
}
}

override fun onDestroy() {
playerNotificationManager.setPlayer(null)
player.release()
super.onDestroy()
}

override fun onBind(intent: Intent?): IBinder? {
return null
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return START_STICKY
}

}
11 changes: 11 additions & 0 deletions app/src/main/java/com/mikkipastel/exoplayer18/C.kt
@@ -0,0 +1,11 @@
package com.mikkipastel.exoplayer18

object C {

val PLAYBACK_CHANNEL_ID = "playback_channel"
val PLAYBACK_NOTIFICATION_ID = 1
val MEDIA_SESSION_TAG = "audio_demo"
val DOWNLOAD_CHANNEL_ID = "download_channel"
val DOWNLOAD_NOTIFICATION_ID = 2

}
38 changes: 10 additions & 28 deletions app/src/main/java/com/mikkipastel/exoplayer18/MainActivity.kt
@@ -1,46 +1,28 @@
package com.mikkipastel.exoplayer18

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import com.google.android.exoplayer2.ExoPlayerFactory
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.source.ExtractorMediaSource
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import android.widget.ArrayAdapter
import com.google.android.exoplayer2.util.Util
import com.mikkipastel.exoplayer18.Samples.SAMPLES
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : Activity() {

private var player: SimpleExoPlayer? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}

override fun onStart() {
super.onStart()

player = ExoPlayerFactory.newSimpleInstance(this, DefaultTrackSelector())

playerView.player = player
val intent = Intent(this, AudioPlayerService::class.java)
Util.startForegroundService(this, intent)

val dataSourceFactory = DefaultDataSourceFactory(this,
Util.getUserAgent(this, getString(R.string.app_name)))
val mediaSource = ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Samples.MP4_URI)

player?.prepare(mediaSource)
player?.playWhenReady = true
listview.adapter = ArrayAdapter(
this,
android.R.layout.simple_list_item_1,
emptyArray<Samples>()
)

}

override fun onStop() {
super.onStop()

playerView.player = null
player?.release()
player = null
}
}
60 changes: 56 additions & 4 deletions app/src/main/java/com/mikkipastel/exoplayer18/Samples.kt
@@ -1,11 +1,63 @@
package com.mikkipastel.exoplayer18

import android.content.Context
import android.net.Uri
import android.graphics.drawable.BitmapDrawable
import android.support.annotation.DrawableRes
import android.graphics.Bitmap
import android.support.v4.media.MediaDescriptionCompat
import android.support.v4.media.MediaMetadataCompat
import android.os.Bundle

class Samples {
object Samples {

companion object {
val MP4_URI = Uri.parse("https://storage.googleapis.com/exoplayer-test-media-0/firebase-animation.mp4")
val AD_TAG_URI = Uri.parse("https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostlongpod&cmsid=496&vid=short_tencue&correlator=")
class Sample(
url: String,
val mediaId: String,
val title: String,
val description: String,
val bitmapResource: Int) {

val uri: Uri = Uri.parse(url)

override fun toString(): String {
return title
}
}

val SAMPLES = arrayOf(Sample(
"http://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
"audio_1",
"Jazz in Paris",
"Jazz for the masses",
R.drawable.album_art_1), Sample(
"http://storage.googleapis.com/automotive-media/The_Messenger.mp3",
"audio_2",
"The messenger",
"Hipster guide to London",
R.drawable.album_art_2), Sample(
"http://storage.googleapis.com/automotive-media/Talkies.mp3",
"audio_3",
"Talkies",
"If it talks like a duck and walks like a duck.",
R.drawable.album_art_3))

fun getMediaDescription(context: Context, sample: Sample): MediaDescriptionCompat {
val extras = Bundle()
val bitmap = getBitmap(context, sample.bitmapResource)
extras.putParcelable(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap)
extras.putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, bitmap)
return MediaDescriptionCompat.Builder()
.setMediaId(sample.mediaId)
.setIconBitmap(bitmap)
.setTitle(sample.title)
.setDescription(sample.description)
.setExtras(extras)
.build()
}

fun getBitmap(context: Context, @DrawableRes bitmapResource: Int): Bitmap {
return (context.resources.getDrawable(bitmapResource, context.theme) as BitmapDrawable).bitmap
}

}
Binary file added app/src/main/res/drawable/album_art_1.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/album_art_2.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/album_art_3.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/ic_queue_music_24dp.xml
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFCCCCCC"
android:pathData="M15,6L3,6v2h12L15,6zM15,10L3,10v2h12v-2zM3,16h8v-2L3,14v2zM17,6v8.18c-0.31,-0.11 -0.65,-0.18 -1,-0.18 -1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3L19,8h3L22,6h-5z"/>
</vector>
11 changes: 8 additions & 3 deletions app/src/main/res/layout/activity_main.xml
Expand Up @@ -3,9 +3,14 @@
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/playerView"
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
android:layout_height="match_parent"
android:src="@drawable/ic_queue_music_24dp"
android:scaleType="fitCenter" />

<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
@@ -1,3 +1,5 @@
<resources>
<string name="app_name">exoplayer18</string>
<string name="playback_channel_name">Playback</string>
<string name="download_channel_name">Download</string>
</resources>

0 comments on commit 4911665

Please sign in to comment.