• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
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.exoplayer2.ui;
17 
18 import android.app.Notification;
19 import android.app.PendingIntent;
20 import android.content.Context;
21 import androidx.annotation.DrawableRes;
22 import androidx.annotation.Nullable;
23 import androidx.annotation.StringRes;
24 import androidx.core.app.NotificationCompat;
25 import com.google.android.exoplayer2.C;
26 import com.google.android.exoplayer2.offline.Download;
27 import java.util.List;
28 
29 /** Helper for creating download notifications. */
30 public final class DownloadNotificationHelper {
31 
32   private static final @StringRes int NULL_STRING_ID = 0;
33 
34   private final Context context;
35   private final NotificationCompat.Builder notificationBuilder;
36 
37   /**
38    * @param context A context.
39    * @param channelId The id of the notification channel to use.
40    */
DownloadNotificationHelper(Context context, String channelId)41   public DownloadNotificationHelper(Context context, String channelId) {
42     context = context.getApplicationContext();
43     this.context = context;
44     this.notificationBuilder = new NotificationCompat.Builder(context, channelId);
45   }
46 
47   /**
48    * Returns a progress notification for the given downloads.
49    *
50    * @param smallIcon A small icon for the notification.
51    * @param contentIntent An optional content intent to send when the notification is clicked.
52    * @param message An optional message to display on the notification.
53    * @param downloads The downloads.
54    * @return The notification.
55    */
buildProgressNotification( @rawableRes int smallIcon, @Nullable PendingIntent contentIntent, @Nullable String message, List<Download> downloads)56   public Notification buildProgressNotification(
57       @DrawableRes int smallIcon,
58       @Nullable PendingIntent contentIntent,
59       @Nullable String message,
60       List<Download> downloads) {
61     float totalPercentage = 0;
62     int downloadTaskCount = 0;
63     boolean allDownloadPercentagesUnknown = true;
64     boolean haveDownloadedBytes = false;
65     boolean haveDownloadTasks = false;
66     boolean haveRemoveTasks = false;
67     for (int i = 0; i < downloads.size(); i++) {
68       Download download = downloads.get(i);
69       if (download.state == Download.STATE_REMOVING) {
70         haveRemoveTasks = true;
71         continue;
72       }
73       if (download.state != Download.STATE_RESTARTING
74           && download.state != Download.STATE_DOWNLOADING) {
75         continue;
76       }
77       haveDownloadTasks = true;
78       float downloadPercentage = download.getPercentDownloaded();
79       if (downloadPercentage != C.PERCENTAGE_UNSET) {
80         allDownloadPercentagesUnknown = false;
81         totalPercentage += downloadPercentage;
82       }
83       haveDownloadedBytes |= download.getBytesDownloaded() > 0;
84       downloadTaskCount++;
85     }
86 
87     int titleStringId =
88         haveDownloadTasks
89             ? R.string.exo_download_downloading
90             : (haveRemoveTasks ? R.string.exo_download_removing : NULL_STRING_ID);
91     int progress = 0;
92     boolean indeterminate = true;
93     if (haveDownloadTasks) {
94       progress = (int) (totalPercentage / downloadTaskCount);
95       indeterminate = allDownloadPercentagesUnknown && haveDownloadedBytes;
96     }
97     return buildNotification(
98         smallIcon,
99         contentIntent,
100         message,
101         titleStringId,
102         /* maxProgress= */ 100,
103         progress,
104         indeterminate,
105         /* ongoing= */ true,
106         /* showWhen= */ false);
107   }
108 
109   /**
110    * Returns a notification for a completed download.
111    *
112    * @param smallIcon A small icon for the notifications.
113    * @param contentIntent An optional content intent to send when the notification is clicked.
114    * @param message An optional message to display on the notification.
115    * @return The notification.
116    */
buildDownloadCompletedNotification( @rawableRes int smallIcon, @Nullable PendingIntent contentIntent, @Nullable String message)117   public Notification buildDownloadCompletedNotification(
118       @DrawableRes int smallIcon, @Nullable PendingIntent contentIntent, @Nullable String message) {
119     int titleStringId = R.string.exo_download_completed;
120     return buildEndStateNotification(smallIcon, contentIntent, message, titleStringId);
121   }
122 
123   /**
124    * Returns a notification for a failed download.
125    *
126    * @param smallIcon A small icon for the notifications.
127    * @param contentIntent An optional content intent to send when the notification is clicked.
128    * @param message An optional message to display on the notification.
129    * @return The notification.
130    */
buildDownloadFailedNotification( @rawableRes int smallIcon, @Nullable PendingIntent contentIntent, @Nullable String message)131   public Notification buildDownloadFailedNotification(
132       @DrawableRes int smallIcon, @Nullable PendingIntent contentIntent, @Nullable String message) {
133     @StringRes int titleStringId = R.string.exo_download_failed;
134     return buildEndStateNotification(smallIcon, contentIntent, message, titleStringId);
135   }
136 
buildEndStateNotification( @rawableRes int smallIcon, @Nullable PendingIntent contentIntent, @Nullable String message, @StringRes int titleStringId)137   private Notification buildEndStateNotification(
138       @DrawableRes int smallIcon,
139       @Nullable PendingIntent contentIntent,
140       @Nullable String message,
141       @StringRes int titleStringId) {
142     return buildNotification(
143         smallIcon,
144         contentIntent,
145         message,
146         titleStringId,
147         /* maxProgress= */ 0,
148         /* currentProgress= */ 0,
149         /* indeterminateProgress= */ false,
150         /* ongoing= */ false,
151         /* showWhen= */ true);
152   }
153 
buildNotification( @rawableRes int smallIcon, @Nullable PendingIntent contentIntent, @Nullable String message, @StringRes int titleStringId, int maxProgress, int currentProgress, boolean indeterminateProgress, boolean ongoing, boolean showWhen)154   private Notification buildNotification(
155       @DrawableRes int smallIcon,
156       @Nullable PendingIntent contentIntent,
157       @Nullable String message,
158       @StringRes int titleStringId,
159       int maxProgress,
160       int currentProgress,
161       boolean indeterminateProgress,
162       boolean ongoing,
163       boolean showWhen) {
164     notificationBuilder.setSmallIcon(smallIcon);
165     notificationBuilder.setContentTitle(
166         titleStringId == NULL_STRING_ID ? null : context.getResources().getString(titleStringId));
167     notificationBuilder.setContentIntent(contentIntent);
168     notificationBuilder.setStyle(
169         message == null ? null : new NotificationCompat.BigTextStyle().bigText(message));
170     notificationBuilder.setProgress(maxProgress, currentProgress, indeterminateProgress);
171     notificationBuilder.setOngoing(ongoing);
172     notificationBuilder.setShowWhen(showWhen);
173     return notificationBuilder.build();
174   }
175 }
176