I have been working on an app which uses a song chosen by the user from the internal device storage. When saving the uri of the selected audio file to shared preferences the audio will load and play when the app is still running (including changing between activities), however, as soon as the app is restarted there is an issue creating the media player using the same unchanged uri.
I have spent a lot of time looking for a way to get this to work so any help would be much appreciated.
There was a similar question asked without an answer a few years ago... Saving audio content Uri in sharedpreference to play later
I have some code below of the song selector part of the app:
JAVA:
package com.example.android.songselector;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
MediaPlayer player;
SharedPreferences sharedPrefs;
SharedPreferences.Editor prefsEditor;
SeekBar seekBar;
ImageButton playBtn;
Button chooseBtn;
Button stopBtn;
Uri selectedSong;
String mySong;
int mProgress;
Runnable runnable;
Handler mainHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sharedPrefs = getSharedPreferences("PREFS", MODE_PRIVATE);
mySong = sharedPrefs.getString("song", "");
if (!mySong.equals("")) {
selectedSong = Uri.parse(mySong);
}
playBtn = findViewById(R.id.play_button);
chooseBtn = findViewById(R.id.choose_song_button);
stopBtn = findViewById(R.id.stop_button);
seekBar = findViewById(R.id.seek_bar);
mainHandler = new Handler();
if (selectedSong != null) {
player = MediaPlayer.create(MainActivity.this, selectedSong);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
seekBar.setMax(player.getDuration());
player.seekTo(0);
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean input) {
if (input) {
if (player != null) {
player.seekTo(progress);
}
mProgress = progress;
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
else {
chooseSong();
if(selectedSong != null) {
player = MediaPlayer.create(MainActivity.this, selectedSong);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
seekBar.setMax(player.getDuration());
player.seekTo(0);
}
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean input) {
if(input){
if(player != null){
player.seekTo(progress);
}
mProgress = progress;
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
playBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(selectedSong == null){
chooseSong();
}
else {
if(player == null){
if(selectedSong != null){
player = MediaPlayer.create(MainActivity.this, selectedSong);
seekBar.setMax(player.getDuration());
}
else{
Toast.makeText(MainActivity.this, "Please select a song file to play.", Toast.LENGTH_SHORT).show();
}
}
if(player != null){
seekBar.refreshDrawableState();
if(mProgress > (player.getDuration() - 30)){
player.seekTo(0);
}
else{
player.seekTo(mProgress);
}
if(player.isPlaying()){
player.pause();
setPlayButtonImage();
}
else {
player.start();
playCycle();
setPlayButtonImage();
}
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
//Restarts song from beginning
player.seekTo(0);
seekBar.setProgress(0);
player.start();
playCycle();
}
});
}
}
}
});
chooseBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent audiofile_chooser_intent = new Intent();
audiofile_chooser_intent.setAction(Intent.ACTION_GET_CONTENT);
audiofile_chooser_intent.setType("audio/*");
startActivityForResult(audiofile_chooser_intent, 1);
stopPlaying();
}
});
stopBtn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
stopPlaying();
if(selectedSong != null){
player = MediaPlayer.create(MainActivity.this, selectedSong);
seekBar.setMax(player.getDuration());
seekBar.setProgress(0);
mProgress = 0;
setPlayButtonImage();
}
}
});
}
//Changes the play button depending on whether the song is playing or not
private void setPlayButtonImage(){
if(player.isPlaying()){
playBtn.setImageResource(R.drawable.pause_button);
}
else {
playBtn.setImageResource(R.drawable.play_button);
}
}
public void playCycle() {
seekBar.setProgress(player.getCurrentPosition());
if(player.isPlaying()){
runnable = new Runnable() {
@Override
public void run() {
playCycle();
}
};
mainHandler.postDelayed(runnable, 1000);
}
}
private void stopPlaying(){
if(player != null){
player.stop();
player.reset();
player.release();
player = null;
}
}
//Creates dialog box for user to select an audio file from internal storage
private void chooseSong() {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
AlertDialog songDialog = builder.create();
songDialog.setTitle(R.string.select_song);
songDialog.setMessage(getString(R.string.choose_song));
songDialog.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.button_browse), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent audiofile_chooser_intent = new Intent();
audiofile_chooser_intent.setAction(Intent.ACTION_GET_CONTENT);
audiofile_chooser_intent.setType("audio/*");
audiofile_chooser_intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(audiofile_chooser_intent, 1);
}
});
songDialog.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.button_cancel), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//Do nothing
}
});
songDialog.show();
}
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
if(requestCode == 1){
if(resultCode == RESULT_OK){
selectedSong = data.getData();
if(selectedSong != null){
mySong = selectedSong.toString();
}
//Save the Song Uri in string format to Shared Preferences
prefsEditor = sharedPrefs.edit();
prefsEditor.putString("song", mySong);
prefsEditor.apply();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
protected void onPause() {
super.onPause();
if(player != null){
player.pause();
setPlayButtonImage();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(player != null){
player.release();
}
mainHandler.removeCallbacks(runnable);
}
}
LOGCAT:
10-19 19:49:06.084 32507-32507/com.example.android.songselector E/MediaPlayerNative: Unable to create media player
10-19 19:49:06.085 32507-32507/com.example.android.songselector D/MediaPlayer: create failed:
java.io.IOException: setDataSource failed.: status=0x80000000
at android.media.MediaPlayer.nativeSetDataSource(Native Method)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1235)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1223)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1138)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1080)
at android.media.MediaPlayer.create(MediaPlayer.java:972)
at android.media.MediaPlayer.create(MediaPlayer.java:949)
at android.media.MediaPlayer.create(MediaPlayer.java:928)
at com.example.android.songselector.MainActivity.onCreate(MainActivity.java:84)
at android.app.Activity.performCreate(Activity.java:7174)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
10-19 19:49:06.086 32507-32507/com.example.android.songselector D/AndroidRuntime: Shutting down VM
10-19 19:49:06.086 32507-32507/com.example.android.songselector E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.songselector, PID: 32507
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.songselector/com.example.android.songselector.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.media.MediaPlayer.setAudioStreamType(int)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2957)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.media.MediaPlayer.setAudioStreamType(int)' on a null object reference
at com.example.android.songselector.MainActivity.onCreate(MainActivity.java:85)
at android.app.Activity.performCreate(Activity.java:7174)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
User contributions licensed under CC BY-SA 3.0