1
0
mirror of https://github.com/nerzhul/ownCloud-SMS-App.git synced 2025-06-05 23:16:27 +00:00

Fix notifications not being shown on modern Androids (#221)

* Add notification channels support

* Update Travis CI config
This commit is contained in:
Dmitriy Bogdanov 2025-01-23 18:47:17 +01:00 committed by GitHub
parent 5ea03be8d6
commit 7d677a9fe2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 134 additions and 42 deletions

View File

@ -12,15 +12,15 @@ jdk:
- oraclejdk8
before_install:
- yes | sdkmanager "platforms;android-27"
- yes | sdkmanager "platforms;android-28"
android:
components:
- tools
- platform-tools
- extra
- build-tools-27.0.3
- android-27
- build-tools-28.0.3
- android-28
licenses:
- 'android-sdk-license-.+'
- 'google-gdk-license-.+'

View File

@ -93,12 +93,16 @@ public interface ASyncSMSSync {
if (prefs.showSyncNotifications()) {
OCSMSNotificationUI.notify(_context, _context.getString(R.string.sync_title),
_context.getString(R.string.sync_inprogress), OCSMSNotificationType.SYNC.ordinal());
_context.getString(R.string.sync_inprogress), OCSMSNotificationType.SYNC);
}
syncStartupDate = smsBuffer.getLastMessageDate();
performSync(smsBuffer);
hasSyncSomething = true;
try {
syncStartupDate = smsBuffer.getLastMessageDate();
performSync(smsBuffer);
hasSyncSomething = true;
} finally {
OCSMSNotificationUI.cancel(_context, OCSMSNotificationType.SYNC);
}
}
}
@ -114,17 +118,16 @@ public interface ASyncSMSSync {
// Fetch API version first to do some early verifications
Log.i(ASyncSMSSync.TAG, "Server API version: " + _client.getServerAPIVersion());
_client.doPushRequest(smsBuffer);
OCSMSNotificationUI.cancel(_context);
OCSMSNotificationUI.cancel(_context, OCSMSNotificationType.SYNC_FAILED);
} catch (IllegalStateException e) { // Fail to read account data
OCSMSNotificationUI.notify(_context, _context.getString(R.string.fatal_error),
e.getMessage(), OCSMSNotificationType.SYNC_FAILED.ordinal());
e.getMessage(), OCSMSNotificationType.SYNC_FAILED);
} catch (OCSyncException e) {
Log.e(ASyncSMSSync.TAG, _context.getString(e.getErrorId()));
OCSMSNotificationUI.notify(_context, _context.getString(R.string.fatal_error),
e.getMessage(), OCSMSNotificationType.SYNC_FAILED.ordinal());
e.getMessage(), OCSMSNotificationType.SYNC_FAILED);
}
}
OCSMSNotificationUI.cancel(_context);
smsBuffer.clear();
}

View File

@ -0,0 +1,48 @@
package fr.unix_experience.owncloud_sms.enums;
import android.app.NotificationManager;
import android.os.Build;
import android.support.annotation.StringRes;
import fr.unix_experience.owncloud_sms.R;
public enum OCSMSNotificationChannel {
DEFAULT("OCSMS_DEFAULT", R.string.notification_channel_name_default, null),
SYNC("OCSMS_SYNC", R.string.notification_channel_name_sync, null);
static {
// well, that's a bit of a hack :/
// can be inlined in the future
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
DEFAULT.importance = NotificationManager.IMPORTANCE_DEFAULT;
SYNC.importance = NotificationManager.IMPORTANCE_LOW;
}
}
private final String channelId;
private final int nameResId;
private final Integer descResId;
private int importance;
OCSMSNotificationChannel(String channelId, @StringRes int nameResId, @StringRes Integer descResId) {
this.channelId = channelId;
this.nameResId = nameResId;
this.descResId = descResId;
}
public String getChannelId() {
return channelId;
}
public int getNameResId() {
return nameResId;
}
public Integer getDescResId() {
return descResId;
}
public int getImportance() {
return importance;
}
}

View File

@ -18,8 +18,23 @@ package fr.unix_experience.owncloud_sms.enums;
*/
public enum OCSMSNotificationType {
SYNC,
SYNC_FAILED,
DEBUG,
PERMISSION,
SYNC(OCSMSNotificationChannel.SYNC, 0),
SYNC_FAILED(OCSMSNotificationChannel.DEFAULT, 1),
PERMISSION(OCSMSNotificationChannel.DEFAULT, 2);
private final OCSMSNotificationChannel channel;
private final int notificationId;
OCSMSNotificationType(OCSMSNotificationChannel channel, int notificationId) {
this.channel = channel;
this.notificationId = notificationId;
}
public OCSMSNotificationChannel getChannel() {
return channel;
}
public int getNotificationId() {
return notificationId;
}
}

View File

