On Android 4.4.2 Environment.getExternalStorageDirectory().getPath() returns /storage/emulated/0 but this path does not exist on my Nexus5 Android 4.4.2. Environment.getExternalStorageDirectory().getPath() worked up until Android 4.4.2.
How can I get the /sdcard path on Android 4.4.2?
This path does not exist on my Nexus5 Android 4.4.2.
Yes, it does, for your process at runtime.
For example, this sample project downloads a file to Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS). If you log the location at runtime, when running it on a Nexus 5, it is reported as /storage/emulated/0/Download. And the download succeeds.
If you are looking for /storage/emulated/0 via DDMS or adb shell, you will not find it. For those tools, default external storage is /mnt/shell/emulated/0. Hence, the downloaded file from the above sample appears in the /mnt/shell/emulated/0/Download directory.
AFAIK, the difference is tied to providing separate external storage to secondary accounts.
The Storage Options documentation says to use Environment.getExternalStorageDirectory() (as you are already correctly using). This function is available on all versions of Android.
Are you seeing it return a path that isn't actually available on a 4.2 device?
Please note (from Environment.getExternalStorageDirectory()):
Applications should not directly use this top-level directory, in order to avoid polluting the user's root namespace. Any files that are private to the application should be placed in a directory returned by Context.getExternalFilesDir, which the system will take care of deleting if the application is uninstalled. Other shared files should be placed in one of the directories returned by getExternalStoragePublicDirectory(String).
Writing to this path requires the WRITE_EXTERNAL_STORAGE permission, and starting in read access requires the READ_EXTERNAL_STORAGE permission, which is automatically granted if you hold the write permission.
Starting in KITKAT, if your application only needs to store internal data, consider using getExternalFilesDir(String) or getExternalCacheDir(), which require no permissions to read or write.
Sometimes /storage/emulated/0 can be written to, but reads fail... so tests for "writability" are not sufficient. This is such an annoying problem, I have come up with an equally annoying but effective solution.
Hardcode "/mnt/sdcard" Yea, I said it.
Looks like someone else said it first ... storing android application data on SD Card
More joy... http://forums.bignerdranch.com/viewtopic.php?f=414&t=7407
Related
I am trying to use "Legacy Storage" for my app so that it can run on API29, as a temporary measure until I can understand the new storage model. I have set
requestLegacyExternalStorage="true"
in the manifest, but it still doesn't work. The Android docs say:
Test scoped storage
To enable scoped storage in your app, regardless
of your app's target SDK version and manifest flag values, enable the
following app compatibility flags:
DEFAULT_SCOPED_STORAGE (enabled for all apps by default)
FORCE_ENABLE_SCOPED_STORAGE (disabled for all apps by default)
To disable scoped storage and use the legacy storage model instead, unset both flags.
How do I unset the flags? Any other advice?
Back to the main question:
How do I unset the flags? Any other advice?
The flags you mention (DEFAULT_SCOPED_STORAGE and FORCE_ENABLE_SCOED_STORAGE) are for development purpouse only. You can set them in App Compatibility Changes panel on settings. To find this pannel, you have to unlock Developer options in settings and you can find there App Compatibility Changes.
For more information, see the documentation: How to identify which changes are enabled
At last (with more research on stackoverflow!) I have found the way around my problem, so I'll describe it here in case it is of help to anyone else.
THE APP WORKS OK UP TO API28:
My app downloads a file called myfile.txt and saves it in external memory, using DownloadManager. The directory where DownloadManager saves it is determined by
request.setDestinationInExternalPublicDir("","myfile.txt");
which returns the directory path/storage/emulated/0
When I read the file, I get the directory to read from using
String myPath = Environment.getExternalStorageDirectory();
which returns the same directory path. This works OK up to API28.
THE PROBLEM:
For API29, I put
android:requestLegacyExternalStorage="true"
in the <application....../> section of the manifest, but even then request.setDestinationInExternalPublicDir doesn't work - it crashes with a runtime error.
THE ANSWER THAT WORKED FOR ME:
Instead of request.setDestinationInExternalPublicDir I used
request.setDestinationInExternalFilesDir(this,"","myfile,txt");
which works OK in API29 and also the earlier versions. However, it returns a different directory path: /storage/emulated/0/Android/data/com.barney.aboutmyjourney/files (com.barney/aboutmyjourney is my app).
To get the directory path when reading the file, I therefore used
File myFile=this.getExternalFilesDir("myfile.txt");
String myPath=myFile.getParent();
which returns the path I want (/storage/emulated/0/Android/data/com.barney.aboutmyjourney/files).
This now works for me. Now just lots of slog modifying all my file IO. Perhaps I should just understand and used Scoped Storage instead!
1)Question
I have used installLocation in manifest
android:installLocation="preferExternal"
Correct me if i am wrong. android:installLocation="preferExternal" make your app install on external sdcard . If this is true then i should not be able to use myapplication when sdcard is removed . But however i can use myapplication even when i removed sdcard from my device
2)Question
what is the difference between sdcard0 and extsdcard on my device ?
even when i use in my manifest
android:installLocation="preferExternal"
all app files are stored on sdcard0 and it is accessible even when i have sdcard in my device . i have used below method to store files on sdcard
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
So in which condition my files will be stored on my sdcard ?
and how can i store files on extsdcard?
1) As stated in the docs:
If you declare "preferExternal", you request that your application be
installed on the external storage, but the system does not guarantee
that your application will be installed on the external storage.
Unmounting the external storage means that all running apps that were installed there will be immediately killed. If you are still able to use your app, I see 2 possible reasons: the system decided to install your app on the internal storage OR your device also features an emulated "external" storage and your app was installed there.
2)
what is the difference between sdcard0 and extsdcard on my device
It's common that sdcard0 refers to the device internal storage while extsdcard refers to the external storage that might be physical or emulated. However there's no reliable naming convention, it's up to the vendor.
Also note that "external" an Android basically means "a storage that the user can access".
A few further steps that might help:
use ADB Shell to examine your device's storage structure, with SD card attached and detached
verify your app's install location from the "Apps" settings menu
Log absolute paths of directories provided by different methods of the Environment class
Note: generally, you should never rely on assumptions of your app's install location since that might get you in trouble on some devices
I'm trying to create an android application that writes to a text file that can later be accessed once a button is pushed.
The past week i've tried a bunch of methods that people suggest to write to the internal storage, and sometimes it appears to work (using an outputwriter, and also a File class?), but i'm never able to locate the file on the Android device I test-run it on.
I'm rather new to development for Android, so all this is confusing to me.
Thanks
If by "internal storage" you mean what the Android SDK refers to as internal storage, this is not possible. Files that you create there are only accessible to your app, not by file managers on or off the device.
If by "internal storage", you mean what the Android SDK refers to as external storage, you need to:
Get a File pointing to a directory on external storage, such as calling getExternalFilesDir() on some Context, like your Activity
Create that directory if it does not exist
Create a File object pointing to the file you want to create, off of that directory
Use standard Java file I/O to write to the location identified by that File
Use MediaScannerConnection and its scanFile() method to tell Android "hey, I just put a file on external storage, please index it so it shows up in file managers"
Also:
Ideally, you do the disk I/O on a background thread, so you do not freeze the UI while that work is going on.
Depending on your minSdkVersion and where you choose to write the file, you may need the WRITE_EXTERNAL_STORAGE permission
Depending on your targetSdkVersion, you may need to ask for WRITE_EXTERNAL_STORAGE at runtime
You CAN access internal storage sometimes, but this depends on your phone.
You always can get data from internal memory for rooted phones (need root).
Files are in the folder /Android/data/
Some vendors allows you to run root shell on non-rooted phone through adb
(I saw this behaviour on Explay tabet) just run adb shell su to
test. Then you can copy your file from internal storage to public
with shell commands.
adb pull may also work in this case. (Again
vendor dependent)
There are many questions about this topic, but I cannot find any answers for my corrective example.
I'm using Samsung galaxy S5 run android 4.4, which is limited for storage
The official document said:
The WRITE_EXTERNAL_STORAGE permission must only grant write access to the primary external storage on a device. 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.
My application need to write files to Sdcard (Absolute path is /storage/extSdCard), so I write my app data to my app directory: /storage/extSdCard/Android/com.myapp.example/files but got permission denied exception. So I suspect the above statement:
except in their package-specific directories as allowed by synthesized
permissions
I think I cannot write to root directory /storage/extSdCard but still able to write my app data to my app package directory. Did I misunderstand something here?
p/s: I still able to write my app data to built-in storage: /storage/emulated/0/Android/data/com.myapp.example/files. I don't want to use getExternalFileDirs() because it always return built-in, not my sdcard directory.
If getExternalFilesDir(null) is returning somewhere different to /storage/extSdCard/Android/com.myapp.example/files, then I would think that is why it is giving you access permission errors. The only place on the SD card you can write to without permissions is the directory returned by getExternalFilesDir()
Since you say the directory returned by getExternalFilesDir(null) is not acceptable, I would suggest adding the WRITE_EXTERNAL_STORAGE permission to your manifest.
Your app specific directory should be /storage/extSdCard/Android/data/com.myapp.example/files and not /storage/extSdCard/Android/com.myapp.example/files
I'm writing an Android app which uses wi-fi, so I can't easily debug to emulator (no wi-fi support... ;-), so I go with my real device (a Samsung Galaxy S).
I would like to be able to read data files my app writes, to debug and test.
If I use, say:
new File(getFilesDir(), "myfile.xml");
I get my data file written to /data/data/MYPACKAGE/files/, but that directory is non accessible via adb (nor via Eclipse's DDMS).
My device is not rooted (and I'd prefer to avoid rooting it, if possible... ;-)
Where should I write my data file to?
It probably makes sense to put the files on the sdcard during development, formally you should call getExternalStorageDirectory() to find it and of course will need external storage permission.
Alternatively, you could give public access to your private files in the debug version; just don't forget to turn that off before you ship (as a certain Internet telephony company reportedly did). However, this will not make the private files browsable as the intervening directories are not, you would only be able to adb pull them via their exact path name.
A third choice would be to leave the data internal and private, but have a debug function to copy it over to the sdcard for analysis. You could even do this in a separate .apk establishing a shared user id with the first, meaning no changes at all to your application.
Simply use external storage!
You can write to your SDcard. You should use getExternalStorageDirectory() to get your SDcard's path. You will have to include the <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in your Manifest to do that.
The answer differs depending on your API level. Review the section in the documentation on external storage to get the answer for this.
http://developer.android.com/guide/topics/data/data-storage.html#filesExternal
For a somewhat generic answer, the sdcard directory that you should be storing files in is the directory returned from getExternalStorageDirectory() (which should be the root of your sdcard or possibly internal expanded storage as with my Captivate), with subdirectories of /Android/data/your.package.name/files
Oh yes, and as another poster mentioned, don't forget the WRITE_EXTERNAL_STORAGE permission in your manifest.