全部产品
云市场

快速入门

更新时间:2018-07-24 10:03:08

一、SDK的引入

1、引入SDK包中的SDK-CMNS.jar。注:如何下载SDK?

2、引入安全保镖,包括:SecurityBodySDK.jar, SecurityGuardSDK.jar, libsgmain.so, libsgsecuritybody.so。

3、拷贝资源文件,包括:安全图片(yw_1222_aicc.jpg),以及两张SDK的图片资源文件( alisdk_cmns_ic_notification.png,alisdk_cmns_ic_large.png)。

4、在AndroidManifest.xml中增加以下内容:

增加权限

  1. <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  3. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  4. <uses-permission android:name="android.permission.INTERNET" />

注:在Android5.0或者更高版本,android.permission.READ_PHONE_STATE需要动态申请,申请方式为:

  1. class MainActivity {
  2. @Override
  3. public void onCreate() {
  4. ...
  5. ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_PHONE_STATE}, 0);
  6. }
  7. }

增加receiver

  1. <receiver android:name="com.aliyun.push.api.PushMessageReceiver">
  2. <intent-filter>
  3. <action android:name="com.aliyun.cmns.intent.SEND_NOTIFICATION"/>
  4. <action android:name="com.aliyun.cmns.intent.CANCEL_NOTIFICATION"/>
  5. <action android:name="com.aliyun.cmns.intent.PASSTHROUGH"/>
  6. <action android:name="com.aliyun.cmns.intent.NOTIFICATION_CLICKED"/>
  7. <action android:name="com.aliyun.cmns.intent.NOTIFICATION_REMOVE"/>
  8. </intent-filter>
  9. </receiver>

注:安全保镖,安全图片,资源文件,assets文件,AndroidManifest.xml内容,均需要按照上面方法正确操作,否则将引起CMNS接入失败。

二、SDK初始化

接口原型:

  1. /** CMNS SDK初始化
  2. * @param applicationContext Context 应用Context
  3. * @param listener PushAsyncListener 初始化完成后的回调
  4. */
  5. void init(Context applicationContext, PushAsyncInitListener listener);
  6. /** CMNS SDK初始化
  7. * @param applicationContext Context 应用Context
  8. * @param authCode String 安全图片的authCode,如图片名称为yw_1222_abc.jpg,则authCode为abc
  9. * @param listener PushAsyncListener 初始化完成后的回调
  10. */
  11. void init(Context applicationContext, String authCode, PushAsyncInitListener listener);
  12. /** CMNS SDK初始化
  13. * @param applicationContext Context 应用Context
  14. * @param appKeyIndex int 安全图片中cmns的key的位置,SDK中默认位置为1
  15. * @param pAppkey String 业务处理的AppKey
  16. * @param authCode String 安全图片的authCode,如图片名称为yw_1222_abc.jpg,则authCode为abc
  17. * @param listener PushAsyncListener 初始化完成后的回调
  18. */
  19. void init(Context applicationContext, int appKeyIndex, String pAppKey, String authCode, PushAsyncInitListener listener);

其中PushAsyncInitListener如下:

  1. public interface PushAsyncInitListener {
  2. /** PushAsyncListener
  3. * @param errorCode int 返回码,0表示成功,错误码详见com.aliyun.aicc.cmns.PushErrorCode
  4. */
  5. void onInit(int errorCode);
  6. }

调用示例:

  1. public class MyApplication extends Application {
  2. @Override
  3. public void onCreate() {
  4. super.onCreate();
  5. PushClient.getInstance().init(this, new PushAsyncInitListener() {
  6. @Override
  7. public void onInit(final int errorCode) {
  8. Log.d(TAG, "init " + errorCode == PushErrorCode.ERROR_OK ? "success" : "failed");
  9. }
  10. });
  11. }
  12. }

三、获取长连接状态

描述:获取CMNS长连接通道状态(是否在线)。

接口原型:

  1. /**
  2. * @return isConnected boolean 设备是否在线
  3. */
  4. boolean isConnected();

调用示例:

  1. boolean isConnnected = PushClient.getInstance().isConnecte();
  2. Log.d("Push", "connect status: " + isConnected ? "connected" : "disconnected");

注:在某些情况下,比如网络不好、ssl证书验证失败等情况下,CMNS通道会不存在,调用sendMessagesendMessageWithReply等接口,需要判断CMNS服务的连接状态,如果CMNS通道不存在,需要接入方选择丢弃不发或者等待通道恢复延迟发送

四、设置CMNS连接状态改变事件监听