@ -17,17 +17,17 @@ package fr.unix_experience.owncloud_sms.notifications;
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import fr.unix_experience.owncloud_sms.R;
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationChannel;
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
/**
* Helper class for showing and canceling ui
@ -42,25 +42,30 @@ public class OCSMSNotificationUI {
*/
private static final String NOTIFICATION_TAG = "OCSMS_NOTIFICATION";
public static void notify(Context context, String titleString,
String contentString, OCSMSNotificationType type) {
notify(context, titleString, contentString,
type.getChannel().getChannelId(), type.getNotificationId());
}
/**
* Shows the notification, or updates a previously shown notification of
* this type, with the given parameters.
*
* @see #cancel(Context)
* @see #cancel(Context, OCSMSNotificationType)
*/
public static void notify(Context context, String titleString,
String contentString, int number) {
public static void notify(Context context, String titleString, String contentString,
String channelId, int notificationId) {
Resources res = context.getResources();
// This image is used as the notification's large icon (thumbnail).
// TODO: Remove this if your notification has no relevant thumbnail.
Bitmap picture = BitmapFactory.decodeResource(res, R.mipmap.ic_launcher);
// Bitmap picture = BitmapFactory.decodeResource(res, R.mipmap.ic_launcher);
String ticker = (titleString.length() > 20) ? titleString.substring(0, 20) : titleString;
// String ticker = (titleString.length() > 20) ? titleString.substring(0, 20) : titleString;
String title = res.getString(R.string.ui_notification_title_template, titleString);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
// Set appropriate defaults for the notification light, sound,
// and vibration.
@ -77,9 +82,6 @@ public class OCSMSNotificationUI {
// Set ticker text (preview) information for this notification.
//.setTicker(ticker)
// Show a number. This is useful when stacking notifications of
// a single type.
.setNumber(number)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(contentString)
.setBigContentTitle(title)
@ -87,24 +89,45 @@ public class OCSMSNotificationUI {
.setAutoCancel(true)
.setColor(context.getResources().getColor(R.color.oc_primary));
OCSMSNotificationUI.notify(context, builder.build());
notify(context, builder.build(), notificationId);
}
@TargetApi(Build.VERSION_CODES.ECLAIR)
private static void notify(Context context, Notification notification) {
private static void notify(Context context, Notification notification, int notificationId) {
NotificationManager nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(OCSMSNotificationUI.NOTIFICATION_TAG, 0, notification);
createNotificationChannels(context, nm);
nm.notify(OCSMSNotificationUI.NOTIFICATION_TAG, notificationId, notification);
}
/**
* Cancels any notifications of this type previously shown using
* {@link #notify(Context, String, String, int)}.
* {@link #notify(Context, String, String, OCSMSNotificationType)}.
*/
@TargetApi(Build.VERSION_CODES.ECLAIR)
public static void cancel(Context context) {
public static void cancel(Context context, OCSMSNotificationType type) {
cancel(context, type.getNotificationId());
}
public static void cancel(Context context, int notificationId) {
NotificationManager nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
nm.cancel(OCSMSNotificationUI.NOTIFICATION_TAG, 0);
nm.cancel(OCSMSNotificationUI.NOTIFICATION_TAG, notificationId);
}
private static void createNotificationChannels(Context context, NotificationManager nm) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
for (OCSMSNotificationChannel ocsmsChannel : OCSMSNotificationChannel.values()) {
NotificationChannel channel = new NotificationChannel(
ocsmsChannel.getChannelId(),
context.getString(ocsmsChannel.getNameResId()),
ocsmsChannel.getImportance());
if (ocsmsChannel.getDescResId() != null) {
channel.setDescription(context.getString(ocsmsChannel.getDescResId()));
}
nm.createNotificationChannel(channel);
}
}
}
}

View File

@ -67,7 +67,7 @@ public class PermissionChecker {
// For context only show a notification
OCSMSNotificationUI.notify(context, context.getString(R.string.notif_permission_required),
context.getString(R.string.notif_permission_required_content),
OCSMSNotificationType.PERMISSION.ordinal());
OCSMSNotificationType.PERMISSION);
return false;
}

View File

@ -45,7 +45,7 @@ class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
if (new OCSMSSharedPrefs(getContext()).showSyncNotifications()) {
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.sync_title),
getContext().getString(R.string.sync_inprogress), OCSMSNotificationType.SYNC.ordinal());
getContext().getString(R.string.sync_inprogress), OCSMSNotificationType.SYNC);
}
try {
@ -56,14 +56,13 @@ class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
// and push datas
_client.doPushRequest(null);
OCSMSNotificationUI.cancel(getContext());
OCSMSNotificationUI.cancel(getContext(), OCSMSNotificationType.SYNC_FAILED);
} catch (IllegalStateException e) {
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.fatal_error),
e.getMessage(), OCSMSNotificationType.SYNC_FAILED.ordinal());
e.getMessage(), OCSMSNotificationType.SYNC_FAILED);
} catch (OCSyncException e) {
OCSMSNotificationUI.cancel(getContext());
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.fatal_error),
getContext().getString(e.getErrorId()), OCSMSNotificationType.SYNC_FAILED.ordinal());
getContext().getString(e.getErrorId()), OCSMSNotificationType.SYNC_FAILED);
if (e.getErrorType() == OCSyncErrorType.IO) {
syncResult.stats.numIoExceptions++;
}
@ -76,6 +75,8 @@ class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
else {
Log.w(SmsSyncAdapter.TAG, "onPerformSync: unhandled response");
}
} finally {
OCSMSNotificationUI.cancel(getContext(), OCSMSNotificationType.SYNC);
}
}

View File

@ -206,6 +206,8 @@
<string name="sync_title">Sync process</string>
<string name="sync_inprogress">Sync in progress …</string>
<string name="fatal_error">Fatal error ! </string>
<string name="notification_channel_name_default">Default</string>
<string name="notification_channel_name_sync">Sync</string>
<!-- Errors -->
<string name="err_sync_get_smslist">Error #1: Invalid data received from server when getting previous messages</string>