In my application I will be constantly using the DirectoryPath of my storage. In my MAIN I am initially creating the directory I would like to store this in a String to use in other methods such as when I create the actual database, I want it to be created in this path. I have gotten myself twisted up with everyone's recommendations and am returning a boolean value instead. Not sure I will use that value at all.
Here is what I have:
private static boolean mCreateDatabaseDirectory(String dbPath) {
boolean directoryCreated = true;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
Log.d("GENERAL", "Moving to mExternalStorageAvailable");
mExternalStorageAvailable();
Log.d("GENERAL", "Returning values of Available and Writeable");
if(mExternalStorageAvailable = mExternalStorageWriteable = true){
Log.d("GENERAL", "Booleans are True, creating Directoy");
File directoryPath = new File(Environment.getExternalStorageDirectory().toString()+"/APP/database");
Log.d("GENERAL", "directoryPath = " + directoryPath);
if(!directoryPath.exists()) {
directoryPath.mkdirs();
String databasePath = directoryPath.toString();
Log.d(DATABASE, "Database directory path created as " + databasePath);
//If we try to create the file but there is a problem then Log the error
if(!directoryPath.mkdirs()){
Log.e("DATABASE", "Problem creating Database Directory");
directoryCreated = false;
}
Log.d("GENERAL", "Directory did not exist but was created");
return directoryCreated;
}else {
Log.d("GENERAL", "Directory already exists, nothing to do here");
return directoryCreated;
}
}
return directoryCreated;
}
Another problem is that this does not actually create the directory in the SDCARD as I want it. It creates the directory in the /storage/emulated/0/APP/database which I assume is the internal storage likely designated as external. Well that is going to be a problem if this app starts creating a database that is 100mb or more and they do not have the space. How do I get it to the SDCARD?
Please ignore my million comments. I was debugging a NullPointer Error and needed to find out which line specifically was the problem. I will erase them later.
Did you test this with an emulator or your phone? In both cases, is a sdcard mounted?
Maybe this helps Does Environment.getExternalStorageDirectory() returns a usable data folder when no sd card is mounted? and I think you need to usegetExternalFilesDir. As of JellyBean and multiuser environments the behaviour changed as stated in the docs: developer.android.com/about/versions/android-4.2.html. To be sure that the external sdcard is mounted use: getExternalStorageState
heres a little snippet converting the FilePaths returned into a String and outputting them on Logcat
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String getDataDirectory = Environment.getDataDirectory().toString();
String getExternalStorageState = Environment.getExternalStorageState()
.toString();
String getExternalStorageDirectory = Environment
.getExternalStorageDirectory().toString();
String getExternalStoragePublicDirectory = Environment
.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS).toString();
String getExternalFilesDir = getExternalFilesDir("Documents")
.toString();
Log.i("INFO", "getDataDirectory " + getDataDirectory);
Log.i("INFO", "getExternalStorageState " + getExternalStorageState);
Log.i("INFO", "getExternalStorageDirectory "
+ getExternalStorageDirectory);
Log.i("INFO", "getExternalStoragePublicDirectory Documents "
+ getExternalStoragePublicDirectory);
Log.i("INFO", "getExternalFilesDir Documents " + getExternalFilesDir);
setContentView(R.layout.activity_main);
}
Be careful about getExternalStoragePublicDirectory and make sure you are using the right constant, documented here: http://developer.android.com/reference/android/os/Environment.html paragraph fields.
I m trying to save a file in sd card at the following path.
Environment.getExternalStorageDirectory().getAbsolutePath() + dir + filename
if sd card state is mounted.
String state = Environment.getExternalStorageState();
One of my user complained
No backup to the extern sd card (/storage/sdcard1/)
This issue raied in Galaxy Tab2 10.1.
I am little confused,i have nexus 4,where it has only internal memory.
and verified the same in S4,s3 and note 3 all worked fine.
Hope i am saving the file in right path and works fine in all devices.
how do i resolve complain ? any things is wrong ?
.
The SD card might not be ready yet. Consider waiting for external storage to get ready, before writing to it, as shown below.
// Wait till external storage is initialized upon startup.
private void awaitExternalStorageInitialization() {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
int count = 0;
do {
String state = Environment.getExternalStorageState();
if(count > 0) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Logger.log(e.getMessage(), Logger.LogType.ERROR, e);
}
}
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states,
// but all we need to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
count++;
} while ((!mExternalStorageAvailable) && (!mExternalStorageWriteable)
&& (count < 15));
if(!mExternalStorageWriteable)
Logger.log("External storage not ready yet", Logger.LogType.ERROR, null);
}
Manifest has
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
Application settings, 'Storage' = modify/delete SD card contents'
Same results on Samsung Tablet running 2.3.5 and Motorola Droid running 2.3.4.
Devices are not tethered to development machine.
Code follows:
public class OutputStudentRecords extends StActivity{
SharedPreferences mStudentSettings;
protected Cursor mCursor;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.create_csv);
String state = Environment.getExternalStorageState();
Toast.makeText(getApplicationContext(),"State is " + state, Toast.LENGTH_LONG).show();
if (!Environment.MEDIA_MOUNTED.equals(state)){
//We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
Toast.makeText(getApplicationContext(), "We Can Read And Write ", Toast.LENGTH_LONG).show();
File file = new File(Environment.getExternalStorageDirectory()
+File.separator
+"studentrecords"); //folder name
file.mkdir();
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
Toast.makeText(getApplicationContext(), "We Can Read but Not Write ", Toast.LENGTH_LONG).show();
}else{
//something else is wrong
mExternalStorageAvailable = mExternalStorageWriteable = false;
Toast.makeText(getApplicationContext(), "We Can't Read OR Write ", Toast.LENGTH_LONG).show();
}
}
}
Toast returns State="mounted" however it skips down to "we can't read or write" on both machines. I've missed something but can't find it, any help would be appreciated.
Thank you
Maybe you should change this:
if (!Environment.MEDIA_MOUNTED.equals(state)){
into this:
if (Environment.MEDIA_MOUNTED.equals(state)){
(ie: remove the "!")
I've reviewed numerous posts but still have no answer. After adding WRITE_EXTERNAL_STORAGE then checking that the sd card is writable and mounted, I still get "Parent directory of file is not writable." I'm using eclipse and the emulator and targeting SdkVersion="7".
How can I write to the sd card?
Example code follows:
<uses-premission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
.
.
.
checkSDStatus();
.
.
.
File sdCardRoot = Environment.getExternalStorageDirectory();
// Check state of SD card
String sdState = Environment.getExternalStorageState();
Log.d("--- state ---", sdState);
File dir = new File (sdCardRoot.getAbsolutePath() + "/download");
dir.mkdirs();
File file = new File(dir, fileName);
.
.
.
private void checkSDStatus(){
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
mExternalStorageAvailable = mExternalStorageWriteable = true;
Log.d("-- sd card --", "-- card writable --");
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
Log.d("-- sd card --", "-- card read only --");
} else {
mExternalStorageAvailable = mExternalStorageWriteable = false;
Log.d("-- sd card --", "-- card unvailable --");
}
}
Okay, I'll answer my question for others.
After adding to my manifest file several times previously I had nothing to lose so I copied another version of it and added it to the manifest below the existing permission.
The permissions appeared identical to the eye but I deleted my old one and used the new I had copied in.
I reran the app and it worked!!! Perhaps there was a bug on the disk, the manifest file wasn't getting read for some reason, or whatever - at least it now works!
If anyone knows why I'd sure like to hear the reason for this problem!
I'm trying to save my file to the following location
FileOutputStream fos = new FileOutputStream("/sdcard/Wallpaper/"+fileName);
but I'm getting the exception java.io.FileNotFoundException
However, when I put the path as "/sdcard/" it works.
Now I'm assuming that I'm not able to create directory automatically this way.
Can someone suggest how to create a directory and sub-directory using code?
If you create a File object that wraps the top-level directory you can call it's mkdirs() method to build all the needed directories. Something like:
// create a File object for the parent directory
File wallpaperDirectory = new File("/sdcard/Wallpaper/");
// have the object build the directory structure, if needed.
wallpaperDirectory.mkdirs();
// create a File object for the output file
File outputFile = new File(wallpaperDirectory, filename);
// now attach the OutputStream to the file object, instead of a String representation
FileOutputStream fos = new FileOutputStream(outputFile);
Note: It might be wise to use Environment.getExternalStorageDirectory() for getting the "SD Card" directory as this might change if a phone comes along which has something other than an SD Card (such as built-in flash, a'la the iPhone). Either way you should keep in mind that you need to check to make sure it's actually there as the SD Card may be removed.
UPDATE: Since API Level 4 (1.6) you'll also have to request the permission. Something like this (in the manifest) should work:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Had the same problem and just want to add that AndroidManifest.xml also needs this permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Here is what works for me.
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
in your manifest and the code below
public static boolean createDirIfNotExists(String path) {
boolean ret = true;
File file = new File(Environment.getExternalStorageDirectory(), path);
if (!file.exists()) {
if (!file.mkdirs()) {
Log.e("TravellerLog :: ", "Problem creating Image folder");
ret = false;
}
}
return ret;
}
Actually I used part of #fiXedd asnwer and it worked for me:
//Create Folder
File folder = new File(Environment.getExternalStorageDirectory().toString()+"/Aqeel/Images");
folder.mkdirs();
//Save the path as a string value
String extStorageDirectory = folder.toString();
//Create New file and name it Image2.PNG
File file = new File(extStorageDirectory, "Image2.PNG");
Make sure that you are using mkdirs() not mkdir() to create the complete path
With API 8 and greater, the location of the SD card has changed. #fiXedd's answer is good, but for safer code, you should use Environment.getExternalStorageState() to check if the media is available. Then you can use getExternalFilesDir() to navigate to the directory you want (assuming you're using API 8 or greater).
You can read more in the SDK documentation.
Make sure external storage is present:
http://developer.android.com/guide/topics/data/data-storage.html#filesExternal
private boolean isExternalStoragePresent() {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but
// all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
if (!((mExternalStorageAvailable) && (mExternalStorageWriteable))) {
Toast.makeText(context, "SD card not present", Toast.LENGTH_LONG)
.show();
}
return (mExternalStorageAvailable) && (mExternalStorageWriteable);
}
Don't forget to make sure that you have no special characters in your file/folder names. Happened to me with ":" when I was setting folder names using variable(s)
not allowed characters in file/folder names
" * / : < > ? \ |
U may find this code helpful in such a case.
The below code removes all ":" and replaces them with "-"
//actualFileName = "qwerty:asdfg:zxcvb" say...
String[] tempFileNames;
String tempFileName ="";
String delimiter = ":";
tempFileNames = actualFileName.split(delimiter);
tempFileName = tempFileNames[0];
for (int j = 1; j < tempFileNames.length; j++){
tempFileName = tempFileName+" - "+tempFileNames[j];
}
File file = new File(Environment.getExternalStorageDirectory(), "/MyApp/"+ tempFileName+ "/");
if (!file.exists()) {
if (!file.mkdirs()) {
Log.e("TravellerLog :: ", "Problem creating Image folder");
}
}
//Create File object for Parent Directory
File wallpaperDir = new File(Environment.getExternalStorageDirectory().getAbsoluteFile() +File.separator + "wallpaper");
if (!wallpaperDir.exists()) {
wallpaperDir.mkdir();
}
File out = new File(wallpaperDir, wallpaperfile);
FileOutputStream outputStream = new FileOutputStream(out);
I was facing the same problem, unable to create directory on Galaxy S but was able to create it successfully on Nexus and Samsung Droid. How I fixed it was by adding following line of code:
File dir = new File(Environment.getExternalStorageDirectory().getPath()+"/"+getPackageName()+"/");
dir.mkdirs();
File sdcard = Environment.getExternalStorageDirectory();
File f=new File(sdcard+"/dor");
f.mkdir();
this will create a folder named dor in your sdcard.
then to fetch file for eg- filename.json which is manually inserted in dor folder. Like:
File file1 = new File(sdcard,"/dor/fitness.json");
.......
.....
< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and don't forget to add code in manifest
This will make folder in sdcard with Folder name you provide.
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Folder name");
if (!file.exists()) {
file.mkdirs();
}
Just completing the Vijay's post...
Manifest
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
Function
public static boolean createDirIfNotExists(String path) {
boolean ret = true;
File file = new File(Environment.getExternalStorageDirectory(), path);
if (!file.exists()) {
if (!file.mkdirs()) {
Log.e("TravellerLog :: ", "Problem creating Image folder");
ret = false;
}
}
return ret;
}
Usage
createDirIfNotExists("mydir/"); //Create a directory sdcard/mydir
createDirIfNotExists("mydir/myfile") //Create a directory and a file in sdcard/mydir/myfile.txt
You could check for errors
if(createDirIfNotExists("mydir/")){
//Directory Created Success
}
else{
//Error
}
ivmage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent i = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, RESULT_LOAD_IMAGE_ADD);
}
});`