I'm developping a music player application for android and I'm stuck with a problem in the notification layout. It seems like I can't add any complicated element in it or it throws android.app.RemoteServiceException: Bad notification.
Problem is I wrote a player controller that is a Fragment. I can't find how to add the fragment by hand in code so I tried directly in XML layout but without success. I also had the problem with a custom ImageView that I wrote.
Am I really obliged to duplicate code ?
It does not look like you can add a fragment. You could see if MediaStyle fits your needs. In your notification builder you would add .setStyle(NotificationCompat.MediaStyle). Otherwise it looks like you would have to subclass Notification.Style or NotificationCompat.Style to create a custom layout. It also looks like for some options you can intercept the notification as it's being created. Check this out for more details.
Edit:
Given your time frame, and if you're willing to flex some on your layout, then I would just add buttons to the notification. Create a pending intent for each action you want to be able to do from your notification (play, pause, skip). By way of a code sample I've included an abbreviated version of how I put a dismiss button in my notifications.
Intent resultIntent = new Intent(context, AlarmScreen.class);
resultIntent.putExtra("Id",reminder.getId());
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
context,
reminder.getId()*2,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
Notification.Builder mBuilder =
new Notification.Builder(context)
.setStyle(new Notification.BigTextStyle()
.bigText(reminder.getDescription()))
.addAction(R.drawable.ic_stat_content_clear, "Dismiss", dismissPendingIntent)
.build();
In your case you should be able to replace the R.drawable.ic_stat_content_clear with an appropriate icon and maybe skip the text. You can just repeat .addAction() for each button you want. Notice also where I have reminder.getId()*2 in my pending intent declaration? I found that if I had the same number there for both of my buttons I got strange results, so one of my buttons has id*2 and the other has id*2+1.
As for how you handle the intents sent by the buttons, you'll have to create a BroadcastReceiver to receive them, and figure out where to go from there based on how you're implementing the rest of your logic.
That is not possible. Notification only able to use with RemoteView. RemoteView support some views only, and it do not support custom views or fragment.
Related
I have set up a notification for a custom xml and I can successfully register click events.
remoteViews.setOnClickPendingIntent(R.id.notif_button, pendingIntent);
I also have a broadcast receiver that receives the onclick event, no problem there.
As you can see, this event fires once when the user releases the button. I need an event that fires every time when the user touches the button, so I can change it. Like every button in android.
Setting selectors in xml did not work. I tried this example:
https://developer.android.com/reference/android/widget/ImageButton.html
It should be possible, since some music players implemented this behaviour. Any ideas to achieve that?
As you can see, this event fires once when the user releases the button.
That's because that's what is considered a "click" -> touch down and then touch up on the same object. If you touch a button, keep it on screen but move out of it and release then the click won't be fired. That's why it works that way.
I need an event that fires every time when the user touches the button
You cannnot have this. Luckily.
Setting selectors in xml did not work
Selectors are not for this.
private NotificationTarget notificationTarget;
notificationTarget = new NotificationTarget(
context,
R.id.remoteview_notification_icon,
remoteViews,
notification,
NOTIFICATION_ID);
GlideApp
.with(context.getApplicationContext())
.asBitmap()
.load(eatFoodyImages[3])
.into(notificationTarget);
For further reference please visit
https://futurestud.io/tutorials/glide-loading-images-into-notifications-and-appwidgets
Create a custom notification...define your xmls add your selectors and background and create and trigger your notifications.
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this).setSmallIcon(R.drawable.ic_launcher);
RemoteViews mContentView = new RemoteViews(getPackageName(), R.layout.test_tt);
mContentView.setImageViewResource(R.id.image, R.drawable.ic_action_search);
mContentView.setTextViewText(R.id.title, "Custom notification");
mContentView.setTextViewText(R.id.text, "This is a custom layout");
mBuilder.setContent(mContentView);
notimgr.notify(1001, mBuilder.build());
let me know if any issues.
Best Regds
I have been struggling in these last two days to find a way to make a custom android notification. I have passed by the remote views solution but this solution is very limited to changing the layout only. What I need is to put a custom view(other than text views, image views, and these typical views that are usually seen in a notification) in a notification. Is that possible?
but this solution is very limited to changing the layout only
I do not know what you mean by this. The RemoteViews can certainly have more than a layout manager (e.g., LinearLayout); otherwise, it would pointless.
What I need is to put a custom view(other than text views, image views, and these typical views that are usually seen in a notification) in a notification. Is that possible?
You are welcome to try whatever RemoteViews supports, minus the AdapterView subclasses (e.g., ListView). Interactive widgets, such as buttons, will be unreliable, particularly on Android 1.x/2.x, as vendor customizations to the notification tray sometimes prevent interactive widgets from working properly.
A simplest example of custom notification
private void showCustomeNoti() {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this).setSmallIcon(R.drawable.ic_launcher);
RemoteViews mContentView = new RemoteViews(getPackageName(),
R.layout.custome_notification_layout);
mBuilder.setContent(mContentView);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(100, mBuilder.build());
}
Call this function when you want to show custom notification.
I am using the following code showing the notification, it works properly. I am look for the listener from which i can come to know whether the notification is expanded or not.
I want to open the app if the notification is expanded or else open the particular activity of the app.
Intent intent= new Intent(context, Activity1.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, getNextRandom(), intent, 0);
Builder newBuilder newBuilder = new Notification.Builder(context);
newBuilder.setContentTitle(title)
.setContentText(subtitle)
.setAutoCancel(true)
.setSmallIcon(R.drawable.icon)
.setTicker(notificationMessage)
.setContentIntent(pendingIntent);
Notificationnotification = new Notification.BigTextStyle(newBuilder)
.setBigContentTitle(notificationTitle)
.bigText(text)
.build();
Let me know if there is way to acheive this?
There is no way to know if the notification is open... What you can do is add buttons to the expanded notification that pressing on them will act differently than pressing on the notification itself.
There maybe no direct way, but maybe the following hack can help!!
You can have a custom notification layout and use RemoteView, Set a setOnClickPendingIntent to launch a service for the entire view so that you get notified when the notification is clicked.
When the user clicks the notification, service is started and show the new expanded custom layout from the service (you replace the old notification with the new one)
Maybe show your initial notification also from the same service using startforeground, so that your app is not killed and the view click can be received faster since service is already running and response time for changing the view is lower.
see this for remoteview and this for launching service from notification click.
I want to create such kind of a notification (like here, in Breaking out of the card (with custom layouts) section). That is, it shoud contain a full screen page (in fact, with a map).
Is it (on a picture) an extended notification or a wear app? How to implement this full screen view?
I have tried doing as described here, but my activity is not starting from a notification.
You can embed an Activity into a Wear Notification like so:
Notification myFullScreenNotification = new Notification.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText(notificationText)
.extend(new Notification.WearableExtender()
.setCustomSizePreset(Notification.WearableExtender.SIZE_FULL_SCREEN)
.setDisplayIntent(PendingIntent.getActivity(context, 0, new Intent(context, MyActivity.class), 0)))
.build();
Make sure you give the right permissions in your AndroidManifest.xml:
<activity
android:name=".MyActivity"
android:exported="true"
android:allowEmbedded="true"
android:taskAffinity="" />
The notification shows normally until the user swipes upwards, then it will turn into fullscreen and run the activity on the page.
If you want to use the Activity as a secondary page of the Notification, then insert the Notification above as a page of another notification like so:
Notification myWearNotification = new Notification.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText(notificationText)
.extend(new Notification.WearableExtender()
.addPage(myFullScreenNotification)
.build();
An Android Wear app is required to fully customise the layout of a notification.
I tried coding a custom library which ships a layout xml from the phone to wear and inflate but that's not possible because of limitations relating to LayoutInflator.
Here's the relevant bit for reference: For performance reasons, view inflation relies heavily on pre-processing of XML files that is done at build time. Therefore, it is not currently possible to use LayoutInflater with an XmlPullParser over a plain XML file at runtime; it only works with an XmlPullParser returned from a compiled resource (R.something file.)
I'd like to remove the ContentIntent from my android wear notification (I have a separate action i'd like to use when opening app from watch), but still keep it on the handheld. The following code sets the content intent and then ends up removing it later. Does anyone know how to do this?
mainNotification.setContentIntent(contentIntent)
// wearable extender to add 2nd page and extend the main notification
dualNotification =
new NotificationCompat.WearableExtender()
.extend(mainNotification)
.extend(wearableExtendedNotification)
.setContentIntent(null) // thisremoves content intent that was set before
;
I also tried using setContentAction() which would work fine but it squishes the first notification card down on the wearable so the text isn't readable.