/* * Copyright (C) 2017 volders GmbH with <3 in Berlin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package berlin.volders.rxdownload; import android.app.DownloadManager; import android.content.Context; import android.content.IntentFilter; import android.net.Uri; import android.os.Environment; import android.support.annotation.NonNull; import android.support.annotation.StringRes; import android.support.annotation.VisibleForTesting; import java.lang.ref.WeakReference; import rx.Single; /** * A reference to the {@code RxDownloadManager} has to be initialised by passing {@link Context}. * Then the manager can be directly used by supplying a {@link Uri}, {@link String} file name * and a string resource with a description passed to the {@code download} method. * * <pre> * rxDownloadManager.download(remoteFileUri, fileName, R.string.description) * .subscribe(this::useLocalFileUri, this::handleError); * </pre> */ public class RxDownloadManager { private final IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); final WeakReference<Context> context; final DownloadManager dm; @VisibleForTesting RxDownloadManager(Context context, DownloadManager dm) { this.context = new WeakReference<>(context); this.dm = dm; } /** * @param context Any available {@link Context}. Required to get the application context * @return A new instance of this manager */ public static RxDownloadManager from(@NonNull Context context) { DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); return new RxDownloadManager(context.getApplicationContext(), dm); } /** * @param uri {@link Uri} for downloading the file * @param fileName Destination file name * @param description String resource for the text to be shown in the notification associated with the download * @return {@link Single} that, upon download completion, will emit the {@link Uri} pointing to the local file */ public Single<Uri> download(Uri uri, String fileName, @StringRes int description) { return download(request(uri, fileName, description)); } /** * @param request {@link DownloadManager.Request} that contains the file destination and URL information for downloading * @return {@link Single} that, upon download completion, will emit the {@link Uri} pointing to the local file */ public Single<Uri> download(DownloadManager.Request request) { DownloadBroadcastReceiver receiver = new DownloadBroadcastReceiver(dm.enqueue(request)); context.get().registerReceiver(receiver, intentFilter); return receiver.getDownloadId().map(new DownloadIdToUri(dm)).toSingle(); } /** * @param uri {@link Uri} for downloading the file * @param fileName Destination file name * @return Built {@link DownloadManager.Request} with destination folder {@link Environment#DIRECTORY_DOWNLOADS} and file name */ public static DownloadManager.Request request(Uri uri, String fileName) { return new DownloadManager.Request(uri) .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName) .setTitle(fileName); } /** * @param uri {@link Uri} for downloading the file * @param fileName Destination file name * @param description {@link String} to be shown in the notification associated with the download * @return {@link DownloadManager.Request} with destination folder {@link Environment#DIRECTORY_DOWNLOADS} and file name */ public static DownloadManager.Request request(Uri uri, String fileName, String description) { return request(uri, fileName).setDescription(description); } /** * @param uri {@link Uri} for downloading the file * @param fileName Destination file name * @param description String resource for the text to be shown in the notification associated with the download * @return {@link DownloadManager.Request} with destination folder {@link Environment#DIRECTORY_DOWNLOADS} and file name */ public DownloadManager.Request request(Uri uri, String fileName, @StringRes int description) { return request(uri, fileName).setDescription(context.get().getString(description)); } }