I'm trying to create a notification media controller in my app using the code below which is working fine on all devices expect Huawei P8 Lite with Android 5.0 , I get this error log from Firebase Test Lab :
android.app.RemoteServiceException: Bad notification posted from
package maa.app_app: Couldn't expand RemoteViews for:
StatusBarNotification(pkg=maa.app_app
user=UserHandle{0} id=555 tag=null score=10
key=0|maa.app_app|555|null|10108: Notification(pri=1
contentView=maa.app_app/0x109007f vibrate=null
sound=null defaults=0x0 flags=0x62 color=0xffbfbfbf category=transport
actions=2 vis=PUBLIC)) FATAL EXCEPTION: main Process:
maa.app_app, PID: 18793
android.app.RemoteServiceException: Bad notification posted from
package maa.app_app: Couldn't expand RemoteViews for:
StatusBarNotification(pkg=maa.app_app
user=UserHandle{0} id=555 tag=null score=10
key=0|maa.app_app|555|null|10108: Notification(pri=1
contentView=maa.app_app/0x109007f vibrate=null
sound=null defaults=0x0 flags=0x62 color=0xffbfbfbf category=transport
actions=2 vis=PUBLIC)) at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1534)
at android.os.Handler.dispatchMessage(Handler.java:102) at
android.os.Looper.loop(Looper.java:135) at
android.app.ActivityThread.main(ActivityThread.java:5538) at
java.lang.reflect.Method.invoke(Native Method) at
java.lang.reflect.Method.invoke(Method.java:372) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
here's my code :
void startNotify(Context context, String playbackStatus, String title) {
String titlesonge;
String artist;
try {
titlesonge = StringUtils.substringBefore(title, " - ");
artist = StringUtils.substringAfter(title, " - ");
} catch (Exception e) {
titlesonge = title.substring(0, title.indexOf(" - "));
artist = title.substring(title.lastIndexOf(" - ") - 1);
}
int icon = R.drawable.ic_pause_white;
Intent playbackAction = new Intent(service, RadioService.class);
playbackAction.setAction(RadioService.ACTION_PAUSE);
PendingIntent action = PendingIntent.getService(service, 1, playbackAction, 0);
if (playbackStatus.equals(PlaybackStatus.PAUSED)) {
icon = R.drawable.ic_play_white;
playbackAction.setAction(RadioService.ACTION_PLAY);
action = PendingIntent.getService(service, 2, playbackAction, 0);
}
Intent stopIntent = new Intent(service, RadioService.class);
stopIntent.setAction(RadioService.ACTION_STOP);
PendingIntent stopAction = PendingIntent.getService(service, 3, stopIntent, 0);
Intent intent = new Intent(service, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP |
Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(service, 0, intent, 0);
notificationManager.cancel(NOTIFICATION_ID);
String PRIMARY_CHANNEL = "PRIMARY_CHANNEL_ID";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE);
String PRIMARY_CHANNEL_NAME = "PRIMARY";
NotificationChannel channel = new NotificationChannel(PRIMARY_CHANNEL, PRIMARY_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
if (manager != null) {
manager.createNotificationChannel(channel);
}
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(service, PRIMARY_CHANNEL)
.setAutoCancel(false)
.setContentTitle(titlesonge)
.setContentText(artist)
.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.largeicon))
.setContentIntent(pendingIntent)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.smallwidth)
.setColor(ContextCompat.getColor(context, R.color.colorneeded))
.addAction(icon, "pause", action)
.addAction(R.drawable.ic_stop_white, "stop", stopAction)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setWhen(System.currentTimeMillis())
.setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
.setMediaSession(service.getMediaSession().getSessionToken())
.setShowActionsInCompactView(0, 1)
.setShowCancelButton(true)
.setCancelButtonIntent(stopAction));
service.startForeground(NOTIFICATION_ID, builder.build());
}
can anyone help me to get resolved this issue
For some reason, Huawei devices with Android 5.0 crashes when using .setStyle() method so you have two possibilities :
1 - detect device Manufacture if is Huawei or not, and have an Android 5.0 or below or not
public boolean isLolliPopHuawei() {
return (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1 ||
android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) && Build.MANUFACTURER.equalsIgnoreCase("HUAWEI");
}
2 - Use PlayerNotificationManager instead
void exoPlayerNotification(Context context, SimpleExoPlayer exoPlayer, String title) {
String titlesonge;
String artist;
try {
titlesonge = StringUtils.substringBefore(title, " - ");
artist = StringUtils.substringAfter(title, " - ");
} catch (Exception e) {
titlesonge = title.substring(0, title.indexOf(" - "));
artist = title.substring(title.lastIndexOf(" - ") - 1);
}
String finalArtist = artist;
String finalTitlesonge = titlesonge;
mPlayerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
context,
"PRIMARY_CHANNEL_ID",
R.string.plaza,
NOTIFICATION_ID,
new PlayerNotificationManager.MediaDescriptionAdapter() {
#Override
public String getCurrentContentTitle(Player player) {
return finalArtist;
}
#Nullable
#Override
public PendingIntent createCurrentContentIntent(Player player) {
Intent intent = new Intent(service, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return PendingIntent.getActivity(service, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
#Override
public String getCurrentContentText(Player player) {
return finalTitlesonge;
}
#Nullable
#Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
return BitmapFactory.decodeResource(service.getResources(), R.drawable.largeicon);
}
#Nullable
#Override
public String getCurrentSubText(Player player) {
return null;
}
}
);
mPlayerNotificationManager.setUseNavigationActions(false);
mPlayerNotificationManager.setFastForwardIncrementMs(0);
mPlayerNotificationManager.setRewindIncrementMs(0);
mPlayerNotificationManager.setColorized(true);
mPlayerNotificationManager.setColor(0xFFEEEEEE);
mPlayerNotificationManager.setUseChronometer(true);
mPlayerNotificationManager.setOngoing(true);
mPlayerNotificationManager.setPriority(NotificationCompat.PRIORITY_MAX);
mPlayerNotificationManager.setUsePlayPauseActions(true);
mPlayerNotificationManager.setSmallIcon(R.drawable.smallwidth);
mPlayerNotificationManager.setNotificationListener(new PlayerNotificationManager.NotificationListener() {
#Override
public void onNotificationStarted(int notificationId, Notification notification) {
service.startForeground(notificationId, notification);
}
#Override
public void onNotificationCancelled(int notificationId) {
service.stopSelf();
cancelNotify();
}
});
mPlayerNotificationManager.setPlayer(exoPlayer);
}
Since some Huawei devices don't support MediaStyle you need to build notification without styling. I experienced this issue on this models Huawei P8 Lite and Huawei Y3II. So, check if device is huawei and SDK versions as mentioned and create a simple notification as below. This question helped me to find solution Strange allow/deny question on Huawei 5.1 phone when showing notification
. Anyway, I hope helps someone
boolean isLollipopHuawei = (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1 ||
android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) && Build.MANUFACTURER.equalsIgnoreCase("HUAWEI");
if (isLollipopHuawei) {
builder
.setContentTitle(description.getTitle())
.setContentText(contentText)
.setOngoing(true)
.setContentIntent(createContentIntent())
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
R.drawable.mobi_plc))
.addAction(R.drawable.ic_previous_outline_notification,
this.service.getString(R.string.next_station),
MediaButtonReceiver.buildMediaButtonPendingIntent(
this.service,
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS))
.addAction(R.drawable.ic_next_outline_notification,
this.service.getString(R.string.next_station),
MediaButtonReceiver.buildMediaButtonPendingIntent(
this.service,
PlaybackStateCompat.ACTION_SKIP_TO_NEXT))
.setSmallIcon(R.drawable.ic_stat)
.setAutoCancel(false);
}
I had the same issue and the root cause was not able to setStyle, it was only giving this exception in Huawei P8 Lite, not on other devices.
So, what i had to do was check if current device is android version 5.0 and its manufacturer is Huawei and remove the setStyle property. please check below code
boolean isLollipopHuawei = (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1 ||
android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) && Build.MANUFACTURER.equalsIgnoreCase("HUAWEI");
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT || Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1 || Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
if (isLollipopHuawei) {
return builder
.addAction(generateAction(android.R.drawable.ic_media_previous, "Previous", Constants.ACTION_PREVIOUS))
.addAction(action)
.addAction(generateAction(android.R.drawable.ic_media_next, "Next", Constants.ACTION_NEXT))
.setSmallIcon(R.mipmap.vpicon_grayscale)
.setContentTitle(getSongDataHelper().getTitle())
.setContentIntent(pendingIntent)
.setContentText(getSongDataHelper().getAlbum())
.setLargeIcon(getSongDataHelper().getAlbumArt())
//.setColor(color)
/* .setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2)
.setMediaSession(mMediaSession.getSessionToken()))*/
.build();
} else {
return builder
.addAction(generateAction(android.R.drawable.ic_media_previous, "Previous", Constants.ACTION_PREVIOUS))
.addAction(action)
.addAction(generateAction(android.R.drawable.ic_media_next, "Next", Constants.ACTION_NEXT))
.setSmallIcon(R.mipmap.vpicon_grayscale)
.setContentTitle(getSongDataHelper().getTitle())
.setContentIntent(pendingIntent)
.setContentText(getSongDataHelper().getAlbum())
.setLargeIcon(getSongDataHelper().getAlbumArt())
//.setColor(color)
.setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2)
.setMediaSession(mMediaSession.getSessionToken()))
.build();
}
}
Related
I have been trying showing heads up notification as part of Full Screen Intent. It works well in some devices and if device is not locked, it shows up as heads up notification.
But in samsung devices, i have set system notification setting to brief (that shows notification for brief amount of time and then disappear back to system tray). This setting causing heads up notification to appear for small amount of time.
For the same setting, whatsapp and system caller app able to show heads up notification for incoming call.
i have used the following code
Channel creation
private void createFullIntentChannel(){
NotificationManager manager = (NotificationManager)ctx.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + ctx.getPackageName() + "/raw/new_ride.mp3" ) ;
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
String NOTIFICATION_CHANNEL_ID = "com.myapp.app.fullintent";
String channelName = "FullRide";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_HIGH);
chan.setLightColor(Color.BLUE);
chan.enableVibration(true);
chan.setImportance(NotificationManager.IMPORTANCE_HIGH);
chan.setSound(sound, attributes);
chan.setShowBadge(true);
chan.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
manager.createNotificationChannel(chan);
}
}
Setting content and action buttons on notification
public void showFullScreenIntent(final int notifId, String pickLoc, String dropLoc, String tripType, String accountID, String accountType,
String qrMode, Integer stopCount, Integer vhclType, String estInfo) {
setMediaPlayerFile();
if (mediaPlayer != null) {
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
PlayFile();
}
});
PlayFile();
}
// set content pending intent
Intent fullScreenIntent = new Intent(ctx, NewRideRequest.class);
fullScreenIntent.putExtra("Action", "UserChoice");
fullScreenIntent.putExtra("ID", notifId);
fullScreenIntent.putExtra("BookingID", String.valueOf(notifId));
PendingIntent contentIntent = PendingIntent.getActivity(ctx, ACTION_USER_REQUEST_ID,
fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
// set action button accept pending intent
Intent acceptIntent = new Intent(ctx, NewRideRequest.class);
acceptIntent.putExtra("Action", "Accept");
acceptIntent.putExtra("ID", notifId);
acceptIntent.putExtra("BookingID", String.valueOf(notifId));
PendingIntent pendingAcceptIntent = PendingIntent
.getActivity(ctx, ACTION_INTENT_REQUEST_ID, acceptIntent,PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
// set action button reject pending intent
Intent rejectIntent = new Intent(ctx, NotificationAction.class);
rejectIntent.putExtra("Action", "Reject");
rejectIntent.putExtra("ID", notifId);
rejectIntent.putExtra("BookingID", String.valueOf(notifId));
PendingIntent pendingRejectIntent = PendingIntent
.getBroadcast(ctx, ACTION_INTENT_REQUEST_ID, rejectIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + ctx.getPackageName() + "/raw/new_ride.mp3") ;
createFullIntentChannel();
String val = dbHelper.GetVehicleMaster(dbHelper.getReadableDatabase(), vhclType);
// set notification builder
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(ctx, "com.myapp.app.fullintent")
.setSmallIcon(R.drawable.ic_yego_logo)
.setContentTitle("New " + (val.contains(",") ? val.split(",")[0] : "") + " Ride Request")
.setContentText(getContent(stopCount, pickLoc, dropLoc))
//.setSound(sound)
.setOngoing(true)
.setTimeoutAfter(10000)
.setDefaults(Notification.DEFAULT_VIBRATE| Notification.DEFAULT_SOUND)
.addAction(R.drawable.payment_success_1, getActionText(R.string.txt_accept, R.color.colorGreen), pendingAcceptIntent)
.addAction(R.drawable.payment_failed_1, getActionText(R.string.txt_reject, R.color.colorRed), pendingRejectIntent)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setFullScreenIntent(contentIntent, true);
Notification incomingCallNotification = notificationBuilder.build();
incomingCallNotification.sound = sound;
//incomingCallNotification.flags = Notification.FLAG_INSISTENT;
final NotificationManager notificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notifId, incomingCallNotification);
Handler handler = new Handler(Looper.getMainLooper());
long delayInMilliseconds = 10000;
handler.postDelayed(new Runnable() {
public void run() {
try {
Log.e("MyApp", "Handler runs");
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
notificationManager.cancel(notifId);
}catch (Exception e){
}
}
}, delayInMilliseconds);
}
Please suggest how can i set ongoing heads up notification to be on screen regardless of system setting of notification.
i have an app published in Google play,and i'm stucking with below crash report in Google Console, can anyone help me to understand where this issue came from and how to get resolved.
java.lang.RuntimeException:
at android.app.ActivityThread.handleReceiver (ActivityThread.java:3523)
at android.app.ActivityThread.access$1400 (ActivityThread.java:207)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1759)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:193)
at android.app.ActivityThread.main (ActivityThread.java:6863)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run
(RuntimeInit.java:537)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:858)
Caused by: java.lang.IllegalStateException:
at android.support.v4.media.session.MediaButtonReceiver.onReceive
(MediaButtonReceiver.java:124)
at android.app.ActivityThread.handleReceiver (ActivityThread.java:3507)
Notification :
void startNotify(Context context, String playbackStatus, String title) {
String titlesonge;
String artist;
try {
titlesonge = StringUtils.substringBefore(title, " - ");
artist = StringUtils.substringAfter(title, " - ");
} catch (Exception e) {
titlesonge = title.substring(0, title.indexOf(" - "));
artist = title.substring(title.lastIndexOf(" - ") - 1);
}
int icon = R.drawable.ic_pause_white;
Intent playbackAction = new Intent(service, RadioService.class);
playbackAction.setAction(RadioService.ACTION_PAUSE);
PendingIntent action = PendingIntent.getService(service, 1, playbackAction, 0);
if (playbackStatus.equals(PlaybackStatus.PAUSED)) {
icon = R.drawable.ic_play_white;
playbackAction.setAction(RadioService.ACTION_PLAY);
action = PendingIntent.getService(service, 2, playbackAction, 0);
}
Intent stopIntent = new Intent(service, RadioService.class);
stopIntent.setAction(RadioService.ACTION_STOP);
PendingIntent stopAction = PendingIntent.getService(service, 3, stopIntent, 0);
Intent intent = new Intent(service, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP |
Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(service, 0, intent, 0);
notificationManager.cancel(NOTIFICATION_ID);
String PRIMARY_CHANNEL = "PRIMARY_CHANNEL_ID";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE);
String PRIMARY_CHANNEL_NAME = "PRIMARY";
NotificationChannel channel = new NotificationChannel(PRIMARY_CHANNEL, PRIMARY_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
if (manager != null) {
manager.createNotificationChannel(channel);
}
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(service, PRIMARY_CHANNEL)
.setAutoCancel(false)
.setContentTitle(titlesonge)
.setContentText(artist)
.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.largeicon))
.setContentIntent(pendingIntent)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.smallwidth)
.setColor(ContextCompat.getColor(context, R.color.colorneeded))
.addAction(icon, "pause", action)
.addAction(R.drawable.ic_stop_white, "stop", stopAction)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setWhen(System.currentTimeMillis())
.setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
.setMediaSession(service.getMediaSession().getSessionToken())
.setShowActionsInCompactView(0, 1)
.setShowCancelButton(true)
.setCancelButtonIntent(stopAction));
service.startForeground(NOTIFICATION_ID, builder.build());
}
This will solve in 3 steps.
1:_ Open your build.gradle(Module: app) file.
Add this under the application tag
defaultConfig {
multiDexEnabled true
}
2:_ If you using appcompact then add this line under the dependencies tag
dependencies {
implementation 'com.android.support:multidex:1.0.3'
}
else if you migrate your project to AndroidX then add this line
dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
}
3:_ Open your all activity java files and add MultiDex.intall(contextName)
protected void onCreate(Bundle savedInstanceState) {
MultiDex.install(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mine);
`enter code here`
}
Just add flag to your PendingIntent for Android 12 and above.
Reference
I am building an app that should remind the user about upcoming events that they set (basically a reminder). The issue i'm running into is pushing notifications to the user's phone (only on API 26+) when the app has not been utilized for a while (about 15 minutes or more); notifications are not displayed at all.
I read up on this and realized that App Standby and Doze mode may prevent my app from pushing such notifications; my notifications are received as intended by the user on phones running API 25 and below. To solve this I tried using AlarmManager.setExactAndAllowWhileIdle() but the issue persists.
class TaskNotifications {
private AlarmManager alarmManager;
private Context c;
TaskNotifications(Context context) {
this.c = context;
this.alarmManager = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
}
void setReminder(Context context, Task task) {
if (VERSION.SDK_INT < Build.VERSION_CODES.O) {
long reminderMilliseconds = task.getReminderMilliseconds();
if (reminderMilliseconds > Calendar.getInstance().getTimeInMillis() && !task.isDone()) {
Intent intent = new Intent(context, NotificationReceiver.class);
intent.putExtra("ID", task.getID());
intent.putExtra("TITLE", task.getTitle());
intent.putExtra("DETAILS", task.getDetails());
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, task.getID(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (VERSION.SDK_INT >= 23) {
this.alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, reminderMilliseconds, pendingIntent);
} else
this.alarmManager.setExact(AlarmManager.RTC_WAKEUP, reminderMilliseconds, pendingIntent);
}
}
}
void cancelReminder(Task task) {
if (VERSION.SDK_INT < Build.VERSION_CODES.O) {
this.alarmManager.cancel(PendingIntent.getBroadcast(this.c, task.getID(),
new Intent(this.c, NotificationReceiver.class), PendingIntent.FLAG_CANCEL_CURRENT));
}
}
}
public class NotificationReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent startIntent = new Intent(context, NotificationJobIntentService.class);
startIntent.putExtra("ID", intent.getIntExtra("ID", -1));
startIntent.putExtra("TITLE", intent.getStringExtra("TITLE"));
startIntent.putExtra("DETAILS", intent.getStringExtra("DETAILS"));
JobIntentService.enqueueWork(context, NotificationJobIntentService.class, intent.getIntExtra("ID", -1), startIntent);
}
}
public class NotificationJobIntentService extends JobIntentService {
private String CHANNEL_ID = getResources().getString(R.string.channel_name);
protected void onHandleWork(#NonNull Intent intent) {
createNotificationChannel(NotificationJobIntentService.this);
int NOTIFICATION_ID = intent.getIntExtra("ID", -1);
String GROUP = "NOTIFICATION_GROUP";
String title = intent.getStringExtra("TITLE");
if (title.isEmpty())
title = getResources().getString(R.string.no_title);
String details = intent.getStringExtra("DETAILS");
if (details.isEmpty())
details = getResources().getString(R.string.no_details);
Intent openAppIntent = new Intent(NotificationJobIntentService.this, MainActivity.class);
TaskStackBuilder create = TaskStackBuilder.create(this);
create.addNextIntentWithParentStack(openAppIntent);
NotificationCompat.Builder builder = new NotificationCompat.Builder(NotificationJobIntentService.this, this.CHANNEL_ID)
.setContentTitle(title)
.setContentText(details)
.setSmallIcon(R.drawable.baseline_alarm_black_18)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentIntent(create.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT))
.setCategory(NotificationCompat.CATEGORY_ALARM)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setGroup(GROUP)
.setAutoCancel(true)
.setColor(Color.argb(100, 0, 87, 75))
.setVibrate(new long[]{1000, 1000})
.setLights(Color.GREEN, PathInterpolatorCompat.MAX_NUM_POINTS, PathInterpolatorCompat.MAX_NUM_POINTS)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM));
NotificationManagerCompat.from(this).notify(NOTIFICATION_ID, builder.build());
}
private void createNotificationChannel(Context context) {
if (VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence string = context.getString(R.string.channel_name);
String description = context.getString(R.string.channel_description);
NotificationChannel notificationChannel = new NotificationChannel(this.CHANNEL_ID, string, NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setDescription(description);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.GREEN);
notificationChannel.enableVibration(true);
notificationChannel.setVibrationPattern(new long[]{1000, 1000});
(context.getSystemService(NotificationManager.class)).createNotificationChannel(notificationChannel);
}
}
}
Is there a reliable way for me to send exact/somewhat exact notifications to my users' phones running API 26+? Or is there an error in my code that I did not notice?
I was unable to make the notification system work on API 26+ devices, however, I used the Android Calendar Provider Reminders to add the event to the users calendar and then set a reminder through the default calendar...not what I originally wanted, but it is a band-aid solution.
If anybody can still solve the problem as intended, please let me know.
Code below:
if (task.getEventID() > 0) {
//Remove existing events for this task
ContentResolver cr = c.getContentResolver();
int iNumRowsDeleted;
Uri eventUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, task.getEventID());
iNumRowsDeleted = cr.delete(eventUri, null, null);
Log.i("removeEvent()", "Deleted " + iNumRowsDeleted + " calendar entry.");
}
try {
//Add an event
ContentResolver cr = context.getContentResolver();
ContentValues values = new ContentValues();
values.put(CalendarContract.Events.DTSTART, task.getCal().getTimeInMillis());
values.put(CalendarContract.Events.DTEND, task.getCal().getTimeInMillis()+60*60*1000);//Each task a duration of 60 minutes
values.put(CalendarContract.Events.TITLE, task.getTitle() + " - " + task.getDetails());
values.put(CalendarContract.Events.CALENDAR_ID, getPrimaryCalendar());
values.put(CalendarContract.Events.EVENT_TIMEZONE, Calendar.getInstance().getTimeZone().getID());
Uri uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);
// Save the eventId into the Task object for possible future delete.
task.setEventID(Integer.parseInt(uri.getLastPathSegment()));
Log.i("addEvent()","The event id is " + task.getEventID());
// Add a reminder
ContentValues valuesR = new ContentValues();
valuesR.put(CalendarContract.Reminders.MINUTES, (task.getCal().getTimeInMillis() - reminderMilliseconds)/(1000*60));
valuesR.put(CalendarContract.Reminders.EVENT_ID, task.getEventID());
valuesR.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT); /*The alarm method, as set on the server. METHOD_DEFAULT, METHOD_ALERT, METHOD_EMAIL, METHOD_SMS and METHOD_ALARM are possible values; the device will only process METHOD_DEFAULT and METHOD_ALERT reminders (the other types are simply stored so we can send the same reminder info back to the server when we make changes).*/
Uri uriR = cr.insert(CalendarContract.Reminders.CONTENT_URI, valuesR);
Cursor c = CalendarContract.Reminders.query(cr, task.getEventID(), new String[]{CalendarContract.Reminders.MINUTES});
if (c.moveToFirst()) {
Log.i("setReminder()",task.toString());
Log.i("setReminder()","calendar has reminder at " + c.getInt(c.getColumnIndex(CalendarContract.Reminders.MINUTES)));
}
c.close();
} catch (Exception e) {
e.printStackTrace();
}
I am trying to use Custom Notification sound in my android application. I have checked all related questions and answers in stackoverflow but I am not able to figure why its not playing my custom sound in application. My code for notification is like below.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if (remoteMessage.getNotification() != null) {
}
if (remoteMessage.getData().size() > 0) {
sendNotification(remoteMessage.getData().get("title"));
}
}
#Override
public void onNewToken(String token) {
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, SplashActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Context context = getBaseContext();
String channelId = "raj";
int sound_notification = context.getSharedPreferences("setting", MODE_PRIVATE).getInt("sound_notification", 1);
Uri MyCustomSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/raw/sound" + (sound_notification));
//Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(messageBody)
.setAutoCancel(true)
.setSound(MyCustomSound)
.setContentIntent(pendingIntent);
//notificationBuilder.setSound(MyCustomSound);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Raj",
NotificationManager.IMPORTANCE_HIGH);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
if (notificationManager != null) {
notificationManager.notify(0, notificationBuilder.build());
}
}
I have tried to send notification from My Server with PHP as well from Firebase Console but its always play default sound instead my custom sound. Let me know if someone can help me for out from the issue.
Thanks
notification.sound = Uri.parse("android.resource://" + getPackageName() + "/sound/" + R.raw.sound);
mBuilder.setSound(Uri.parse("android.resource://" + getPackageName() + "/sound/" + R.raw.sound));
I had tried many things but non of them work. I am not getting code which will announce/tell notification present in notification bar of mobile. It should announce all application notification on notification bar as that of call announcer app work for call. I had tried lot of things and all of them had failed. any help will be really helpful for me. one of thing i had tried from solution given below. but has lot of error.
public class notif extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notif);
TextToSpeech tts = new TextToSpeech(this/*context*/, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {//Checking For Success
int result = tts.setLanguage(Locale.US);//Setting Language
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {//Checking If Language Available
Log.e("TTS", "This Language is not supported");
} else {
Log.d("TTS","Language Loaded...");
}
} else {
Log.e("TTS", "Initilization Failed!");
}
}
});
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher) // notification icon
.setContentTitle(title) // title for notification
.setContentText(message) // message for notification
.setAutoCancel(true); // clear notification after click
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0,intent, Intent.FLAG_ACTIVITY_NEW_TASK);
mBuilder.setContentIntent(pi);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
speakOut(message);//Function call <- <- <-
}
private void speakOut(String notification)
{
tts.speak(notification, TextToSpeech.QUEUE_FLUSH, null);//Making The TextToSpeech Speak
}
}
here the error occur on Intent.FLAG_ACTIVITY_NEW_TASK.
error :- Must be one or more of: PendingIntent.FLAG_ONE_SHOT, PendingIntent.FLAG_NO_CREATE, PendingIntent.FLAG_CANCEL_CURRENT, PendingIntent.FLAG_UPDATE_CURRENT, PendingIntent.FLAG_IMMUTABLE, Intent.FILL_IN_ACTION, Intent.FILL_IN_DATA, Intent.FILL_IN_CATEGORIES, Intent.FILL_IN_COMPONENT, Intent.FILL_IN_PACKAGE, Intent.FILL_IN_SOURCE_BOUNDS, Intent.
You can try using Text To Speech When Showing Notification
Example:-
TextToSpeech tts = new TextToSpeech(this/*context*/, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {//Checking For Success
int result = tts.setLanguage(Locale.US);//Setting Language
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {//Checking If Language Available
Log.e("TTS", "This Language is not supported");
} else {
Log.d("TTS","Language Loaded...")
}
} else {
Log.e("TTS", "Initilization Failed!");
}
}
});
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher) // notification icon
.setContentTitle(title) // title for notification
.setContentText(message) // message for notification
.setAutoCancel(true); // clear notification after click
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0,intent,Intent.FLAG_ACTIVITY_NEW_TASK);
mBuilder.setContentIntent(pi);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
speakOut(message)//Function call <- <- <-
Function For Speaking:-
private void speakOut(String notification)
{
tts.speak(notification, TextToSpeech.QUEUE_FLUSH, null);//Making The TextToSpeech Speak
}
Full Code:-
public class notif extends AppCompatActivity {
TextToSpeech tts;
String title,message;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notif);
title = "Your notification title";
message = "Your notification body";
tts = new TextToSpeech(this/*context*/, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {//Checking For Success
int result = tts.setLanguage(Locale.US);//Setting Language
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {//Checking If Language Available
Log.e("TTS", "This Language is not supported");
} else {
Log.d("TTS","Language Loaded...");
}
} else {
Log.e("TTS", "Initilization Failed!");
}
}
});
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher) // notification icon
.setContentTitle(title) // title for notification
.setContentText(message) // message for notification
.setAutoCancel(true); // clear notification after click
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0,intent, Intent.FLAG_ACTIVITY_NEW_TASK);
mBuilder.setContentIntent(pi);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
speakOut(message);//Function call <- <- <-
}
I will advise you to not to use this, as reading whole notification may make the user feel uncomfortable but as your wish.