Haipad M701 using /nand directory when I request external storage - android

I have an Android app which by preference uses external storage if available to store various files but will use internal storage if external storage is unavailable.
I've extended Application and maintain a static File for the app's working directory as follows...
public class MyApp extends Application {
protected static File myFilesDir = null;
protected static Helper myHelper = null;
#Override
public void onCreate() {
super.onCreate();
myHelper = new Helper(this);
if (myHelper.CanWriteExtStorage()) {
Log.d(TAG, "onCreate() - myHelper.CanWriteExtStorage() returned TRUE");
myFilesDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + packageName + "/files");
}
else {
Log.d(TAG, "onCreate() - myHelper.CanWriteExtStorage() returned FALSE");
myFilesDir = new File(getFilesDir().getAbsolutePath());
}
myFilesDir.mkdirs();
if (!myFilesDir.equals(null)) {
Log.d(TAG, "onCreate() - myFilesDir: " + myFilesDir.getAbsolutePath());
}
The app is currently being beta-tested by some people I'm in direct contact with and one guy commented that he thought I was supposed to be using the SD card if available but he could see from logcat the app was using /nand/Android/data... I asked what /nand referenced and he said it is internal memory on his pad/tablet device.
The code the Helper class uses to check for external storage is as follows...
protected boolean CanWriteExtStorage() {
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state))
mExternalStorageWriteable = true;
return mExternalStorageWriteable;
}
...but the relevant log output is as follows...
D/com.mycompany.myapp(3844): onCreate() - myHelper.CanWriteExtStorage() returned TRUE
D/com.mycompant.myapp(3844): onCreate() - myFilesDir: /nand/Android/data/com.company.myapp/files
So, the question is why, when I'm able to test that the external storage state shows it is mounted, would Environment.getExternalStorageDirectory() return a path to what appears to be internal storage?
Should I be testing for something other than Environment.MEDIA_MOUNTED or is there just something strange about this device or Android version (he is running v2.1).
In the long run it possible doesn't matter but I'm concerned my logic is incorrect for certain devices.

Read the documentation for Environment.getExternalStorageDirectory()
Note: don't be confused by the word
"external" here. This directory can
better be thought as media/shared
storage. It is a filesystem that can
hold a relatively large amount of data
and that is shared across all
applications (does not enforce
permissions). Traditionally this is an
SD card, but it may also be
implemented as built-in storage in a
device that is distinct from the
protected internal storage and can be
mounted as a filesystem on a computer.
In devices with multiple "external"
storage directories (such as both
secure app storage and mountable
shared storage), this directory
represents the "primary" external
storage that the user will interact
with.
I have not personally seen a case but there is no requirement that getExternalStorageDirectory returns the memory card. You are doing the correct thing by treating the returned directory as shared storage as it was an intentional decision by the device manufacturer.

Related

getExternalFilesDir () doesnot store file to mounted memory card