描述: 设置CMNS连接状态改变事件监听,可以获取到长连接状态实时变化通知接口原型:

  1. /**
  2. * @param listener PushConnectionStateChangeListener 连接状态改变事件监听
  3. */
  4. void setConnectionStateChangeListener(PushConnectionStateChangeListener listener);

其中PushConnectionStateChangeListener为:

  1. public interface PushConnectionStateChangeListener {
  2. // 当连接成功时回调
  3. void onConnect();
  4. // 当断开连接时回调
  5. void onDisconnect();
  6. }

调用示例:

  1. PushClient.getInstance().setConnectionStateChangeListener(new PushConnectionStateChangeListener() {
  2. @Override
  3. public void onConnect() {
  4. Log.d(TAG, "push connect");
  5. }
  6. @Override
  7. public void onDisconnect() {
  8. Log.d(TAG, "push disconnect");
  9. }
  10. });

五、客户端设置消息监听

描述:设置消息监听可以收到CMNS服务端下发的透传消息、以及通知消息的点击回调

接口原型:

  1. /**
  2. * @param listener PushMessageListener 消息回调
  3. */
  4. void setMessageListener(PushMessageListener listener);

其中相关类与方法如下:

  1. interface PushMessageListener {
  2. /** 当收到CMNS服务端透传的消息时回调
  3. * @param mid long 当前消息的消息id,建议将此消息id打印出来,方便调试
  4. * @param payload String 透传的消息主体
  5. */
  6. void onPassThroughMessage(long mid, String payload);
  7. /** 当用户点击通知中心消息时回调
  8. * @param mid long 当前消息的消息id,建议将此消息id打印出来,方便调试
  9. * @param payload String 透传的消息主体
  10. */
  11. void onNotificationClicked(long mid, String payload);
  12. }

调用示例:

  1. PushClient.getInstance().setMessageListener(new PushMessageListener() {
  2. // 透传消息回调,PushMessage为CMNS服务端下发的回调消息。
  3. @Override
  4. public void onPassThroughMessage(long mid, String payload) {
  5. Log.d(TAG, "pass mid: " + mid + "\tmsg: " + payload);
  6. }
  7. // 通知中心点击事件,在用户手动点击通知中心消息后回调,PushMessage为CMNS服务端下发的通知消息。
  8. @Override
  9. public void onNotificationClicked(long mid, String paylaod) {
  10. Log.d(TAG, "click mid: " + mid + "\tmsg: " + payload);
  11. }
  12. });

注:setMessageListenr接口需要在Application.onCreate中设置,因为推送消息会通过com.aliyun.cmns.CMNSMessageReceiver唤醒应用,如果不在Application.onCreate里面调用,唤醒状态无法设置消息监听者,应用就无法感知消息回调。

六、非可靠消息上行

描述:上传消息到应用appKey关联的mns消息队列上,此接口适用于不关注成功性的接口,比如上报位置信息等(CMNS底层也会多次重传,尽量保证上传成功率,只是没有成功与否的返回)。

接口原型:

  1. /**
  2. * @param tag String 上行消息的tag,服务端用来过滤
  3. * @param msg String 上行的消息
  4. */
  5. void sendMessage(String tag, String msg);

调用示例:

  1. PushClient.getInstance().sendMessage("place", "在杭州");

七、可靠消息上行

描述:上传消息到应用appKey关联的mns消息队列上,此接口会在服务端将消息放到mns后返回,会告知客户端消息是否成功上传。

接口原型:

  1. /**
  2. * @param tag String 上行消息的tag,服务端做过滤消息用
  3. * @param msg String 上行的消息
  4. * @param listener PushSendMessageListener 上行消息的回调
  5. */
  6. void sendMessageWithReply(String tag, String msg, PushSendMessageListener listener);

接口需要的相关类与方法如下:

  1. interface PushSendMessageListener {
  2. /** 上行消息回调
  3. * @param errorCode int 上行消息错误码,详见PushErrorCode.java
  4. */
  5. void onSendMessage(int errorCode);
  6. }

调用示例:

  1. PushClient.getInstance().sendMessageWithReply("place", "在杭州", new PushSendMessageListener() {
  2. @Override
  3. public void onSendMessage(final int errorCode) {
  4. Log.d(TAG, "onSendMessage: " + errorCode);
  5. }
  6. });

注:如果网络状态不佳,上行消息可能会超时(可能数据已经上传到服务端,但是客户端没有收到回包),如果选择重发,CMNS服务端可能会收到多条一样的数据,此时需要应用服务端到mns中取数据时做数据去重。

八、RPC 远程服务调用

描述:调用业务方服务端注册在CMNS服务端的HTTP接口。

