Skip to content

Commit c658f28

Browse files
Merge pull request TeamNewPipe#10078 from Isira-Seneviratne/Improve_feed_notifications
Improve new stream notifications
2 parents cd2884d + cb00c57 commit c658f28

8 files changed

Lines changed: 91 additions & 35 deletions

File tree

app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt

Lines changed: 79 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.schabi.newpipe.local.feed.notifications
22

3+
import android.app.Notification
34
import android.app.NotificationManager
5+
import android.app.PendingIntent
46
import android.content.Context
57
import android.content.Intent
68
import android.graphics.Bitmap
@@ -12,46 +14,41 @@ import androidx.core.app.NotificationCompat
1214
import androidx.core.app.NotificationManagerCompat
1315
import androidx.core.app.PendingIntentCompat
1416
import androidx.core.content.ContextCompat
17+
import androidx.core.content.getSystemService
1518
import androidx.preference.PreferenceManager
1619
import com.squareup.picasso.Picasso
1720
import com.squareup.picasso.Target
1821
import org.schabi.newpipe.R
1922
import org.schabi.newpipe.extractor.stream.StreamInfoItem
2023
import org.schabi.newpipe.local.feed.service.FeedUpdateInfo
21-
import org.schabi.newpipe.util.Localization
2224
import org.schabi.newpipe.util.NavigationHelper
2325
import org.schabi.newpipe.util.PicassoHelper
2426

