I'm trying to share an MP3 file from my android's internal files (the root of which is getFilesDir()
) to another application using an ACTION_VIEW
implicit intent. The MP3 file was originally stored in my app's /raw
folder, but I copied it over to my app's internal files.
I have verified that the file exists using file.exists()
. When I use a FileProvider to construct a content URI for the file and use that content URI as the data in an implicit intent, however, I get FileNotFoundException: open failed: ENOTDIR
when I try to start the implicit intent.
I have tried changing the FileProvider's authority, and I've looked into Android's specifications for sharing a media file using intents and ensured that my implicit intent conforms to the standards.
Here is the output from the log window when the error occurs:
23349-23349/? D/MusicLifecycle: com.google.android.music.ui.playback.AudioPreviewActivity generated event: Activity created
23349-23349/? W/MediaPlayer: Couldn't open content://com.example.selfcareapplication.fileprovider/meditation-files/breathing-meditation.mp3: java.io.FileNotFoundException: open failed: ENOTDIR (Not a directory)
1844-2784/? W/ActivityManager: Permission Denial: opening provider android.support.v4.content.FileProvider from (null) (pid=1694, uid=1013) that is not exported from UID 10099
1694-2151/? E/MediaPlayerService: Couldn't open fd for content://com.example.selfcareapplication.fileprovider/meditation-files/breathing-meditation.mp3
23349-23349/? E/MediaPlayerNative: Unable to create media player
23349-23349/? D/AudioPreviewActivity: Failed to open file: java.io.IOException: setDataSource failed.: status=0x80000000
Here is the code I have to get the file, create the FileProvider, and start the intent:
Intent openMeditationFileIntent = new Intent(Intent.ACTION_VIEW);
File testFile = new File(this.getFilesDir(), "meditation-files\\breathing-meditation.mp3");
//check if file was written to internal memory. It prints "FILE WAS OUTPUT!"
if(testFile.exists()) {
Log.d(LOG_TAG, "FILE WAS OUTPUT!");
} else {
Log.d(LOG_TAG, "FILE WAS NOT OUTPUT!!!");
}
//create content URI using FileProvider and the testFile
Uri meditationFileContentUri = FileProvider.getUriForFile(this.getApplicationContext(), "com.example.selfcareapplication.fileprovider", testFile);
openMeditationFileIntent.setDataAndType(meditationFileContentUri, "audio/*");
openMeditationFileIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//try to open implicit intent using content URI as its data:
if(openMeditationFileIntent.resolveActivity(getPackageManager()) != null) {
startActivity(openMeditationFileIntent);
} else {
Log.d(LOG_TAG, "Could not resolve activity");
}
This is my manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.selfcareapplication.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
And this is my file_paths.xml file:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="meditation-files" path="meditation-files/"/>
</paths>
EDIT:
I was able to get this working! Per the suggestion from @CommonsWare, I changed the MIME Type to '"audio/mpeg"', which is the MIME type for MP3s.
I also took out the hypens in the path names. Doing this seemed to cause that prevented MP3 file from being properly written to 'getFilesDir() + "meditationPaths"' since checking 'file.exists()' on the MP3's path would return false. Changing the '\'s in the paths to '/'s fixed this problem.
That said, when I did some further testing later, I found that both '\' and '/' allowed the MP3 to be written properly... so I am not absolutely certain what went wrong my first time through. I would just recommend using 'File.separator' to ensure you automatically use the correct separator for the environment your program is running in.
Here is the final code to get the file, create the FileProvider, and start the intent:
Intent openMeditationFileIntent = new Intent(Intent.ACTION_VIEW);
File testFile = new File(this.getFilesDir(), "meditationFiles" + Path.separator + "breathingMeditation.mp3");
//check if file was written to internal memory. It prints "FILE WAS OUTPUT!"
if(testFile.exists()) {
Log.d(LOG_TAG, "FILE WAS OUTPUT!");
} else {
Log.d(LOG_TAG, "FILE WAS NOT OUTPUT!!!");
}
//create content URI using FileProvider and the testFile
Uri meditationFileContentUri = FileProvider.getUriForFile(this.getApplicationContext(), "com.example.selfcareapplication.fileprovider", testFile);
openMeditationFileIntent.setDataAndType(meditationFileContentUri, "audio/mpeg");
openMeditationFileIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//try to open implicit intent using content URI as its data:
if(openMeditationFileIntent.resolveActivity(getPackageManager()) != null) {
startActivity(openMeditationFileIntent);
} else {
Log.d(LOG_TAG, "Could not resolve activity");
}
I also had to change my file-paths.xml file to reflect the change in the folder name:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="meditationFiles" path ="meditationFiles"/>
</paths>
User contributions licensed under CC BY-SA 3.0