博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JPush极光推送的原理与简单demo的实现会遇到的问题
阅读量:5948 次
发布时间:2019-06-19

本文共 6203 字,大约阅读时间需要 20 分钟。

hot3.png

相信开发者们一定不陌生JPush极光推送,像QQ、微信的推送机制,QQ采用的是APNS推送服务,微信则采用google的GCM推送机制,很 多人都说APNS是一个死流氓服务,我也没去了解,而GCM有点像IOS自带的推送,有待了解。很多项目做一些通讯功能,大部分人都会选择JPush极光 推送,因为用起来简单,代码量也少,JPush官网上的开发文档也写的相当清楚,一些步骤也清晰明了。今天在这边主要就是讲一下推送的原理,以及demo 测试中会遇到的问题,这也是移植到项目中易出错的地方。

极光推送的功能:主动 即时的向用户发起交互,可以发送聊天信息等;

——作用:通过向精准的目标用户推送有价值的消息,可以提供用户的忠诚度,提高留存率。

(1)推送方式

——发送通知:推送的文本内容,展示在通知栏上面;
——自定义消息:推送自定义消息,给用户自行处理;
——富媒体:推送的是HTML网页内容。

(2)推送目标

——广播推送:向所有用户发送广播信息;
——标签推送 Tag:根据用户设置自定义的标签分组,向某一组推送消息;
——别名推送 Alias:客户端绑定用户自定义的用户别名,向单个用户推送消息。

(3)用户分群

——用户分群:可以根据JPush提供的多条件组合,对用户进行群组划分,实现实时筛选推送。

(4)推送历史

——推送历史:通过WEB或者API发出的推送,都可以在推送历史记录中查询到,并可以实时显示推送结果数据。

推送框架

——推送的数据源:自己开发的服务器端或者使用极光推送官网的WEB后台;

——JPush API:部署在服务器端,开发者的服务器端发起推送时,将数据传到JPush API中,然后向下传递;
——建立长链接:集成JPush的SDK客户端启动后会建立一个到JPush Cloud的长链接,提供App永远在线的能力();
——原理图:
原理图

客户端原理

IP地址的分配原理

——IP地址有限:IPv4的IP地址数量有限,运营商要动态的为手机分配IP地址,这些IP地址都是运营商的内网IP;
——网络地址转换(NAT):全称Network Address Translation,网关维护一个外网IP地址,与内网的IP地址对应;
——外网IP不固定:由于运营商持有的外网IP数量有限,需要动态的为分配给接入运营商的用户,因此在手机一段时间没有数据传输时会将该手机分配的外网IP地址收回,分配给其他用户;
——解决方案:Android手机端想要保持长链接,首先外网IP地址不能变,不能让运营商收回这个IP地址。

Android手机端实现方案

——心跳:为了长时间保持外网IP,需要客户端定期发送心跳给运营商,以便刷新NAT列表;
——Timer定时方法:该类计划循环执行定时任务,但是使用该类会使CPU保持唤醒状态,比较费电。
——AlarmManager定时方法:该类封装了Android手机的RTC硬件时钟模块,可以在CPU休眠时正常运行,保持任务执行时再唤醒CPU,这样做到了电量节省。

简单demo容易出错的地方

·Appcation中初始化JPush
——JPushInterface.init(this); // 初始化 JPush
·启动的主程序里面一定要复写两个生命周期:

