36

I have a custom notification with a button. To set the notification and use the event OnClick on my button I've used this code:

//Notification and intent of the notification 
Notification notification = new Notification(R.drawable.stat_notify_missed_call,
            "Custom Notification", System.currentTimeMillis());

Intent mainIntent = new Intent(getBaseContext(), NotificationActivity.class);
PendingIntent pendingMainIntent = PendingIntent.getActivity(getBaseContext(),
    0, mainIntent , 0);
notification.contentIntent = pendingMainIntent;

//Remoteview and intent for my button
RemoteViews notificationView = new RemoteViews(getBaseContext().getPackageName(),
    R.layout.remote_view_layout);

Intent activityIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:190"));
PendingIntent pendingLaunchIntent = PendingIntent.getActivity(getBaseContext(), 0,
            activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);

notificationView.setOnClickPendingIntent(R.id.button1,
    pendingLaunchIntent);

notification.contentView = notificationView;

notificationManager.notify(CUSTOM_NOTIFICATION_ID, notification);

With this code I've a custom notification with my custom layout...but I can't click the button! every time I try to click the button I click the entire notification and so the script launch the "mainIntent" instead of "activityIntent".

I have read in internet that this code doesn't work on all terminals. I have tried it on the emulator and on an HTC Magic but I have always the same problem: I can't click the button!

My code is right? someone can help me?

Thanks,

Simone

Simone
  • 795
  • 2
  • 7
  • 17
  • i.e. I need something particular in my "androidmanifest.xml" to use a button in a remoteview? – Simone Mar 30 '11 at 18:10
  • May be this will help you do this Here's [a link](http://stackoverflow.com/questions/16396318/adding-onclick-action-to-button-in-notification)! – Syed Raza Mehdi Feb 20 '14 at 08:09

5 Answers5

25

I am writing code in my MyActivity.java class that extends android.app.Activity

It creates a custom notification, when user click on the button it sends a broadcast. There is a broadcast receiver that receives the broadcast.

private void createDownloadNotification() {
        Intent closeButton = new Intent("Download_Cancelled");
        closeButton.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

        PendingIntent pendingSwitchIntent = PendingIntent.getBroadcast(this, 0, closeButton, 0);

        RemoteViews notificationView = new RemoteViews(getPackageName(), R.layout.widget_update_notification);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.ic_launcher).setTicker("Ticker Text").setContent(notificationView);
        notificationView.setProgressBar(R.id.pb_progress, 100, 12, false);
        notificationView.setOnClickPendingIntent(R.id.btn_close, pendingSwitchIntent);

        notificationManager.notify(1, builder.build());

    }


public static class DownloadCancelReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            System.out.println("Received Cancelled Event");
        }
    }

Register receiver in AndroidManifest.xml

<receiver android:name=".MainActivity$DownloadCancelReceiver" android:exported="false">
            <intent-filter>
                <action android:name="Download_Cancelled" />
            </intent-filter>
        </receiver>

Since it is inner class so have to use $ sign

Widget xml is here

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:orientation="horizontal" >

    <Button
        android:id="@+id/btn_close"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Close Me" />

    <ProgressBar
        android:id="@+id/pb_progress"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
AZ_
  • 21,688
  • 25
  • 143
  • 191
  • Having a `public static` class simply for this purpose is opening up too much access. Can't this class be **not** static? – IgorGanapolsky Apr 27 '16 at 15:49
  • 2
    it is an inner class, so i made it static. you can always chose different approaches. – AZ_ Apr 28 '16 at 16:11
9

check this out

  1. Create an xml layout file for your notification.

  2. Create the notification using the Notification.Builder. After adding everything you want (icons, sounds, etc) do this:

    //R.layout.notification_layout is from step 1
    
    RemoteViews contentView=new RemoteViews(ctx.getPackageName(), R.layout.notification_layout);
    
    setListeners(contentView);//look at step 3
    
    notification.contentView = contentView;
    
  3. Create a method setListeners. Inside this method you have to write this:

    //HelperActivity will be shown at step 4
    
    Intent radio=new Intent(ctx, packagename.youractivity.class);  
    radio.putExtra("AN_ACTION", "do");//if necessary
    
    PendingIntent pRadio = PendingIntent.getActivity(ctx, 0, radio, 0);
    //R.id.radio is a button from the layout which is created at step 2                  view.setOnClickPendingIntent(R.id.radio, pRadio); 
    
    //Follows exactly my code!
    Intent volume=new Intent(ctx, tsapalos11598712.bill3050.shortcuts.helper.HelperActivity.class);
    volume.putExtra("DO", "volume");
    
    //HERE is the whole trick. Look at pVolume. I used 1 instead of 0.
    PendingIntent pVolume = PendingIntent.getActivity(ctx, 1, volume, 0);
    view.setOnClickPendingIntent(R.id.volume, pVolume);
    
  4. For my requirements I used a HelperActivity which responds to the intents. But for you I don't think it is necessary.

