Oschina 安卓客户端源码学习之三

今天呢,来研究一个功能,消息通知

(1)首先是消息推送的获得或者说是产生。

在main.java这个文件里有这样一个函数

/**
	 * 轮询通知信息
	 */
	private void foreachUserNotice() {
		final int uid = appContext.getLoginUid();
		final Handler handler = new Handler() {
			public void handleMessage(Message msg) {
				if (msg.what == 1) {
					UIHelper.sendBroadCast(Main.this, (Notice) msg.obj);
				}
				foreachUserNotice();// 回调
			}
		};
		new Thread() {
			public void run() {
				Message msg = new Message();
				try {
					sleep(60 * 1000);
					if (uid > 0) {
						Notice notice = appContext.getUserNotice(uid);
						msg.what = 1;
						msg.obj = notice;
					} else {
						msg.what = 0;
					}
				} catch (AppException e) {
					e.printStackTrace();
					msg.what = -1;
				} catch (Exception e) {
					e.printStackTrace();
					msg.what = -1;
				}
				handler.sendMessage(msg);
			}
		}.start();
	}

这便是简单粗暴的消息取得过程

sleep(60* 1000);

休息一分钟之后appContext.getUserNotice(uid);通过这个函数来取得消息。跟踪该函数代码后得知,它其实是和开源中国的服务器请求了一些数据,然后构造成Notice对象,返回来。然后塞到msg里。最后通过handler.sendMessage(msg);把msg发送出去。而在上面handleMessage里头又调用了foreachUserNotice()这个函数。这就是最终的一个过程,周而复始,一分钟歇一次,歇够了要数据。专业一点叫轮询。

然后我们看这个handleMessage里头有一个sendBroadCast函数,也就是说轮询之后得到的notice最终都是发送广播,发送出去了。

(2)接下来,我们来看看广播的接收部分

首先静态注册了一个广播

<receiver android:name=".ui.BroadCast">
            <intent-filter>
                <action android:name="net.oschina.app.action.APPWIDGET_UPDATE"/>
            </intent-filter>
       </receiver>

我们找到ui.BroadCast这个类,下面是对收到的广播的处理方法

@Override
   public void onReceive(Contextcontext, Intent intent) {
      StringACTION_NAME = intent.getAction();
      if("net.oschina.app.action.APPWIDGET_UPDATE".equals(ACTION_NAME))
      {
          int atmeCount =intent.getIntExtra("atmeCount", 0);//@我
          int msgCount =intent.getIntExtra("msgCount", 0);//留言
          int reviewCount =intent.getIntExtra("reviewCount", 0);//评论
          int newFansCount =intent.getIntExtra("newFansCount", 0);//新粉丝
          int activeCount = atmeCount+ reviewCount + msgCount + newFansCount;//信息总数

          //动态-总数
          if(Main.bv_active != null){
             if(activeCount > 0){
                Main.bv_active.setText(activeCount+"");
                Main.bv_active.show();
             }else{
                Main.bv_active.setText("");
                Main.bv_active.hide();
             }
          }
          //@我
          if(Main.bv_atme != null){
             if(atmeCount > 0){
                Main.bv_atme.setText(atmeCount+"");
                Main.bv_atme.show();
             }else{
                Main.bv_atme.setText("");
                Main.bv_atme.hide();
             }
          }
          //评论
          if(Main.bv_review != null){
             if(reviewCount > 0){
                Main.bv_review.setText(reviewCount+"");
                Main.bv_review.show();
             }else{
                Main.bv_review.setText("");
                Main.bv_review.hide();
             }
          }
          //留言
          if(Main.bv_message != null){
             if(msgCount > 0){
                Main.bv_message.setText(msgCount+"");
                Main.bv_message.show();
             }else{
                Main.bv_message.setText("");
                Main.bv_message.hide();
             }
          }

          //通知栏显示
          this.notification(context,activeCount);
      }
   }

