Android Studio Hedgehog | 2023.1.2
Note: For personal reference using MediaPlayer and Media3 ExoPlayer in java
build.gradle.kts (Module: app)
dependencies {
....
implementation("androidx.media3:media3-exoplayer:1.2.1") // ExoPlayer
implementation("androidx.media3:media3-common:1.2.1") // setAudioAttributes; MediaItem
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
...
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MediaPlayer"
android:id="@+id/b_mediaplayer"
/>
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ExoPlayer"
android:id="@+id/b_exoplayer"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
MyExoPlayer.java
package com.dedetok.tutorialexoplayer;
import android.content.Context;
import android.util.Log;
import androidx.media3.common.MediaItem;
import androidx.media3.exoplayer.ExoPlaypackage com.dedetok.tutorialexoplayer;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatButton;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
MyMediaPlayer myMediaPlayer;
MyExoPlayer myExoPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myMediaPlayer = new MyMediaPlayer();
myExoPlayer = new MyExoPlayer(this);
String myRadioUrl = "https://stream-node1.rri.co.id/streaming/25/9025/rrijakartapro1.mp3";
//String myRadioUrl = "http://cast1.my-control-panel.com/proxy/radioso1/stream";
AppCompatButton bMediaPlayer = findViewById(R.id.b_mediaplayer);
bMediaPlayer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myExoPlayer.stop();
myMediaPlayer.play(myRadioUrl);
}
});
AppCompatButton bExoPlayer = findViewById(R.id.b_exoplayer);
bExoPlayer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myMediaPlayer.stop();
myExoPlayer.play(myRadioUrl);
}
});
}
}er;
public class MyExoPlayer {
// API level 23 / Android N / Android 6.0
ExoPlayer myPlayer;
public MyExoPlayer(Context appContext) {
myPlayer = new ExoPlayer.Builder(appContext).build();
}
public void play(String myRadioUrl) {
if (myPlayer.isPlaying()) {
myPlayer.stop();
Log.e("dedetok", "ExoPlaayer playing Stop"); // debug
} else {
try {
Log.e("dedetok", "ExoPlaayer playing " + myRadioUrl); // debug
MediaItem myRadio = MediaItem.fromUri(myRadioUrl);
myPlayer.setMediaItem(myRadio);
myPlayer.prepare();
myPlayer.play();
} catch (IllegalArgumentException e) {
Log.e("dedetok", "ExoPlayer IllegalArgumentException " + e.getMessage()); // debug
}
}
}
public void stop() {
myPlayer.stop();
}
public void release() {
myPlayer.release();
myPlayer=null;
}
}
MyMediaPlayer.java
package com.dedetok.tutorialexoplayer;
import android.media.AudioAttributes;
import android.media.MediaPlayer;
import android.util.Log;
import java.io.IOException;
public class MyMediaPlayer implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener {
MediaPlayer myPlayer;
boolean isPrepared= false;
public MyMediaPlayer() {
myPlayer = new MediaPlayer();
}
public void play(String myRadioUrl) {
if (myPlayer.isPlaying()) {
myPlayer.stop();
myPlayer.reset();
Log.e("dedetok", "MediaPlayer Stop"); // debug
} else {
Log.e("dedetok", "MediaPlayer playing " + myRadioUrl); // debug
myPlayer.setOnPreparedListener(this);
myPlayer.setAudioAttributes(
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.setLegacyStreamType(AudioAttributes.USAGE_MEDIA)
.build()
);
myPlayer.setOnErrorListener(this);
try {
myPlayer.setDataSource(myRadioUrl);
isPrepared=true;
myPlayer.prepareAsync();
} catch (IOException e) {
Log.e("dedetok", "IOException " + e.getMessage()); // debug
} catch (IllegalArgumentException e) {
Log.e("dedetok", "IllegalArgumentException " + e.getMessage()); // debug
}
}
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
/*
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (mediaPlayer.getDrmInfo() != null) {
myPlayer.prepareDrm();
//myPlayer.getKeyRequest();
//myPlayer.provideKeyResponse();
}
}
*/
myPlayer.start();
isPrepared=false;
}
public void stop() {
if (!isPrepared) {
myPlayer.stop();
myPlayer.reset();
isPrepared = false;
} else {
myPlayer.reset();
isPrepared = false;
}
}
@Override
public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
String tmp="";
if (what == MediaPlayer.MEDIA_ERROR_UNKNOWN)
tmp = "MediaPlayer.MEDIA_ERROR_UNKNOWN";
if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED)
tmp = "MediaPlayer.MEDIA_ERROR_SERVER_DIED";
if (extra == MediaPlayer.MEDIA_ERROR_IO)
tmp+=" MediaPlayer.MEDIA_ERROR_IO";
if (extra == MediaPlayer.MEDIA_ERROR_MALFORMED)
tmp+=" MediaPlayer.MEDIA_ERROR_MALFORMED";
if (extra == MediaPlayer.MEDIA_ERROR_UNSUPPORTED)
tmp+=" MediaPlayer.MEDIA_ERROR_UNSUPPORTED";
if (extra == MediaPlayer.MEDIA_ERROR_TIMED_OUT)
tmp+=" MediaPlayer.MEDIA_ERROR_TIMED_OUT";
Log.e("dedetok", "OnErrorListener " + tmp); // debug
myPlayer.reset();
isPrepared=false;
return true;
}
public void release() {
myPlayer.release();
myPlayer=null;
}
}
MainActivity.java
package com.dedetok.tutorialexoplayer;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatButton;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
MyMediaPlayer myMediaPlayer;
MyExoPlayer myExoPlayer;
int buildVersion=0;
/*
* ## activity life cycle 1 ##
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildVersion = Build.VERSION.SDK_INT; // get android version from device
String myRadioUrl = "https://stream-node1.rri.co.id/streaming/25/9025/rrijakartapro1.mp3";
//String myRadioUrl = "http://cast1.my-control-panel.com/proxy/radioso1/stream";
AppCompatButton bMediaPlayer = findViewById(R.id.b_mediaplayer);
bMediaPlayer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myExoPlayer.stop();
myMediaPlayer.play(myRadioUrl);
}
});
AppCompatButton bExoPlayer = findViewById(R.id.b_exoplayer);
bExoPlayer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myMediaPlayer.stop();
myExoPlayer.play(myRadioUrl);
}
});
}
/*
* ## activity life cycle 2 ##
*/
@Override
protected void onStart() {
super.onStart();
// Android N Android 7
if (buildVersion>= Build.VERSION_CODES.N) {
myMediaPlayer = new MyMediaPlayer();
myExoPlayer = new MyExoPlayer(this);
}
}
/*
* ## activity life cycle 3 ##
*/
@Override
protected void onResume() {
super.onResume();
// Android N Android 7
if (buildVersion< Build.VERSION_CODES.N) {
myMediaPlayer = new MyMediaPlayer();
myExoPlayer = new MyExoPlayer(this);
}
}
/*
* ## activity life cycle 4 ##
*/
@Override
protected void onPause() {
if (buildVersion<Build.VERSION_CODES.N) {
myMediaPlayer.release();
myMediaPlayer=null;
myExoPlayer.release();
myExoPlayer=null;
}
super.onPause();
}
/*
* ## activity life cycle 5 ##
*/
@Override
protected void onStop() {
if (buildVersion>=Build.VERSION_CODES.N) {
myMediaPlayer.release();
myMediaPlayer=null;
myExoPlayer.release();
myExoPlayer=null;
}
super.onStop();
}
/*
* ## activity life cycle 6 ##
*/
@Override
protected void onDestroy() {
super.onDestroy();
}
}
Pron using ExoPlayer:
- ExoPlayer can handle https media streaming for self signing sertificate but MediaPlayer can not.
- Handing media streaming in ExoPlayer uses less code then MediaPlayer.
Cons using ExoPlayer
- ExoPlayer required minimum API level 23 / Android N / Android 6.0