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

Notification Channel sound uri should not be based on fragile resource ids #94

Merged
Merged
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ Supported notification fields:
* "tag" => "custom_notification_tag", // push with the same tag will replace each other
* "sound" => "string" (e.g. "notification.mp3" will play /platform/android/res/raw/notification.mp3)

### Android: Note for switching between v<=v2.0.2 and >=v2.0.3 if you use notification channels with custom sounds
With versions prior to 2.0.3 of this module, FirebaseCloudMessaging.createNotificationChannel would create the notification sound uri using the resource id of the sound file in the `res/raw` directory. However, as described in this [android issue](https://issuetracker.google.com/issues/131303134), those resource ids can change to reference different files (or no file) between app versions, and that happens the notification channel may play a different or no sound than originally intended.
With version 2.0.3 and later, we now create the uri's using the string filename so that it will not change if resource ids change. So if you are on version <=2.0.2 and are switching to version >=2.0.3, you will want to check if this is a problem for you by installing a test app using version >= 2.0.3 as an upgrade to a previous test app using version <= 2.0.2. Note that you should not uninstall the first app before installing the second app; nor should you reset user data.
If it is a problem you can workaround by first deleting the existing channel using deleteNotificationChannel, and then recreating the channel with the same settings as before, except with a different id. Don't forget that your push server will need to be version aware and send to this new channel for newer versions of your apps.

## API

### `FirebaseCloudMessaging`
Expand Down Expand Up @@ -236,6 +241,9 @@ so receive the `gcm.message_id` key from the notification payload instead.

Read more in the [official Android docs](https://developer.android.com/reference/android/app/NotificationChannel).

`deleteNotificationChannel(channelId)` - Android-only
- `channelId` (String) - same as the id used to create in createNotificationChannel

`setForceShowInForeground(showInForeground)` - Android-only
- `showInForeground` (Boolean) Force the notifications to be shown in foreground.

Expand Down
2 changes: 1 addition & 1 deletion android/manifest
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# this is your module manifest and used by Titanium
# during compilation, packaging, distribution, etc.
#
version: 2.0.2
version: 2.0.3
apiversion: 4
architectures: arm64-v8a armeabi-v7a x86
description: titanium-firebase-cloud-messaging
Expand Down
21 changes: 16 additions & 5 deletions android/src/firebase/cloudmessaging/CloudMessagingModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
Expand Down Expand Up @@ -216,10 +215,8 @@ public void createNotificationChannel(KrollDict options)
if (sound.equals("default") || sound.equals("")) {
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
} else if (!sound.equals("silent")) {
String path = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/"
+ Utils.getResourceIdentifier("raw", sound);
Log.d(LCAT, "createNotificationChannel with sound " + sound + " at " + path);
soundUri = Uri.parse(path);
soundUri = Utils.getSoundUri(sound);
Log.d(LCAT, "createNotificationChannel with sound " + sound + " at " + soundUri.toString());
}

NotificationChannel channel = new NotificationChannel(channelId, channelName, importanceVal);
Expand All @@ -238,6 +235,20 @@ public void createNotificationChannel(KrollDict options)
notificationManager.createNotificationChannel(channel);
}

@Kroll.method
public void deleteNotificationChannel(String channelId)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
Log.d(LCAT, "deleteNotificationChannel " + channelId);

Context context = Utils.getApplicationContext();
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.deleteNotificationChannel(channelId);
}

@Kroll.getProperty
public String fcmToken()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,8 @@ private Boolean showNotification(RemoteMessage remoteMessage)
}

if (params.get("sound") != null && params.get("sound") != "" && !params.get("sound").isEmpty()) {
int resource = getResource("raw", params.get("sound"));
if (resource != 0) {
defaultSoundUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + resource);
Log.d(TAG, "custom sound: " + defaultSoundUri);
} else {
Log.d(TAG, "custom sound not found");
builder_defaults |= Notification.DEFAULT_SOUND;
}
defaultSoundUri = Utils.getSoundUri(params.get("sound"));
Log.d(TAG, "showNotification custom sound: " + defaultSoundUri);
} else {
builder_defaults |= Notification.DEFAULT_SOUND;
}
Expand Down
17 changes: 15 additions & 2 deletions android/src/firebase/cloudmessaging/Utils.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package firebase.cloudmessaging;

import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
import org.appcelerator.titanium.TiApplication;

public final class Utils
Expand All @@ -35,6 +37,17 @@ public static int getResourceIdentifier(String type, String name)
return icon;
}

public static Uri getSoundUri(String name)
{
Context context = getApplicationContext();
return new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(context.getPackageName())
.appendPath("raw")
.appendPath(name)
.build();
}

public static Context getApplicationContext()
{
return TiApplication.getInstance().getApplicationContext();
Expand Down