查看代码得知bv_active等bv开头的变量类型都是BadgeView变量。这个类继承自textView类。实现的功能呢就是一个控件上方一个红色小圆圈,里面有数字。也就是说提示你的新消息条数,这玩意,很常用的哈。具体的就不说了。

这里呢就是把notice的内容拿出来去更新这个控件。这个消息的过程在这就走到终点了。

this.notification这个函数呢,很明显就是手机通知栏的消息通知了

咱们来看看

private voidnotification(Context context, int noticeCount){
      //创建NotificationManager
      NotificationManagernotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

      StringcontentTitle = "开源中国";
      StringcontentText = "您有 " + noticeCount + " 条最新信息";
      int _lastNoticeCount;

      //判断是否发出通知信息
      if(noticeCount == 0)
      {
          notificationManager.cancelAll();
          lastNoticeCount= 0;
          return;
      }
      else if(noticeCount == lastNoticeCount)
      {
          return;
      }
      else
      {
          _lastNoticeCount= lastNoticeCount;
          lastNoticeCount= noticeCount;
      }

      //创建通知 Notification
      Notificationnotification = null;

      if(noticeCount >_lastNoticeCount)
      {
          StringnoticeTitle = "您有 " + (noticeCount-_lastNoticeCount) + " 条最新信息";
         notification= newNotification(R.drawable.icon, noticeTitle, System.currentTimeMillis());
      }
      else
      {
          notification= newNotification();
      }

      //设置点击通知跳转
      Intentintent = newIntent(context, Main.class);
      intent.putExtra("NOTICE",true);
   intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);

     PendingIntentcontentIntent = PendingIntent.getActivity(context, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);

      //设置最新信息
      notification.setLatestEventInfo(context,contentTitle, contentText, contentIntent);

      //设置点击清除通知
      notification.flags = Notification.FLAG_AUTO_CANCEL;

      if(noticeCount >_lastNoticeCount)
      {
          //设置通知方式
          notification.defaults |= Notification.DEFAULT_LIGHTS;

          //设置通知音-根据app设置是否发出提示音
         if(((AppContext)context.getApplicationContext()).isAppSound())
             notification.sound = Uri.parse("android.resource://"+ context.getPackageName() + "/" + R.raw.notificationsound);

          //设置振动 <需要加上用户权限android.permission.VIBRATE>
          //notification.vibrate = new long[]{100, 250, 100, 500};
      }

      //发出通知
      notificationManager.notify(NOTIFICATION_ID,notification);
   }

具体的就不分析了,还是很简单的。

时间: 2024-10-09 10:03:54

Oschina 安卓客户端源码学习之三的相关文章

Oschina 安卓客户端源码学习之一

