本文简介:本文前篇,可以帮助朋友们快速集成极光推送。本文后篇,是我自己项目实践的一些总结和心得,应该对读者们还是很有参考价值的,相信读完这篇文章,你会对极光推送有更加深入的理解,而不仅仅只是会集成而已。总之呢,集成第三方SDK,都不是很难的事情,仔细阅读文档,一步步来,遇到Bug,慢慢解决就行,实在解决不了,可以问问客服小哥哥或者小姐姐,重要的是,你得有着解决它的决心和耐心。

《一》JPush SDK的集成

简要介绍:
极光推送(JPush)是一个端到端的推送服务,使得服务器端消息能够及时地推送到终端用户手机上,让开发者积极地保持与用户的连接,从而提高用户活跃度、提高应用的留存率。

开发者集成 JPush Android SDK 到其应用里,JPush Android SDK 创建到 JPush Cloud 的长连接,为 App 提供永远在线的能力。 当开发者想要及时地推送消息到达 App 时,只需要调用 JPush API 推送,或者使用其他方便的智能推送工具,即可轻松与用户交流。
JPush Android SDK 是作为 Android Service 长期运行在后台的,从而创建并保持长连接,保持永远在线的能力。

假设你已经注册了极光的账号,登录进来了。点击立即体验,创建自己的应用。

App端集成需要用到的AppKey。

添加集成代码,此处使用jcenter的方式集成。
一、确认android studio的 Project 根目录的主 gradle 中配置了jcenter支持。(新建project默认配置就支持)

buildscript {repositories {jcenter()}......
}allprojets {repositories {jcenter()}
}

二、在 module 的 gradle 中添加依赖和AndroidManifest的替换变量。

android {......defaultConfig {applicationId "com.xxx.xxx" //JPush上注册的包名.......ndk {//选择要添加的对应cpu类型的.so库。abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a'// 还可以添加 'x86', 'x86_64', 'mips', 'mips64'}manifestPlaceholders = [JPUSH_PKGNAME : applicationId,JPUSH_APPKEY : "你的appkey", //JPush上注册的包名对应的appkey.JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.]......}......
}dependencies {......compile 'cn.jiguang.sdk:jpush:3.1.1'  // 此处以JPush 3.1.1 版本为例。compile 'cn.jiguang.sdk:jcore:1.1.9'  // 此处以JCore 1.1.9 版本为例。......
}

三、AndroidManifest.xml中添加

  <!--Jpush配置 所需权限start--><!-- Required --><permissionandroid:name="你的应用包名.permission.JPUSH_MESSAGE"android:protectionLevel="signature" /><!-- Required  一些系统要求的权限,如访问网络等--><uses-permission android:name="你的应用包名.permission.JPUSH_MESSAGE" /><uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" /><!--<uses-permission android:name="android.permission.INTERNET" />--><uses-permission android:name="android.permission.WAKE_LOCK" /><!--<uses-permission android:name="android.permission.READ_PHONE_STATE" />--><!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />--><!--<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />--><uses-permission android:name="android.permission.WRITE_SETTINGS" /><!--<uses-permission android:name="android.permission.VIBRATE" />--><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><!--<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />--><!--<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />--><!-- Optional for location --><uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 用于开启 debug 版本的应用在6.0 系统上 层叠窗口权限 --><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><!--<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />--><!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />--><uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /><!--<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />--><!--<uses-permission android:name="android.permission.GET_TASKS" />--><!--Jpush配置 所需权限end--><!--Jpush配置 start--><application<!-- Rich push 核心功能 since 2.0.6--><activityandroid:name="cn.jpush.android.ui.PopWinActivity"android:theme="@style/MyDialogStyle"android:exported="false"></activity><!-- Required SDK核心功能--><activityandroid:name="cn.jpush.android.ui.PushActivity"android:configChanges="orientation|keyboardHidden"android:theme="@android:style/Theme.NoTitleBar"android:exported="false"><intent-filter><action android:name="cn.jpush.android.ui.PushActivity" /><category android:name="android.intent.category.DEFAULT" /><category android:name="你的应用包名" /></intent-filter></activity><!-- Required SDK 核心功能--><!-- 可配置android:process参数将PushService放在其他进程中 --><serviceandroid: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 3.0.9 Required SDK 核心功能--><providerandroid:authorities="你的应用包名.DataProvider"android:name="cn.jpush.android.service.DataProvider"android:exported="false"/><!-- since 1.8.0 option 可选项。用于同一设备中不同应用的JPush服务相互拉起的功能。 --><!-- 若不启用该功能可删除该组件,将不拉起其他应用也不能被其他应用拉起 --><serviceandroid: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="你的应用包名" /></intent-filter></service><!-- since 3.1.0 Required SDK 核心功能--><providerandroid:authorities="你的应用包名.DownloadProvider"android:name="cn.jpush.android.service.DownloadProvider"android:exported="true"/><!-- Required SDK核心功能--><receiverandroid:name="cn.jpush.android.service.PushReceiver"android:enabled="true"android:exported="false"><intent-filter android:priority="1000"><action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" />   <!--Required  显示通知栏 --><category android:name="你的应用包名" /></intent-filter><intent-filter><action android:name="android.intent.action.USER_PRESENT" /><action android:name="android.net.conn.CONNECTIVITY_CHANGE" /></intent-filter><!-- Optional --><intent-filter><action android:name="android.intent.action.PACKAGE_ADDED" /><action android:name="android.intent.action.PACKAGE_REMOVED" /><data android:scheme="package" /></intent-filter></receiver><!-- Required SDK核心功能--><receiver android:name="cn.jpush.android.service.AlarmReceiver" android:exported="false"/><!-- User defined.  For test only  MyReceiver为用户自定义的广播接收器--><receiverandroid:name=".util.MyReceiver"android:exported="false"android:enabled="true"><intent-filter><action android:name="cn.jpush.android.intent.REGISTRATION" /> <!--Required  用户注册SDK的intent--><action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!--Required  用户接收SDK消息的intent--><action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!--Required  用户接收SDK通知栏信息的intent--><action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!--Required  用户打开自定义通知栏的intent--><action android:name="cn.jpush.android.intent.CONNECTION" /><!-- 接收网络变化 连接/断开 since 1.6.3 --><category android:name="你的应用包名" /></intent-filter></receiver><!-- Required  . Enable it you can get statistics data with channel --><meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/><meta-data android:name="JPUSH_APPKEY" android:value="应用的Appkey" /> <!--  </>值来自开发者平台取得的AppKey--></application><!--Jpush配置 end-->

四、自定义一个广播接收器MyReceiver(此处直接使用官方Demo中的MyReceiver)

/*** 自定义接收器* * 如果不定义这个 Receiver,则:* 1) 默认用户会打开主界面* 2) 接收不到自定义消息*/
public class MyReceiver extends BroadcastReceiver {private static final String TAG = "JIGUANG-Example";@Overridepublic void onReceive(Context context, Intent intent) {try {Bundle bundle = intent.getExtras();Logger.d(TAG, "[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle));if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID);Logger.d(TAG, "[MyReceiver] 接收Registration Id : " + regId);//send the Registration Id to your server...} else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {Logger.d(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));processCustomMessage(context, bundle);} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {Logger.d(TAG, "[MyReceiver] 接收到推送下来的通知");int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);Logger.d(TAG, "[MyReceiver] 接收到推送下来的通知的ID: " + notifactionId);} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {Logger.d(TAG, "[MyReceiver] 用户点击打开了通知");//打开自定义的ActivityIntent i = new Intent(context, TestActivity.class);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())) {Logger.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);Logger.w(TAG, "[MyReceiver]" + intent.getAction() +" connected state change to "+connected);} else {Logger.d(TAG, "[MyReceiver] Unhandled intent - " + intent.getAction());}} catch (Exception e){}}// 打印所有的 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 (TextUtils.isEmpty(bundle.getString(JPushInterface.EXTRA_EXTRA))) {Logger.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();sb.append("\nkey:" + key + ", value: [" +myKey + " - " +json.optString(myKey) + "]");}} catch (JSONException e) {Logger.e(TAG, "Get message extra JSON error!");}} else {sb.append("\nkey:" + key + ", value:" + bundle.getString(key));}}return sb.toString();}//send msg to MainActivityprivate 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 (extraJson.length() > 0) {msgIntent.putExtra(MainActivity.KEY_EXTRAS, extras);}} catch (JSONException e) {}}LocalBroadcastManager.getInstance(context).sendBroadcast(msgIntent);}}
}

五、在Application中的onCreate()方法中初始化极光推送

   // 初始化 JPushJPushInterface.init(this);//发布时关闭日志JPushInterface.setDebugMode(false);

六、最后不要忘了添加混淆代码哦!

请在工程的混淆文件proguard-rules.pro中添加以下配置:
-dontoptimize
-dontpreverify-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; }-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }

七、通过极光官网控制台推送,测试推送结果。

《二》推送方式分析

使用场景分析:推送消息,无疑就是两种情形,一种是全部推送,这种方式简单,群发就行了,Portal与API都支持向指定的 appKey 群发消息。但是一般实际的业务需求,都不仅仅是群发,还需要针对某一个人或者某一群人进行推送。例如:给会员推送一些新的内容,此时就需要针对会员这一群特定的人,来进行推送。简单的说,就是需要把JPush的注册用户与开发者App用户绑定起来。JPush给了我们以下两种方式来实现。

1.RegistrationID方式实现点对点的精准推送(把绑定关系保存到开发者应用服务器中)

集成了 JPush SDK 的应用程序在第一次成功注册到 JPush 服务器时,JPush 服务器会以广播的形式发送RegistrationID到应用程序,给客户端返回一个唯一的该设备的标识 - RegistrationID。首次注册成功,自定义的MyReceiver中会收到一条广播。

如下图,会在MyReceiver中收到RegistrationID的值。只要极光推送第一次注册成功了,后期不会再发 RegistrationID 的广播了。RegistrationID 就会被保留在手机内,下次即使你是无网状态进入APP,你也可以获取到这个RegistrationID。有了这个标识,App 编程可以把这个 RegistrationID 保存到自己的应用服务器上,然后就可以根据 RegistrationID 来向设备推送消息或者通知。所以建议可以在你的Application和MyReceiver中都对这个RegistrationID进行赋值。然后根据项目的业务需要,将RegistrationID和用户标识的对应关系,上传自己的服务端。

public class MyApplication extends Application{public static String registrationID;@Overridepublic void onCreate() {// 初始化 JPushJPushInterface.init(this);registrationID = JPushInterface.getRegistrationID(this);Log.d("TAG", "接收Registration Id : " + registrationID);}
}

【注意】:
如果 App 不卸载,是直接覆盖安装,Android, iOS 上 RegistrationID 的值都不会变化。
如果 App 是卸载之后再次安装:Android 上 RegistrationID 基本不会变;
iOS 上如果启用了 IDFA 变化可能性不大,如果未启用 IDFA 则每次安装 RegistrationID 都会变;
参考: 极光推送设备唯一性标识RegistrationID

如果使用此种推送方式,你可能会遇到的问题:假设在一个设备中登录不同的账号,那此时上传给服务器的都是同一个RegistrationID,因为设备没有变化。那么可能出现:本来服务器是根据A用户找到它的RegistrationID进行推送,但是B用户也是在A用户登录的设备登录的,RegistrationID跟A的一样,这样就导致B用户收到了推送给A用户的推送内容。

需要谨记:

使用 RegistrationID 推送的关键于,App 开发者需要在开发 App 时,获取到这个 RegistrationID,保存到 App 业务服务器上去,并且与自己的用户标识对应起来。建议 App 开发者尽可能做这个保存动作。因为这是最精确地定位到设备的。(RegistrationID 的方式,相对而言比较麻烦一点,因为需要自己的App服务端维护RegistrationID和用户的对应关系。暂时我还没有使用这种方式,真正投入到线上的项目,只是测试环境下调试过。)
值得一读: 推送方式

2.别名与标签推送(把绑定关系保存到 JPush 服务器端)

别名推送也是一种实现点对点推送的方式,用于给某特定用户推送消息。
功能介绍:
①为安装了应用程序的用户,取个别名来标识。以后给该用户 Push 消息时,就可以用此别名来指定。
②每个用户只能指定一个别名。
③同一个应用程序内,对不同的用户,建议取不同的别名。这样,尽可能根据别名来唯一确定用户。
④系统不限定一个别名只能指定一个用户。如果一个别名被指定到了多个用户,当给指定这个别名发消息时,服务器端API会同时给这多个用户发送消息。

举例:在一个用户要登录的游戏中,可能设置别名为 userid。游戏运营时,发现该用户 3 天没有玩游戏了,则根据 userid 调用服务器端API发通知到客户端提醒用户。


别名设置:

需要和自己的服务端协商好别名的规则,例如下面的代码中,是将用户ID通过MD5加密,作为别名,设置保存到JPush服务器。当然你也可以使用其他的拼接规则,具体根据每个公司的项目需要设置即可,只要满足别名的命名限制就行: 命名长度限制为 40 字节。(判断长度需采用UTF-8编码)

深入理解各种推送方式可以参考: 推送方式

下面是一个JPush设置别名和标签的辅助类。

public class JPushHelper {private String TAG = "JPushHelper";/*** 设置别名与标签** @param UUID*/private void setAlias(String UUID) {if (null != UUID) {//恢复接收推送JPushInterface.resumePush(MyApplication.getInstance());JPushInterface.setAliasAndTags(MyApplication.getInstance(), UUID, null, mAliasCallback);}}public void setAlias() {if (MyApplication.isLogin) { //必须登录UserInfo userBean = ACT_Login.getLoginUser();if (null != userBean) {//根据具体业务需求,可以再拼接上其他相关字段//String alias = "";//StringBuilder stringBuffer = new StringBuilder();// stringBuffer.append(StringUtil.getString(userBean.user_id));Log.e(TAG, stringBuffer.toString());alias = MD5Util.string2MD5(userBean.user_id);//限制:alias 命名长度限制为 40 字节。(判断长度需采用UTF-8编码)Log.e(TAG, alias);setAlias("");setAlias(alias);}}}/*** 清除设置别名与标签,停止接收推送*/public void removeAlias() {JPushInterface.clearAllNotifications(MyApplication.getInstance());setAlias("");JPushInterface.stopPush(MyApplication.getInstance());}private final TagAliasCallback mAliasCallback = new TagAliasCallback() {@Overridepublic void gotResult(int code, String alias, Set<String> tags) {String logs;switch (code) {case 0:logs = "Set tag and alias success";Log.e(TAG, logs);break;case 6002:logs = "Failed to set alias and tags due to timeout. Try again after 60s.";// 延迟 60 秒来调用 Handler 设置别名mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SET_ALIAS, alias), 1000 * 6);Log.e(TAG, logs + AppDateUtil.getTimeStamp(System.currentTimeMillis(), AppDateUtil.MM_DD_HH_MM_SS));break;default:logs = "Failed with errorCode = " + code;Log.e(TAG, logs);}}};private static final int MSG_SET_ALIAS = 1001;private final Handler mHandler = new Handler() {@Overridepublic void handleMessage(android.os.Message msg) {super.handleMessage(msg);switch (msg.what) {case MSG_SET_ALIAS:Log.e(TAG, "Set alias in handler." + ((String) msg.obj));// 调用 JPush 接口来设置别名。JPushInterface.setAliasAndTags(MyApplication.getInstance(),(String) msg.obj,null,mAliasCallback);break;default:Log.e(TAG, "Unhandled msg - " + msg.what);}}};// 校验Tag Alias 只能是数字,英文字母和中文public static boolean isValidTagAndAlias(String s) {Pattern p = Pattern.compile("^[\u4E00-\u9FA50-9a-zA-Z_!@#$&*+=.|]+$");Matcher m = p.matcher(s);return m.matches();}
}

3.关于后端服务器设置别名还是前端设置别名:

说实在的,以前没有遇到过这个选择题,因为之前做的极光推送都是在我们客户端设置,不过最近调试JPush的时候后台说他设置别名,我突然就有点蒙了?不是一般都是前端设置吗???
于是有个疑问:如果是服务端设置别名,那服务端也没有经过客户端,那极光服务器咋通过别名来匹配用户进行点对点推送呀???我一下子有点想不通了。然后查了一下文档和相关博客,确实极光服务器也给后端服务提供设置别名的API,又问了一下后端开发,他是不是只是单单设置了别名,还是在设备ID上也有做了处理,因为没有映射关系,极光服务器也不可能找到对应的用户进行推送呀。果不其然,他是在RegistrationID上设置的别名,这下我就明白了。
不过大部分的情况,应该还是前端设置别名吧,毕竟那些登入登出的操作在前端控制会比较方便。

小提醒:

实际应用场景,客户端一般都需要在登录到App成功后,设置别名,恢复接收推送。退出登录后,清除别名,停止接收推送。

恢复接收推送:

 JPushInterface.resumePush(MyApplication.getInstance());

停止接收推送:

JPushInterface.stopPush(MyApplication.getInstance());

4.App杀死后还想要收到推送

有的公司由于业务需求,可能会要求你,App杀死后还想要收到推送。如果知道JPush Android SDK 是作为 Android Service 长期运行在后台的,从而创建并保持长连接,保持永远在线的能力...的童鞋们,那么必须要清楚一点的是:如果APP真的被杀死了,是不可能收到推送的,如果杀死了还能收到,那说明可能是以下几种情况:
①应用自启动了
②要么是其他方式将App拉起来了。
③你压根就没有杀死App,Service还在运行着。(有的手机清理App,并没有完全杀死进程的)

关于这个问题可以看看这位小姐姐的总结:Android关于App被杀死后,如何接收极光推送

阅读参考:
官网集成
极光推送Android端API

详解激光推送的4种消息形式

常见问题-JPush合集(持续更新)

三分钟帮你集成极光推送——和那些可能你不知道的事相关推荐

  1. android 极光推送测试,Android 3分钟带你集成极光推送

    话不多说 首先申请极光的账号,(官方地址:https://www.jiguang.cn) 1561710140829.png 登录完成之后,先看到这个地方 ,我个人比较喜欢用旧版本,这里点击旧版 15 ...

  2. Android集成极光推送踩坑(二)升级篇

    转载请标明出处 http://blog.csdn.net/mohan6/article/details/74133186 本文作者:[默寒的博客] 前言 前段时间针对集成极光推送写了篇文章( Andr ...

  3. 极光推送 android 最新,Android——快速集成极光推送-Go语言中文社区

    集成极光推送 1,首先肯定是注册,添加应用 2,开始自动集成比手动集成简单第一步 在 build.gradle defaultConfig { multiDexEnabledtrue applicat ...

  4. ionic4 集成极光推送jpush

    ionic4 集成极光推送jpush 1. 在极光官网注册.登录.创建应用 极光推送官网 应用包名要与config.xml一致 2.安装插件 ionic cordova plugin add jpus ...

  5. Android第三方SDK集成 —— 极光推送

    前言: 本文前篇,可以帮助朋友们快速集成极光推送.本文后篇,是我自己项目实践的一些总结和心得,应该对读者们还是很有参考价值的,相信读完这篇文章,你会对极光推送有更加深入的理解,而不仅仅只是会集成而已. ...

  6. 跨平台应用开发进阶(十一) :uni-app 实现IOS原生APP-云打包集成极光推送(JG-JPUSH)详细教程

    文章目录 一.前言 二.资源 三.集成 四.遇到的问题及解决措施 4.1 IOS开发者证书无推送权限 4.2 manifest中并没有配置push模块.但云端打包ios就是一直报Code Signin ...

  7. Android之集成极光推送

    安卓端集成极光推送是很常见的,极光推送的简单高效性适合很多想要集成推送的APP,如果你要自己装逼,也可以自己写推送,只要想做都是可以的. 第一步.Gradle配置(Module的build.gradl ...

  8. php集成极光推送,thinkphp 写APP接口集成极光推送的例子

    下面我们来看一篇关于thinkphp 写APP接口集成极光推送,对于app的数据都得通过接口来实现了,当然也有内置数据库的不过这种非常少了. 最近用Thinkphp写了个App接口用到第三方推送功能, ...

  9. React-Native集成极光推送(Android和IOS)

    React-Native集成极光推送的具体流程如下: 本文选取的是极光官方维护的react-native推送插件,github地址:https://github.com/jpush/jpush-rea ...

最新文章

  1. Parallels Desktop 16 Win11虚拟机将继续正常运作,但将无法连接网络
  2. 如何判断Linux load的值是否过高
  3. java-commons-HttpClient超时设置setConnectionTimeout和setSoTimeout
  4. windows10加载动画_如何关闭动画并使Windows 10看起来更快
  5. 吓人!深夜悄悄上街扫地!
  6. 车联网创新生态发展报告
  7. boost::lockfree::queue多线程读写实例
  8. jpsnamenode和不显示_hadoop启动后jps查不到namenode的解决办法
  9. GAT1400---视图库标准
  10. lopatkin俄大神精简中文系统Windows 8.1 Pro 19599 x86-x64 ZH-CN SM
  11. 社科院与杜兰大学金融管理硕士——在自己的领域努力拼搏,终将遇到专属的光芒
  12. SHAP:解释模型预测的通用方法
  13. 利用cmd命令创建vue项目
  14. Mysql如何添加环境变量(详细教程)
  15. Python基础练习题--第一章 Python语言入门
  16. K7 IDELAY2 仿真实验
  17. 6大常用电源设计电路,电源工程师必备知识宝典
  18. 数仓建设目标-统计口径
  19. 铁路“12306”的架构太牛了!
  20. 【SLAM】牛津大学 The Newer College Dataset下载分享

热门文章

  1. jquery中解决设置图片不显示
  2. 百度员工吐槽:35岁失业,之前月薪2w,现降到5k都没人理
  3. STM32:PWM驱动LED达到呼吸灯效果(内含:1.接线原理图/实物图+2.代码部分+3.注意事项/补充知识点部分)
  4. 三生三世十里桃花用计算机怎么弄,三生三世十里桃花灵宠系统怎么玩?三生三世十里桃花灵宠系统详解...
  5. java重新定义_重新定义Spring Cloud实战 PDF 下载
  6. 刘强东给京东高管降薪:2千多位总监兄弟工资打8折,并拿出100亿保障”兄弟“基础住房
  7. VUE父子组件-传数据的理解
  8. 用JAVA实现输入年月日,输出这是一年的第几天,是星期几
  9. python 实现热门音乐分析 附代码+数据 +论文
  10. 京东健康和药明康德入股卫宁软件,分别持有7.7%股权