带有按钮的 Android 通知

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10516722/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:01:46  来源:igfitidea点击:

Android notification with buttons on it

androidandroid-notifications

提问by doronsl

I'm trying to make a notification with 2 buttons on it:

我正在尝试制作带有 2 个按钮的通知:

  • one takes me back to the activity
  • the other closes it
  • 一个带我回到活动
  • 另一个关闭它

Has anyone got an idea on how to catch the button click event (remember that the Activity is paused)?

有没有人知道如何捕捉按钮点击事件(记住 Activity 已暂停)?

回答by LiTTle

I am glad to post it! After working all night I found something. So, here we go!

我很高兴发布它!经过一夜的工作,我发现了一些东西。所以,我们开始!

1. Create an xml layout file for your notification.

1. 为您的通知创建一个 xml 布局文件。

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

2. 使用 Notification.Builder 创建通知。添加您想要的所有内容(图标、声音等)后,请执行以下操作:

        //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:

3. 创建一个方法setListeners。在这个方法中,你必须这样写:

    //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");</p>

    //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.

4. 对于我的要求,我使用了一个响应意图的 HelperActivity。但对你来说,我认为没有必要。

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

如果你想要完整的源代码,你可以浏览它或从我的 git repo 下载它。代码仅供个人使用,因此不要期望阅读带有大量注释的华丽代码。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

如何清除Android中的通知

Just remember to use the id you parsed at the notify method when you called the notification for fist time

请记住使用您在第一次调用通知时在通知方法中解析的 id

回答by Shine

As for ICS, the question is simple to reply because the required behaviour reflects default notification: you can closea notification swiping it to the right, and you can define which activityto send the user to when he presses it simply using PendingIntent:

至于 ICS,这个问题很容易回答,因为所需的行为反映了默认通知:您可以关闭通知向右滑动,您可以定义当用户按下它时将其发送到哪个活动,只需使用PendingIntent

// The PendingIntent to launch our activity if the user selects this
// notification.  Note the use of FLAG_CANCEL_CURRENT so that, if there
// is already an active matching pending intent, cancel it and replace
// it with the new array of Intents.
PendingIntent contentIntent = PendingIntent.getActivities(this, 0,
        makeMessageIntentStack(this, from, message), PendingIntent.FLAG_CANCEL_CURRENT);

code taken from http://developer.android.com/guide/topics/ui/notifiers/notifications.html

代码取自http://developer.android.com/guide/topics/ui/notifiers/notifications.html

回答by qubit

If you want to assign specific intent to a button:

如果您想为按钮分配特定的意图:

views.setOnClickPendingIntent(R.id.your_button_id, pendingIntent);

I suppose that you need only one intent to be sent when the button is clicked, so you have to AVOID setting the main notification intent

我想您只需要在单击按钮时发送一个意图,因此您必须避免设置主通知意图

notification.contentIntent = yourPendingIntent;

Otherwise (if you set "notification.contentIntent = pendingIntent;" as usual) both intents will be called which might not be what you want/user expects.

否则(如果您像往常一样设置“notification.contentIntent = pendingIntent;”)两个意图都将被调用,这可能不是您想要/用户期望的。

If you still want pressing other parts of the notification invoke that general intent (or any other) you can use the same method of intent-per-view assignment as above. Don't forget to set

如果您仍然希望按下通知的其他部分来调用该一般意图(或任何其他),您可以使用与上述相同的每视图意图分配方法。不要忘记设置

android:clickable="true"

to any view you'd like to track onClick() for.

到您想要跟踪 onClick() 的任何视图。

You can track these intents by their extras in the activity they are calling. Ifyou are calling you main/launcher activitythan you'll track them here (as it comes from javadoc for this method):

您可以通过他们正在调用的活动中的附加内容来跟踪这些意图。如果调用主/启动器活动,那么您将在此处跟踪它们(因为它来自此方法的 javadoc):

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    Bundle data = intent.getExtras();

    if (data != null && data.containsKey(YOUR_INTENT_KEY_SOURCE_CONSTANT)) {
       // process your notification intent
    }

    // go on with smth else
}

回答by Tushar Purohit

You can simply add action Buttons in your Notificationby setting action to your Notification.Builderand defining PendingIntentfor each action

