mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-30 23:03:00 +00:00 
			
		
		
		
	Create individual stream notifications for convenience on Android 7.0 and later.
This commit is contained in:
		 Isira Seneviratne
					Isira Seneviratne
				
			
				
					committed by
					
						 TobiGr
						TobiGr
					
				
			
			
				
	
			
			
			 TobiGr
						TobiGr
					
				
			
						parent
						
							8cfba4003d
						
					
				
				
					commit
					7742c40ac0
				
			| @@ -1,6 +1,8 @@ | ||||
| package org.schabi.newpipe.local.feed.notifications | ||||
|  | ||||
| import android.app.Notification | ||||
| import android.app.NotificationManager | ||||
| import android.app.PendingIntent | ||||
| import android.content.Context | ||||
| import android.content.Intent | ||||
| import android.graphics.Bitmap | ||||
| @@ -12,6 +14,7 @@ import androidx.core.app.NotificationCompat | ||||
| import androidx.core.app.NotificationManagerCompat | ||||
| import androidx.core.app.PendingIntentCompat | ||||
| import androidx.core.content.ContextCompat | ||||
| import androidx.core.content.getSystemService | ||||
| import androidx.preference.PreferenceManager | ||||
| import com.squareup.picasso.Picasso | ||||
| import com.squareup.picasso.Target | ||||
| @@ -26,23 +29,22 @@ import org.schabi.newpipe.util.PicassoHelper | ||||
|  * Helper for everything related to show notifications about new streams to the user. | ||||
|  */ | ||||
| class NotificationHelper(val context: Context) { | ||||
|  | ||||
|     private val manager = context.getSystemService( | ||||
|         Context.NOTIFICATION_SERVICE | ||||
|     ) as NotificationManager | ||||
|  | ||||
|     private val manager = context.getSystemService<NotificationManager>()!! | ||||
|     private val iconLoadingTargets = ArrayList<Target>() | ||||
|  | ||||
|     /** | ||||
|      * Show a notification about new streams from a single channel. | ||||
|      * Opening the notification will open the corresponding channel page. | ||||
|      * Show notifications for new streams from a single channel. The individual notifications are | ||||
|      * expandable on Android 7.0 and later. | ||||
|      * | ||||
|      * Opening the summary notification will open the corresponding channel page. Opening the | ||||
|      * individual notifications will open the corresponding video. | ||||
|      */ | ||||
|     fun displayNewStreamsNotification(data: FeedUpdateInfo) { | ||||
|         val newStreams: List<StreamInfoItem> = data.newStreams | ||||
|     fun displayNewStreamsNotifications(data: FeedUpdateInfo) { | ||||
|         val newStreams = data.newStreams | ||||
|         val summary = context.resources.getQuantityString( | ||||
|             R.plurals.new_streams, newStreams.size, newStreams.size | ||||
|         ) | ||||
|         val builder = NotificationCompat.Builder( | ||||
|         val summaryBuilder = NotificationCompat.Builder( | ||||
|             context, | ||||
|             context.getString(R.string.streams_notification_channel_id) | ||||
|         ) | ||||
| @@ -50,7 +52,7 @@ class NotificationHelper(val context: Context) { | ||||
|             .setContentText( | ||||
|                 data.listInfo.relatedItems.joinToString( | ||||
|                     context.getString(R.string.enumeration_comma) | ||||
|                 ) { x -> x.name } | ||||
|                 ) { it.name } | ||||
|             ) | ||||
|             .setNumber(newStreams.size) | ||||
|             .setBadgeIconType(NotificationCompat.BADGE_ICON_LARGE) | ||||
| @@ -60,16 +62,19 @@ class NotificationHelper(val context: Context) { | ||||
|             .setColorized(true) | ||||
|             .setAutoCancel(true) | ||||
|             .setCategory(NotificationCompat.CATEGORY_SOCIAL) | ||||
|             .setGroupSummary(true) | ||||
|             .setGroup(data.listInfo.url) | ||||
|             .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) | ||||
|  | ||||
|         // Build style | ||||
|         // Build a summary notification for Android versions < 7.0 | ||||
|         val style = NotificationCompat.InboxStyle() | ||||
|             .setSummaryText(summary) | ||||
|             .setBigContentTitle(data.name) | ||||
|         newStreams.forEach { style.addLine(it.name) } | ||||
|         style.setSummaryText(summary) | ||||
|         style.setBigContentTitle(data.name) | ||||
|         builder.setStyle(style) | ||||
|         summaryBuilder.setStyle(style) | ||||
|  | ||||
|         // open the channel page when clicking on the notification | ||||
|         builder.setContentIntent( | ||||
|         // open the channel page when clicking on the summary notification | ||||
|         summaryBuilder.setContentIntent( | ||||
|             PendingIntentCompat.getActivity( | ||||
|                 context, | ||||
|                 data.pseudoId, | ||||
| @@ -84,13 +89,21 @@ class NotificationHelper(val context: Context) { | ||||
|         // a Target is like a listener for image loading events | ||||
|         val target = object : Target { | ||||
|             override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) { | ||||
|                 builder.setLargeIcon(bitmap) // set only if there is actually one | ||||
|                 manager.notify(data.pseudoId, builder.build()) | ||||
|                 summaryBuilder.setLargeIcon(bitmap) // set only if there is actually one | ||||
|  | ||||
|                 // Show individual stream notifications | ||||
|                 showStreamNotifications(newStreams, data.listInfo.serviceId) | ||||
|                 // Show summary notification | ||||
|                 manager.notify(data.pseudoId, summaryBuilder.build()) | ||||
|  | ||||
|                 iconLoadingTargets.remove(this) // allow it to be garbage-collected | ||||
|             } | ||||
|  | ||||
|             override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) { | ||||
|                 manager.notify(data.pseudoId, builder.build()) | ||||
|                 // Show individual stream notifications | ||||
|                 showStreamNotifications(newStreams, data.listInfo.serviceId) | ||||
|                 // Show summary notification | ||||
|                 manager.notify(data.pseudoId, summaryBuilder.build()) | ||||
|                 iconLoadingTargets.remove(this) // allow it to be garbage-collected | ||||
|             } | ||||
|  | ||||
| @@ -106,6 +119,41 @@ class NotificationHelper(val context: Context) { | ||||
|         PicassoHelper.loadNotificationIcon(data.avatarUrl).into(target) | ||||
|     } | ||||
|  | ||||
|     private fun showStreamNotifications(newStreams: List<StreamInfoItem>, serviceId: Int) { | ||||
|         newStreams.asSequence() | ||||
|             .map { it to createStreamNotification(it, serviceId) } | ||||
|             .forEach { (stream, notification) -> | ||||
|                 manager.notify(stream.url.hashCode(), notification) | ||||
|             } | ||||
|     } | ||||
|  | ||||
|     private fun createStreamNotification(item: StreamInfoItem, serviceId: Int): Notification { | ||||
|         return NotificationCompat.Builder( | ||||
|             context, | ||||
|             context.getString(R.string.streams_notification_channel_id) | ||||
|         ) | ||||
|             .setSmallIcon(R.drawable.ic_newpipe_triangle_white) | ||||
|             .setContentTitle(item.name) | ||||
|             .setContentText(item.uploaderName) | ||||
|             .setGroup(item.uploaderUrl) | ||||
|             .setColor(ContextCompat.getColor(context, R.color.ic_launcher_background)) | ||||
|             .setColorized(true) | ||||
|             .setAutoCancel(true) | ||||
|             .setCategory(NotificationCompat.CATEGORY_SOCIAL) | ||||
|             .setContentIntent( | ||||
|                 // Open the stream link in the player when clicking on the notification. | ||||
|                 PendingIntentCompat.getActivity( | ||||
|                     context, | ||||
|                     item.url.hashCode(), | ||||
|                     NavigationHelper.getStreamIntent(context, serviceId, item.url, item.name), | ||||
|                     PendingIntent.FLAG_UPDATE_CURRENT, | ||||
|                     false | ||||
|                 ) | ||||
|             ) | ||||
|             .setSilent(true) // Avoid creating noise for individual stream notifications. | ||||
|             .build() | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|         /** | ||||
|          * Check whether notifications are enabled on the device. | ||||
| @@ -124,9 +172,7 @@ class NotificationHelper(val context: Context) { | ||||
|         fun areNotificationsEnabledOnDevice(context: Context): Boolean { | ||||
|             return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|                 val channelId = context.getString(R.string.streams_notification_channel_id) | ||||
|                 val manager = context.getSystemService( | ||||
|                     Context.NOTIFICATION_SERVICE | ||||
|                 ) as NotificationManager | ||||
|                 val manager = context.getSystemService<NotificationManager>()!! | ||||
|                 val enabled = manager.areNotificationsEnabled() | ||||
|                 val channel = manager.getNotificationChannel(channelId) | ||||
|                 val importance = channel?.importance | ||||
|   | ||||
| @@ -55,7 +55,7 @@ class NotificationWorker( | ||||
|             .map { feedUpdateInfoList -> | ||||
|                 // display notifications for each feedUpdateInfo (i.e. channel) | ||||
|                 feedUpdateInfoList.forEach { feedUpdateInfo -> | ||||
|                     notificationHelper.displayNewStreamsNotification(feedUpdateInfo) | ||||
|                     notificationHelper.displayNewStreamsNotifications(feedUpdateInfo) | ||||
|                 } | ||||
|                 return@map Result.success() | ||||
|             } | ||||
|   | ||||
| @@ -563,11 +563,8 @@ public final class NavigationHelper { | ||||
|                                        @Nullable final PlayQueue playQueue, | ||||
|                                        final boolean switchingPlayers) { | ||||
|  | ||||
|         final Intent intent = getOpenIntent(context, url, serviceId, | ||||
|                 StreamingService.LinkType.STREAM); | ||||
|         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||
|         intent.putExtra(Constants.KEY_TITLE, title); | ||||
|         intent.putExtra(VideoDetailFragment.KEY_SWITCHING_PLAYERS, switchingPlayers); | ||||
|         final Intent intent = getStreamIntent(context, serviceId, url, title) | ||||
|                 .putExtra(VideoDetailFragment.KEY_SWITCHING_PLAYERS, switchingPlayers); | ||||
|  | ||||
|         if (playQueue != null) { | ||||
|             final String cacheKey = SerializedCache.getInstance().put(playQueue, PlayQueue.class); | ||||
| @@ -680,6 +677,15 @@ public final class NavigationHelper { | ||||
|         return getOpenIntent(context, url, serviceId, StreamingService.LinkType.CHANNEL); | ||||
|     } | ||||
|  | ||||
|     public static Intent getStreamIntent(final Context context, | ||||
|                                          final int serviceId, | ||||
|                                          final String url, | ||||
|                                          @Nullable final String title) { | ||||
|         return getOpenIntent(context, url, serviceId, StreamingService.LinkType.STREAM) | ||||
|                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | ||||
|                 .putExtra(Constants.KEY_TITLE, title); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Finish this <code>Activity</code> as well as all <code>Activities</code> running below it | ||||
|      * and then start <code>MainActivity</code>. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user