Fix push notifications in Android 12
This commit is contained in:
parent
d513de70c4
commit
3e140825f5
2 changed files with 131 additions and 108 deletions
|
@ -1,21 +1,28 @@
|
||||||
/* Copyright 2018 Jeremiasz Nelz <remi6397(a)gmail.com>
|
/*
|
||||||
* Copyright 2017 Andrew Dawson
|
* Husky -- A Pleroma client for Android
|
||||||
*
|
*
|
||||||
* This file is a part of Tusky.
|
* Copyright (C) 2022 The Husky Developers
|
||||||
|
* Copyright (C) 2022 Conny Duck
|
||||||
|
* Copyright (C) 2018 Jeremiasz Nelz <remi6397(a)gmail.com>
|
||||||
|
* Copyright (C) 2017 Andrew Dawson
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
* it under the terms of the GNU General Public License as published by
|
||||||
* License, or (at your option) any later version.
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
* This program is distributed in the hope that it will be useful,
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* Public License for more details.
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
* You should have received a copy of the GNU General Public License
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.keylesspalace.tusky.components.notifications;
|
package com.keylesspalace.tusky.components.notifications;
|
||||||
|
|
||||||
|
import static com.keylesspalace.tusky.viewdata.PollViewDataKt.buildDescription;
|
||||||
import android.app.NotificationChannel;
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationChannelGroup;
|
import android.app.NotificationChannelGroup;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
|
@ -28,8 +35,6 @@ import android.graphics.Color;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
|
@ -42,7 +47,6 @@ import androidx.work.NetworkType;
|
||||||
import androidx.work.PeriodicWorkRequest;
|
import androidx.work.PeriodicWorkRequest;
|
||||||
import androidx.work.WorkManager;
|
import androidx.work.WorkManager;
|
||||||
import androidx.work.WorkRequest;
|
import androidx.work.WorkRequest;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
import com.bumptech.glide.request.FutureTarget;
|
import com.bumptech.glide.request.FutureTarget;
|
||||||
|
@ -51,7 +55,6 @@ import com.keylesspalace.tusky.MainActivity;
|
||||||
import com.keylesspalace.tusky.R;
|
import com.keylesspalace.tusky.R;
|
||||||
import com.keylesspalace.tusky.db.AccountEntity;
|
import com.keylesspalace.tusky.db.AccountEntity;
|
||||||
import com.keylesspalace.tusky.db.AccountManager;
|
import com.keylesspalace.tusky.db.AccountManager;
|
||||||
import com.keylesspalace.tusky.entity.ChatMessage;
|
|
||||||
import com.keylesspalace.tusky.entity.Notification;
|
import com.keylesspalace.tusky.entity.Notification;
|
||||||
import com.keylesspalace.tusky.entity.Poll;
|
import com.keylesspalace.tusky.entity.Poll;
|
||||||
import com.keylesspalace.tusky.entity.PollOption;
|
import com.keylesspalace.tusky.entity.PollOption;
|
||||||
|
@ -60,21 +63,17 @@ import com.keylesspalace.tusky.receiver.NotificationClearBroadcastReceiver;
|
||||||
import com.keylesspalace.tusky.receiver.SendStatusBroadcastReceiver;
|
import com.keylesspalace.tusky.receiver.SendStatusBroadcastReceiver;
|
||||||
import com.keylesspalace.tusky.util.StringUtils;
|
import com.keylesspalace.tusky.util.StringUtils;
|
||||||
import com.keylesspalace.tusky.viewdata.PollViewDataKt;
|
import com.keylesspalace.tusky.viewdata.PollViewDataKt;
|
||||||
|
import io.reactivex.Single;
|
||||||
import org.json.JSONArray;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import org.json.JSONException;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.json.JSONArray;
|
||||||
import io.reactivex.Single;
|
import org.json.JSONException;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import timber.log.Timber;
|
||||||
|
|
||||||
import static com.keylesspalace.tusky.viewdata.PollViewDataKt.buildDescription;
|
|
||||||
|
|
||||||
public class NotificationHelper {
|
public class NotificationHelper {
|
||||||
|
|
||||||
|
@ -154,18 +153,18 @@ public class NotificationHelper {
|
||||||
public static void make(final Context context, Notification body, AccountEntity account, boolean isFirstOfBatch) {
|
public static void make(final Context context, Notification body, AccountEntity account, boolean isFirstOfBatch) {
|
||||||
body = Notification.rewriteToStatusTypeIfNeeded(body, account.getAccountId());
|
body = Notification.rewriteToStatusTypeIfNeeded(body, account.getAccountId());
|
||||||
|
|
||||||
if (!filterNotification(account, body, context)) {
|
if(!filterNotification(account, body, context)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pleroma extension: don't notify about seen notifications
|
// Pleroma extension: don't notify about seen notifications
|
||||||
if (body.getPleroma() != null && body.getPleroma().getSeen()) {
|
if(body.getPleroma() != null && body.getPleroma().getSeen()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body.getStatus() != null &&
|
if(body.getStatus() != null &&
|
||||||
(body.getStatus().isUserMuted() ||
|
(body.getStatus().isUserMuted() ||
|
||||||
body.getStatus().isThreadMuted())) {
|
body.getStatus().isThreadMuted())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,18 +173,18 @@ public class NotificationHelper {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
currentNotifications = new JSONArray(rawCurrentNotifications);
|
currentNotifications = new JSONArray(rawCurrentNotifications);
|
||||||
} catch (JSONException e) {
|
} catch(JSONException e) {
|
||||||
currentNotifications = new JSONArray();
|
currentNotifications = new JSONArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < currentNotifications.length(); i++) {
|
for(int i = 0; i < currentNotifications.length(); i++) {
|
||||||
try {
|
try {
|
||||||
if (currentNotifications.getString(i).equals(body.getAccount().getName())) {
|
if(currentNotifications.getString(i).equals(body.getAccount().getName())) {
|
||||||
currentNotifications.remove(i);
|
currentNotifications.remove(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (JSONException e) {
|
} catch(JSONException e) {
|
||||||
Log.d(TAG, Log.getStackTraceString(e));
|
Timber.e(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +201,7 @@ public class NotificationHelper {
|
||||||
builder.setContentTitle(titleForType(context, body, account))
|
builder.setContentTitle(titleForType(context, body, account))
|
||||||
.setContentText(bodyForType(body, context));
|
.setContentText(bodyForType(body, context));
|
||||||
|
|
||||||
if (body.getType() == Notification.Type.MENTION || body.getType() == Notification.Type.POLL) {
|
if(body.getType() == Notification.Type.MENTION || body.getType() == Notification.Type.POLL) {
|
||||||
builder.setStyle(new NotificationCompat.BigTextStyle()
|
builder.setStyle(new NotificationCompat.BigTextStyle()
|
||||||
.bigText(bodyForType(body, context)));
|
.bigText(bodyForType(body, context)));
|
||||||
}
|
}
|
||||||
|
@ -217,8 +216,8 @@ public class NotificationHelper {
|
||||||
.submit();
|
.submit();
|
||||||
|
|
||||||
accountAvatar = target.get();
|
accountAvatar = target.get();
|
||||||
} catch (ExecutionException | InterruptedException e) {
|
} catch(ExecutionException | InterruptedException e) {
|
||||||
Log.d(TAG, "error loading account avatar", e);
|
Timber.e("Error loading account avatar %s", e);
|
||||||
accountAvatar = BitmapFactory.decodeResource(context.getResources(), R.drawable.avatar_default);
|
accountAvatar = BitmapFactory.decodeResource(context.getResources(), R.drawable.avatar_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,14 +279,14 @@ public class NotificationHelper {
|
||||||
// =======
|
// =======
|
||||||
final NotificationCompat.Builder summaryBuilder = newNotification(context, body, account, true);
|
final NotificationCompat.Builder summaryBuilder = newNotification(context, body, account, true);
|
||||||
|
|
||||||
if (currentNotifications.length() != 1) {
|
if(currentNotifications.length() != 1) {
|
||||||
try {
|
try {
|
||||||
String title = context.getString(R.string.notification_title_summary, currentNotifications.length());
|
String title = context.getString(R.string.notification_title_summary, currentNotifications.length());
|
||||||
String text = joinNames(context, currentNotifications);
|
String text = joinNames(context, currentNotifications);
|
||||||
summaryBuilder.setContentTitle(title)
|
summaryBuilder.setContentTitle(title)
|
||||||
.setContentText(text);
|
.setContentText(text);
|
||||||
} catch (JSONException e) {
|
} catch(JSONException e) {
|
||||||
Log.d(TAG, Log.getStackTraceString(e));
|
Timber.e(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +299,7 @@ public class NotificationHelper {
|
||||||
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
||||||
|
|
||||||
notificationManager.notify(notificationId, builder.build());
|
notificationManager.notify(notificationId, builder.build());
|
||||||
if (currentNotifications.length() == 1) {
|
if(currentNotifications.length() == 1) {
|
||||||
notificationManager.notify((int) account.getId(), builder.setGroupSummary(true).build());
|
notificationManager.notify((int) account.getId(), builder.setGroupSummary(true).build());
|
||||||
} else {
|
} else {
|
||||||
notificationManager.notify((int) account.getId(), summaryBuilder.build());
|
notificationManager.notify((int) account.getId(), summaryBuilder.build());
|
||||||
|
@ -314,8 +313,10 @@ public class NotificationHelper {
|
||||||
summaryStackBuilder.addParentStack(MainActivity.class);
|
summaryStackBuilder.addParentStack(MainActivity.class);
|
||||||
summaryStackBuilder.addNextIntent(summaryResultIntent);
|
summaryStackBuilder.addNextIntent(summaryResultIntent);
|
||||||
|
|
||||||
PendingIntent summaryResultPendingIntent = summaryStackBuilder.getPendingIntent((int) (notificationId + account.getId() * 10000),
|
PendingIntent summaryResultPendingIntent = summaryStackBuilder.getPendingIntent(
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
(int) (notificationId + account.getId() * 10000),
|
||||||
|
pendingIntentFlags(false)
|
||||||
|
);
|
||||||
|
|
||||||
// we have to switch account here
|
// we have to switch account here
|
||||||
Intent eventResultIntent = new Intent(context, MainActivity.class);
|
Intent eventResultIntent = new Intent(context, MainActivity.class);
|
||||||
|
@ -324,13 +325,16 @@ public class NotificationHelper {
|
||||||
eventStackBuilder.addParentStack(MainActivity.class);
|
eventStackBuilder.addParentStack(MainActivity.class);
|
||||||
eventStackBuilder.addNextIntent(eventResultIntent);
|
eventStackBuilder.addNextIntent(eventResultIntent);
|
||||||
|
|
||||||
PendingIntent eventResultPendingIntent = eventStackBuilder.getPendingIntent((int) account.getId(),
|
PendingIntent eventResultPendingIntent = eventStackBuilder.getPendingIntent(
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
(int) account.getId(),
|
||||||
|
pendingIntentFlags(false));
|
||||||
|
|
||||||
Intent deleteIntent = new Intent(context, NotificationClearBroadcastReceiver.class);
|
Intent deleteIntent = new Intent(context, NotificationClearBroadcastReceiver.class);
|
||||||
deleteIntent.putExtra(ACCOUNT_ID, account.getId());
|
deleteIntent.putExtra(ACCOUNT_ID, account.getId());
|
||||||
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, summary ? (int) account.getId() : notificationId, deleteIntent,
|
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
context, summary ? (int) account.getId() : notificationId,
|
||||||
|
deleteIntent,
|
||||||
|
pendingIntentFlags(false));
|
||||||
|
|
||||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, getChannelId(account, body))
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, getChannelId(account, body))
|
||||||
.setSmallIcon(R.drawable.ic_notify)
|
.setSmallIcon(R.drawable.ic_notify)
|
||||||
|
@ -349,11 +353,11 @@ public class NotificationHelper {
|
||||||
|
|
||||||
private static PendingIntent getStatusReplyIntent(String action, Context context, Notification body, AccountEntity account) {
|
private static PendingIntent getStatusReplyIntent(String action, Context context, Notification body, AccountEntity account) {
|
||||||
Intent replyIntent = new Intent(context, SendStatusBroadcastReceiver.class)
|
Intent replyIntent = new Intent(context, SendStatusBroadcastReceiver.class)
|
||||||
.setAction(action)
|
.setAction(action)
|
||||||
.putExtra(KEY_SENDER_ACCOUNT_ID, account.getId())
|
.putExtra(KEY_SENDER_ACCOUNT_ID, account.getId())
|
||||||
.putExtra(KEY_SENDER_ACCOUNT_IDENTIFIER, account.getIdentifier())
|
.putExtra(KEY_SENDER_ACCOUNT_IDENTIFIER, account.getIdentifier())
|
||||||
.putExtra(KEY_SENDER_ACCOUNT_FULL_NAME, account.getFullName())
|
.putExtra(KEY_SENDER_ACCOUNT_FULL_NAME, account.getFullName())
|
||||||
.putExtra(KEY_NOTIFICATION_ID, notificationId);
|
.putExtra(KEY_NOTIFICATION_ID, notificationId);
|
||||||
|
|
||||||
if(action == CHAT_REPLY_ACTION) {
|
if(action == CHAT_REPLY_ACTION) {
|
||||||
replyIntent.putExtra(KEY_CHAT_ID, body.getChatMessage().getChatId());
|
replyIntent.putExtra(KEY_CHAT_ID, body.getChatMessage().getChatId());
|
||||||
|
@ -369,7 +373,7 @@ public class NotificationHelper {
|
||||||
Status.Mention[] mentions = actionableStatus.getMentions();
|
Status.Mention[] mentions = actionableStatus.getMentions();
|
||||||
List<String> mentionedUsernames = new ArrayList<>();
|
List<String> mentionedUsernames = new ArrayList<>();
|
||||||
mentionedUsernames.add(actionableStatus.getAccount().getUsername());
|
mentionedUsernames.add(actionableStatus.getAccount().getUsername());
|
||||||
for (Status.Mention mention : mentions) {
|
for(Status.Mention mention : mentions) {
|
||||||
mentionedUsernames.add(mention.getUsername());
|
mentionedUsernames.add(mention.getUsername());
|
||||||
}
|
}
|
||||||
mentionedUsernames.removeAll(Collections.singleton(account.getUsername()));
|
mentionedUsernames.removeAll(Collections.singleton(account.getUsername()));
|
||||||
|
@ -386,12 +390,11 @@ public class NotificationHelper {
|
||||||
return PendingIntent.getBroadcast(context.getApplicationContext(),
|
return PendingIntent.getBroadcast(context.getApplicationContext(),
|
||||||
notificationId,
|
notificationId,
|
||||||
replyIntent,
|
replyIntent,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
pendingIntentFlags(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createNotificationChannelsForAccount(@NonNull AccountEntity account, @NonNull Context context) {
|
public static void createNotificationChannelsForAccount(@NonNull AccountEntity account, @NonNull Context context) {
|
||||||
if (NOTIFICATION_USE_CHANNELS) {
|
if(NOTIFICATION_USE_CHANNELS) {
|
||||||
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
String[] channelIds = new String[]{
|
String[] channelIds = new String[]{
|
||||||
|
@ -406,6 +409,7 @@ public class NotificationHelper {
|
||||||
CHANNEL_SUBSCRIPTIONS + account.getIdentifier(),
|
CHANNEL_SUBSCRIPTIONS + account.getIdentifier(),
|
||||||
CHANNEL_MOVE + account.getIdentifier()
|
CHANNEL_MOVE + account.getIdentifier()
|
||||||
};
|
};
|
||||||
|
|
||||||
int[] channelNames = {
|
int[] channelNames = {
|
||||||
R.string.notification_mention_name,
|
R.string.notification_mention_name,
|
||||||
R.string.notification_follow_name,
|
R.string.notification_follow_name,
|
||||||
|
@ -418,6 +422,7 @@ public class NotificationHelper {
|
||||||
R.string.notification_subscription_name,
|
R.string.notification_subscription_name,
|
||||||
R.string.notification_move_name
|
R.string.notification_move_name
|
||||||
};
|
};
|
||||||
|
|
||||||
int[] channelDescriptions = {
|
int[] channelDescriptions = {
|
||||||
R.string.notification_mention_descriptions,
|
R.string.notification_mention_descriptions,
|
||||||
R.string.notification_follow_description,
|
R.string.notification_follow_description,
|
||||||
|
@ -438,7 +443,7 @@ public class NotificationHelper {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
notificationManager.createNotificationChannelGroup(channelGroup);
|
notificationManager.createNotificationChannelGroup(channelGroup);
|
||||||
|
|
||||||
for (int i = 0; i < channelIds.length; i++) {
|
for(int i = 0; i < channelIds.length; i++) {
|
||||||
String id = channelIds[i];
|
String id = channelIds[i];
|
||||||
String name = context.getString(channelNames[i]);
|
String name = context.getString(channelNames[i]);
|
||||||
String description = context.getString(channelDescriptions[i]);
|
String description = context.getString(channelDescriptions[i]);
|
||||||
|
@ -455,24 +460,20 @@ public class NotificationHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
notificationManager.createNotificationChannels(channels);
|
notificationManager.createNotificationChannels(channels);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void deleteNotificationChannelsForAccount(@NonNull AccountEntity account, @NonNull Context context) {
|
public static void deleteNotificationChannelsForAccount(@NonNull AccountEntity account, @NonNull Context context) {
|
||||||
if (NOTIFICATION_USE_CHANNELS) {
|
if(NOTIFICATION_USE_CHANNELS) {
|
||||||
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
notificationManager.deleteNotificationChannelGroup(account.getIdentifier());
|
notificationManager.deleteNotificationChannelGroup(account.getIdentifier());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void deleteLegacyNotificationChannels(@NonNull Context context, @NonNull AccountManager accountManager) {
|
public static void deleteLegacyNotificationChannels(@NonNull Context context, @NonNull AccountManager accountManager) {
|
||||||
if (NOTIFICATION_USE_CHANNELS) {
|
if(NOTIFICATION_USE_CHANNELS) {
|
||||||
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
// used until Tusky 1.4
|
// used until Tusky 1.4
|
||||||
|
@ -483,36 +484,33 @@ public class NotificationHelper {
|
||||||
notificationManager.deleteNotificationChannel(CHANNEL_FOLLOW);
|
notificationManager.deleteNotificationChannel(CHANNEL_FOLLOW);
|
||||||
|
|
||||||
// used until Tusky 1.7
|
// used until Tusky 1.7
|
||||||
for(AccountEntity account: accountManager.getAllAccountsOrderedByActive()) {
|
for(AccountEntity account : accountManager.getAllAccountsOrderedByActive()) {
|
||||||
notificationManager.deleteNotificationChannel(CHANNEL_FAVOURITE+" "+account.getIdentifier());
|
notificationManager.deleteNotificationChannel(CHANNEL_FAVOURITE + " " + account.getIdentifier());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean areNotificationsEnabled(@NonNull Context context, @NonNull AccountManager accountManager) {
|
public static boolean areNotificationsEnabled(@NonNull Context context, @NonNull AccountManager accountManager) {
|
||||||
if (NOTIFICATION_USE_CHANNELS) {
|
if(NOTIFICATION_USE_CHANNELS) {
|
||||||
|
|
||||||
// on Android >= O, notifications are enabled, if at least one channel is enabled
|
// on Android >= O, notifications are enabled, if at least one channel is enabled
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
if (notificationManager.areNotificationsEnabled()) {
|
if(notificationManager.areNotificationsEnabled()) {
|
||||||
for (NotificationChannel channel : notificationManager.getNotificationChannels()) {
|
for(NotificationChannel channel : notificationManager.getNotificationChannels()) {
|
||||||
if (channel.getImportance() > NotificationManager.IMPORTANCE_NONE) {
|
if(channel.getImportance() > NotificationManager.IMPORTANCE_NONE) {
|
||||||
Log.d(TAG, "NotificationsEnabled");
|
Timber.d("NotificationsEnabled");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.d(TAG, "NotificationsDisabled");
|
Timber.d("NotificationsDisabled");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// on Android < O, notifications are enabled, if at least one account has notification enabled
|
// on Android < O, notifications are enabled, if at least one account has notification enabled
|
||||||
return accountManager.areNotificationsEnabled();
|
return accountManager.areNotificationsEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void enablePullNotifications(Context context) {
|
public static void enablePullNotifications(Context context) {
|
||||||
|
@ -530,26 +528,26 @@ public class NotificationHelper {
|
||||||
|
|
||||||
workManager.enqueue(workRequest);
|
workManager.enqueue(workRequest);
|
||||||
|
|
||||||
Log.d(TAG, "enabled notification checks with "+ PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS + "ms interval");
|
Timber.d("enabled notification checks with ${PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS} ms interval");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void disablePullNotifications(Context context) {
|
public static void disablePullNotifications(Context context) {
|
||||||
WorkManager.getInstance(context).cancelAllWorkByTag(NOTIFICATION_PULL_TAG);
|
WorkManager.getInstance(context).cancelAllWorkByTag(NOTIFICATION_PULL_TAG);
|
||||||
Log.d(TAG, "disabled notification checks");
|
Timber.d("Disabled notification checks");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearNotificationsForActiveAccount(@NonNull Context context, @NonNull AccountManager accountManager) {
|
public static void clearNotificationsForActiveAccount(@NonNull Context context, @NonNull AccountManager accountManager) {
|
||||||
AccountEntity account = accountManager.getActiveAccount();
|
AccountEntity account = accountManager.getActiveAccount();
|
||||||
if (account != null && !account.getActiveNotifications().equals("[]")) {
|
if(account != null && !account.getActiveNotifications().equals("[]")) {
|
||||||
Single.fromCallable(() -> {
|
Single.fromCallable(() -> {
|
||||||
account.setActiveNotifications("[]");
|
account.setActiveNotifications("[]");
|
||||||
accountManager.saveAccount(account);
|
accountManager.saveAccount(account);
|
||||||
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
notificationManager.cancel((int) account.getId());
|
notificationManager.cancel((int) account.getId());
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
@ -557,8 +555,7 @@ public class NotificationHelper {
|
||||||
|
|
||||||
private static boolean filterNotification(AccountEntity account, Notification notification,
|
private static boolean filterNotification(AccountEntity account, Notification notification,
|
||||||
Context context) {
|
Context context) {
|
||||||
|
if(NOTIFICATION_USE_CHANNELS) {
|
||||||
if (NOTIFICATION_USE_CHANNELS) {
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
String channelId = getChannelId(account, notification);
|
String channelId = getChannelId(account, notification);
|
||||||
|
@ -571,7 +568,7 @@ public class NotificationHelper {
|
||||||
return channel.getImportance() > NotificationManager.IMPORTANCE_NONE;
|
return channel.getImportance() > NotificationManager.IMPORTANCE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (notification.getType()) {
|
switch(notification.getType()) {
|
||||||
case MENTION:
|
case MENTION:
|
||||||
return account.getNotificationsMentioned();
|
return account.getNotificationsMentioned();
|
||||||
case STATUS:
|
case STATUS:
|
||||||
|
@ -599,7 +596,7 @@ public class NotificationHelper {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static String getChannelId(AccountEntity account, Notification notification) {
|
private static String getChannelId(AccountEntity account, Notification notification) {
|
||||||
switch (notification.getType()) {
|
switch(notification.getType()) {
|
||||||
case MENTION:
|
case MENTION:
|
||||||
return CHANNEL_MENTION + account.getIdentifier();
|
return CHANNEL_MENTION + account.getIdentifier();
|
||||||
case STATUS:
|
case STATUS:
|
||||||
|
@ -623,25 +620,24 @@ public class NotificationHelper {
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setupPreferences(AccountEntity account,
|
private static void setupPreferences(
|
||||||
NotificationCompat.Builder builder) {
|
AccountEntity account,
|
||||||
|
NotificationCompat.Builder builder) {
|
||||||
if (NOTIFICATION_USE_CHANNELS) {
|
if(NOTIFICATION_USE_CHANNELS) {
|
||||||
return; //do nothing on Android O or newer, the system uses the channel settings anyway
|
return; //do nothing on Android O or newer, the system uses the channel settings anyway
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.getNotificationSound()) {
|
if(account.getNotificationSound()) {
|
||||||
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
|
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.getNotificationVibration()) {
|
if(account.getNotificationVibration()) {
|
||||||
builder.setVibrate(new long[]{500, 500});
|
builder.setVibrate(new long[]{500, 500});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.getNotificationLight()) {
|
if(account.getNotificationLight()) {
|
||||||
builder.setLights(0xFF2B90D9, 300, 1000);
|
builder.setLights(0xFF2B90D9, 300, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -652,19 +648,19 @@ public class NotificationHelper {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static String joinNames(Context context, JSONArray array) throws JSONException {
|
private static String joinNames(Context context, JSONArray array) throws JSONException {
|
||||||
if (array.length() > 3) {
|
if(array.length() > 3) {
|
||||||
int length = array.length();
|
int length = array.length();
|
||||||
return String.format(context.getString(R.string.notification_summary_large),
|
return String.format(context.getString(R.string.notification_summary_large),
|
||||||
wrapItemAt(array, length - 1),
|
wrapItemAt(array, length - 1),
|
||||||
wrapItemAt(array, length - 2),
|
wrapItemAt(array, length - 2),
|
||||||
wrapItemAt(array, length - 3),
|
wrapItemAt(array, length - 3),
|
||||||
length - 3);
|
length - 3);
|
||||||
} else if (array.length() == 3) {
|
} else if(array.length() == 3) {
|
||||||
return String.format(context.getString(R.string.notification_summary_medium),
|
return String.format(context.getString(R.string.notification_summary_medium),
|
||||||
wrapItemAt(array, 2),
|
wrapItemAt(array, 2),
|
||||||
wrapItemAt(array, 1),
|
wrapItemAt(array, 1),
|
||||||
wrapItemAt(array, 0));
|
wrapItemAt(array, 0));
|
||||||
} else if (array.length() == 2) {
|
} else if(array.length() == 2) {
|
||||||
return String.format(context.getString(R.string.notification_summary_small),
|
return String.format(context.getString(R.string.notification_summary_small),
|
||||||
wrapItemAt(array, 1),
|
wrapItemAt(array, 1),
|
||||||
wrapItemAt(array, 0));
|
wrapItemAt(array, 0));
|
||||||
|
@ -676,7 +672,7 @@ public class NotificationHelper {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static String titleForType(Context context, Notification notification, AccountEntity account) {
|
private static String titleForType(Context context, Notification notification, AccountEntity account) {
|
||||||
String accountName = StringUtils.unicodeWrap(notification.getAccount().getName());
|
String accountName = StringUtils.unicodeWrap(notification.getAccount().getName());
|
||||||
switch (notification.getType()) {
|
switch(notification.getType()) {
|
||||||
case MENTION:
|
case MENTION:
|
||||||
return String.format(context.getString(R.string.notification_mention_format),
|
return String.format(context.getString(R.string.notification_mention_format),
|
||||||
accountName);
|
accountName);
|
||||||
|
@ -711,11 +707,12 @@ public class NotificationHelper {
|
||||||
return String.format(context.getString(R.string.notification_move_format), accountName);
|
return String.format(context.getString(R.string.notification_move_format), accountName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String bodyForType(Notification notification, Context context) {
|
private static String bodyForType(Notification notification, Context context) {
|
||||||
switch (notification.getType()) {
|
switch(notification.getType()) {
|
||||||
case MOVE:
|
case MOVE:
|
||||||
return "@" + notification.getTarget().getUsername();
|
return "@" + notification.getTarget().getUsername();
|
||||||
case FOLLOW:
|
case FOLLOW:
|
||||||
|
@ -726,19 +723,19 @@ public class NotificationHelper {
|
||||||
case REBLOG:
|
case REBLOG:
|
||||||
case EMOJI_REACTION:
|
case EMOJI_REACTION:
|
||||||
case STATUS:
|
case STATUS:
|
||||||
if (!TextUtils.isEmpty(notification.getStatus().getSpoilerText())) {
|
if(!TextUtils.isEmpty(notification.getStatus().getSpoilerText())) {
|
||||||
return notification.getStatus().getSpoilerText();
|
return notification.getStatus().getSpoilerText();
|
||||||
} else {
|
} else {
|
||||||
return notification.getStatus().getContent().toString();
|
return notification.getStatus().getContent().toString();
|
||||||
}
|
}
|
||||||
case POLL:
|
case POLL:
|
||||||
if (!TextUtils.isEmpty(notification.getStatus().getSpoilerText())) {
|
if(!TextUtils.isEmpty(notification.getStatus().getSpoilerText())) {
|
||||||
return notification.getStatus().getSpoilerText();
|
return notification.getStatus().getSpoilerText();
|
||||||
} else {
|
} else {
|
||||||
StringBuilder builder = new StringBuilder(notification.getStatus().getContent());
|
StringBuilder builder = new StringBuilder(notification.getStatus().getContent());
|
||||||
builder.append('\n');
|
builder.append('\n');
|
||||||
Poll poll = notification.getStatus().getPoll();
|
Poll poll = notification.getStatus().getPoll();
|
||||||
for(PollOption option: poll.getOptions()) {
|
for(PollOption option : poll.getOptions()) {
|
||||||
builder.append(buildDescription(option.getTitle(),
|
builder.append(buildDescription(option.getTitle(),
|
||||||
PollViewDataKt.calculatePercent(option.getVotesCount(), poll.getVotersCount(), poll.getVotesCount()),
|
PollViewDataKt.calculatePercent(option.getVotesCount(), poll.getVotersCount(), poll.getVotesCount()),
|
||||||
context));
|
context));
|
||||||
|
@ -747,7 +744,7 @@ public class NotificationHelper {
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
case CHAT_MESSAGE:
|
case CHAT_MESSAGE:
|
||||||
if (!TextUtils.isEmpty(notification.getChatMessage().getContent())) {
|
if(!TextUtils.isEmpty(notification.getChatMessage().getContent())) {
|
||||||
return notification.getChatMessage().getContent().toString();
|
return notification.getChatMessage().getContent().toString();
|
||||||
} else if(notification.getChatMessage().getAttachment() != null) {
|
} else if(notification.getChatMessage().getAttachment() != null) {
|
||||||
return context.getString(notification.getChatMessage().getAttachment().describeAttachmentType());
|
return context.getString(notification.getChatMessage().getAttachment().describeAttachmentType());
|
||||||
|
@ -760,4 +757,10 @@ public class NotificationHelper {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int pendingIntentFlags(boolean mutable) {
|
||||||
|
return (PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
| (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ?
|
||||||
|
(mutable ? PendingIntent.FLAG_MUTABLE : PendingIntent.FLAG_IMMUTABLE) : 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Husky -- A Pleroma client for Android
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 The Husky Developers
|
||||||
|
* Copyright (C) 2020 Alibek Omarov
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.keylesspalace.tusky.service
|
package com.keylesspalace.tusky.service
|
||||||
|
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
|
@ -222,15 +242,15 @@ class StreamingService : Service(), Injectable {
|
||||||
return object : WebSocketListener() {
|
return object : WebSocketListener() {
|
||||||
|
|
||||||
override fun onOpen(webSocket: WebSocket, response: Response) {
|
override fun onOpen(webSocket: WebSocket, response: Response) {
|
||||||
Timber.d("Stream connected to: $tag")
|
Timber.d("Stream connected to: $tag. Response[$response]")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
|
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
|
||||||
Timber.d("Stream closed for: $tag")
|
Timber.d("Stream closed for: $tag. Reason[$reason]")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
|
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
|
||||||
Timber.e("Stream failed for $tag", t)
|
Timber.e("Stream failed for $tag: $t. Response[$response]")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMessage(webSocket: WebSocket, text: String) {
|
override fun onMessage(webSocket: WebSocket, text: String) {
|
||||||
|
|
Loading…
Reference in a new issue