Skip to main content

Ongoing Notifications

In order for the system not to kill the application while scanning and uploading the photos to the cloud (especially when the application is not active and works in the background mode), the Photo SDK launches the foreground service and displays ongoing notifications. The application is responsible for preparing the UI of these notifications, since only this application has all the necessary resources.

The interaction is as follows:

  • The Photos SDK declares interfaces;
  • The application implements these interfaces and sets the implementation to the SDK;
  • The SDK calls the application's implementation every time it needs to show or update the notification;
  • Application returns a new notification object on each call.

There are two types of notifications:

  1. Scan: A notification appears when the Photos SDK is scanning photos in the background mode. Note that this notification appears only when app is started in background without user interaction;
  2. Upload: A notification appears when the Photos SDK is uploading photos;

The Photos SDK declares two interfaces for those notification types:

  1. ScanNotificationProvider provides a notification for scanning service.
  2. UploadNotificationAdapter provides a notification for uploading service.

The following example shows the implementation of ScanNotificationProvider.

class ScanForeProvider(    private val context: Context) : ScanNotificationProvider {
    companion object {
        private const val NOTIFICATION_ID = 13243
        // Both notification adapter/provider can share single notification channel        internal const val NOTIFICATION_CHANNEL_ID = "foreground_upload_progress"
        /**         * Application must independently register a message channel on Android 8+.         *         * Call only once from Application.onCreate()         */        @JvmStatic        @RequiresApi(Build.VERSION_CODES.O)        fun registerNotificationChannel(context: Context) {            val channel = NotificationChannel(                NOTIFICATION_CHANNEL_ID,                "Auto upload progress",                NotificationManager.IMPORTANCE_LOW            )            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager            notificationManager.createNotificationChannel(channel)        }    }
    /**     * Returns notification     */    override fun getNotification(): Notification {        val intent = Intent(context, MainActivity::class.java)        intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS        val pendingIntent = PendingIntent.getActivity(            context,            NOTIFICATION_ID,            intent,            PendingIntent.FLAG_UPDATE_CURRENT        )
        // Do not reuse builder as it may lead to resource leaks. Create builder every time.        val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)            .setContentIntent(pendingIntent)            .setCategory(Notification.CATEGORY_SERVICE)            .setSmallIcon(R.drawable.ic_notification)            .setContentText("Scanning photos on device...")            .setContentTitle("Photo's timeline")        return builder.build()    }
    /**     * Returns notification id     */    override fun getNotificationId() = NOTIFICATION_ID}

// ...
// Register notification channelif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {    ScanForeProvider.registerNotificationChannel(this)}
// Set the implementation to the SDKPhotoManager.timeline.setScanNotificationProvider(ScanForeProvider(this))

The following example shows the implementation of UploadNotificationAdapter.

class UploadForeAdapter(    private val context: Context) : UploadNotificationAdapter {
    companion object {
        private const val NOTIFICATION_ID = 13244
        // Both notification adapter/provider can share single notification channel        private const val NOTIFICATION_CHANNEL_ID = "foreground_upload_progress"
        /**         * Application must independently register a message channel on Android 8+.         *         * Call only once from Application.onCreate()         */        @RequiresApi(Build.VERSION_CODES.O)        fun registerNotificationChannel(context: Context) {            val channel = NotificationChannel(                NOTIFICATION_CHANNEL_ID,                "Auto upload progress",                NotificationManager.IMPORTANCE_LOW            )            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager            notificationManager.createNotificationChannel(channel)        }    }
    /**     * The method statusToNotification() receives the upload status and returns a ready     * notification displayed by the foreground service from the Photos SDK.     * The statusToNotification() method is called each time the upload status is changed.     */    override fun statusToNotification(uploadStatus: UploadStatus): Notification {
        // Do not reuse builder as it may lead to resource leaks. Create builder every time.        val intent = Intent(context, MainActivity::class.java)        intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS        val pendingIntent = PendingIntent.getActivity(            context,            NOTIFICATION_ID,            intent,            PendingIntent.FLAG_UPDATE_CURRENT        )
        val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)            .setContentIntent(pendingIntent)            .setCategory(Notification.CATEGORY_SERVICE)            .setSmallIcon(R.drawable.ic_notification)            .setContentText(String.format("Uploading photos. %d left ...", uploadStatus.photosLeft))            .setContentTitle("Photo's timeline")        return builder.build()    }}
// ...
// Register notification channelif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {    UploadForeAdapter.registerNotificationChannel(this)}
// Set the implementation to the SDKPhotoManager.uploadManager.setNotificationAdapter(UploadForeAdapter(this))