您可以Notification通过将操作设置为您的操作Notification.BuilderPendingIntent为每个操作定义来简单地在您的操作按钮中添加操作按钮

below is the sample code:

下面是示例代码:

    NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.notification_icon)
                .setContentTitle("My notification")
                .setContentText("Hello World!")
       .addAction(R.drawable.action_posetive,"posetive",PendingIntent.getActivity(0,intent,0))
.addAction(R.drawable.action_clear,"clear",PendingIntent.getActivity(0,intent,0));
        NotificationManager mNotificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(0, mBuilder.build());

回答by Amin

There is a full example for you here

这里有一个完整的例子

    //Add this code to onCreate or some onclick Buttton
    NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
    long when = System.currentTimeMillis();
    builder.setSmallIcon(R.drawable.ic_notification);
    Intent notificationIntent = new Intent(getApplicationContext(), notificationActivity.class).putExtra("notification", "1");
    PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 1, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    builder.setContentIntent(contentIntent);
    Notification notification = builder.getNotification();
    notification.when = when;

    RemoteViews remoteViews = new RemoteViews(getApplicationContext().getPackageName(), R.layout.notification_view);
    remoteViews.setTextViewText(R.id.tvName, "New Name");
    listener(remoteViews,getApplicationContext());


    notification.contentView = remoteViews;
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    manager.notify(1, notification);

and then you can define listener method :

然后你可以定义监听器方法:

    public void listener(RemoteViews remoteViews, Context context) {
    // you have to make intetns for each action (your Buttons)
    Intent intent = new Intent("Accept");
    Intent intent2 = new Intent("Reject");

    PendingIntent pendingIntent = PendingIntent.getBroadcast(context,1,intent,0);
    PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context,1,intent2,0);

    // add actions here !
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("Accept");
    intentFilter.addAction("Reject");


    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction().equals("Accept")){
                Toast.makeText(context, "Accepted !!", Toast.LENGTH_SHORT).show();
            } else if(intent.getAction().equals("Reject")) {
                Toast.makeText(context, "Rejected !!", Toast.LENGTH_SHORT).show();
            }
        }
    };

    context.registerReceiver(receiver,intentFilter);
    remoteViews.setOnClickPendingIntent(R.id.ivRequest,pendingIntent);
    remoteViews.setOnClickPendingIntent(R.id.ivReject,pendingIntent2);

}

and here is the notification_view layout to costumize your notification .

这是用于装饰您的通知的 notification_view 布局。

    <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp">

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:text="Request from "
    />

<TextView
    android:id="@+id/tvName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_marginStart="15dp"
    android:layout_toRightOf="@id/textView"
    android:text="Amin"
    />

<ImageView
    android:id="@+id/ivRequest"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:layout_alignParentEnd="true"
    android:layout_centerVertical="true"
    android:src="@drawable/notification"
    />

<ImageView
    android:id="@+id/ivReject"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:layout_marginEnd="10dp"
    android:layout_toLeftOf="@id/ivRequest"
    android:layout_centerVertical="true"
    android:src="@drawable/trash"
    />

  </RelativeLayout>

回答by Muhaiminur Rahman

For me, this is working greatly.. I will write down the whole example.. This is for Notification create

对我来说,这很有用..我会写下整个例子.. 这是用于通知创建

