Android(安卓)Jpush的集成
推送是现在应用中经常要用到的一个功能 不管是IM体系还是其他的 提醒/通知什么的 甚至是有些厌恶的广告……
极光推送做得一直还可以而且还是免费的,集成也相对来说比较简单。
(本文主要讲的是Android的集成,服务端的话主要是调用相关的极光Api,大部分功能需要两者协调才能走通)
主要步骤
- 注册开发者账号
- 添加应用,下载example
- 配置资源和manifest
- 自定义Receiver
- 初始化代码
- 封装JpushUtil
注册开发者账号
登录官网 极光推送,注册开发者账号(这个账号需要记住的,如果忘掉,就没法看推送相关的后台信息了)
添加应用
登陆控制台后在左侧添加应用
其中包名最好与你要集成的项目包名一致,否则可能会引起不可预知的问题。
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
manifest文件很长,看着麻烦,但是其实Jpush做得真的很人性化,在这一步博主几乎没花什么力气。
Jpush官方文档有一些说明:
这里无论是从 example直接复制过去,还是下载sdk复制进去都可以。
其中so文件如果不需要适配多个CPU版本的话 只复制armeabi目录下的就可以了。
这里主要是 复制过去把包名替换掉,然后在最后将Key换成你刚刚注册所得的AppKey(不是Secret)
自定义Receiver
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(可选)
目前这个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这个例子。遇到其他问题可以留言提问。
总体来说,极光还算是简单易用的第三方推送。
更多相关文章
- 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
- activity的生命周期——第一行代码阅读笔记
- 换一种方式理解 Android协程
- 如何正确的在 Android(安卓)上使用协程 ?
- Android(安卓)LitePal的简单使用
- WeakReference在android中的使用场景
- Android(安卓)APK签名对比及说明
- Android混淆代码proguard,内存溢出
- Android小项目之二 代码的组织结构