Xamarin.Android通知詳解
一、傳送通知的機制
在日常的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 };View Code
其中我們先例項化了一個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 };View Code
然後傳送一個通知後,點選取消普通通知,會發現通知欄中不存在我們傳送的通知了。
五、傳送帶有聲音、震動和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 };View Code
下面我們來分析一下程式碼,既然這個通知帶有聲音等,那麼我們需要設定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 };View Code
這裡我們可以看到通過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 };View Code
這裡主要使用了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>View Code
當然最終的結果圖如下所示:
開啟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 };View Code
首先我們需要例項化一個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真機上測試成功(需要設定生成的配置)。