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() getFragmentManager().beginTransaction()
.replace(android.R.id.content, new PreferencesFragment()) .replace(android.R.id.content, new PreferencesFragment())
.commit(); .commit();
} }
private void saveInstanceState(Bundle outState) { private void saveInstanceState(Bundle outState) {

View File

@ -229,7 +229,7 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
} }
} }
SharedPreferences pm = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences pm = PreferenceManager.getDefaultSharedPreferences(context);
Boolean isAlwayShowSensitive = pm.getBoolean("alwayShowSensitiveMedia",false); Boolean isAlwayShowSensitive = pm.getBoolean("alwayShowSensitiveMedia", false);
if (sensitive && (!isAlwayShowSensitive)) { if (sensitive && (!isAlwayShowSensitive)) {
sensitiveMediaWarning.setVisibility(showingSensitive ? View.GONE : View.VISIBLE); sensitiveMediaWarning.setVisibility(showingSensitive ? View.GONE : View.VISIBLE);
sensitiveMediaShow.setVisibility(showingSensitive ? View.VISIBLE : View.GONE); sensitiveMediaShow.setVisibility(showingSensitive ? View.VISIBLE : View.GONE);

View File

@ -15,9 +15,14 @@
package com.keylesspalace.tusky.fragment; package com.keylesspalace.tusky.fragment;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import com.keylesspalace.tusky.BuildConfig;
import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.R;
public class PreferencesFragment extends PreferenceFragment { public class PreferencesFragment extends PreferenceFragment {
@ -25,5 +30,26 @@ public class PreferencesFragment extends PreferenceFragment {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences); 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.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.Spanned; import android.text.Spanned;
import android.util.Log;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@ -58,6 +59,9 @@ public class PullNotificationService extends IntentService {
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleIntent(Intent intent) {
Log.d("PullNotifications", "pulling for notification");
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences( SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(
getApplicationContext()); getApplicationContext());
boolean enabled = preferences.getBoolean("notificationsEnabled", true); boolean enabled = preferences.getBoolean("notificationsEnabled", true);

View File

@ -15,6 +15,7 @@
package com.keylesspalace.tusky.util; package com.keylesspalace.tusky.util;
import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
@ -28,6 +29,7 @@ import android.provider.Settings;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder; import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.ContextCompat;
import android.util.Log; import android.util.Log;
import com.keylesspalace.tusky.MainActivity; import com.keylesspalace.tusky.MainActivity;
@ -41,9 +43,18 @@ import com.squareup.picasso.Target;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
public class NotificationMaker { public class NotificationMaker {
public static final String TAG = "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 * 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. * the state of the existing notification to reflect the new interaction.
@ -62,6 +73,8 @@ public class NotificationMaker {
return; return;
} }
createNotificationChannels(context);
String rawCurrentNotifications = notificationPreferences.getString("current", "[]"); String rawCurrentNotifications = notificationPreferences.getString("current", "[]");
JSONArray currentNotifications; JSONArray currentNotifications;
@ -103,12 +116,15 @@ public class NotificationMaker {
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent,
PendingIntent.FLAG_CANCEL_CURRENT); 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) .setSmallIcon(R.drawable.ic_notify)
.setContentIntent(resultPendingIntent) .setContentIntent(resultPendingIntent)
.setDeleteIntent(deletePendingIntent) .setDeleteIntent(deletePendingIntent)
.setColor(ContextCompat.getColor(context, (R.color.primary)))
.setDefaults(0); // So it doesn't ring twice, notify only in Target callback .setDefaults(0); // So it doesn't ring twice, notify only in Target callback
setupPreferences(preferences, builder);
if (currentNotifications.length() == 1) { if (currentNotifications.length() == 1) {
builder.setContentTitle(titleForType(context, body)) builder.setContentTitle(titleForType(context, body))
.setContentText(truncateWithEllipses(bodyForType(body), 40)); .setContentText(truncateWithEllipses(bodyForType(body), 40));
@ -118,8 +134,6 @@ public class NotificationMaker {
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
builder.setLargeIcon(bitmap); builder.setLargeIcon(bitmap);
setupPreferences(preferences, builder);
NotificationManager notificationManager = (NotificationManager) NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE); context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notifyId, builder.build()); notificationManager.notify(notifyId, builder.build());
@ -138,7 +152,6 @@ public class NotificationMaker {
.transform(new RoundedTransformation(7, 0)) .transform(new RoundedTransformation(7, 0))
.into(target); .into(target);
} else { } else {
setupPreferences(preferences, builder);
try { try {
String format = context.getString(R.string.notification_title_summary); String format = context.getString(R.string.notification_title_summary);
String title = String.format(format, currentNotifications.length()); String title = String.format(format, currentNotifications.length());
@ -160,9 +173,55 @@ public class NotificationMaker {
notificationManager.notify(notifyId, builder.build()); 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, private static boolean filterNotification(SharedPreferences preferences,
Notification notification) { Notification notification) {
switch (notification.type) {
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: default:
case MENTION: case MENTION:
return preferences.getBoolean("notificationFilterMentions", true); return preferences.getBoolean("notificationFilterMentions", true);
@ -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) { private static String truncateWithEllipses(String string, int limit) {
if (string.length() < limit) { if (string.length() < limit) {
return string; return string;
@ -185,6 +259,11 @@ public class NotificationMaker {
private static void setupPreferences(SharedPreferences preferences, private static void setupPreferences(SharedPreferences preferences,
NotificationCompat.Builder builder) { 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)) { if (preferences.getBoolean("notificationAlertSound", true)) {
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI); builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
} }
@ -245,4 +324,5 @@ public class NotificationMaker {
} }
return null; return null;
} }
} }

View File

@ -173,6 +173,16 @@
<string name="pref_title_show_replies">Show replies</string> <string name="pref_title_show_replies">Show replies</string>
<string name="pref_title_show_media_preview">Show media previews</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_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_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> <string name="notification_summary_medium">%1$s, %2$s, and %3$s</string>

View File

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