Android Notification 和曾經踩過的坑

zlove發表於2018-01-29

Notification

說明

本專案展示了常用的Android系統自帶的Notification,以及總結了一些自己在使用notification的過程中遇到的坑。

首先來看一下常見的notification type:

public static final int TYPE_NORMAL = 1;  // 普通通知
public static final int TYPE_PROGRESS = 2;  // 下載進度的通知
public static final int TYPE_BIG_TEXT = 3;  // BigTextStyle通知
public static final int TYPE_INBOX = 4;  // InboxStyle
public static final int TYPE_BIG_PICTURE = 5;  // BigPictureStyle
public static final int TYPE_HANGUP = 6;  // hangup橫幅通知
複製程式碼

一、普通通知

Android Notification 和曾經踩過的坑

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//為了版本相容  選擇V7包下的NotificationCompat進行構造
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
//Ticker是狀態列顯示的提示
builder.setTicker("簡單Notification");
//第一行內容  通常作為通知欄標題
builder.setContentTitle("標題");
//第二行內容 通常是通知正文
builder.setContentText("通知內容");
//第三行內容 通常是內容摘要什麼的 在低版本機器上不一定顯示
builder.setSubText("這裡顯示的是通知第三行內容!");
//ContentInfo 在通知的右側 時間的下面 用來展示一些其他資訊
//builder.setContentInfo("2");
//number設計用來顯示同種通知的數量和ContentInfo的位置一樣,如果設定了ContentInfo則number會被隱藏
builder.setNumber(2);
//可以點選通知欄的刪除按鈕刪除
builder.setAutoCancel(true);
//系統狀態列顯示的小圖示
builder.setSmallIcon(R.mipmap.ic_launcher);
//下拉顯示的大圖示
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.contact));
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 1, intent, 0);
//點選跳轉的intent
builder.setContentIntent(pIntent);
//通知預設的聲音 震動 呼吸燈
builder.setDefaults(NotificationCompat.DEFAULT_ALL);
Notification notification = builder.build();
manager.notify(TYPE_NORMAL, notification);
複製程式碼

二、下載進度的通知

Android Notification 和曾經踩過的坑

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.contact));
//禁止使用者點選刪除按鈕刪除
builder.setAutoCancel(false);
//禁止滑動刪除
builder.setOngoing(true);
//取消右上角的時間顯示
builder.setShowWhen(false);
builder.setContentTitle("下載中...7%");
builder.setProgress(100, 7, false);
//builder.setContentInfo(progress+"%");
builder.setOngoing(true);
builder.setShowWhen(false);
Intent intent = new Intent(this, NotificationActivity.class);
intent.putExtra("command", 1);
PendingIntent pIntent = PendingIntent.getActivity(this, 1, intent, 0);
//點選跳轉的intent
builder.setContentIntent(pIntent);
builder.setDefaults(NotificationCompat.DEFAULT_ALL);
Notification notification = builder.build();
manager.notify(TYPE_PROGRESS, notification);
複製程式碼

三、BigTextStyle通知

Android Notification 和曾經踩過的坑

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("BigTextStyle");
builder.setContentText("BigTextStyle演示示例");
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.contact));
android.support.v4.app.NotificationCompat.BigTextStyle style = new android.support.v4.app.NotificationCompat.BigTextStyle();
style.bigText("這裡是點選通知後要顯示的正文,可以換行可以顯示很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長");
style.setBigContentTitle("點選後的標題");
//SummaryText沒什麼用 可以不設定
style.setSummaryText("末尾只一行的文字內容");
builder.setStyle(style);
builder.setAutoCancel(true);
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 1, intent, 0);
builder.setContentIntent(pIntent);
builder.setDefaults(NotificationCompat.DEFAULT_ALL);
Notification notification = builder.build();
manager.notify(TYPE_BIG_TEXT, notification);
複製程式碼

四、InboxStyle通知

Android Notification 和曾經踩過的坑

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("InboxStyle");
builder.setContentText("InboxStyle演示示例");
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.contact));
android.support.v4.app.NotificationCompat.InboxStyle style = new android.support.v4.app.NotificationCompat.InboxStyle();
style.setBigContentTitle("BigContentTitle")
        .addLine("第一行,第一行,第一行,第一行,第一行,第一行,第一行")
        .addLine("第二行")
        .addLine("第三行")
        .addLine("第四行")
        .addLine("第五行")
        .setSummaryText("SummaryText");
builder.setStyle(style);
builder.setAutoCancel(true);
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 1, intent, 0);
builder.setContentIntent(pIntent);
builder.setDefaults(NotificationCompat.DEFAULT_ALL);
Notification notification = builder.build();
manager.notify(TYPE_INBOX, notification);
複製程式碼

