我们在QQ项目中实现了通知栏后台运行,以及来新消息提示,通常在消息通知时,我们经常用到两个组件Toast和Notification。特别是重要的和需要长时间显示的信息,用Notification就最合适不过了。当有消息通知时,状态栏会显示通知的图标和文字,通过下拉状态栏,就可以看到通知信息了,Android这一创新性的UI组件赢得了用户的一致好评,就连苹果也开始模仿了。其实有点类似于Windows的托盘显示。

下面我们就来根据QQ小项目,来具体分析一下。先看下两张效果图:


Android之动态更新通知栏_后台运行

Android之动态更新通知栏_Notification_02

通知栏的布局文件,在我们这个QQ小项目中,当我们在好友列表的Activity按返回键的时候,先作一个程序进入后台运行的标记(可以是全局变量,也可以保存到SharedPreferenced文件中),然后发送一个广播,我们通过在服务里接收这个广播,就马上初始化后台运行的通知栏的view,当新消息到来时,我们就不把消息通过广播发送出去了(因为没有Activity在运行),而是直接通过更新通知栏来提醒用户,同时发送一个通知(带声音、带振动)。下面是我们这个在通知栏的view的布局文件notify_view.xml:


[html]  view plain  copy

1. <?xml version="1.0" encoding="utf-8"?>  
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
3. android:layout_width="match_parent"  
4. android:layout_height="match_parent"  
5. android:orientation="vertical" >  
6.   
7. <LinearLayout  
8. android:layout_width="match_parent"  
9. android:layout_height="wrap_content"  
10. android:orientation="vertical"  
11. android:padding="2dp" >  
12.   
13. <RelativeLayout  
14. android:layout_width="match_parent"  
15. android:layout_height="wrap_content" >  
16.   
17. <ImageView  
18. android:id="@+id/notify_imageLog"  
19. android:layout_width="40dp"  
20. android:layout_height="40dp"  
21. android:layout_alignParentLeft="true"  
22. android:layout_centerVertical="true"  
23. android:paddingLeft="5dp"  
24. android:src="@drawable/h001" />  
25.   
26. <TextView  
27. android:id="@+id/notify_name"  
28. android:layout_width="wrap_content"  
29. android:layout_height="wrap_content"  
30. android:layout_centerVertical="true"  
31. android:layout_toRightOf="@+id/notify_imageLog"  
32. android:paddingLeft="5dp"  
33. android:text="name"  
34. android:textColor="#000000"  
35. android:textSize="20sp" />  
36. </RelativeLayout>  
37.   
38. <LinearLayout  
39. android:layout_width="fill_parent"  
40. android:layout_height="wrap_content"  
41. android:layout_gravity="center"  
42. android:orientation="horizontal" >  
43.   
44.   
45. <TextView  
46. android:id="@+id/notify_msg"  
47. android:layout_width="wrap_content"  
48. android:layout_height="wrap_content"  
49. android:layout_weight="1"  
50. android:paddingLeft="15dp"  
51. android:text="msg"  
52. android:textColor="@color/black"  
53. android:textSize="15sp" />  
54.   
55. <TextView  
56. android:id="@+id/notify_time"  
57. android:layout_width="wrap_content"  
58. android:layout_height="wrap_content"  
59. android:layout_weight="1"  
60. android:gravity="right"  
61. android:paddingRight="15dp"  
62. android:text="time"  
63. android:textColor="@color/black"  
64. android:textSize="15sp" />  
65. </LinearLayout>  
66. </LinearLayout>  
67.   
68. </LinearLayout>



二、初始化通知栏view的方法,在GetMsgService中写一个方法,初始化我们这个通知栏的view:


