Reputation: 451
My Android app I'm building is having difficulty reading any file from inside my app's directories, including internal storage (using filesDir
).
Because it's internal storage, I shouldn't need any read/write permissions added to my manifest, but just to troubleshoot, I've added:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Additionally, I'm targeting devices from Marshmallow up, so I have successfully implemented Runtime permissions as well (in a different activity)... so permissions of any type should not be an issue.
Here's my Kotlin code, which upon the Activity being started, is supposed to start playing an MP3 file. (The fileName
is passed by the previous activity)
class RecordingManager : AppCompatActivity() {
var audioPlayer: MediaPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_recording_manager)
actionBar?.title = getString(R.string.recording_manager_actionbar_title)
supportActionBar?.title = getString(R.string.recording_manager_actionbar_title)
actionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val typedValue = TypedValue()
theme.resolveAttribute(R.attr.colorPrimary, typedValue, true)
val color = typedValue.data
supportActionBar?.setBackgroundDrawable(ColorDrawable(color))
val recordingsDir = File(filesDir, "recordings")
val fileName = intent.getStringExtra("fileName")
txtTitle.text = fileName
val audioFile = File(recordingsDir, fileName!!)
audioFile.setReadable(true)
audioFile.setWritable(true)
var mediaPlayer: MediaPlayer? = MediaPlayer.create(this, Uri.parse(audioFile.absolutePath))
mediaPlayer?.start() // no need to call prepare(); create() does that for you
}
Reading the Logcat, I can clearly see that the MP3 file exists, however, MediaPlayer is unable to read it:
2019-08-05 14:03:21.360 993-20629/? E/ClearFileSource: Failed to open file '/data/user/0/dev.oliverm.materialvoicerecorder/files/recordings/recording2019-08-0323:35:55.97500.mp3'. (Permission denied)
2019-08-05 14:03:21.360 993-20629/? E/GenericSource: Failed to create data source!
2019-08-05 14:03:21.357 993-993/? W/generic: type=1400 audit(0.0:566): avc: denied { read } for name="0" dev="sda45" ino=524291 scontext=u:r:mediaserver:s0 tcontext=u:object_r:system_data_file:s0 tclass=lnk_file permissive=0
2019-08-05 14:03:21.360 20593-20610/dev.oliverm.materialvoicerecorder E/MediaPlayerNative: error (1, -2147483648)
2019-08-05 14:03:21.361 20593-20593/dev.oliverm.materialvoicerecorder D/MediaPlayer: create failed:
This line right here:
W/generic: type=1400 audit(0.0:566): avc: denied { read } for name="0" dev="sda45" ino=524291
leads me to believe it's an SELinux issue.
I've tested this using multiple emulators & devices. I've used my own Pixel phone to test it, and I've used multiple emulators (M, N, O, P, Q beta) to no avail.
I have no idea why SELinux is not permitting my app to read files from inside my internal app's directory. Any help is greatly appreciated.
Upvotes: 2
Views: 1215
Reputation: 451
Update
I finally was able to do some more work, and the code that works for me is below:
audioPlayer = MediaPlayer()
audioPlayer?.setDataSource("file://"+audioFile.absoluteFile)
audioPlayer?.prepare()
audioPlayer?.start()
My best guess why this was happening is that audioPlayer
was created outside of the onCreate, and wasn't being set to MediaPlayer()
. Now that I've explicitly set audioPlayer
to MediaPlayer()
, it appears to be working for now.
This conversation may also be helpful for others, it helps troubleshoot playing local files with MediaPlayer
If anyone has a better explanation, please feel free to leave your answer below, and I will mark it as correct.
Upvotes: 0
Reputation: 93668
Uri.parse(audioFile.absolutePath)
audioFile.absolutePath
is not a URI, its a path. URIs would start with a scheme (file:). Paths start from a directory. So you're parsing a non URI as a URI, ending with an exception. Use Uri.fromFile(audioFile)
instead
Upvotes: 2