implement notification channels, use system notification settings on android Oreo

This commit is contained in:
Conny Duck 2017-10-18 22:18:07 +02:00
parent 7d7aeadd41
commit 30312e0e55
7 changed files with 192 additions and 68 deletions

View File

@ -46,6 +46,8 @@ public class PreferencesActivity extends BaseActivity
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new PreferencesFragment())
.commit();
}
private void saveInstanceState(Bundle outState) {

View File

@ -15,9 +15,14 @@
package com.keylesspalace.tusky.fragment;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import com.keylesspalace.tusky.BuildConfig;
import com.keylesspalace.tusky.R;
public class PreferencesFragment extends PreferenceFragment {
@ -25,5 +30,26 @@ public class PreferencesFragment extends PreferenceFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
//on Android O and newer, launch the system notification settings instead of the app settings
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PreferenceScreen notificationPreferences = (PreferenceScreen) findPreference("notificationSettings");
notificationPreferences.removeAll();
notificationPreferences.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent();
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("android.provider.extra.APP_PACKAGE", BuildConfig.APPLICATION_ID);
startActivity(intent);
return true;
}
});
}
}
}

View File

@ -21,6 +21,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.Spanned;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@ -58,6 +59,9 @@ public class PullNotificationService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
Log.d("PullNotifications", "pulling for notification");
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(
getApplicationContext());
boolean enabled = preferences.getBoolean("notificationsEnabled", true);

View File