[java]  view plain  copy


    1. /**
    2.      * 创建通知
    3.      */  
    4. private void setMsgNotification() {  
    5. int icon = R.drawable.notify;  
    6. "";  
    7. long when = System.currentTimeMillis();  
    8. new Notification(icon, tickerText, when);  
    9.   
    10. // 放置在"正在运行"栏目中  
    11.         mNotification.flags = Notification.FLAG_ONGOING_EVENT;  
    12.   
    13. new RemoteViews(mContext.getPackageName(),  
    14.                 R.layout.notify_view);  
    15.         contentView.setTextViewText(R.id.notify_name, util.getName());  
    16. "手机QQ正在后台运行");  
    17.         contentView.setTextViewText(R.id.notify_time, MyDate.getDate());  
    18. // 指定个性化视图  
    19.         mNotification.contentView = contentView;  
    20.   
    21. new Intent(this, FriendListActivity.class);  
    22. 0,  
    23.                 intent, PendingIntent.FLAG_UPDATE_CURRENT);  
    24. // 指定内容意图  
    25.         mNotification.contentIntent = contentIntent;  
    26.         mNotificationManager.notify(Constants.NOTIFY_ID, mNotification);  
    27.     }


    三,好友列表Activity返回按键的广播接收者,用户按返回键发送广播,并做好标记,程序进入后台运行:


    [java]  view plain  copy


    1. // 收到用户按返回键发出的广播,就显示通知栏  
    2. private BroadcastReceiver backKeyReceiver = new BroadcastReceiver() {  
    3.   
    4. @Override  
    5. public void onReceive(Context context, Intent intent) {  
    6. // TODO Auto-generated method stub  
    7. "QQ进入后台运行", 0).show();  
    8.             setMsgNotification();  
    9.         }  
    10.     };



    四,通过handler更新通知栏,我们是通过handler来处理消息并更新通知栏的:


    [java]  view plain  copy


      1. // 用来更新通知栏消息的handler  
      2. private Handler handler = new Handler() {  
      3. public void handleMessage(Message msg) {  
      4. switch (msg.what) {  
      5. case MSG:  
      6. int newMsgNum = application.getNewMsgNum();// 从全局变量中获取  
      7. // 每收到一次消息,自增一次  
      8. // 再设置为全局变量  
      9.                 TranObject<TextMessage> textObject = (TranObject<TextMessage>) msg  
      10. "msg");  
      11. // System.out.println(textObject);  
      12. if (textObject != null) {  
      13. int form = textObject.getFromUser();// 消息从哪里来  
      14. // 消息内容  
      15.   
      16. new ChatMsgEntity("",  
      17. 1, true);// 收到的消息  
      18. // 保存到数据库  
      19.   
      20. // 更新通知栏  
      21. int icon = R.drawable.notify_newmessage;  
      22. ":" + content;  
      23. long when = System.currentTimeMillis();  
      24. new Notification(icon, tickerText, when);  
      25.   
      26.                     mNotification.flags = Notification.FLAG_NO_CLEAR;  
      27. // 设置默认声音  
      28.                     mNotification.defaults |= Notification.DEFAULT_SOUND;  
      29. // 设定震动(需加VIBRATE权限)  
      30.                     mNotification.defaults |= Notification.DEFAULT_VIBRATE;  
      31. null;  
      32.   
      33. new Intent(mContext,  
      34. class);  
      35.                     PendingIntent contentIntent = PendingIntent.getActivity(  
      36. 0, intent, 0);  
      37.                     mNotification.setLatestEventInfo(mContext, util.getName()  
      38. " (" + newMsgNum + "条新消息)", content,  
      39.                             contentIntent);  
      40.                 }  
      41. // 通知一下才会生效哦  
      42. break;  
      43.   
      44. default:  
      45. break;  
      46.             }  
      47.         }  
      48.     };


       

      监听消息,我们监听收消息线程中收到的消息先判断程序是否运行在后台,如果在后台,我们就直接把消息发送给handler,如果不是,就通过广播发送出去这个消息,所以:我们首先需要在按返回键的进入后台的时候,做一个标记,表示程序进入后台运行,我这里是通过保存在SharedPreferenced文件中的,其实可以保存到应用的全局变量:


      [java]  view plain  copy

      1. in.setMessageListener(new MessageListener() {  
      2.   
      3. @Override  
      4. public void Message(TranObject msg) {  
      5. // System.out.println("GetMsgService:" + msg);  
      6. if (util.getIsStart()) {// <span style="color:#ff0000;">如果 是在后台运行,就更新通知栏,否则就发送广播给</span>Activity  
      7. if (msg.getType() == TranObjectType.MESSAGE) {// 只处理文本消息类型  
      8. // System.out.println("收到新消息");  
      9. // 把消息对象发送到handler去处理  
      10.                             Message message = handler.obtainMessage();  
      11.                             message.what = MSG;  
      12. "msg", msg);  
      13.                             handler.sendMessage(message);  
      14.                         }  
      15. else {  
      16. new Intent();  
      17.                         broadCast.setAction(Constants.ACTION);  
      18.                         broadCast.putExtra(Constants.MSGKEY, msg);  
      19. // 把收到的消息已广播的形式发送出去  
      20.                     }  
      21.                 }  
      22.             });


      后台消息处理就是这样实现的,如果大家有什么好的建议或者疑问,欢迎给我留言,谢谢。