Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android notification with RemoteViews - having activity associated with RemoteViews layout

I've been researching on how to create custom-layout notification using RemoteView.

So far, I am able to create a notification with contentView and bigContentView pointing to a RemoteView with a custom layout xml. However, what does not happen, is to have Activity (associated with custom layout) started when this RemoteView is created.

I've double checked and in my layout xml, it appears to have correct Activity class name:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="0dp"
    android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    tools:context=".LLMNotificationActivity" >

..... the rest are standard layout items: images, buttons and text

</RelativeLayout>

In manifest file, right after main application main activity, notification activity is also added:

<activity
    android:name=".LLMNotificationActivity"
    android:label="@string/app_name">
    <intent-filter>
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

I would expect when notification uses RemoteView for its content, that this RemoteView will launch activity that is attached to its layout definition. However it appears not.

Here is how I create a notification in main application Activity:

protected void startNoti() {
    if( noti!=null ) return;

    Context context = getApplicationContext();  

    RemoteViews contentView = new RemoteViews(context.getPackageName(),R.layout.activity_noti1);

    Notification.Builder notibuilder = new Notification.Builder(context);
    notibuilder.setContentTitle(" ");
    notibuilder.setContentText(" ");
    notibuilder.setSmallIcon(R.drawable.ic_launcher);
    notibuilder.setOngoing(true);

    manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    noti = notibuilder.build();

    noti.contentView = contentView;

    manager.notify(NOTIFICATION_ID, noti);  
}

LLMNotificationActivity activity class is defined as usual:

public class LLMNotificationActivity extends Activity {
    .... etc.... constructor, some button on-click handlers, nothing spectacular...
}

Can anyone point to me what I am missing or if I have misunderstood what RemoteView can do? My understanding is that RemoteView should, once created, invoke activity associated with its layout. Or - is there some API I've missed that explicitly can set intent of the RemoteView?

What I have found so far are only setting content Intent which basically just launches an Activity once user touches notification. What I'm looking for is to handle touches to some of UI elements inside custom-layout notification, not to launch an Activity regardless where the user clicks on notification surface.

For example, if I have 3 icons (i.e. ImageView) in a RemoteView which notification uses, I'd like to be able to handle touch on each one of them. I can't imagine this wouldn't be possible as if it's not, what's the point of having RemoteView in notification?

like image 846
Siniša Avatar asked Mar 23 '14 00:03

Siniša


People also ask

What is RemoteViews?

android.widget.RemoteViews. A class that describes a view hierarchy that can be displayed in another process. The hierarchy is inflated from a layout resource file, and this class provides some basic operations for modifying the content of the inflated hierarchy.


2 Answers

All you need to do is addsetContentIntent to your Notification.Builder like this:

Intent i = new Intent(context, YourLaunchedActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, 0);
Notification.Builder notibuilder = new Notification.Builder(context);
notibuilder.setContentIntent(pendingIntent);

Now, when you click on your notification, YourLanchedActivity will be launched.

like image 105
IgorGanapolsky Avatar answered Oct 13 '22 13:10

IgorGanapolsky


You have to associate the activity thought setOnClickPendingIntent to launch the activity from remote view as below...You can set any of the layout id in the RemoteView to click.

 Intent intent = new Intent(context, YourActivity.class);
 PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent,   PendingIntent.FLAG_UPDATE_CURRENT);
 RemoteViews removeWidget = new RemoteViews(context.getPackageName(), R.layout.your_layout);
 removeWidget.setOnClickPendingIntent(R.id.layout_id, pendingIntent);

provide an +id/layout_id to the RelativeLayout your using.

If you have to launch the activity when user click on the notification, then you have to use PendingIntent as....

    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentTitle("title")
                    .setContent(mRemoteControl);
    Intent notificationIntent = new Intent(this, YourActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(
            this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    mBuilder.setContentIntent(contentIntent);
    mNM.notify(1000,mBuilder.build());

For 3 buttons , You have to use create a custom RemoteView and use PendingIntent. some thing as below...

Here is the custom remote view i am using for one of my media player app. it has three button to handler click.

public class RemoveControlWidget extends RemoteViews
{
private final Context mContext;

public static final String ACTION_PLAY = "com.mediabook.app.ACTION_PLAY";

public static final String ACTION_PREVIOUS = "com.mediabook.app.ACTION_PREVIOUS";

public static final String ACTION_NEXT = "com.mediabook.app.ACTION_NEXT";

public RemoveControlWidget(Context context , String packageName, int layoutId)
{
    super(packageName, layoutId);
    mContext = context;
    Intent intent = new Intent(ACTION_PLAY);
    PendingIntent pendingIntent = PendingIntent.getService(mContext.getApplicationContext(),100,
            intent,PendingIntent.FLAG_UPDATE_CURRENT);
    setOnClickPendingIntent(R.id.play_control,pendingIntent);
    setOnClickPendingIntent(R.id.pause_control,pendingIntent);
    intent = new Intent(ACTION_PREVIOUS);
    pendingIntent = PendingIntent.getService(mContext.getApplicationContext(),101,
            intent,PendingIntent.FLAG_UPDATE_CURRENT);
    setOnClickPendingIntent(R.id.previous_control,pendingIntent);
    intent = new Intent(ACTION_NEXT);
    pendingIntent = PendingIntent.getService(mContext.getApplicationContext(),102,
            intent,PendingIntent.FLAG_UPDATE_CURRENT);
    setOnClickPendingIntent(R.id.next_control,pendingIntent);
}
}
like image 20
Libin Avatar answered Oct 13 '22 13:10

Libin