今天主要研究一下两个功能 (1)双击返回键退出程序 (2)接近完美地退出程序 (1) 在很多应用程序里都有一个功能,就是点击返回键,之后提示你再点击返回键就退出程序.之前一直很好奇这是怎么实现的,今天正好把开源中国安卓客户端源码扒下来了,所以就在这里研究一下这个很简单的功能. public class DoubleClickExitHelper { private final Activity mActivity; private boolean isOnKeyBacking; private

开源中国安卓客户端源码学习(一) 渐变启动界面

开源中国安卓客户端源码学习(一) 准备学习安卓开发, 看到网上有人推荐开源中国安卓客户端的源码, 说里面包含了大部分技术, 于是准备好好研究研究. 特开通此系列博客来记录学习过程. 由于是在学习, 经验不足, 里面肯定有很多不对的地方, 望大家指正. 到这里下载源码包,开发环境为Linux下Eclipse,导入源码后有可能会出现android.webkit.CacheManager找不到的错误, 原因是这个类在4.0以上版本的SDK被删除了, 只要下载4.0版本的SDK使用即可. 由于googl

OSChina客户端源码学习(3)--轮询机制的实现

主要以OSChina Android客户端源码中Notice的轮询机制进行解读. 一.基础知识 一般IM(即使通讯)的实现有两种方式:推送和轮询,推送就是服务器主动向客户端发送消息,用特定的协议比如XMPP.MQTT.另一种是轮询,实时性并不高,而且比较耗电.这种有分为两种情况:一段时间发起一次查询和死循环进行查询. 参考: http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0401/1609.html 远端Service调用: a.服

春秋旅行安卓客户端源码项目

春秋旅行安卓客户端源码,这是一款高度模仿春秋旅行app开发的一款应用,通过抓包工具获取到的接口,希望大家能够喜欢,并且对大家的学习能够有所帮助. 源码下载:http://code.662p.com/view/12837.html <ignore_js_op> <ignore_js_op> 详细说明:http://android.662p.com/thread-6460-1-1.html

Android应用源码仿暴风影音安卓客户端源码

Android应用源码仿暴风影音安卓客户端源码 本项目是一个模仿暴风影音的UI项目源码,仿照的界面有菜单页,主页,分类页等,项目内的所有数据都使用的本地模拟数据,仿照度一般在大分辨设备上布局显示会有问题,480x800的分辨率应该正合适,默认编译版本4.2.2编码GBK,注释不多,需要的朋友可以下载看一下. 下载地址:http://www.devstore.cn/code/info/133.html 运行截图:     版权声明:本文为博主原创文章,未经博主允许不得转载.

开源中国安卓客户端源码之自定义控件---ScreenShotView

首先,感谢开源中国的开源精神.当初学者拿到客户端源码时,可能会对其中的项目结构和代码产生许多困惑,不知道该从何下手,当然我也是其中一员,接触安卓时间不长,也不是很精通,但是通过一段时间的琢磨,慢慢地领会到其中的一些编程方法,我只是想把我弄明白的这些知识通过博客的形式记录下来,以备以后查看,当然也可以帮助到更多的初学者.我的主要工作是给代码添加注释,理顺调用关系,让初学者更快.更深刻地理解代码的含义,领会其精神.首先大家从http://git.oschina.net/oschina/android

开源中国 OsChina Android 客户端源码分析(12)清理缓存

上一篇中 缓存对象中我们提到了,将对象数据缓存的地方有三个地方,这里我们详细的说下: 1(/data/data/com.xxx.xxx/cache) 应用私有的缓存目录,属于内部缓存,其他应用无法访问,一般存储较小的数据: 2(/mnt/sdcard/android/data/com.xxx.xxx/cache),应用私有的外部缓存目录. 3SD卡下的自定义目录,共用的. 要实现清除缓存,那么首先你需要知道: 1应用是否采用了缓存策略: 2缓存的数据是什么,在哪里进行了缓存? 3缓存大小的计算实

OSChina客户端源码学习(2)--缓存的设计

一.缓存的作用 请求数据的时候,首先进行判断,是否可以从缓存中获取数据,如果满足条件,则直接从缓存中获取数据.否则请求新的数据.这样比没有缓存的情况下,每次都要从服务器请求数据要快,而且,没有网的情况下,也可以浏览已经缓存了的数据,极大的提高了用户的体验. 二.源码解析 源码中用到缓存的地方有: 1 请求数据之前,先判断是否可以从缓存中获取,如果满足条件,则直接从缓存中读取,否则,向服务器请求新的数据. // 获取缓存的目录 private String getCacheKey() { retu

开源中国 OsChina Android 客户端源码分析(8)数据库Sqlite

1开源中国客户端使用的数据库部分的源码在net.oschina.app.db包下,两个类一个是用于管理数据库的创建类DatabaseHelper,继承SQLiteOpenHelper,另一个是用于数据库的增删改查的工具类NoteDatabase.那么数据库在开源中国源码中哪一模块用到了呢? 便签管理,便签是什么?就是一个记事本的功能o(^▽^)o 2关于SQLiteOpenHelper的使用,自己之前的项目中没有用到过,看了下,这里有个体会:当获取到SQLiteOpenHelper实例,并使用g