aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2018-09-12 22:32:47 +0200
committerChristian Schneppe <christian@pix-art.de>2018-09-13 17:29:36 +0200
commit46b77bf34219aa47e916f0ab980d3bd5bb05ba34 (patch)
tree0a73271b9cdea5577b7d69dbdbf525f24bcc31b7
parente50ba72e8ae024e64b1e2b2838f73faf64330adb (diff)
initial work toward api 26+
* introduce notification channels * always use foreground service on 26+
-rw-r--r--build.gradle5
-rw-r--r--gradle.properties1
-rw-r--r--gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--src/main/AndroidManifest.xml4
-rw-r--r--src/main/java/de/pixart/messenger/services/BarcodeProvider.java1
-rw-r--r--src/main/java/de/pixart/messenger/services/ContactChooserTargetService.java1
-rw-r--r--src/main/java/de/pixart/messenger/services/EventReceiver.java19
-rw-r--r--src/main/java/de/pixart/messenger/services/ExportLogsService.java35
-rw-r--r--src/main/java/de/pixart/messenger/services/NotificationService.java304
-rw-r--r--src/main/java/de/pixart/messenger/services/UpdateService.java15
-rw-r--r--src/main/java/de/pixart/messenger/services/XmppConnectionService.java40
-rw-r--r--src/main/java/de/pixart/messenger/ui/SettingsActivity.java3
-rw-r--r--src/main/java/de/pixart/messenger/ui/SettingsFragment.java2
-rw-r--r--src/main/java/de/pixart/messenger/ui/XmppActivity.java6
-rw-r--r--src/main/java/de/pixart/messenger/utils/Compatibility.java66
-rw-r--r--src/main/java/de/pixart/messenger/utils/ConversationsFileObserver.java11
-rw-r--r--src/main/res/values/strings.xml11
-rw-r--r--src/main/res/xml/preferences.xml14
18 files changed, 362 insertions, 178 deletions
diff --git a/build.gradle b/build.gradle
index aa6c0a122..ec296b161 100644
--- a/build.gradle
+++ b/build.gradle
@@ -85,11 +85,11 @@ ext {
android {
- compileSdkVersion 27
+ compileSdkVersion 28
defaultConfig {
minSdkVersion 16
- targetSdkVersion 25
+ targetSdkVersion 28
versionCode 239
versionName "2.1.1 beta (2018-08-28)"
@@ -139,7 +139,6 @@ android {
}
buildTypes {
debug {
- minSdkVersion 14
debuggable true
buildTypes.release.signingConfig = null
}
diff --git a/gradle.properties b/gradle.properties
index fbdb9f362..b3c7a0330 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1 @@
org.gradle.jvmargs=-Xmx2048M
-org.gradle.configureondemand=false \ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 68382dc23..7a84270ae 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index c64f89ef8..e34cb1cb2 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -18,6 +18,7 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.CAMERA" />
@@ -235,8 +236,7 @@
android:label="@string/share_location" />
<activity
android:name=".ui.ShowLocationActivity"
- android:label="@string/show_location">
- </activity>
+ android:label="@string/show_location"></activity>
<activity
android:name=".ui.SearchActivity"
android:label="@string/search_messages" />
diff --git a/src/main/java/de/pixart/messenger/services/BarcodeProvider.java b/src/main/java/de/pixart/messenger/services/BarcodeProvider.java
index 67dc74cc6..5ac2ee016 100644
--- a/src/main/java/de/pixart/messenger/services/BarcodeProvider.java
+++ b/src/main/java/de/pixart/messenger/services/BarcodeProvider.java
@@ -162,7 +162,6 @@ public class BarcodeProvider extends ContentProvider implements ServiceConnectio
synchronized (this) {
if (mXmppConnectionService == null && !mBindingInProcess) {
Log.d(Config.LOGTAG, "calling to bind service");
- context.startService(intent);
context.bindService(intent, this, Context.BIND_AUTO_CREATE);
this.mBindingInProcess = true;
}
diff --git a/src/main/java/de/pixart/messenger/services/ContactChooserTargetService.java b/src/main/java/de/pixart/messenger/services/ContactChooserTargetService.java
index 5d6469bae..d20f9c1f3 100644
--- a/src/main/java/de/pixart/messenger/services/ContactChooserTargetService.java
+++ b/src/main/java/de/pixart/messenger/services/ContactChooserTargetService.java
@@ -32,7 +32,6 @@ public class ContactChooserTargetService extends ChooserTargetService implements
public List<ChooserTarget> onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) {
Intent intent = new Intent(this, XmppConnectionService.class);
intent.setAction("contact_chooser");
- startService(intent);
bindService(intent, this, Context.BIND_AUTO_CREATE);
ArrayList<ChooserTarget> chooserTargets = new ArrayList<>();
try {
diff --git a/src/main/java/de/pixart/messenger/services/EventReceiver.java b/src/main/java/de/pixart/messenger/services/EventReceiver.java
index 6200a40ce..529741ead 100644
--- a/src/main/java/de/pixart/messenger/services/EventReceiver.java
+++ b/src/main/java/de/pixart/messenger/services/EventReceiver.java
@@ -4,6 +4,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.preference.PreferenceManager;
+import android.support.v4.content.ContextCompat;
import android.util.Log;
import de.pixart.messenger.Config;
@@ -13,26 +14,26 @@ public class EventReceiver extends BroadcastReceiver {
public static final String SETTING_ENABLED_ACCOUNTS = "enabled_accounts";
@Override
- public void onReceive(Context context, Intent intent) {
- Intent mIntentForService = new Intent(context, XmppConnectionService.class);
- if (intent.getAction() != null) {
- mIntentForService.setAction(intent.getAction());
+ public void onReceive(final Context context, final Intent originalIntent) {
+ final Intent intentForService = new Intent(context, XmppConnectionService.class);
+ if (originalIntent.getAction() != null) {
+ intentForService.setAction(originalIntent.getAction());
} else {
- mIntentForService.setAction("other");
+ intentForService.setAction("other");
}
- final String action = intent.getAction();
+ final String action = originalIntent.getAction();
if (action.equals("ui") || hasEnabledAccounts(context)) {
try {
- context.startService(mIntentForService);
+ ContextCompat.startForegroundService(context, intentForService);
} catch (RuntimeException e) {
Log.d(Config.LOGTAG, "EventReceiver was unable to start service");
}
} else {
- Log.d(Config.LOGTAG, "EventReceiver ignored action " + mIntentForService.getAction());
+ Log.d(Config.LOGTAG, "EventReceiver ignored action " + intentForService.getAction());
}
}
- public static boolean hasEnabledAccounts(Context context) {
+ public static boolean hasEnabledAccounts(final Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTING_ENABLED_ACCOUNTS, true);
}
diff --git a/src/main/java/de/pixart/messenger/services/ExportLogsService.java b/src/main/java/de/pixart/messenger/services/ExportLogsService.java
index b485fb91d..c2704490d 100644
--- a/src/main/java/de/pixart/messenger/services/ExportLogsService.java
+++ b/src/main/java/de/pixart/messenger/services/ExportLogsService.java
@@ -1,7 +1,5 @@
package de.pixart.messenger.services;
-import android.app.NotificationManager;
-import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -10,7 +8,6 @@ import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.preference.PreferenceManager;
import android.support.annotation.BoolRes;
-import android.support.v4.app.NotificationCompat;
import android.util.Log;
import java.io.BufferedWriter;
@@ -41,19 +38,17 @@ import rocks.xmpp.addr.Jid;
import static de.pixart.messenger.ui.SettingsActivity.USE_MULTI_ACCOUNTS;
-public class ExportLogsService extends Service {
+public class ExportLogsService extends XmppConnectionService {
private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
private static final String DIRECTORY_STRING_FORMAT = FileBackend.getConversationsDirectory("Chats", false) + "%s";
private static final String MESSAGE_STRING_FORMAT = "(%s) %s: %s\n";
- private static final int NOTIFICATION_ID = 1;
private static AtomicBoolean running = new AtomicBoolean(false);
+ boolean ReadableLogsEnabled = false;
private DatabaseBackend mDatabaseBackend;
private List<Account> mAccounts;
- boolean ReadableLogsEnabled = false;
private WakeLock wakeLock;
private PowerManager pm;
- XmppConnectionService mXmppConnectionService;
@Override
public void onCreate() {
@@ -63,20 +58,19 @@ public class ExportLogsService extends Service {
ReadableLogsEnabled = ReadableLogs.getBoolean("export_plain_text_logs", getResources().getBoolean(R.bool.plain_text_logs));
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExportLogsService");
+ this.startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, getNotificationService().exportLogsNotification());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (running.compareAndSet(false, true)) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- export();
- stopForeground(true);
- WakeLockHelper.release(wakeLock);
- running.set(false);
- stopSelf();
- }
+ new Thread(() -> {
+ startForcingForegroundNotification();
+ export();
+ stopForcingForegroundNotification();
+ WakeLockHelper.release(wakeLock);
+ running.set(false);
+ stopSelf();
}).start();
}
return START_NOT_STICKY;
@@ -84,16 +78,9 @@ public class ExportLogsService extends Service {
private void export() {
wakeLock.acquire();
+ getNotificationService().exportLogsServiceNotification(getNotificationService().exportLogsNotification());
List<Conversation> conversations = mDatabaseBackend.getConversations(Conversation.STATUS_AVAILABLE);
conversations.addAll(mDatabaseBackend.getConversations(Conversation.STATUS_ARCHIVED));
- NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext());
- mBuilder.setContentTitle(getString(R.string.app_name))
- .setContentText(getString(R.string.notification_export_logs_title))
- .setSmallIcon(R.drawable.ic_import_export_white_24dp)
- .setProgress(0, 0, true);
- startForeground(NOTIFICATION_ID, mBuilder.build());
- mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
if (ReadableLogsEnabled) {
for (Conversation conversation : conversations) {
writeToFile(conversation);
diff --git a/src/main/java/de/pixart/messenger/services/NotificationService.java b/src/main/java/de/pixart/messenger/services/NotificationService.java
index 7fa091478..4cdde8390 100644
--- a/src/main/java/de/pixart/messenger/services/NotificationService.java
+++ b/src/main/java/de/pixart/messenger/services/NotificationService.java
@@ -1,16 +1,23 @@
package de.pixart.messenger.services;
import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Typeface;
+import android.media.AudioAttributes;
+import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.SystemClock;
import android.preference.PreferenceManager;
+import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.BigPictureStyle;
import android.support.v4.app.NotificationCompat.Builder;
@@ -46,9 +53,9 @@ import de.pixart.messenger.entities.Conversational;
import de.pixart.messenger.entities.Message;
import de.pixart.messenger.persistance.FileBackend;
import de.pixart.messenger.ui.ConversationsActivity;
-import de.pixart.messenger.ui.EditAccountActivity;
import de.pixart.messenger.ui.ManageAccountActivity;
import de.pixart.messenger.ui.TimePreference;
+import de.pixart.messenger.utils.Compatibility;
import de.pixart.messenger.utils.GeoHelper;
import de.pixart.messenger.utils.UIHelper;
import de.pixart.messenger.xmpp.XmppConnection;
@@ -56,39 +63,108 @@ import de.pixart.messenger.xmpp.XmppConnection;
public class NotificationService {
public static final Object CATCHUP_LOCK = new Object();
+
private static final String CONVERSATIONS_GROUP = "de.pixart.messenger";
- private final XmppConnectionService mXmppConnectionService;
- private final LinkedHashMap<String, ArrayList<Message>> notifications = new LinkedHashMap<>();
private static final int NOTIFICATION_ID_MULTIPLIER = 1024 * 1024;
public static final int NOTIFICATION_ID = 2 * NOTIFICATION_ID_MULTIPLIER;
public static final int FOREGROUND_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 4;
public static final int ERROR_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 6;
- public static final int UPDATE_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 8;
+ public static final String MESSAGES_CHANNEL_ID = "messages";
+ public static final String FOREGROUND_CHANNEL_ID = "foreground";
+ public static final String ERROR_CHANNEL_ID = "error";
+
+ private final XmppConnectionService mXmppConnectionService;
+ private final LinkedHashMap<String, ArrayList<Message>> notifications = new LinkedHashMap<>();
+ private final HashMap<Conversation, AtomicInteger> mBacklogMessageCounter = new HashMap<>();
private Conversation mOpenConversation;
private boolean mIsInForeground;
private long mLastNotification;
- private final HashMap<Conversation, AtomicInteger> mBacklogMessageCounter = new HashMap<>();
-
- public NotificationService(final XmppConnectionService service) {
+ NotificationService(final XmppConnectionService service) {
this.mXmppConnectionService = service;
}
+ private static boolean displaySnoozeAction(List<Message> messages) {
+ int numberOfMessagesWithoutReply = 0;
+ for (Message message : messages) {
+ if (message.getStatus() == Message.STATUS_RECEIVED) {
+ ++numberOfMessagesWithoutReply;
+ } else {
+ return false;
+ }
+ }
+ return numberOfMessagesWithoutReply >= 3;
+ }
+
public static Pattern generateNickHighlightPattern(final String nick) {
return Pattern.compile("(?<=(^|\\s))" + Pattern.quote(nick) + "\\b");
}
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ public void initializeChannels() {
+ final Context c = mXmppConnectionService;
+ NotificationManager notificationManager = c.getSystemService(NotificationManager.class);
+ if (notificationManager == null) {
+ return;
+ }
+ notificationManager.createNotificationChannelGroup(new NotificationChannelGroup("status", c.getString(R.string.notification_group_status_information)));
+ notificationManager.createNotificationChannelGroup(new NotificationChannelGroup("chats", c.getString(R.string.notification_group_messages)));
+
+ final NotificationChannel foregroundServiceChannel = new NotificationChannel(FOREGROUND_CHANNEL_ID,
+ c.getString(R.string.foreground_service_channel_name),
+ NotificationManager.IMPORTANCE_MIN);
+ foregroundServiceChannel.setDescription(c.getString(R.string.foreground_service_channel_description));
+ foregroundServiceChannel.setShowBadge(false);
+ foregroundServiceChannel.setGroup("status");
+ notificationManager.createNotificationChannel(foregroundServiceChannel);
+
+ final NotificationChannel errorChannel = new NotificationChannel(ERROR_CHANNEL_ID,
+ c.getString(R.string.error_channel_name),
+ NotificationManager.IMPORTANCE_LOW);
+ errorChannel.setDescription(c.getString(R.string.error_channel_description));
+ errorChannel.setShowBadge(false);
+ errorChannel.setGroup("status");
+ notificationManager.createNotificationChannel(errorChannel);
+
+ final NotificationChannel messagesChannel = new NotificationChannel(MESSAGES_CHANNEL_ID,
+ c.getString(R.string.messages_channel_name),
+ NotificationManager.IMPORTANCE_HIGH);
+ messagesChannel.setShowBadge(true);
+ messagesChannel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), new AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+ .build());
+ messagesChannel.setLightColor(0xff00ff00);
+ final int dat = 70;
+ final long[] pattern = {0, 3 * dat, dat, dat};
+ messagesChannel.setVibrationPattern(pattern);
+ messagesChannel.enableVibration(true);
+ messagesChannel.enableLights(true);
+ messagesChannel.setGroup("chats");
+ notificationManager.createNotificationChannel(messagesChannel);
+
+ final NotificationChannel silentMessagesChannel = new NotificationChannel("silent_messages",
+ c.getString(R.string.silent_messages_channel_name),
+ NotificationManager.IMPORTANCE_LOW);
+ silentMessagesChannel.setDescription(c.getString(R.string.silent_messages_channel_description));
+ silentMessagesChannel.setShowBadge(true);
+ silentMessagesChannel.setLightColor(0xff00ff00);
+ silentMessagesChannel.enableLights(true);
+ silentMessagesChannel.setGroup("chats");
+ notificationManager.createNotificationChannel(silentMessagesChannel);
+ }
+
public boolean notify(final Message message) {
final Conversation conversation = (Conversation) message.getConversation();
return message.getStatus() == Message.STATUS_RECEIVED
&& notificationsEnabled()
&& !conversation.isMuted()
&& (conversation.alwaysNotify() || wasHighlightedOrPrivate(message))
- && (!conversation.isWithStranger() || notificationsFromStrangers()
- );
+ && (!conversation.isWithStranger() || notificationsFromStrangers())
+ ;
}
- public boolean notificationsEnabled() {
+ private boolean notificationsEnabled() {
return mXmppConnectionService.getBooleanPreference("show_notification", R.bool.show_notification);
}
@@ -96,7 +172,7 @@ public class NotificationService {
return mXmppConnectionService.getBooleanPreference("notifications_from_strangers", R.bool.notifications_from_strangers);
}
- public boolean isQuietHours() {
+ private boolean isQuietHours() {
if (!mXmppConnectionService.getBooleanPreference("enable_quiet_hours", R.bool.enable_quiet_hours)) {
return false;
}
@@ -104,7 +180,6 @@ public class NotificationService {
final long startTime = preferences.getLong("quiet_hours_start", TimePreference.DEFAULT_VALUE) % Config.MILLISECONDS_IN_DAY;
final long endTime = preferences.getLong("quiet_hours_end", TimePreference.DEFAULT_VALUE) % Config.MILLISECONDS_IN_DAY;
final long nowTime = Calendar.getInstance().getTimeInMillis() % Config.MILLISECONDS_IN_DAY;
-
if (endTime < startTime) {
return nowTime > startTime || nowTime < endTime;
} else {
@@ -159,7 +234,7 @@ public class NotificationService {
}
}
}
- Log.d(Config.LOGTAG,account.getJid().asBareJid()+": backlog message count="+count);
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": backlog message count=" + count);
return count;
}
@@ -260,9 +335,8 @@ public class NotificationService {
updateNotification(notify, false);
}
- public void updateNotification(final boolean notify, boolean summaryOnly) {
+ private void updateNotification(final boolean notify, boolean summaryOnly) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mXmppConnectionService);
-
if (notifications.size() == 0) {
cancel(NOTIFICATION_ID);
} else {
@@ -271,15 +345,16 @@ public class NotificationService {
}
final Builder mBuilder;
if (notifications.size() == 1 && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
- mBuilder = buildSingleConversations(notifications.values().iterator().next());
+ mBuilder = buildSingleConversations(notifications.values().iterator().next(), notify);
modifyForSoundVibrationAndLight(mBuilder, notify, preferences);
notify(NOTIFICATION_ID, mBuilder.build());
} else {
- mBuilder = buildMultipleConversation();
+ mBuilder = buildMultipleConversation(notify);
+ mBuilder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN);
modifyForSoundVibrationAndLight(mBuilder, notify, preferences);
if (!summaryOnly) {
for (Map.Entry<String, ArrayList<Message>> entry : notifications.entrySet()) {
- Builder singleBuilder = buildSingleConversations(entry.getValue());
+ Builder singleBuilder = buildSingleConversations(entry.getValue(), notify);
singleBuilder.setGroup(CONVERSATIONS_GROUP);
setNotificationColor(singleBuilder);
notify(entry.getKey(), NOTIFICATION_ID, singleBuilder.build());
@@ -330,9 +405,8 @@ public class NotificationService {
}
}
- private Builder buildMultipleConversation() {
- final Builder mBuilder = new NotificationCompat.Builder(
- mXmppConnectionService);
+ private Builder buildMultipleConversation(final boolean notify) {
+ final Builder mBuilder = new NotificationCompat.Builder(mXmppConnectionService, notify ? "messages" : "silent_messages");
final NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();
style.setBigContentTitle(notifications.size()
+ " "
@@ -378,8 +452,8 @@ public class NotificationService {
return mBuilder;
}
- private Builder buildSingleConversations(final ArrayList<Message> messages) {
- final Builder mBuilder = new NotificationCompat.Builder(mXmppConnectionService);
+ private Builder buildSingleConversations(final ArrayList<Message> messages, final boolean notify) {
+ final Builder mBuilder = new NotificationCompat.Builder(mXmppConnectionService, notify ? "messages" : "silent_messages");
if (messages.size() >= 1) {
final Conversation conversation = (Conversation) messages.get(0).getConversation();
final UnreadConversation.Builder mUnreadBuilder = new UnreadConversation.Builder(conversation.getName().toString());
@@ -407,8 +481,7 @@ public class NotificationService {
R.drawable.ic_reply_white_24dp,
replyLabel,
createReplyIntent(conversation, false)).addRemoteInput(remoteInput).build();
- NotificationCompat.Action wearReplyAction = new NotificationCompat.Action.Builder(
- R.drawable.ic_wear_reply,
+ NotificationCompat.Action wearReplyAction = new NotificationCompat.Action.Builder(R.drawable.ic_wear_reply,
replyLabel,
createReplyIntent(conversation, true)).addRemoteInput(remoteInput).build();
mBuilder.extend(new NotificationCompat.WearableExtender().addAction(wearReplyAction));
@@ -473,18 +546,6 @@ public class NotificationService {
return mBuilder;
}
- private static boolean displaySnoozeAction(List<Message> messages) {
- int numberOfMessagesWithoutReply = 0;
- for (Message message : messages) {
- if (message.getStatus() == Message.STATUS_RECEIVED) {
- ++numberOfMessagesWithoutReply;
- } else {
- return false;
- }
- }
- return numberOfMessagesWithoutReply >= 3;
- }
-
private void modifyForImage(final Builder builder, final UnreadConversation.Builder uBuilder,
final Message message, final ArrayList<Message> messages) {
try {
@@ -545,7 +606,7 @@ public class NotificationService {
styledString.setSpan(new StyleSpan(Typeface.BOLD), 0, name.length(), 0);
builder.setContentText(styledString);
} else {
- builder.setContentText(mXmppConnectionService.getResources().getQuantityString(R.plurals.x_messages,count,count));
+ builder.setContentText(mXmppConnectionService.getResources().getQuantityString(R.plurals.x_messages, count, count));
}
}
}
@@ -596,7 +657,7 @@ public class NotificationService {
private CharSequence getMergedBodies(final ArrayList<Message> messages) {
final StringBuilder text = new StringBuilder();
- for(Message message : messages) {
+ for (Message message : messages) {
if (text.length() != 0) {
text.append("\n");
}
@@ -606,7 +667,7 @@ public class NotificationService {
}
private PendingIntent createShowLocationIntent(final Message message) {
- Iterable<Intent> intents = GeoHelper.createGeoIntentsFromMessage(message, this.mXmppConnectionService.getApplicationContext());
+ Iterable<Intent> intents = GeoHelper.createGeoIntentsFromMessage(message, mXmppConnectionService);
for (Intent intent : intents) {
if (intent.resolveActivity(mXmppConnectionService.getPackageManager()) != null) {
return PendingIntent.getActivity(mXmppConnectionService, generateRequestCode(message.getConversation(), 18), intent, PendingIntent.FLAG_UPDATE_CURRENT);
@@ -676,7 +737,7 @@ public class NotificationService {
return PendingIntent.getService(mXmppConnectionService, generateRequestCode(conversation, 16), intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
- public PendingIntent createSnoozeIntent(Conversation conversation) {
+ private PendingIntent createSnoozeIntent(Conversation conversation) {
final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class);
intent.setAction(XmppConnectionService.ACTION_SNOOZE);
intent.putExtra("uuid", conversation.getUuid());
@@ -736,52 +797,61 @@ public class NotificationService {
}
public Notification createForegroundNotification() {
- final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mXmppConnectionService);
- List<Account> accounts = mXmppConnectionService.getAccounts();
- String status;
- Account mAccount = null;
- Log.d(Config.LOGTAG, "Accounts size " + accounts.size());
- if (accounts.size() == 1) {
- mAccount = accounts.get(0);
- if (mAccount.getStatus() == Account.State.ONLINE) {
- status = "(" + mXmppConnectionService.getString(R.string.account_status_online) + ")";
- } else if (mAccount.getStatus() == Account.State.CONNECTING) {
- status = "(" + mXmppConnectionService.getString(R.string.account_status_connecting) + ")";
- } else {
- status = "(" + mXmppConnectionService.getString(R.string.account_status_offline) + ")";
- }
- } else if (accounts.size() > 1) {
- status = ""; // todo: status for multiple accounts???
- } else {
- status = "(" + mXmppConnectionService.getString(R.string.account_status_offline) + ")";
- }
- status = " " + status;
- Log.d(Config.LOGTAG, "Status: " + status);
- mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.conversations_foreground_service) + status);
- if (Config.SHOW_CONNECTED_ACCOUNTS) {
+ final Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
+ mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.conversations_foreground_service));
+ if (Compatibility.twentySix() || Config.SHOW_CONNECTED_ACCOUNTS) {
+ List<Account> accounts = mXmppConnectionService.getAccounts();
int enabled = 0;
int connected = 0;
- for (Account account : accounts) {
- if (account.isOnlineAndConnected()) {
- connected++;
- enabled++;
- } else if (account.isEnabled()) {
- enabled++;
+ String status;
+ Account mAccount = null;
+ if (accounts != null) {
+ for (Account account : accounts) {
+ if (account.isOnlineAndConnected()) {
+ connected++;
+ enabled++;
+ } else if (account.isEnabled()) {
+ enabled++;
+ }
+ }
+ if (accounts.size() == 1) {
+ mAccount = accounts.get(0);
+ if (mAccount.getStatus() == Account.State.ONLINE) {
+ status = "(" + mXmppConnectionService.getString(R.string.account_status_online) + ")";
+ status = " " + status;
+ Log.d(Config.LOGTAG, "Status: " + status);
+ mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.conversations_foreground_service) + status);
+ } else if (mAccount.getStatus() == Account.State.CONNECTING) {
+ status = "(" + mXmppConnectionService.getString(R.string.account_status_connecting) + ")";
+ status = " " + status;
+ Log.d(Config.LOGTAG, "Status: " + status);
+ mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.conversations_foreground_service) + status);
+ } else {
+ status = "(" + mXmppConnectionService.getString(R.string.account_status_offline) + ")";
+ status = " " + status;
+ Log.d(Config.LOGTAG, "Status: " + status);
+ mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.conversations_foreground_service) + status);
+ }
+ } else if (accounts.size() > 1) {
+ mBuilder.setContentText(mXmppConnectionService.getString(R.string.connected_accounts, connected, enabled));
+ } else {
+ status = "(" + mXmppConnectionService.getString(R.string.account_status_offline) + ")";
+ status = " " + status;
+ Log.d(Config.LOGTAG, "Status: " + status);
+ mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.conversations_foreground_service) + status);
}
+ } else {
+ mBuilder.setContentText(mXmppConnectionService.getString(R.string.touch_to_open_conversations));
}
- mBuilder.setContentText(mXmppConnectionService.getString(R.string.connected_accounts, connected, enabled));
} else {
mBuilder.setContentText(mXmppConnectionService.getString(R.string.touch_to_open_conversations));
}
mBuilder.setContentIntent(createOpenConversationsIntent());
mBuilder.setWhen(0);
- mBuilder.setPriority(Config.SHOW_CONNECTED_ACCOUNTS ? NotificationCompat.PRIORITY_DEFAULT : NotificationCompat.PRIORITY_MIN);
- if (accounts.size() == 1 && accounts.get(0).getStatus() == Account.State.ONLINE) {
- mBuilder.setSmallIcon(R.drawable.ic_link_white_24dp);
- } else if (accounts.size() > 1) {
- mBuilder.setSmallIcon(R.drawable.ic_link_white_24dp); // todo: status for multiple accounts???
- } else {
- mBuilder.setSmallIcon(R.drawable.ic_unlink_white_24dp);
+ mBuilder.setPriority(Notification.PRIORITY_LOW);
+ mBuilder.setSmallIcon(R.drawable.ic_link_white_24dp);
+ if (Compatibility.twentySix()) {
+ mBuilder.setChannelId(FOREGROUND_CHANNEL_ID);
}
return mBuilder.build();
}
@@ -801,10 +871,10 @@ public class NotificationService {
errors.add(account);
}
}
- if (mXmppConnectionService.showForegroundService()) {
+ if (Compatibility.keepForegroundService(mXmppConnectionService)) {
notify(FOREGROUND_NOTIFICATION_ID, createForegroundNotification());
}
- final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mXmppConnectionService);
+ final Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
if (errors.size() == 0) {
cancel(ERROR_NOTIFICATION_ID);
return;
@@ -819,38 +889,70 @@ public class NotificationService {
mXmppConnectionService.getString(R.string.try_again),
createTryAgainIntent());
mBuilder.setDeleteIntent(createDismissErrorIntent());
- mBuilder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE);
- mBuilder.setSmallIcon(R.drawable.ic_warning_white_24dp);
- mBuilder.setLocalOnly(true);
- mBuilder.setPriority(NotificationCompat.PRIORITY_LOW);
- if (errors.size() == 1) {
- Intent intent = new Intent(mXmppConnectionService, EditAccountActivity.class);
- Account mAccount = mXmppConnectionService.getAccounts().get(0);
- intent.putExtra("jid", mAccount.getJid().asBareJid().toString());
- intent.putExtra("init", false);
- mBuilder.setContentIntent(PendingIntent.getActivity(mXmppConnectionService,
- 145,
- intent,
- PendingIntent.FLAG_UPDATE_CURRENT));
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ mBuilder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE);
+ mBuilder.setSmallIcon(R.drawable.ic_warning_white_24dp);
} else {
- mBuilder.setContentIntent(PendingIntent.getActivity(mXmppConnectionService,
- 145,
- new Intent(mXmppConnectionService, ManageAccountActivity.class),
- PendingIntent.FLAG_UPDATE_CURRENT));
+ mBuilder.setSmallIcon(R.drawable.ic_warning_white_24dp);
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
+ mBuilder.setLocalOnly(true);
+ }
+ mBuilder.setPriority(Notification.PRIORITY_LOW);
+ mBuilder.setContentIntent(PendingIntent.getActivity(mXmppConnectionService,
+ 145,
+ new Intent(mXmppConnectionService, ManageAccountActivity.class),
+ PendingIntent.FLAG_UPDATE_CURRENT));
+ if (Compatibility.twentySix()) {
+ mBuilder.setChannelId(ERROR_CHANNEL_ID);
}
notify(ERROR_NOTIFICATION_ID, mBuilder.build());
}
- public Notification updateFileAddingNotification(int current, Message message) {
- final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mXmppConnectionService);
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mXmppConnectionService);
+ public void updateFileAddingNotification(int current, Message message) {
+ Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.transcoding_video));
mBuilder.setProgress(100, current, false);
mBuilder.setSmallIcon(R.drawable.ic_hourglass_empty_white_24dp);
mBuilder.setContentIntent(createContentIntent(message.getConversation()));
+ if (Compatibility.twentySix()) {
+ mBuilder.setChannelId(FOREGROUND_CHANNEL_ID);
+ }
Notification notification = mBuilder.build();
notify(FOREGROUND_NOTIFICATION_ID, notification);
- return notification;
+ }
+
+ public Notification exportLogsNotification() {
+ Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
+ mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.app_name));
+ mBuilder.setContentText(mXmppConnectionService.getString(R.string.notification_export_logs_title));
+ mBuilder.setProgress(0, 0, true);
+ mBuilder.setSmallIcon(R.drawable.ic_import_export_white_24dp);
+ if (Compatibility.twentySix()) {
+ mBuilder.setChannelId(FOREGROUND_CHANNEL_ID);
+ }
+ return mBuilder.build();
+ }
+
+ public void exportLogsServiceNotification(Notification notification) {
+ notify(FOREGROUND_NOTIFICATION_ID, notification);
+ }
+
+ public Notification AppUpdateNotification(PendingIntent intent, String version, String filesize) {
+ Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService);
+ mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.app_name));
+ mBuilder.setContentText(mXmppConnectionService.getString(R.string.notification_export_logs_title));
+ mBuilder.setContentText(String.format(mXmppConnectionService.getString(R.string.update_available), version, filesize));
+ mBuilder.setSmallIcon(R.drawable.ic_update_notification);
+ mBuilder.setContentIntent(intent);
+ if (Compatibility.twentySix()) {
+ mBuilder.setChannelId(FOREGROUND_CHANNEL_ID);
+ }
+ return mBuilder.build();
+ }
+
+ public void AppUpdateServiceNotification(Notification notification) {
+ notify(FOREGROUND_NOTIFICATION_ID, notification);
}
private void notify(String tag, int id, Notification notification) {
diff --git a/src/main/java/de/pixart/messenger/services/UpdateService.java b/src/main/java/de/pixart/messenger/services/UpdateService.java
index 3b3829290..bf5242939 100644
--- a/src/main/java/de/pixart/messenger/services/UpdateService.java
+++ b/src/main/java/de/pixart/messenger/services/UpdateService.java
@@ -1,14 +1,11 @@
package de.pixart.messenger.services;
-import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
-import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import android.widget.Toast;
@@ -27,12 +24,12 @@ import de.pixart.messenger.R;
import de.pixart.messenger.ui.UpdaterActivity;
import static de.pixart.messenger.http.HttpConnectionManager.getProxy;
-import static de.pixart.messenger.services.NotificationService.UPDATE_NOTIFICATION_ID;
public class UpdateService extends AsyncTask<String, Object, UpdateService.Wrapper> {
private boolean mUseTor;
private Context context;
private String store;
+ private NotificationService getNotificationService;
public UpdateService() {
}
@@ -40,6 +37,7 @@ public class UpdateService extends AsyncTask<String, Object, UpdateService.Wrapp
this.context = context;
this.store = Store;
this.mUseTor = mXmppConnectionService.useTorToConnect();
+ this.getNotificationService = mXmppConnectionService.getNotificationService();
}
@Override
@@ -145,14 +143,7 @@ public class UpdateService extends AsyncTask<String, Object, UpdateService.Wrapp
intent.putExtra("changelog", changelog);
intent.putExtra("store", store);
PendingIntent pi = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
- final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
- mBuilder.setContentTitle(context.getString(R.string.update_service));
- mBuilder.setContentText(String.format(context.getString(R.string.update_available), version, filesize));
- mBuilder.setSmallIcon(R.drawable.ic_update_notification);
- mBuilder.setContentIntent(pi);
- Notification notification = mBuilder.build();
- notificationManager.notify(UPDATE_NOTIFICATION_ID, notification);
+ getNotificationService.AppUpdateServiceNotification(getNotificationService.AppUpdateNotification(pi, version, filesize));
}
private int checkVersion(String remoteVersion, String installedVersion) {
diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
index 896061457..af94d017b 100644
--- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
+++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
@@ -1,5 +1,6 @@
package de.pixart.messenger.services;
+import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.AlarmManager;
@@ -114,6 +115,7 @@ import de.pixart.messenger.ui.SettingsActivity;
import de.pixart.messenger.ui.UiCallback;
import de.pixart.messenger.ui.interfaces.OnAvatarPublication;
import de.pixart.messenger.ui.interfaces.OnSearchResultsAvailable;
+import de.pixart.messenger.utils.Compatibility;
import de.pixart.messenger.utils.ConversationsFileObserver;
import de.pixart.messenger.utils.CryptoHelper;
import de.pixart.messenger.utils.ExceptionHelper;
@@ -170,8 +172,6 @@ public class XmppConnectionService extends Service {
public static final String ACTION_FCM_MESSAGE_RECEIVED = "fcm_message_received";
public static final String FDroid = "org.fdroid.fdroid";
public static final String PlayStore = "com.android.vending";
- public static final String Yalp = "com.github.yeriomin.yalpstore";
- private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
private static final String SETTING_LAST_ACTIVITY_TS = "last_activity_timestamp";
static {
@@ -234,6 +234,7 @@ public class XmppConnectionService extends Service {
) {
@Override
public void onEvent(int event, String path) {
+ Log.d(Config.LOGTAG, "event " + event + " path=" + path);
markFileDeleted(path);
}
};
@@ -244,17 +245,16 @@ public class XmppConnectionService extends Service {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
- Intent intent = new Intent(getApplicationContext(),
- XmppConnectionService.class);
- intent.setAction(ACTION_MERGE_PHONE_CONTACTS);
- startService(intent);
+ if (restoredFromDatabaseLatch.getCount() == 0) {
+ loadPhoneContacts();
+ }
}
};
private MemorizingTrustManager mMemorizingTrustManager;
private NotificationService mNotificationService = new NotificationService(this);
private ShortcutService mShortcutService = new ShortcutService(this);
private AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false);
- private AtomicBoolean mForceForegroundService = new AtomicBoolean(false);
+ protected AtomicBoolean mForceForegroundService = new AtomicBoolean(false);
private OnMessagePacketReceived mMessageParser = new MessageParser(this);
private OnPresencePacketReceived mPresenceParser = new PresenceParser(this);
private IqParser mIqParser = new IqParser(this);
@@ -590,11 +590,6 @@ public class XmppConnectionService extends Service {
resetAllAttemptCounts(true, false);
}
break;
- case ACTION_MERGE_PHONE_CONTACTS:
- if (restoredFromDatabaseLatch.getCount() == 0) {
- loadPhoneContacts();
- }
- return START_STICKY;
case Intent.ACTION_SHUTDOWN:
logoutAndSave(true);
return START_NOT_STICKY;
@@ -1094,6 +1089,9 @@ public class XmppConnectionService extends Service {
Resolver.init(this);
this.mRandom = new SecureRandom();
updateMemorizingTrustmanager();
+ if (Compatibility.twentySix()) {
+ mNotificationService.initializeChannels();
+ }
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
this.mBitmapCache = new LruCache<String, Bitmap>(cacheSize) {
@@ -1120,7 +1118,10 @@ public class XmppConnectionService extends Service {
editor.apply();
restoreFromDatabase();
- getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
+ //TODO get this restarted if users gives permission
+ getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
+ }
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d(Config.LOGTAG, "starting file observer");
new Thread(fileObserver::startWatching).start();
@@ -1203,7 +1204,7 @@ public class XmppConnectionService extends Service {
}
public void toggleForegroundService() {
- if (mForceForegroundService.get() || (showForegroundService())) {
+ if (mForceForegroundService.get() || (Compatibility.keepForegroundService(this) && hasEnabledAccounts())) {
startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, this.mNotificationService.createForegroundNotification());
Log.d(Config.LOGTAG, "started foreground service");
} else {
@@ -1215,7 +1216,8 @@ public class XmppConnectionService extends Service {
@Override
public void onTaskRemoved(final Intent rootIntent) {
super.onTaskRemoved(rootIntent);
- if (showForegroundService() || mForceForegroundService.get()) {
+ //TODO check for accounts enabled
+ if ((Compatibility.keepForegroundService(this) && hasEnabledAccounts()) || mForceForegroundService.get()) {
Log.d(Config.LOGTAG, "ignoring onTaskRemoved because foreground service is activated");
} else {
this.logoutAndSave(false);
@@ -2195,6 +2197,7 @@ public class XmppConnectionService extends Service {
updateAccountUi();
getNotificationService().updateErrorNotification();
syncEnabledAccountSetting();
+ toggleForegroundService();
}
}
@@ -2637,6 +2640,9 @@ public class XmppConnectionService extends Service {
}
private boolean hasEnabledAccounts() {
+ if (this.accounts == null) {
+ return true; // set to true if accounts could not be fetched - used for notifications
+ }
for (Account account : this.accounts) {
if (account.isEnabled()) {
return true;
@@ -4330,10 +4336,6 @@ public class XmppConnectionService extends Service {
return getBooleanPreference(SettingsActivity.BLIND_TRUST_BEFORE_VERIFICATION, R.bool.btbv);
}
- public boolean showForegroundService() {
- return getBooleanPreference(SettingsActivity.SHOW_FOREGROUND_SERVICE, R.bool.show_foreground_service);
- }
-
public void ScheduleAutomaticExport() {
//start export log service every day at given time
if (Config.ExportLogs) {
diff --git a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java
index 1ace03e5e..4bf9d26cc 100644
--- a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java
@@ -17,6 +17,7 @@ import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.support.annotation.NonNull;
+import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater;
@@ -541,7 +542,7 @@ public class SettingsActivity extends XmppActivity implements
}
private void startExport() {
- startService(new Intent(getApplicationContext(), ExportLogsService.class));
+ ContextCompat.startForegroundService(this, new Intent(this, ExportLogsService.class));
}
private void displayToast(final String msg) {
diff --git a/src/main/java/de/pixart/messenger/ui/SettingsFragment.java b/src/main/java/de/pixart/messenger/ui/SettingsFragment.java
index b40875f7c..ec4898f89 100644
--- a/src/main/java/de/pixart/messenger/ui/SettingsFragment.java
+++ b/src/main/java/de/pixart/messenger/ui/SettingsFragment.java
@@ -10,6 +10,7 @@ import android.text.TextUtils;
import de.pixart.messenger.Config;
import de.pixart.messenger.R;
+import de.pixart.messenger.utils.Compatibility;
public class SettingsFragment extends PreferenceFragment {
@@ -30,6 +31,7 @@ public class SettingsFragment extends PreferenceFragment {
mCategory.removePreference(cleanPrivateStorage);
}
}
+ Compatibility.removeUnusedPreferences(this);
if (!TextUtils.isEmpty(page)) {
openPreferenceScreen(page);
diff --git a/src/main/java/de/pixart/messenger/ui/XmppActivity.java b/src/main/java/de/pixart/messenger/ui/XmppActivity.java
index 3ab6bfc6a..acb970e82 100644
--- a/src/main/java/de/pixart/messenger/ui/XmppActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/XmppActivity.java
@@ -536,7 +536,11 @@ public abstract class XmppActivity extends ActionBarActivity {
intent.setAction(Intent.ACTION_SEND);
intent.setData(uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- startService(intent);
+ try {
+ startService(intent);
+ } catch (Exception e) {
+ Log.e(Config.LOGTAG, "unable to delegate uri permission", e);
+ }
}
protected void inviteToConversation(Conversation conversation) {
diff --git a/src/main/java/de/pixart/messenger/utils/Compatibility.java b/src/main/java/de/pixart/messenger/utils/Compatibility.java
new file mode 100644
index 000000000..95d7b4ef2
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/utils/Compatibility.java
@@ -0,0 +1,66 @@
+package de.pixart.messenger.utils;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.preference.Preference;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.support.annotation.BoolRes;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import de.pixart.messenger.R;
+import de.pixart.messenger.ui.SettingsActivity;
+import de.pixart.messenger.ui.SettingsFragment;
+
+public class Compatibility {
+ private static final List<String> UNUSED_SETTINGS_POST_TWENTYSIX = Arrays.asList(
+ SettingsActivity.SHOW_FOREGROUND_SERVICE,
+ "led",
+ "notification_ringtone",
+ "notification_headsup",
+ "vibrate_on_notification");
+ private static final List<String> UNUESD_SETTINGS_PRE_TWENTYSIX = Collections.singletonList("more_notification_settings");
+
+ public static boolean twentySix() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
+ }
+
+ private static boolean getBooleanPreference(Context context, String name, @BoolRes int res) {
+ return getPreferences(context).getBoolean(name, context.getResources().getBoolean(res));
+ }
+
+ private static SharedPreferences getPreferences(final Context context) {
+ return PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ public static boolean keepForegroundService(Context context) {
+ return twentySix() || getBooleanPreference(context, SettingsActivity.SHOW_FOREGROUND_SERVICE, R.bool.show_foreground_service);
+ }
+
+ public static void removeUnusedPreferences(SettingsFragment settingsFragment) {
+ List<PreferenceScreen> screens = Arrays.asList(
+ (PreferenceScreen) settingsFragment.findPreference("notifications"));
+ List<PreferenceCategory> categories = Arrays.asList(
+ (PreferenceCategory) settingsFragment.findPreference("general"));
+ for (String key : (twentySix() ? UNUSED_SETTINGS_POST_TWENTYSIX : UNUESD_SETTINGS_PRE_TWENTYSIX)) {
+ Preference preference = settingsFragment.findPreference(key);
+ if (preference != null) {
+ for (PreferenceScreen screen : screens) {
+ if (screen != null) {
+ screen.removePreference(preference);
+ }
+ }
+ for (PreferenceCategory category : categories) {
+ if (category != null) {
+ category.removePreference(preference);
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/utils/ConversationsFileObserver.java b/src/main/java/de/pixart/messenger/utils/ConversationsFileObserver.java
index 4e275df3f..73d5589e4 100644
--- a/src/main/java/de/pixart/messenger/utils/ConversationsFileObserver.java
+++ b/src/main/java/de/pixart/messenger/utils/ConversationsFileObserver.java
@@ -2,12 +2,15 @@ package de.pixart.messenger.utils;
import android.os.FileObserver;
+import android.util.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
+import de.pixart.messenger.Config;
+
/**
* Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2015 ownCloud Inc.
@@ -19,7 +22,7 @@ public abstract class ConversationsFileObserver {
private final String path;
private final List<SingleFileObserver> mObservers = new ArrayList<>();
- public ConversationsFileObserver(String path) {
+ protected ConversationsFileObserver(String path) {
this.path = path;
}
@@ -88,13 +91,17 @@ public abstract class ConversationsFileObserver {
private class SingleFileObserver extends FileObserver {
private final String path;
- public SingleFileObserver(String path, int mask) {
+ SingleFileObserver(String path, int mask) {
super(path, mask);
this.path = path;
}
@Override
public void onEvent(int event, String filename) {
+ if (filename == null) {
+ Log.d(Config.LOGTAG, "ignored file event with NULL filename (event=" + event + ")");
+ return;
+ }
ConversationsFileObserver.this.onEvent(event, path + '/' + filename);
}
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 1481bc6cc..3c1e766da 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -814,4 +814,15 @@
<string name="pref_quick_share_attachment_choice">Attachment choice</string>
<string name="phone_book">Address book</string>
<string name="unable_to_save_recording">Unable to save recording</string>
+ <string name="foreground_service_channel_name">Foreground service</string>
+ <string name="foreground_service_channel_description">This notification category is used to display a permanent notification indicating that Conversations is running.</string>
+ <string name="notification_group_status_information">Status Information</string>
+ <string name="error_channel_name">Connectivity Problems</string>
+ <string name="error_channel_description">This notification category is used to display a notification in case there is a problem connecting to an account.</string>
+ <string name="notification_group_messages">Messages</string>
+ <string name="messages_channel_name">Messages</string>
+ <string name="silent_messages_channel_name">Silent messages</string>
+ <string name="silent_messages_channel_description">This notification group is used to display notifications that should not trigger any sound. For example when being active on another device (Grace Period).</string>
+ <string name="pref_more_notification_settings">Notification Settings</string>
+ <string name="pref_more_notification_settings_summary">Importance, Sound, Vibrate</string>
</resources>
diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml
index b4edb7a34..73d817782 100644
--- a/src/main/res/xml/preferences.xml
+++ b/src/main/res/xml/preferences.xml
@@ -152,6 +152,20 @@
android:key="notifications_from_strangers"
android:summary="@string/pref_notifications_from_strangers_summary"
android:title="@string/pref_notifications_from_strangers" />
+ <PreferenceScreen
+ android:dependency="show_notification"
+ android:key="more_notification_settings"
+ android:summary="@string/pref_more_notification_settings_summary"
+ android:title="@string/pref_more_notification_settings">
+ <intent android:action="android.settings.CHANNEL_NOTIFICATION_SETTINGS">
+ <extra
+ android:name="android.provider.extra.APP_PACKAGE"
+ android:value="@string/applicationId" />
+ <extra
+ android:name="android.provider.extra.CHANNEL_ID"
+ android:value="messages" />
+ </intent>
+ </PreferenceScreen>
</PreferenceScreen>
<!--Attachments-->
<PreferenceScreen