最近公司有一個通知的功能,於是想起之前看過的Notification,當時看的時候看到網上有很多的講解和程式碼,就覺得這個功能真的是so easy,然而實際操作的時候才發現網上的程式碼坑真多。
首先說明一下,我是在三款手機上進行的測試,華為榮耀v10(Android8.0系統),oppo手機(Android7.0系統),魅藍note5(Android6.0系統),還有一個oppo(Android5.0系統)。
在我寫這個功能的過程中,遇到了一下幾個問題:
1:對於8.0系統,需要使用NotificationChannel,建立Notification的時候需要用這行程式碼:Notification.Builder builder =new Notification.Builder(this);
並且必須給builder 設定ChannelId,通過setChannelId()這個方法。
2:在點選通知欄上的通知跳轉到新介面後,通知不消失。
這個需要在新介面進行取消操作,在新介面的onCerate()方法中進行以下操作:
//關閉通知欄上的通知
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(5); //5表示跳轉過來的通知的ID
複製程式碼
3:華為8.0手機上修改提示音後提示音不變的問題:必須解除安裝重灌才能生效
4:oppo手機上通知不顯示問題:需要進行以下設定:
設定 ——》其他設定——》應用程式管理——》找到自己的應用——》點選後找到通知管理——》將通知管理裡面的都開啟
5:震動問題:魅藍手機上需要開啟震動按鈕才能震動,oppo和華為不用
6:v4包和v7包的區別:
Android Support v4:這個包是為了照顧1.6及更高版本而設計的,這個包是使用最廣泛的。
Android Support v7:這個包是為了考慮照顧2.1及以上版本而設計的,但不包含更低,故如果不考慮1.6,我們可以採用再加上這個包,另外注意,v7是要依賴v4這個包的,即,兩個得同時被包含。
Android Support v13:這個包的設計是為了android 3.2及更高版本的,一般我們都不常用,平板開發中能用到
7:Android3.0之前使用new Notification()建立Notification物件,3.0之後就不用這麼建立物件了
Notification notification = new Notification();
複製程式碼
8:呼吸燈問題:setLights()這個方法設定的是螢幕這一側的呼吸燈,不是手機背面的攝像頭的閃光燈,至於不知道什麼是呼吸燈的同學,可以百度一下
9:許可權問題:只需要在清單檔案中宣告震動許可權即可,不需要動態獲取許可權
下面是程式碼(注意:程式碼中已經對8.0進行了適配)
package gcg.testproject.activity.notifycation;
import android.Manifest;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.annotation.RequiresApi;
import android.support.v7.app.NotificationCompat;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.TextView;
import com.bumptech.glide.load.model.file_descriptor.FileDescriptorStringLoader;
import butterknife.Bind;
import butterknife.ButterKnife;
import gcg.testproject.R;
import gcg.testproject.base.BaseActivity;
import gcg.testproject.utils.LogUtils;
public class Notifycation2Activityextends BaseActivityimplements View.OnClickListener {
@Bind(R.id.tv_common)
TextViewmTvCommon;
@Bind(R.id.tv_remove)
TextViewmTvRemove;
@Bind(R.id.tv_bigicon)
TextViewmTvBigicon;
@Bind(R.id.tv_progress)
TextViewmTvProgress;
@Bind(R.id.tv_multi)
TextViewmTvMulti;
@Bind(R.id.tv_custom)
TextViewmTvCustom;
private int num_else;
private int num;
private Stringid ="my_channel_01";
private Stringname="我是渠道名字";
private NotificationChannelmChannel;
private NotificationManagermanager;//通知管理器,用於傳送通知Notification物件
private boolean isO;//用來判斷是不是8.0系統
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notifycation2);
ButterKnife.bind(this);
mTvCommon.setOnClickListener(this);
mTvRemove.setOnClickListener(this);
mTvBigicon.setOnClickListener(this);
mTvProgress.setOnClickListener(this);
mTvMulti.setOnClickListener(this);
mTvCustom.setOnClickListener(this);
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isO =true;
mChannel =new NotificationChannel(id,name, NotificationManager.IMPORTANCE_DEFAULT);
mChannel.setBypassDnd(true);//設定繞過免打擾模式
mChannel.canBypassDnd();//檢測是否繞過免打擾模式
mChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);//設定在鎖屏介面上顯示這條通知
//設定通知出現時的呼吸燈
mChannel.enableLights(true);
mChannel.enableVibration(true);
mChannel.setLightColor(Color.WHITE);
//解除安裝重灌,讓設定的震動生效 注意:設定震動時不用動態申請震動許可權,只在清單檔案中宣告即可
mChannel.setVibrationPattern(new long[]{100,200,300,400,500,400,300,200,400});
Uri mUri = Settings.System.DEFAULT_NOTIFICATION_URI;
mChannel.setSound(mUri, Notification.AUDIO_ATTRIBUTES_DEFAULT);
//自定義聲音 注意:要想讓設定的聲音生效,必須解除安裝重灌
// AudioAttributes.Builder audioAttributesBuilder = new AudioAttributes.Builder();
// audioAttributesBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC);
// AudioAttributes aa = audioAttributesBuilder.build();
// Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.umeng_push_notification_default);
// mChannel.setSound(uri, aa);
manager.createNotificationChannel(mChannel);
}else {
isO =false;
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.tv_common://傳送一個普通通知
LogUtils.i("送一個普通通知");
if (isO)
{
btn_8_common();
}else {
else_common();
}
break;
case R.id.tv_remove://移除通知
LogUtils.i("移除通知");
// manager.cancel(5);
manager.cancelAll();
break;
case R.id.tv_bigicon://設定大圖通知
LogUtils.i("設定大圖通知");
if (isO)
{
btn_8_bigicon();
}else {
else_big();
}
break;
case R.id.tv_progress://傳送帶進度條的通知
LogUtils.i("傳送帶進度條的通知");
if (isO)
{
btn_8_progress();
}else {
else_progress();
}
break;
case R.id.tv_multi://封裝多行文字樣式
LogUtils.i("封裝多行文字樣式");
if (isO)
{
btn_8_multi();
}else {
else_multi();
}
break;
case R.id.tv_custom://完全自定義的通知
LogUtils.i("完全自定義的通知");
if (isO)
{
btn_8_custom();
}else {
else_custom();
}
break;
}
}
複製程式碼
// ========================== 以下是8.0以下的通知========================================
private void else_common(){
LogUtils.i("else_common");
// 注意:Android3.0之前使用new Notification()建立Notification物件
// Notification notification = new Notification();
// Android Support v4:這個包是為了照顧1.6及更高版本而設計的,這個包是使用最廣泛的。
// Android Support v7:這個包是為了考慮照顧2.1及以上版本而設計的,但不包含更低,故如果不考慮1.6,
// 我們可以採用再加上這個包,另外注意,v7是要依賴v4這個包的,即,兩個得同時被包含。
// Android Support v13:這個包的設計是為了android 3.2及更高版本的,一般我們都不常用,平板開發中能用到
//Android3.0之後用
NotificationCompat.Builder builder =new NotificationCompat.Builder(this);
builder.setContentTitle("設定標題" + System.currentTimeMillis());
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));//設定大圖示
builder.setContentText("內容文字部分");
builder.setContentInfo("info資訊");//設定info資訊,即設定顯示在時間右下角的文字
builder.setSmallIcon(R.mipmap.ic_launcher);//必須要設定的小圖示
builder.setWhen(System.currentTimeMillis());//設定通知時間
builder.setTicker("設定滾動提示的文字設定滾動提示的文字設定滾動提示的文字設定滾動提示的文字設定滾動提示的文字");
builder.setOngoing(false);//設定左右滑動時是否會消失
builder.setAutoCancel(true);
builder.setDefaults(Notification.DEFAULT_SOUND);//設定預設鈴聲
//設定自定義鈴聲
// builder.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.umeng_push_notification_default)); //呼叫系統多媒體褲內的鈴聲
//設定震動;部分手機必須開啟震動功能才能震動
long[] vibrate =new long[]{0,500,500,500,500};
builder.setVibrate(vibrate);
// builder.setDefaults(Notification.DEFAULT_VIBRATE); //設定預設震動
// builder.setDefaults(Notification.DEFAULT_ALL);
//設定呼吸燈(不是閃光燈);注意:顏色跟裝置有關,不是所有的顏色都可以,要看具體裝置。
//注意:閃爍時長和熄滅時長也會跟裝置有關,不完全跟設定的一樣
builder.setLights(0xff0000ff,300,0);
num_else++;
manager.notify(num_else, builder.build());//傳送通知
}
//部分手機的大圖通知在6.0系統上親測不能顯示大圖,如果要顯示大圖,建議設定自定義view
private void else_big()
{
LogUtils.i("else_big");
NotificationCompat.Builder builder =new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.t2);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.t1));//設定大圖示
builder.setContentTitle("大圖片通知");
builder.setContentText("內容文字部分");
builder.setTicker("大圖通知來了");
builder.setContentInfo("info資訊");//設定info資訊,即設定顯示在時間右下角的文字
builder.setDefaults(Notification.DEFAULT_SOUND);//設定預設鈴聲
manager.notify(7, builder.build());
}
private void else_progress()
{
LogUtils.i("else_progress");
final NotificationCompat.Builder builder =new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle("帶進度條的通知");
builder.setProgress(100,0,false);
builder.setDefaults(Notification.DEFAULT_SOUND);//設定預設鈴聲
manager.notify(3, builder.build());
new Thread(new Runnable() {
@Override
public void run() {
for (int i =0; i <=100; i++) {
builder.setProgress(100, i,false);
manager.notify(3,builder.build());
SystemClock.sleep(200);
if (i ==100)//當進度條走完後,清除這個通知
{
manager.cancel(3);
}
}
}
}).start();
}
private void else_multi()
{
NotificationCompat.InboxStyle inboxStyle =new NotificationCompat.InboxStyle();
for (int i =0; i <10; i++) {
inboxStyle.addLine("這是第" + i +"行" +"文字");
}
NotificationCompat.Builder builder =new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle("多行文字");
inboxStyle.setBigContentTitle("多行文字標題");
builder.setStyle(inboxStyle);
builder.setDefaults(Notification.DEFAULT_SOUND);//設定預設鈴聲
manager.notify(4, builder.build());
}
private void else_custom()
{
RemoteViews views =new RemoteViews(getPackageName(),R.layout.remote);
NotificationCompat.Builder builder =new NotificationCompat.Builder(this);
builder.setContent(views);
builder.setSmallIcon(R.mipmap.ic_launcher);//設定了setContent屬性後,setSmallIcon就不生效了
builder.setContentTitle("自定義佈局");//設定了setContent屬性後,setContentTitle就不生效了
builder.setContentText("點選聯絡人行可跳轉");//設定了setContent屬性後,setContentText就不生效了
builder.setAutoCancel(true);//設定點選通知自動消失,8.0時並沒有用
builder.setOngoing(false);//true:左右滑動時通知不會消失 false:左右滑動時可以滑動消失
builder.setDefaults(Notification.DEFAULT_SOUND);//設定預設鈴聲
Notification build = builder.build();
build.flags = Notification.FLAG_AUTO_CANCEL;
PendingIntent pendingIntent = PendingIntent.getActivity(this,1,
new Intent(Notifycation2Activity.this, NotifycationActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT);
//當前設定代表點選id為R.id.but_re的按鈕時,要執行跳轉到TwoActivity頁面的操作
views.setOnClickPendingIntent(R.id.item, pendingIntent);
manager.notify(5, build);
}
複製程式碼
// ========================== 以下是8.0上的通知==========================================
@RequiresApi(api = Build.VERSION_CODES.O)
private void btn_8_common() {
Notification.Builder builder =new Notification.Builder(this);
builder.setChannelId(id);//8.0必須設定通道
builder.setContentTitle("設定標題" + System.currentTimeMillis());
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));//設定大圖示
builder.setContentText("內容文字部分");
builder.setContentInfo("info資訊");//設定info資訊,即設定顯示在時間右下角的文字
builder.setSmallIcon(R.mipmap.ic_launcher);//必須要設定的小圖示
builder.setWhen(System.currentTimeMillis());//設定通知時間
builder.setTicker("設定滾動提示的文字");
builder.setOngoing(false);
num++;
manager.notify(num, builder.build());//傳送通知
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void btn_8_bigicon() {
Notification.Builder builder =new Notification.Builder(this);
builder.setChannelId(id);//8.0必須設定通道
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.t1));//設定大圖示
builder.setContentTitle("大圖片通知");
builder.setContentText("內容文字部分");
builder.setTicker("大圖通知來了");
manager.notify(7, builder.build());
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void btn_8_progress() {
final Notification.Builder builder =new Notification.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle("帶進度條的通知");
builder.setProgress(100,0,false);
builder.setChannelId(id);//8.0必須設定通道
manager.notify(3, builder.build());
new Thread(new Runnable() {
@Override
public void run() {
for (int i =0; i <=100; i++) {
builder.setProgress(100, i,false);
manager.notify(3,builder.build());
SystemClock.sleep(500);
}
}
}).start();
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void btn_8_multi() {
Notification.InboxStyle inboxStyle =new Notification.InboxStyle();
for (int i =0; i <10; i++) {
inboxStyle.addLine("這是第" + i +"行" +"文字");
}
Notification.Builder builder =new Notification.Builder(this);
builder.setChannelId(id);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle("多行文字");
inboxStyle.setBigContentTitle("多行文字標題");
builder.setStyle(inboxStyle);
manager.notify(4, builder.build());
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void btn_8_custom() {
RemoteViews views =new RemoteViews(getPackageName(),R.layout.remote);
Notification.Builder builder =new Notification.Builder(this);
builder.setContent(views);
builder.setSmallIcon(R.mipmap.ic_launcher);//設定了setContent屬性後,setSmallIcon就不生效了
builder.setContentTitle("自定義佈局");//設定了setContent屬性後,setContentTitle就不生效了
builder.setContentText("點選聯絡人行可跳轉");//設定了setContent屬性後,setContentText就不生效了
builder.setChannelId(id);
builder.setAutoCancel(true);//設定點選通知自動消失,8.0時並沒有用
builder.setOngoing(false);//true:左右滑動時通知不會消失 false:左右滑動時可以滑動消失
Notification build = builder.build();
build.flags = Notification.FLAG_AUTO_CANCEL;
PendingIntent pendingIntent = PendingIntent.getActivity(this,1,
new Intent(Notifycation2Activity.this, NotifycationActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT);
//當前設定代表點選id為R.id.but_re的按鈕時,要執行跳轉到TwoActivity頁面的操作
views.setOnClickPendingIntent(R.id.item, pendingIntent);
manager.notify(5, build);
}
}
複製程式碼
=================================================
package gcg.testproject.activity.notifycation;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.NotificationCompat;
import android.view.View;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.ButterKnife;
import gcg.testproject.R;
import gcg.testproject.base.BaseActivity;
import gcg.testproject.utils.LogUtils;
//參考連結:https://www.jianshu.com/p/f2cf23d6d836
public class NotifycationActivityextends BaseActivity{
@Bind(R.id.tv_send)
TextViewmTvSend;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notifycation);
ButterKnife.bind(this);
//關閉通知欄上的通知
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(5);
}
}
複製程式碼
======================= 佈局檔案 ====================
<TextView
android:id="@+id/tv_common"
android:gravity="center"
android:textColor="#fff"
android:textSize="20sp"
android:text="普通通知"
android:background="#4caf65"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<TextView
android:layout_marginTop="@dimen/dp10"
android:id="@+id/tv_remove"
android:gravity="center"
android:textColor="#fff"
android:textSize="20sp"
android:text="移除通知"
android:background="#4caf65"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<TextView
android:layout_marginTop="@dimen/dp10"
android:id="@+id/tv_bigicon"
android:gravity="center"
android:textColor="#fff"
android:textSize="20sp"
android:text="設定大圖通知"
android:background="#4caf65"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<TextView
android:layout_marginTop="@dimen/dp10"
android:id="@+id/tv_progress"
android:gravity="center"
android:textColor="#fff"
android:textSize="20sp"
android:text="進度條通知"
android:background="#4caf65"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<TextView
android:layout_marginTop="@dimen/dp10"
android:id="@+id/tv_multi"
android:gravity="center"
android:textColor="#fff"
android:textSize="20sp"
android:text="多行文字樣式通知"
android:background="#4caf65"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<TextView
android:layout_marginTop="@dimen/dp10"
android:id="@+id/tv_custom"
android:gravity="center"
android:textColor="#fff"
android:textSize="20sp"
android:text="完全自定義通知"
android:background="#4caf65"
android:layout_width="match_parent"
android:layout_height="50dp"/>
複製程式碼