To make visible to my folder from Windows with USB connection (MTP) : /storage/emulated/0/MyFolder
I put a dummy file on this folder and use MediaScannerConnection.scanFile to scan this file.
File file = new File(Environment.getExternalStorageDirectory() + "MyFolder" + File.separator + "dummy.txt");
MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null, null);
All work well at the first time, i see that folder and dymmy file on windows. But if i delete the whole folder, when folder are re-created, it is seen as a file of 4K on windows.
Is there any cache on this level ? And how can i refresh this cache ?
Thank you
This bug of MTP still persists :
https://issuetracker.google.com/issues/36956498
https://issuetracker.google.com/issues/37071807
MediaScannerConnection.scanFile is not a perfect solution.
Related
It's been two days now I'm stucked on a veeery common and simple problem I don't seem to be able to solve (while other people are):
creating a folder on a SD card on Android!!! YES!!!
I red many many posts here, many tutorials that seems to say the same thing:
create a string with the external folder path + /yourFolderName
create a new file passing the path as argument
call mkdir() (or mkdirs()) on it
done!
alongside you can check if the SD card is MOUNTED, READABLE, WRITABLE,
and of course don't forget to put in your Manifest.xml the permission to WRITE_EXTERNAL_STORAGE, but be careful, it must be set as direct child of the manifest and not of the application!!!
Well nothing of that seems to work for me.
The folder_creation code is inside onCreate() and I'm trying to call a MediaScannerConnection to test if the file exists but it return null on OnScanCompleteListener - but I'm not sure I'm using this in the correct way-.
The application runs fine (launch the default camera activity then returns to the main one), but the folder is not created! (by now I just want to create the folder with nothing inside)
Maybe is an issue related to the package name containing the word "example" included in my package name? (I red something related somewhere...)
What could be wrong? Please give me an hint, advice, something...
I'm building on a Mac 1.7.5 with Eclipse using minSdkVersion = 8 and testing on a HTC Wildfire S with 2.3.5 (sdkVersion = 10). Checking with ES File Manager 1.6.1.6 on a non rooted device
Here's the main part of the code driving me crazy...
I would be very glad to know there's something I can do...
Thank you in advance!
myPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator
+ "myFolder";
File newDirectory = new File(myPath);
Log.v("judy says", newDirectory.toString());
newDirectory.mkdir(); // this doesn't work because "no directory" is displayed in the logCat window
if (!newDirectory.exists()) {
newDirectory.mkdir();
Log.v("no, no, no", "no directory");
}
MediaScannerConnection.scanFile(this,
new String[] { newDirectory.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
This works, if you want to create a directory "/mnt/sdcard/somedir/newdir"
File temp = new File (Environment.getExternalStorageDirectory (),
"somedir" + File.separator + "newdir");
if (!temp.exists ())
temp.mkdirs ();
ok, I solved: Simply using "uses permission" instead of "permission", the problem was that I was hard writing it in the manifest.xml, instead of using the graphical interface, this way I could use the built in list to choose a permission...
Really sorry if I bored...
I hope this could be useful for someone.
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'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).
I have an app that downloads files using Android's DownloadManager to a folder on the external file storage (SD card). This normally works fine, but there are some sources that cause the DownloadManager to trash the file when it finishes downloading it. A good example of a source file is:
http://traffic.libsyn.com/hdtvpodcast/HDTV-2012-06-01.mp3
It looks like maybe the problem is only with files from libsyn.com, but I'm not positive. I've looked around for ways to change how DownloadManager handles saving files, but can't find any options in the class.
This is where I enqueue the URL for download:
request = new Request(Uri.parse(currUrl));
external = Uri.fromFile(externalFile);
request.setDestinationUri(external);
request.setVisibleInDownloadsUi(false);
request.setNotificationVisibility(
DownloadManager.Request.VISIBILITY_HIDDEN);
currDownloadId = dm.enqueue(request);
The file locations are created using this:
Environment.getExternalStorageDirectory().getAbsolutePath() +
File.separator + "Podcatcher" + File.separator + "Feeds" + File.separator +
[int] + File.separator + [int] + [string extension];
Which turns out to be something like this when I query DownloadManager.COLUMN_LOCAL_FILENAME column from DownloadManager:
/mnt/sdcard/Podcatcher/Feeds/19/225.mp3
Most of the files are fine and persist after download, but not in this case. Any ideas about how I can force DownloadManager to leave the file after it is downloaded?
EDIT: I neglected to mention that when I use the standalone Download Manager when downloading this file from a browser that it reports failed at the end of the download. Perhaps my only solution is to download it from scratch, without DownloadManager?
try please followed code - worked for me:
request.setMimeType(application/octet-stream);
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.