If you want the full source code you can browse it or download it from my git repo. The code is for personal use, so don't expect to read a gorgeous code with a lot of comments. https://github.com/BILLyTheLiTTle/AndroidProject_Shortcuts

ALL THE ABOVE, ANSWERS THE QUESTION OF CATCHING EVENT FROM DIFFERENT BUTTONS.

About canceling the notification I redirect you here (How to clear a notification in Android). Just remember to use the id you parsed at the notify method when you called the notification for fist time

Community
  • 1
  • 1
Mahalakshmi
  • 320
  • 2
  • 13
  • 3
    What if I do not want to launch activity on button click I just want to perform simple action like play/pause the song. – Ashwin N Bhanushali May 29 '14 at 06:20
  • Good one. You also should mention that PendingIntent.FLAG_UPDATE_CURRENT should be used when intent has extras. And i think it will be nice to say about requestCode incrementation on the first lines of explanation. Thx! – Vitaliy A Dec 20 '15 at 18:20
  • 1
    you just copied and pasted, you should give credits to him https://stackoverflow.com/a/10959343/8678995 – Haider Saleem Feb 17 '20 at 08:40
3

it seems that setOnClickPendingIntent doesn't work when used inside collections.

So try setPendingIntentTemplate instead of setOnClickPendingIntent. for more information bellow android developer link...

Click here for More Detail - Goto Android Developer Site.

kaushik
  • 903
  • 7
  • 16
1

You need to create Service to detect on Click event: For example Create NotificationIntentService.class and put below code:

public class NotificationIntentService extends IntentService {

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     */
    public NotificationIntentService() {
        super("notificationIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        switch (intent.getAction()) {
            case "left":
                android.os.Handler leftHandler = new android.os.Handler(Looper.getMainLooper());
                leftHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getBaseContext(),
                                "You clicked the left button", Toast.LENGTH_LONG).show();
                    }
                });
                break;
            case "right":
                android.os.Handler rightHandler = new android.os.Handler(Looper.getMainLooper());
                rightHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getBaseContext(), "You clicked the right button", Toast.LENGTH_LONG).show();
                    }
                });
                break;
        }
    }
}

Add this metod to your activity:

private void sendNotification() {

    RemoteViews expandedView = new RemoteViews(getPackageName(), R.layout.view_expanded_notification);
    expandedView.setTextViewText(R.id.timestamp, DateUtils.formatDateTime(this, System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME));
    expandedView.setTextViewText(R.id.notification_message, mEditText.getText());
    // adding action to left button
    Intent leftIntent = new Intent(this, NotificationIntentService.class);
    leftIntent.setAction("left");
    expandedView.setOnClickPendingIntent(R.id.left_button, PendingIntent.getService(this, 0, leftIntent, PendingIntent.FLAG_UPDATE_CURRENT));
    // adding action to right button
    Intent rightIntent = new Intent(this, NotificationIntentService.class);
    rightIntent.setAction("right");
    expandedView.setOnClickPendingIntent(R.id.right_button, PendingIntent.getService(this, 1, rightIntent, PendingIntent.FLAG_UPDATE_CURRENT));

    RemoteViews collapsedView = new RemoteViews(getPackageName(), R.layout.view_collapsed_notification);
    collapsedView.setTextViewText(R.id.timestamp, DateUtils.formatDateTime(this, System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME));

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
            // these are the three things a NotificationCompat.Builder object requires at a minimum
            .setSmallIcon(R.drawable.ic_pawprint)
            .setContentTitle(NOTIFICATION_TITLE)
            .setContentText(CONTENT_TEXT)
            // notification will be dismissed when tapped
            .setAutoCancel(true)
            // tapping notification will open MainActivity
            .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0))
            // setting the custom collapsed and expanded views
            .setCustomContentView(collapsedView)
            .setCustomBigContentView(expandedView)
            // setting style to DecoratedCustomViewStyle() is necessary for custom views to display
            .setStyle(new android.support.v7.app.NotificationCompat.DecoratedCustomViewStyle());

    // retrieves android.app.NotificationManager
    NotificationManager notificationManager = (android.app.NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    notificationManager.notify(0, builder.build());
}
Shivam Kumar
  • 1,892
  • 2
  • 21
  • 33
Fakhriddin Abdullaev
  • 4,169
  • 2
  • 35
  • 37
0

it seems that setOnClickPendingIntent doesn't work when used inside collections:

http://developer.android.com/reference/android/widget/RemoteViews.html#setOnClickPendingIntent(int,%20android.app.PendingIntent)

Try using setPendingIntentTemplate instead.

  • Errors excepted setPendingIntentTemplate is for honeycomb (android 3.0) while I'm working with Froyo (Android 2.2). So I can't use button in notification with Froyo? – Simone Apr 01 '11 at 09:05
  • 2
    Probably to late anyway, but that's the way it is. Button notifications don't work in Gingerbread as well, while on Honeycomb, your code from above should work as well. At least similar code does in my app. – M. Schenk Aug 04 '11 at 09:29