我一直在开发一个使用用户从内部设备存储中选择的歌曲的应用程序。将所选音频文件的uri保存为共享首选项时,音频将在应用程序仍在运行(包括在活动之间进行更改)时加载并播放,但是,一旦应用程序重新启动,就会出现使用不变的uri。
我已经花了很多时间寻找使它起作用的方法,因此我们将不胜感激。
几年前,有一个类似的问题问了却没有答案... Saving audio content Uri in sharedpreference to play later
我在应用程序的歌曲选择器部分下面有一些代码:
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)