推送是现在应用中经常要用到的一个功能 不管是IM体系还是其他的 提醒/通知什么的 甚至是有些厌恶的广告……
极光推送做得一直还可以而且还是免费的,集成也相对来说比较简单。
(本文主要讲的是Android的集成,服务端的话主要是调用相关的极光Api,大部分功能需要两者协调才能走通)
登录官网 极光推送,注册开发者账号(这个账号需要记住的,如果忘掉,就没法看推送相关的后台信息了)
登陆控制台后在左侧添加应用
其中包名最好与你要集成的项目包名一致,否则可能会引起不可预知的问题。
PS:IOS的那边推送也可以加进来,不过除了统一统计推送数据也没啥意义了吧。什么?你说WinPhone?
AndroidManifest文件中的包名
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ysdemo.jpushdemo" //你的包名
android:versionCode="181"
android:versionName="1.8.1"
manifest文件很长,看着麻烦,但是其实Jpush做得真的很人性化,在这一步博主几乎没花什么力气。
Jpush官方文档有一些说明:
这里无论是从 example直接复制过去,还是下载sdk复制进去都可以。
其中so文件如果不需要适配多个CPU版本的话 只复制armeabi目录下的就可以了。
这里主要是 复制过去把包名替换掉,然后在最后将Key换成你刚刚注册所得的AppKey(不是Secret)
example的manifest中有一段这样的代码,替换其中的包名,也直接复制进自己的项目。
<receiver
android:name="com.example.jpushdemo.MyJpushReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTRATION" />
<action android:name="cn.jpush.android.intent.UNREGISTRATION" />
<action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" />
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" />
<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" />
<action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" />
<action android:name="cn.jpush.android.intent.CONNECTION" />
<category android:name="com.zhong.jplus.example" />
intent-filter>
receiver>
报错了?当然报错啦,去创建一个对应的MyJpushReceiver吧~
MyJpushReceiver.java
package com.yedemo.jpushdemo.receiver;
import org.json.JSONObject;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import cn.jpush.android.api.JPushInterface;
public class MyJpushReceiver extends BroadcastReceiver {
private static final String TAG = "JPush";
private SharedPreferenceUtil spu;
@Override
public void onReceive(final Context context, Intent intent) {
final Bundle bundle = intent.getExtras();
Log.d(TAG, "[MyJpushReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle));
if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {
String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID);
Log.d(TAG, "[MyJpushReceiver] 接收Registration Id : " + regId);
//send the Registration Id to your server...
} else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
Log.d(TAG, "[MyJpushReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));
//需要自定义通知展示
} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
Log.d(TAG, "[MyJpushReceiver] 接收到推送下来的通知");
int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);
Log.d(TAG, "[MyJpushReceiver] 接收到推送下来的通知的ID: " + notifactionId);
} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
Log.d(TAG, "[MyJpushReceiver] 用户点击打开了通知");
//这里可以写一些跳转到某界面的代码,用户点击后就会进行跳转
} else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) {
Log.d(TAG, "[MyJpushReceiver] 用户收到到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, "[MyJpushReceiver]" + intent.getAction() +" connected state change to "+connected);
} else {
Log.d(TAG, "[MyJpushReceiver] 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 {
sb.append("\nkey:" + key + ", value:" + bundle.getString(key));
}
}
return sb.toString();
}
}
其实这个文件example里面也有,你也可以把那个复制进去稍加改动。
Jpush建议在Application中进行初始化:
MyApplication.java
import android.app.Application;
import android.util.Log;
import cn.jpush.android.api.JPushInterface;
/**
* For developer startup JPush SDK
*
* 一般建议在自定义 Application 类里初始化。也可以在主 Activity 里。
*/
public class MyApplication extends Application {
private static final String TAG = "JPush";
@Override
public void onCreate() {
Log.d(TAG, "[ExampleApplication] onCreate");
super.onCreate();
JPushInterface.setDebugMode(true); // 设置开启日志,发布时请关闭日志
JPushInterface.init(this); // 初始化 JPush
}
}
到这里你的应用就可以接受到广播推送了。
但是请注意,只是广播推送。
然而个别推送需要向你自己的服务器提供别名Alias(可以用类似用户名/用户Id这样的)或者Jpush初始化时候获得的Registration ID(初始化后可以通过JPushInterface.getRegistrationID(context)
获取)。
但如果是这样的话,你得保证用户每次进入/登陆应用都进行设置别名从而能够正常地接受推送,所以往往需要一个JpushUtil来封装一些操作。
目前这个JpushUtil呢我写的也不是很完善,只是在原来基础上增添了一个设置别名的方法。你可以把其他代码也放进来。
public class JpushUtil {
// public static final String PREFS_NAME = "JPUSH_EXAMPLE";
// public static final String PREFS_DAYS = "JPUSH_EXAMPLE_DAYS";
// public static final String PREFS_START_TIME = "PREFS_START_TIME";
// public static final String PREFS_END_TIME = "PREFS_END_TIME";
public static final String KEY_APP_KEY = "JPUSH_APPKEY";
public static final String TAG = JpushUtil.class.getName().toString();
public static boolean isEmpty(String s) {
if (null == s)
return true;
if (s.length() == 0)
return true;
if (s.trim().length() == 0)
return true;
return false;
}
// 校验Tag Alias 只能是数字,英文字母和中文
public static boolean isValidTagAndAlias(String s) {
Pattern p = Pattern.compile("^[\u4E00-\u9FA50-9a-zA-Z_-]{0,}$");
Matcher m = p.matcher(s);
return m.matches();
}
// 取得AppKey
public static String getAppKey(Context context) {
Bundle metaData = null;
String appKey = null;
try {
ApplicationInfo ai = context.getPackageManager().getApplicationInfo(
context.getPackageName(), PackageManager.GET_META_DATA);
if (null != ai)
metaData = ai.metaData;
if (null != metaData) {
appKey = metaData.getString(KEY_APP_KEY);
if ((null == appKey) || appKey.length() != 24) {
appKey = null;
}
}
} catch (NameNotFoundException e) {
}
return appKey;
}
// 取得版本号
public static String GetVersion(Context context) {
try {
PackageInfo manager = context.getPackageManager().getPackageInfo(
context.getPackageName(), 0);
return manager.versionName;
} catch (NameNotFoundException e) {
return "Unknown";
}
}
public static void showToast(final String toast, final Context context)
{
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(context, toast, Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start();
}
public static boolean isConnected(Context context) {
ConnectivityManager conn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = conn.getActiveNetworkInfo();
return (info != null && info.isConnected());
}
public static String getImei(Context context, String imei) {
try {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
imei = telephonyManager.getDeviceId();
} catch (Exception e) {
Log.e(JpushUtil.class.getSimpleName(), e.getMessage());
}
return imei;
}
/* 以上内容example中有,以下内容为本人添加 */
public static TagAliasCallback getCallBack(final Context context){
return new TagAliasCallback() {
public void gotResult(int code,final String alias, Set tags) {
String logs ;
switch (code) {
case 0:
logs = "Set tag and alias success" + alias;
SharedPreferenceUtil spu = SharedPreferenceUtil.getInstance(context);
spu.save("jpushAlias", alias);
spu.save("jpushAliasLogin", true);
Log.i(TAG, logs);
break;
case 6002:
logs = "Failed to set alias and tags due to timeout. Try again after 60s.";
Log.i(TAG, logs);
if (JpushUtil.isConnected(context)) {
new Handler().postDelayed(new Runnable() {
public void run() {
JPushInterface.setAliasAndTags(context, alias, null, getCallBack(context));
}
}, 1000 * 60);
} else {
Log.i(TAG, "No network");
}
break;
default:
logs = "Failed with errorCode = " + code;
Log.e(TAG, logs);
}
// JpushUtil.showToast(logs, context);
}
};
}
//设置别名
public static void setAlias(Context context,String alias) {
if (!SharedPreferenceUtil.getInstance(context).loadStrPrefer("jpushAlias").equals(alias)
&&!SharedPreferenceUtil.getInstance(context).loadBooleanPrefer("jpushAliasLogin")) {
JPushInterface.setAliasAndTags(context, alias+"", null, JpushUtil.getCallBack(context));
}else {
Log.i(TAG,"alias has been set as "+alias);
}
}
//如果停止了推送服务并允许推送,开启
public static void resetPushState(Context context) {
SharedPreferenceUtil spu = SharedPreferenceUtil.getInstance(context);
if (JPushInterface.isPushStopped(context) && !spu.loadBooleanPrefer("jpushSetUp")) {
JPushInterface.resumePush(context);
}else if (spu.loadBooleanPrefer("jpushSetUp")) {
JPushInterface.stopPush(context);
}
}
}
其中SharedPreferenceUtil 这个单例类主要是封装了一些对SharedPreference的操作,如果你应用中没有的话,你可以取一个SharedPreference出来进行操作。
本文没有demo,一切API调用可参考下载下来的push-example这个例子。遇到其他问题可以留言提问。
总体来说,极光还算是简单易用的第三方推送。