Android: Custom notification appearance issue - android

I am using MediaPlayer in my app. I am adding an Ongoing Notification with media player controls (such as previous, next and stop buttons) in my app, so that users don't have to go in the app to access those controls. It looks fine on platforms 4.x. Here is the screenshot of the notification on Android 4.2.2.
But, on Android 2.2, it looks like this:
My code is as follows:
private Notification generateNotification() {
Log.d(TAG, "generateNotification called");
Intent actionIntent = new Intent(getApplicationContext(),
AartiActivity.class);
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(),
0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews mNotificationView = new RemoteViews(getPackageName(),
R.layout.notification_view);
NotificationCompat.Builder builder = new NotificationCompat.Builder(
getApplicationContext());
builder.setSmallIcon(R.drawable.icon);
builder.setContent(mNotificationView);
builder.setOngoing(true);
builder.setTicker("Aarti Sangrah");
builder.setContentIntent(pi);
mNotificationView.setImageViewResource(R.id.imgAppIc, R.drawable.icon);
mNotificationView.setTextViewText(R.id.txtAartiPlaying, mediaName);
return builder.build();
}// generateNotification
And then, I called startForeground(1, generateNotification()); in onPrepared().
The Remote Views is available since API level 1. And, it is well supported also. I read somewhere, it was not supported prior to Honeycomb. But, on several devices having Android 2.x, this feature is available. Also, in order to check this, I looked at the source code of Music Player of Android 2.2 from here.
Here, is the snippet from its Music Player Service.
RemoteViews views = new RemoteViews(getPackageName(),
R.layout.statusbar);
views.setOnClickPendingIntent(R.id.btnTest, PendingIntent
.getActivity(getApplicationContext(), 0,
new Intent(getApplicationContext(),
MusicBrowserActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT));
views.setImageViewResource(R.id.icon,
R.drawable.stat_notify_musicplayer);
if (getAudioId() < 0) {
// streaming
views.setTextViewText(R.id.trackname, getPath());
views.setTextViewText(R.id.artistalbum, null);
} else {
String artist = getArtistName();
views.setTextViewText(R.id.trackname, getTrackName());
if (artist == null || artist.equals(MediaStore.UNKNOWN_STRING)) {
artist = getString(R.string.unknown_artist_name);
}
String album = getAlbumName();
if (album == null || album.equals(MediaStore.UNKNOWN_STRING)) {
album = getString(R.string.unknown_album_name);
}
views.setTextViewText(
R.id.artistalbum,
getString(R.string.notification_artist_album, artist,
album));
}
Notification status = new Notification();
status.contentView = views;
status.flags |= Notification.FLAG_ONGOING_EVENT;
status.icon = R.drawable.stat_notify_musicplayer;
status.contentIntent = PendingIntent.getActivity(this, 0,
new Intent("com.android.music.PLAYBACK_VIEWER")
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);
startForeground(PLAYBACKSERVICE_STATUS, status);
The Remote Views has been used in this code. It had two TextViews. I modified the code by adding a button to it, and also performed action on button click. Everything worked fine on every platform.
Same thing, I want with my application. But, on 2.2, it looks as I had shown above in the screenshot. I thought it is because of white colors text and button so tried changing the colors of button and text, but no luck. As far as I understand, only thing I figured out is remote view is not inflated on Android 2.2 (in my case). I am not getting why notification is not appearing properly on Android 2.x platforms.

I solved my problem. Here is my solution.
private Notification generateNotification() {
Log.d(TAG, "generateNotification called");
Intent actionIntent = new Intent(getApplicationContext(),
AartiActivity.class);
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(),
0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews mNotificationView = new RemoteViews(getPackageName(),
R.layout.notification_view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(
getApplicationContext());
builder.setSmallIcon(R.drawable.icon);
builder.setContent(mNotificationView);
builder.setOngoing(true);
builder.setTicker("Aarti Sangrah");
builder.setContentIntent(pi);
mNotificationView.setImageViewResource(R.id.imgAppIc,
R.drawable.icon);
mNotificationView.setTextViewText(R.id.txtAartiPlaying, mediaName);
mNotificationView.setTextColor(R.id.txtAartiPlaying, getResources()
.getColor(android.R.color.holo_orange_light));
return builder.build();
} else {
mNotificationView.setTextViewText(R.id.txtAartiPlaying, mediaName);
mNotificationView.setTextColor(R.id.txtAartiPlaying, getResources()
.getColor(android.R.color.holo_orange_light));
Notification statusNotification = new Notification();
statusNotification.contentView = mNotificationView;
statusNotification.flags |= Notification.FLAG_ONGOING_EVENT;
statusNotification.icon = R.drawable.icon;
statusNotification.contentIntent = PendingIntent.getActivity(this,
0, new Intent(getApplicationContext(), AartiActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);
return statusNotification;
}
}// generateNotification
But, I am quiet surprised. NotificationCompat.Builder is available in support package and it has been provided for backward compatibility. But, in my case it is working only on Honeycomb and above. As per this section:
Not all notification features are available for a particular version, even though the methods to set them are in the support library class NotificationCompat.Builder. For example, action buttons, which depend on expanded notifications, only appear on Android 4.1 and higher, because expanded notifications themselves are only available on Android 4.1 and higher.
But, I don't think that, this is applicable for my case. NotificationCompat.Builder works with remote views but didn't worked on 2.x(at least in my case, may be I am wrong or missing something). If anybody has any information or resources in this regard, please share it so that I can figure out my mistake.

Related

Inconsistent notification actions buttons' UI even on same device

I have an app where i'm having some issues with notifications not being consistent on different devices. The notification is used by a foreground service
This is what my notification looks like in my pixel3 api29 emulator
Because of the issue i'm troubleshooting, I decided to extract the code and put it in a dummy app that would let me simulate the triggering event more easily. However, after doing that and running on the exact same pixel3 api29 emulator, i realized the notification is not even consistent on the same device. In the dummy app for a dummy foreground service the notification looks like this
I can't find what's driving the different look of the action buttons in the two apps. Even the behaviour is different. In the first version, the floating headsup notification stays there forever until i clear it programatically but in the second dummy app the notification clears itself after 6 seconds. I tried using the same theme in both, added the exact same dependency versions thinking that i was pulling different versions of the notification library but nothing, the code to create the notifications is the same in both:
private Notification createIncomingCallNotification(Intent intent) {
Intent hangupIntent = new Intent(this, getClass());
hangupIntent.setAction("hangup");
PendingIntent hangupPendingIntent = PendingIntent.getService(this, 1244, hangupIntent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Action hangupAction = new NotificationCompat.Action.Builder(0, getActionText(R.string.hangup_button_label, R.color.test1), hangupPendingIntent).build();
Intent uiIntent = new Intent(this, VideoCallActivity.class);
uiIntent.putExtras(intent);
uiIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0, uiIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action previewAction = new NotificationCompat.Action.Builder(0, getActionText(R.string.preview, R.color.test2), fullScreenPendingIntent).build();
String caller = "Caller guy";
Log.v(TAG, "Creating incoming call notification from " + caller);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, ChannelIds.INCOMING_CALL_CHANNEL_ID)
.setContentTitle(getString(R.string.incoming_call_notification_title, caller))
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setSmallIcon(R.drawable.ic_white_100dp)
.addAction(hangupAction)
.addAction(previewAction)
.setOnlyAlertOnce(true)
.setFullScreenIntent(fullScreenPendingIntent, true);
return notificationBuilder.build();
}
private Spanned getActionText(#StringRes int stringRes, #ColorRes int colourRes) {
Spannable spannable = new SpannableString(getText(stringRes));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
// This will only work for cases where the Notification.Builder has a fullscreen intent set
// Notification.Builder that does not have a full screen intent will take the color of the
// app and the following leads to a no-op.
spannable.setSpan(new ForegroundColorSpan(getColor(colourRes)), 0, spannable.length(), 0);
}
return spannable;
}
Does anyone know what can cause this inconsistency even on the same device?
I finally figured it out. What changes the headsup notification is this permission in the manifest
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>

Notification bar icon turns white in Android L

I'm using a remote view for custom notification layout. Everything works fine. Only problem that I'm facing is the notification is displayed as a white circle in the notification status bar. I want my app icon to be shown in the notification status bar(how it shows in kitkat & lower versions). is there any way to change this?
private void showNotification() {
Intent intent = new Intent(this, HomeActivity.class);
intent.putExtra(LIVE_RADIO_PUSH, true);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, 0);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setCategory(Notification.CATEGORY_SERVICE);
mBuilder.setContentTitle(mTitle);
mBuilder.setContentText("Live Radio");
mBuilder.setSmallIcon(R.drawable.logo);
mBuilder.setWhen(System.currentTimeMillis());
mBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
mBuilder.setContentIntent(pendingIntent);
mBuilder.setColor(getResources().getColor(R.color.theme_primary));
mNotificationView = new RemoteViews(getPackageName(), R.layout.notification_layout);
mNotificationView.setTextViewText(R.id.content_title, mTitle);
mNotificationView.setTextViewText(R.id.content_text, "Live Radio");
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm");
String time = dateFormat.format(new Date(System.currentTimeMillis()));
mNotificationView.setTextViewText(R.id.current_time, time);
mNotificationView.setImageViewResource(R.id.play_pause, R.drawable.pause_radio);
mNotificationView.setImageViewResource(R.id.close_btn, R.drawable.notifictn_close_btn);
setListeners(mNotificationView);
mBuilder.setContent(mNotificationView);
Log.d(TAG, "App is freezed2");
if (null != mNotificationMngr)
mNotificationMngr.notify(RADIO_NOTIFICATION_ID, mBuilder.build());
}
I have encountered this issue too, as you mention, if your ANDROID_BUILD_TARGET_SDK_VERSION = 21, it will change this notification into white.
The notification icon design guideline as this link.
http://developer.android.com/design/style/iconography.html
Recently we done one application with notification.Its working fine in lollipop also.Once check the below code may be it will helps you.
mNotification = new Notification.Builder(this).setContentTitle("M3 Media Player").setContentIntent(mPendingIntentHome)
.setSmallIcon(R.drawable.app_icon).setPriority(Notification.PRIORITY_MAX).setContent(mNotificationContentView)
.setStyle(new Notification.BigPictureStyle()).build();
If your compileSDKversion is above 20 then notification icon should be a white-on-transparent background image. Otherwise the image will be rendered as a white colored image.
Please go through the below link too for guidelines to create the icon
https://www.google.com/design/spec/patterns/notifications.html
and also the notification icon generator.
https://romannurik.github.io/AndroidAssetStudio/icons-notification.html#source.space.trim=1&source.space.pad=0&name=ic_stat_example

