How to play audio file from raw/assets folder on t

2019-01-12 05:25发布

问题:

I know i can play an mp3 file in the media player like that:

Intent intent = new Intent();  
intent.setAction(android.content.Intent.ACTION_VIEW);  
File file = new File(YOUR_SONG_URI);  
intent.setDataAndType(Uri.fromFile(file), "audio/*");  
startActivity(intent);

Following this link I tried to get the URI like:

Uri audio = Uri.parse("android.resource://com.audio.test/"+R.raw.audio1);
Log.d(TAG,"uri:"+audio.toString());

and

Uri audio = Uri.parse("android.resource://com.audio.test/raw/audio");
Log.d(TAG,"uri:"+audio.toString());

Which outputs the expected result:

01-24 15:28:23.190: D/MyClass(30234): uri:android.resource://com.audio.test/2131034112
01-24 15:29:13.: D/MyClass(30234): uri:android.resource://com.audio.test/raw/audio1

But it doesn't work. The media player does not start. Any ideas why?

Update

I included a createChooser and instead of the expected list with players i get a "Unable to find application to perform this action" message. This is my exact code:

 public void playAudio(){
          Intent viewMediaIntent = new Intent();   
          viewMediaIntent.setAction(android.content.Intent.ACTION_VIEW);        
          Uri audio = Uri.parse("android.resource://com.audio.test/raw/"+R.raw.audio1);       
          Log.d(TAG,"uri:"+audio.toString());
          viewMediaIntent.setDataAndType(audio, "video/*");   
          viewMediaIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
          Log.d(TAG,"Starting");
          Intent i = Intent.createChooser(viewMediaIntent, "Play Music");
            mGap.startActivity(i);
          Log.d(TAG,"Started");
      }

Update 2

Thank you @CommonsWare for the explanation. Now I understand why it doesn't work. But the problem remains, can I achieve what I want? Get a Uri of a file stored in the raw/assets folder with a file:// scheme?

Update 3

I found a way to do it, although it's not the best it works. I have only 3 files and this doesn't delay the execution at all. I am copying the file from the res/raw to a local directory on the phone and getting the Uri from that file. Any suggestions on how to avoid that step are appreciated.

 public void copyFileToDir(String audioFile){
          File test = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC + "/" + audioFile + ".mp3");
          if (test.exists()){
              Toast.makeText(mGap, "Exists", Toast.LENGTH_SHORT).show();
              return;
          }
          File dest = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
          int i = mGap.getResources().getIdentifier("raw/"+audioFile, "string", mGap.getPackageName());
          InputStream in = mGap.getResources().openRawResource(i);
          // Used the File-constructor
          OutputStream out;
        try {
            out = new FileOutputStream(new File(dest, audioFile + ".mp3"));
              // Transfer bytes from in to out
              byte[] buf = new byte[1024];
              int len;
              try {
                  // A little more explicit
                  while ( (len = in.read(buf, 0, buf.length)) != -1){
                       out.write(buf, 0, len);
                  }
              } finally {
                  // Ensure the Streams are closed:
                  in.close();
                  out.close();
              }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 


      }


      public void playAudio(String audioFile){
          copyFileToDir(audioFile);
          File dest = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC + "/" + audioFile + ".mp3");
          Uri r = Uri.fromFile(dest);         
          Intent viewMediaIntent = new Intent();   
          viewMediaIntent.setAction(android.content.Intent.ACTION_VIEW);                                 
          viewMediaIntent.setDataAndType(r, "audio/*");   
          viewMediaIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);          
          Intent i = Intent.createChooser(viewMediaIntent, "Play Music");
            mGap.startActivity(i);

      }

      public void playVideo(String movieurl){
          Intent intentToPlayVideo = new Intent(Intent.ACTION_VIEW);
          intentToPlayVideo.setDataAndType(Uri.parse(movieurl), "video/*");
          Log.d(TAG,"Playing:" + movieurl);
          mGap.startActivity(intentToPlayVideo);
      }

回答1:

When you call startActivity(), you are trying to start an activity. The Intent you pass to startActivity() indicates what activity -- or selection out of a set of available activities -- you want to start. In your case, you are trying to view an android.resource:// Uri. This is not an http:// Uri, nor an https:// Uri, nor a file:// Uri.

Activities that advertise themselves as supporting operations like this have, in their <intent-filter> a statement of what Uri schemes they support. You are assuming that there is an app, on the user's device, that supports an android.resource:// scheme. Personally, I do not think that this is a safe assumption. http://, https://, and file:// should be safe, and content:// (for a ContentProvider) is fairly likely as well.

For example, the AOSP Music app does not support the android.resource scheme, based on its current manifest contents.



回答2:

Any reason why don't you use the MediaPlayer directly? You can pass the resource id directly

int resourceId = R.raw.your_media_resource;
MediaPlayer mediaPlayer = MediaPlayer.create( context, resourceId );
mediaPlayer.setOnCompletionListener( new OnCompletionListener()
{
    @Override
    public void onCompletion( MediaPlayer mp )
    {
        mp.release();
    }
} );
mediaPlayer.start();


回答3:

If you just need to set the sound URI on the Notification.Builder, use

 Uri.parse("android.resource://com.my.great.application/"
                        + R.raw.mysound);

where R.raw.mysound can be something like mysoud.ogg in the raw resources folder.

However I am not sure if MP3 is exactly supported. As these are just internal resources of your application, try to convert to OGG.



回答4:

It is not possible to use content from your RES folder outside of the App. The content is inside the App and not reachable from outside the App. If you want to make the content available you have to implement your own ContentProvider returning the data.

@CommonsWare is right. See http://iserveandroid.blogspot.nl/2011/01/how-to-access-resources-from-other.html