Open file from external storage in Android - android

This could probably be a fast fix but currently I am unable to get this working...
I have an asynctask where I am parsing a XML file. If I place an XML file in the assets folder i can open and parse it no problem.
But if I try to open a XML file from external storage it fails.
Here is my asynctask:
private class async extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
while (!isCancelled()) {
try {
NodeList nList;
Node node;
InputStream is = getAssets().open("file.xml");
// this works
File is = new File("/storage/emulated/0/test.xml");
// this fails
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(is);
I am getting this error:
I/System.out: File path: /storage/emulated/0/test.xml
W/System.err: java.io.FileNotFoundException: /storage/emulated/0/test.xml (Permission denied)
These permissions are in my manifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Could someone tell me why I am getting this error?
Thanks!

I see your error message :
java.io.FileNotFoundException: /storage/emulated/0/test.xml
(Permission denied)
Remember that running on running Android 6.0 you must implement runtime permissions before you try to read or write the external storage.
setting this into your manifest.xml is not enough for devices with Android 6.0+:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

You should not hardcode the path. You can try this:
String path = Environment.getExternalStorageDirectory() + File.separator + MY_DIR_NAME + File.separator + "file.xml"

You should not try to access the filesystem using absolute paths.
To retrieve the path of the SD card you can use:
Environment.getExternalStorageDirectory()
So if you want to create a file named test.xml
new File(Environment.getExternalStorageDirectory(),"test.xml");

this is the method I use to open a pdf file from the folder that I created in the internal storage (sd card) of my phone.
but first you need to asd the user for the permission , go to manifest and write down :
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and in your main activity, you must implement runtime permissions before you try to read or write the external storage.
than use this method below don't forget to change the folder and file name
public void openPDF2(){
String path = Environment.getExternalStorageDirectory() + File.separator + "PDF folder 12"+ File.separator ;
File file = new File(path,fileName+".pdf");
String extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_NEW_TASK);
Uri uri = FileProvider.getUriForFile(GenerateQRActivity.this, GenerateQRActivity.this.getApplicationContext().getPackageName() + ".provider", file);
try {
intent.setDataAndType(uri, mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(intent, "choseFile"));
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG2, "openPDF2: the problem is : "+e.getMessage());
}
}

Related

Unable to write to external storage

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

FileNotFoundException:EACCES (Permission denied)

I get data from my service :
JSONObject userGuid = new JSONObject();
userGuid.put("userGuid", id);
Bitmap bitmap = null;
String response = HttpUtil.post(mService + "GetUser", userGuid.toString(), mCookie);
JSONObject result = new JSONObject(response).getJSONObject("User");
String temp = result.getJSONArray("UserImage").toString();
in received data, there is an Base64 image user and I got it and convert it to arryByte and then I convert it to InputStream :
byte[] tmp = Base64.decode(temp, Base64.DEFAULT);
InputStream is = new ByteArrayInputStream(tmp);
I want to write it to a File by outputStream :
OutputStream os = new FileOutputStream(f);
but I got this error:
java.io.FileNotFoundException: /storage/emulated/0/fcImages/581864034: open failed: EACCES (Permission denied)
In manifest I added these 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.INTERNET"/>
What is your Idea?
Edit
I create file in this way:
public class FileCache {
private File cacheDir;
public FileCache(Context context) {
if((Environment
.getExternalStorageState()).equals(Environment.MEDIA_MOUNTED)) {
cacheDir = new File(Environment.getExternalStorageDirectory(), "fcImages");
} else {
cacheDir = context.getCacheDir();
}
if(!cacheDir.mkdirs()) {
cacheDir.mkdirs();
}
}
public File getFile(String id) {
String filename = String.valueOf(id.hashCode());
File f = new File(cacheDir, filename);
return f;
}
There are 3 things that come in my mind to check:
uses-permission tag is inside manifest tag (and not application tag)
EACCESS may due to the fact that fcImages directory does not exist, or it is a file
permission for Android api 23 must be requested runtime
Source for (1) is this answer, while source for (3) is this answer
If you're writing the file to the application's internal storage. Try this:
Example 1:
java.io.File xmlFile = new java.io.File((getActivity()
.getApplicationContext().getFileStreamPath("FileName.xml")
.getPath()));
Also give the manifest permission correct way as below:
Example 2 :
<manifest>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
...
<application>
...
<activity>
...
</activity>
</application>
</manifest>

Unable to write image to Android SD Card (Permission Denied) [duplicate]

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();
}

