ey up. ive built a simple music app that reads wav files from the sdcard and plays them.
how do i access the default media directory?
this is how i get the sdcard
public void LoadSounds() throws IOException
{
String extState = Environment.getExternalStorageState();
if(!extState.equals(Environment.MEDIA_MOUNTED)) {
//handle error here
}
else {
File sd = new File(Environment.getExternalStorageDirectory ()); //this needs to be a folder the user can access, like media
as usual the docs dont give an actual example of usage but it says this - If you're using API Level 8 or greater, use getExternalFilesDir() to open a File that represents the external storage directory where you should save your files. This method takes a type parameter that specifies the type of subdirectory you want, such as DIRECTORY_MUSIC...
how do i use it?
thank you
edit:
this makes it crash if i try to fill a spinner array with file path Strings.
File path = getExternalFilesDir(Environment.DIRECTORY_MUSIC);
File sd = new File(path, "/myFolder");
File[] sdDirList = sd.listFiles(new WavFilter());
if (sdDirList != null)
{
//sort the spinner
amountofiles = sdDirList.length;
array_spinner=new String[amountofiles];
......
final Spinner s = (Spinner) findViewById(R.id.spinner1); //crashes here
ArrayAdapter<?> adapter = new ArrayAdapter<Object>(this,
android.R.layout.select_dialog_item, array_spinner);
EDIT2:
ok so ive done this test that is supposed to write a txt file to the music directory.
i run the app, no txt file is written anywhere on the device i can find.
// Path to write files to
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath();
String fname = "mytest.txt";
// Current state of the external media
String extState = Environment.getExternalStorageState();
// External media can be written onto
if (extState.equals(Environment.MEDIA_MOUNTED))
{
try {
// Make sure the path exists
boolean exists = (new File(path)).exists();
if (!exists){ new File(path).mkdirs(); }
// Open output stream
FileOutputStream fOut = new FileOutputStream(path + fname);
fOut.write("Test".getBytes());
// Close output stream
fOut.flush();
fOut.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
another edit: i will get this working!!
so if i use this line it creates a folder on the sdcard called 'Musictest'. dont understand??
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC + "test").getAbsolutePath();
////////////////////////////////////////////////////////////////////
Final Edit:
right so this will look for a folder called test in the devices music directory.
if it doesnt exist, it will be created.
(some fixing to be done here, error if empty) it then lists the files in the directory and adds them to an array.
public void LoadSounds() throws IOException
{
String extState = Environment.getExternalStorageState();
// Path to write files to
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC + "/test").getAbsolutePath();
if(!extState.equals(Environment.MEDIA_MOUNTED)) {
//handle error here
}
else {
//do your file work here
// Make sure the path exists
boolean exists = (new File(path)).exists();
//if not create it
if (!exists){ new File(path).mkdirs(); }
File sd = new File(path);
//This will return an array with all the Files (directories and files)
//in the external storage folder
File[] sdDirList = sd.listFiles();
if (sdDirList != null)
{
//add the files to the spinner array
array_spinnerLoad=new String[sdDirList.length];
files = new String[sdDirList.length];
for(int i=0;i<sdDirList.length;i++){
array_spinnerLoad[i] = sdDirList[i].getName();
files[i] = sdDirList[i].getAbsolutePath();
}
}
}
}
as mentioned in the docs, getExternalFilesDir() return File. And File object can represent either file or directory.
Therefore:
File musicDirectory = new File( getExternalFilesDir(Environment.DIRECTORY_MUSIC));
Will give you the object to play with.
Related
I am trying to pull multiple images from gallery and place in grid view , Unfortunately I am not able to do so, Can you help me with that. And also I made a folder in sd card and I m trying to store audio as well as photographs in the same folder. Can you help me with that as well?
I am using android 2.3.
So I have included this code inside the button click but on click of button it has created the folder but its not storing the file inside the folder. On click of the button every other thing is working, its opening the gallery and its calculating numpic. I am not sure why its not storing the file in CN Video folder.
public void onClick(View v) {
Intent pass_data = new Intent(MainRecord.this, OpenGallery.class);
pass_data.putExtra("numpic",numpic);
startActivity(pass_data);
// Saving Audio recorded file to directory
File f = new File(Environment.getExternalStorageDirectory() + "/CNvideo");
if(f.isDirectory()) {
//Write code for the folder exist condition
}else {
// create a File object for the parent directory
File CNvideoDirectory = new File("/sdcard/CNVideo/");
// have the object build the directory structure, if needed.
CNvideoDirectory.mkdirs();
// create a File object for the output file
String filename = getfilename();
File outputFile = new File(CNvideoDirectory, filename);
// now attach the OutputStream to the file object, instead of a String representation
try {
FileOutputStream fos = new FileOutputStream(outputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}};
I am using the following code for trying to list the files in Download directory.
I build the apk, install it on my phone and then run it. I have files in both Internal memory/Download folder and External memory/Download folder when I view in File Browser of my phone, but the app does not display the file list. When I debug I find that the listFiles() function returns null.
Please let me know where I am doing wrong. The variable state has value mounted so the issue has nothing to do with the memory not being mounted.
String state = Environment.getExternalStorageState();
private boolean isMediaAvailable() {
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
} else {
return false;
}
}
if (!isMediaAvailable()) {
Utility.finishWithError(this,"Media Not Available");
} else {
String path =Environment.getExternalStorageDirectory().toString()+ File.separator + Environment.DIRECTORY_DOWNLOADS;
File file = new File(path);
mRootPath = file.getAbsoluteFile().getPath();
mFileNames = new ArrayList<String>();
File filesInDirectory[] = file.listFiles();
if (filesInDirectory != null) {
for (int i = 0; i<filesInDirectory.length;i++) {
mFileNames.add(filesInDirectory[i].getName());
}
}
}
Use :
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
to get the downloaded directory,
and use File.list() to get an array with the list of files in the directory.
I have been trying to copy a file from one location to another. To my understanding the copying mechanism of my program is working properly, however when I run the app I constantly get a file path error. I happen to be working with the data files within the xbmc app.
AssetManager-->addDefaultAssets CIP path not exsit
/data/data/org.xbmc.xbmc/.xbmc/userdata/guisettings.bak: open failed: ENOENT (No such file or directory)
The problem seems to occur when I create File objects for the string paths. Here is the code snippet for that portion of the program:
File inputFile = new File(inputPath);
File outputFile = new File(outputPath);
No matter how I try to access the files, I keep getting the above error. I have tried using the File, FileInputStream, and Uri libraries to get the file paths with no luck. Could I be having issues with write privileges, or am I just not specifying the file paths correctly? I am posting the whole solution just in case the problem lies elsewhere within the code.
public class myActivity extends Activity {
private static final String TAG = "myActivity.java";
//The package name representing the application directory that is to be accessed
String packageName = "org.xbmc.xbmc";
//The input filename to read and copy
String inputFileName = "guisettings.bak";
//The output filename to append to
String outputFileName = "guisettings.xml";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
//Check the status of the external storage
if(isExternalReady()) {
//The external file system is ready
//Start the specific file operation
restoreFile();
} else {
//Not ready. Create a Broadcast Receiver and wait for the filesystem to mount
BroadcastReceiver mExternalInfoReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent intent) {
//The external filesystem is now mounted
//Start the specific file operation
restoreFile();
}
};
//Get the IntentFilter Media Mounted
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
//Specify the filesystem data type
filter.addDataScheme("file");
//Register the receiver as "mExternalInfoReceiver" with the Media Mount filter
registerReceiver(mExternalInfoReceiver, new IntentFilter(filter));
}
}
//Restore the specific xml file
public void restoreFile() {
/*
//Get the internal storage of this app (Android/data/com.website.appname/files/)
String internalStorage = Environment.getFilesDir();
//Get the external storage path now that it is available
String externalStorage = Environment.getExternalStorageDirectory().toString();
//The directory of the file desired
String filePath = "Android/data/org.xbmc.xbmc/files/.xbmc/userdata/";
*/
//The information of the desired package
ApplicationInfo desiredPackage;
//Get the path of the application data folder if the application exists
try {
//Get the info of the desired application package
desiredPackage = getPackageInfo(packageName);
} catch (Exception e) {
//Output the stack trace
e.printStackTrace();
//Stop the function
return;
}
//Get the data dir of the package
String rootPackageDir = desiredPackage.dataDir;
//The path to the file in the package
String packageFilePath = "/.xbmc/userdata/";
//Construct the complete path of the input and output files respectively
//based on the application path
String inputPath = String.format("%s%s%s", rootPackageDir, packageFilePath, inputFileName);
String outputPath = String.format("%s%s%s", rootPackageDir, packageFilePath, outputFileName);
try {
//Copy the input file to the output file
if(copyFile(inputPath, outputPath)) {
//The file has been successfully copied
//Exit the application
System.exit(0);
}
} catch (IOException e) { e.printStackTrace(); return; }
}
//Is the external storage ready?
public boolean isExternalReady() {
//Get the current state of the external storage
//Check if the state retrieved is equal to MOUNTED
Boolean isMounted = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
if(isMounted) {
//The external storage is ready
return true;
}
//The external storage is not ready
return false;
}
//Get the data dir of a specific app if it exists
public ApplicationInfo getPackageInfo(String packageName) throws PackageNotFoundException {
List<ApplicationInfo> packages;
PackageManager pm;
//Init the package manager as pm
pm = getPackageManager();
//Get all installed applications
packages = pm.getInstalledApplications(0);
//Get the ApplicationInfo as packageInfo from each packages
for(ApplicationInfo packageInfo:packages) {
//Check for a name that matches the packageName
if(packageInfo.packageName.equals(packageName)) {
//The package exists
return packageInfo;
}
}
//The package was not found
//Throw an exception
throw new PackageNotFoundException("Package not found");
}
//Copy a file from an input directory to an output directory
public boolean copyFile(String inputPath, String outputPath) throws IOException {
//Construct the input and output paths as File objects with respective read/write privileges
//File inputFile = new File("/data/data/org.xbmc.xbmc/files/.xbmc/userdata/guisettings.bak");
//File outputFile = new File("/data/data/org.xbmc.xbmc/files/.xbmc/userdata/guisettings.xml");
//File inputFile = getDir(inputPath, MODE_PRIVATE);
//File outputFile = getDir(outputPath, MODE_PRIVATE);
File inputFile = new File(inputPath);
File outputFile = new File(outputPath);
//Check if the input and output files exist
if(!inputFile.exists()) {
return false;
}
if(!outputFile.exists()) {
//Create the output file
new File(outputPath);
}
//Get the input read state
boolean canReadInput = inputFile.canRead();
//Get the output write state
boolean canWriteOutput = outputFile.canWrite();
//Check if the input file can be read and if the output file can be written
if(canReadInput && canWriteOutput) {
//Open respective input and output buffer streams
InputStream in = new FileInputStream(inputFile);
OutputStream out = new FileOutputStream(outputFile);
//Create a byte array
byte[] buffer = new byte[1024];
//The current position of the byte buffer
int bufferPosition;
//While the bufferPosition is reading the file 1024 bytes at a time (-1 = no longer reading)
while((bufferPosition = in.read(buffer)) != -1) {
//Append the current buffer in memory to the output file
//With a pointer offset of 0 and a count of the current bufferPosition
out.write(buffer, 0, bufferPosition);
}
//Close the file streams
in.close();
out.close();
return true;
}
return false;
}
//The Package Error Class
private class PackageNotFoundException extends Exception {
//If an error is thrown with a message parameter
PackageNotFoundException(String m) {
//Pass the message to the super Exception class
super(m);
}
}
}
It turns out that my android device was having some issues connecting to my computer, hence the CIP Error.
After switching to another device, I also discovered that the input file itself was not being found, as I was trying to access the it through the "data/data" directory. The app data directories for installed apps can only be accessed through the external storage path. Since this varies from device to device, it needs to be retrieved dynamically.
Environment.getExternalStorageDirectory().getAbsolutePath();
After accessing the file this way I was able to successfully copy it.
My app allows user to take a picture and I want that picture to be stored in the app's external files directory (getExternalFilesDir(null)). It all works except for the call to renameTo(), this call returns false and I don't know why.
The src file is:
/storage/extSdCard/DCIM/Camera/20140424_154458.jpg
Dest file is:
/storage/emulated/0/Android/data/com.myapp.myapp/files/20140424_154458.jpg
I also have specified the WRITE_EXTERNAL_STORAGE permission.
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
if (item.getItemId() == R.id.action_take_picture)
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, TAKE_PICTURE_REQUEST_CODE);
return true;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == TAKE_PICTURE_REQUEST_CODE && resultCode == RESULT_OK)
{
File dest = new File(
getExternalFilesDir(null),
new SimpleDateFormat("yyyyMMdd_hhmmss", Locale.getDefault()).format(new Date()) + ".jpg");
File src = new File(convertMediaUriToPath(data.getData()));
if (src.renameTo(dest)) // Always returns false
{
mAdapter.add(dest);
mAdapter.notifyDataSetChanged();
}
}
}
private String convertMediaUriToPath(Uri uri)
{
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String path = cursor.getString(column_index);
cursor.close();
return path;
}
I have ran into this problem previously - unfortunately, you are not allowed to use renameTo to move files and/or directories between different mount points (for example, internal and external storage). Consider using a different way of moving files, such as the one outlined here:
http://www.mkyong.com/java/how-to-copy-directory-in-java/
public static void copyFolder(File src, File dest) throws IOException{
if(src.isDirectory()){
//if directory not exists, create it
if(!dest.exists()){
dest.mkdir();
System.out.println("Directory copied from "
+ src + " to " + dest);
}
//list all the directory contents
String files[] = src.list();
for (String file : files) {
//construct the src and dest file structure
File srcFile = new File(src, file);
File destFile = new File(dest, file);
//recursive copy
copyFolder(srcFile,destFile);
}
}else{
//if file, then copy it
//Use bytes stream to support all file types
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
//copy the file content in bytes
while ((length = in.read(buffer)) > 0){
out.write(buffer, 0, length);
}
in.close();
out.close();
System.out.println("File copied from " + src + " to " + dest);
}
}
The problem is with the method renameTo, the renameTo doesn't create subdirectories,
Reason being The current File API isn't very well implemented in Java. There is a lot of functionality that would be desirable in a File API that isn't currently present such as move, copy and retrieving file metadata.
I don't think anyone will be able to give you an answer as to why the API is written as is. Probably a poor first draft that went live and couldn't be changed due to backwards compatibility issues.
These issue have been addressed in the Java 7. A entirely new API has been created to deal with files java.nio.file.Files.
To Solve this issue, try to get directory path of destination file
e.g /storage/emulated/0/Android/data/com.myapp.myapp/files/20140424_154458.jpg
Destination Directory is
/storage/emulated/0/Android/data/com.myapp.myapp/files/
Use mkdirs() , it will create all sub directories for you
If you want to add a file or folder or move application into your SD Card just do the following:
steps:
1) Open your Android application's source code file with a text or programming editor. 2) Browse to the location in the source code where you wish to call the function that writes a file to the device's external storage. 3) Insert this single line of code to check for the SD card:
File sdCard = Environment.getExternalStorageDirectory();
4) Insert these lines of code to set the directory and file name:
File dir = new File (sdcard.getAbsolutePath() + "/folder1/folder2");
dir.mkdirs();
File file = new File(dir, "example_file");
// The mkdirs function will create the directory folder for you, use it only you want to create a new one.
5) Replace "/folder1/folder2" in the above code with the actual path where you intend to save the file. This should be a location in which you normally save your application files. Also, change the "example_file" value to the actual file name you wish to use.
6) Insert the following line of code to output the file to the SD card:
FileOutputStream f = new FileOutputStream(file);
Finally step 7:
Save the file, then compile it and test the application using the Android emulator software or the device.
This will work!!! ;-)
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);
}
});`