【问题标题】:NotificationCompat.Builder action is not workingNotificationCompat.Builder 操作不起作用
【发布时间】:2018-04-11 07:42:49
【问题描述】:

我正在尝试在foreground service notification 中添加action。但是动作点击从未触发pending intent。我尝试了以下两种方法。

第一种方法

服务

Intent stopActionIntent = new Intent(STOP_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MyService.this, 0, stopActionIntent,0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.addAction(0,"stop",pendingIntent);

清单

<receiver android:name="com.myproject.receivers.ServiceActionReceiver">
    <intent-filter >
        <action android:name="com.myproject.services.myservice.STOP_SERVICE"/>
    </intent-filter>
</receiver>

广播接收器

@Override
public void onReceive(Context context, Intent intent) {
    if(intent != null && intent.getAction().equals(MyService.STOP_SERVICE)){
        context.stopService(new Intent(context,MyService.class));
    }
}

但广播接收器从未调用过。

第二种方法

服务

if(intent != null && STOP_SERVICE.equals(intent.getAction())){
    stopSelf();
    return  super.onStartCommand(intent,flags,startId);
}
else {
    Intent stopActionIntent = new Intent(this,MyService.class);
    stopActionIntent.setAction(STOP_SERVICE);
    PendingIntent pendingIntent = PendingIntent.getActivity(MyService.this, 0, stopActionIntent,0);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
    builder.addAction(0,"stop",pendingIntent);
}

这两种方法都行不通。

build.gradle

defaultConfig {
    applicationId "com.myproject.project"
    minSdkVersion 16
    targetSdkVersion 27
    versionCode 2
    versionName "1.0.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    multiDexEnabled true
}

注意:通知和操作是可见的。

编辑

不适用于 Android 8.0 或更高版本,其他版本可以使用。

【问题讨论】:

    标签: android-notifications notification-action


    【解决方案1】:

    在 Android O 中,必须将通道与通知生成器一起使用。

    示例代码:

    // Sets an ID for the notification, so it can be updated
    int notifyID = 1; 
    String CHANNEL_`enter code here`ID = "my_channel_01";// The id of the channel. 
    CharSequence name = getString(R.string.channel_name);// The user-visible name of the channel.
    int importance = NotificationManager.IMPORTANCE_HIGH;
    NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
    // Create a notifi`enter code here`cation and set the notification channel.
    Notification notification = new Notification.Builder(MainActivity.this)
            .setContentTitle("New Message")
            .setContentText("You've received new messages.")
            .setSmallIcon(R.drawable.ic_notify_status)
            .setChannelId(CHANNEL_ID)
            .build();
    

    【讨论】:

    • 我已经创建了频道,通知和操作按钮是可见的。
    【解决方案2】:

    试试下面的通知代码:

    public void heads_up_notification() {
        Notification.Builder mBuilder = new Notification.Builder(this);
        NotificationManager nNotificationManager = (NotificationManager) getSystemService("notification");
        PendingIntent piDismiss = PendingIntent.getActivity(this, 0, new Intent(this, DirectReplyActivity.class), 0);
        Intent snoozeIntent = new Intent(this, MainActivity.class);
        snoozeIntent.setAction(NotificationCompat.CATEGORY_ALARM);
        PendingIntent piSnooze = PendingIntent.getService(this, 0, snoozeIntent, 0);
        mBuilder.setSmallIcon(C0220R.drawable.ic_launcher_background);
        mBuilder.setContentTitle("Heads up Notification");
        mBuilder.setContentText("heads up activated");
        mBuilder.setDefaults(-1);
        mBuilder.setPriority(1);
        mBuilder.addAction(C0220R.mipmap.ic_dismiss, "Dismiss", piDismiss);
        mBuilder.addAction(C0220R.mipmap.ic_stop, "Stop", piSnooze);
        nNotificationManager.notify(2, mBuilder.build());
    }
    

    【讨论】:

      【解决方案3】:

      @Shantanu, 你有多个问题。我建议您应该创建另一个新的示例项目,以使您的概念清晰,并且一旦清除,就可以在现有项目中使用它。您有多个问题,让我们一一解决-

      1. 使接收器捕获特定事件
      2. 从 Receiver 启动一个服务(前台服务)
      3. 从服务创建通知

      在开始之前,你必须有一个新的示例项目,其中包含一个 mainactivity 和一个 mainactivity 的布局。

      Manifest.xml :此文件必须具有我们在应用程序中所需的权限。我在下面发布了一个示例文件,其中我正在处理多个权限,并且在特定事件中我正在呼叫接收者。我希望我的接收器保持清醒,并在每次拨出和拨入或未接电话时被呼叫。

      <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
      <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
      <uses-permission android:name="android.permission.READ_PHONE_STATE" />
      
      <uses-permission android:name="android.permission.VIBRATE" />
      
      <uses-permission android:name="android.permission.READ_CONTACTS" />
      
      <uses-permission android:name="android.permission.SEND_SMS" />
      <uses-permission android:name="android.permission.READ_SMS" />
      <uses-permission android:name="android.permission.WRITE_SMS" />
      
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
      <uses-permission android:name="android.permission.GET_ACCOUNTS" />
      
      <application
          android:allowBackup="true"
          android:icon="@mipmap/ic_launcher"
          android:label="@string/app_name"
          android:roundIcon="@mipmap/ic_launcher_round"
          android:supportsRtl="true"
          android:theme="@style/AppTheme">
          <activity
              android:name=".MainActivity"
              android:screenOrientation="portrait">
              <intent-filter>
                  <action android:name="android.intent.action.MAIN" />
      
                  <category android:name="android.intent.category.LAUNCHER" />
              </intent-filter>
          </activity>
      
          <service
              android:name=".WatchMan"
              android:enabled="true"
              android:exported="true" />
      
          <receiver
              android:name=".Receiver"
              android:enabled="true"
              android:exported="true">
      
              <intent-filter>
                  <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
              </intent-filter>
              <intent-filter>
                  <action android:name="android.intent.action.PHONE_STATE" />
              </intent-filter>
          </receiver>
      
          <activity android:name=".developer_activity" />
          <activity android:name=".WhiteListActivity" />
          <activity android:name=".Contacts"></activity>
      </application>
      

      不要照原样复制上面的文件,只看权限的位置和方式。如果您复制整个文件,它将无法正常工作。只需将您的权限放在application 标签之上。就是这样。

      现在从->您的项目资源管理器中创建一个服务,在 android studio / eclipse.. 右键单击​​它-> 选择 new -> 选择 service-> service 它将为您打开对话框并给出适合您的服务的名称。

      它将为您创建一个服务类,并为您修改 manifest.xml。您不需要为此编辑 manifest.xml 你看看我上面的清单文件service标签。当我创建这样的服务时,它会自动为我创建。


      现在如何创建接收器以在 android 系统中触发时捕获特定事件:

      再次转到项目资源管理器 -> 右键单击​​ -> new -> other -> broadcast receiver。它还将为您打开一个对话框并为您的接收器命名。 同样,您不需要手动修改清单文件。这将自动修改您的 manifest.xml。您可以再次参考上面的清单文件。并查看为我创建的服务和接收器..


      现在如何在新呼叫开始时呼叫该接收器.. 看看我是如何放置的

      <intent-filter>
          <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
      </intent-filter>
      <intent-filter>
          <action android:name="android.intent.action.PHONE_STATE" />
      </intent-filter>
      

      在接收者标签内;这意味着我的接收器将始终被这两个事件调用。


      现在 Receiver.java :

      在你的接收器的 onReceive 函数中

      Log.d("RECEIVER ","\SUCCESS : ");
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
      {
          context.startForegroundService(new Intent(context, WatchMan.class));
      }
      else
      {
          context.startService(new Intent(context, WatchMan.class));
      }
      

      再次在这里 .. 您无需在此处手动编写函数代码。您可以通过右键单击扩展类 BroadcastReceiver -> generate - override methods 并选择 onReceive 来创建示例覆盖函数。它将为您创建 onReceive 示例方法。您必须在其中插入上面的代码如何调用您的服务(前台服务)


      现在服务:

      转到服务类。右键单击扩展类 service -> generate -> override methods 以及您需要的任何方法。 必须有空的服务方法,oncreate、onStartCommand、onDestroy、onBind。同样,您可以使用与上述相同的创建方法创建为您准备好的示例标准方法。


      现在通知:

      服务类声明:

      NotificationManager mNotifyManager;
      NotificationCompat.Builder mBuilder;
      NotificationChannel notificationChannel;
      String NOTIFICATION_CHANNEL_ID = "2";
      

      在 OnCreate 方法中:

      try
          {
      
              Intent intent = new Intent(this, MainActivity.class);
              PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
      
              mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
              mBuilder = new NotificationCompat.Builder(this, null);
              mBuilder.setContentTitle("App name")
                      .setContentText("Notification text..")
                      .setTicker("Notification text..")
                      .setSmallIcon(R.drawable.ic_service_success)
                      .setPriority(Notification.PRIORITY_HIGH)
                      .setDefaults(Notification.DEFAULT_ALL)
                      .setVisibility(Notification.VISIBILITY_PUBLIC)
                      .setContentIntent(pendingIntent);
      
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
              {
      
                  notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
      
                  // Configure the notification channel.
                  notificationChannel.setDescription("Channel description");
                  notificationChannel.enableLights(true);
                  notificationChannel.setLightColor(Color.RED);
                  notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
                  notificationChannel.enableVibration(true);
                  notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
                  mNotifyManager.createNotificationChannel(notificationChannel);
              }
      
              mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
              startForeground(2, mBuilder.build());
      
      
          }
          catch(Exception e)
          {
              Log.d("xx", "EXCEPTION IN SHOWING NOTIFICATION...\n");
              Log.e("xx", "Exception is : ", e);
          }
      

      现在由于调用启动前台,它将开始运行您的 Onstartcommand 方法


      在 onstartcommand 中,您的逻辑和代码将放在那里...是否实现 runnable thread 取决于您。它是可选的。


      您可以再次显示其他通知,例如:

      mBuilder.setContentText("Some success or failure...");
      mBuilder.setTicker("Some success or failure...");
      mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
      startForeground(2, mBuilder.build());
      

      就是这样。它应该做你想做的一切......权限、事件、接收器、服务(前台)和通知超过 4.0 到 8.0 androids 设备近 99.8% 的设备。

      【讨论】:

      • 它是经过测试和工作的代码,只需要严格按照建议进行..!!
      猜你喜欢
      • 1970-01-01
      • 2013-12-09
      • 2013-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多