Android Wear Notification Page Actions

I have an app that kicks off a notification on a Wear device (the notification is created and shown on the Wear device).
What I want to do is have the "first" notification page display some high level info (app name, scroll to see more, etc...), and then have a list of pages containing content after that.
That works fine. The issue is that I want to attach an Action to each page (to kick off a PendingIntent). However, no matter what I try, I can't get the page to perform the Action.
I've tried:
setContentIntent
addAction
addAction and extend(new Notification.WearableExtender().setContentAction(0))
Anyone have any ideas?
I'm using Notification, not NotificationCompat, but I don't think that should make a difference.
UPDATE: I'm creating the notification on the watch. Here is the code I use:
private void createNotifications(ArrayList<Thing> things) {
DataApi data = Wearable.DataApi;
int notificationId = 0;
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification.Builder mainBuilder = new Notification.Builder(this)
.setSmallIcon(R.drawable.default_icon)
.setContentTitle("Things")
.setContentText("Swipe to see your things")
.setPriority(Notification.PRIORITY_DEFAULT);
List<Notification> pages = new ArrayList<>(things.size());
for(Thing thing : things) {
pages.add(createNotificationPageForThing(data, thing, notificationId).build());
notificationId++;
}
Notification n = new Notification.WearableExtender().addPages(pages).extend(mainBuilder).build();
nm.notify(notificationId, n);
}
private Notification.Builder createNotificationPageForThing(DataApi data, Thing thing, int notificationId) {
Asset bitmapAsset = getBitmapAsset(data, contact);
Intent thingIntent = new Intent(this, WearDetailActivity.class);
thingIntent.putExtra(WearDetailActivity.DETAIL_EXTRA, thing);
PendingIntent thingPendingIntent = PendingIntent.getActivity(this, notificationId, thingIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Action action = new Notification.Action(R.drawable.ic_action_social_person, "More details", thingPendingIntent);
Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_action_social_person)
.setContentTitle(thing.getDisplayName())
.setPriority(Notification.PRIORITY_DEFAULT)
.addAction(action)
.extend(new Notification.WearableExtender().setContentAction(0));
if(bitmapAsset != null) {
try {
Bitmap b = BitmapFactory.decodeStream(
data.getFdForAsset(connection.getClient(), bitmapAsset).await().getInputStream());
builder.setLargeIcon(b);
} catch (Throwable ignore) {}
}
return builder;
}
#Eliezer, reading at the following line I did not understand what exactly is the behaviour you're experiencing ... explaining it in details might be helpful to debug your problem.
However, no matter what I try, I can't get the page to perform the Action.
Using .addAction() should work in your case. You'd want to use WearableExtender if you were creating the notification from the device, not the watch itself. Just to confirm something obvious - you're passing the .addAction a PendingIntent right?
Here's a code snippet from one of my applications, which accomplishes exactly what you're aiming for - I have just "Swipe for actions" text in the first page, and the next 2 pages perform different actions.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
Intent openIntent = new Intent(this, CommonWearIntentService.class);
openIntent.setAction(CommonWearIntentService.ACTION_OPEN_ON_PHONE);
PendingIntent openPendingIntent = PendingIntent.getService(this, 0, openIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent addTransactionIntent = new Intent(this, CommonWearIntentService.class);
addTransactionIntent.setAction(CommonWearIntentService.ACTION_ADD_TRANSACTION);
PendingIntent addTransactionPendingIntent = PendingIntent.getService(this, 0, addTransactionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.swipe_for_actions))
.addAction(R.drawable.add_transaction, getString(R.string.add_transaction), addTransactionPendingIntent)
.addAction(R.drawable.common_full_open_on_phone, getString(R.string.common_open_on_phone), openPendingIntent)
.setVibrate(new long[]{500, 500, 500, 1000})
.setLights(Color.BLUE, 3000, 3000)
.setOngoing(true);
notificationManager.notify(ONGOING_NOTIFICATION_ID, builder.build());
Hope this helps!
Per the documentation, you must use NotificationCompat. After you switch to that setContentIntent() looks to be the right way to set the PendingIntent.
Example from the linked docs:
// Create builder for the main notification
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.new_message)
.setContentTitle("Page 1")
.setContentText("Short message")
.setContentIntent(viewPendingIntent);
// Create a big text style for the second page
BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
secondPageStyle.setBigContentTitle("Page 2")
.bigText("A lot of text...");
// Create second page notification
Notification secondPageNotification =
new NotificationCompat.Builder(this)
.setStyle(secondPageStyle)
.build();
// Add second page with wearable extender and extend the main notification
Notification twoPageNotification =
new WearableExtender()
.addPage(secondPageNotification)
.extend(notificationBuilder)
.build();
// Issue the notification
notificationManager =
NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, twoPageNotification);

