I'm running Marshmellow 6.0.1 on a Samsung SM-T350, and I'm trying to create a file on the external sd card (/mnt/media_rw/38E5-07B6).
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I ask for permission at runtime and the user grants them. I can double check this from the system preferences. In the code I check to make sure the user granted the permissions before continuing.
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], int[] grantResults) {
check against PackageManager.PERMISSION_GRANTED
}
When I try to write to the external SD card like this:
File exportFile = new File("/mnt/media_rw/38E5-07B6/junk.txt");
exportFile.createNewFile();
I get this:
java.io.IOException: open failed: EACCES (Permission denied)
at java.io.File.createNewFile(File.java:939)
at com.myapp.util.FileUtils.copyFile(FileUtils.java:42)
at com.myapp.service.ExportService$1.onClick(ExportService.java:47)
at android.view.View.performClick(View.java:5714)
at android.widget.TextView.performClick(TextView.java:10926)
at android.view.View$PerformClick.run(View.java:22589)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at java.io.File.createNewFile(File.java:932)
at com.myapp.util.FileUtils.copyFile(FileUtils.java:42)
at com.myapp.service.ExportService$1.onClick(ExportService.java:47)
at android.view.View.performClick(View.java:5714)
at android.widget.TextView.performClick(TextView.java:10926)
at android.view.View$PerformClick.run(View.java:22589)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
When I mount the device with adb shell I grab the pid and then dump /proc/{pid}/status and I can see my user does not have the AID_SDCARD_RW (1015) permission required to write to the SD card.
Groups: 3003 9997 50143
I also found this in /system/etc/permissions/permissions.xml
<permission name="android.permission.WRITE_MEDIA_STORAGE" >
<group gid="media_rw" />
<group gid="sdcard_rw" />
</permission>
there is no android.permission.WRITE_EXTERNAL_STORAGE, but there is permission:android.permission.WRITE_MEDIA_STORAGE
So after all that, my question is this: Has anyone run into this issue where the permission is in the manifest, and they've made the changes for the new permission model, and they still can't write to the SD card? How can I (without rooting, because it shouldn't be needed) get this to work?
First, there is a WRITE_EXTERNAL_STORAGE permission. Secondly, you're assuming that external storage is /mnt/media_rw/38E5-07B6. THere is no assured hard coded path for external storage. You should request the directory instead. Third, you won't have write permission to everywhere on the disk even if you add the permission- you're limited to common directories and your app's directory. Fourth, in newer versions of Android you have to request runtime permissions as well.
So you have a lot of problems to fix.
Related
First of all, this is not a duplicate of Error: open failed: ENOENT (No such file or directory) I have been through this.
Second: Please read the whole question.
Third: The error was not in my code. I had to remove all filters from logcat and see this error.
This is strange, I was developing this app and using it until yesterday. Right now when I launched it on my device from Android Studio I see this error. When I remove the code that handles firebase auth and firebase UI this the error goes away.
Also, I don't know if it is related but, I had to uninstall and reinstall Android Studio and all SDKs this morning, I am facing this error after that.
I have looked at almost every resource out there, on StackOverflow and multiple gists on GitHub but none of them helped.
Any help will be appreciated.
Thank in advance.
12-26 12:17:50.061 1207-1315/? E/KernelUidCpuTimeReader: Failed to read uid_cputime
java.io.FileNotFoundException: /proc/uid_cputime/show_uid_stat: open failed: ENOENT (No such file or directory)
at libcore.io.IoBridge.open(IoBridge.java:452)
at java.io.FileInputStream.<init>(FileInputStream.java:76)
at java.io.FileInputStream.<init>(FileInputStream.java:103)
at java.io.FileReader.<init>(FileReader.java:66)
at com.android.internal.os.KernelUidCpuTimeReader.readDelta(KernelUidCpuTimeReader.java:71)
at com.android.internal.os.BatteryStatsImpl.updateCpuTimeLocked(BatteryStatsImpl.java:8862)
at com.android.server.am.BatteryStatsService.updateExternalStats(BatteryStatsService.java:1685)
at com.android.server.am.BatteryStatsService$BatteryStatsHandler.handleMessage(BatteryStatsService.java:232)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:168)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:438)
at java.io.FileInputStream.<init>(FileInputStream.java:76)
at java.io.FileInputStream.<init>(FileInputStream.java:103)
at java.io.FileReader.<init>(FileReader.java:66)
at com.android.internal.os.KernelUidCpuTimeReader.readDelta(KernelUidCpuTimeReader.java:71)
at com.android.internal.os.BatteryStatsImpl.updateCpuTimeLocked(BatteryStatsImpl.java:8862)
at com.android.server.am.BatteryStatsService.updateExternalStats(BatteryStatsService.java:1685)
at com.android.server.am.BatteryStatsService$BatteryStatsHandler.handleMessage(BatteryStatsService.java:232)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:168)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
I have required permission to read and write in manifest too
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Found the solution. For the newbies out there. The error occurred because of unstable network.
I dont know why the FileNotFound Error was thrown though. But I tested the same thing on five different devices and finally, only this makes sense. When I moved to a better internet connection the error seemed to resolve itself.
Hope this saves someone else's time.
Following code works perfectly for Android 5, 6. But its crashing on Android 7.1
Intent intent1 = new Intent(Intent.ACTION_VIEW, Uri.parse(""));
intent1.setDataAndType(Uri.parse("file:///" + "sdcard/path/"+fName), "application/pdf");
startActivity(intent1);
Logcat:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.amey.newunipunebuddy, PID: 19574
android.os.FileUriExposedException: file:///sdcard/unipunebuddy_data/timetables/Timetable.pdf exposed beyond app through Intent.getData()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
at android.net.Uri.checkFileUriExposed(Uri.java:2346)
at android.content.Intent.prepareToLeaveProcess(Intent.java:9022)
at android.content.Intent.prepareToLeaveProcess(Intent.java:8983)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1519)
at android.app.Activity.startActivityForResult(Activity.java:4225)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:75)
at android.app.Activity.startActivityForResult(Activity.java:4183)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:856)
at android.app.Activity.startActivity(Activity.java:4522)
at android.app.Activity.startActivity(Activity.java:4490)
at com.amey.newunipunebuddy.Timetable$DownloadTask.onPostExecute(Timetable.java:498)
at com.amey.newunipunebuddy.Timetable$DownloadTask.onPostExecute(Timetable.java:415)
at android.os.AsyncTask.finish(AsyncTask.java:660)
at android.os.AsyncTask.-wrap1(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:677)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6145)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)
W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
Application terminated.
From Android 6.0 onwards you need to prompt user for permission to write to external storage (Manifest.permission.WRITE_EXTERNAL_STORAGE) - https://developer.android.com/training/permissions/requesting.html (am assuming, despite title, that it is writing to external storage given use of /sdcard ?)
Google documentation on external storage
You have to use getExternalFilesDir(). Take a look at the link for other options (pictures, music,...)
Also check your permissions, I don't remember when but now Android asks you to validate permissions at app startup. Maybe it is linked to the different systems. (5, 6,...)
FileUriExposedException
You expose the uri of your file to the outside world. Which Nougat does not allow you to do any more.
Use a file provider or file content provider to serve the file.
My create method looks like this:
#Override
public void create () {
batch = new SpriteBatch();
FileHandle file = Gdx.files.external("file.txt");
file.writeString("My god, it's full of stars", false);
}
I also included:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
The Exception I get is this:
02-13 14:45:51.858 12439-12466/com.snowdevs.tweetiebirds E/AndroidRuntime: FATAL EXCEPTION: GLThread 1120
Process: com.snowdevs.tweetiebirds, PID: 12439
com.badlogic.gdx.utils.GdxRuntimeException: Error writing file: file.txt (External)
at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:353)
at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339)
at com.snowdevs.tweetiebirds.TweetieBirdsGame.create(TweetieBirdsGame.java:22)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1519)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Caused by: com.badlogic.gdx.utils.GdxRuntimeException: Error writing file: file.txt (External)
at com.badlogic.gdx.files.FileHandle.writer(FileHandle.java:330)
at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:350)
at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339)
at com.snowdevs.tweetiebirds.TweetieBirdsGame.create(TweetieBirdsGame.java:22)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1519)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Caused by: java.io.FileNotFoundException: /storage/emulated/0/file.txt: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:452)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
at com.badlogic.gdx.files.FileHandle.writer(FileHandle.java:322)
at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:350)
at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339)
at com.snowdevs.tweetiebirds.TweetieBirdsGame.create(TweetieBirdsGame.java:22)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1519)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:438)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
at com.badlogic.gdx.files.FileHandle.writer(FileHandle.java:322)
at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:350)
at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339)
at com.snowdevs.tweetiebirds.TweetieBirdsGame.create(TweetieBirdsGame.java:22)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1519)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
I use a Nexus 5 with Android 6 Marshmallow for testing.
I searched and found that Android 6 uses Run Time Permissions, but the LibGDX developers say that it works even on Android 6. Is there a fix, either with or without Run Time Permissions?
I solved the problem by checking if the user has granted permission of external storage and request permision if not granted by using:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_REQUEST_CODE);
}
All of this is android-specific code and thus resides in the AndroidLauncher class.
I don't believe Nexus 5 has external storage (SD card).
Use this to test to find out -
boolean isExtAvailable = Gdx.files.isExternalStorageAvailable();
You can find more information here.
I had the same situation(Android 6, Nexus 4 No SD Card, libGDX 1.9.3):
I checked the external storage with
Gdx.files.isExternalStorageAvailable() // returns true
then get the fileHandle with
FileHandle file = Gdx.files.external("file.txt"); // no exception
then call
file.writeString("text",false); // throws GdxRuntimeException
So I checked on android side is the external storage really available with this code:
Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); // returns true
This also returned true. So it's not a libGDX issue, rather than an Android issue.
then I solved it with catching the exception and in that case writing the file to local storage.
I'm trying to set a ringtone with my app. For that I need to write a sound in the external memory of the phone. But every time I try to do it I get this error :
FATAL EXCEPTION: main
Process: com.mtoy.tiboxinshape, PID: 26322
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=26322, uid=10211 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:1620)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
at android.content.ContentResolver.insert(ContentResolver.java:1231)
at com.mtoy.tiboxinshape.SoundAdaptateur$2.onLongClick(SoundAdaptateur.java:142)
at android.view.View.performLongClick(View.java:5243)
at android.view.View$CheckForLongPress.run(View.java:21127)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
I don't understand why I still have this error as I have the following line in my manifest.xml :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Do you have an idea of what I can do to avoid having this error ?
Android changed permission accept in Latest 23 API level,In This Process Some permission that will be automatically granted at install time those are available for mention in Manifest ,Remaining Permission's Are Accept's in RunTime , Because So many bad guys trying to collect user's personal data through this security weakness So Android Change's to Runtime Permission
For More Information About Runtime Permission's And Process Of Runtime Permisson Accept
Fallow Below Link
Every Android Developer must know about new Android's Runtime Permission
Here is the solution I found :
https://developer.android.com/training/permissions/requesting.html
My app writes (and reads) cache files to the getExternalCacheDir() location. Before Android Lollipop (API 21) I've been using this permission with success:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />
The maxSdkVersion is there because this permission shouldn't be needed after API v18:
http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE
But on Android Lollipop (5.0) I'm getting an access permission like so (with my log output to show the actual path used):
11-19 13:01:59.257 4462-4541/com.murrayc.galaxyzoo.app E/android-galaxyzoo﹕ createCacheFile(): IOException for filename=/storage/emulated/0/Android/data/com.murrayc.galaxyzoo.app/cache/52
java.io.IOException: open failed: EACCES (Permission denied)
at java.io.File.createNewFile(File.java:941)
at com.murrayc.galaxyzoo.app.provider.ItemsContentProvider.createCacheFile(ItemsContentProvider.java:528)
I see this both in the emulator and on my Nexus 4. Has something changed, or was I doing something wrong all along? I just want to access my own app's cache.
Update: I now see this only on my device (Nexus 4 running the standard Android 5.1.1, which has even had a fresh Android reflash since I first had this problem). I no longer see this in the emulator - of course the system images have been updated several times.
We've seen same behaviour on API 21 (Lollipop) on a Nexus 5:
java.io.FileNotFoundException: /storage/emulated/0/Android/data/[package name]/cache/http/journal.tmp: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:456)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
at com.android.okhttp.internal.DiskLruCache.rebuildJournal(DiskLruCache.java:346)
at com.android.okhttp.internal.DiskLruCache.open(DiskLruCache.java:239)
at com.android.okhttp.HttpResponseCache.<init>(HttpResponseCache.java:140)
at android.net.http.HttpResponseCache.install(HttpResponseCache.java:199)
...
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1011)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4518)
at android.app.ActivityThread.access$1500(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1339)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Posix.java)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:442)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
at com.android.okhttp.internal.DiskLruCache.rebuildJournal(DiskLruCache.java:346)
at com.android.okhttp.internal.DiskLruCache.open(DiskLruCache.java:239)
at com.android.okhttp.HttpResponseCache.<init>(HttpResponseCache.java:140)
at android.net.http.HttpResponseCache.install(HttpResponseCache.java:199)
...
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1011)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4518)
at android.app.ActivityThread.access$1500(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1339)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Until Google push Android 5.0 to the AOSP we won't be able to work out if its a bug or deliberate (but undocumented) change, but I've raised this bug regardless:
https://code.google.com/p/android/issues/detail?id=81357
Adding WRITE_EXTERNAL_STORAGE permission prevents the above exception being thrown, but will require end user permission to upgrade existing apps. Since our app doesn't use this permission and we don't want to add it, we're falling back to using internal cache for all except KitKat devices.
As an aside, I found this an interesting background to the changes introduced in KitKat: http://www.doubleencore.com/2014/03/android-external-storage/