1:为什么要用推送?
作用 :通常在程序没有启动的时候,可以在后台收到服务器主动给客户端发送的信息
对于用户:及时提醒用户关注的内容;例如大家都有qq ,只要qq一响了,就会看一下。或者及时通知软件的动态,节假日的软件的营销 。最终为了让用户能够持续的经常性的使用软件
软件上面有一个红点,忍不住要点.国内设计
有一些软件,可能第一安装的时候,看了不怎么样,但是如果发送一个推送"护士走光了",然后用户点击了。
每天给用户推送,死缠烂打。
用户慢慢的习惯了之后,可能就等你的通知。例如微博,就等微博发推送
简单的一句话就是,为了引起用户的注意.经常使用软件.
2:常见名词:PushNotification,推送通知。
GCM(Google Cloud Message)在国外没有自己推送服务器的,都是直接使用GCM的。软件面向世界的时候考虑GCM.
APNs(Apple Push Notifcation service)3:有哪些推送的服务:百度云推送(需要做出来), 极光推送JPush,新浪云平台,阿里云,友盟, 小米推送
这里介绍极光推送。 https://www.jpush.cn/
kodulf.cj
4:推送的网络结构:
5:https://www.jpush.cn/common/products
极光推送
极光推送,使得开发者可以即时地向其应用程序的用户推送通知或者消息,与用户保持互动,从而有效地提高留存率,提升用户体验。平台提供整合了Android推送、iOS推送的统一推送服务。
极光推送就和发送qq消息是一样的。其实底层就是socket的传送。例如发一个字节1代表启动,发一个字节2代表xxxx发一个字节4代表。。。。
标签:可以在情人节的时候,给所有的男性,今天你送花了吗?给所有的女性,今天你收到花了吗?
别名推送:京东里面,快递小哥到哪了。
产品特点
![多种推送方式](https://www.jpush.cn/res/v3/images/common/v4/product-push-feature-multi.png)
多种推送方式
Push Methods
通知:推送文本内容直接展示在用户的通知栏中。
自定义消息:推送自定义的消息内容透传给应用处理。
富媒体:推送预先编辑好的图文并茂的HTML页面内容。
![灵活推送精准推送](https://www.jpush.cn/res/v3/images/common/v4/product-push-feature-target.png)
灵活的推送目标
Push Targets
广播推送:向所有的注册用户发送一条广播消息。
标签推送:根据属性对用户设置标签分组,向群组用户发送。
别名推送:客户端绑定用户别名,向具体的单个用户推送。
![实时筛选实时推送](https://www.jpush.cn/res/v3/images/common/v4/product-push-feature-user.png)
用户分群
Segment
根据 JPush 提供的多条件组合进行用户群组划分,实时筛选实时推送。
![推送历史轻松查询](https://www.jpush.cn/res/v3/images/common/v4/product-push-feature-history.png)
推送历史
Message History
无论是通过Web发送的还是通过API发送的都可以在推送历史记录中查询。
![简单集成Android sdk、iOS sdk](https://www.jpush.cn/res/v3/images/common/v4/product-push-feature-done.png)
简单易集成
Easy Integration
网站后台:通过 JPush 网站后台完成推送以及查看历史、报表,无需技术要求。
发送与查询API:开放推送和结果查询的 RESTful API 供开发商可以灵活对接。
客户端SDK:简单集成Android, iOS SDK。
![推送报表与用户统计报表呈现推送的效果](https://www.jpush.cn/res/v3/images/common/v4/product-push-feature-stat.png)
统计与报表
Statistics and Reports
“推送报表”与“用户统计报表”呈现推送的效果和应用发展趋势。
PS: PhoneGap 是H5使用的推送。
+++++++++++++++++++++++++++++++++++++++++++++++++++++
3 分钟快速集成 JPush Android SDK
+++++++++++++++++++++++++++++++++++++++++++++++++++++
本文目的在于,指导新接触极光推送的开发者,在短短几分钟时间内把极光推送跑起来:
-
安装Demo客户端到手机
-
在Portal上推送通知
-
客户端收到推送并显示在状态栏pi
创建极光推送开发者帐号
要创建极光推送开发者帐号,请访问极光推送官方网站http://jpush.cn
Portal上创建应用
使用注册账号登陆,进入极光控制台后,点击“创建应用”按钮。创建帐号进入极光推送后,首先显示的是创建应用的界面。填上你的应用程序的名称,以及 Android包名这二顶就可以了。
下载应用Example
点击 ”下载应用Example “
你将下载到一个 .zip 压缩文件。解压后,即看到一个同名目录。这个目录下,是一个 Android 项目里的所有文件。
把Example(Android项目)导入 Eclipse 里
在你的 Eclipse 里,新建一个项目,把项目目录位置指向上步骤解压缩开的 Example目录。
运行 Example 这个应用
上步骤导入这个 Android 项目后,你就马上可以点击鼠标右键,把这个 Android 应用跑起来了。(如果你的Eclipse设置的是自动编译的话)
如果你的 Android 手机接在电脑上了,则这个 JPush Example 应用就可以安装上,并运行起来了。
做下一步动作之前,请确保你的手机上的网络是可用的。
Portal上推送通知
手机上收到通知
在上述步骤安装 JPush Example 的手机上,你就可以收到推送的通知了。
Portal上推送消息
具体详情请查看控制台使用
在LogCat中查看收到的自定义消息
自定义消息可以在LogCat日志中查看,开发者根据自己需要做展现处理,JPush不做干预.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
自定义集成
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
注意这里的Master Secret修改了,之前可以推送的都不可以推送了。
如果有免费版和收费版。多渠道,需要在极光推送上创建不同的应用与之对应
可以参考:快速集成:http://docs.jpush.io/guideline/android_guide/
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
可以直接将我们的应用的example 下载下来。
导入到android studio 中:
1:将lib 下面的jpush-android-2.0.6.jar拷贝到lib文件夹下面,右键 点击 add as library
2:在main 下面新建一个文件家jniLibs 把 so的目录复制过去。
3:res 下面的所有的文件夹拷贝过来。拷贝的时候有两个选项
选择1:跳过strings,把string修改为jpush_strings.xml,将values_zh 下面的string也修改一下。然后把一个app_name 删除了。
选择2:其实就是把之前的strings文件删除就好了
4:把com复制到目录下
5:清单文件复制一下:直接复制一些内容,
清单文件中application 内部指定了name 用于初始化极光。类似于百度地图,
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
一些详解:
qq 现在是有一个功能,在锁屏的状态输入,其实是截屏了,然后作为背景,然后其实是qq的界面。
推送不用启动软件就可以收到,就是因为有了service,这个是推送的核心逐渐
<!-- Required SDK核心功能,用于后台下载的资源信息,当然了也是可以做一些更新和操作。
-->
<service android:name="cn.jpush.android.service.DownloadService" android:enabled="true" android:exported="false" />
- <!-- 可配置android:process参数将PushService放在其他进程中 ,核心收推送的。后台接收推送信息的服务,肯定是在后台长时间爱你的
-->
- <service android:name="cn.jpush.android.service .PushService" android:enabled="true" android:exported="false">
- <intent-filter>
<action android:name="cn.jpush.android.intent.REGISTER" />
<action android:name="cn.jpush.android.intent.REPORT" />
<action android:name="cn.jpush.android.intent.PushService" />
<action android:name="cn.jpush.android.intent.PUSH_TIME" />
</intent-filter>
</service>
如果手机上面有三个应用都用了极光推送,所有的发通知只用这一个服务就行了。
<!-- since 1.8.0 option 可选项。用于同一设备中不同应用的JPush服务相互拉起的功能。
-->
- <!-- 若不启用该功能可删除该组件,将不拉起其他应用也不能被其他应用拉起
-->
- <service android:name="cn.jpush.android.service. DaemonService" android:enabled="true" android:exported="true">
- <intent-filter>
<action android:name="cn.jpush.android.intent.DaemonService" />
<category android:name="com.example.kodulf.jpushshow" />
</intent-filter>
</service>
两种推送的方式:
1:服务在后台接收到了push以后,会发送一个广播。会有一个广播接受者。来专门接收这个广播。
2:服务在后台接收到push之后,直接发送一个通知。(极光推送中简单的广播是service 直接发的通知。)
极光推送中简单的广播是service 直接发的通知。
如果是复杂的广播是要service 发送后brodcastReceiver再来发送通知
极光推送就和发送qq消息是一样的。其实底层就是socket的传送。
默认的情况下手机系统会检测我们网络连接的状况。如果在一定时间之内,没有任何的数据传输,系统就会强制关闭这个连接;
推送那么要求客户端每隔一段事件发送一个非常少的心跳数据,用来告诉系统,当前连接还是有效的,来保持推送的连接,可以及时的接收;
所谓的心跳连接,客户端和服务器端,始终连接,只不过发送的信息非常小,一个字节。
++++++++
PS: 手机没有网络的情况下,如果程序写的烂,每次连接都建立信的连接,这样手机就非常的卡了。之前的linux 有这样的攻击,因为linus 65535个进程,让它沾满了就宕机 了.
下面是极光推送的一些日志:
[PushService] Send heart beat
02-19 11:09:33.594 22744-23556/com.example.kodulf.jpushshow D/JPush: [NetworkingClient] Received bytes - len:31, connection:-1190892944, pkg:com.example.kodulf.jpushshow
02-19 11:09:33.594 22744-23556/com.example.kodulf.jpushshow D/JPush: [NetworkingClient] Action - receivedCommand - cmd: 19
02-19 11:09:33.594 22744-23556/com.example.kodulf.jpushshow D/JPush: [NetworkingClient] Network listening...
02-19 11:09:33.594 22744-22744/com.example.kodulf.jpushshow D/JPush: [PushService] Action - onHeartbeatSucceed
找到MyRecevier
/*** 自定义接收器
*
* 如果不定义这个 Receiver,则:
* 1) 默认用户会打开主界面
* 2) 接收不到自定义消息
*/
//TODO 当手机和极光推送服务器进行了注册之后,会给手机分配一个id
//TODO 这个iD 是存储在极光推送的服务器数据库中,用来给手机发送消息的
//TODO !!! 客户端自己的服务器上面,也必须要保存用户帐号和注册手机设备id的关系,
//TODO 客户端在收到ID的时候,需要将当前ID与当前登录用户发送给自己的服务器。
//TODO 可以通过API获取,或者 注册成功获取;更推荐注册成功获取。
package com.example.jpushdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.example.kodulf.jpushshow.NewsDetailActivity;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Iterator;
import cn.jpush.android.api.JPushInterface;
/**
* 自定义接收器
*
* 如果不定义这个 Receiver,则:
* 1) 默认用户会打开主界面
* 2) 接收不到自定义消息
*/
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "JPush";
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Log.d(TAG, "[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle));
//TODO 当手机和极光推送服务器进行了注册之后,会给手机分配一个id
//TODO 这个iD 是存储在极光推送的服务器数据库中,用来给手机发送消息的
//TODO !!! 客户端自己的服务器上面,也必须要保存用户帐号和注册手机设备id的关系,
//TODO 客户端在收到ID的时候,需要将当前ID与当前登录用户发送给自己的服务器。
//TODO 可以通过API获取,或者 注册成功获取;更推荐注册成功获取。
if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {
String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID);
Log.d(TAG, "[MyReceiver] 接收Registration Id : " + regId);
//send the Registration Id to your server...
//TODO: 对应自定义消息这个功能,接收服务器传过来的,不用显示在通知栏上的消息;例如手机丢了,我想要删除消息
//TODO:内部通常包含JSON字符串,可以实现任意功能的处理。处理的部分,就在当前的方法上
//TODO: 例如通知软件自动更新,软件界面内容的动态更新,
} else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
Log.d(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));
processCustomMessage(context, bundle);
//TODO :当普通的通知收到之后,已经显示在状态烂的时候,会有一个广播
} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
Log.d(TAG, "[MyReceiver] 接收到推送下来的通知");
int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);
Log.d(TAG, "[MyReceiver] 接收到推送下来的通知的ID: " + notifactionId);
//TODO 当普通的推送通知,收到,显示状态栏通知后,用户点击了这个通知。
//TODO 并不是真正的启动activity,而是发送当前的广播。
//TODO 当前这个广播中包含了通知的莪所有数据和信息,就可以实现类似新闻点击查看详情
} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
Log.d(TAG, "[MyReceiver] 用户点击打开了通知");
//打开自定义的Activity
//TODO 相当于打开通知要显示的内容。
// Intent i = new Intent(context, TestActivity.class);
//TODO 新建的activity
Intent i = new Intent(context, NewsDetailActivity.class);
//bundle内部存放的就是推送通知的各种数据,也包括自定义的JSON字段。
i.putExtras(bundle);
//i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP );
context.startActivity(i);
} else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) {
Log.d(TAG, "[MyReceiver] 用户收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA));
//在这里根据 JPushInterface.EXTRA_EXTRA 的内容处理代码,比如打开新的Activity, 打开一个网页等..
} else if(JPushInterface.ACTION_CONNECTION_CHANGE.equals(intent.getAction())) {
boolean connected = intent.getBooleanExtra(JPushInterface.EXTRA_CONNECTION_CHANGE, false);
Log.w(TAG, "[MyReceiver]" + intent.getAction() +" connected state change to "+connected);
} else {
Log.d(TAG, "[MyReceiver] Unhandled intent - " + intent.getAction());
}
}
// 打印所有的 intent extra 数据
private static String printBundle(Bundle bundle) {
StringBuilder sb = new StringBuilder();
for (String key : bundle.keySet()) {
if (key.equals(JPushInterface.EXTRA_NOTIFICATION_ID)) {
sb.append("\nkey:" + key + ", value:" + bundle.getInt(key));
}else if(key.equals(JPushInterface.EXTRA_CONNECTION_CHANGE)){
sb.append("\nkey:" + key + ", value:" + bundle.getBoolean(key));
} else if (key.equals(JPushInterface.EXTRA_EXTRA)) {
if (bundle.getString(JPushInterface.EXTRA_EXTRA).isEmpty()) {
Log.i(TAG, "This message has no Extra data");
continue;
}
try {
JSONObject json = new JSONObject(bundle.getString(JPushInterface.EXTRA_EXTRA));
Iterator<String> it = json.keys();
while (it.hasNext()) {
String myKey = it.next().toString();
sb.append("\nkey:" + key + ", value: [" +
myKey + " - " +json.optString(myKey) + "]");
}
} catch (JSONException e) {
Log.e(TAG, "Get message extra JSON error!");
}
} else {
sb.append("\nkey:" + key + ", value:" + bundle.getString(key));
}
}
return sb.toString();
}
//send msg to MainActivity
private void processCustomMessage(Context context, Bundle bundle) {
if (MainActivity.isForeground) {
String message = bundle.getString(JPushInterface.EXTRA_MESSAGE);
String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
Intent msgIntent = new Intent(MainActivity.MESSAGE_RECEIVED_ACTION);
msgIntent.putExtra(MainActivity.KEY_MESSAGE, message);
if (!ExampleUtil.isEmpty(extras)) {
try {
JSONObject extraJson = new JSONObject(extras);
if (null != extraJson && extraJson.length() > 0) {
msgIntent.putExtra(MainActivity.KEY_EXTRAS, extras);
}
} catch (JSONException e) {
}
}
context.sendBroadcast(msgIntent);
}
}
}
package com.example.kodulf.jpushshow;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//点击打开通知详情的功能,通知详情使用Bundle来传过来的。
Bundle extras = getIntent().getExtras();
if(extras !=null){
Set<String> keys = extras.keySet();
for(String key:keys){
Object value = extras.get(key);
Log.d("Kodulf","extras key "+key+" value "+value);
}
}
}
}
点击“自定义消息”
手机端可以设置-》高级设置:设置tag 和alias以后
在MainActivity 中的onResume中做一个事情:
//设置
JPushInterface.setTags
@Override
protected void onResume() {
isForeground = true;
super.onResume();
//TODO 设置标签TAG 的操作:用于给推送服务器创建不同的标签;
//TODO 给同一个应用程序制定的标签发送消息,那么这些设置过标签的手机都可以收到
//TODO 业务,用户的类型区分和共同特征的管理
Set<String> tags = new TreeSet<String>();
tags.add("中年人");
tags.add("80后");
tags.add("男人");
JPushInterface.setTags(this,tags,this);
}
@Override
public void gotResult(int i, String s, Set<String> set) {
Toast.makeText(this,"Success",Toast.LENGTH_LONG).show();
}
环信使用的是xmlpp的协议