what to code for notification to stick until music stop playing

I want notification which will stick on notification bar until music stop playing it.
currently i have written some code in which i can show notification but when i press clear notification button or swap it than it disappear from notification center.
I want notification like spotify which stays on bar until you stop playing music.
Here is my code for notification
int pendingRequestCode = 0;
// final Resources res = getResources();
notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);
Intent i = new Intent(getApplicationContext(),Mainactivity.class);
Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_action_search)
.setAutoCancel(true)
.setTicker("test ckick")
.setContentIntent(PendingIntent.getActivity(getApplicationContext(), NOTIFICATION_DEFAULT, i,0));
// Sets a custom content view for the notification, including an image button.
layout = new RemoteViews(getPackageName(), R.layout.notification);
layout.setTextViewText(R.id.notification_title, getString(R.string.app_name));
Intent clickIntent = new Intent();
clickIntent.setAction(ACTION_DIALOG);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), pendingRequestCode, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
layout.setOnClickPendingIntent(R.id.notification_button,pendingIntent);
builder.setContent(layout);
// Notifications in Android 3.0 now have a standard mechanism for displaying large
// bitmaps such as contact avatars. Here, we load an example image and resize it to the
// appropriate size for large bitmaps in notifications.
layout.setImageViewResource(R.id.notification_button, R.drawable.pause);
notificationManager.notify(NOTIFICATION_DEFAULT, builder.getNotification());
waiting for reply
Use setOngoing(true) to indicate that the event is ongoing. You may also wish to remove setAutoCancel(true), as that clears the Notification when the user taps upon it.
notification.flags = Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL

