supports grouped notification channels
This commit is contained in:
parent
1d81c8cdf8
commit
c21e6ebcb5
|
@ -6,7 +6,7 @@ buildscript {
|
|||
maven { url 'https://maven.google.com' }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.0-beta2'
|
||||
classpath 'com.android.tools.build:gradle:3.0.0-beta3'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
|||
}
|
||||
super.onCreate()
|
||||
EmojioneTranslator.init(this)
|
||||
NotificationChannelsManager.createChannels(this)
|
||||
NotificationChannelsManager.initialize(this)
|
||||
applyLanguageSettings()
|
||||
startKovenant()
|
||||
initializeAsyncTask()
|
||||
|
@ -159,8 +159,11 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
|||
|
||||
Analyzer.preferencesChanged(sharedPreferences)
|
||||
DataSyncProvider.Factory.notifyUpdate(this)
|
||||
|
||||
NotificationChannelsManager.updateAccountChannelsAndGroups(this)
|
||||
}
|
||||
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration?) {
|
||||
applyLanguageSettings()
|
||||
super.onConfigurationChanged(newConfig)
|
||||
|
@ -336,6 +339,10 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
|||
})
|
||||
}
|
||||
|
||||
private fun updateAccountNotificationGroup() {
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val KEY_UCD_DATA_PROFILING = "ucd_data_profiling"
|
||||
|
|
|
@ -20,12 +20,24 @@
|
|||
package org.mariotaku.twidere.extension.model
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.support.v4.app.NotificationCompat
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.notification.NotificationChannelSpec
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/8/25.
|
||||
*/
|
||||
fun NotificationChannelSpec.notificationBuilder(context: Context): NotificationCompat.Builder {
|
||||
return NotificationCompat.Builder(context, id)
|
||||
}
|
||||
|
||||
fun NotificationChannelSpec.accountNotificationBuilder(context: Context, accountKey: UserKey): NotificationCompat.Builder {
|
||||
if (!grouped) throw IllegalArgumentException("Requires grouped channel")
|
||||
return NotificationCompat.Builder(context, accountKey.notificationChannelId(id)).setGroup(accountKey.notificationChannelGroupId())
|
||||
}
|
||||
|
||||
fun UserKey.notificationChannelId(id: String): String {
|
||||
return "${id}_${Uri.encode(toString())}"
|
||||
}
|
||||
|
||||
fun UserKey.notificationChannelGroupId(): String {
|
||||
return Uri.encode(toString())
|
||||
}
|
|
@ -31,7 +31,8 @@ enum class NotificationChannelSpec(
|
|||
@StringRes val nameRes: Int,
|
||||
@StringRes val descriptionRes: Int = 0,
|
||||
val importance: Int,
|
||||
val showBadge: Boolean = false) {
|
||||
val showBadge: Boolean = false,
|
||||
val grouped: Boolean = false) {
|
||||
/**
|
||||
* For notifications send by app itself.
|
||||
* Such as "what's new"
|
||||
|
@ -53,37 +54,31 @@ enum class NotificationChannelSpec(
|
|||
serviceStatuses("service_statuses", R.string.notification_channel_name_service_statuses,
|
||||
importance = NotificationManager.IMPORTANCE_MIN),
|
||||
|
||||
/**
|
||||
* For import notifications related to micro-blogging features.
|
||||
* Such as failure to update status.
|
||||
*/
|
||||
contentNotices("content_notices", R.string.notification_channel_name_content_notices,
|
||||
importance = NotificationManager.IMPORTANCE_HIGH, showBadge = true),
|
||||
/**
|
||||
* For updates related to micro-blogging features.
|
||||
* Such as new statuses posted by friends.
|
||||
*/
|
||||
contentUpdates("content_updates", R.string.notification_channel_name_content_updates,
|
||||
importance = NotificationManager.IMPORTANCE_DEFAULT, showBadge = true),
|
||||
importance = NotificationManager.IMPORTANCE_DEFAULT, showBadge = true, grouped = true),
|
||||
/**
|
||||
* For updates related to micro-blogging features.
|
||||
* Such as new statuses posted by friends user subscribed to.
|
||||
*/
|
||||
contentSubscriptions("content_subscriptions", R.string.notification_channel_name_content_subscriptions,
|
||||
importance = NotificationManager.IMPORTANCE_HIGH, showBadge = true),
|
||||
importance = NotificationManager.IMPORTANCE_HIGH, showBadge = true, grouped = true),
|
||||
/**
|
||||
* For interactions related to micro-blogging features.
|
||||
* Such as replies and likes.
|
||||
*/
|
||||
contentInteractions("content_interactions", R.string.notification_channel_name_content_interactions,
|
||||
descriptionRes = R.string.notification_channel_description_content_interactions,
|
||||
importance = NotificationManager.IMPORTANCE_HIGH, showBadge = true),
|
||||
importance = NotificationManager.IMPORTANCE_HIGH, showBadge = true, grouped = true),
|
||||
/**
|
||||
* For messages related to micro-blogging features.
|
||||
* Such as direct messages.
|
||||
*/
|
||||
contentMessages("content_messages", R.string.notification_channel_name_content_messages,
|
||||
descriptionRes = R.string.notification_channel_description_content_messages,
|
||||
importance = NotificationManager.IMPORTANCE_HIGH, showBadge = true)
|
||||
importance = NotificationManager.IMPORTANCE_HIGH, showBadge = true, grouped = true)
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.util.notification
|
||||
|
||||
import android.accounts.AccountManager
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
|
@ -45,14 +46,12 @@ import org.mariotaku.twidere.annotation.NotificationType
|
|||
import org.mariotaku.twidere.constant.IntentConstants
|
||||
import org.mariotaku.twidere.constant.iWantMyStarsBackKey
|
||||
import org.mariotaku.twidere.constant.nameFirstKey
|
||||
import org.mariotaku.twidere.extension.model.*
|
||||
import org.mariotaku.twidere.extension.model.api.formattedTextWithIndices
|
||||
import org.mariotaku.twidere.extension.model.getSummaryText
|
||||
import org.mariotaku.twidere.extension.model.getTitle
|
||||
import org.mariotaku.twidere.extension.model.notificationBuilder
|
||||
import org.mariotaku.twidere.extension.model.notificationDisabled
|
||||
import org.mariotaku.twidere.extension.rawQuery
|
||||
import org.mariotaku.twidere.model.*
|
||||
import org.mariotaku.twidere.model.notification.NotificationChannelSpec
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
import org.mariotaku.twidere.model.util.ParcelableActivityUtils
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
|
||||
|
@ -135,7 +134,8 @@ class ContentNotificationManager(
|
|||
}
|
||||
|
||||
// Setup notification
|
||||
val builder = NotificationChannelSpec.contentUpdates.notificationBuilder(context)
|
||||
val builder = NotificationChannelSpec.contentUpdates.accountNotificationBuilder(context,
|
||||
accountKey)
|
||||
builder.setAutoCancel(true)
|
||||
builder.setSmallIcon(R.drawable.ic_stat_twitter)
|
||||
builder.setTicker(notificationTitle)
|
||||
|
@ -148,7 +148,6 @@ class ContentNotificationManager(
|
|||
accountKey, positionKey, false))
|
||||
builder.setNumber(statusesCount)
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL)
|
||||
builder.setGroup("timeline")
|
||||
applyNotificationPreferences(builder, pref, pref.homeTimelineNotificationType)
|
||||
try {
|
||||
val notificationId = Utils.getNotificationId(NOTIFICATION_ID_HOME_TIMELINE, accountKey)
|
||||
|
@ -165,8 +164,10 @@ class ContentNotificationManager(
|
|||
}
|
||||
|
||||
fun showInteractions(pref: AccountPreferences, position: Long) {
|
||||
val am = AccountManager.get(context)
|
||||
val cr = context.contentResolver
|
||||
val accountKey = pref.accountKey
|
||||
val account = AccountUtils.getAccountDetails(am, accountKey, false) ?: return
|
||||
val where = Expression.and(
|
||||
Expression.equalsArgs(Activities.ACCOUNT_KEY),
|
||||
Expression.greaterThan(Activities.POSITION_KEY, position),
|
||||
|
@ -176,7 +177,8 @@ class ContentNotificationManager(
|
|||
@SuppressLint("Recycle")
|
||||
val c = cr.query(Activities.AboutMe.CONTENT_URI, Activities.COLUMNS, where, whereArgs,
|
||||
OrderBy(Activities.TIMESTAMP, false).sql) ?: return
|
||||
val builder = NotificationChannelSpec.contentInteractions.notificationBuilder(context)
|
||||
val builder = NotificationChannelSpec.contentInteractions.accountNotificationBuilder(context,
|
||||
accountKey)
|
||||
val pebbleNotificationStringBuilder = StringBuilder()
|
||||
try {
|
||||
val count = c.count
|
||||
|
@ -186,7 +188,7 @@ class ContentNotificationManager(
|
|||
applyNotificationPreferences(builder, pref, pref.mentionsNotificationType)
|
||||
|
||||
val resources = context.resources
|
||||
val accountName = DataStoreUtils.getAccountDisplayName(context, accountKey, nameFirst)
|
||||
val accountName = userColorNameManager.getDisplayName(account.user, nameFirst)
|
||||
builder.setContentText(accountName)
|
||||
val style = NotificationCompat.InboxStyle()
|
||||
builder.setStyle(style)
|
||||
|
@ -246,7 +248,6 @@ class ContentNotificationManager(
|
|||
builder.setContentTitle(title)
|
||||
style.setBigContentTitle(title)
|
||||
builder.setNumber(displayCount)
|
||||
builder.setGroup("interactions")
|
||||
builder.setContentIntent(getContentIntent(context, CustomTabType.NOTIFICATIONS_TIMELINE,
|
||||
NotificationType.INTERACTIONS, accountKey, newMaxPositionKey))
|
||||
builder.setDeleteIntent(getMarkReadDeleteIntent(context, NotificationType.INTERACTIONS,
|
||||
|
@ -289,7 +290,8 @@ class ContentNotificationManager(
|
|||
}
|
||||
if (messageSum == 0) return
|
||||
|
||||
val builder = NotificationChannelSpec.contentMessages.notificationBuilder(context)
|
||||
val builder = NotificationChannelSpec.contentMessages.accountNotificationBuilder(context,
|
||||
accountKey)
|
||||
applyNotificationPreferences(builder, pref, pref.directMessagesNotificationType)
|
||||
builder.setSmallIcon(R.drawable.ic_stat_message)
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL)
|
||||
|
@ -324,7 +326,6 @@ class ContentNotificationManager(
|
|||
style.addLine(context.getString(R.string.and_N_more, remaining))
|
||||
}
|
||||
val notificationId = Utils.getNotificationId(NOTIFICATION_ID_DIRECT_MESSAGES, accountKey)
|
||||
builder.setGroup("direct_messages")
|
||||
notificationManager.notify("direct_messages", notificationId, builder.build())
|
||||
} finally {
|
||||
cur.close()
|
||||
|
@ -337,7 +338,8 @@ class ContentNotificationManager(
|
|||
val userDisplayName = userColorNameManager.getDisplayName(status.user,
|
||||
preferences[nameFirstKey])
|
||||
val statusUri = LinkCreator.getTwidereStatusLink(accountKey, status.id)
|
||||
val builder = NotificationChannelSpec.contentSubscriptions.notificationBuilder(context)
|
||||
val builder = NotificationChannelSpec.contentSubscriptions.accountNotificationBuilder(context,
|
||||
accountKey)
|
||||
builder.color = userColorNameManager.getUserColor(userKey)
|
||||
builder.setAutoCancel(true)
|
||||
builder.setWhen(status.createdAt?.time ?: 0)
|
||||
|
@ -355,7 +357,6 @@ class ContentNotificationManager(
|
|||
}, PendingIntent.FLAG_UPDATE_CURRENT))
|
||||
|
||||
val tag = "$accountKey:$userKey:${status.id}"
|
||||
builder.setGroup("user_notif_$accountKey:$userKey")
|
||||
notificationManager.notify(tag, NOTIFICATION_ID_USER_NOTIFICATION, builder.build())
|
||||
}
|
||||
|
||||
|
@ -382,7 +383,7 @@ class ContentNotificationManager(
|
|||
uriBuilder.scheme(SCHEME_TWIDERE)
|
||||
uriBuilder.authority(AUTHORITY_DRAFTS)
|
||||
intent.data = uriBuilder.build()
|
||||
val nb = NotificationChannelSpec.contentNotices.notificationBuilder(context)
|
||||
val nb = NotificationChannelSpec.appNotices.notificationBuilder(context)
|
||||
nb.setTicker(message)
|
||||
nb.setContentTitle(title)
|
||||
nb.setContentText(item.text)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.util.notification
|
||||
|
||||
import android.accounts.AccountManager
|
||||
import android.annotation.TargetApi
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationChannelGroup
|
||||
|
@ -27,53 +28,102 @@ import android.content.Context
|
|||
import android.os.Build
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.twidere.constant.nameFirstKey
|
||||
import org.mariotaku.twidere.model.AccountDetails
|
||||
import org.mariotaku.twidere.extension.model.notificationChannelGroupId
|
||||
import org.mariotaku.twidere.extension.model.notificationChannelId
|
||||
import org.mariotaku.twidere.model.notification.NotificationChannelSpec
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
import org.mariotaku.twidere.util.dagger.DependencyHolder
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/8/25.
|
||||
*/
|
||||
object NotificationChannelsManager {
|
||||
fun createChannels(context: Context) {
|
||||
|
||||
fun initialize(context: Context) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
|
||||
NotificationChannelCreatorImpl.createChannels(context)
|
||||
NotificationChannelManagerImpl.initialize(context)
|
||||
}
|
||||
|
||||
fun createAccountGroup(context: Context, account: AccountDetails) {
|
||||
fun updateAccountChannelsAndGroups(context: Context) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
|
||||
NotificationChannelCreatorImpl.createAccountGroup(context, account)
|
||||
NotificationChannelManagerImpl.updateAccountChannelsAndGroups(context)
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
private object NotificationChannelCreatorImpl {
|
||||
private object NotificationChannelManagerImpl {
|
||||
|
||||
fun createChannels(context: Context) {
|
||||
fun initialize(context: Context) {
|
||||
val nm = context.getSystemService(NotificationManager::class.java)
|
||||
val values = NotificationChannelSpec.values()
|
||||
nm.notificationChannels.filterNot { channel ->
|
||||
values.any { channel.id == it.id }
|
||||
}.forEach {
|
||||
nm.deleteNotificationChannel(it.id)
|
||||
}
|
||||
for (spec in values) {
|
||||
|
||||
val addedChannels = mutableListOf<String>()
|
||||
|
||||
for (spec in NotificationChannelSpec.values()) {
|
||||
if (spec.grouped) continue
|
||||
val channel = NotificationChannel(spec.id, context.getString(spec.nameRes), spec.importance)
|
||||
|
||||
if (spec.descriptionRes != 0) {
|
||||
channel.description = context.getString(spec.descriptionRes)
|
||||
}
|
||||
channel.setShowBadge(spec.showBadge)
|
||||
nm.createNotificationChannel(channel)
|
||||
addedChannels.add(channel.id)
|
||||
}
|
||||
|
||||
nm.notificationChannels.forEach {
|
||||
if (it.id !in addedChannels && it.group == null) {
|
||||
nm.deleteNotificationChannel(it.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createAccountGroup(context: Context, account: AccountDetails) {
|
||||
val nm = context.getSystemService(NotificationManager::class.java)
|
||||
fun updateAccountChannelsAndGroups(context: Context) {
|
||||
val holder = DependencyHolder.get(context)
|
||||
|
||||
val am = AccountManager.get(context)
|
||||
val nm = context.getSystemService(NotificationManager::class.java)
|
||||
val pref = holder.preferences
|
||||
val ucnm = holder.userColorNameManager
|
||||
val group = NotificationChannelGroup(account.key.toString(),
|
||||
ucnm.getDisplayName(account.user, pref[nameFirstKey]))
|
||||
nm.createNotificationChannelGroup(group)
|
||||
|
||||
val accounts = AccountUtils.getAllAccountDetails(am, false)
|
||||
val specs = NotificationChannelSpec.values()
|
||||
|
||||
val addedChannels = mutableListOf<String>()
|
||||
val addedGroups = mutableListOf<String>()
|
||||
|
||||
accounts.forEach { account ->
|
||||
val group = NotificationChannelGroup(account.key.notificationChannelGroupId(),
|
||||
ucnm.getDisplayName(account.user, pref[nameFirstKey]))
|
||||
|
||||
addedGroups.add(group.id)
|
||||
nm.createNotificationChannelGroup(group)
|
||||
|
||||
for (spec in specs) {
|
||||
if (!spec.grouped) continue
|
||||
val channel = NotificationChannel(account.key.notificationChannelId(spec.id),
|
||||
context.getString(spec.nameRes), spec.importance)
|
||||
|
||||
if (spec.descriptionRes != 0) {
|
||||
channel.description = context.getString(spec.descriptionRes)
|
||||
}
|
||||
channel.group = group.id
|
||||
channel.setShowBadge(spec.showBadge)
|
||||
nm.createNotificationChannel(channel)
|
||||
addedChannels.add(channel.id)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Delete all channels and groups of non-existing accounts
|
||||
nm.notificationChannels.forEach {
|
||||
if (it.id !in addedChannels && it.group != null) {
|
||||
nm.deleteNotificationChannel(it.id)
|
||||
}
|
||||
}
|
||||
nm.notificationChannelGroups.forEach {
|
||||
if (it.id !in addedGroups) {
|
||||
nm.deleteNotificationChannelGroup(it.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -774,11 +774,10 @@
|
|||
<string name="notification_channel_description_content_messages">Important messages like DMs</string>
|
||||
<string name="notification_channel_name_app_notices">App notices</string>
|
||||
<string name="notification_channel_name_background_progresses">Background operations</string>
|
||||
<string name="notification_channel_name_content_interactions">Content interactions</string>
|
||||
<string name="notification_channel_name_content_messages">Content messages</string>
|
||||
<string name="notification_channel_name_content_notices">Content notices</string>
|
||||
<string name="notification_channel_name_content_subscriptions">Content subscriptions</string>
|
||||
<string name="notification_channel_name_content_updates">Content updates</string>
|
||||
<string name="notification_channel_name_content_interactions">Interactions</string>
|
||||
<string name="notification_channel_name_content_messages">Messages</string>
|
||||
<string name="notification_channel_name_content_subscriptions">Subscriptions</string>
|
||||
<string name="notification_channel_name_content_updates">Updates</string>
|
||||
<string name="notification_channel_name_service_statuses">Service statuses</string>
|
||||
<string name="notification_direct_message"><xliff:g id="user">%s</xliff:g> sent you a direct message.</string>
|
||||
<string name="notification_direct_message_multiple_messages"><xliff:g id="user">%1$s</xliff:g> sent you <xliff:g id="messages_count">%2$d</xliff:g> direct messages.</string>
|
||||
|
|
Loading…
Reference in New Issue