@Override    protected void onPause() {        isForeground = false;        super.onPause();        JPushInterface.onPause(MainActivity.this);    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
@Override    protected void onResume() {        isForeground = true;        super.onResume();        JPushInterface.onResume(MainActivity.this);    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意:如果主程序里面的Activity继承的是InstrumentedActivity,则不需要写 JPushInterface.onResume(MainActivity.this);我的MainActivity继承的是 FragmentActivity,所以加上了这句。

这是我的demo代码,贴出来大家看的比较清晰些:

package com.lai.jpushdemo;import android.os.Bundle;import android.os.Handler;import android.support.v4.app.FragmentActivity;import android.text.TextUtils;import android.util.Log;import android.view.KeyEvent;import android.widget.Toast;import com.ms.stock.R;import java.util.LinkedHashSet;import java.util.Set;import cn.jpush.android.api.JPushInterface;import cn.jpush.android.api.TagAliasCallback;public class MainActivity extends FragmentActivity{    private static final String TAG = "JPush";    @Override    public void onCreate(Bundle icicle) {        super.onCreate(icicle);        setTag("abc");    }    /**     * 设置tags     */    private void setTag(String tag){        // 检查 tag 的有效性        if (TextUtils.isEmpty(tag)) {            Toast.makeText(MainActivity.this,R.string.error_tag_empty, Toast.LENGTH_SHORT).show();            return;        }        // ","隔开的多个 转换成 Set        String[] sArray = tag.split(",");        Set
tagSet = new LinkedHashSet
(); for (String sTagItme : sArray) { if (!ExampleUtil.isValidTagAndAlias(sTagItme)) { Toast.makeText(MainActivity.this,R.string.error_tag_gs_empty, Toast.LENGTH_SHORT).show(); return; } tagSet.add(sTagItme); } //调用JPush API设置Tag mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_TAGS, tagSet)); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK){ finish(); } return super.onKeyDown(keyCode, event); } private final TagAliasCallback mTagsCallback = new TagAliasCallback() { @Override public void gotResult(int code, String alias, Set
tags) { String logs ; switch (code) { case 0: logs = "设置别名和标签成功!"; Log.i(TAG, logs); break; case 6002: logs = "设置超时,60s后重试!"; Log.i(TAG, logs); if (ExampleUtil.isConnected(getApplicationContext())) { mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SET_TAGS, tags), 1000 * 60); } else { Log.i(TAG, "没有连接网络"); } break; default: logs = "失败代码 = " + code; Log.e(TAG, logs); } ExampleUtil.showToast(logs, getApplicationContext()); } }; private static final int MSG_SET_TAGS = 1002; private final Handler mHandler = new Handler() { @Override public void handleMessage(android.os.Message msg) { super.handleMessage(msg); switch (msg.what) { case MSG_SET_TAGS: Log.d(TAG, "在handler里面设置tags"); JPushInterface.setAliasAndTags(getApplicationContext(), null, (Set
) msg.obj, mTagsCallback); break; default: Log.i(TAG, "handler没有内容 - " + msg.what); } } }; public static boolean isForeground = false; @Override protected void onResume() { isForeground = true; super.onResume(); JPushInterface.onResume(MainActivity.this); } @Override protected void onPause() { isForeground = false; super.onPause(); JPushInterface.onPause(MainActivity.this); }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134

这里设置的Tag值是写死的(我项目中只用到Tag),写成动态的话,后面大家可以写到Appcation里面。

·别忘记添加jar包和.so文件

  如果博友用eclipse开发的话,直接把jar和.so文件添加到libs目录中即可,如果用的是android studio,则需要把.so文件单独放进jniLibs文件夹中(注意:studio新建的文件夹自带是jni,这边的jniLibs目录是需要手动去 重命名文件夹,经测试,如果是jni文件夹,项目会异常,找不到文件,所以必须是jniLibs)。

·AndroidManifest.xml

  *权限(uses-permission)一定要放在appcation前面。
这点大家注意下,昨天因为这个问题折腾了好久,我的习惯就是先写一个demo,然后再移植到自己的项目中,这样做起来比较快,也不会太乱。恰恰这个问题让我非常痛苦,最后看了日志才发现的,值得大家注意。

这个是我修改过得demo,只需要在AndroidManifest.xml中修改包名,以及包名的Appkey值即可,大家也可以去官网上下载。

转载于:https://my.oschina.net/u/588516/blog/740331

你可能感兴趣的文章
python练习笔记——丑数的计算
查看>>
OpenCV + python 实现人脸检测(基于照片和视频进行检测)
查看>>
XSS 前端防火墙 —— 天衣无缝的防护
查看>>
Node.js umei图片批量下载Node.js爬虫1.00
查看>>
客户端拖动控件封装(让拖动变得更简单)
查看>>
linux下IPTABLES配置详解
查看>>
Sharepoint学习笔记—习题系列--70-576习题解析 -(Q131-Q134)
查看>>
iOS边练边学--iOS中的(ARC下)单粒模式(GCD实现)
查看>>
php get_magic_quotes_gpc()函数用法介绍
查看>>
SQL to Java code for Elasticsearch
查看>>
Java RMI之HelloWorld程序以及相关的安全管理器的知识
查看>>
FlatBuffers
查看>>
美团HD(5)-选择城市
查看>>
$.when()方法监控ajax请求获取到的数据与普通ajax请求回调获取到的数据的不同
查看>>
pthread_mutex_t
查看>>
LR11.0 下载及破解
查看>>
Java基础-绘图技术
查看>>
又转出61.8万个ETH,EOS不疯狂不成魔
查看>>
程序员面试IT公司的33个小贴士
查看>>
多款C系列手机亮相三星中国论坛,更加注重中国用户体验
查看>>