getExternalStorageDirectory not working - java

I am trying to save a file to my SDcard on my Samsung Galaxy Nexus running 4.2.2. From my app I am using
Environment.getExternalStorageDirectory()
But it returns
/storage/emulated/0/
Which is not where my SDcard information is located to. Is there any working method I can use to get the correct path to my SDcard?

Actually, that is the correct location.
From android 4,2 onwards, Google introduced multiple user accounts. Every user has his/her own external storage, which has the user ID in the path to maintain uniqueness.
The primary (default) user's ID is 0. So you get /storage/emulated/0/ as the path to the external storage.

I just learned this is the Jelly Bean's way of dealing with the lack of android.permission.WRITE_EXTERNAL_STORAGE permission. I haven't seen such a behavior with older versions of Android.
Just add this line to your AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Environment.getExternalStorageDirectory() refers to whatever the device manufacturer considered to be "external storage". I can be something else than the SD-card.
You may get more informations here: Find an external SD card location

I think its because of using genymotion emulator,
the path is true and in Eclipse it locates at
File Explorer - > mnt - > shell - > emulated -> 0
hope it helps ;)

Sure? Where do you think your sdcard is mounted? Try doing ls -l on that directory – it's probably a symlink to /storage/emulated/0/.

I had somehow lost my symlink at /storage/emulated/0, causing a similar failure. What I did was use the camera app to take a picture. I observed that the pictures details said it was within /storage/emulated/0, though that directory did not exist from the file explorer. Then I rebooted the phone. After reboot the link existed.

Try to use getExternalFilesDir() or getExternalStoragePublicDirectory().
From Android 4.2 documentation

Related

android studio with Java compiler error: string too large to encode using UTF-8 written instead as 'STRING_TOO_LARGE'