public void createNotification2(String aMessage) {
    final int NOTIFY_ID = 11;
    String name = getString(R.string.app_name);
    String id = getString(R.string.app_name); // The user-visible name of the channel.
    String description = getString(R.string.app_name); // The user-visible description of the channel.
    NotificationCompat.Builder builder;
    if (notifManager == null) {
        notifManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel mChannel = notifManager.getNotificationChannel(id);
        if (mChannel == null) {
            mChannel = new NotificationChannel(id, name, importance);
            mChannel.setDescription(description);
            mChannel.enableVibration(true);
            mChannel.setLightColor(getColor(R.color.colorPrimaryDark));
            mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
            notifManager.createNotificationChannel(mChannel);
        }
    } else {

    }
    Intent Off_broadcastIntent = new Intent(this, Database_Update.class);
    Off_broadcastIntent.setAction("on");
    Off_broadcastIntent.putExtra("toastMessage", "1");
    PendingIntent Off_actionIntent = PendingIntent.getService(this, 0, Off_broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    Intent on_broadcastIntent = new Intent(this, Database_Update.class);
    on_broadcastIntent.setAction("off");
    on_broadcastIntent.putExtra("toastMessage", "0");
    PendingIntent on_actionIntent = PendingIntent.getService(this, 0, on_broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    Intent cancel_broadcastIntent = new Intent(this, Database_Update.class);
    cancel_broadcastIntent.setAction("cancel");
    cancel_broadcastIntent.putExtra("toastMessage", "close");
    PendingIntent cancel_actionIntent = PendingIntent.getService(this, 0, cancel_broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    Intent content_intent = new Intent(this, Status_Page.class);
    content_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, content_intent, PendingIntent.FLAG_UPDATE_CURRENT);


    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, id)
            .setSmallIcon(android.R.drawable.ic_popup_reminder)
            .setContentTitle(name)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setContentIntent(pendingIntent)
            .setAutoCancel(false)
            .setVibrate(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400})
            .addAction(R.drawable.block, "ON", Off_actionIntent)
            .addAction(R.drawable.notification, "OFF", on_actionIntent)
            .addAction(R.drawable.clear, "CLOSE", cancel_actionIntent);
    Notification notification = mBuilder.build();
    notification.flags = Notification.FLAG_NO_CLEAR|Notification.FLAG_ONGOING_EVENT;
    notifManager.notify(11, notification);
}

In Android Menifest

在 Android 菜单中

<service android:name=".Database_Update"></service>

This is service class

这是服务类

public class Database_Update extends Service {
String result="";

Realm realm;
BlockList blockList;
@Override
public void onCreate() {
    try {
        RealmConfiguration config = new RealmConfiguration.Builder()
                .name("notification.realm")
                .schemaVersion(1)
                .deleteRealmIfMigrationNeeded()
                .build();
        realm = Realm.getInstance(config);

    } catch (Exception e) {

        Log.d("Error Line Number", Log.getStackTraceString(e));
    }
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    //Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
    Log.d("SERVICE","SERVICE CHECKING");
    result=intent.getStringExtra("toastMessage");
    Log.d("SERVICE",result);
    if (realm!=null){
        Log.d("SERVICE","realm working");
    }else {
        Log.d("SERVICE","Realm not working");
    }
    blockList=realm.where(BlockList.class).equalTo("package_name", "BLOCK_ALL").findFirst();
    try {
        Log.d("SERVICE",blockList.getStatus());
    } catch (Exception e) {
        Log.d("Error Line Number", Log.getStackTraceString(e));
    }
    realm.beginTransaction();
    if (result.equals("1")){
        if (blockList==null){
            BlockList blockList_new=realm.createObject(BlockList.class);
            blockList_new.setPackage_name("BLOCK_ALL");
            blockList_new.setStatus("yes");
        }else {
            blockList.setStatus("yes");
        }
        Log.d("SERVICE","BLOCKING NOTIFICATION");
        Toast.makeText(this, "BLOCKING", Toast.LENGTH_SHORT).show();
    }else if (result.equals("0")){
        if (blockList==null){
            BlockList blockList_new=realm.createObject(BlockList.class);
            blockList_new.setPackage_name("BLOCK_ALL");
            blockList_new.setStatus("no");
        }else {
            blockList.setStatus("no");
        }
        Log.d("SERVICE","ALLOW NOTIFICATION");
        Toast.makeText(this, "ALLOW NOTIFICATION", Toast.LENGTH_SHORT).show();
    }else if (result.equals("close")){
        NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
        manager.cancel(11);
        Log.d("SERVICE","REMOVING");
        Toast.makeText(this, "CLOSED", Toast.LENGTH_SHORT).show();
    }
    realm.commitTransaction();
    return START_STICKY;
}

@Override
public IBinder onBind(Intent intent) {
    // We don't provide binding, so return null
    return null;
}

@Override
public void onDestroy() {
    if (realm!=null){
        realm.close();
    }
    Toast.makeText(this, "REMOVING", Toast.LENGTH_SHORT).show();
}
}