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

378 Views Asked by At

I am developing an application that manages WhatsApp voice notes. In WhatsApp UI the user can share a voice note and then select my application as the sharing option. 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.

The issue I am facing is the following: right after saving the voice note URI in my application I am able to play it, but if I close (in task manager) my application and then I open it again I am not able anymore to play the voice note. I am not making any copies of the voice note file: I just play it by passing its URI to the MediaPlayer class in my app. The error I get is:

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$2.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)

Here is how I get the the WhatsApp voice note URI from implicit intent (all this is done in the 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();
        }

And here is how I play the WhatsApp voice note in my application by pressing a button in its UI (the recordingData object contains the voice note URI and title saved in the previous 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.");
                    }
                });
            }
        });

The actual audio file is stored in the WhatsApp folder on file system. What I do in my app is playing it by passing its URI to a MediaPlayer object. I do not undestand why I am able to play the WhatsApp voice note in my application only right after getting the URI via implicit intent.

Once my application is closed and re-opened the URI seems to point at null. But it cannot be so, because the resource the URI points to still exists. Any ideas how to fix this?

1

There are 1 best solutions below

2
On BEST ANSWER

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.

You have temporary access to the content identified by the 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

Your temporary access to the content lapsed. Among other times, you will lose access rights when your process ends.

Consider the Uri to be akin to an HTTPS URL to an authenticated Web server. Once the user's session expires, that URL is useless.

Any ideas how to fix this?

While you have access to the content, make a copy of the bytes to some file that you control.

Or, have the user send the content again to your app from the other app.