I am using Nougut 7.1.1 device
When I run the below given code, file is stored in device or internal storage "emulated/0..." but I want to store it in removable memory card.
I logged getExternalStorageState() and it shows mounted.
I tried using Environment.getExternalStorageDirectory() also,stored in "emulated/0...", no result
I have used permissions in manifest file too as below:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Note: However, both internal and external(memory card) storage consist of "Hello World" folder like:
Android/Data/com.example.myapplication/files/Hello World/
but stored file(myData2.txt) is present only in "Hello World" folder of internal storage
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("tag", Environment.getExternalStorageState().toString());
Log.i("tag", getExternalFilesDir(null).toString());
savePrivate();
}
public void savePrivate() {
String info = "Written";
File folder = getExternalFilesDir("Hello World");// Folder Name
File myFile = new File(folder, "myData2.txt");// Filename
writeData(myFile, info);
}
private void writeData(File myFile, String data) {
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(myFile);
fileOutputStream.write(data.getBytes());
Toast.makeText(this, "Done" + myFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Changed my savePrivate() method as below and it worked like a charm!!
As per #CommonsWare suggested,using getExternalFilesDirs() returned available array of locations from which I could select particular storage,In my case folder[0] pointed to "emulated/0.." and folder[1] pointed to removable storage (storage/15C8-119Z/...).
public void savePrivate() {
String info = "Written";
File[] folder = getExternalFilesDirs("backup");// Folder Name
Log.i("tag", String.valueOf(folder[1]).toString());
File myFile = new File(folder[1], "myData2.txt");// Filename
writeData(myFile, info);
}
but stored file(myData2.txt) is present only in "Hello World" folder of internal storage
It is stored in what the Android SDK refers to as external storage. External storage is not removable storage, nor is it what the Android SDK refers to as internal storage.
When I run the below given code, file is stored in device or internal storage "emulated/0..." but I want to store it in removable memory card.
First, you are passing an invalid value to getExternalFilesDir(). Please follow the documentation and pass in a valid value (e.g., Environment.DIRECTORY_MUSIC) or null.
To write to removable storage, replace getExternalFilesDir() with getExternalFilesDirs() and choose a location from the returned array of locations. If that array has 2+ entries, 1+ of them will be on removable storage.
Beginning with Android 4.4 (API level 19), reading or writing files in your app's private external storage directory—accessed using getExternalFilesDir()—does not require the READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE permissions. So if your app supports Android 4.3 (API level 18) and lower, and you want to access only the private external storage directory, you should declare that the permission be requested only on the lower versions of Android by adding the maxSdkVersion attribute:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
</manifest>
Select between multiple storage locations
Sometimes, a device that allocates a partition of the internal memory for use as the external storage also provides an SD card slot. This means that the device has two different external storage directories, so you need to select which one to use when writing "private" files to the external storage.
Beginning with Android 4.4 (API level 19), you can access both locations by calling getExternalFilesDirs(), which returns a File array with entries for each storage location. The first entry in the array is considered the primary external storage, and you should use that location unless it's full or unavailable.
If your app supports Android 4.3 and lower, you should use the support library's static method, ContextCompat.getExternalFilesDirs(). This always returns a File array, but if the device is running Android 4.3 and lower, then it contains just one entry for the primary external storage (if there's a second storage location, you cannot access it on Android 4.3 and lower).
Check official documentation for detailed description.
Hope this helps.
This is a function in context where you could get all mounted storage's
ContextCompat.getExternalFilesDirs(context,Environment.YOUR_DIRECTORY);
So , First is your primary internal storage and second will be your mounted sd-card if mounted . You may use this function that returns the sd-card directory if sd-card mounted else the internal-storage directory
File getDir(Context context){
File[] mountedStorage = ContextCompat.getExternalFilesDirs(context,Environment.DIRECTORY_PICTURES);
return mountedStorage[mountedStorage.length-1];
}
With Kotlin
val dir:File = ContextCompat.getExternalFilesDirs(context,Environment.YOUR_DIRECTORY).last()

Use Googles FUSE to determine if SD CARD is mounted

We have looked at numerous SO post that deal with the SD CARD also the SO post which seems to be the Gold Standard Gold Standard But it deals with permissions we are not asking about permission. The question deals with finding another way to determine if the SD CARD is mounted. This question only wants to deal with SDK 23+ The article that discuss FUSE is at this link FUSE
We have tried this code that when the emulator has the SD CARD ejected returns or evaluates to TRUE. Other similar configuration from SO have also been tested.
My question is not only how to detect if the SD CARD is mounted but why is this code failing? We are not sure if this code can be tested on an emulator or if a real device is needed. We feel this code failure is because of the concept of the term EXTERNAL storage not meaning an actual SD CARD but making reference to the secondary EXTERNAL storage that is internal.
public boolean chkFORSDCARD() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
System.out.println("#################### IS ####### TRUE "+state);
return true;
}
System.out.println("##################### IS ###### Not Available "+state);
return false;
}
Here is where #james_duh are getting into trouble this line of code as mentioned in your comment `THE_PATH = THE_PATH + "/Documents/"; will not work when the SD CARD is unmounted with this line of code set to [1]
File removable = ContextCompat.getExternalFilesDirs(this, null)[1];
The solution is simple remove the THE_PATH = THE_PATH + "/Documents/";
As for testing if the SD CARD is mounted I am still working on that stay tuned
This code is not real neat but it works. Why you want it to work might be a 64K question ? ? I have tested the code and it works. What might be or concern is the words used to evaluate the path not sure they are or will remain consistent
Here is the code It seems point less to check the state so you can remove that test and construct a new more suitable one I did not get that far
public void onAvail() {
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED) || (!state.equals(Environment.MEDIA_MOUNTED_READ_ONLY))) {
File removable = ContextCompat.getExternalFilesDirs(this, null)[1];
THE_PATH = String.valueOf(removable);
if(THE_PATH.contains("Android")){
System.out.println("################################### EXTERNAL Storage "+THE_PATH);
THE_PATH = THE_PATH + "/Documents/";
}else {
File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
String INTERNAL_PATH = String.valueOf(dir);
if(INTERNAL_PATH.contains("emulated")){
System.out.println("######################## $$$$$$$ #### Internal Storage "+INTERNAL_PATH);
}
}
}
}

