I am trying to read a file from the SD card, but finding that I don't have read permissions.
I first get the public storage directory and list the files like so:
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File[] files = dir.listFiles();
Then I select one of the files and test to see if it is readable:
Log.d(TAG, files[0].canRead());
This always displays false, and I'm not sure why. I am able to write to the directory (in fact it's the file that I've written that I want to read), and I've tried variations of
files[0].setReadable(true);
and
dir.setReadable(true);
with no luck. I also have
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
included in my Manifest file and made sure my device wasn't connected to anything (as suggested here), but that wasn't it.
I am able to pull the file from the device and read it in a text editor. Any ideas as to what this could be?
Stats: Using API 12 on Samsung Galaxy tablet.
Related
Please read the whole post before down-voting and/or marking it as a duplicate!
I'm working on an app that reads files from within a specific folder on the user's phone - either from the SD card (if there's one) or from the built in storage. Yes, the "READ_EXTERNAL_STORAGE" is mentioned in the manifest and I'm also handling the permission popup for API>23.
I used to simply use
File folder = new File(Environment.getExternalStorageDirectory(), "myfolder");
to get the path of the folder that is stored in the built in storage (32gb for an S7) but now I want to get the path to the SD card. According to pretty much every result google gave me, "Environment.getExternalStorageDirectory()" is supposed to give you the path to the SD card but for me it doesn't (and never has).
I've tested the following with two different Samsung Galaxy S7s, both with Android 7.0, one with an SD card (+ the folder), the other without (+ the folder):
Log.d(tag, System.getenv("EXTERNAL_STORAGE"));
Log.d(tag, System.getenv("SECONDARY_STORAGE"));
Log.d(tag, ""+new File(System.getenv("EXTERNAL_STORAGE")+File.separator+"myfolder").isDirectory());
Log.e(tag, ""+new File(System.getenv("EXTERNAL_STORAGE")+File.separator+ordner).getAbsolutePath());
Log.d(tag, Environment.isExternalStorageRemovable());
Log.d(tag, Environment.getExternalStorageDirectory());
Log.d(tag, Environment.getExternalStorageDirectory().getAbsolutePath());
To my surprise both phones output the same infos:
/sdcard
null
true
/sdcard/myfolder
false
/storage/emulated/0
/storage/emulated/0
According to the file manager app ("My Files"), the built in storage is called "Internal Storage", which makes even less sense (I know the difference between Internal and External Storage in Android).
How do I get the path to the actual SD card (without hardcoding it)?
The only way I found is to semi-hardcode it:
File[] folders = myappcontext.getExternalCacheDirs();
gives you the path to the "cache" folders your app has access to (but that are deleted when you uninstall your app).
If the phone uses a removable SD card (that is currently mounted), the length of the array should be "2":
The path to the "cache" folder in the external (not removable) storage
The path to the "cache" folder on your SD card
They look something like this:
/storage/emulated/0/Android/data/com.mycompany.myapp/cache
/storage/xxxx-xxxx/Android/data/com.mycompany.myapp/cache
... where "x" is the number (id?) of your sd card. I've only been able to test it with 2 different SD cards and both had their own number.
Environment.getExternalStorageDirectory();
should also give you
/storage/emulated/0/
which is the non-hardcoding way of getting access to the external storage. ;)
If you create a new folder on the very first level of your SD card on your PC, its path will be:
/storage/xxxx-xxxx/myfolder
I also have to warn you: While you can read the "myfolder" folder, you can't write in it (will just throw an "Access Denied" exception with Android 7) because of the changes to the whole system that came with Kitkat. But that's a different problem I'm going to address in a new question.
you have to insert the following permission into your application's manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Add this -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
</manifest>
I tried writing to the sdcard folder using the emulator, with no success, although few weeks ago it worked. I get the sdcard folder, in my app, using Environment.getExternalStorageDirectory(). So I opened Android Device Monitor and I see no sdcard folder. I see a file with the name sdcard in my root folder and one in the mnt/ folder.
What is wrong?
The problem I am facing is not only that I do not see the sdcard but rather that I can not create a folder in it. I thought that if I solve the problem of not seeing it it will solve my main issue. Here is my code where isPresesnt returns false.
I also made sure that I have permission to write to the external storage.
It seems that the problem exists only with the emulator - I just tested it on my phone and it worked fine.
I also noticed that if I connect my phone to my computer while the emulator is opened, I do see the sdcard folder in the Android Device Monitor, but I do not know to which device it belongs to.
my code
File path = new File(Environment.getExternalStorageDirectory() + "/Documents");
boolean isPresent = true;
if (!path.exists()) {
isPresent = path.mkdir();
}
MANIFEST
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
permission code
perms.put(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
Actually we cannot see SD card folder on our emulator, but it still exist in mnt/sdcard like what you mention above. If you want to see it, just import an image to that folder and it with appear in Gallery with folder name sdcard.
Our game is bigger than 50Mb so we will be using an expansion file. This supposedly goes in the /Android/obb/package-name/ folder. To test it, we copy the file to that location using Windows file explorer.
To find the location, we call
String dir1 = Environment.getExternalStorageDirectory().getAbsolutePath();
However, on some device, it cant find the file
e.g. the GalaxyTab2.7.0 - the above call returns the location /storage/sdcard0, but it cant open the file /storage/sdcard0/Android/obb/package-name/base.tcf, even though we have copied it there, using Windows file explorer, to the Android/obb/package-name/ folder.
Now, maybe this "Android" folder is not the same one as the storage/sdcard one - maybe I CAN only put it on an sdcard ? But this same thing works on Nexus 10 and Sony Experia device, with the same paths, which don't have sd cards in them.
To get this working on other devices we had to put READ_EXTERNAL_STORAGE permissions in the manifest file. Maybe there is another permission ? Maybe once we actually download the expansion file, it will just work, but we can't test it otherwise.
Any ideas?
Thanks
Shaun Southern
I want to display image from a sd card into image view
Following code works in emulator but does not work on actual phone
File f = new File(imgPath);
if (f.exists()) {
imgView.setImageDrawable(Drawable.createFromPath("/mnt/sdcard/abc.jpg") ));
} else {
imgView.setImageResource( R.drawable.image_abasent);
}
abc.jpg is put in emulator sd card sdk folder using DDMS
I have also put abc.jpg directly on SD card through USB connection
I have added following permission too in the manifest file (but while installing from apk permission is not asked though)
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
Still on phone the desired image is not accessible.
What else is to be added or modified?
Please paste your manifest and also for accessing the SDCard you must use Environment.getExternalStorageDirectory() since /mnt/sdcard/ would be a hardcoded solution and may not work on some devices or android builds.
Edit: This was user error (sorry). I have answered it below.
I am developing an application that needs to access data on the sd card. When I run on my development device (an odroid with Android 2.1) I have root access and can construct the path using:
File sdcard = Environment.getExternalStorageDirectory();
String path = sdcard.getAbsolutePath() + File.separator + "mydata"
File data = new File(path);
File[] files = data.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String filename) {
return filename.toLowerCase().endsWith(".xyz");
}});
However, when I install this on a phone (2.1) where I do not have root access I get files == null. I assume this is because I do not have the right permissions to read the data from the sd card. I also get files == null when just trying to list files on /sdcard. So the same applies without my constructed path.
Also, this app is not intended to be distributed through the app store and is needs to use data copied separately to the sd card so this is a real use-case. It is too much data to put in res/raw (I have tried, it did not work).
I have also tried adding:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
to the manifest, even though I only want to read the sd card, but it did not help. I have not found a permission type for reading the storage.
There is probably a correct way to do this, but I haven't been able to find it. Any hints would be useful.
So I just spent half an hour to write this question and then I disconnected the phone and connected it whithout mounting it as a drive.
This was the problem. Now it works.
Sorry for wasting your time. :/