时间过得太快,想抽出点时间做点东西也是很难,总有各种各样的事。之前其实看书谢了关于Notification的demo,但是感觉还是不够。于是又打开了sdk文档和谷歌官方的Status Bar Notifications developer guide。其实之前一直是看书和网上的教程在学android,但是后来发现只有官方的文档才是原汁原味,虽然是英文,但是更全面,往往百思不得其解的问题看一眼官方文档就明白了。所以之后的打算是跟着官方的开发者指南走。又可以学习英文,又可以学技术。
Notifications的重要性不用多说,现在每天最常用的进入程序的入口就是通知了,所以对通知的管理一定要熟悉。主要用到的三个类Notifications,NotificationManager(NotificationCompat.Builder用于兼容性,NotificationManager.builde()在4.1以后才加入),PendingIntent。
当有新通知到来时,都会位于设备的顶端的status bar上,这是看到的是个小图标,当我们展开系统的状态栏时,通知也会展开。借用官方的图简要的说明一下:
插图中的各序号释义如下:
1.消息的标题
2.大图标
3.内容的概要
4.内容的信息,比如新消息的数量
5.小图标
6.通知到达的时间
创建通知的必须需要的三个元素:1.小图标,2.消息的标题,3.消息的内容
因为我的模拟器的api的level是14,所以为了兼容性,这里采用NotificationCompat.Builder来创造一个notification。消息的通知既然是作为程序的入口那么就要提供能通过点击消息进入程序的功能,所以就用到了PendingIntent。
NotificationCompat.Builder类常用方法:
public Notification build ():通过build方法构造一个Notification对象。
public NotificationCompat.Builder setContentTitle (CharSequence title):设置消息的标题
public NotificationCompat.Builder setContentText (CharSequence text):设置消息的内容
public NotificationCompat.Builder setProgress (int max, int progress, boolean indeterminate):设置进度条的进度
public NotificationCompat.Builder setVibrate (long[] pattern):设置手机震动。
public NotificationCompat.Builder setContent (RemoteViews views):允许用户自定义通知的视图
程序的大致流程如下:首先通过NotificationCompat.Builder来获得一个构造器对象,然后通过方法来设置notification的各个参数,最后通过build方法来成成一个notification对象,再通过notification manager来将通知显示到status bar上。通知管理器是系统提供的服务,所以需要通过(NotificationManager)getSystemService(NOTIFICATION_SERVICE)来获取管理器的实例。在这里通过按钮来出发这些事件,从而实现创建一条新消息,更新消息,清除消息。
3 import android.app.Activity; 4 import android.app.NotificationManager; 5 import android.app.PendingIntent; 6 import android.content.Intent; 7 import android.graphics.BitmapFactory; 8 import android.os.Bundle; 9 import android.support.v4.app.NotificationCompat; 10 import android.view.Menu; 11 import android.view.View; 12 import android.widget.Button; 13 import android.widget.Toast; 14 15 public class MainActivity extends Activity { 16 int notificationID=1; 17 NotificationManager nm; 18 PendingIntent pendingintent ; 19 NotificationCompat.Builder mBuilder; 20 //Bitmap bt_icon = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.drawable.ic_launcher); 21 @Override 22 protected void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 setContentView(R.layout.activity_main); 25 mBuilder = new NotificationCompat.Builder(getBaseContext()); 26 nm = (NotificationManager) 27 getSystemService(NOTIFICATION_SERVICE); 28 Button button1 = (Button)findViewById(R.id.display_button); 29 Button button2 = (Button)findViewById(R.id.update_button); 30 Button button3 = (Button)findViewById(R.id.clear_button); 31 button1.setOnClickListener(new View.OnClickListener() { 32 33 @Override 34 public void onClick(View v) { 35 // TODO Auto-generated method stub 36 displayNotification(); 37 } 38 }); 39 button2.setOnClickListener(new View.OnClickListener() { 40 41 @Override 42 public void onClick(View v) { 43 // TODO Auto-generated method stub 44 if(mBuilder != null){ 45 mBuilder.setContentText("changing tiome to 5pm"); 46 nm.notify(notificationID,mBuilder.build()); 47 48 } 49 else 50 { 51 Toast.makeText(getBaseContext(), "there is no Notification",Toast.LENGTH_SHORT).show(); 52 } 53 } 54 }); 55 button3.setOnClickListener(new View.OnClickListener() { 56 57 @Override 58 public void onClick(View v) { 59 // TODO Auto-generated method stub 60 nm.cancelAll(); 61 } 62 }); 63 } 64 65 @Override 66 public boolean onCreateOptionsMenu(Menu menu) { 67 // Inflate the menu; this adds items to the action bar if it is present. 68 getMenuInflater().inflate(R.menu.main, menu); 69 return true; 70 } 71 public void displayNotification() 72 { 73 Intent i = new Intent(this,NotificationView.class); 74 i.putExtra("notificationID", notificationID); 75 76 PendingIntent pendingintent = 77 PendingIntent.getActivity(this, 0, i, 0); 78 //设置各项参数 79 80 mBuilder.setContentTitle("New mail from mali") 81 .setContentText("Metting with customer at 3pm") 82 .setSmallIcon(R.drawable.ic_launcher) 83 .setLargeIcon(BitmapFactory.decodeResource(MainActivity.this.getResources(), R.drawable.a)); 84 nm.notify(notificationID,mBuilder.build()); 85 86 87 } 88 89 }
为了明显的区分出大图标与小图标,这里用了两张不同的图片。运行程序后,点击第一个按钮,生成一个通知,拉下通知栏。
对于消息的通知我们不可能每次来一个消息都生成一个通知,那样通知栏一直往下堆砌既不好看也不实用,特别是同一类的消息,比如某个人给你发的新的QQ消息。只需要在刚才的消息上进行更新就行。所以最好给每个消息分派一个ID,这样以后就能根据ID去更新。这里我点击第二个按钮,刷新一下消息的内容。
消息内容发生改变:
第三个按钮是清除消息,这里用的是clearAll方法。清除所有的通知。
接下来是意图,pending意思就是等待的,通过pending intent消息已经准备好进入另一个activity的入口。所以我们构造另一个类NotificationView.java用来测试消息的入口。
package com.example.notifications; import android.app.Activity; import android.app.NotificationManager; import android.os.Bundle; public class NotificationView extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.notification); //查找通知管理服务 NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); nm.cancel(getIntent().getExtras().getInt("notificationID")); } }
代码比较简单,主要是帮助理解pending intent的意思。在这里我们用了另一个cancel的方法,他的参数是传递过来的通知的ID,通过这个方法来清除指定的通知。
还有一种很常见的通知就是在下载的时候提示我们下载进度的通知,构造器也提供了setProgress方法来方便的管理进度条。注释掉上面displayNotification()方法中的设置参数的代码,添加如下代码:
1 new Thread(new Runnable() { 2 3 @Override 4 public void run() { 5 // TODO Auto-generated method stub 6 int incr; 7 for(incr=0;incr<=100;incr+=5){ 8 mBuilder.setProgress(100, incr, false); 9 nm.notify(0,mBuilder.build()); 10 try { 11 // Sleep for 5 seconds 12 Thread.sleep(5*1000); 13 } catch (InterruptedException e) { 14 Log.d("sleep", "sleep failure"); 15 } 16 } 17 mBuilder.setContentText("Download complete") 18 // Removes the progress bar 19 .setProgress(0,0,false); 20 nm.notify(notificationID, mBuilder.build()); 21 } 22 }).start();
需要注意的是,如果想要显示进度条的话,小图标的位置就会被挤掉,如果设置了小图标,没设置大图标,小图标会自动移动到大图标的位置。效果如下图: