I am newbie Android developer who is trying to debug why our app is crashing. We are experiencing crashes when we attempt to send push notifications to an Android device. This is an onboarding ticket that I need to solve .I don't know what is causing this issue which can be reproduced in Android N, O and P. Our stack trace from Fabric is given below
Caused by java.lang.SecurityException: UID 10243 does not have permission to content://media/external/audio/media/5927 [user 0]
at android.os.Parcel.createException + 1966(Parcel.java:1966)
at android.os.Parcel.readException + 1934(Parcel.java:1934)
at android.os.Parcel.readException + 1884(Parcel.java:1884)
at android.app.INotificationManager$Stub$Proxy.enqueueNotificationWithTag + 1653(INotificationManager.java:1653)
at android.app.NotificationManager.notifyAsUser + 429(NotificationManager.java:429)
at android.app.NotificationManager.notify + 379(NotificationManager.java:379)
at android.app.NotificationManager.notify + 355(NotificationManager.java:355)
at com.myproject.mobile.notifications.NotificationHelper.process + 66(NotificationHelper.java:66)
at com.myproject.mobile.notifications.NotificationService.constructNotification + 709(NotificationService.java:709)
at com.myproject.mobile.notifications.NotificationService.processNotification + 173(NotificationService.java:173)
at com.myproject.mobile.notifications.PushJobIntentService.onHandleWork + 24(PushJobIntentService.java:24)
at androidx.core.app.JobIntentService$CommandProcessor.doInBackground + 392(JobIntentService.java:392)
at androidx.core.app.JobIntentService$CommandProcessor.doInBackground + 383(JobIntentService.java:383)
at android.os.AsyncTask$2.call + 333(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run + 266(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker + 1167(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run + 641(ThreadPoolExecutor.java:641)
at java.lang.Thread.run + 764(Thread.java:764)
The block of code that calls NotificationManager
public void process()
{
NotificationPayload payload = getPayload(); # Helper function to create a payload object. The object is a Java Bean.
final NotificationHelper helper = new NotificationHelper(context, payloadObject);
if (helper != null)
{
// Notification channels set up.
setupChannels(context); // IntentService context.
Notification notification = helper.buildNotification(payload); // to set up notifications.
if (notification != null)
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(payload.getNotificationId(), notification);
}
}
File Provider XML file file_provider_paths.xml
.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path
name="photos"
path="images/" />
</paths>
File Provider definition in Android Manifest
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>
More stack traces from Fabric
Caused by android.os.RemoteException: Remote stack trace:
at com.android.server.am.ActivityManagerService.checkGrantUriPermissionLocked(ActivityManagerService.java:12738)
at com.android.server.am.ActivityManagerService.checkGrantUriPermission(ActivityManagerService.java:12755)
at com.android.server.notification.NotificationRecord.visitGrantableUri(NotificationRecord.java:1147)
at com.android.server.notification.NotificationRecord.calculateGrantableUris(NotificationRecord.java:1123)
at com.android.server.notification.NotificationRecord.<init>(NotificationRecord.java:208)
My proposed PR would have added the following entry to file_provider_paths.xml
, but my PR was closed because the reviewer's comment was
sound files are packages resources and not saved in external storage
<external-path
name="external_files"
path="." />
UPDATE
Builder function to build the notification
public Notification buildNotification(NotificationPayload payload)
{
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "channelId");
final RemoteViews collapsedView = new RemoteViews(context.getPackageName(), R.layout.expanded_notification)
if (payload.getTitle() != null)
builder.setContentTitle(payload.getTitle());
if (payload.getBody() != null)
builder.setContentText(payload.getBody());
builder.setContentIntent(payload.getClickIntent(context));
builder.setDeleteIntent(payload.getDeleteIntent(context));
builder.setCustomContentView(collapsedView);
builder.setAutoCancel(true);
builder.setSound(Uri.parse("android.resource://" + BuildConfig.APPLICATION_ID + "/" + R.raw.notif_general));
return builder.build();
}
UPDATE # 2*
This is how the sounds are set for notification channels.
@RequiresApi(Build.VERSION_CODES.O)
@VisibleForTesting()
void setSound(Context context, NotificationChannel channel, String soundUri)
{
AudioAttributes audioAttribute = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
channel.setSound(Uri.parse(soundUri), audioAttribute);
}
Creation of NotificationChannel
@TargetApi(26)
void registerChannel(Context context, NotificationManager notificationManager, String id, String name, String soundUri)
{
if (notificationManager.getNotificationChannel(id) != null)
return;
NotificationChannel channel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(true);
channel.setLightColor(Color.BLUE);
channel.enableVibration(false);
if (soundUri != null)
{
setSound(context, channel, soundUri);
}
notificationManager.createNotificationChannel(channel);
}
My question is how do I resolve this crash.