When I clean the android project in android studio, the error happen, I have backed to previous commit or different branch, which works find couple days ago, but has this error now. I have checked this question and there is not large image or strings added for my project. STRING_TOO_LARGE String in Kothlin
I had encountered the same and fixed by clear the build cache .
I was stuck on this problem and read through this topic and no one provided a future solution. I did NOT want to revert back my Gradle. Therefore, here is the link to the updated dependencies https://github.com/stripe/stripe-android. Look for the "Android Studio (or Gradle)" section and you should see this "implementation 'com.stripe:stripe-android:8.1.0'" also you might need to add "-keep class com.stripe.android.** { *; }" if you are enabling minification in your build.gradle file.
Overall Stripe has stopped updating their own "Stripe docs" which can be found here. To give them credit their docs are helpful and should be read at least once, but be mindful that most of the docs are out date when I wrote this...
Hope this helps :)
You can use AAPT (from the android sdk/build-tools) to examine the APK and look for the offending string with the following command line (Linux):
// Linux/Mac
./aapt dump --values resources MyAppName-regular-debug.apk | grep -B 1 'STRING_TOO_LARGE'
// Windows
aapt dump --values resources MyAppName-regular-debug.apk | grep -B 1 'STRING_TOO_LARGE'
Which should point you to the culprit. In my case it was:
resource 0x7f0f015a com.example.app:string/eula: t=0x03 d=0x00000f10 (s=0x0008 r=0x00)
(string8) "STRING_TOO_LARGE"
For the time being, you can downgrade Gradle version to resolve this issue.
Use gradle 3.1 version like 3.1.3 below.
classpath 'com.android.tools.build:gradle:3.1.3'
It happens that I had an SVG too long (90Kb). So I've opened de SVG in Adobe illustrator, simplified the path to a significant number of vector less so the new icon weight 3Kb and, finally, imported again in Android Studio.
You can have a look at your Project in Android Studio and watch if your SVG drawables are larger than needed for an icon.
just use <?xml version="1.0" encoding="utf-8"?> before in your drawable file.
Example:
<?xml version="1.0" encoding="utf-8"?>
<vector
android:autoMirrored="true"
android:height="24dp"
android:viewportHeight="490.282"
android:viewportWidth="490.282"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="#fff"
android:pathData="M0.043,245.197c0.6,10.1 7.3,18.6 17,21.5l179.6,54.3l6.6,123.8c0.3,4.9 3.6,9.2 8.3,10.8c1.3,0.5 2.7,0.7 4,0.7c3.5,0 6.8,-1.4 9.2,-4.1l63.5,-70.3l90,62.3c4,2.8 8.7,4.3 13.6,4.3c11.3,0 21.1,-8 23.5,-19.2l74.7,-380.7c0.9,-4.4 -0.8,-9 -4.2,-11.8c-3.5,-2.9 -8.2,-3.6 -12.4,-1.9l-459,186.8C5.143,225.897 -0.557,235.097 0.043,245.197zM226.043,414.097l-4.1,-78.1l46,31.8L226.043,414.097zM391.443,423.597l-163.8,-113.4l229.7,-222.2L391.443,423.597zM432.143,78.197l-227.1,219.7l-179.4,-54.2L432.143,78.197z"/>
</vector>
None of the above solutions worked for me. What ended up being the cause of the problem was, as it states, a String that was too large. Specifically, in my arrays.xml file under the values directory, I had some SVG arrays that were used within my app and commenting them out solved the issue.
If you know for certain you have some longer Strings somewhere in your resource directories (/res), check for any large Strings that may be lurking.
Also, this solution may help others but was not linked to in this thread.
I've been hunting for the source of STRING_TOO_LARGE errors in our build for a long time and none of these solutions worked. The reason none of them worked was that I had progaurd turned on in debug builds so when the string was replaced it didn't end up in the apk. When i disabled progaurd for debug builds, built the apk and then decompiled with apktool as suggested elsewhere
java -jar apktool_2.4.1.jar d debug.apk
and found the xml file that was in another library but progaurd stripped out before:
grep -r "STRING_TOO_LARGE" ./debug
Hope that helps someone
I found an SVG file that had a very long pathData. I commented it out and the error went away. That very same vector (when called) at runtime would cause a crash (before it was commented out).
clear your gradle in windows
gradlew cleanBuildCache
in mac
./gradlew cleanBuildCache
then building you apk if your project has problem it will be show you in the 'Messages'
view. location your problem and fix it. run agent.
The issue is caused by the AAPT/AAPT2 (Android Asset Packaging Tool) which processes your app’s resources and replaces them with the STRING_TOO_LARGE value when it finds a large string.
Find out for which one cause this problem.
To find out follow below steps:
A. Best Way:
Generate build APK
Decompile APK using any decompiler and download it.
Open it in any editor(Ex. VS Code)
Then search "STRING_TOO_LARGE" text globally and you will find affected files.
B. Another Way
The simplest way to find out, Builds an APK and analyze it. Select Build > Build Bundle(s) / APK(s) > Build APK(s). When the build completes, a confirmation notification appears, providing a link to the APK file and a link to analyze it in the APK Analyzer.
If you take a look into the the vector drawable file affected by this issue, you will find something like this:
I found this solution from Here
Just use gradlew cleanBuildCache in your Android studio terminal
In my case, i deleted a view from xml but forgot to remove its references in my kotlin code. Make sure to check this before doing anything fancy.
I found the answer from a duplicate question for Kotlin from here
Add <?xml version="1.0" encoding="utf-8"?> to the top of any resource .xml file that is missing it. (check your layout xml files, specially)
For me "gradlew cleanBuildCache" did not work, and running aapt dump --values resources MyAppName-regular-debug.apk | grep -B 1 'STRING_TOO_LARGE' did nothing either...
I ended up just deleting all my vector images since they were all pretty large and that fixed my build.. So I guess I'll have to add those back in a way that does not throw the error again..
In my case, I had renamed the package and the output-metadata.json contained the old package name. Renamed the package name there, and it was fixed.
In my case, the problem was due to the following lines in the manifest:
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="#string/app_name"/>
Once I deleted them, the build went fine.
In my case I declared a string variable in xml using data binding without assigning a value to it. by setting value to variable problem resolved
Windows 10 Solution
Finding the file with the error: use a online decompiler if it's not a problem is some one else sees your code. Download .zip file. Open up notepad++ search -> Find in files -> STRING_TOO_LARGE -> Find all.
If the problem file is a vector asset:
Vikasdeep Singh has a great solution: avocado. Avocado will make the vector file smaller.
I had this problem and clearing the cache or updating the Gradle plugin version was not a solution
To solve the problem I had to change the name of the longest XML file to make it a bit shorter, and right after doing that the problem was solved.
In my case I use Invalidate cache and restore
go to file/Invalidate cache and restore
instead of this
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
Replaced it with this in the gradle.properties
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=STRING_TOO_LARGE