@ -15,6 +15,7 @@
package com.keylesspalace.tusky.util;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
@ -28,6 +29,7 @@ import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.keylesspalace.tusky.MainActivity;
@ -41,9 +43,18 @@ import com.squareup.picasso.Target;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
public class NotificationMaker {
public static final String TAG = "NotificationMaker";
/** notification channels used on Android O+ **/
private static final String CHANNEL_MENTION = "CHANNEL_MENTION";
private static final String CHANNEL_FOLLOW = "CHANNEL_FOLLOW";
private static final String CHANNEL_BOOST = "CHANNEL_BOOST";
private static final String CHANNEL_FAVOURITE =" CHANNEL_FAVOURITE";
/**
* Takes a given Mastodon notification and either creates a new Android notification or updates
* the state of the existing notification to reflect the new interaction.
@ -62,6 +73,8 @@ public class NotificationMaker {
return;
}
createNotificationChannels(context);
String rawCurrentNotifications = notificationPreferences.getString("current", "[]");
JSONArray currentNotifications;
@ -103,12 +116,15 @@ public class NotificationMaker {
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context, getChannelId(body))
.setSmallIcon(R.drawable.ic_notify)
.setContentIntent(resultPendingIntent)
.setDeleteIntent(deletePendingIntent)
.setColor(ContextCompat.getColor(context, (R.color.primary)))
.setDefaults(0); // So it doesn't ring twice, notify only in Target callback
setupPreferences(preferences, builder);
if (currentNotifications.length() == 1) {
builder.setContentTitle(titleForType(context, body))
.setContentText(truncateWithEllipses(bodyForType(body), 40));
@ -118,8 +134,6 @@ public class NotificationMaker {
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
builder.setLargeIcon(bitmap);
setupPreferences(preferences, builder);
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notifyId, builder.build());
@ -138,7 +152,6 @@ public class NotificationMaker {
.transform(new RoundedTransformation(7, 0))
.into(target);
} else {
setupPreferences(preferences, builder);
try {
String format = context.getString(R.string.notification_title_summary);
String title = String.format(format, currentNotifications.length());
@ -160,8 +173,54 @@ public class NotificationMaker {
notificationManager.notify(notifyId, builder.build());
}
private static void createNotificationChannels(Context context) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String[] channelIds = new String[]{CHANNEL_MENTION, CHANNEL_FOLLOW, CHANNEL_BOOST, CHANNEL_FAVOURITE};
int[] channelNames = {
R.string.notification_channel_mention_name,
R.string.notification_channel_follow_name,
R.string.notification_channel_boost_name,
R.string.notification_channel_favourite_name
};
int[] channelDescriptions = {
R.string.notification_channel_mention_descriptions,
R.string.notification_channel_follow_description,
R.string.notification_channel_boost_description,
R.string.notification_channel_favourite_description
};
List<NotificationChannel> channels = new ArrayList<>(4);
for(int i=0; i<channelIds.length; i++) {
String id = channelIds[i];
String name = context.getString(channelNames[i]);
String description = context.getString(channelDescriptions[i]);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(id, name, importance);
channel.setDescription(description);
channel.enableLights(true);
channel.enableVibration(true);
channel.setShowBadge(true);
channels.add(channel);
}
mNotificationManager.createNotificationChannels(channels);
}
}
private static boolean filterNotification(SharedPreferences preferences,
Notification notification) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return true; //do not filter on Android O or newer, the system does it for us
}
switch (notification.type) {
default:
case MENTION:
@ -175,6 +234,21 @@ public class NotificationMaker {
}
}
private static String getChannelId(Notification notification) {
switch (notification.type) {
default:
case MENTION:
return CHANNEL_MENTION;
case FOLLOW:
return CHANNEL_FOLLOW;
case REBLOG:
return CHANNEL_BOOST;
case FAVOURITE:
return CHANNEL_FAVOURITE;
}
}
private static String truncateWithEllipses(String string, int limit) {
if (string.length() < limit) {
return string;
@ -185,6 +259,11 @@ public class NotificationMaker {
private static void setupPreferences(SharedPreferences preferences,
NotificationCompat.Builder builder) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return; //do nothing on Android O or newer, the system uses the channel settings anyway
}
if (preferences.getBoolean("notificationAlertSound", true)) {
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
}
@ -245,4 +324,5 @@ public class NotificationMaker {
}
return null;
}
}

View File

@ -173,6 +173,16 @@
<string name="pref_title_show_replies">Show replies</string>
<string name="pref_title_show_media_preview">Show media previews</string>
<string name="notification_channel_mention_name">New Mentions</string>
<string name="notification_channel_mention_descriptions">Notifications about new mentions</string>
<string name="notification_channel_follow_name">New Followers</string>
<string name="notification_channel_follow_description">Notifications about new followers</string>
<string name="notification_channel_boost_name">Boosts</string>
<string name="notification_channel_boost_description">Notifications when your toots get boosted</string>
<string name="notification_channel_favourite_name">Favourites</string>
<string name="notification_channel_favourite_description">Notifications when your toots get mark as favourite</string>
<string name="notification_mention_format">%s mentioned you</string>
<string name="notification_summary_large">%1$s, %2$s, %3$s and %4$d others</string>
<string name="notification_summary_medium">%1$s, %2$s, and %3$s</string>

View File

@ -5,90 +5,92 @@
<PreferenceCategory android:title="@string/pref_title_appearance_settings">
<CheckBoxPreference
android:defaultValue="false"
android:key="lightTheme"
android:title="@string/pref_title_light_theme"
android:defaultValue="false" />
android:title="@string/pref_title_light_theme" />
<CheckBoxPreference
android:defaultValue="false"
android:key="fabHide"
android:title="@string/pref_title_hide_follow_button"
android:defaultValue="false" />
android:title="@string/pref_title_hide_follow_button" />
<CheckBoxPreference
android:defaultValue="true"
android:key="mediaPreviewEnabled"
android:title="@string/pref_title_show_media_preview"
android:defaultValue="true" />
android:title="@string/pref_title_show_media_preview" />
<CheckBoxPreference
android:defaultValue="false"
android:key="alwayShowSensitiveMedia"
android:title="@string/pref_title_alway_show_sensitive_media"
android:defaultValue="false" />
android:title="@string/pref_title_alway_show_sensitive_media" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_browser_settings">
<CheckBoxPreference
android:defaultValue="true"
android:key="customTabs"
android:title="@string/pref_title_custom_tabs"
android:defaultValue="true" />
android:title="@string/pref_title_custom_tabs" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_status_filter">
<PreferenceScreen android:title="@string/pref_title_status_tabs">
<PreferenceCategory
android:dependency="notificationsEnabled"
android:title="@string/title_home">
<PreferenceCategory android:title="@string/title_home">
<CheckBoxPreference
android:defaultValue="true"
android:key="tabFilterHomeBoosts"
android:title="@string/pref_title_show_boosts"
android:defaultValue="true" />
android:title="@string/pref_title_show_boosts" />
<CheckBoxPreference
android:defaultValue="true"
android:key="tabFilterHomeReplies"
android:title="@string/pref_title_show_replies"
android:defaultValue="true" />
android:title="@string/pref_title_show_replies" />
</PreferenceCategory>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_notification_settings">
<PreferenceScreen android:title="@string/pref_title_edit_notification_settings">
<CheckBoxPreference
android:key="notificationsEnabled"
android:title="@string/pref_title_notifications_enabled"
android:defaultValue="true" />
<ListPreference android:key="pullNotificationCheckInterval"
android:title="@string/pref_title_pull_notification_check_interval"
<ListPreference
android:defaultValue="15"
android:entries="@array/pull_notification_check_interval_names"
android:entryValues="@array/pull_notification_check_intervals"
android:key="pullNotificationCheckInterval"
android:summary="%s"
android:defaultValue="15" />
android:title="@string/pref_title_pull_notification_check_interval" />
<PreferenceScreen
android:key="notificationSettings"
android:title="@string/pref_title_edit_notification_settings">
<CheckBoxPreference
android:defaultValue="true"
android:key="notificationsEnabled"
android:title="@string/pref_title_notifications_enabled" />
<PreferenceCategory
android:dependency="notificationsEnabled"
android:title="@string/pref_title_notification_filters">
<CheckBoxPreference
android:defaultValue="true"
android:key="notificationFilterMentions"
android:title="@string/pref_title_notification_filter_mentions"
android:defaultValue="true" />
android:title="@string/pref_title_notification_filter_mentions" />
<CheckBoxPreference
android:defaultValue="true"
android:key="notificationFilterFollows"
android:title="@string/pref_title_notification_filter_follows"
android:defaultValue="true" />
android:title="@string/pref_title_notification_filter_follows" />
<CheckBoxPreference
android:defaultValue="true"
android:key="notificationFilterReblogs"
android:title="@string/pref_title_notification_filter_reblogs"
android:defaultValue="true" />
android:title="@string/pref_title_notification_filter_reblogs" />
<CheckBoxPreference
android:defaultValue="true"
android:key="notificationFilterFavourites"
android:title="@string/pref_title_notification_filter_favourites"
android:defaultValue="true" />
android:title="@string/pref_title_notification_filter_favourites" />
</PreferenceCategory>
@ -97,19 +99,19 @@
android:title="@string/pref_title_notification_alerts">
<CheckBoxPreference
android:defaultValue="true"
android:key="notificationAlertSound"
android:title="@string/pref_title_notification_alert_sound"
android:defaultValue="true" />
android:title="@string/pref_title_notification_alert_sound" />
<CheckBoxPreference
android:defaultValue="true"
android:key="notificationAlertVibrate"
android:title="@string/pref_title_notification_alert_vibrate"
android:defaultValue="true" />
android:title="@string/pref_title_notification_alert_vibrate" />
<CheckBoxPreference
android:defaultValue="true"
android:key="notificationAlertLight"
android:title="@string/pref_title_notification_alert_light"
android:defaultValue="true" />
android:title="@string/pref_title_notification_alert_light" />
</PreferenceCategory>