五、BigPictureStyle通知

Android Notification 和曾經踩過的坑

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("BigPictureStyle");
builder.setContentText("BigPicture演示示例");
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setDefaults(NotificationCompat.DEFAULT_ALL);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.contact));
android.support.v4.app.NotificationCompat.BigPictureStyle style = new android.support.v4.app.NotificationCompat.BigPictureStyle();
style.setBigContentTitle("BigContentTitle");
style.setSummaryText("SummaryText");
style.bigPicture(BitmapFactory.decodeResource(getResources(), R.mipmap.img_power_popup_notice));
builder.setStyle(style);
builder.setAutoCancel(true);
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 1, intent, 0);
//設定點選大圖後跳轉
builder.setContentIntent(pIntent);
Notification notification = builder.build();
manager.notify(TYPE_BIG_PICTURE, notification);
複製程式碼

六、hangup橫幅通知

Android Notification 和曾經踩過的坑

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("橫幅通知");
builder.setContentText("請在設定通知管理中開啟訊息橫幅提醒許可權");
builder.setDefaults(NotificationCompat.DEFAULT_ALL);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.contact));
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 1, intent, 0);
builder.setContentIntent(pIntent);
//這句是重點
builder.setFullScreenIntent(pIntent, true);
builder.setAutoCancel(true);
Notification notification = builder.build();
manager.notify(TYPE_HANGUP, notification);
複製程式碼

常見的幾種notification樣式已經介紹完畢,下面說一說我踩過的坑(前方高能,請注意)

坑一、notification全展示

以上的例子中,連續傳送多條notification,你會發現所有的notification都只展示了最新的一條,之前傳送的都會被最後一條頂替。假如你想要展示所有的
notification,應該怎麼處理呢?只要將 
複製程式碼
manager.notify(TYPE_HANGUP, notification);
複製程式碼
這個方法中的第一個引數id,改成不同值,就可以讓不同的notification全展示了。
複製程式碼

坑二、hangup橫幅通知不消失

當你傳送橫幅通知的時候你會發現橫幅沒有自動收起,我採用了下面的方法達到了自動收起的效果
複製程式碼
new Handler().postDelayed(new Runnable() {
  @Override
  public void run() {
      manager.cancel(TYPE_HANGUP);
      NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);
      builder.setContentTitle("橫幅通知");
      builder.setContentText("請在設定通知管理中開啟訊息橫幅提醒許可權");
      builder.setSmallIcon(R.mipmap.ic_launcher);
      builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.contact));
      Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
      PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this, 1, intent, 0);
      builder.setContentIntent(pIntent);
      builder.setAutoCancel(true);
      Notification notification = builder.build();
      manager.notify(TYPE_HANGUP, notification);
  }
}, 2000);
複製程式碼
延遲兩秒去cancel這個notification,但是又會發現通知欄裡又沒有了這個notification,此時再悄無聲息的再傳送一次,完美解決。
複製程式碼

坑三、hangup橫幅通知自動喚起app

這個坑很蛋疼,當你呼叫了這個方法 builder.setFullScreenIntent(pIntent, true); 並且你的app沒有退出的時候,你會發現在某些手機上,你的app會自動
跳轉到你notification裡設定的那個頁面,即使在息屏的狀態下也會。修復的辦法只要將上面的程式碼改為 builder.setFullScreenIntent(null, true); 即可。
複製程式碼

坑四、點開notification,發現intent所攜帶的引數丟失

當你傳送多條notification,並且每條notification所攜帶的引數(即想要開啟的指定的頁面)不同,你會發現intent裡攜帶的引數會被最新的一條notification
裡帶的引數替換,導致總是開啟同一個頁面。修正的方法是將 PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this, 1, intent, 0);
這句程式碼裡的第二個引數 requestCode 設定成不同的值,即可將不同notification intent所攜帶的引數存住。
複製程式碼

end

That's all, I hope this will help you!

附:原始碼地址

感謝大神的評論,鑑於大神的評論,對文章內容做出以下修正

notification全展示

展示不同的notification,就需要不同的id,使用同一個id,新的notification中的內容會去更新老notification的內容,而不是替換。
複製程式碼

橫幅通知不消失

當你設定了 builder.setFullScreenIntent(pIntent, true); 這句程式碼時,notification是預設懸浮在手機頂部待處理的。我這裡做的讓它自動收回的效果(假象)只是產品的特殊需求。
複製程式碼

點開notification,發現intent所攜帶的引數丟失

關於這個問題的正解,建議看一下這篇文章,你會得到答案。

最後,感謝大神的評論,感謝連結文章的原作者。

相關文章