Custom notification with remote view on Android

I have edited the code by using setOnClick pending intent, and this code works for ImageView and notifications text seperate as I want, but I still need some help.
I want to pause or play mediaplayer from my service class, so how could I access the stop or play method of service from Notification pending intent?
Some says broadcast receivers will help you, but I don't get exactly how it's going to work.
I have managed to open a web browser from the pause button from notification, but I don't know how to access service methods. Share any sample code if you have some.
#SuppressWarnings("deprecation")
void showNotification() {
int pendingRequestCode = 0;
int pendingFlag = 0;
final Resources res = getResources();
final NotificationManager notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);
Intent intent = new Intent(this,MainActivity.class);
PendingIntent pi= PendingIntent.getActivity(this, 0, intent, 0);
Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_action_search)
.setAutoCancel(true)
.setTicker("this is notification")
.setContentIntent(pi);
// Sets a custom content view for the notification, including an image button.
RemoteViews layout = new RemoteViews(getPackageName(), R.layout.notification);
layout.setTextViewText(R.id.notification_title, getString(R.string.app_name));
Intent clickIntent = new Intent(Intent.ACTION_VIEW, Uri_myBlog);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),pendingRequestCode, clickIntent, pendingFlag);
layout.setOnClickPendingIntent(R.id.notification_button,pendingIntent);
builder.setContent(layout);
// Notifications in Android 3.0 now have a standard mechanism for displaying large
// bitmaps such as contact avatars. Here, we load an example image and resize it to the
// appropriate size for large bitmaps in notifications.
Bitmap largeIconTemp = BitmapFactory.decodeResource(res,
R.drawable.pause);
Bitmap largeIcon = Bitmap.createScaledBitmap(
largeIconTemp,
res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width),
res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height),
false);
largeIconTemp.recycle();
builder.setLargeIcon(largeIcon);
notificationManager.notify(NOTIFICATION_DEFAULT, builder.getNotification());
}
PendingIntent getDialogPendingIntent(String dialogText) {
return PendingIntent.getActivity(
this,
dialogText.hashCode(), // Otherwise previous PendingIntents with the same
// requestCode may be overwritten.
new Intent(ACTION_DIALOG)
.putExtra(Intent.EXTRA_TEXT, dialogText)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
0);
}
You did not tell what version of Android you target, but in general it is not possible until Android 3.x (Honeycomb). So if you want that to happen on 2.x, then sorry - you are out of luck.
For Honeycomb, you simply have to provide a custom layout and assign PendingIntent to each button you need, by calling setOnClickPendingIntent(). If you got the SDK's samples downloaded, then see MainActivity of the HoneycombGallery app (shall be in your <SDK>\samples\android-XX\HoneycombGallery\ folder. XX is anything from 14 (or higher).
Check Bound Services using Messenger
http://developer.android.com/guide/components/bound-services.html
Also you can check this question
Binding to a local Service from a BroadcastReceiver

Categories

Resources