• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.android.libraries.mobiledatadownload.lite;
17 
18 import android.content.Context;
19 import com.google.android.libraries.mobiledatadownload.downloader.FileDownloader;
20 import com.google.common.base.Optional;
21 import com.google.common.base.Preconditions;
22 import com.google.common.base.Supplier;
23 import com.google.common.util.concurrent.ListenableFuture;
24 import com.google.common.util.concurrent.MoreExecutors;
25 import com.google.errorprone.annotations.CanIgnoreReturnValue;
26 import com.google.errorprone.annotations.CheckReturnValue;
27 import java.util.concurrent.Executor;
28 
29 /** The root object and entry point for the MDDLite (<internal>). */
30 public interface Downloader {
31 
32   /**
33    * Downloads a file with the given {@link DownloadRequest}.
34    *
35    * <p>This method will not create a notification and will not run in a ForegroundService.
36    *
37    * <p>NOTE: The caller is responsible for keeping the download alive. This is typically used by
38    * clients who use a service the platform binds with, so a notification is not needed. If you are
39    * unsure whether to use this method or {@link #downloadWithForegroundService}, contact the MDD
40    * team (<internal>@ or via <a href="<internal>">yaqs</a>.
41    */
42   @CheckReturnValue
download(DownloadRequest downloadRequest)43   ListenableFuture<Void> download(DownloadRequest downloadRequest);
44 
45   /**
46    * Download a file and show foreground download progress in a notification. User can cancel the
47    * download from the notification menu.
48    *
49    * <p>NOTE: Calling downloadWithForegroundService without a provided ForegroundService will return
50    * a failed future.
51    *
52    * <p>The cancel action in the notification menu requires the ForegroundService to be registered
53    * with the application (via the AndroidManifest.xml). This allows the cancellation intents to be
54    * properly picked up. To register the service, the following lines must be included in the app's
55    * {@code AndroidManifest.xml}:
56    *
57    * <pre>{@code
58    * <!-- Needed by foreground download service -->
59    * <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
60    *
61    * <!-- Service for MDD Lite foreground downloads -->
62    * <service
63    *   android:name="com.google.android.libraries.mobiledatadownload.lite.sting.ForegroundDownloadService"
64    *   android:exported="false" />
65    * }</pre>
66    *
67    * <p>NOTE: The above excerpt is for Framework and Sting apps. Dagger apps should use the same
68    * excerpt, but change the {@code android:name} property to:
69    *
70    * <pre>{@code
71    * android:name="com.google.android.libraries.mobiledatadownload.lite.dagger.ForegroundDownloadService"
72    * }</pre>
73    */
74   @CheckReturnValue
downloadWithForegroundService(DownloadRequest downloadRequest)75   ListenableFuture<Void> downloadWithForegroundService(DownloadRequest downloadRequest);
76 
77   /**
78    * Cancel an on-going foreground download.
79    *
80    * <p>Use {@link ForegroundDownloadKey} to construct the unique key.
81    *
82    * <p><b>NOTE:</b> In most cases, clients will not need to call this -- it is meant to allow the
83    * ForegroundDownloadService to cancel a download via the Cancel action registered to a
84    * notification.
85    *
86    * <p>Clients should prefer to cancel the future returned to them from {@link
87    * #downloadWithForegroundService} instead.
88    */
cancelForegroundDownload(String downloadKey)89   void cancelForegroundDownload(String downloadKey);
90 
newBuilder()91   static Downloader.Builder newBuilder() {
92     return new Downloader.Builder();
93   }
94 
95   /** A Builder for the {@link Downloader}. */
96   final class Builder {
97 
98     private static final String TAG = "Builder";
99     private Executor sequentialControlExecutor;
100 
101     private Context context;
102     private Supplier<FileDownloader> fileDownloaderSupplier;
103     private Optional<SingleFileDownloadProgressMonitor> downloadMonitorOptional = Optional.absent();
104     private Optional<Class<?>> foregroundDownloadServiceClassOptional = Optional.absent();
105 
106     @CanIgnoreReturnValue
setContext(Context context)107     public Builder setContext(Context context) {
108       this.context = context.getApplicationContext();
109       return this;
110     }
111 
112     /** Set the Control Executor which will run MDDLite control flow. */
113     @CanIgnoreReturnValue
setControlExecutor(Executor controlExecutor)114     public Builder setControlExecutor(Executor controlExecutor) {
115       Preconditions.checkNotNull(controlExecutor);
116       // Executor that will execute tasks sequentially.
117       this.sequentialControlExecutor = MoreExecutors.newSequentialExecutor(controlExecutor);
118       return this;
119     }
120 
121     /**
122      * Set the SingleFileDownloadProgressMonitor. This instance must be the same instance that is
123      * registered with SynchronousFileStorage.
124      *
125      * <p>This is required to use {@link Downloader#downloadWithForegroundService}. Not providing
126      * this will result in a failed future when calling downloadWithForegroundService.
127      *
128      * <p>This is required to track progress updates and network pauses when passing a {@link
129      * DownloadListener} to {@link Downloader#download}. The DownloadListener's {@code onFailure}
130      * and {@code onComplete} will be invoked regardless of whether this is set.
131      */
132     @CanIgnoreReturnValue
setDownloadMonitor(SingleFileDownloadProgressMonitor downloadMonitor)133     public Builder setDownloadMonitor(SingleFileDownloadProgressMonitor downloadMonitor) {
134       this.downloadMonitorOptional = Optional.of(downloadMonitor);
135       return this;
136     }
137 
138     /**
139      * Set the Foreground Download Service. This foreground service will keep the download alive
140      * even if the user navigates away from the host app. This ensures long download can finish.
141      *
142      * <p>This is required to use {@link Downloader#downloadWithForegroundService}. Not providing
143      * this will result in a failed future when calling downloadWithForegroundService.
144      */
145     @CanIgnoreReturnValue
setForegroundDownloadService(Class<?> foregroundDownloadServiceClass)146     public Builder setForegroundDownloadService(Class<?> foregroundDownloadServiceClass) {
147       this.foregroundDownloadServiceClassOptional = Optional.of(foregroundDownloadServiceClass);
148       return this;
149     }
150 
151     /**
152      * Set the FileDownloader Supplier. MDDLite takes in a Supplier of FileDownload to support lazy
153      * instantiation of the FileDownloader
154      */
155     @CanIgnoreReturnValue
setFileDownloaderSupplier(Supplier<FileDownloader> fileDownloaderSupplier)156     public Builder setFileDownloaderSupplier(Supplier<FileDownloader> fileDownloaderSupplier) {
157       this.fileDownloaderSupplier = fileDownloaderSupplier;
158       return this;
159     }
160 
Builder()161     Builder() {}
162 
build()163     public Downloader build() {
164       return new DownloaderImpl(
165           context,
166           foregroundDownloadServiceClassOptional,
167           sequentialControlExecutor,
168           downloadMonitorOptional,
169           fileDownloaderSupplier);
170     }
171   }
172 }
173