This question already has answers here:
Android permission doesn't work even if I have declared it
(11 answers)
Storage permission error in Marshmallow
(12 answers)
Closed 3 years ago.
I'm trying to write to a file in android but i keep getting this error:
java.io.FileNotFoundException: /storage/emulated/0/Notes/TestFile.txt (Permission denied)
Searching this site gives a simple resolution to this problem, which is to add WRITE_EXTERNAL_STORAGE to the app manifest file, but this isnt working for me. I keep getting the same error.
Code to write to file:
try {
File root = new File(Environment.getExternalStorageDirectory(), "Notes");
if (!root.exists()) {
root.mkdirs();
}
File gpxfile = new File(root, "TestFile.txt");
FileWriter writer = new FileWriter(gpxfile);
writer.append("Hello World");
writer.flush();
writer.close();
Toast.makeText(getApplicationContext(), "Saved", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
You have mentioned permission in AndroidManifest.xml but not yet granted it from the user. You need to grant WRITE_EXTERNAL_STORAGE permission through the user in your Android activity.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
Next time you launch the Activity, grant it the permission and then you can access external storage. Mind that this will give only write access, not read access.
If your targeted sdk is equal or greater to mashmallow version you must ask for runtime permissions
You can check it here
https://developer.android.com/training/permissions/requesting
Fixed it, i had to request permission using this code just above where i wrote to the file:
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
1);
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
The full code looks like this to write to a file in a button click function:
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
1);
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
try {
File root = new File(Environment.getExternalStorageDirectory(), "Notes");
if (!root.exists()) {
root.mkdirs();
}
File gpxfile = new File(root, "TestFile.txt");
FileWriter writer = new FileWriter(gpxfile);
writer.append("Hello World");
writer.flush();
writer.close();
Toast.makeText(getApplicationContext(), "Saved", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
Related
I am working on a photo editor app in which after editing my picture I save it into my local storage. It is working fine till android 9 but not on android 10. It shows exception of "No such file or directory found" in Android 10. After some research I found that getExternalFilesDir() is deprecated in android Q+. But I cannot find any proper way to do it in android 10. So please if anyone can provide a tutorial it would be really helpful.
I've added and granted uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in case of it was the issue, and it didn't solve anything.
This is my try (Used ParcelFileDescriptor):
private void fileAccessForAndroidQ(Uri fileUri){
try {
ParcelFileDescriptor parcelFileDescriptor = this.getContentResolver().openFileDescriptor(fileUri, "r", null);
InputStream inputStream = new FileInputStream(parcelFileDescriptor.getFileDescriptor());
Cursor returnCursor =
getContentResolver().query(fileUri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
fileName = returnCursor.getString(nameIndex);
file = new File(this.getFilesDir(), fileName);
OutputStream outputStream = new FileOutputStream(file);
IOUtils.copyStream(inputStream, outputStream);
}catch (Exception e){
Toast.makeText(this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
Any kind of help would be appreciated.
If you target Android 10 (API level 29) or higher, set the value of requestLegacyExternalStorage to true in your app's manifest file:
Documentation
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.appname"
android:installLocation="auto">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme.NoActionBar">
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Here is the best I could find:
https://developer.android.com/training/data-storage/app-specific#external
Basically, you now use app-specific directories for your files. For example:
#Nullable
File getAppSpecificAlbumStorageDir(Context context, String albumName) {
// Get the pictures directory that's inside the app-specific directory on
// external storage.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (file == null || !file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
I found this working for me. i am trying to list all file on ListView
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
} else {
File s = Environment.getExternalStorageDirectory();
Log.d("Path ",Arrays.toString(s.listFiles()));
File[] s1 = new File[s.listFiles().length];
for(int i=0;i<s.listFiles().length;i++){
s1[i]= new File(s.listFiles()[i].toString().replace("/storage/emulated/0/", ""));
}
ArrayAdapter<File> adapter = new ArrayAdapter<File>(this,R.layout.support_simple_spinner_dropdown_item,s1);
l1.setAdapter(adapter);
}
I have a problem with my app. I'm trying to read files from my SD card, but I cannot find any file. Files are added to main folder in my sdcard. I tried also create a new folder and read files from folder, but I have the same problem. Other files from SD card (not added by me for app purposes) are also not visible. I'm testing my app on real device Samsung Galaxy A3. Do you have any idea, where is a problem, or what I do wrong? Below is my code:
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".RecipeActivity"></activity>
</application>
Activity class:
File dir = Environment.getExternalStorageDirectory();
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "receip.txt");
if(file.exists()) // check if file exist
{
//Read text from file
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append("\n");
}
}
catch (IOException e) {
//You'll need to add proper error handling here
}
//Set the text
Log.d("File text:", text.toString() );
Toast.makeText(getApplicationContext(),"File Found", Toast.LENGTH_SHORT);
}
else
{
Log.d("Romek file:", "File not found" );
Toast.makeText(getApplicationContext(),"File not Found", Toast.LENGTH_SHORT);
}
I added also below methods to checked whether my SD card is writable and readable. All methods return true.
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
Log.d("Romek", "External Storage is writable");
return true;
}
Log.d("Romek", "External Storage is not writable");
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Log.d("Romek", "External Storage is readable");
return true;
}
Log.d("Romek", "External Storage is not readable");
return false;
}
I used runtime permission and I can read files, but I have another problem. How can I get a correct path to my files in external SDCARD. When I using a Environment.getExternalStorageDirectory().getAbsolutePath(), then I recived a path to external card in my phone, not SDCARD.
If your phone has android 6.0 or newer version, you have to ask run time permissions. More info you can get from https://developer.android.com/training/permissions/requesting.html
i need to save an image from camera on android.
i used the write external storage permission in manifest and i am using this code
File dir = new File(Environment.getExternalStorageDirectory(), "Test");
if (!dir.exists() || !dir.isDirectory())
dir.mkdirs();
String path = dir.getAbsolutePath();
Log.d(TAG, path); //log show the path
File file = new File(dir.getAbsolutePath() + "/Pic.jpg");
Log.d(TAG, file.getAbsolutePath()); //again path is shown here
outStream = new FileOutputStream(file);
outStream.write(bytes);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + bytes.length); //fail here
} catch (FileNotFoundException e) {
Log.d(TAG, "not done"); //error is here (this exception is thrown)
} catch (IOException e) {
Log.d(TAG, "not");
} finally { }
i also tried mkdir() instead of mkdirs() same result.
any idea what went wrong in the code?
thanks
For those not as experienced like me. I fought this issue, lost hair for some time. I am targeting api 21 (for compatibility sake) and it worked on lollipop but on marshmallow it would not create the directory. I did have the "uses" permission in the manifest but it still would not work. Apparently in Marshmallow when you install with Android studio it never asks you if you should give it permission it just quietly fails, like you denied it. You must go into Settings, apps, select your application and flip the permission switch on.
Some one like me who was trying in Android10. Please use below API in manifest:
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
Latest Update From Google:
After you update your app to target Android 11, the system ignores the requestLegacyExternalStorage flag.
Did you put
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
in your AndroidManifest? If you are using android M you must request user permission to write on sd, look here an example
IDIOT ME! i have used the Manifest Permission but when installed the app on phone i didnt grant permission for storage!... i understand a negative on this question... but i hope if someone else face the same..check your phone permission. sorry all for inconvenience.
you have created directory, not file. Create new file with following code
File file = new File(dir.getAbsolutePath() + "/Pic.jpg");
file.createNewFile()
if you are testing on android M, you should probably check Settings > App > Permission to see if permission to access storage is granted. This saved me.
if you already allowed R/W permission(Runtime Permission too) and still doesn't work add this below mentioned line in your AndroidManifest.xml
<application
........
........
android:requestLegacyExternalStorage="true">
Note: this must required if you'r targeting Android 10+
Starting from API 30 you can only write in your app-specific files
File dir = new File(context.getFilesDir(), "YOUR_DIR");
dir.mkdirs();
or in the external storage of your app Android/data
File dir = new File(myContext.getExternalFilesDir("FolderName"),"YOUR_DIR");
UPDATE
this answer provided another solution https://stackoverflow.com/a/65744517/8195076
UPDATE
another way is to grant this permission in manifest
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
like this answer https://stackoverflow.com/a/66968986/8195076
Try this. Provide runtime permission for marshmallow it is perfectly work in my Application code :
private String getFilename(String strFileName) {
String filepath = Environment.getExternalStorageDirectory().getPath();
File fileBase = new File(filepath, "Test");
if (!fileBase.exists()) {
fileBase.mkdirs();
}
return (file.getAbsolutePath() + "/" + strFileName + file_exts[currentFormat]);
}
new File(getFilename(edt.getText().toString().trim()))
outputFile = new File(apkStorage + "/" + downloadFileName );
//Create Output file in Main File
//Create New File if not present
if (!outputFile.exists()) {
isExternalStorageWritable();
outputFile.getParentFile().mkdirs();
outputFile.createNewFile();
Log.e(TAG, "File Created");
OutputStream fos = new FileOutputStream(outputFile);//Get OutputStream for NewFile Location
InputStream fis = c.getInputStream();//Get InputStream for connection
byte[] buffer = new byte[1024];//Set buffer type
int len1 = 0;//init length
while ((len1 = fis.read(buffer)) >0) {
fos.write(buffer, 0, len1);//Write new file
}
//Close all connection after doing task
fos.close();
fis.close();
I wrote this code for creating a file, but it is not working in android 11
when writing code for android API 29 and above use the following permission in your application manifest (AndroidManifest.xml)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
Adjust your code to read like the following
ActivityCompat.requestPermissions(this, new String[]
{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
PackageManager.PERMISSION_GRANTED);
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
file = new File(Environment.getExternalStorageDirectory().getPath(), "TestDirectory/Document/");
if (!file.exists()) {
try {
file.mkdirs();
} catch (Exception e) {
e.printStackTrace();
}
}
I need help with permission to save file in Android emulator ... I've had added
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera" android:required="true" />
in AndroidManifest.xml
My code for save file:
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(imageBitmap);
}
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/Img");
myDir.mkdirs();
long n = System.currentTimeMillis();
String fname = "IMG_" + n + ".jpeg";
file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out2 = new FileOutputStream(file);// here fire exception
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out2);
out2.flush();
out2.close();
} catch (Exception e) {
e.printStackTrace();
}
}
AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.denis.calculator">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".InfoActivity"></activity><!-- ATTENTION: This was auto-generated to add Google Play services to your project for
App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information. -->
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera" android:required="true" />
Any ideas pls?
Solution is downgrade from Nougat to KitKat! thanks for advices
Replace the below lines
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/Img");
With
File myDir = new File(Environment.getExternalStorageDirectory(),"Img");
Also remove the below lines from your code
if (file.exists())
file.delete();
Because the way you defining the file name will never gonna have the same file name. So validating the existence of file is irrelevant here.
You also have to ask writing permission with the user if your app is going to be used for Android 6.0 or above. Refer the link given below for details:
https://developer.android.com/training/permissions/requesting.html
You can use the solution defined in the library I've recently created this repository including a demo for Permission.
https://github.com/eeshan-jamal/DroidLibX
I will later make it available through Maven but for now you have to import the droidlibx library module in your project.
I am unable to create a directory in the external storage folder. I have created a new project, modified the manifest and added the code as seen below. Any help would be greatly appreciated. I updated my post to include that the code provided below does not work. The only thing I can think is the emulator is the problem. I am running Nexis API 32 x64.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.us.foobar"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
Source:
public void mkdir() throws Exception
{
String root = Environment.getExternalStorageDirectory().getAbsolutePath();
String dir = root + "/Foobar";
File file = new File(dir);
if (!file.exists())
{
if (!file.mkdirs())
{
throw new Exception("Unable to create application data directory.\r\n\r\nDirectory: " + dir);
}
}
}
I call the same function on onCreate and works fine. Look at my code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
test();
}
public void test() {
String root = Environment.getExternalStorageDirectory().getAbsolutePath();
String dir = root + "/Foobar";
File file = new File(dir);
if (!file.exists()) {
if (!file.mkdirs()) {
Log.e("Error", "Unable to create application data directory.\r\n\r\nDirectory: " + dir);
}
}
}
}
Using API 23 I had to request the permissions prior to writing to the file system as follows:
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_EXTERNAL_STORAGE
);