I want to run background location service. It works more or less, however - instead of my custom notification with text and content intent, generic notification is shown. Why is that?
I am using Nexus API 28 emulator.
Service starting method:
private void moveToRunningState() {
Intent serviceStartIntent = new Intent(getApplicationContext(), this.getClass());
int requestId = 1;
Intent goToMainScreenIntent = new Intent(getApplicationContext(), MainActivity.class);
serviceStartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent onTapIntent = PendingIntent.getActivity(getApplicationContext(), requestId, goToMainScreenIntent, 0);
Notification.Builder builder = NotificationUtils.notificationBuilderO(this);
builder.setContentTitle("Location tracking is running");
builder.setContentText("Your location is beeing sent to the server so it can be shown on map");
builder.setFullScreenIntent(onTapIntent, true);
builder.setProgress(0,100,true);
if (NotificationUtils.isPreAndroidO()) {
Log.d(TAG, "moveToStartedState: Running on Android N or lower - startService(intent)");
startService(serviceStartIntent);
} else {
Log.d(TAG, "moveToStartedState: Running on Android O - startForegroundService(intent)");
startForegroundService(serviceStartIntent);
}
startForeground(1, builder.build());
Log.i(TAG, "Service moved to start state");
isRunning = true;
}
Just in case, builder creation
public static Notification.Builder notificationBuilderO(Context ctx) {
NotificationManager notificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel notificationChannel = new NotificationChannel(UUID.randomUUID().toString(), "Geoloc channel", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(notificationChannel);
Notification.Builder builder = new Notification.Builder(ctx, notificationChannel.getId());
return builder;
and actual result:
As usual, I had to post question on SO only to find answer myself seconds afterwards.
The problem is, that I am not setting notification icon. I have tried to show the same notification using NotificationManager and it failed with explainatory exception saying that this icon is not set. This exception is not shown in logs in my case when using startForeground
All in all, setting icon fixes the issue.
Related
On my Github acccount I made a simple projet that delineate my problem here my project
My Main Activity has a button whose onClick method calls a Background Service.
The Backgroundservice wait for 5 second and then fires a notification.
here the code of the BackgroundService (you can find on Github
#Override
protected void onHandleIntent(Intent intent) {//methode appelée en arrière plan
if (intent != null) {
try{
Thread.sleep(5000);
} catch (Exception e){
e.printStackTrace();
}
mNotificationsManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
CharSequence tickerText = "view hike";
Intent intentReceiverAcctivity = new Intent(TAG_INTENT);
intentReceiverAcctivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0, intentReceiverAcctivity, 0);
Notification.Builder builder = new Notification.Builder(this);
builder.setAutoCancel(false);
builder.setTicker(tickerText);
builder.setContentTitle("The Hike");
builder.setContentText("HikeMap is available");
builder.setSmallIcon(R.drawable.explore);
Bitmap large_icon_bmp = BitmapFactory.decodeResource(this.getResources(),
R.drawable.ic_action_map);
builder.setLargeIcon(large_icon_bmp);
builder.setContentIntent(pendingIntent);
builder.setOngoing(true);
builder.setSubText("Click on this icon to access the Hike's map"); //API level 16
builder.setNumber(5000); //durée d'apparition de l'icone dans la barre de notifications ?
builder.build();
Notification notification = builder.getNotification();
mNotificationsManager.notify(11, notification);
}
}
Expanding the notification bar and clicking on the large_icon shoud start a second Activity called ReceiverActivity whose sole purpose is to show a different message.
On an emulator the small icon appears on the notification bar, when I expand that bar I can see the large Icon, but clicking on it does not fire the ReceiverActivity
On my smartphone no small icon on the notification bar, no large icon on the expanded notification area ...
Any Idea of what went wrong with the service code ?
The entire code of that small example is to be found on GitHub...
Thanks in advance for your help!!!
Intent intentReceiverAcctivity = new Intent(TAG_INTENT);
public final static String TAG_INTENT = "NotificationClicked";
Sorry, you didn't set an activity to run. You should use an Intent with two parameters like
Intent intent = new Intent(Context, YourActivity.class);
Here's example of NotificationChannel
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"channel_id",
"channel_name",
NotificationManager.IMPORTANCE_DEFAULT
);
channel.setDescription("channel_description");
channel.setImportance(NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
builder = new NotificationCompat.Builder(context, "channel_id");
} else {
builder = new NotificationCompat.Builder(context);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
}
I submitted my app at the end of 2017 in the play store and it worked.
Then it was built in Eclipse.
Now I run it in Android Studio and the same code doesn't show any notification.
It is a permanent notification which is present after I call the app's finish() method. (why I do this: see at the bottom if you want to know).
So I looked at all the examples and NONE of the work. No single notification is shown.
So I start an activity and in the activity I show the notification. Then I call finish().
This is my code:
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
intent, 0);
CharSequence connectedPart = getResources().getString(R.string.app_name);
String melding = "";
melding = getResources().getString(R.string.screentimeoutsetto) + " " + newTimeString + ".";
NotificationManager notificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification.Builder(this)
.setContentTitle(connectedPart)
.setTicker(connectedPart)
.setContentText(melding)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.flags |= Notification.FLAG_NO_CLEAR;
notificationManager.notify(2, notification);
dependencies:
dependencies{
implementation "com.android.support:support-compat:26.1.0"
}
Why I do this:
My app does 1 thing: toggle the screentimeout. So when you start it it sets the screentimeout to 30 minutes (starts, sets a notification, then finish()). Start again, it removes the notification and restore the original value for the screen timeout.
Starting with Android Oreo, all notifications require a notification channel, otherwise the notification wont post and an error will appear in your logcat. Here's an example of how you can do it, lifted from one of my apps:
private static void createNotificationChannel(Context ctx) {
if(SDK_INT < O) return;
final NotificationManager mgr = ctx.getSystemService(NotificationManager.class);
if(mgr == null) return;
final String name = ctx.getString(R.string.channel_name);
if(mgr.getNotificationChannel(name) == null) {
final NotificationChannel channel =
new NotificationChannel(CHANNEL_ID, name, IMPORTANCE_DEFAULT);
mgr.createNotificationChannel(channel);
}
}
//Usage...
createNotificationChannel(context);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID);
builder.setSmallIcon(R.drawable.ic_alarm_white_24dp);
//etc...
manager.notify(id, builder.build());
Now from Android 8.0 and onward you need to create notification channel before showing notifications. Here is the Docs link
https://developer.android.com/training/notify-user/channels
I am facing this problem for a long time now, I have an application with many functions, one of them is the alarm
My notification just stays there and never disappears although I am calling cancelAll() / cancel() from the notification manager, also I have autoCancel set to true! It also stays clickable, I just need it to disappear after actions are triggered!
(I am testing this on an emulator with Android Studio, not sure if this could be the problem)
I searched a lot an tried so many things and nothing worked so I would appreciate the help :)
I have set my notification as follow:
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// ...
private void initNotification() {
setNotificationChannel();
notificationBuilder = new NotificationCompat.Builder(getApplicationContext(), notificationChannel.getId());
Intent click_intent = new Intent(getApplicationContext(), RingtonePlayingService.class)
.putExtra("intent_action", "click")
.putExtra("REQUEST_CODE", alarmRequestCode)
.putExtra("ID", alarmId);
PendingIntent click_pending = PendingIntent.getService(this, MainActivity.getRequestCode(), click_intent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent dismiss_intent = new Intent(getApplicationContext(), RingtonePlayingService.class)
.putExtra("intent_action", "dismiss")
.putExtra("REQUEST_CODE", alarmRequestCode)
.putExtra("ID", alarmId);
PendingIntent dismiss_pending = PendingIntent.getService(getApplicationContext(),MainActivity.getRequestCode(), dismiss_intent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent snooze_intent = new Intent(getApplicationContext(), RingtonePlayingService.class)
.putExtra("intent_action", "snooze")
.putExtra("REQUEST_CODE", alarmRequestCode)
.putExtra("ID", alarmId);
PendingIntent snooze_pending = PendingIntent.getService(getApplicationContext(),MainActivity.getRequestCode(), snooze_intent, PendingIntent.FLAG_UPDATE_CURRENT);
dismissAction = new NotificationCompat.Action(R.drawable.small_delete,
"Dismiss", dismiss_pending);
snoozeAction = new NotificationCompat.Action(R.drawable.bell_ring,
"Snooze", snooze_pending);
notificationBuilder.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE)
.setSmallIcon(R.drawable.alarm)
.setContentTitle("Alarm On!")
.setContentText("Click the notification to dismiss")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(click_pending)
.setDeleteIntent(click_pending)
.addAction(dismissAction)
.addAction(snoozeAction)
.setAutoCancel(true);
}
private void showNotification() {
notificationManager.notify(alarmRequestCode, notificationBuilder.build());
}
private void setNotificationChannel() {
channelId = "alarm_channel_id";
channelName = "alarm_notification_channel";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
notificationChannel = new NotificationChannel(channelId, channelName, importance);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationManager.createNotificationChannel(notificationChannel);
}
When the actions buttons are pressed this is the part of code triggered:
if (action != null) {
switch (action) {
case "click":
alarmManager.cancel(cancelPendingIntent);
notificationManager.cancelAll();
player.stop();
changeAlarmValuesToOff();
break;
case "snooze":
alarmManager.cancel(cancelPendingIntent);
notificationManager.cancelAll();
player.stop();
setNewSnoozeAlarm();
break;
case "dismiss":
alarmManager.cancel(cancelPendingIntent);
notificationManager.cancelAll();
player.stop();
changeAlarmValuesToOff();
break;
default:
}
}
I also tried using cancel() using the alarmRequestCode which is the unique ID used for both alarm and notification and still didn't work
Everything is working fine, the actions perform as desired only that the notification stays right there and stays clickable and performing actions as shown in the screenshot below
The problem here is not in the notification settings itself, the problem is that the notification is running in a Service class. While the service is still running the notification cannot be dismissed.
How I solved this:
In the service class, after the action is performed (Where I was calling cancelAll()) I call stopSelf()instead.
Then override onDestroy() and call cancelAll() in it instead!
Cheers
I'm attempting to show a notification through Android Auto. The notification does show on my phone. However, it is not showing on Android Auto emulator. This is a media application.
automotvie_app_desc.xml:
<automotiveApp>
<uses name="media"/>
</automotiveApp>
This code is in my MediaBrowserService class:
private Notification postNotification(AutoNotificationHelper.Type type) {
Log.d(TAG, "Post Notification");
Notification notification = AutoNotificationHelper.createMenuErrorNotification(
getApplicationContext(), type, mSession);
if (notification != null) {
mNotificationManager.notify(TAG, NOTIFICATION_ID, notification);
}
return notification;
}
Here is where the notification is created:
static Notification createMenuErrorNotification(Context context, Type type,
MediaSessionCompat mediaSession) {
MediaControllerCompat controller = mediaSession.getController();
MediaMetadataCompat mMetadata = controller.getMetadata();
PlaybackStateCompat mPlaybackState = controller.getPlaybackState();
if (mMetadata == null) {
Log.e(TAG, "MetaData is null");
}
if (mPlaybackState == null) {
Log.e(TAG, "Playback state is null");
}
if (type.equals(Type.MENU_ERROR)) {
Bitmap icon = BitmapFactory.decodeResource(context.getResources(), R.drawable.error);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context.getApplicationContext());
notificationBuilder.extend(new android.support.v4.app.NotificationCompat.CarExtender())
.setStyle(new NotificationCompat.MediaStyle()
.setMediaSession(mediaSession.getSessionToken()))
.setSmallIcon(R.drawable.error)
.setShowWhen(false)
.setContentTitle(context.getString(R.string.title))
.setContentText(context.getString(R.string.message))
.setLargeIcon(icon)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
return notificationBuilder.build();
}
return null;
}
What am I missing to get this to show on the auto display and not on the phone?
NotificationCompat.CarExtender seems to be an option only for app declare as "notification" (message read and response feature for a messaging app for example).
<automotiveApp>
<uses name="notification"/>
</automotiveApp>
Display notification on home in "Auto" context with a "media" automotiveApp seems not allowed in actual api version.
For an error message associated to a media playing app (like it seems to be in your case) you can use error state which will be interpreted and displayed directly by Auto system.
private void showErrorMessage(final int errorCode, final String errorMessage) {
final PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder();
playbackStateBuilder.setState(PlaybackStateCompat.STATE_ERROR, -1L, 1.0F);
playbackStateBuilder.setErrorMessage(errorCode, errorMessage);
mSession.setPlaybackState(playbackStateBuilder.build());
}
Try this code to show the notification,
private void showPushNotification(String title, String message, Intent tapIntent, int notificationID) {
android.support.v7.app.NotificationCompat.Builder builder = new android.support.v7.app.NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.swiftee_white_logo_notification);
//Intent tapIntent = new Intent(this, HomeScreenActivity.class);
//tapIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//tapIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//tapIntent.putExtra(AppConstants.PUSH_MESSAGE, true);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, tapIntent, PendingIntent.FLAG_ONE_SHOT);
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
builder.setContentTitle(title);
builder.setContentText(message);
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationID, builder.build());
}
Please follow step by step from here
This sample demonstrate full demo
EDIT
For Media Notification you can use this . Here step by step explained about media app and notification for auto
I am putted my logic in android background service,which will be start on onClick action of my sticky notification.Everything working fine but problems are:-
When I am lock my phone and try to click/tap on notification it requires double click/tap always.
My logic is in background service but after clicked on notification Background service does not start until my mobile is unlocked.(Background service is sticky)
Below code is used for generate a sticky notification.
private void Notify() {
Context objContext = this.cordova.getActivity();
Intent objIntent = new Intent(objContext, ApiCallServeice.class);
PendingIntent pi = PendingIntent.getService(objContext, intNotificationId, objIntent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification.Builder builder = new Notification.Builder(objContext);
builder.setContentTitle("Click to get help.");
builder.setAutoCancel(false);
builder.setSmallIcon(objContext.getApplicationInfo().icon);
builder.setOngoing(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setVisibility(Notification.VISIBILITY_PUBLIC);
}
builder.setContentIntent(pi);
builder.build();
myNotication = builder.getNotification();
manager.notify(intNotificationId, myNotication);
}
Please suggest me the solution or need to set any flag in my code.
For getting click on notification UI everwhere.We need to use the Remote View in which you can put the button overlay on whole layout and write click listener on that button
Below is the update code I am used:-
private void Notify() {
Context objContext=this.cordova.getActivity();
Intent objIntent = new Intent(objContext, ApiCallServeice.class);
PendingIntent pi = PendingIntent.getService(objContext, intNotificationId, objIntent, PendingIntent.FLAG_CANCEL_CURRENT);
RemoteViews objRemoteViews = new RemoteViews(objContext.getApplicationContext().getPackageName(), R.layout.your_notification_layout);
objRemoteViews.setOnClickPendingIntent(R.id.your_notification_clickable_button, pi);
Notification.Builder builder = new Notification.Builder(objContext);
builder.setAutoCancel(false);
builder.setSmallIcon(objContext.getApplicationInfo().icon);
objRemoteViews.setImageViewResource(R.id.img_icon, objContext.getApplicationInfo().icon);
builder.setOngoing(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setVisibility(Notification.VISIBILITY_PUBLIC);
}
builder.setContent(objRemoteViews);
builder.build();
myNotication = builder.getNotification();
manager.notify(intNotificationId, myNotication);
}