一、發送通知的機制
在日常的app應用中經常需要使用通知,因為服務、廣播后台活動如果有事件需要通知用戶,則需要通過通知欄顯示,而在Xamarin.Android下的通知需要獲取NotificationManager服務,而該服務需要通過GetSystemService獲取,同時還要傳遞一個標識符。獲取了通知管理器后我們就可以實例化Notification,然后再由NotificationManager發送出去。這就是整個過程了。下面我們將一一詳解通知。
二、前期准備
為了下面的學習和演示我們需要做好一些前期的准備
1.打開Main.axml刪除上面的控件
2.打開MainActivity.cs文件並寫入以下內容
1 [Activity(Label = "NotificationStudy", MainLauncher = true, Icon = "@drawable/icon")] 2 public class MainActivity : Activity 3 { 4 private NotificationManager nMgr; 5 6 protected override void OnCreate(Bundle bundle) 7 { 8 base.OnCreate(bundle); 9 SetContentView(Resource.Layout.Main); 10 11 //獲取通知管理類 12 nMgr = (NotificationManager)GetSystemService(NotificationService);
3.右擊項目-》屬性然后按照如下所示加上能夠控制振動的權限
三、發送普通通知
首先我們打開Main.axml文件,然后設置如下一個按鈕:
並設置id為@+id/normalButton
在MainActivity.cs先獲取按鈕對象:
1 Button normalButton = FindViewById<Button>(Resource.Id.normalButton);
監聽normalButton按鈕的點擊事件:

1 normalButton.Click += (e, s) => 2 { 3 //設置通知的圖標以及顯示的簡介Title 4 Notification notify = new Notification(Resource.Drawable.Icon, "普通通知"); 5 //初始化點擊通知后打開的活動 6 PendingIntent pintent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(MainActivity)), PendingIntentFlags.UpdateCurrent); 7 //設置通知的主體 8 notify.SetLatestEventInfo(this, "普通通知標題", "普通通知內容", pintent); 9 //發送通知 10 nMgr.Notify(0, notify); 11 };
其中我們先實例化了一個Notification對象,並設置其圖標以及Ticker文字:
1 Notification notify = new Notification(Resource.Drawable.Icon, "普通通知");
當然眾所周知當我們點擊通知之后都會打開對應的活動,所以我們需要初始化一個延遲意圖,以便通知可以打開:
1 PendingIntent pintent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(MainActivity)), PendingIntentFlags.UpdateCurrent);
這個PendingIntent僅僅只是Intent的一個封裝。最后是設置通知的標題和內容以及對應的活動,最后就是發送這個通知,再發送通知的Notify方法中第一個參數為該通知的ID,有了這個ID后面就可以取消這個通知。
下面我們測試,發送該通知:
四、取消通知
通過上面的代碼我們已經發送了一個通知,那么我們還需要關閉這個通知,這里我們再在Main.axml中添加一個按鈕:
並設置其id為@+id/cancelNotifyButton
打開MainActivity.cs文件,並綁定監聽事件:

1 Button cancelNotifyButton = FindViewById<Button>(Resource.Id.cancelNotifyButton); 2 cancelNotifyButton.Click += (e, s) => 3 { 4 //根據id取消通知 5 nMgr.Cancel(0); 6 };
然后發送一個通知后,點擊取消普通通知,會發現通知欄中不存在我們發送的通知了。
五、發送帶有聲音、震動和LED燈的通知
首先我們還是要在Main.axml中添加一個按鈕:
並設置它的id為@+id/lsvButton
打開MainActivity.cs並寫入如下代碼:

1 Button lsvButton = FindViewById<Button>(Resource.Id.lsvButton); 2 lsvButton.Click += (e, s) => 3 { 4 Notification notify = new Notification(Resource.Drawable.Icon, "帶有聲音、LED光和震動的通知"); 5 //設置該通知具有聲音、LED光和震動 6 notify.Defaults = NotificationDefaults.All; 7 8 //獲取系統默認的通知聲音 9 Android.Net.Uri ringUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification); 10 //設置通知的聲音 11 notify.Sound = ringUri; 12 13 //設置一秒的震動 14 notify.Vibrate = new long[] { 1000 }; 15 16 //設置LED的顏色為綠色 17 notify.LedARGB = Color.Green; 18 //設置LED顯示時間為1s 19 notify.LedOnMS = 1000; 20 //設置LED熄滅時間為1s 21 notify.LedOffMS = 1000; 22 //設置標志位,否則無法顯示LED 23 notify.Flags = NotificationFlags.ShowLights | notify.Flags; 24 25 PendingIntent pintent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(MainActivity)), 0); 26 27 notify.SetLatestEventInfo(this, "標題", "內容", pintent); 28 29 nMgr.Notify(1, notify); 30 };
下面我們來分析一下代碼,既然這個通知帶有聲音等,那么我們需要設置Defaults:
1 notify.Defaults = NotificationDefaults.All;
因為筆者使用了所有,所以直接是All,當然還可以是Sound、Vibrate和Lights的組合
為了能夠貼近系統,所以我們並沒有設置個性的聲音,而是獲取了系統本身的通知聲音,下面的代碼就是獲取代碼:
1 Android.Net.Uri ringUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
最后是將這個聲音賦給通知:
1 notify.Sound = ringUri;
然后就是震動:
1 notify.Vibrate = new long[] { 1000 };
筆者設置的是震動一秒,當然這是一個數組。而規則就是 震動的毫秒數,靜止的毫秒數,震動的毫秒數…這種規則
最后就是比較麻煩的LED,首先是指定LED燈的顏色(如果不存在該顏色,系統會選擇臨近的顏色):
1 notify.LedARGB = Color.Green;
然后筆者設置了顯示的毫秒數與熄滅的毫秒數:
1 //設置LED顯示時間為1s 2 notify.LedOnMS = 1000; 3 //設置LED熄滅時間為1s 4 notify.LedOffMS = 1000;
為了能夠確保LED能夠顯示我們還需要設置Flags:
1 notify.Flags = NotificationFlags.ShowLights | notify.Flags;
最后發送通知(模擬器上看不出來,建議真機測試)
六、通過Builder發送通知
這個方式相對於Notification更簡單,也更快捷,但是只有在Android 3.0以上才支持(面對如今都是Android 4.0以上應該沒有問題了)
先在Main.axml中添加對應的按鈕:
並設置對應的id為@+id/builderButton
最后就是MainActivity.cs中的代碼:

1 Button builderButton = FindViewById<Button>(Resource.Id.builderButton); 2 builderButton.Click += (e, s) => 3 { 4 var pintent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(MainActivity)), 0); 5 6 var notify = new Notification.Builder(this) 7 .SetTicker("來自Builder的通知") //設置通知的簡介文字 8 .SetSmallIcon(Resource.Drawable.Icon) //設置通知的圖標 9 .SetDefaults(NotificationDefaults.All) //設置該通知具備聲音、LED和震動 10 .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification)) //設置通知聲音 11 .SetVibrate(new long[] { 1000 }) //設置震動頻率 12 .SetLights(Color.Red, 1, 0) //設置LED 13 .SetContentTitle("標題") //設置標題 14 .SetContentText("內容") //設置內容 15 .SetContentInfo("信息") //設置右下角顯示的文字 16 .SetAutoCancel(true) //點擊該通知后是否自動消失 17 //通過 SetLargeIcon 可以設置大圖標 18 .SetContentIntent(pintent); 19 20 nMgr.Notify(3, notify.Notification); 21 };
這里我們可以看到通過Builder方式創建一個通知是多么的方便,只要通過SetXXXXX就可以完成了,最后只要在發送通知的時候傳入其Notification屬性即可,當然這里很多的方法跟通過Nitification是一樣的就不單獨解釋了,而且也有注釋說明。
七、進度條式通知
大家在下載文件的時候,都會看到通知欄會有當前下載任務的進度,而這個通知可以通過Builder方式實現,而且更快捷。
在Main.axml中添加對應的按鈕
並設置id為@+id/builderButton
其次就是MainActivity.cs文件

1 Button progressButton = FindViewById<Button>(Resource.Id.progressButton); 2 progressButton.Click += (e, s) => 3 { 4 var notify = new Notification.Builder(this) 5 .SetTicker("進度條通知") 6 .SetSmallIcon(Resource.Drawable.Icon) 7 .SetOngoing(true) //設置該通知是否可以被用戶移除 true 表示不可以 8 .SetNumber(2) //設置該同時的條數 會在右下角顯示數量 9 .SetContentTitle("標題") 10 .SetProgress(100, 50, true); //第三個參數如果設置為true則進度條變成不確定進度條 11 12 nMgr.Notify(4, notify.Notification); 13 };
這里主要使用了SetProgress方法來設置進度條的最大值,當前值。最后一個參數設置為true則表示該進度條為不確定進度條,就是只會顯示滑動,不會顯示當前的進度。
1 SetProgress(100, 50, true);
這里我們還使用了一個新方法SetOngoing,通過前面的通知,大家會發現這些通知用戶完全可以通過手動的方式移除掉,但是我們如何創建一個用戶無法移除的通知呢?就是通過使用SetOngoing方法,並傳入一個true即可。
下面為實際運行圖:
八、自定義視圖通知
大家在使用音樂相關的應用的時候會發現通知欄會有一個簡單的功能界面,有當前歌曲的名稱,專輯圖片和暫停,下一曲等按鈕,這些當然不是通知自帶的,而是通過自定義通知來實現的,而本節我們不僅僅會學習如何使用自定義通知,同時還會學習如何設置自定義通知中控件的值,以及綁定監聽事件。
首先我們在Main.axml中添加按鈕
設置其id為@+id/customeViewButton
既然是自定義視圖,當然還需要一個視圖,所以我們在Resources/layout下新建一個視圖,並命名為NotificationCustomeView,並在其中寫入如下的xml:

1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:p1="http://schemas.android.com/apk/res/android" 3 p1:minWidth="25px" 4 p1:minHeight="25px" 5 p1:layout_width="match_parent" 6 p1:layout_height="match_parent" 7 p1:id="@+id/relativeLayout1" 8 p1:padding="5dp"> 9 <ImageView 10 p1:src="@drawable/Icon" 11 p1:layout_width="wrap_content" 12 p1:layout_height="match_parent" 13 p1:id="@+id/imageView1" /> 14 <RelativeLayout 15 p1:minWidth="25px" 16 p1:minHeight="25px" 17 p1:layout_width="match_parent" 18 p1:layout_height="match_parent" 19 p1:layout_toRightOf="@id/imageView1" 20 p1:id="@+id/relativeLayout2" 21 p1:paddingLeft="10dp"> 22 <TextView 23 p1:text="Large Text" 24 p1:textAppearance="?android:attr/textAppearanceLarge" 25 p1:layout_width="match_parent" 26 p1:layout_height="wrap_content" 27 p1:id="@+id/ncvTextView" /> 28 <ProgressBar 29 style="?android:attr/progressBarStyleHorizontal" 30 p1:layout_width="match_parent" 31 p1:layout_height="match_parent" 32 p1:layout_below="@id/ncvTextView" 33 p1:id="@+id/ncvProgressBar" 34 p1:indeterminateOnly="false" 35 p1:indeterminate="false" /> 36 </RelativeLayout> 37 </RelativeLayout>
當然最終的結果圖如下所示:
打開MainActivity.cs文件

1 Button customeViewButton = FindViewById<Button>(Resource.Id.customeViewButton); 2 customeViewButton.Click += (e, s) => 3 { 4 //初始化自定義視圖 5 var customeView = new RemoteViews(this.PackageName, Resource.Layout.NotificationCustomeView); 6 7 var notify = new Notification.Builder(this) 8 .SetTicker("自定義視圖通知") 9 .SetSmallIcon(Resource.Drawable.Icon) 10 .SetNumber(2) 11 .SetContent(customeView); //設置通知的自定義視圖 12 13 //設置自定義視圖中textview的文字 14 notify.Notification.ContentView.SetTextViewText(Resource.Id.ncvTextView, "通過代碼修改"); 15 16 //設置自定義視圖中Progressbar的進度 17 notify.Notification.ContentView.SetProgressBar(Resource.Id.ncvProgressBar, 100, 40, false); 18 19 //給自定義視圖中的ProgressBar綁定事件 20 var pIntent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(MainActivity)), 0); 21 //綁定事件 22 notify.Notification.ContentView.SetOnClickPendingIntent(Resource.Id.ncvProgressBar, pIntent); 23 24 nMgr.Notify(5, notify.Notification); 25 };
首先我們需要實例化一個RemoteViews封裝自定義視圖:
1 var customeView = new RemoteViews(this.PackageName, Resource.Layout.NotificationCustomeView);
然后通過通知的SetContent將其傳入
1 SetContent(customeView)
下面我們還需要訪問自定義視圖中的控件並設置他們的值,這里我們需要使用ContentView的Setxxxxxx來設置,如下下面我們就設置了TextView的文字和ProgressBar的進度:
1 //設置自定義視圖中textview的文字 2 notify.Notification.ContentView.SetTextViewText(Resource.Id.ncvTextView, "通過代碼修改"); 3 4 //設置自定義視圖中Progressbar的進度 5 notify.Notification.ContentView.SetProgressBar(Resource.Id.ncvProgressBar, 100, 40, false);
最后就是綁定事件,通知里面的綁定事件不同於其他的,只能將一個意圖與這個事件綁定(實際運用中也應該如此,比如你點擊了暫停按鈕,將會通過意圖傳遞對應的參數到服務中從而停止播放)
1 notify.Notification.ContentView.SetOnClickPendingIntent(Resource.Id.ncvProgressBar, pIntent);
下面為實際的運行圖
至此關於通知欄的使用就結束了,本人在Galaxy S4真機上測試成功(需要設置生成的配置)。