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();
}
}
Related
I'm trying to write data from the app's form into a .txt file but it won't work. I've put in an empty "record.txt" into the directory but nothing is written inside.
AndroidManifest.xml
...
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
MainActivity.java
String statement = textView.getText.toString();
File root = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
final File file = new File (root, "record.txt");
try {
FileWriter f = new FileWriter(file);
BufferedWriter buffwrite = new BufferedWriter(new FileWriter(file));
buffwrite.append(statement);
buffwrite.newLine();
buffwrite.flush();
buffwrite.close();
} catch (IOException e) {
e.printStackTrace();
}
Java doesn't automatically create a file when you just create reference you have to check if the files exist or not
if(file.exists()) { ... }. Else
file.createNewFile();
And make sure you have necessary permissions
You should ask for permission at runtime, WRITE_EXTERNAL_STORAGE is consider a dangerous permissions.
permissions overview
request permissions
I'm trying to generate a folder with my android application in my phone storage (not on the sdcard) but my mkdirs() is not working.
I have set the android.permission.WRITE_EXTERNAL_STORAGE in my manifest and use this basic code :
File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "/MyDirName");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("App", "failed to create directory");
}
}
but it doesn't work ... The mkdirs is always at false and the folder is not created.
I have tried everything and looked at all the topics about it but nothing is working and I don't know why.
if you target and compile sdk is higher then lolipop then please refer this link
or
File sourcePath = Environment.getExternalStorageDirectory();
File path = new File(sourcePath + "/" + Constants.DIR_NAME + "/");
path.mkdir();
If you you the emulator and the Device File Explorer of Android Studio, be sure that you right-click over a folder of the emulator and then click on 'synchronize' to update the files displayed. The Device File Explorer doesn't update by itself in real time.
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"/>
Then in your java file add the following lines of code
`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(), "MyDirName/");
if (!file.exists()) {
try {
file.mkdirs();
} catch (Exception e) {
e.printStackTrace();
}
}
`
The following code which consists of downloading a file from a server and save it in the storage works fine when the device has an internal storage.
But when I tried it with a device with no internal storage, only with external storage I get the following exception.
java.io.filenotfoundexception open failed eacces (permission denied)
public void downloadFile(String dlUrl, String dlName) {
int count;
HttpURLConnection con = null;
InputStream is = null;
FileOutputStream fos = null;
try {
URL url = new URL( dlUrl );
con = (HttpURLConnection) url.openConnection();
con.setDoInput(true);
con.connect();
is = url.openStream();
String dir = Environment.getExternalStorageDirectory() + Util.DL_DIRECTORY;
File file = new File( dir );
if( !file.exists() ){
file.mkdir();
}
Util.LOG_W(TAG, "Downloading: " + dlName + " ...");
fos = new FileOutputStream(file + "/" + dlName);
byte data[] = new byte[1024];
while( (count = is.read(data)) != -1 ){
fos.write(data, 0, count);
}
Util.LOG_D(TAG, dlName + " Download Complete!");
} catch (Exception e) {
Util.LOG_E(TAG, "DOWNLOAD ERROR = " + e.toString() );
bServiceDownloading = false;
}
finally{
try {
if( is != null)
is.close();
if( fos != null)
fos.close();
if( con != null)
con.disconnect();
} catch (Exception e) {
Util.LOG_E(TAG, "CLOSE ERROR = " + e.toString() );
}
}
}
And in manifest file I has the following:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Any suggestions what maybe the cause?
By the way Environment.getExternalStorageDirectory() returns /mnt/sdcard/ and file.mkdir() return false.
This attribute is "false" by default on apps targeting
Android 10 or higher.
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
This problem seems to be caused by several factors.
Check#1
First add this permission in your manifest file and check if it is working:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application>
...
</application>
.....
Check#2:
If you are running on an emulator, check the properties to see if it has an SD card.
Check#3:
Disable file transfer from device to computer. If Enabled, the app wont be able to access the SD card.
Check#4:
If still not working, try the following:
String dir = Environment.getExternalStorageDirectory().getAbsolutePath()
For me the following worked:
The problem is that getExternalStorageDirectory returns /mnt/sdcard whereas I need the actual path of external storage which is /mnt/sdcard-ext and there is no API in android that can get me the absolute path of removable sdcard.
My solution was to hard code the directory as follows:
String dir = "/mnt/sdcard-ext" ;
Since the application is intended to work only on one device, the above did the job.
If you encounter the same problem, use an file explorer application to find out the name of the external directory and hard code it.
Use READ_EXTERNAL_STORAGE permission to read data from the device.
Did you try it on emulator? Check the properties if it has an SD card. I had the same problem, and it was because the emulator did not have an SD card. Check if yours has or not.
I had the same problem, and i solved it by disabling file transfer from device to computer.
Because if u enable file transfer, sd card is not accessible to debugging application.
try
Environment.getExternalStorageDirectory().getAbsolutePath()
and don't forget to add
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Try using mkdirs instead of mkdir. If you are creating a directory path and parent doesn't exist then you should use mkdirs.
I suspect you are running Android 6.0 Marshmallow (API 23) or later. If this is the case, you must implement runtime permissions before you try to read/write external storage.
https://developer.android.com/training/permissions/requesting.html
i have done very silly mistake.
I have already put in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and also add permission in java file,as get permission pragmatically.
But there is mistake of Manifest.permission.READ_EXTERNAL_STORAGE.
Please use Manifest.permission.WRITE_EXTERNAL_STORAGE.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode);
I had the same problem. I used the write and read permission in the manifest correctly , yet it didn't work! The solution was very silly: unplug your phone from the PC before running the application. It seems when your phone is connected as "Mass storage" to the PC, the application cannot access the external storage.
First in your manifest file declare permissions :
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
now in header of application tag of manifest file :
android:requestLegacyExternalStorage="true"
now defines provider for your app in between tag of manifest file. as :
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_path" />
</provider>
now create a folder xml in res folder like this :
now create a xml file provider_path.xml and copy below code in it :
<?xml version="1.0" encoding="utf-8"?>
<path>
<external-path
name="external_files"
path="." />
now in your activity :
String filename = null ;
URL url = null;
try {
url = new URL("http://websitename.com/sample.pdf");
filename = url.getPath();
filename = filename.substring(filename.lastIndexOf('/')+1);
} catch (MalformedURLException e) {
e.printStackTrace();
}
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"/"+filename);
if(file.exists()){
Uri uri = FileProvider.getUriForFile(context, "com.example.www"+".provider",file);
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(uri, "application/pdf");
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(i);
}
else {
//download file here
new AlertDialog.Builder(context)
.setTitle("Information")
.setMessage("Do you want to download this file ?")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url+""));
request.setTitle(filename);
request.setMimeType("application/pdf");
request.allowScanningByMediaScanner();
request.setAllowedOverMetered(true);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
DownloadManager downloadManager = (DownloadManager)context.getSystemService(DOWNLOAD_SERVICE);
downloadManager.enqueue(request);
}
}).show();
}
All I want is to be able to write a log/exception report for my app inside a very specific folder (related to my app) in order to understand failures and exceptions, so this is the code I'm using:
File logFile = new File(Environment.getExternalStorageDirectory() + File.separator + "/appname/log.txt");
if (!logFile.exists()) {
try {
if (logFile.getParentFile().mkdir()) {
if (!logFile.createNewFile())
showPopup(context.getString(R.string.app_name), "error creating log file");
}
} catch (IOException e) {
e.printStackTrace();
}
}
try {
BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
buf.append(text);
buf.newLine();
buf.flush();
buf.close();
} catch (IOException e) {
e.printStackTrace();
}
For the above to work, I have to add the following permissions: android.permission.WRITE_EXTERNAL_STORAGE but when the user reads it, it says both reading and writing the external storage and understandably, this is scaring away the user. Is there a better way to log my app's behavior and use a less scary permission for that?
First, switch from:
File logFile = new File(Environment.getExternalStorageDirectory() + File.separator + "/appname/log.txt");
to:
File logFile = new File(context.getExternalFilesDir(), "log.txt");
Not only does this avoid manual string concatenation when creating your path, and not only does this stop cluttering up the user's external storage with random app-specific directories, but it now means that you can have:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
to eliminate WRITE_EXTERNAL_STORAGE on API Level 19+.
Beyond that, try raising your targetSdkVersion to 4 or higher. Quoting the docs for READ_EXTERNAL_STORAGE:
Note: If both your minSdkVersion and targetSdkVersion values are set to 3 or lower, the system implicitly grants your app this permission. If you don't need this permission, be sure your targetSdkVersion is 4 or higher.
Try this:
File storageDir = new File(Environment.getExternalStorageDirectory(), "your folder name");
storageDir.mkdir();
Put this code to your manifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
While writing file in External SD card I am getting an error EACCESS permission denied. I have set the permission
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
But the when I read the file I am successfully able to read it but not able to write the file. The code that I am using for writing the file in SD card is:
String path="mnt/extsd/Test";
try{
File myFile = new File(path, "Hello.txt"); //device.txt
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(txtData.getText());
myOutWriter.close();
fOut.close();
Toast.makeText(getBaseContext(),"Done writing SD "+myFile.getPath(),Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_SHORT).show();
System.out.println("Hello"+e.getMessage());
}
}
The path for the external storage card is mnt/extsd/. Thats why I am not able to use Environment.getExternalStorageDirectory().getAbsolutePath() which is giving me a path mnt/sdcard and this path is for internal storage path in my tablet. Please suggest why this is so n how can I resolve this
As I remember Android got a partial multi-storage support since Honeycomb, and the primary storage (the one you get from Environment.getExternalStorageDirectory, usually part of the internal eMMC card) is still protected by the permission WRITE_EXTERNAL_STORAGE, but the secondary storages (like the real removable SD card) are protected by a new permission android.permission.WRITE_MEDIA_STORAGE, and the protection level is signatureOrSystem, see also the discussion in this article.
If this is the case then it seems impossible for an normal app to write anything to the real sdcard without a platform signature...
From API level 19, Google has added API.
Context.getExternalFilesDirs()
Context.getExternalCacheDirs()
Context.getObbDirs()
Apps must not be allowed to write to secondary external storage devices, except in their package-specific directories as allowed by synthesized permissions. Restricting writes in this way ensures the system can clean up files when applications are uninstalled.
Following is approach to get application specific directory on external SD card with absolute paths.
Context _context = this.getApplicationContext();
File fileList2[] = _context.getExternalFilesDirs(Environment.DIRECTORY_DOWNLOADS);
if(fileList2.length == 1) {
Log.d(TAG, "external device is not mounted.");
return;
} else {
Log.d(TAG, "external device is mounted.");
File extFile = fileList2[1];
String absPath = extFile.getAbsolutePath();
Log.d(TAG, "external device download : "+absPath);
appPath = absPath.split("Download")[0];
Log.d(TAG, "external device app path: "+appPath);
File file = new File(appPath, "DemoFile.png");
try {
// Very simple code to copy a picture from the application's
// resource into the external file. Note that this code does
// no error checking, and assumes the picture is small (does not
// try to copy it in chunks). Note that if external storage is
// not currently mounted this will silently fail.
InputStream is = getResources().openRawResource(R.drawable.ic_launcher);
Log.d(TAG, "file bytes : "+is.available());
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
} catch (IOException e) {
// Unable to create file, likely because external storage is
// not currently mounted.
Log.d("ExternalStorage", "Error writing " + file, e);
}
}
Log output from above looks like:
context.getExternalFilesDirs() : /storage/extSdCard/Android/data/com.example.remote.services/files/Download
external device is mounted.
external device download : /storage/extSdCard/Android/data/com.example.remote.services/files/Download
external device app path: /storage/extSdCard/Android/data/com.example.remote.services/files/
I solved this problem by removing the android:maxSdkVersion="18" in uses-permission
in manifest file.
I.e. use this:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
instead of:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
Check if user is having external storage permission or not. If not then use cache dir for saving the file.
final boolean extStoragePermission = ContextCompat.checkSelfPermission(
context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED;
if (extStoragePermission &&
Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) {
parentFile = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
}
else{
parentFile = new File(context.getCacheDir(), Environment.DIRECTORY_PICTURES);
}