1 /* 2 * Copyright (C) 2023 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 17 package com.android.providers.media.photopicker.sync; 18 19 import android.app.Notification; 20 import android.app.NotificationChannel; 21 import android.app.NotificationManager; 22 import android.content.Context; 23 import android.content.res.Resources; 24 import android.util.Log; 25 26 import androidx.annotation.NonNull; 27 import androidx.annotation.VisibleForTesting; 28 import androidx.core.app.NotificationCompat; 29 import androidx.work.ForegroundInfo; 30 31 import com.android.modules.utils.build.SdkLevel; 32 import com.android.providers.media.R; 33 34 /** 35 * Helper functions for Picker sync notifications. 36 */ 37 public class PickerSyncNotificationHelper { 38 private static final String TAG = "SyncNotifHelper"; 39 @VisibleForTesting 40 static final String NOTIFICATION_CHANNEL_ID = "PhotoPickerSyncChannel"; 41 @VisibleForTesting 42 static final int NOTIFICATION_ID = 0; 43 private static final int NOTIFICATION_TIMEOUT_MILLIS = 1000; 44 45 46 /** 47 * Created notification channel for Picker Sync notifications. 48 * Recreating an existing notification channel with its original values performs no operation, 49 * so it's safe to call this code when starting an app. 50 */ createNotificationChannel(@onNull Context context)51 public static void createNotificationChannel(@NonNull Context context) { 52 final String contentTitle = context.getResources() 53 .getString(R.string.picker_sync_notification_channel); 54 55 final NotificationChannel channel = new NotificationChannel( 56 NOTIFICATION_CHANNEL_ID, contentTitle, NotificationManager.IMPORTANCE_LOW); 57 channel.enableLights(false); 58 channel.enableVibration(false); 59 60 final NotificationManager notificationManager = 61 context.getSystemService(NotificationManager.class); 62 if (notificationManager != null) { 63 notificationManager.createNotificationChannel(channel); 64 } 65 } 66 67 /** 68 * Return Foreground info. This object contains a Notification and notification id that should 69 * be displayed in the context of a foreground service. 70 * This method should not be invoked by WorkManager in Android S+ devices. 71 */ 72 @NonNull getForegroundInfo(@onNull Context context)73 public static ForegroundInfo getForegroundInfo(@NonNull Context context) { 74 if (SdkLevel.isAtLeastS()) { 75 Log.w(TAG, "Picker Sync notifications should not be displayed in S+ devices."); 76 } 77 return new ForegroundInfo(NOTIFICATION_ID, getNotification(context)); 78 } 79 80 /** 81 * Create a notification to display when Picker sync is happening. 82 */ getNotification(@onNull Context context)83 private static Notification getNotification(@NonNull Context context) { 84 final Resources resources = context.getResources(); 85 final String contentTitle = resources.getString(R.string.picker_sync_notification_title); 86 final String contentText = resources.getString(R.string.picker_sync_notification_text); 87 88 return new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) 89 .setSmallIcon(R.drawable.picker_app_icon) 90 .setContentTitle(contentTitle) 91 .setContentText(contentText) 92 .setPriority(NotificationCompat.PRIORITY_MIN) 93 .setVisibility(NotificationCompat.VISIBILITY_SECRET) 94 .setSilent(true) 95 .setTimeoutAfter(NOTIFICATION_TIMEOUT_MILLIS) 96 .build(); 97 } 98 } 99