接口原型:

  1. /** 获取服务端远程服务
  2. * @param interfaceClass 远程服务的接口名
  3. */
  4. <T> T getRemoteRpcService(Class<T> interfaceClass);

接口需要的相关类与方法如下:

  1. // Rpc调用回调
  2. public interface PushRpcListener {
  3. /**
  4. * @param errorCode int rpc调用返回的错误码
  5. * @param response String rpc调用返回的response
  6. */
  7. void onReply(int errorCode, String response);
  8. }
  9. // Rpc设置
  10. public @interface PushRpcSetting {
  11. /** 协议超时时间设置
  12. * return int 当前协议的超时时间,默认为30s
  13. */
  14. int timeout() default 30000;
  15. }

调用示例:

  1. public interface TestRemoteRpcService {
  2. @PushRcpSetting (timeout = 3000)
  3. void addInt(int a, int b, int c, PushRpcListener listener);
  4. void addString(String a, String b, PushRpcListener listener);
  5. }
  6. void callRemoteFunc() {
  7. TestRemoteRpcService rpcService = PushClient.getInstance().getRemoteRpcService(TestRemoteRpcService.class);
  8. rpcService.addInt(1, 2, 3, new PushRpcListener() {
  9. @Override
  10. public void onReply(int errorCode, String response) {
  11. Log.d(TAG, "addInt result, errorCode: " + errorCode + ", response: " + response);
  12. }
  13. });
  14. rpcService.addString("a", "b", new PushRpcListener() {
  15. @Override
  16. public void onReply(int errorCode, String response) {
  17. Log.d(TAG, "addInt result, errorCode: " + errorCode + ", response: " + response);
  18. }
  19. });
  20. }

注:

  1. 目前支持的类型有int、long、float、double、boolean、byte[]等基本类型,支持Int、Long、Float、Double、Boolean、String等基本类。
  2. 调用的接口必须是业务服务端已经存在的接口,如果接口不存在则会报相关错误。
  3. rpc调用必须在长连接通道存在的时候调用。
  4. 客户端调用的接口与服务端暴露的接口,通过appKey关联,如果服务端暴露了名为addInt(String a, String b)的接口,客户端则按照调用示例调用addInt方法即可。
  5. 如果对超时时间无特殊要求,不建议修改超时时间,在客户端网络比较弱的情况下,CMNS底层会多次重试,尽量保证请求成功,如果时间太短,则会容易引起失败。
  6. 客户端声明的RPC interface的每一个方法,最后一个参数必须写PushRpcListener,否则会引起调用失败。

九、客户端通知消息处理

通过CMNS服务端推送 “通知消息” ,会带有五个Intent对象:ActionComponentDataTypeCategory,点击通知中心的点击消息,会通过这五个Intent对象去打开相应的应用页面。

  • Action(动作) Action规定了Intent要完成的动作,在打开页面的过程中,需要在目标组件的AndroidManifest.xml中声明过滤器规则,将Action加入其中。 默认action是Intent.ACTION_VIEW,即android.intent.action.View,也可以根据具体需求需求设置其他Action。Action设置方法如下:

    1. <activity android:name="MessageClickActivity">
    2. <intent-filter>
    3. <action android:name="android.intent.action.VIEW" />
    4. <category android:name="android.intent.category.DEFAULT" />
    5. </intent-filter>
    6. </activity>
  • Component(组件) 如果应用服务端传给CMNS服务端的字段中带有Component这个属性的话,将直接使用它指定的组件。指定了这个属性以后,Intent的其它所有属性都是可选的。 收到带有Component的消息,SDK会取其中的class和package字段放到Intent中,去完成相应的操作。

  • Category(类别) 如果应用服务端传给CMNS服务端的字段中带有Category这个属性的话,SDK会在Intent中添加多个类别,那就要求被匹配的组件必须同时满足这多个类别,才能匹配成功。

    默认category是android.intent.category.DEFAULT,也可以根据具体需求设置其他Category。配置方法如下:

    1. <activity android:name="MessageClickActivity">
    2. <intent-filter>
    3. <action android:name="android.intent.action.VIEW" />
    4. <category android:name="android.intent.category.DEFAULT" />
    5. <category android:name="com.yunos.push.category.DEFAULT" />
    6. </intent-filter>
    7. </activity>
  • Data(数据) Data字段指定了一个Uri,表示需要访问的数据。通常情况下,我们可以使用Action加Data两个属性来描述一个意图。 Data与Action、Category声明方式相同,也是描述在<intent-filter>中,设置方法如下:

    1. <activity android:name="MessageClickActivity">
    2. <intent-filter>
    3. <action android:name="android.intent.action.VIEW" />
    4. <category android:name="android.intent.category.DEFAULT" />
    5. <data android:scheme="http" android:host="yunos.com"/>
    6. </intent-filter>
    7. </activity>
  • Type(数据类型) 如果Intent对象中既包含Uri又包含Type,那么,在<intent-filter>中也必须二者都包含才能通过测试。 Type属性用于明确指定Data属性的数据类型或MIME类型,但是通常来说,当Intent不指定Data属性时,Type属性才会起作用,否则Android系统将会根据Data属性值来分析数据的类型,所以无需指定Type属性。

    配置方法如下:

    1. <activity android:name="MessageClickActivity">
    2. <intent-filter>
    3. <action android:name="android.intent.action.VIEW" />
    4. <category android:name="android.intent.category.DEFAULT" />
    5. <data android:type="audio/mpeg" android:scheme="http" android:host="yunos.com" />
    6. </intent-filter>
    7. </activity>

