I've created a file in the SD card using the code below:
File outputFile = new File( Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test.jpg" );
outputFile.createNewFile();
OutputStream outputStream = new FileOutputStream( outputFile );
mBitmap.compress( Bitmap.CompressFormat.JPEG, 95, outputStream );
outputStream.flush();
outputStream.close ();
When I try to see this file browsing SD card contents through Windows Explorer in my computer (phone connected via USB), all SD card folders and files are displayed, except mine. Astro displays the file, but not as a thumbnail.
Strangest thing is that this happens only with one of my phones (a Samsung Galaxy X phone), and if I reboot this phone, file is displayed both within Windows Explorer and as a thumbnail in Astro.
Could there be something wrong or missing in the code I wrote?
Thanks
image files need to be explicitly indexed in order to appear in the gallery. I suppose other applications may be using the same mechanism to get the thumbnail. Here is some code that will scan a new media file, right after you wrote it:
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(outputFile);
intent.setData(uri);
sendBroadcast(intent);
Maybe there is some Windows caching behind in order not to continuously poll the directory listing. Try hitting F5 in Explorer to see if file comes up. In any case, file should be visible in Eclipse's phone File Explorer (in DDMS Perspective).
Related
I'm writing an airplane simulator program and want the user to be able create model files seperately using XML. Then, in the app they can select which model (XML file) to load. I have the XML files in a subdirectory on my SD card and can read it with my BLU phone but not my Motorola Photon II. With the Motorola I get a file not found when initializing the input stream. I have the following code...
In the Manifest I have set read external storage permission...
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Here's the code to open the XML file...
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/SimFiles/Vehicles/" + "myModel.xml");
InputStream in = new BufferedInputStream(new FileInputStream(file));
It's pretty straight forward. So, why on one and not the other? Is it a permissions thing- one more strict than the other? Thanks.
Try using this...
File file = new File(Environment.getExternalStorageDirectory() + "/SimFiles/Vehicles/" + "myModel.xml");
InputStream in = new BufferedInputStream(new FileInputStream(file));
I'm trying to save pictures in a subfolder on Android. Here's a bit of my code:
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
path = new File(path, "SubDirName");
path.mkdirs();
(I've tried getExternalStorageDirectory instead of getExternalStoragePublicDirectory and the Pictures folder instead of DCIM.)
Any subfolder I add, including its contents, don't show up in Windows Explorer when the device is connected via USB. It does show in the Android File Manager, though.
I've tried broadcasting the ACTION_MEDIA_MOUNTED intent on the new directory's parent. It didn't work.
If I add a file in Windows, it shows up on Android. If I add a file on Android via the File Manager, it shows up in Windows. If I add the file programmatically, it shows up on the Android File Manager, but not in Windows Explorer. And I need to get it from Windows, and I don't want the final user to have to create the folder manually.
What am I doing wrong?
I faced the same issue and rebooting either the Android device or the PC is not a practical solution for users. :)
This issue is through the use of the MTP protocol (I hate this protocol). You have to
initiate a rescan of the available files, and you can do this using the MediaScannerConnection class:
// Snippet taken from question
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
path = new File(path, "SubDirName");
path.mkdirs();
// Initiate a media scan and put the new things into the path array to
// make the scanner aware of the location and the files you want to see
MediaScannerConnection.scanFile(this, new String[] {path.toString()}, null, null);
The way used in Baschi's answer doesn't always work for me. Well, here is a full solution.
// Snippet taken from question
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
path = new File(path, "SubDirName");
path.mkdirs();
// Fix
path.setExecutable(true);
path.setReadable(true);
path.setWritable(true);
// Initiate media scan and put the new things into the path array to
// make the scanner aware of the location and the files you want to see
MediaScannerConnection.scanFile(this, new String[] {path.toString()}, null, null);
The only thing that worked for me was this:
Intent mediaScannerIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri fileContentUri = Uri.fromFile(path);
mediaScannerIntent.setData(fileContentUri);
this.sendBroadcast(mediaScannerIntent);
Credit to https://stackoverflow.com/a/12821924/1964666
None of the above helped me, but this worked:
The trick being to NOT scan the new folder, but rather create a file in the new folder and then scan the file. Now Windows Explorer sees the new folder as a true folder.
private static void fixUsbVisibleFolder(Context context, File folder) {
if (!folder.exists()) {
folder.mkdir();
try {
File file = new File(folder, "service.tmp");//workaround for folder to be visible via USB
file.createNewFile();
MediaScannerConnection.scanFile(context,
new String[]{file.toString()},
null, (path, uri) -> {
file.delete();
MediaScannerConnection.scanFile(context,
new String[]{file.toString()} ,
null, null);
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks to https://issuetracker.google.com/issues/37071807#comment90
You also should scan every created file in the directory analogically:
private static void fixUsbVisibleFile(Context context, File file) {
MediaScannerConnection.scanFile(context,
new String[]{file.toString()},
null, null);
}
If you add the folder to the SD card from the PC directly to the card through the card reader, it will not show in Windows Explorer when connected with the phone.
The solution is to copy or move the same folder using the Android file manager program and then it will be listed in the SD card index when connected to the PC.
It's work fine for me.
MediaScannerConnection.scanFile work if there is file in directory (not directory)
private fun checkMTPFolder(f: File, context: Context) {
if (f.isDirectory) {
val newFilePath = f.absolutePath + "/tempFIle"
val newFile = File(newFilePath)
newFile.mkdir()
MediaScannerConnection.scanFile(context, arrayOf(newFilePath), null, object : MediaScannerConnection.OnScanCompletedListener {
override fun onScanCompleted(p0: String?, p1: Uri?) {
val removedFile = File(p0)
removedFile.delete()
MediaScannerConnection.scanFile(context,arrayOf(removedFile.absolutePath), null, null)
}
})
}
}
I have solved this problem by toggling the phone setting:
After a directory is created and/or a file saved, change from (MTP) mode to USB (SD card) mode for a moment, wait for the SD card mounting on the PC, so the directory and file will be shown.
Turn back to (MTP) mode again where the last file still shows up.
When re-saving a file, you have to change to USB again to see it.
Just create the directory on the PC first, and then copy it over to the SD card/phone storage.
You can either put in the contents into the folder first and copy over or just the folder first. As long as the folder is created from the PC, any content can just be copied directly to internal/external mobile devices. For zipped content, it cannot be directly unzipped and copied over unfortunately; you need to unzip them first.
I am trying to read an image file from /mnt/sdcard/image.jpg into my ImageView. Here is my code:
Bitmap bmp = BitmapFactory.decodeFile("/mnt/sdcard/image.jpg");
webImage.setImageBitmap(bmp);
I have write external storage permission.
My code says bmp is null, even though the image resides in the root directory (I go to I Drive and image.jpg is there.)
What am I doing incorrectly?
There could be two cases:
1) If you image is in the root folder of sdcard then it is possible to to access it through
Environment.getExternalStorageDirectory().toString + File.separator + "yourimage.jpg"
2) But i guess in your case it is in the /mnt/sdcard/external_sd which your memory card of the device in that case try this:
Environment.getExternalStorageDirectory().toString + File.separator + "external_sd" + File.separator + "yourimage.jpg"
Replace the above two paths with yours in BitmapFactory.decodeFile("Replace Here...")
I suspect the card with the image isn't mounted under /mnt/sdcard/.
Since you are using a Motorola device, chances are that you have two mass storage devices (see this list, if your device is in there, this is the case). In this situation you have to use the Motorola "External" Storage API to get the path to your second mass storage.
Also in general: You can't rely on hardcoding paths to the SD-Card like this. The mountpoint differs across devices. Or might be named differently, some devices might have a flash storage instead of a card, and so on. In short: What works on your phone breaks on others. You can read a reliable path to the primary external storage by calling Environment.getExternalStorageDirectory() instead.
Thanks, I managed to resolve it. Here is what I found:
I went to project > clean
I disconnected the phone from the computer. When it is connected, the SD is mounted and you can't view data.
The image name can't start with numbers. I am using SDK 7.
I viewed LogCat and I didn't get any errors, however, saving to other system areas (like /Android/Data/) caused a FileNotFoundException - permissions error.
File destination = new File(Environment.getExternalStorageDirectory(), "image" +
DateHelper.getTodaysDate() + "_" + DateHelper.getCurrentTime() + ".jpg");
private View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Add extra to save full-image somewhere
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(destination));
startActivityForResult(intent, REQUEST_IMAGE);
}
};
Please check you LogCat for more information.
My guess is you have a Samsung device. Samsung tends to have an external_sd folder, so you might have added it to the wrong sdcard because Samsung often has an internal and an external one.
Your code is perfectly okay. Just check whether you are writing proper sd card path or not. May be for that reason you are getting null bitmap.
And "write external storage permission" is for writing to your sd card not for reading from sd card. Make this concept clear.
If I run the following code on an ASUS Transformer then 'testfile.txt' is created in the top level of the 'sd card' directory as expected.
private void testWriteFile () throws IOException
{
File sdCard = Environment.getExternalStorageDirectory();
File file = new File(sdCard, "testfile.txt");
FileOutputStream myOutput = new FileOutputStream(file);
byte buffer[] = {'0','1','2','3','4','5','6','7','8','9'};
myOutput.write(buffer,0,buffer.length);
myOutput.flush();
myOutput.close();
}
I can view the file on the ASUS Transformer using a File Manager app. I can see the file from a Windows dos box via the 'adb shell' command and its permissions appear to be set correctly. However, if I view the directory from Windows Explorer, 'testfile.txt' is not there. I have set the options to display hidden and system files, but with no luck.
If I use the ASUS file manager app to change the name of 'testfile.txt', then it becomes visible in Windows Explorer, so other apps are able to make files visible in Explorer.
If I run the same code on a ZTE Blade (Orange San Francisco) then I can see 'testfile.txt' in Windows Explorer without needing to change its name.
Is there something else I need to do to finalize this file so that it becomes visible?
A similar problem is reported here, Can't see a file in Windows written by an android app on sd-card unless I "Force Close" the app, but forcing a close in my case does not make the file visible.
I have solved this with the following instruction:
MediaScannerConnection.scanFile
(this, new String[] {file.toString()}, null, null);
I am not sure why this is required for the Asus and not for the ZTE Blade. However, there is a difference in the way that they connect to my PC and I suspect this is the reason.
The ZTE Blade appears as a USB mass storage device and is assigned a drive letter. The Asus appears as a portable media player (MTP) and is not assigned a drive letter.
I have this worked on android5.x:
File sdcard = Environment.getExternalStorageDirectory();
//step 1.
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.parse("file://" + sdcard)));
//step 2.
MediaScannerConnection.scanFile(getApplicationContext(),
new String[]{sdcard.getAbsolutePath()
+ "/screenshots/myscreen_" + IMAGES_PRODUCED + ".png"}, null, null);
Thanks.
Im trying to save data to sdCard first i tried to saave it privately within app directory on externalStorage using getExternalFilesDir but gives me nullPointerException so i tried the other way given below it worked but when i want to store files into a custom directory that i want to named myself it give me error:
FileOutputStream os;
dirName = "/mydirectory/";
try {
if (android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)){
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File (sdCard.getAbsolutePath() + dirName);
dir.mkdirs();
//File file = new File(this.getExternalFilesDir(null), this.dirName+fileName); //this function give null pointer exception so im using other one
File file = new File(dir, dirName+fileName);
os = new FileOutputStream(file);
}else{
os = context.openFileOutput(fileName, MODE_PRIVATE);
}
resizedBitmap.compress(CompressFormat.PNG, 100, os);
os.flush();
os.close();
}catch(Exception e){
}
ErrorLog:
java.io.FileNotFoundException: /mnt/sdcard/mvc/mvc/myfile2.png (No such file or directory)
Your directory "/mnt/sdcard/mvc/mvc" may not exist. What about changing your path to store the image in the Environment.getExternalStorageDirectory() path and then working from there?
Also, as Robert pointed out, make sure you have write permission to external storage in your manifest.
Edit - to create directories:
String root = Environment.getExternalStorageDirectory().toString();
new File(root + "/mvc/mvc").mkdirs();
Then you can save a file to root + "/mvc/mvc/foo.png".
Have you requested permission to write onto SD card? Add the following string to you app manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You should check if you have added the required permission android.permission-group.STORAGE to your app. Without that permission you won't be able to access anything on the SD-Card.
BTW: On the Android system I know the SD-card is mounted on /sdcard not /mnt/sdcard
I found this book to be very helpful: "Pro Android Media: Developing Graphics, Music, Video, and Rich Media Apps for Smartphones and Tablets". I noticed a part that allows saving images and stuff to the SD card.