Android how to create a folder on sd-card?

On my StartActivity, I want to create a Folder for the App on my SD-Card. Now first I set the permission at the manifest.xml like this
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Than I write some code at onCreate Method on my StartActivity like this
//Creat an AppFolder
String appPathString = Environment.getExternalStorageDirectory().getPath() + "/MyIdea";
try {
File appPath = new File(appPathString);
if (!appPath.exists()) {
appPath.mkdirs();
Toast.makeText(getApplicationContext(), "Folder created", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Log.e("saveToExternalStorage()", e.getMessage());
}
Now I run the app on my Nexus 5 the app start and the toast is showing. But if I go on my device, I can't find any folder which the name, that is beeing created. What is wrong ?
Try this code. It works for me . You need to point to AbsolutePath of storage
String state;
state = Environment.getExternalStorageState();
if ((Environment.MEDIA_MOUNTED).equals(state)) {
File root = Environment.getExternalStorageDirectory();
File Dir = new File(root.getAbsolutePath() + "/My Ideas");
if (!Dir.exists()) {
Dir.mkdir();
}
I'm just wondering, ( I know, we don't write anything) but please give a try to call appPath.flush(); and appPath.close();
and when I'm adding the WRITE permission, I also adding the READ, just to make sure !
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
After a short search i found, that I need special uses-permissions for android sdk 23. So I change my android
<uses-permission-sdk-23
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="23"
/>
Now it works fine. Thanks all for support!

Permission denied when writing into sdCard

I'm trying write a file into SDCard, but I am getting error in logcat:
01-24 09:03:33.647: W/System.err(3353): java.io.FileNotFoundException: /mnt/sdcard/fun/itisfun.txt: open failed: EACCES (Permission denied)
01-24 08:24:28.007: W/System.err(3353): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
01-24 09:03:33.756: W/System.err(3353):at libcore.io.Posix.open(Native Method)
And here my code to write into SDCard:
File root = null;
try {
// check for SDcard
root = Environment.getExternalStorageDirectory();
Log.i(TAG,"path.." +root.getAbsolutePath());
//check sdcard permission
if (root.canWrite()){
File fileDir = new File(root.getAbsolutePath()+"/fun/");
fileDir.mkdirs();
File file = new File(fileDir, "itisfun.txt");
FileWriter filewriter = new FileWriter(file);
BufferedWriter out = new BufferedWriter(filewriter);
out.write("I m enjoying......dude");
out.close();
}
} catch(...) {
...
}
Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<permission android:name="android.permission.INTERNET"></permission>
For writing to the Sdcard you need to give the permission in your manifest file
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You need to make sure you have the permission #Ram mentions, and the SD Card is mounted. You can check if it is mounted by:-
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
You should handle an unmounted card gracefully, but a common gotcha is if your phone is plugged in via the USB cable you may have it mounted via your desktop OS, which means it's not mounted by Android.
Thanks,
Ryan
Here's a bit of code I use,
public void yourMethod(){
File root = getDir(getApplicationContext());
try {
File fileDir = new File(root.getAbsolutePath()+"/fun/");
fileDir.mkdirs();
File file = new File(fileDir, "itisfun.txt");
FileWriter filewriter = new FileWriter(file);
BufferedWriter out = new BufferedWriter(filewriter);
out.write("I m enjoying......dude");
out.close();
} catch(...) {
...
}
}
public File getDir(Context context) {
if (android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED))
cacheDir = new File(
android.os.Environment.getExternalStorageDirectory(),
DIRECTORY_NAME);
else
cacheDir = context.getCacheDir();
return cacheDir;
}
If there is no external storage, it basically uses the phones internal cache (not good for large files)
Read this
If you're on 4.4, read here: http://www.androidcentral.com/kitkat-sdcard-changes Basically you can no longer read and write anywhere on the drive. You can only write to your private directory and directories you've become the owner of.
Check that your directory fun and the file itisfun.txt exists on the SDcard, if you want to make them by program, you have to add the permission:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
This permission allows the application to create file or directory, the permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> only allows the application to read and write the file that is already exist.
Make sure that your permission is outside of the <application> tag, usually before it.

Categories

Resources