安卓webservicepush,有没有办法不注册service实现呀

[原创]通过代码及流程图说明Google在Android上的Push机制的实现 - 坚持,淡定 - ITeye技术网站
博客分类:
声明: 如果您要转载, 请事先征得本人的同意后方可并且请您附上原文链接. 本人保留一切权利. 多谢!
Google从FroYo版本后引入了C2DM (Cloud to Device Messaging)框架:
Android Cloud to Device Messaging (C2DM) is a service that helps developers send data from servers to their applications on Android devices. The service provides a simple, lightweight mechanism that servers can use to tell mobile applications to contact the server directly, to fetch updated application or user data. The C2DM service handles all aspects of queueing of messages and delivery to the target application running on the target device.
这个C2DM框架实际上就是一种Push机制, 当服务器端有changes(creates/updates/deletes)时, 服务器端立刻会通过Push机制通知客户端, 然后客户端会通过Sync机制从服务器端获取server-side diffs, 同时也会把client-side diffs发送给服务器端. 通过Push机制, 用户可以及时获得服务器端的改动, 因此有更好的用户体验.
注:
1. Push机制的实现有多种, 比如通过SMS, 以及现在介绍的C2DM.
2. Android上的Sync机制这里不做过多介绍. 实际上对应下面介绍的内容Google是把Push机制和Sync机制一起使用的.
那么, C2DM的实现原理是什么呢? XMPP!!! 和Android GTalk Client的协议实现一样, 都是XMPP, 并且用的都是同一个XMPP框架, XMPP Stack的实现用的是开源的Smack. 其实, 在FroYo之前, Google的Push机制直接就是在XMPP上面, 只不过在引入了C2DM后, 变成Push机制在C2DM上面, 然后C2DM在XMPP上面了.
下面, 通过介绍Android上Google Contacts/Calendar如何利用C2DM实现Push机制来进行说明. 说的顺序可能比较乱, 大家慢慢理解, 并且其中的code只是用来帮助大家来进行理解.
1. 在AndroidManifest.xml上declare了一个broadcast receiver和一个对应的service用来接收C2DM发送的通知.
&receiver android:name=".subscribedfeeds.SubscribedFeedsBroadcastReceiver"&
&intent-filter&
&action android:name="com.google.android.c2dm.intent.RECEIVE" /&
&category android:name="com.google.android.gsf.subscribedfeeds" /&
&/intent-filter&
&/receiver&
&service android:name=".subscribedfeeds.SubscribedFeedsIntentService" /&
Google Sync是通过Atom Feed协议进行的. 这样当Server端有changes后, 会通过C2DM框架发送"com.google.android.c2dm.intent.RECEIVE" action给SubscribedFeedsBroadcastReceiver,& 而SubscribedFeedsBroadcastReceiver在onReceive()方法启动SubscribedFeedsIntentService. 其可能的代码为:
public class SubscribedFeedsBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
intent.setClass(context, SubscribedFeedsIntentService.class);
context.startService(intent);
关于"com.google.android.c2dm.intent.RECEIVE" action, 这是C2DM框架定义的标准action, 可以参考C2DM开发文档.
2. C2DM框架什么时候以及如何发送"com.google.android.c2dm.intent.RECEIVE" action.
这里用到的就是XMPP协议扩展. 这里扩展了XMPP的&message& packet, 在其中加入了自定义的elements. 当Google Server有changes后, 会通过XMPP发送&message&给Android上的XMPP client框架,& XMPP client框架会解析&message& packet, 如果发现是关于Google Sync的&message& packet, 则发送"com.google.android.c2dm.intent.RECEIVE" action.
如何接收自定义的XMPP packets呢? 需要首先了解一下Smack的API, 这里不赘述.
2.1 类DataMessageManager
DataMessageManager是一个PacketListener, 当有特定的Packets到达时会调用它的processPacket()方法.
public class DataMessageManager implements PacketListener
2.2 注册DataMessageManager这个PacketListener
PacketTypeFilter filter = new PacketTypeFilter(DataMessage.class);
connection.addPacketListener(this, localPacketTypeFilter);
注意这里的PacketTypeFilter用的是DataMessage, 表示DataMessage这样的XMPP packets才是需要处理的Packets.
2.3 类DataMessage
public class DataMessage extends Message
private ArrayList&AppData& mAppDataL
private String mC
private boolean mFromTrustedServer = 0;
private String mP
private String mT
}
其中override了一个方法:
public String getExtensionsXML() {
StringBuilder buf = new StringBuilder()
buf.append("&data").append(" xmlns=\"")append("google:mobile:data").append("\"");
if (getCategory() != null)
buf.append(" category=\"").append(getCategory()).append("\"");
if (getToken() != null)
buf.append(" token=\"").append(getToken()).append("\"");
if (getPermission() != null)
buf.append(" permission=\"").append(getPermission()).append("\"");
if (this.mFromTrustedServer)
buf.append(" from-trusted-server=\"true\"");
buf.append("&");
int size = getAppDataSize();
for (int i = 0; i & i++) {
AppData appData = (AppData)this.mAppDataList.get(i);
buf.append("&app-data key=\"").append(appData.getKey()).append("\" value=\"")
.append(appData.getValue()).append("\" /&");
buf.append("&/data&";
return buf.toString();
}
从这里可以发现, DataMessage对应的是类似下面的XMPP packets:
&message id="zUwxRf4-9" persistent_id="0:5" from="" type="headline"&&data xmlns="google:mobile:data" category="GSYNC_TICKLE" token="cl_6" from-trusted-server="true"&&app-data key="account" value="zhangsan." /&&/data&&/message&
也就是说, 当Server端有changes需要客户端来sync的时候, 会发送类似与上面的消息给客户端, 这个消息会被DataMessageManager处理.
而在DataMessageManager的processPacket()方法中, 会再做如下判断:
String category= dataMessage.getCategory();
if ("GSYNC_TICKLE".equals(str2))
category = "com.google.android.gsf.subscribedfeeds";
Intent intent = new Intent("com.google.android.c2dm.intent.RECEIVE");
intent.addCategory(category);
context.sendBroadcast(intent);
这个code会认为category为"GSYNC_TICKLE"的XMPP packets才是有关Google Sync的, 并做相应转换.
3. SubscribedFeedsIntentService被启动, 会调用下面的API进行Sync, 后面涉及到的就是Android的Sync机制了, 如果有时间再解释.
ContentResolver.requestSync(......);
大概的时序图为:
浏览 14356
这个必须要smack包吧..??需要 smack 包是标准的开源方式,比如 androidpn
不用一直开着吧,貌似是接到命令才启动的Serviceservice一直开着还是需要的时候再开着, 都无所谓了,根据需要. Service各种情况都能满足的.
laiyangdeli
浏览: 526504 次
来自: 南京
多谢楼主分享,感激不尽
不错,有收获
楼主你好,srec我怎么没有啊在我的工程里,无法import
加了这句后,不止是程序不见,整个屏幕都点不动了
楼主你用什么工具画出那个图片的,我之前用过一段时间,在华为的时 ...经验内容仅供参考,如果您需解决具体问题(尤其法律、医学等领域),建议您详细咨询相关领域专业人士。
说说为什么给这篇经验投票吧!
我为什么投票...
你还可以输入500字
看了这篇经验,你有一些独到的心得要分享给大家?或是,你按照作者的指导,做出了一模一样,甚至更棒的结果?
不管是“有心得”,还是“有所得”,都快分享给经验的小伙伴们看看吧!
你还可以输入1000字
如对这篇经验有疑问,可反馈给作者,经验作者会尽力为您解决!
你还可以输入500字
请扫描分享到朋友圈后使用快捷导航没有帐号?
只需一步,快速开始
查看: 751|回复: 5
在线时间38 小时经验值116 最后登录注册时间帖子阅读权限40UID5237570
高中生, 积分 116, 距离下一级还需 84 积分
该用户从未签到
G币81 最后登录注册时间
马上注册,结交更多机友,下载更多应用,让你轻松玩转手机。
已有帐号?   下载游戏和软件,请【】进入机锋市场!
每天都能收到Push&&message的短信,但是每次点击进去却什么都看不到!
11:54 上传
就是红线圈起来的地方是 有显示的。
11:57 上传
可是点进去就什么都看不到。
(104.97 KB)
11:47 上传
点击文件名下载附件
(277.62 KB)
11:47 上传
点击文件名下载附件
(277.62 KB)
11:54 上传
点击文件名下载附件
在线时间146 小时经验值297 最后登录注册时间帖子阅读权限50UID647884
大学专科, 积分 297, 距离下一级还需 103 积分
TA的每日心情开心3&天前签到天数: 5 天[LV.2]偶尔看看I
G币290 最后登录注册时间
GO短信收不了,看系统自带的就有了。
在线时间194 小时经验值126 最后登录注册时间帖子阅读权限40UID8271491
高中生, 积分 126, 距离下一级还需 74 积分
该用户从未签到
G币21 最后登录注册时间
表示没有收到过
在线时间460 小时经验值732 最后登录注册时间帖子阅读权限70UID6018336
学士, 积分 732, 距离下一级还需 368 积分
TA的每日心情开心 18:18签到天数: 12 天[LV.3]偶尔看看II
G币1349 最后登录注册时间
没遇到过,希望有大神给楼主解决啊
在线时间38 小时经验值116 最后登录注册时间帖子阅读权限40UID5237570
高中生, 积分 116, 距离下一级还需 84 积分
该用户从未签到
G币81 最后登录注册时间
& & 我谢你哦!&&还真是这样子的!&&不过系统自带的短信感觉不好看。。。还是喜欢GO短信!
在线时间1276 小时经验值5401 最后登录注册时间帖子阅读权限120UID917920
导师, 积分 5401, 距离下一级还需 699 积分
TA的每日心情开心6&天前签到天数: 2 天[LV.1]初来乍到
G币1795 最后登录注册时间
没进来都知道是go短信了
Powered byAndroid push Service Notification
-------------
新增文件夹...
新增文件夹
(多个标签用逗号分隔)
在APP中经常会用到通知。这是个比较普遍的功能。比如网易新闻客户端,有什么重大新闻的话会在通知栏弹出一条通知。  在做程序过程中我也遇到这个需求。每隔7天就自动弹出通知,提醒用户。在网上搜了搜,用了2天时间实现了。实现过程如下:
  一:通知要调用闹钟功能来实现,第一步设置闹钟
  /*参数1:context 参数2:唤醒的时间(毫秒格式)
   *功能:发出闹钟广播
 public static void setAlarmTime(Context context, long timeInMillis) {
    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent("android.alarm.demo.action");
    PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent,PendingIntent.FLAG_CANCEL_CURRENT);
    int interval = 7*24*60*60*1000; //7天时间的毫秒形式
    am.setRepeating(AlarmManager.RTC_WAKEUP, timeInMillis,
    interval, sender);//参数2表示唤醒时间,参数2表示时间间隔。
  要在需要的地方调用该方法,调用之后将调用时的时间存储起来,为什么,下面会说。
  存储代码:
  SharedPreferences alarmTime = context.getSharedPreferences(Constant.ALARM_TIME, 0);
  Editor editor = alarmTime.edit();
  editor.putLong("theFirstNotifyBeginTime",System.currentTimeMillis());
  mit();
  二:接收步骤一中发出的BroadCast
public class AlarmReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
  if ("android.alarm.demo.action".equals(intent.getAction())){
  //就在这里调用通知的操作
    NotifyUtil.addAppNotify(context); //我自己的通知的函数,见第三步
    SharedPreferences alarmTime = context.getSharedPreferences("alarm_time", 0);//为什么会有这个,接着往下看就行。
    Editor editor = alarmTime.edit();
    editor.putLong("lastNotifyTime",System.currentTimeMillis());
    mit();
  三:步骤二中要调用的通知函数。
public class NotifyUtil {
    public static void addAppNotify(Context context){
    NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    Notification notification = new Notification();
    notification.icon = R.drawable.icon_app_ //通知图标
    notification.tickerText = context.getResources().getString(R.string.app_tickerText); //通知的内容
    notification.defaults=Notification.DEFAULT_SOUND; //通知的铃声
    notification.audioStreamType= android.media.AudioManager.ADJUST_LOWER;
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("carman.execise","carman.execise.Main"));
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
    // 点击状态栏的图标出现的提示信息设置
    notification.setLatestEventInfo(context,context.getResources().getString(R.string.app_notify_title),
    context.getResources().getString(R.string.app_notify), pendingIntent);
    manager.notify(1, notification); //这个函数中第一个参数代表identifier.如果要同时弹出多条通知,每个通知的这个参数必须不同。
                   否则,后面的会覆盖前面的通知。
  以上步骤就可以实现通知功能,但是还缺一个重启的监听。否则,手机一重启所设置的闹钟就失效了。
  四:重启恢复闹钟,通过一个广播来实现
  因为重启之后所设置的闹钟就失效了,必须通过该广播重新计算好下次响的时间nextNotifyTime,并再次调用步骤一的方法。
 public class BootReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
  // TODO Auto-generated method stub
    String action = intent.getAction();
    if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
    SharedPreferences alarmTime = context.getSharedPreferences("alarm_time", 0);
//存储数据的首选项
    long lastNotifyTime = alarmTime.getLong("lastNotifyTime",0);
//取得上次闹钟响的时间,也就是步骤二中存储的值
    long nextNotifyT
    if(lastNotifyTime == 0){
    long theFirstNotifyBeginTime = alarmTime.getLong("theFirstNotifyBeginTime",0); //若没弹出过通知,取得步骤一中存储的值
    nextNotifyTime = 7*24*60*60*1000 + theFirstNotifyBeginT
    }else{
    nextNotifyTime = 7*24*60*60*1000 + lastNotifyT
    if(nextNotifyTime &= System.currentTimeMillis()){
    NotifyUtil.setAlarmTime(context,System.currentTimeMillis());
    }else{
    NotifyUtil.setAlarmTime(context,nextNotifyTime); //再次设置为闹钟
  五:这些做好了之后调试还是通不过,因为需要在androidManifest中注册下广播的接收器才行。如下:
  步骤二的接收器,监听闹钟
&receiver android:name=".notifications.AlarmReceiver"&
    &intent-filter&
      &action android:name="android.alarm.demo.action" /&
  &/intent-filter&
  &/receiver&
    步骤四的接收器,监听重启
&receiver android:name=".notifications.BootReceiver"&
    &intent-filter&
      &action android:name="android.intent.action.BOOT_COMPLETED" /&
    &/intent-filter&
  &/receiver&   
  黄色字体部分为闹钟重启监听的相关代码。
相关资讯  — 
相关文档  — 
发布时间: 20:34:56
同类热门经验
39802次浏览
108072次浏览
27227次浏览
69413次浏览
36786次浏览
OPEN-OPEN, all rights reserved.}

我要回帖

更多关于 有没有安卓通用刷机包 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信