How properly work with android internal and external storage?

i am creating Download Manager app therefore my requirement is to store files on sdcard and phone internal storage if sdcard not available and access them later to open files from app.
i have read almost every post to store files but it confuses me to decide which method is best to use because there are lot of different ways to do.i want to create folder inside external(if available) or internal then store files inside this folder.
Now here can anyone tell me what is best way to access sdcard if available otherwise internal storage
Storage options in android is the place where you need to go. You will know how to Checking media availability from there, more specifically external storage.
The sample code is
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
Use Environment to access ExternalStorageDirectory

Environment.getExternalStorageState() returns MEDIA_REMOVED on an HTC that has available memory

In my app, im trying to check whether the user has connected their phone to the pc as a drive, so I can warn them to disconnect it because I need access to the storage.
It works fine on all 4-5 devices that I've tested on, except this HTC Desire X phone, Android 4.0.4 . It has no SD card, but there is about 2 gb of some storage available for writing.
Here is the code that I use
private void checkStorage() {
// Get the external storage's state
String state = Environment.getExternalStorageState();
Log.d("STATE", state);
if (state.equals(Environment.MEDIA_MOUNTED)) {
// Storage is available and writeable
externalStorageAvailable = externalStorageWriteable = true;
} else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
// Storage is only readable
externalStorageAvailable = true;
externalStorageWriteable = false;
} else {
// Storage is neither readable nor writeable
externalStorageAvailable = externalStorageWriteable = false;
}
}
So when I run it, the logcat debug tag returns:
removed
According to documentation:
http://developer.android.com/reference/android/os/Environment.html#MEDIA_REMOVED
"Storage state if the media is not present."
How can I modify this code so it detects the presence of a memory that is available for use?
Now, there is another thing. On this phone, when I try downloading an image from the browser, Im not allowed to, and I get the following message:
No SD card
An SD card is required to download <filename>
OK
Is there something wrong with the phone or is this normal? How do I make my app work on this phone?
EDIT: Furthermore, if I am able to get past this, how do I write files to the storage? Here's my code that does that and works on other devices:
File directory = null;
File file = null;
try {
directory = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),
Utils.getWritableDiectory(Locale.ENGLISH));
if (!directory.exists()) {
directory.mkdirs();
}
file = new File(directory, "data.json");

How to prevent data on external storage getting deleted on reinstall/update?

I notice that my app's data on external storage (i.e. SD card) gets deleted during an "adb install -r". While this is normal for uninstall (and then afterwards install optionally to notice it), I do not understand why this is the case for reinstall (and thus for Market updates as well). I could have sworn this was not always the case.
Referring to http://developer.android.com/guide/topics/data/data-storage.html#filesExternal I am specifically using "Accessing files on external storage" on Android 2.2, but not "Saving files that should be shared" or "Saving cache files". So I am writing and reading data in "/sdcard/Android/data//files/somefolder/data". My preferences do stick.
#Commonsware: The problem is not so much with getExternalFilesDir() IMHO as I see my data is written where I expect it. It just does not stick. I am using a.o.:
public static File getDefaultDirectory(Context context, String packageName) {
File dir;
if(mActivity_getExternalFilesDir!=null){//API >=8
dir = invokeGetExternalFilesDir(context, "fortune");
}else if(mEnvironment_getExternalStorageDirectory!=null){//API <=7
dir = invokeGetExternalStorageDirectory();
dir = new File(dir.getPath() + "/Android/data/" + packageName + "/files/");
}else{
//should never occur
return null;
}
return dir;
}
IIRC, there is a bug in Android 2.2 that causes these symptoms. I advise against the use of getExternalFilesDir() until Gingerbread.

Categories

Resources