How can I find the main directory on my Android app?

I would like my Android app to find the main directory on my tablet's internal storage. The furthest I can get is reading the contents of the "user.dir", but that seems to be the root directory and the listing there is too immense to find what would be considered the DOS equivalent of C:\
I am listing the code snippet I use to read the directory to show I can access the internal storage, but somewhere I'm not able to do it correctly.
workingDir = System.getProperty("user.dir");
File f = new File(workingDir);
File[] files = f.listFiles();
for (File inFile : files) {
if (inFile.isDirectory()) {
Thanks
in fact, if you were to open the "My Files" explorer that comes with Android the top option on my tablet is called Internal Storage, and it lists all the viewable folders from within
That is what the Android SDK refers to as external storage. You can find the root of that via Environment.getExternalStorageDirectory(). However:
Don't put things directly there, just as well-written Windows programs haven't put stuff in C: for the past couple of decades. Use Environment.getExternalStoragePublicDirectory() for standard locations (e.g., downloads directory), or use getExternalFilesDir() on Context for a location that is unique to your app.
You need to hold READ_EXTERNAL_STORAGE and/or WRITE_EXTERNAL_STORAGE permissions, including setting up runtime permissions for use on Android 6.0+ devices.
You can try to give a look at the android Environment documentation and access internal storage root/main directory with this Environment.getRootDirectory()

Using DownloadManager to download into new folder on phones storage

Im using a download manager which downloads a file into a new folder on the phone storage. Here is the code im using:
DownloadManager.Request downloadSample = new DownloadManager.Request(Uri.parse(urlSample));
downloadSample.allowScanningByMediaScanner();
downloadSample.setDestinationInExternalPublicDir("/Samples/"+previewName, "sample.ttf");
downloadSample.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(downloadSample);
This works perfectly fine on many of the devices Ive tested on, but a few devices force close the app with the following error in the log:
E/AndroidRuntime(29918): java.lang.IllegalStateException: Unable to create directory: /storage/sdcard0/Samples/Helvetica
E/AndroidRuntime(29918): at android.app.DownloadManager$Request.setDestinationInExternalPublicDir(DownloadManager.java:507)
Its annoying that it works fine on some but not at all on other devices. Does anyone know why this is happening?
The documentation for setDestinationInExternalPublicDir(String dirType, String subPath) says that dirType can take only specified values.
Here dirType can only be the android defined directories for example:
Environment.DIRECTORY_DOWNLOADS
etc.
you can find all the possible values of dirType at: http://developer.android.com/reference/android/os/Environment.html#getExternalStoragePublicDirectory(java.lang.String)
So the proper way to use this method is:
setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, subPath)
Also note that this will make the folder in Downloads folder on phone storage. Download manager will not allow you to make a folder in the default directory of phone storage.
This will not give you IllegalStateException for creating directory.

Deleted APK Expansion file still gives NO_DOWNLOAD_REQUIRED

[UPDATE]
I uninstalled and then installed again the application on the test device, and it started working fine.
I'm implementing APK Expansion file support (but no XAPK ZIP library support).
The documentation implies that if a required APK Expansion file is missing (e.g. it got deleted from the obb folder), my application will re-download it. This doesn't happen for me; my app keeps saying NO_DOWNLOAD_REQUIRED. It seems that the Google Play Downloader Library gets null for the download info from its SQLite database. Note that I haven't updated the draft APK and Expansion file on Google Play - they are still the first version. Moreover, the versionCode of the APK uploaded to Google Play is also identical with the one on the test device.
In details:
There was an APK Expansion file in the correct folder (obb). I used it for testing purposes before I actually started implementing the downloader functionality.
When the Downloader implementation (based on Google Play Downloader Library) was finished, I changed the size of the above obb file to make it invalid for my app. Therefore, this makes my app call the startDownloadIfNeeded() method.
First, I ran my implementation without any files on Google Play. The response was, as I expected: "Download failed because the resources could not be found"
Then I uploaded my 40MB APK and a 4 MB expansion file to Google Play (for testing purposes). Note that this 4 MB expansion file is not the invalid one which was left in the obb folder. When I ran my implementation, the response came after 1.5 seconds: "Download complete".
This was strange, because my internet connection is not so fast to download 4 MB. Indeed, the obb folder (the folder for APK Expansion files) still contained the invalid expansion file that I initially put there manually. That is, nothing was downloaded!
I deleted the invalid file, i.e. the obb folder is now empty, but still no download starts, and Downloader Library says NO_DOWNLOAD_REQUIRED. (I checked its internal implementation: when it queries an SQLite database for download info, it gets null after the query.)
I just read on SO somewhere that the APK Expansion files uploaded to Google Play require a few hours to take effect. In my case, I tested my implementation immediately after upload. But it must have noticed that there are files on Google Play, because instead of "resources could not be found", it gave a different message ("Download completed"). Too bad that it didn't actually download anything; and since then, it doesn't even try to (it keeps returning NO_DOWNLOAD_REQUIRED).
What am I missing?
Shouldn't the Downloader Library notice if an APK Expansion file gets deleted? Its implementation seems to deal with this, but only if the SQLite database query returns non-null for downloadable files.
The relevant part of internal implementation of Google Play Downloader Library (the last comment is mine):
int status = NO_DOWNLOAD_REQUIRED;
// the database automatically reads the metadata for version code
// and download status when the instance is created
DownloadsDB db = DownloadsDB.getDB(context);
// we need to update the LVL check and get a successful status to
// proceed
if (isLVLCheckRequired(db, pi)) {
status = LVL_CHECK_REQUIRED;
}
// we don't have to update LVL. do we still have a download to start?
if (db.mStatus == 0) {
DownloadInfo[] infos = db.getDownloads();
if (null != infos) {
for (DownloadInfo info : infos) {
if (!Helpers.doesFileExist(context, info.mFileName, info.mTotalBytes, true)) {
status = DOWNLOAD_REQUIRED;
db.updateStatus(-1);
break;
}
}
}
/// <----- This is when infos==null, in this case result will be NO_DOWNLOAD_REQUIRED
} else {
status = DOWNLOAD_REQUIRED;
}
If you encounter the same issue, uninstall the application, and then install it again. (Don't let Eclipse reinstall it in the usual way. Uninstall it completely from the device, manually.)

Why fopen gets fail in native method due to permission issue from Android-NDK application?

see i have following code in one native call
errno = 0;
FILE *fp;
fp = fopen("jigar.txt","wb");
if(fp == NULL)
__android_log_print(ANDROID_LOG_ERROR, APPNAME, "FOPEN FAIL with %d",errno);
else
__android_log_print(ANDROID_LOG_ERROR, APPNAME, "FOPEN pass ");
which gets fail and shows
FOPEN FAIL with 30
now here 30 means it shows error
#define EROFS 30 /* Read-only file system */
In MainFest file on my application i have added this line
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
still i am getting this error..
How to resolve this issue?
Edit
thanks by specifies folder name it works But
In my case i have one Library which has such fopen() call where file names i can not give. It takes it default filename.
And i am using this Library in my ndk application so in this case how to solve this?
By default when you are running your App, it runs in its own context. fopen("jigar.txt","wb"); will try to open the file in current directory, which i think mostly would be /data/.. So you cant create files like that. Instead, if you want a folder inside /data/ you can call a function gteDir() and inside it you can create your own files. Ok this is all for general information.
Coming to your problem, as mentioned above you need to give absolute path to create a file in a different directory. This is the same case even in Linux.
For the Library thing, you can do two things.
1) Make changes in the library source code and compile it again using NDK. While making changes, give some string as the argument for fopen() which you will pass it while executing the Application.
2) remount the filesystem in which your library is creating the file, then do chmod 777 to the specific directory inside which your file is being created. Now execute the Application. It should work. But this is not generic. If you are doing it for some testing purpose then this solution is simplest and time saving...
If stuck somewhere, let me know..
You should specify folder where to write the "jigar.txt" file. Like this:
fp = fopen("/sdcard/figar.txt", "wb");
yuppi finally i got that
i have did this way
first change the current directory of my process from "/" to "/sdcard/"
chdir("/sdcard/");
and then it find path with respect to /sdcard/
and everything WORKING..!!!

Categories

Resources