Выберите музыкальный файл для воспроизведения с помощью MediaPlayer

Я новичок в программировании для Android, и теперь у меня проблема с моим приложением. Я намерен закодировать приложение MediaPlayer с функцией: выберите файл из хранилища с помощью намерения, а затем начните воспроизведение этого файла. Я использую метод «MediaPlayer.create(context, uri)», но в настоящее время я получаю сообщение об ошибке

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //openFile();
    Button openFile = (Button) this.findViewById(R.id.ButtonOpen);
    openFile.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            Intent chooseFile;
            Intent intent;
            chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
            chooseFile.setType("file/*");
            intent = Intent.createChooser(chooseFile, "Choose a file");
            startActivityForResult(intent, ACTIVITY_CHOOSE_FILE);

            Uri uri = intent.getData();
            initViews(uri);
        }
    }); 

}

private void initViews(Uri uri) {
    mButtonPlayStop = (Button) findViewById(R.id.ButtonPlayStop);
    mButtonPlayStop.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            buttonClick();
        }
    });

    mMediaPlayer = MediaPlayer.create(this, uri);
}


private void starPlayProgressUpdater() {
    mSeekBar.setProgress(mMediaPlayer.getCurrentPosition());

    if (mMediaPlayer.isPlaying()) {
        Runnable notification = new Runnable() {

            @Override
            public void run() {
                starPlayProgressUpdater();
            }
        };
        mHandler.postDelayed(notification, 1000);
    } else {
        mMediaPlayer.pause();
        mButtonPlayStop.setText(getString(R.string.play_str));
        mSeekBar.setProgress(0);
    }
}

private void buttonClick() {
    if (mButtonPlayStop.getText() == getString(R.string.play_str)) {
        mButtonPlayStop.setText(getString(R.string.pause_str));
        try {
            mMediaPlayer.start();
            starPlayProgressUpdater();              
        } catch (IllegalStateException e) {
            mMediaPlayer.pause();
        }
    } else {
        mButtonPlayStop.setText(getString(R.string.play_str));
        mMediaPlayer.pause();
    }
}

И он генерирует исключение NullPointerException в «mMediaPlayer = MediaPlayer.create(this, uri);». У него проблемы с uri. Может ли кто-нибудь указать мне путь?


Спасибо, Ilango j, я пересмотрел свой код, и теперь я могу выбрать и воспроизвести музыкальный файл. Но мое ожидание - это выбрать файл, а затем воспроизводить его только после нажатия кнопки «Воспроизведение/Пауза» (с индикатором выполнения), но я получил новое исключение NullPointerException с моей кнопкой.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mContext = (Context) getApplicationContext();

    Button openFile = (Button) this.findViewById(R.id.ButtonOpen);
    openFile.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {       
            initView();
        }
    }); 

}

private void initView() {
    mButtonPlayStop = (Button) findViewById(R.id.ButtonPlayStop);
    mButtonPlayStop.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            buttonClick();
        }
    });

    Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, 10);

}
    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == RESULT_OK && requestCode == 10) {
        Uri uri = data.getData();

        mMediaPlayer = MediaPlayer.create(mContext, uri);

        mSeekBar = (SeekBar) findViewById(R.id.SeekBar01);
        mSeekBar.setMax(mMediaPlayer.getDuration());
        mSeekBar.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                seekChange(v);
                return false;
            }
        });         
    }
}   

private void starPlayProgressUpdater() {
    mSeekBar.setProgress(mMediaPlayer.getCurrentPosition());

    if (mMediaPlayer.isPlaying()) {
        Runnable notification = new Runnable() {

            @Override
            public void run() {
                starPlayProgressUpdater();
            }
        };
        mHandler.postDelayed(notification, 1000);
    } else {
        mMediaPlayer.pause();
        mButtonPlayStop.setText(getString(R.string.play_str));
        mSeekBar.setProgress(0);
    }
}

private void seekChange(View v) {
    if (mMediaPlayer.isPlaying()) {
        SeekBar sb = (SeekBar) v;
        mMediaPlayer.seekTo(sb.getProgress());
    }
}

