13

My app uses the DownloadManager to download files to a subdirectory of the device's Music folder.

DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
...
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) + "/MyStuff/song.mp3");
request.setDestinationUri(Uri.fromFile(file));

I have noticed that the files are being deleted when the app is uninstalled from a device running Marshmallow (this is not happening on older OS versions). Do you have any ideas about this?

Thanks

Floern
  • 33,559
  • 24
  • 104
  • 119
Matteo Innocenti
  • 231
  • 2
  • 10
  • I can reproduce this behavior. I'm not terribly shocked that they did this, but that does feel like a regression. – CommonsWare Feb 04 '16 at 21:30
  • 2
    Note that the same behavior occurs with Android 5.1 (tested on a Nexus 4), but does not with Android 4.1 (tested on a Galaxy Nexus), so the change happened in that range. It's not strictly new to Android 6.0. Based on emulator testing, it looks like the change came in Android 5.0 -- 4.4 keeps the download, 5.0 does not. – CommonsWare Feb 04 '16 at 21:41
  • Does this only happen for downloaded files, or for all files placed in one of the public folders by an app? If only for downloaded files, then a quick copy would alleviate this, yes? – 323go Feb 05 '16 at 04:40
  • 1
    @323go it's only for downloaded file. But I wonder if it's also done for files put there with `addCompletedDownload()`. – tynn Feb 07 '16 at 18:23
  • 1
    @323go it seems to be happening only for downloaded files. I have implemented a file copy as a workaround for this bug: note that the copied file needs to have a different file name, a swap won't work. – Matteo Innocenti Mar 07 '16 at 15:50
  • @MatteoInnocenti, thank you. This is good to know. – 323go Mar 07 '16 at 15:58
  • Any updates on this? – Murat Karagöz Jun 01 '17 at 14:17

1 Answers1

5

This is done by an internal class called DownloadReceiver and defined in the com.android.providers.downloads package manifest

<receiver android:name=".DownloadReceiver" android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        <action android:name="android.intent.action.UID_REMOVED" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_MOUNTED" />
        <data android:scheme="file" />
    </intent-filter>
</receiver>

Here the android.intent.action.UID_REMOVED action catches the eye. It was introduced in Lollipop triggering a call to handleUidRemoved() performing

resolver.delete(ALL_DOWNLOADS_CONTENT_URI, Constants.UID + "=" + uid, null);
tynn
  • 38,113
  • 8
  • 108
  • 143
  • This intent seems to be referring to a user (UID) removed, not an application, (which it would make sense to remove user's downloads after their user is deleted.) https://developer.android.com/reference/android/content/Intent.html#ACTION_UID_REMOVED – FaultException Aug 10 '16 at 22:13
  • 2
    @FaultException It's not connected to a real user. It refers to Linux system user id assigned to the application. https://developer.android.com/guide/components/fundamentals.html – tynn Aug 10 '16 at 22:35
  • I see. My mistake. – FaultException Aug 11 '16 at 04:07
  • Great find! Nice job. – yshahak Sep 28 '16 at 11:34
  • 1
    @tynn Any way to prevent this activity? I'd like the files, downloaded through the app, stay in the external memory of the device even if the app is uninstalled. – Adomas Nov 19 '16 at 15:33
  • 1
    @Adomas I don't know if there's any official fix for this feature. What i've been doing is, downloading the file with another name and change the file name on `android.intent.action.DOWNLOAD_COMPLETE` bcast receiver. it actually keeps the file but some what sounds like a hack. If you get any other solution, please let me know. – theapache64 Dec 28 '16 at 12:51