2527
/**
2628
* Helper for everything related to show notifications about new streams to the user.
2729
*/
2830
class NotificationHelper(val context: Context) {
29-
30-
private val manager = context.getSystemService(
31-
Context.NOTIFICATION_SERVICE
32-
) as NotificationManager
33-
31+
private val manager = NotificationManagerCompat.from(context)
3432
private val iconLoadingTargets = ArrayList<Target>()
3533

3634
/**
37-
* Show a notification about new streams from a single channel.
38-
* Opening the notification will open the corresponding channel page.
35+
* Show notifications for new streams from a single channel. The individual notifications are
36+
* expandable on Android 7.0 and later.
37+
*
38+
* Opening the summary notification will open the corresponding channel page. Opening the
39+
* individual notifications will open the corresponding video.
3940
*/
40-
fun displayNewStreamsNotification(data: FeedUpdateInfo) {
41-
val newStreams: List<StreamInfoItem> = data.newStreams
41+
fun displayNewStreamsNotifications(data: FeedUpdateInfo) {
42+
val newStreams = data.newStreams
4243
val summary = context.resources.getQuantityString(
4344
R.plurals.new_streams, newStreams.size, newStreams.size
4445
)
45-
val builder = NotificationCompat.Builder(
46+
val summaryBuilder = NotificationCompat.Builder(
4647
context,
4748
context.getString(R.string.streams_notification_channel_id)
4849
)
49-
.setContentTitle(Localization.concatenateStrings(data.name, summary))
50-
.setContentText(
51-
data.listInfo.relatedItems.joinToString(
52-
context.getString(R.string.enumeration_comma)
53-
) { x -> x.name }
54-
)
50+
.setContentTitle(data.name)
51+
.setContentText(summary)
5552
.setNumber(newStreams.size)
5653
.setBadgeIconType(NotificationCompat.BADGE_ICON_LARGE)
5754
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
@@ -60,16 +57,18 @@ class NotificationHelper(val context: Context) {
6057
.setColorized(true)
6158
.setAutoCancel(true)
6259
.setCategory(NotificationCompat.CATEGORY_SOCIAL)
60+
.setGroupSummary(true)
61+
.setGroup(data.listInfo.url)
62+
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
6363

64-
// Build style
64+
// Build a summary notification for Android versions < 7.0
6565
val style = NotificationCompat.InboxStyle()
66+
.setBigContentTitle(data.name)
6667
newStreams.forEach { style.addLine(it.name) }
67-
style.setSummaryText(summary)
68-
style.setBigContentTitle(data.name)
69-
builder.setStyle(style)
68+
summaryBuilder.setStyle(style)
7069

71-
// open the channel page when clicking on the notification
72-
builder.setContentIntent(
70+
// open the channel page when clicking on the summary notification
71+
summaryBuilder.setContentIntent(
7372
PendingIntentCompat.getActivity(
7473
context,
7574
data.pseudoId,
@@ -84,13 +83,23 @@ class NotificationHelper(val context: Context) {
8483
// a Target is like a listener for image loading events
8584
val target = object : Target {
8685
override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) {
87-
builder.setLargeIcon(bitmap) // set only if there is actually one
88-
manager.notify(data.pseudoId, builder.build())
86+
// set channel icon only if there is actually one (for Android versions < 7.0)
87+
summaryBuilder.setLargeIcon(bitmap)
88+
89+
// Show individual stream notifications, set channel icon only if there is actually
90+
// one
91+
showStreamNotifications(newStreams, data.listInfo.serviceId, bitmap)
92+
// Show summary notification
93+
manager.notify(data.pseudoId, summaryBuilder.build())
94+
8995
iconLoadingTargets.remove(this) // allow it to be garbage-collected
9096
}
9197

9298
override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) {
93-
manager.notify(data.pseudoId, builder.build())
99+
// Show individual stream notifications
100+
showStreamNotifications(newStreams, data.listInfo.serviceId, null)
101+
// Show summary notification
102+
manager.notify(data.pseudoId, summaryBuilder.build())
94103
iconLoadingTargets.remove(this) // allow it to be garbage-collected
95104
}
96105

@@ -106,6 +115,49 @@ class NotificationHelper(val context: Context) {
106115
PicassoHelper.loadNotificationIcon(data.avatarUrl).into(target)
107116
}
108117

118+
private fun showStreamNotifications(
119+
newStreams: List<StreamInfoItem>,
120+
serviceId: Int,
121+
channelIcon: Bitmap?
122+
) {
123+
for (stream in newStreams) {
124+
val notification = createStreamNotification(stream, serviceId, channelIcon)
125+
manager.notify(stream.url.hashCode(), notification)
126+
}
127+
}
128+
129+
private fun createStreamNotification(
130+
item: StreamInfoItem,
131+
serviceId: Int,
132+
channelIcon: Bitmap?
133+
): Notification {
134+
return NotificationCompat.Builder(
135+
context,
136+
context.getString(R.string.streams_notification_channel_id)
137+
)
138+
.setSmallIcon(R.drawable.ic_newpipe_triangle_white)
139+
.setLargeIcon(channelIcon)
140+
.setContentTitle(item.name)
141+
.setContentText(item.uploaderName)
142+
.setGroup(item.uploaderUrl)
143+
.setColor(ContextCompat.getColor(context, R.color.ic_launcher_background))
144+
.setColorized(true)
145+
.setAutoCancel(true)
146+
.setCategory(NotificationCompat.CATEGORY_SOCIAL)
147+
.setContentIntent(
148+
// Open the stream link in the player when clicking on the notification.
149+
PendingIntentCompat.getActivity(
150+
context,
151+
item.url.hashCode(),
152+
NavigationHelper.getStreamIntent(context, serviceId, item.url, item.name),
153+
PendingIntent.FLAG_UPDATE_CURRENT,
154+
false
155+
)
156+
)
157+
.setSilent(true) // Avoid creating noise for individual stream notifications.
158+
.build()
159+
}
160+
109161
companion object {
110162
/**
111163
* Check whether notifications are enabled on the device.
@@ -124,9 +176,7 @@ class NotificationHelper(val context: Context) {
124176
fun areNotificationsEnabledOnDevice(context: Context): Boolean {
125177
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
126178
val channelId = context.getString(R.string.streams_notification_channel_id)
127-
val manager = context.getSystemService(
128-
Context.NOTIFICATION_SERVICE
129-
) as NotificationManager
179+
val manager = context.getSystemService<NotificationManager>()!!
130180
val enabled = manager.areNotificationsEnabled()
131181
val channel = manager.getNotificationChannel(channelId)
132182
val importance = channel?.importance

app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class NotificationWorker(
5555
.map { feedUpdateInfoList ->
5656
// display notifications for each feedUpdateInfo (i.e. channel)
5757
feedUpdateInfoList.forEach { feedUpdateInfo ->
58-
notificationHelper.displayNewStreamsNotification(feedUpdateInfo)
58+
notificationHelper.displayNewStreamsNotifications(feedUpdateInfo)
5959
}
6060
return@map Result.success()
6161
}

app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -563,11 +563,8 @@ public static void openVideoDetail(final Context context,
563563
@Nullable final PlayQueue playQueue,
564564
final boolean switchingPlayers) {
565565

566-
final Intent intent = getOpenIntent(context, url, serviceId,
567-
StreamingService.LinkType.STREAM);
568-
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
569-
intent.putExtra(Constants.KEY_TITLE, title);
570-
intent.putExtra(VideoDetailFragment.KEY_SWITCHING_PLAYERS, switchingPlayers);
566+
final Intent intent = getStreamIntent(context, serviceId, url, title)
567+
.putExtra(VideoDetailFragment.KEY_SWITCHING_PLAYERS, switchingPlayers);
571568

572569
if (playQueue != null) {
573570
final String cacheKey = SerializedCache.getInstance().put(playQueue, PlayQueue.class);
@@ -680,6 +677,15 @@ public static Intent getChannelIntent(final Context context,
680677
return getOpenIntent(context, url, serviceId, StreamingService.LinkType.CHANNEL);
681678
}
682679

680+
public static Intent getStreamIntent(final Context context,
681+
final int serviceId,
682+
final String url,
683+
@Nullable final String title) {
684+
return getOpenIntent(context, url, serviceId, StreamingService.LinkType.STREAM)
685+
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
686+
.putExtra(Constants.KEY_TITLE, title);
687+
}
688+
683689
/**
684690
* Finish this <code>Activity</code> as well as all <code>Activities</code> running below it
685691
* and then start <code>MainActivity</code>.
205 Bytes
Loading
210 Bytes
Loading
366 Bytes
Loading
372 Bytes
Loading
702 Bytes
Loading

0 commit comments

Comments
 (0)