Android极光推送

  • 极光推送

极光推送

步骤:
1,注册,登录成为开发者。 官方网站:https://www.jiguang.cn
2,在控制台创建应用: 参考链接:https://www.jiguang.cn/dev/#/app/list#dev
设置包名。包名一定和应用程序包名一致。

package com.example.jiguang;import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Looper;
import android.widget.Toast;public class ExampleUtil {public static void showToast(final String toast, final Context context){new Thread(new Runnable() {@Overridepublic 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());}
}
package com.example.jiguang;import android.content.Context;import cn.jpush.android.api.JPushMessage;
import cn.jpush.android.service.JPushMessageReceiver;/*** 自定义JPush message 接收器,包括操作tag/alias的结果返回(仅仅包含tag/alias新接口部分)* */
public class MyJPushMessageReceiver extends JPushMessageReceiver {@Overridepublic void onTagOperatorResult(Context context,JPushMessage jPushMessage) {TagAliasOperatorHelper.getInstance().onTagOperatorResult(context,jPushMessage);super.onTagOperatorResult(context, jPushMessage);}@Overridepublic void onCheckTagOperatorResult(Context context,JPushMessage jPushMessage){TagAliasOperatorHelper.getInstance().onCheckTagOperatorResult(context,jPushMessage);super.onCheckTagOperatorResult(context, jPushMessage);}@Overridepublic void onAliasOperatorResult(Context context, JPushMessage jPushMessage) {TagAliasOperatorHelper.getInstance().onAliasOperatorResult(context,jPushMessage);super.onAliasOperatorResult(context, jPushMessage);}@Overridepublic void onMobileNumberOperatorResult(Context context, JPushMessage jPushMessage) {TagAliasOperatorHelper.getInstance().onMobileNumberOperatorResult(context,jPushMessage);super.onMobileNumberOperatorResult(context, jPushMessage);}
}
package com.example.jiguang;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;import org.json.JSONException;
import org.json.JSONObject;import java.util.Iterator;import cn.jpush.android.api.JPushInterface;
import cn.jpush.android.helper.Logger;/*** 自定义接收器* * 如果不定义这个 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, MainActivity.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.get(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 (extraJson.length() > 0) {//                      msgIntent.putExtra(MainActivity.KEY_EXTRAS, extras);
//                  }
//              } catch (JSONException e) {//
//              }
//
//          }
//          LocalBroadcastManager.getInstance(context).sendBroadcast(msgIntent);
//      }
//  }}
package com.example.jiguang;import cn.jpush.android.service.JCommonService;public class PushService extends JCommonService {}
package com.example.jiguang;import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.SparseArray;import java.util.Locale;
import java.util.Set;import cn.jpush.android.api.JPushInterface;
import cn.jpush.android.api.JPushMessage;
import cn.jpush.android.helper.Logger;/*** 处理tagalias相关的逻辑* */
public class TagAliasOperatorHelper {private static final String TAG = "JIGUANG-TagAliasHelper";public static int sequence = 1;/**增加*/public static final int ACTION_ADD = 1;/**覆盖*/public static final int ACTION_SET = 2;/**删除部分*/public static final int ACTION_DELETE = 3;/**删除所有*/public static final int ACTION_CLEAN = 4;/**查询*/public static final int ACTION_GET = 5;public static final int ACTION_CHECK = 6;public static final int DELAY_SEND_ACTION = 1;public static final int DELAY_SET_MOBILE_NUMBER_ACTION = 2;private Context context;private static TagAliasOperatorHelper mInstance;private TagAliasOperatorHelper(){}public static TagAliasOperatorHelper getInstance(){if(mInstance == null){synchronized (TagAliasOperatorHelper.class){if(mInstance == null){mInstance = new TagAliasOperatorHelper();}}}return mInstance;}public void init(Context context){if(context != null) {this.context = context.getApplicationContext();}}private SparseArray<Object> setActionCache = new SparseArray<Object>();public Object get(int sequence){return setActionCache.get(sequence);}public Object remove(int sequence){return setActionCache.get(sequence);}public void put(int sequence,Object tagAliasBean){setActionCache.put(sequence,tagAliasBean);}private Handler delaySendHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {switch (msg.what){case DELAY_SEND_ACTION:if(msg.obj !=null && msg.obj instanceof  TagAliasBean){Logger.i(TAG,"on delay time");sequence++;TagAliasBean tagAliasBean = (TagAliasBean) msg.obj;setActionCache.put(sequence, tagAliasBean);if(context!=null) {handleAction(context, sequence, tagAliasBean);}else{Logger.e(TAG,"#unexcepted - context was null");}}else{Logger.w(TAG,"#unexcepted - msg obj was incorrect");}break;case DELAY_SET_MOBILE_NUMBER_ACTION:if(msg.obj !=null && msg.obj instanceof  String) {Logger.i(TAG, "retry set mobile number");sequence++;String mobileNumber = (String) msg.obj;setActionCache.put(sequence, mobileNumber);if(context !=null) {handleAction(context, sequence, mobileNumber);}else {Logger.e(TAG, "#unexcepted - context was null");}}else{Logger.w(TAG,"#unexcepted - msg obj was incorrect");}break;}}};public void handleAction(Context context,int sequence,String mobileNumber){put(sequence,mobileNumber);Logger.d(TAG,"sequence:"+sequence+",mobileNumber:"+mobileNumber);JPushInterface.setMobileNumber(context,sequence,mobileNumber);}/*** 处理设置tag* */public void handleAction(Context context,int sequence, TagAliasBean tagAliasBean){init(context);if(tagAliasBean == null){Logger.w(TAG,"tagAliasBean was null");return;}put(sequence,tagAliasBean);if(tagAliasBean.isAliasAction){switch (tagAliasBean.action){case ACTION_GET:JPushInterface.getAlias(context,sequence);break;case ACTION_DELETE:JPushInterface.deleteAlias(context,sequence);break;case ACTION_SET:JPushInterface.setAlias(context,sequence,tagAliasBean.alias);break;default:Logger.w(TAG,"unsupport alias action type");return;}}else {switch (tagAliasBean.action) {case ACTION_ADD:JPushInterface.addTags(context, sequence, tagAliasBean.tags);break;case ACTION_SET:JPushInterface.setTags(context, sequence, tagAliasBean.tags);break;case ACTION_DELETE:JPushInterface.deleteTags(context, sequence, tagAliasBean.tags);break;case ACTION_CHECK://一次只能check一个tagString tag = (String)tagAliasBean.tags.toArray()[0];JPushInterface.checkTagBindState(context,sequence,tag);break;case ACTION_GET:JPushInterface.getAllTags(context, sequence);break;case ACTION_CLEAN:JPushInterface.cleanTags(context, sequence);break;default:Logger.w(TAG,"unsupport tag action type");return;}}}private boolean RetryActionIfNeeded(int errorCode,TagAliasBean tagAliasBean){if(!ExampleUtil.isConnected(context)){Logger.w(TAG,"no network");return false;}//返回的错误码为6002 超时,6014 服务器繁忙,都建议延迟重试if(errorCode == 6002 || errorCode == 6014){Logger.d(TAG,"need retry");if(tagAliasBean!=null){Message message = new Message();message.what = DELAY_SEND_ACTION;message.obj = tagAliasBean;delaySendHandler.sendMessageDelayed(message,1000*60);String logs =getRetryStr(tagAliasBean.isAliasAction, tagAliasBean.action,errorCode);ExampleUtil.showToast(logs, context);return true;}}return false;}private boolean RetrySetMObileNumberActionIfNeeded(int errorCode,String mobileNumber){if(!ExampleUtil.isConnected(context)){Logger.w(TAG,"no network");return false;}//返回的错误码为6002 超时,6024 服务器内部错误,建议稍后重试if(errorCode == 6002 || errorCode == 6024){Logger.d(TAG,"need retry");Message message = new Message();message.what = DELAY_SET_MOBILE_NUMBER_ACTION;message.obj = mobileNumber;delaySendHandler.sendMessageDelayed(message,1000*60);String str = "Failed to set mobile number due to %s. Try again after 60s.";str = String.format(Locale.ENGLISH,str,(errorCode == 6002 ? "timeout" : "server internal error”"));ExampleUtil.showToast(str, context);return true;}return false;}private String getRetryStr(boolean isAliasAction,int actionType,int errorCode){String str = "Failed to %s %s due to %s. Try again after 60s.";str = String.format(Locale.ENGLISH,str,getActionStr(actionType),(isAliasAction? "alias" : " tags") ,(errorCode == 6002 ? "timeout" : "server too busy"));return str;}private String getActionStr(int actionType){switch (actionType){case ACTION_ADD:return "add";case ACTION_SET:return "set";case ACTION_DELETE:return "delete";case ACTION_GET:return "get";case ACTION_CLEAN:return "clean";case ACTION_CHECK:return "check";}return "unkonw operation";}public void onTagOperatorResult(Context context, JPushMessage jPushMessage) {int sequence = jPushMessage.getSequence();Logger.i(TAG,"action - onTagOperatorResult, sequence:"+sequence+",tags:"+jPushMessage.getTags());Logger.i(TAG,"tags size:"+jPushMessage.getTags().size());init(context);//根据sequence从之前操作缓存中获取缓存记录TagAliasBean tagAliasBean = (TagAliasBean)setActionCache.get(sequence);if(tagAliasBean == null){ExampleUtil.showToast("获取缓存记录失败", context);return;}if(jPushMessage.getErrorCode() == 0){Logger.i(TAG,"action - modify tag Success,sequence:"+sequence);setActionCache.remove(sequence);String logs = getActionStr(tagAliasBean.action)+" tags success";Logger.i(TAG,logs);ExampleUtil.showToast(logs, context);}else{String logs = "Failed to " + getActionStr(tagAliasBean.action)+" tags";if(jPushMessage.getErrorCode() == 6018){//tag数量超过限制,需要先清除一部分再addlogs += ", tags is exceed limit need to clean";}logs += ", errorCode:" + jPushMessage.getErrorCode();Logger.e(TAG, logs);if(!RetryActionIfNeeded(jPushMessage.getErrorCode(),tagAliasBean)) {ExampleUtil.showToast(logs, context);}}}public void onCheckTagOperatorResult(Context context, JPushMessage jPushMessage){int sequence = jPushMessage.getSequence();Logger.i(TAG,"action - onCheckTagOperatorResult, sequence:"+sequence+",checktag:"+jPushMessage.getCheckTag());init(context);//根据sequence从之前操作缓存中获取缓存记录TagAliasBean tagAliasBean = (TagAliasBean)setActionCache.get(sequence);if(tagAliasBean == null){ExampleUtil.showToast("获取缓存记录失败", context);return;}if(jPushMessage.getErrorCode() == 0){Logger.i(TAG,"tagBean:"+tagAliasBean);setActionCache.remove(sequence);String logs = getActionStr(tagAliasBean.action)+" tag "+jPushMessage.getCheckTag() + " bind state success,state:"+jPushMessage.getTagCheckStateResult();Logger.i(TAG,logs);ExampleUtil.showToast(logs, context);}else{String logs = "Failed to " + getActionStr(tagAliasBean.action)+" tags, errorCode:" + jPushMessage.getErrorCode();Logger.e(TAG, logs);if(!RetryActionIfNeeded(jPushMessage.getErrorCode(),tagAliasBean)) {ExampleUtil.showToast(logs, context);}}}public void onAliasOperatorResult(Context context, JPushMessage jPushMessage) {int sequence = jPushMessage.getSequence();Logger.i(TAG,"action - onAliasOperatorResult, sequence:"+sequence+",alias:"+jPushMessage.getAlias());init(context);//根据sequence从之前操作缓存中获取缓存记录TagAliasBean tagAliasBean = (TagAliasBean)setActionCache.get(sequence);if(tagAliasBean == null){ExampleUtil.showToast("获取缓存记录失败", context);return;}if(jPushMessage.getErrorCode() == 0){Logger.i(TAG,"action - modify alias Success,sequence:"+sequence);setActionCache.remove(sequence);String logs = getActionStr(tagAliasBean.action)+" alias success";Logger.i(TAG,logs);ExampleUtil.showToast(logs, context);}else{String logs = "Failed to " + getActionStr(tagAliasBean.action)+" alias, errorCode:" + jPushMessage.getErrorCode();Logger.e(TAG, logs);if(!RetryActionIfNeeded(jPushMessage.getErrorCode(),tagAliasBean)) {ExampleUtil.showToast(logs, context);}}}//设置手机号码回调public void onMobileNumberOperatorResult(Context context, JPushMessage jPushMessage) {int sequence = jPushMessage.getSequence();Logger.i(TAG,"action - onMobileNumberOperatorResult, sequence:"+sequence+",mobileNumber:"+jPushMessage.getMobileNumber());init(context);if(jPushMessage.getErrorCode() == 0){Logger.i(TAG,"action - set mobile number Success,sequence:"+sequence);setActionCache.remove(sequence);}else{String logs = "Failed to set mobile number, errorCode:" + jPushMessage.getErrorCode();Logger.e(TAG, logs);if(!RetrySetMObileNumberActionIfNeeded(jPushMessage.getErrorCode(),jPushMessage.getMobileNumber())){ExampleUtil.showToast(logs, context);}}}public static class TagAliasBean{int action;Set<String> tags;String alias;boolean isAliasAction;@Overridepublic String toString() {return "TagAliasBean{" +"action=" + action +", tags=" + tags +", alias='" + alias + '\'' +", isAliasAction=" + isAliasAction +'}';}}}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.jiguang"><!-- Required --><permissionandroid:name="com.example.jiguang.permission.JPUSH_MESSAGE"android:protectionLevel="signature" /><!-- Required  一些系统要求的权限,如访问网络等--><uses-permission android:name="com.example.jiguang.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.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.MOUNT_UNMOUNT_FILESYSTEMS" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><applicationandroid:name=".MyApp.MyApp"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><!-- Required SDK 核心功能--><!-- 可配置android:process参数将PushService放在其他进程中 --><serviceandroid:name=".PushService"android:process=":pushcore"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><!-- User defined.  For test only  用户自定义的广播接收器--><receiverandroid:name=".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="com.example.jiguang" /></intent-filter></receiver><!-- User defined.  For test only  用户自定义接收消息器,3.0.7开始支持,目前新tag/alias接口设置结果会在该广播接收器对应的方法中回调--><receiver android:name=".MyJPushMessageReceiver"><intent-filter><action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" /><category android:name="com.example.jiguang"></category></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="7bfc54fd7bbb96ae5a464a94" /> <!--  </>值来自开发者平台取得的AppKey--></application></manifest>

极光推送简单介绍与简单使用相关推荐

  1. 极光推送(一)——极光推送的介绍

    在Android应用开发的过程中,可能需要服务器推送消息到Android客户端,对于iOS有其自己的推送服务,而遗憾的是Android系统没有原生的推送服务,但是我们可以借助第三方推送平台来实现服务器 ...

  2. 个推和极光推送技术介绍

    一.概念 1.早期推送服务 在移动互联网以前的手机,如果有事情发生要通知用户,则会弹出一个窗口,告诉用户正在发生的事,可能是未接电话提示.日历提醒或是一封彩信.推送功能最早是被用于Email中,而目前 ...

  3. 极光推送的简单实现方法

    极光推送的简单实现方法 第一步 导入其jar包和so文件这点不再详解, 但是要注意的一点就是: 个人感觉极光的demo还是有些地方需要改进的, 不建议使用,但是里面的代码是需要我们自己拿的, 我这里主 ...

  4. 极光推送jpush(简单易懂,分分钟教你搞定)

    先注册账户: 然后点击开发者服务:点击打开链接 创建应用: 随便起个名字,但是最好和你的应用名字一样 然后点击下一步推送设置 把你的工程应用名字输入: 应用包名就是build.gradle文件里的ap ...

  5. 关于JPsh极光推送的基本用法和通知介绍

    第一次用极光推送避免不了各种坑.总结一下. 关于架包引入 请先参考官方文档, Android SDK 集成指南 这里文档说的是最新版架包在AndroidStudio中引入的方法, 直接可以在build ...

  6. 看了极光推送技术原理的几点思考

    看了极光推送技术原理的几点思考 分类: android2012-11-26 20:50 16586人阅读 评论(18) 收藏 举报 目录(?)[+] 移动互联网应用现状 因为手机平台本身.电量.网络流 ...

  7. Android开发之第三方推送JPush极光推送知识点详解 学会集成第三方SDK推送

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 下面是一些知识点介绍,后期将会带领大家进行代码实战: 一.Android实现推送方式解决方案: 1.推 ...

  8. 极光推送经验之谈-Java后台服务器实现极光推送的两种实现方式

    转载自 https://www.cnblogs.com/V1haoge/p/6439313.html 原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge ...

  9. iOS推送(利用极光推送)

    本文主要是基于极光推送的SDK封装的一个快速集成极光推送的类的封装(不喜勿喷) (1)首先说一下推送的一些原理: Push的原理: Push 的工作机制可以简单的概括为下图 图中,Provider是指 ...

最新文章

  1. 3W法—what,why,how的运用
  2. Node 10 新功能概览(译)
  3. mysql复制架构迁移到pxc_2020-03-18 Mysql常见的HA中间层架构mmm,pxc,mha
  4. 基于matlab的语音信号基本处理系统,基于matlab的语音信号处理及分析
  5. Core Location :⽤用于地理定位
  6. math api matrix
  7. Hadoop Hive基础sql语法
  8. JavaScript+HTML 实现贪吃蛇简陋版
  9. ea6500 v1 刷梅林_【求助】EA6500 V1和RT-AC66U硬件配置接近,怎么没有EA6500V1可以刷的梅林...
  10. CorelDRAW哪个版本好用实用强x4/X8/2019/2020/2021
  11. EXTJS源码分析与开发实例-原创2章下载
  12. 总结51单片机之上拉电阻
  13. Python与企业微信-3
  14. Cesium 添加天地图三维地形
  15. 如何启动与终止PHP CLI程序的后台运行
  16. 【互联网人的英语】到底要不要学语法?什么时候学比较好?
  17. python基础数据类型
  18. 3.ConcurrentMap-并发Map
  19. java集合类继承关系图_java集合继承关系图
  20. 2017国际大数据及云计算展开幕 凡科建站云平台吸睛

热门文章

  1. mybaties日常开发总结
  2. 关于PDSCH的码字个数问题
  3. 关于瑕积分的几道例题
  4. Linux 内核交互图
  5. [译] 前端攻略-从路人甲到英雄无敌
  6. JS在浏览器上的性能分析(一)脚本的下载与运行
  7. python opencv检测高光点及findContours计算连通域重心
  8. ios xib 初始化高度_基于 xib 开发自适应高度 view
  9. Java从IoC到注解开发(1)
  10. 4diacIDE IEC61499 开发环境编译