Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix notifications not being shown on modern Androids #221

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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-.+'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,16 @@ public void run() {

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);
}
}
}

Expand All @@ -114,17 +118,16 @@ private void performSync(SmsBuffer smsBuffer) {
// 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();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,23 @@
*/

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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
* 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
Expand All @@ -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.
Expand All @@ -77,34 +82,52 @@ public static void notify(Context context, String titleString,
// 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)
.setSummaryText(titleString))
.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);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void onClick(DialogInterface dialog, int which) {
// 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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void onPerformSync(Account account, Bundle extras, String authority,

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 {
Expand All @@ -56,14 +56,13 @@ public void onPerformSync(Account account, Bundle extras, String authority,

// 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++;
}
Expand All @@ -76,6 +75,8 @@ else if (e.getErrorType() == OCSyncErrorType.AUTH) {
else {
Log.w(SmsSyncAdapter.TAG, "onPerformSync: unhandled response");
}
} finally {
OCSMSNotificationUI.cancel(getContext(), OCSMSNotificationType.SYNC);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down