这五个Intent对象可以通过CMNS接口参数pkgContent进行设置,通过这五个对象组合,可以发送以下几种类型的消息:

  • 通知消息-H5消息(只带uri) 点击通知中心里面的H5消息,会使用系统默认的浏览器打开http链接,如果uri不是http格式,系统会默认匹配uri,使用系统默认应用去打开uri,如uri=taobao://m.taobao.com,会跳转到淘宝首页。

  • 通知消息-打开首页(带package+action) 点击通知中心的消息,会打开应用的默认Activity,需要应用在AndroidManifest.xml中Activiy的<intent-filter>中添加action

  • 通知消息-应用内消息(带action+package+uri) 点击通知中心里面的应用内消息,会根据AndroidManifest.xml中的配置去打开相应的界面,即需要应用在AndroidManifest.xml中,给相应Activity的<intent-filter>属性增加actiondata,详见上面Data字段的介绍。

  • 透传消息(带package+action,其中action=应用包名) 透传消息不会显示在通知中心,会通过SDK的回调接口告知应用,可以在后台运行。

十、常见错误码

  1. // 公共错误码
  2. ERROR_OK = 0;
  3. ERROR_INITIALIZE_LOGGING_FAILED = 1000;
  4. ERROR_CREATE_THREADS_FAILED = 1001;
  5. ERROR_NETWORK_ERROR = -1000;
  6. ERROR_BAD_PARA = -999;
  7. ERROR_SESSION_ERROR = -998;
  8. ERROR_SERVER_RETURN_EMPTY = -997;
  9. ERROR_CANCELLED = -996;
  10. ERROR_RESPONSE_CODE_ERROR = -995;
  11. // AndroidSDK独有 410xx
  12. ERROR_SERVICE_IS_NOT_INITIALIZED = 41002;
  13. ERROR_SYSTEM_SERVICE_IS_NOT_CONNECTED = 41003;
  14. ERROR_SYSTEM_SERVICE_IS_NOT_AVALIABLE = 41004;
  15. ERROR_SDK_SERVICE_IS_NOT_AVALIABLE = 41005;
  16. ERROR_SECURITYBOX_INITIALIZE_FAILED = 41006;
  17. ERROR_SECURITYBOX_GETAPPKEY_ERROR = 41007;
  18. ERROR_UNEXPECT_RUN_ERROR = 41008;
  19. ERROR_NO_FULL_PACKAGE = 41009;
  20. ERROR_NO_SUCH_API = 41010;
  21. ERROR_SERVICE_SHUTDOWN = 41011;
  22. // 本地定义, database获取的失败
  23. ERROR_SQL_ERROR = 50000;
  24. // 本地定义,服务器返回超时
  25. ERROR_TIMEOUT = 50001;
  26. // native error code
  27. ERROR_OOM = 60000;
  28. ERROR_INVALID_SOCKET = 60001;
  29. ERROR_DISCONNECT_BY_USER = 60002;
  30. ERROR_CMNS_NOT_CONNECTED = 60003;
  31. ERROR_NETWORK_NOT_REACHABLE = 60004;
  32. ERROR_UNKNOW = 60005;
  33. // connect error code
  34. ERROR_CONNECT_ERROR_BASE = 70000;
  35. ERROR_UNACCEPTABLE_PROTOCOL_VERSION = 70001; // 版本错误
  36. ERROR_IDENTIFIER_REJECTED = 70002;
  37. ERROR_SERVER_UNAVAILABLE = 70003;
  38. ERROR_INVALID_USER_OR_PASSWORD = 70004;
  39. ERROR_NOT_AUTHORIZED_EXPIRED = 70005; // 账号Token过期
  40. ERROR_NOT_AUTHORIZED_ILLEGAL = 70006; // 账号Token非法
  41. ERROR_ACCOUNT_CENTER_ERR = 70007; // 账号中心异常
  42. ERROR_NO_ACCOUNT_CENTER_FOR_APPKEY = 70008; // 账号中心未配置
  43. ERROR_DUPLICATE_IMEI_OR_UUID = 70009; // IMEI或者UUID重复
  44. ERROR_SID_CENTER_ERR = 70010; // SID 中心异常
  45. ERROR_CLIENTID_IMEI_ILLEGAL = 70011; // IMIE非法
  46. ERROR_CLIENTID_LENGTH_ILLEGAL = 70012;
  47. ERROR_CLIENTID_ISNULL = 70013; // ClientID为空
  48. ERROR_PASSWORD_ISNULL = 70014; // Password为空
  49. ERROR_USERNAME_ISNULL = 70015; // UserName为空
  50. ERROR_USERNAME_ILLEGAL = 70016; // UserName非法
  51. ERROR_USERNAME_LENGTH_ILLEGAL = 70017; // UserName长度非法
  52. ERROR_UUID_ILLEGAL = 70018; // UUID非法
  53. ERROR_UUID_CENTER_ERR = 70019; // UUID中心异常
  54. ERROR_APPKEY_ILLEGAL = 70020;
  55. ERROR_DB_REDIS_ERR = 70021;
  56. ERROR_EMPTY_DEVICE_INFO = 70022;
  57. ERROR_CERT_ILLEGAL = 70023;
  58. ERROR_INVALID_CONNECTION = 70024;
  59. ERROR_CONNECTION_NOT_CONACK = 70025;
  60. ERROR_CLOSED_BY_CLIENT = 70026;
  61. ERROR_CLOSED_BY_SINGLESIGNON = 70027;
  62. ERROR_CLIENT_NO_RESPONE = 70028;
  63. ERROR_PACKAGENAME_ILLEGAL = 70029;
  64. ERROR_SECRET_NOT_EXIST = 70030;
  65. ERROR_SIGN_TIMER_ILLEGAL = 70031;
  66. ERROR_SIGN_ILLEGAL = 70032;
  67. // response error code
  68. ERROR_RESPONSE_ERROR_BASE = 80000;
  69. ERROR_INVALID_JSON = 80001;
  70. ERROR_APPKEY_ERROR = 80010;
  71. ERROR_SECRET_ILLEGAL = 80011;
  72. ERROR_NO_UPLOAD_PERMISSION = 80012;
  73. ERROR_PAPPKEY_ILLEGAL = 80013;
  74. ERROR_PAPPKEY_INVALID = 80014;
  75. ERROR_TIMESTAMP_ILLEGAL = 80020;
  76. ERROR_TAG_LENGTH_ILLEGAL = 80030;
  77. ERROR_TAG_COUNT_ILLEGAL = 80031;
  78. ERROR_RPC_SUCCESS = 90200;
  79. ERROR_RPC_PARAMETER_EMPTY = 90201;
  80. ERROR_RPC_PARAMETER_INVALID = 90202;
  81. ERROR_RPC_APP_SERVER_NOT_EXIST = 90203;
  82. ERROR_RPC_APP_CLIENT_NOT_EXIST = 90204;
  83. ERROR_RPC_DEVICE_NOT_EXIST = 90205;
  84. ERROR_RPC_DEVICE_NOT_ONLINE = 90206;
  85. ERROR_RPC_METHOD_NOT_EXIST = 90207;
  86. ERROR_RPC_PARAM_COUNT_NOT_MATCH = 90208;
  87. ERROR_RPC_CLIENT_SIGN_ERROR = 90209;
  88. ERROR_RPC_CLIENT_TIMEOUT = 90210;
  89. ERROR_RPC_CLIENT_UNSUPPORT_PARAM_TYPE = 90211;
  90. ERROR_RPC_SYSTEM_ERROR = 90212;
  91. ERROR_RPC_SERVER_SIGN_ERROE = 90213;
  92. ERROR_RPC_SERVER_DECRYPT_ERROE = 90214;
  93. ERROR_RPC_SERVER_TIMESTAMP_INVALID = 90215;
  94. ERROR_RPC_SERVER_DESERIALIZE_ERROR = 90216;
  95. ERROR_RPC_SERVICE_METHOD_EXIST = 90217;
  96. ERROR_RPC_NO_PRIVILEGE = 90406;
  97. ERROR_RPC_SERVER_REQUEST_TIMEOUT = 90407;
  98. ERROR_RPC_SERVER_SYSTEM_ERROR = 90500;