Question

My application downloads jpgs from a website using DownloadManager and store them in the /sdcard/Android/name.app/ directory to be used in several Fragments in the application. The download works great however, the jpgs are visible in the Gallery application, which I don't want since they are just assets for my application. I cannot figure out how to have them not show up in the Gallery application. I even tried adding .nomedia files to the directories are they are created. Any help would be appreciated!

    DownloadManager myDownloadManager = (DownloadManager) myActivity.getSystemService(Context.DOWNLOAD_SERVICE);
    Request myRequest = new Request(Uri.parse(episodeArtLink));
    myRequest.setNotificationVisibility(Request.VISIBILITY_HIDDEN);
    myRequest.setVisibleInDownloadsUi(false);
    myRequest.setDestinationInExternalFilesDir(myActivity, Environment.DIRECTORY_DOWNLOADS, myFilename);
    myDownloadManager.enqueue(myRequest);

The issues seem to be caused because MediaScanner is adding the Images to the system database even though I have not asked it to.

I have created a test app that demonstrates the problem. If you click the Download button the Google logo will show up in the app. If you go into the Gallery app you should also see the Google logo in a gallery named Download. If you go to Settings -> Apps and Clear the Data for Gallery and Media Storage then the Google logo will be gone and won't show up again in Gallery because the file is under /sdcard/Android/data/ which is protected by the .nomedia file. You can go to /sdcard/Android/data/com.example.downloadmanagertest/files/Download/ to verify that the images are still on the phone. Even after a reboot the images don't show up in Gallery if you clear the Data for Gallery and Media Storage. I have tested this on both a Nexus 4 and a Nexus 7 running 4.2.2.

Source: https://dl.dropboxusercontent.com/u/114414/DownloadManagerTest.zip

Was it helpful?

Solution 2

Solution

The media scanner will eventually sooner or later scan the media card for media and index them. The first intuitive step is to trick the Scanner into not knowing that the file is a media file. This can be achieved by saving the images without the extension. An easy solution would be to append notkevin to the end of the filename. Simply:

Instead of

 myRequest.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, Uri.parse(downloadLink).getLastPathSegment());

Use this

 String filename = Uri.parse(downloadLink).getLastPathSegment() + "notkevin";
 myRequest.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, filename);

However this is not sufficient in your case since you are using the DownloadManager (just a guess). The media scanner somehow knows about the downloaded item and the fact that it is an image and, thus, indexes it. To disallow it, use setMimeType like this:

myRequest.setMimeType("application/octet-stream");

PS: There are ways to change the extension other than adding your or my name to the end of the filename. For example, you could hash the filename

String filename = hash(Uri.parse(downloadLink).getLastPathSegment());

public String hash(String victim) throws NoSuchAlgorithmException
{
    MessageDigest md = MessageDigest.getInstance("SHA1");
    md.reset();
    byte[] buffer = victim.getBytes();
    md.update(buffer);
    byte[] digest = md.digest();

    StringBuilder hexStr = new StringBuilder();
    for (int i = 0; i < digest.length; i++) {
        hexStr.append(Integer.toString( ( digest[i] & 0xff ) + 0x100, 16).substring( 1 ));
    }
    return hexStr.toString();
}

OTHER TIPS

You may also put your entire folder to be untouched by the Scanner without having a change in your file extensions. Please refer to the ".nomedia" file in this link;

Hiding your files from the Media Scanner

Include an empty file named .nomedia in your external files directory (note the dot prefix in the filename). This prevents media scanner from reading your media files and providing them to other apps through the MediaStore content provider. However, if your files are truly private to your app, you should save them in an app-private directory.

I've been at this same problem for a few days now. I've tried just about every combination of creating hidden directories, using different extensions, putting .nomedia files in root and image directories directories, creating the .nomedia before the download, renaming directory (back and forth).

Unfortunately none of these seems to work for me (on the Nexus 4). My understanding is that the MediaScanner only does a re-scan when booting the phone or mounting the external storage. In a Nexus 4 (or any device which has no SD card slot) this mounting only happens at boottime.

However files downloaded with the Android Download Manager are immediately scanned (even though they shouldn't be) and placed into the gallery. Even if you have the .nomedia file they still end in the gallery. Uninstalling the app doesn't help as they thumbnails are still cached (you can remove them without a reboot by clearing the cache, data and force closing the Gallery and Media Storage apps in settings). If you reboot the phone Android rescans the external storage, sees that there is a .nomedia file, and then removes it from the gallery.

So this reboot/rescan kinda fixes the problem. However we don't want to be constantly asking users to reboot the phone so instead what worked for me was to force Android to rescan the external storage after successful downloads with:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" +  Environment.getExternalStorageDirectory())));

Which I got from Darshan's answer to a similar question and Jon.

I setup a broadcast receiver to listen for completed downloads and if they are successful I send the broadcast. Seems to work - downloaded images in my app are no longer appearing in the gallery.

Prefix your folder name with a dot (/sdcard/Android/name.app/.photos/). If that doesn't work, try hiding your folder.

https://github.com/thest1/LazyList/blob/master/src/com/fedorvlasov/lazylist/ImageLoader.java

Look at the methods with names like getphoto , getbitmap in the above link. The LazyLoader github project has all the methods you would need to tweek using suggestions in other answers to bring media from the WEB, to cache ( memory, Filesystem ) and to use bitmaps as you need to in your app.

In the filesinks, where the bitmaps persist , just adopt fileNames that will be recognized as needed by your modules BUT NOT RECOGNIZE by the media scanner.

that should do it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top