private void buttonClick() {
    if (mButtonPlayStop.getText().equals(getString(R.string.play_str))) {
        mButtonPlayStop.setText(getString(R.string.pause_str));
        try {
            mMediaPlayer.start();
            starPlayProgressUpdater();              
        } catch (IllegalStateException e) {
            mMediaPlayer.pause();
        }
    } else {
        mButtonPlayStop.setText(getString(R.string.play_str));
        mMediaPlayer.pause();
    }
}

Не могли бы вы дать совет?


person Liverpudlian    schedule 11.06.2013    source источник


Ответы (3)


Сначала начните работу с мультимедийным файлом pic с SD-карты. Замените следующий код

Button openFile = (Button) this.findViewById(R.id.ButtonOpen);
    openFile.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
           Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(intent, 10);
        }
    }); 

Затем добавьте следующий код в onActivityResult

     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {

          if(resultCode == RESULT_OK && requestCode == 10){
                Uri uriSound=data.getData();
                play(this, uriSound); 
          }
      }

И вызовите приведенный ниже метод, чтобы создать медиаплеер и воспроизвести выбранный аудиофайл.

   private void play(Context context, Uri uri) {

        try {
            MediaPlayer mp = new MediaPlayer();
            mp.setDataSource(context, uri);         
            mp.start();
          } catch (IllegalArgumentException e) {
          // TODO Auto-generated catch block
             e.printStackTrace();
          } catch (SecurityException e) {
          // TODO Auto-generated catch block
             e.printStackTrace();
          } catch (IllegalStateException e) {
          // TODO Auto-generated catch block
             e.printStackTrace();
          } catch (IOException e) {
          // TODO Auto-generated catch block
             e.printStackTrace();
          }
    }
person ilango j    schedule 11.06.2013
comment
Спасибо за ваше руководство, я пересматриваю свой код на основе вашего комментария. Но я ожидаю, что вы выберете музыкальный файл из хранилища, а затем с помощью кнопки «Воспроизведение» начнете/приостановите декодирование. Теперь я сталкиваюсь с новой ошибкой с моей кнопкой. - person Liverpudlian; 12.06.2013
comment
здесь опечатка... должно быть... if(resultCode == RESULT_OK - person romerun; 06.01.2016
comment
Что делать, если я хочу выбрать несколько файлов, есть ли у них какое-либо диалоговое окно с несколькими вариантами выбора? - person Neo; 18.06.2017

Если у кого-то возникнут трудности с этим вопросом, как у меня, я внес некоторые исправления в ответы выше, и этот фрагмент должен работать:

private  final int SELECT_MUSIC = 1;

public void pickMusic() {
    Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(i,SELECT_MUSIC);
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_MUSIC){
            Uri selectedMusicUri = data.getData();
            if (selectedMusicUri != null){
                String pathFromUri = getRealPathFromURI(this, selectedMusicUri);
                MediaPlayer mp = new MediaPlayer();
                try {
                    mp.setDataSource(this, Uri.parse(pathFromUri));
                    mp.prepare();
                    mp.start();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


private String getRealPathFromURI(Context context, Uri contentUri) {
    String[] projection = { MediaStore.Audio.Media.DATA };
    CursorLoader loader = new CursorLoader(context, contentUri, projection, null, null, null);
    Cursor cursor = loader.loadInBackground();
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}
person yshahak    schedule 07.07.2015

Глядя на исходный код создания MediaPlayer, он выглядит так:

public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder) {

        try {
            MediaPlayer mp = new MediaPlayer();
            mp.setDataSource(context, uri);
            if (holder != null) {
                mp.setDisplay(holder);
            }
            mp.prepare();
            return mp;
        } catch (IOException ex) {
            Log.d(TAG, "create failed:", ex);
            // fall through
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "create failed:", ex);
            // fall through
        } catch (SecurityException ex) {
            Log.d(TAG, "create failed:", ex);
            // fall through
        }

        return null;
    }

Таким образом, в вашем случае ошибка может заключаться в том, что URI, который вы передаете в параметр, неверен или искажен, поэтому метод создания возвращает значение null. Проверьте правильность URI при создании объекта mediaPlayer.

Также я видел эту строку:

if (mButtonPlayStop.getText() == getString(R.string.play_str))

Не используйте == для сравнения содержимого строк. Вместо этого используйте .equals():

if (mButtonPlayStop.getText().equals(getString(R.string.play_str)))
person Alexis C.    schedule 11.06.2013
comment
Спасибо за ваш комментарий, я понял - person Liverpudlian; 12.06.2013