关闭后无法从 URI 播放音频 re-opening 我的应用

Impossible to play audio from URI after closing and re-opening my app

我正在开发一个管理 WhatsApp 语音笔记的应用程序。 在 WhatsApp UI 中,用户可以共享语音留言,然后 select 我的应用程序作为共享选项。 然后,我的应用程序通过隐式意图接收 WhatsApp 语音笔记 URI,并且通过使用 URI,当用户按下我应用程序 UI.

中的按钮时,应用程序可以播放语音笔记

我面临的问题如下:在我的应用程序中保存语音笔记 URI 后,我可以播放它,但是如果我关闭(在任务管理器中)我的应用程序然后再次打开它,我是无法再播放语音笔记。 我没有制作语音笔记文件的任何副本:我只是通过将其 URI 传递到我的应用程序中的 MediaPlayer class 来播放它。我得到的错误是:

09-05 18:11:47.532 10160-10160/? E/AndroidRuntime: FATAL EXCEPTION: main
                                               Process: com.id12401446.audios, PID: 10160
                                               java.lang.NullPointerException: Attempt to invoke virtual method 'void android.media.MediaPlayer.start()' on a null object reference
                                                   at com.id12401446.audios.fragments.DefaultPlaylistFragment$DefaultPlaylistAdapter.onClick(DefaultPlaylistFragment.java:174)
                                                   at android.view.View.performClick(View.java:6199)
                                                   at android.widget.TextView.performClick(TextView.java:11090)
                                                   at android.view.View$PerformClick.run(View.java:23647)
                                                   at android.os.Handler.handleCallback(Handler.java:751)
                                                   at android.os.Handler.dispatchMessage(Handler.java:95)
                                                   at android.os.Looper.loop(Looper.java:154)
                                                   at android.app.ActivityThread.main(ActivityThread.java:6682)
                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

以下是我如何从隐式意图中获取 WhatsApp 语音笔记 URI(所有这些都在 SaveRecording activity 中完成):

//Handling external audio intents that can start this activity
    Intent intent = this.getIntent();
    String action = intent.getAction();
    String type = intent.getType();
    if (action != null && action.equals(Intent.ACTION_SEND) && type != null) {
        if (type.startsWith("audio/")) {

            //getExternalRecording(intent);
            Uri uriFromExternalIntent = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
            Log.d(TAG, "mRecording uri got from external intent is: " + uriFromExternalIntent);
            this.mRecordingUriString = uriFromExternalIntent.toString();
        }

下面是我如何在我的应用程序中通过按下 UI 中的按钮来播放 WhatsApp 语音笔记(recordingData object 包含语音笔记 URI 和标题保存在之前的 SaveRecording activity):

 //Adding ClickListener for the play button
        rowPlayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


                String recordingUriString = recordingData.getURI();
                Uri recordingUri = Uri.parse(recordingUriString);

                Log.d("MAD", "URI of the currently playing audio is: " + recordingUriString);

                //Creating a new MediaPlayer object to play the recording
                MediaPlayer mediaPlayer = new MediaPlayer();
                try {
                    Log.d(TAG,"Trying to set audio stream...");
                    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    Log.d(TAG, "Audio stream set successfully");
                    Log.d(TAG, "Trying to set data source...");
                    mediaPlayer.setDataSource(getContext(), recordingUri);
                    Log.d(TAG, "Data source set successfully: preparing MediaPlayer...");
                    mediaPlayer.prepare();
                    Log.d(TAG, "MediaPlayer prepared successfully: starting playback...");
                    mediaPlayer.start();
                } catch (IOException e) {
                    Log.e("MAD", "Error while trying to play data from uri: " + recordingUri);
                    Toast.makeText(getContext(), "Error playing data from uri: " + recordingUri, Toast.LENGTH_LONG).show();
                    e.printStackTrace();
                }
                mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mediaPlayer) {
                        mediaPlayer.release();
                        mediaPlayer = null;
                        Log.d(TAG,"mediaPlayer released and nullified.");
                    }
                });
            }
        });

实际的音频文件存储在文件系统的 WhatsApp 文件夹中。我在我的应用程序中所做的是通过将其 URI 传递给 MediaPlayer object 来播放它。 我不明白为什么我只能在通过隐式意图获取 URI 后才能在我的应用程序中播放 WhatsApp 语音留言。

一旦我的应用程序关闭并且 re-opened URI 似乎指向 null。但不可能如此,因为 URI 指向的资源仍然存在。 有什么解决办法吗?

My application then receives the WhatsApp voice note URI via implicit intent and by using the URI the app can play the voice note when the user presses a button in my application's UI.

您可以临时访问由 Uri 标识的内容。

if I close (in task manager) my application and then I open it again I am not able anymore to play the voice note

您对内容的临时访问权限已失效。此外,当您的进程结束时,您将失去访问权限。

Uri 视为类似于经过身份验证的 Web 服务器的 HTTPS URL。一旦用户会话过期,那个URL就没用了。

Any ideas how to fix this?

当您可以访问内容时,将字节复制到您控制的某个文件中。

或者,让用户从其他应用再次向您的应用发送内容。