页面树结构
转至元数据结尾
转至元数据起始

注:从1.0.***之前的版本升级到5.0.1.***请参考Android SDK (V5) 开发指南

注:由于SDK导入方式发生了变化,从5.0.0.***之前的版本升级到5.0.1.***请再次参考Android SDK (V5) 常见问题及解答导入SDK

注:SDK导入说明请参考:Android SDK (V5) 常见问题及解答

1.基础接口使用

一般情况下,云智易Xlink App SDK(以下简称SDK)的使用过程大致如下图所示:

      配置/初始化/启动SDK
              +
              |
           用户授权
           |     |
      获取设备列表 |
           |     |
           |     |
        +--+     v
        |       扫描设备 +----->选择并订阅新设备
        |                             +
        |                             |
        | <---------------------------+
        v
     连接设备
        +---------------------+-----------------+
        |                     |                 |
        |                     |                 |
        v                     v                 v
   设置/查询数据端点    接收设备状态回调    接收云端推送

程序运行前要配置SDK(config),调用start()后生效。

XLinkConfig.Builder configBuilder = new XLinkConfig.Builder()
                        //.setCloudServer("cm2.xlink.cn", 1884) // 设置cm服务器
                        //.setApiServer("https://api2.xlink.cn", 443) // 设置HTTP API服务器
                        .setXLinkCloudListener(xlinkListener) // 设置云端回调监听
                        .setUserListener(xlinkListener) // 设置用户授权状态回调监听
                        .setDataListener(xlinkListener) // 设置数据回调监听
                        .setDeviceStateListener(xlinkListener) //  设置设备状态监听
                        .setDebug(true) // 是否打印SDK日志
                        .setAutoDumpCrash(true) //是否自动转存崩溃日志
XLinkConfig config = configBuilder.Build();
XLinkSDK.setConfig(config);

start()前要进行初始化SDK。

// 初始化SDK, 仅调用一次
XLinkSDK.init(getApplicationContext());

一般来说,配置和初始化同时进行。

// 初始化SDK, config为参数
XLinkSDK.init(getApplicationContext(),config);

部分重要的配置选项列表如下所示:

配置名称含义默认值
setCloudServer(String, int)设置cm服务器cm.xlink.cn, 23778
setApiServer(String, int)设置HTTP API服务器https://api2.xlink.cn, 443
setEnableSSL(Boolean)是否使用SSLtrue
setSSLTrustStoreFileName(String)设置TrustStore路径null
setSSLTrustStorePassword(String)设置TrustStore密码null
setDebug(Boolean)是否打印SDK日志false
setAutoDumpCrash(Boolean)是否自动转存崩溃日志false

对于一般开发者来说,使用默认值即可。

SDK为云端连接状态、数据传输、设备连接状态提供了统一的回调,如下所示:

// 云端回调
configBuilder.setCloudListener(new XLinkCloudListener() {

    @override
    public void onCloudStateChanged(CloudConnectionState state) {
        // 当SDK与云平台连上/断开的时候,会回调这个方法。
    }

    @Override
    public void onEventNotify(EventNotify eventNotify) {
        // 当SDK连接上云端,并接收到云端推送时,会回调这个方法。
    }
});

configBuilder.setUserListener(new XLinkUserListener() {
    @Override
    public void onUserLogout(LogoutReason reason) {
        // 用户被下线(被踢或者手动退出)/授权信息过期 的时候,会回调这个方法。
        // 请根据LogoutReason进行处理
    }
});

// 数据回调
configBuilder.setDataListener(new XLinkDataListener() {

    @Override
    public void onDataPointUpdate(XDevice xDevice, List<XLinkDataPoint> list) {
        // 当SDK收到设备上报的数据端点时,会回调这个方法。
    }
});

// 设备状态回调
configBuilder.setDeviceStateListener(new XLinkDeviceStateListener() {

    @Override
    public void onDeviceStateChanged(XDevice xDevice, XDevice.State state) {
        // 受SDK管理的设备(用户未调用`XLinkSDK.getDeviceManager().removeDevice(xDevice)`)状态发生改变时
    }
    
    @Override
    public void onDeviceChanged(XDevice xDevice, XDevice.Event event) {
        // 设备属性或者设备状态发生改变时,会回调这个方法。
        // 详情请参阅XDevice.Event
    }

});

配置好SDK后,在执行所有SDK提供的Task之前,要先调用start()方法。在stop调用之前,可多次调用start。

// 启动SDK
XLinkSDK.start();

不使用SDK时,可调用stop()

// 停止SDK, 断开云端连接,回收资源
XLinkSDK.stop();

当App退出登录(授权失败、用户主动退出或其他原因需要重新授权的情况,一般在onUserLogout回调中使用)时,可调用logoutAndStop()

// 停止SDK, 断开云端连接,回收资源,清除授权信息。
XLinkSDK.logoutAndStop();

启动SDK后,若要使用云端服务相关操作(获取设备列表、通过云端获取数据端点、添加设备、删除设备等),需进行用户授权:

XLinkUserAuthorizeTask task = XLinkUserAuthorizeTask.newBuilder()
            .setPhone(<phone>, <password>)// 手机号和密码
            .setEmail(<email>, <password>)// 邮箱和密码,setPhone和setEmail二选一即可。
            .setCorpId(<corpId>) //企业ID
            .setListener(new XLinkTaskListener<UserAuthApi.UserAuthResponse>() {
                @Override
                public void onError(XLinkErrorCode errorCode) {
                    // 登录失败
                }

                @Override
                public void onStart() {
                }

                @Override
                public void onComplete(UserAuthApi.UserAuthResponse result) {
                    // 登录成功,在result中含有授权信息
                    // SDK内部自动进行云端连接
                }
            })
            .build();
    XLinkSDK.startTask(task); 

如使用第三方登陆,请调用XLinkThirdPartyAuthorizeTask:

XLinkThirdPartyAuthorizeTask task = XLinkThirdPartyAuthorizeTask.newBuilder()
            .setOpenId(<openId>, <accessToken>)// 第三方授权后获取的openId和accessToken
            .setCorpId(<corpId>) //企业ID
            .setSource(XLinkRestfulEnum.UserSource.WEIXIN)//登录源,来源类型有以下几种
            .setListener(new XLinkTaskListener<ThirdPartyAuthApi.AuthResponse>() {
                @Override
                public void onError(XLinkErrorCode errorCode) {
                    // 登录失败
                }

                @Override
                public void onStart() {
                }

                @Override
                public void onComplete(ThirdPartyAuthApi.AuthResponse result) {
                    // 登录成功,在result中含有授权信息
                    // SDK内部自动进行云端连接
                }
            })
            .build();
    XLinkSDK.startTask(task); 
//登录源,来源类型有以下几种
public static enum UserSource {
	WEB(1),
	ANDROID(2),
	IOS(3),
	WEIXIN(4),
	QQ(5),
	WEIBO(6),
	FACEBOOK(7),
	TWITTER(8),
	OTHER(10);
}


由于SDK内部需要授权信息,请使用SDK提供的授权接口进行授权,不要自行通过Restful进行用户授权。

1. 2 添加新设备

一般来说,添加设备的流程如下所示:

重置设备 ----> 设备配网 ----> 搜索同一局域网下的云智易设备 ----> 添加设备

                                                   |------------------------XLinkSDK提供-----------------------------|

下面对SDK相关的步骤进行描述。

1.2.1 发现新描设备

可通过该接口自动扫描并发现同一局域网内的新设备。

首先,新建扫描设备任务:

XLinkScanDeviceTask scanTask = XLinkScanDeviceTask.newBuilder()
                            .setProductIds("123456789", "987654321", ...)
                            .setTotalTimeout(90000) // 设置超时,单位毫秒,默认90秒
                            .setRetryInterval(3000) // 设置扫描间隔,默认3秒,如无必要,请使用默认参数
                            .setScanDeviceListener(new XLinkScanDeviceListener() { // 设置搜索回调, **回调在主线程上执行**

                                @override
                                public void onError(XLinkErrorCode errorCode){
                                    switch(errorCode) {
                                        ...
                                    }    
                                }
                                
                                @override
                                public void onStart(){}

                                @override
                                public void onComplete(Void result){}

                                @override
                                public void onScanResult(XDevice xDevice){
                                    // 同一设备仅会回调一次    
                                }
                            })
                            .build();

执行扫描设备, 在异步线程上执行。

XLinkSDK.startTask(scanTask);

停止扫描

XLinkSDK.stopTask(scanTask);
// 这样子也可以
scanTask.cancel(); 

1.2.2 添加设备

对于一般开发者来说,添加设备的代码如下所示:

新建添加设备任务

XLinkAddDeviceTask addDeviceTask = XLinkAddDeviceTask.newBuilder()
                                    .setDevice(mXDevice)
                                    .setListener(new XLinkTaskListener<XDevice>() { // 设置本次订阅任务的回调

                                        @override
                                        public void onError(XLinkErrorCode errorCode){
                                            switch(errorCode) {
                                                ...
                                            }    
                                        }
                                        
                                        @override
                                        public void onStart(){}
                                        
                                        @override
                                        public void onComplete(XDevice xDevice){
                                            // 订阅成功
                                        }
                                    })
                                    .build();


// 执行订阅设备
XLinkSDK.startTask(addDeviceTask);

// 中断订阅
XLinkSDK.stopTask(addDeviceTask);
// 这样子也可以
scanTask.cancel();

已添加成功的设备,SDK会自动在云端建立当前用户账号与设备的订阅关系,并用于后续的数据更新和同步,具体请参考下文的“同步设备列表”。


1.3 删除设备

新建删除设备任务

XLinkRemoveDeviceTask removeDeviceTask = XLinkRemoveDeviceTask.newBuilder()
                                    .setDevice(mXDevice)
                                    .setListener(new XLinkTaskListener<Void>() { // 设置本次删除设备任务的回调

                                        @override
                                        public void onError(XLinkErrorCode errorCode){
                                            switch(errorCode) {
                                                ...
                                            }    
                                        }
                                        
                                        @override
                                        public void onStart(){}

                                        @override
                                        public void onComplete(Void result){
                                            // 删除设备成功
                                        }
                                    })
                                    .build();

// 执行删除设备
XLinkSDK.startTask(removeDeviceTask);

// 中断删除设备
XLinkSDK.stopTask(removeDeviceTask);
// 这样子也可以
removeDeviceTask.cancel();

已成功删除的设备,SDK会自动从云端解除当前用户与设备之间的订阅关系,并删除与该设备相关的共享和访问权限。

1.4 同步设备列表

将当前用户的设备设备从云端同步到本地。要求设备和当前用户之间有订阅关系。任务完成后默认自动发起本地连接和云端连接

XLinkSyncDeviceListTask getDeviceListTask = XLinkSyncDeviceListTask.newBuilder()
                                    .setConnectLocal(true) // 是否自动进行本地连接,默认 true
                                    .setListener(new XLinkTaskListener<List<XDevice>>() { // 设置获取设备列表任务的回调

                                        @override
                                        public void onError(XLinkErrorCode errorCode){
                                            switch(errorCode) {
                                                case XLinkErrorCode.NOT_CONNECTED_SERVER:
                                                    break;
                                                ...
                                            }    
                                        }
                                        
                                        @override
                                        public void onStart(){
                                        }

                                        @Override
                                        public void onComplete(List<XDevice> xDevices) {
                                            // 已同步好的设备列表
                                        }
                                    })
                                    .build();

// 执行获取设备列表任务
XLinkSDK.startTask(getDeviceListTask);

// 中断获取设备列表任务
XLinkSDK.stopTask(getDeviceListTask);
// 这样子也可以
getDeviceListTask.cancel();

1.5 连接设备

控制设备,或者获取设备信息之前,必须先对设备进行连接。这里是指SDK于设备之间通过内网或者外网进行连接。

SDK会自动维护设备的连接,即SDK检测到与设备断开连接后,会自动重连。

具体使用方法如下所示:

// 新建连接任务
XLinkConnectDeviceTask connectTask = XLinkConnectDeviceTask.newBuilder()
                                    .setDevice(mXDevice)
                                    .setListener(new XLinkTaskListener<XDevice>() {
                                        @Override
                                        public void onError(XLinkErrorCode errorCode) {
                                            // 连接失败
                                        }

                                        @Override
                                        public void onStart() {
                                        }

                                        @Override
                                        public void onComplete(XDevice result) {
                                            // 设备变为已连接状态(内网或者外网已连接上)
                                        }
                                    })
                                    .build();


// 执行连接设备
XLinkSDK.startTask(connectTask);

// 中断连接过程
XLinkSDK.stopTask(connectTask);
// 这样子也可以
connectTask.cancel();

连接设备成功后,在XLinkSDK的XLinkDeviceStateListener中的onDeviceStateChanged()会被调用。

//订阅设备状态变化
configBuilder.setDeviceStateListener(new DeviceStateListener() {

    @Override
    public void onDeviceStateChanged(XDevice xDevice, XDevice.State state) {
        switch(state) {
            case OFFLINE:
                break;
            case ONLINE:
                break;
            ...
        }
    }

});

SDK可以断开与设备的本地连接:

XLinkSDK.disconnectLocal(mXDevice);


1.6 获取设备状态和控制设备

云智易平台采用数据端点来描述物理设备的状态和能力,例如,可通过设备状况的查询和回调接口来获取设备的实时状态;可通过更新数据端点状态的接口来实现设备的远程控制。

SDK支持指定内网的本地连接或外网的云端连接来发送数据。也可以采用AUTO模式由SDK底层自适应内外的数据通讯。

数据发送的策略有如下几种:

/**
 * 数据发送策略。默认为AUTO
 */
public enum XLinkSendDataPolicy {
    /**
     * 自动选择发送数据的通道(内/外网)。选择的依据是当前通道的RTT(Round-Trip Time,往返时延)
     * RTT低的通道会被选中。
     */
    AUTO,
    /**
     * 只尝试从内网发送。
     */
    LOCAL_ONLY,
    /**
     * 只尝试从外网发送。
     */
    CLOUD_ONLY,
    /**
     * 尝试从内网发送,失败则尝试外网发送。
     */
    LOCAL_FIRST,
    /**
     * 尝试从外网发送,失败则尝试内网发送。
     */
    CLOUD_FIRST
}

在初始化 XLinkSDK 时可以设置数据发送策略:

XLinkConfig config = new XLinkConfig.Builder()
            ...
            .setSendDataPolicy(XLinkSendDataPolicy.CLOUD_ONLY)
            ...

查询/修改数据端点之前,必须先对设备进行连接。若要使用云端的数据存储/告警功能,则设备需要连接上云服务器。


//接收数据端点变化的回调
configBuilder.setDataListener(new XLinkDataListener() {

    ...

    @Override
    public void onDataPointUpdate(XDevice xDevice, List<XLinkDataPoint> list) {}

    ...

});

// 查询数据端点的值
XLinkGetDataPointTask task = XLinkGetDataPointTask.newBuilder()
    .setXDevice(xDevice)
    .setListener(new XLinkTaskListener<List<XLinkDataPoint>>() {
        @Override
        public void onError(XLinkErrorCode errorCode) {
            Log.d(TAG, "XLinkGetDataPointTask onError() called with: errorCode = [" + errorCode + "]");
        }

        @Override
        public void onStart() {
        }

        @Override
        public void onComplete(List<XLinkDataPoint> result) {
            Log.d(TAG, "XLinkGetDataPointTask onComplete() called with: result = [" + result.size() + "]");
        }
    })
    .build();

//修改数据端点,控制设备
XLinkSetDataPointTask task = XLinkSetDataPointTask.newBuilder()
    .setXDevice(xDevice)
    .setDataPoints(dataPoints)
    .setListener(new XLinkTaskListener<XDevice>() {
        @Override
        public void onError(XLinkErrorCode errorCode) {
        }

        @Override
        public void onStart() {

        }

        @Override
        public void onComplete(XDevice result) {
        }
    })
    .build();

//当数据端点发生变化时,XLinkDataListener会收到回调
configBuilder.setDataListener(new XLinkDataListener() {

    ...

    @Override
    public void onDataPointUpdate(XDevice xDevice, List<XLinkDataPoint> list) {
        // 当SDK收到设备上报的数据端点时,会回调这个方法。
    }

    ...
});

//用户可以指定订阅某些数据端点的变化,传入数据端点的 index 值列表。
XLinkSDK.getDataPointManager().addXLinkDataPointObserver(Arrays.asList(1, 2), new 		  XLinkDataPointObserver() {
    @Override
    public void onDataPointUpdate(XDevice xDevice, List<XLinkDataPoint> list) {
        //
    }
});

//退订某个数据端点的变化
XLinkSDK.getDataPointManager().removeXLinkDataPointObserver(mDataPointObserver);

1.7 接收云端推送(EventNotify)

当SDK使用了云端功能,并连接到云端时,SDK可以收到云端推送的消息。

消息有3种类型,分别是:设备状态、云端通知、告警回调。可以通过eventNotify.type进行区分。

configBuilder.setCloudListener(new XLinkCloudListener() {

    ...

    // 在此处接收服务器的消息通知
    @Override
    public void onEventNotify(EventNotify eventNotify) {

        switch(eventNotify.type) {
            case EventNotify.SUBSCRIPTION_CHANGED:
                <YourOwnDispatcher>.handle(eventNotify);
                break;
            ...
        }

    }

});

1.8 日志功能

SDK运行时会打印日志信息。开发完成后,发布应用时不应显示这些信息。设置setDebug(false)后,SDK不会输出除异常以外的日志信息。

// 配置SDK
XLinkConfig config = new XLinkConfig.Builder()
                        ...
                        .setDebug(true) // 是否打印SDK日志
                        .setAutoDumpCrash(true) //是否自动转存崩溃(crash)日志,默认在`SD卡目录/xlink/`下
                        ...
                        .Build();
XLinkSDK.setConfig(config);


2. 进阶使用

2.1 XLinkTaskListener

SDK中大部分Task都需通过添加XLinkTaskListener回调来获取结果。XLinkTaskListener各成员方法解析如下所示:

XLinkTaskListener<T>() { // 回调结果为类型T

    // Task运行过程中出现错误会回调这个方法(不再调用onComplete)
    @override
    public void onError(XLinkErrorCode errorCode){
        switch(errorCode) {
            ...
        }    
    }
    
    // Task开始运行时会回调这个方法
    @override
    public void onStart(){
    }

    // Task运行结束会回调这个方法(无错误发生)
    @Override
    public void onComplete(T result) {

    }
}

XLinkErrorCode中包含了SDK处理的所有类型的错误码。另外,在XLinkTaskListener中可通过getThrowable()取出原始Throwable,从而得知更详细的错误信息:

    @override
    public void onError(XLinkErrorCode errorCode){
        ......
        Throwable orginalThrowable = getThrowable();
        orginalThrowable.printStackTrace();
        ......
    }

2.2 设备连接状态的刷新

开发app的时候经常需要显示设备的连接状态,很多用例也依赖于设备的连接状态(例如控制设备的时候要求设备在线)。所以如何准确地在app与设备之间同步连接状态是我们首先要解决的问题。

设备状态可以通过getConnectionState()在XDevice实体中取出,代码如下:

XDevice device = XLinkSDK.getDeviceMananger().getDevice(mMacAddressString);
XDevice.State connectionState = device.getConnectionState(); 

对一般开发者来说,设备的连接状态可以用下图表示:

sdk_4_3_设备状态图1

注:detached状态指设备对象刚生成,尚未进行首次连接状态同步时的状态,一般开发者无需处理。

设备可以处于内网连接状态和外网连接状态,可以通过以下代码获取:

XDevice.State innerConnectionState = device.getLocalConnectionState();
XDevice.State outterConnectionState = device.getCloudConnectionState();

开发者可以订阅设备的状态变化,如下所示:

configBuilder.setDeviceStateListener(new XLinkDeviceStateListener() {

    @Override
    public void onDeviceStateChanged(XDevice xDevice, XDevice.State status) {
        switch(status) {
            case OFFLINE:
                ...
                break;
            ...
        }
    }

});

// 或者
XLinkDeviceManager.getInstance().addDeviceStateListener(new XLinkDeviceStateListener() {

    @Override
    public void onDeviceStateChanged(XDevice xDevice, XDevice.State status) {
        switch(status) {
            case OFFLINE:
                ...
                break;
            ...
        }
    }

});
addDeviceStateListener()会持有DeviceStateListener的强引用,所以记得取消订阅以免引起内存泄漏:
XLinkDeviceManager.getInstance().removeDeviceStateListener(mDeviceStateListener);
onDeviceStateChanged(XDevice xDevice, XDevice.State status)status的含义如下所示:
含义
DETACHEDXDevice的状态未知
OFFLINESDK设备与设备失去连接
CONNECTINGSDK正在连接设备
ONLINESDK设备保持连接

device.getConnectionState()的返回值由device.getLocalConnectionState()device.setCloudConnectionState()决定,遵循以下规则:

  1. getConnectionState()返回OFFLINE时,表示SDK与设备无内外网连接。
  2. getConnectionState()返回ONLINE时,表示SDK与设备内外网连接或者内网连接。
  3. getConnectionState()返回CONNECTING时,表示SDK与设备无内外网连接,但正在尝试进行内网或者外网连接。
  4. getConnectionState()返回DETACHED时,表示SDK尚未尝试过内网或者外网连接。

 简单地说,如果开发者不关心设备与SDK的连接方式,只需处理getConnectionState()即可。当getConnectionState()返回ONLINE时,开发者可向设备发送数据。

2.3 数据端点的使用

数据端点是对设备运行状态的一种描述,它支持多种数据格式,如布尔、单字节、短整型、长整形以及字符串等。 当设备的数据端点发生变化,若设备已经连接到云端,那数据端点的变化将会通过云智易提供的硬件SDK,同步到云端上,以便厂商在云平台查看与收集设备的运行状态的变化。

2.3.1 端点数据格式

一个设备的数据端点个数最多为200个,每个数据端点由如下格式组成:

数据端点索引数据长度数据
1字节2字节N字节,长度由数据长度决定

注:数据长度的高字节的高4位表示数据类型,数据长度的高字节的低4位和低字节表示数据长度。

2.3.2 端点数据类型

数据类型定义如下:

数据类型(16进制)类型(高字节在前)Java数据类型
0Byte或者BOOLBoolean或Byte
1Int16Short
2Unsigned Int16Short
3Int32Integer
4Unsigned Int32Integer
5Int64Long
6Unsigned Int64Long
7Float(IEEE754标准)Float
8Double(IEEE754标准)Double
9StringString
ABinary(二进制数据块)byte[]
B-F保留


2.4 服务器推送

前文提到,开发者可以通过XLinkCloudListener接收服务器的推送消息。这里的'推送'不单指通常意义上的文本消息的推送,还包含用户或者设备变化的通知消息。 EventNotify类如下所示:

public class EventNotify implements Serializable {
    
    public static final int FROM_TYPE_FROM_SERVER = 0x01;
    public static final int FROM_TYPE_FROM_DEVICE = 0x02;
    public static final int FROM_TYPE_FROM_APP = 0x03;


    ...
    public byte fromType;
    public int fromId;
    public byte notifyFlags;
    public short messageType;
    public byte[] payload;
    ...
}


开发者可以通过EventNotify.type的来判断消息类型,再根据EventNotify.data来处理消息数据。 当消息数据是字符串时,消息数据前两个字节是字符串的长度,其后紧接着数据。

值得注意的是,当事件来源`fromType`是FROM_TYPE_FROM_DEVICE时,EventNotify.fromId为deviceId。当事件来源`fromType`是FROM_TYPE_FROM_SERVER时,EventNotify.fromId为0。是FROM_TYPE_FROM_APP时,EventNotify.fromId为appid。


消息类型如下表所示:

类型描述
DATA_POINT_CHANGED1设备数据端点变化发送的通知
DATA_POINT_ALERT2设备数据端点变换引起的报警
DEVICE_SHARE3设备管理员推送的分享消息
BROADCAST4厂商推送的消息广播
DEVICE_PROP_CHANGED5设备属性变化通知
SUBSCRIPTION_CHANGED6用户和设备订阅关系发生变化通知
DEVICE_ONLINE_STATE_CHANGED7设备在线状态变化引发的通知
DEVICE_ONLINE_STATE_ALERT8设备在线状态变化引发的告警

各类型对应的数据格式如下所示:

DATA_POINT_CHANGED
JSON
{
    "index" : 0,
    "value" : 100,
    "msg": 管理台设置的报警内容
}

DATA_POINT_ALERT
JSON
{
    "index" : 0,
    "value" : 100,
    "msg": 管理台设置的报警内容
}

DEVICE_SHARE
JSON
{
    "device_id" : 123457
    "invite_code" : 12345,
    "type":0/1/2/3
}

type: 
0 分享请求
1 接受分享
2 拒绝分享
3 分享被取消

BROADCAST
JSON
{
    "msg_type": "txt",
    "action_type": "url/command",
    "url": "http://xxxx.xxx.xxx",
    "command": "xxxx",
    "title": "xxxx",
    "content": "xxxxx"
}

参数:
msg_type:消息类型,暂时只有txt
action_type:url/command
url: 打开链接
command:用户自定义动作
url:如果action_type是url时的参数
command:如果action_type是command时的参数;
title:消息标题,UTF-8
content:消息内容,UTF-8

DEVICE_PROP_CHANGED
JSON
{
    "device_id" : 123456789
    "type" : "info/prop"
}

type: 
info 设备基本属性变化
prop 设备扩展属性变化

SUBSCRIPTION_CHANGED
JSON
{
    "device_id" : 123456789
    "sub" : 0/1
}

sub:
0 订阅关系取消
1 订阅关系建立

DEVICE_ONLINE_STATE_CHANGED
JSON
{
    "device_id" : 123456789
    "state" : 0 / 1
}

state:
0 离线
1 上线

DEVICE_ONLINE_STATE_ALERT
JSON
{
    "device_id" : 123456789
    "state" : 0 / 1
}

state:
0 离线
1 上线

SDK内置了EventNotifyHelper类方便开发者解析消息推送,使用方法如下:

configBuilder.setCloudListener(new XLinkCloudListener() {

    ...

    // 在此处接收服务器的消息通知
    @Override
    public void onEventNotify(EventNotify eventNotify) {

        switch(eventNotify.type) {
            case EventNotify.SUBSCRIPTION_CHANGED:
                // 调用对应的解析api来解析data
                SubscriptionChangeNotify notify = EventNotifyHelper.parseSubscriptionChangeNotify(eventNotify.data);

                ... // 处理notify

                break;
            ...
        }

    }

});


注1:开发者在使用sdk时,如果想避免通过轮询的方式来更新状态,应利用上述通知来更新状态。
注2:目前消息通知在服务器端不会缓存,即离线后上线,期间的消息通知不会再次收到。
注3:消息通知功能需用户登录,并使用云平台服务。

2.5 用户授权管理

调用XLinkUserAuthorizeTask或XLinkThirdPartyAuthorizeTask后,XLinkSDK内部会维护一个XLinkUser对象,里面包含了通讯所需的授权信息:


public class XLinkUser implements XLinkAuthProvider {

    private String mAccessToken;

    private String mRefreshToken;

    private String mAuthString;

    private int mUid;


    ....
}

此对象可通过如下方法取出:

XLinkSDK.getUser();

请不要修改XLinkUser对象内的授权信息。如果开发者需要取出accesstoken、uid等信息,直接调用XLinkUser对象的get方法即可。值得注意的是,app运行时,XLinkSDK会自动更新XLinkUser内部的授权信息,所以开发者应避免自己缓存XLinkUser里的属性(例如把accessToken存在一个变量里),应在每次需要的时候直接调用XLinkSDK.getUser()取出授权信息

app首次打开时(未有用户信息),应跳转至登录页面让用户登陆。登陆动作应包含运行XLinkUserAuthorizeTask或XLinkThirdPartyAuthorizeTask。如果要实现用户在下次打开app时跳过登陆动作,那么在首次授权时需要保存授权信息,在下次打开app启动SDK前提供授权信息

XLinkUserAuthorizeTask task = XLinkUserAuthorizeTask.newBuilder()
            .setPhone(<phone>, <password>)// 手机号和密码
            .setCorpId(<corpId>) //企业ID
            .setListener(new XLinkTaskListener<UserAuthApi.UserAuthResponse>() {
                ...

                @Override
                public void onComplete(UserAuthApi.UserAuthResponse result) {
                    ...

                    // app要保存授权信息,下次打开app跳过登陆的步骤
                    UserManager.getInstance().setUid(result.user_id);
                    UserManager.getInstance().setAccessToken(result.access_token);
                    UserManager.getInstance().setAuthString(result.authorize);
                    UserManager.getInstance().setRefreshToken(result.refresh_token);

                    ...
                }
            })
            .build();
    XLinkSDK.startTask(task); 

再次启动SDK前通过如下方式提供授权信息:

...
// 新建XLinkUser对象,设置保存了的授权信息。AccessToken、RefreshToken、Uid、AuthString四个信息缺一不可。
XLinkUser lastUser = new XLinkUser();
lastUser.setAccessToken(UserManager.getInstance().getAccessToken());
lastUser.setRefreshToken(UserManager.getInstance().getRefreshToken());
lastUser.setUid(UserManager.getInstance().getUid());
lastUser.setAuthString(UserManager.getInstance().getAuthString());


XLinkConfig config = new XLinkConfig.Builder()
                ...
                .setXLinkUser(lastUser) // 设置授权信息
                ...
                .build();

设置好以后,在start()的同时,SDK会自动验证授权信息是否合法,合法则进行云端和后续一系列的内部操作。

一般来说,需要重新授权有如下几个原因:

  • 用户被踢出(单点登录)
  • 过期(含缺失,格式错误等原因)
  • 用户主动退出

当出现如上情况时,onUserLogout(LogoutReason reason)会回调:

    @Override
    public void onUserLogout(LogoutReason reason) {
        switch (reason) {
            case SINGLE_SIGN_KICK_OFF: // 用户被踢出
                Log.w(TAG, "SINGLE_SIGN_KICK_OFF");
                break;
            case TOKEN_EXPIRED: // 过期
                Log.w(TAG, "TOKEN_EXPIRED");
                break;
            case USER_LOGOUT: // 用户主动退出
                Log.w(TAG, "USER_LOGOUT");
                break;
        }
    }

注:如果LogoutReason为SINGLE_SIGN_KICK_OFF或TOKEN_EXPIRED时,应主动调用XLinkSDK.logoutAndStop()。如果是USER_LOGOUT,则无需主动调用XLinkSDK.logoutAndStop()(因为USER_LOGOUT由logoutAndStop()触发)

2.6 设备订阅关系管理

通过XLinkAddDeviceTask可在云端建立用户和设备之间的订阅关系。订阅关系建立后,可使用XLinkSyncDeviceListTask获取与当前用户有订阅关系的设备列表。通过XLinkRemoveDeviceTask可解除订阅关系。

订阅关系的建立可通过以下途径:

  • 添加设备
  • 设备分享
  • 其他建立云端订阅关系的途径

订阅关系的解除可通过以下途径:

  • 删除设备
  • 设备重新激活(设备重置后再连上云端,设备会重新激活)
  • 其他解除云端订阅关系的途径

在订阅关系建立或解除时,以下两个回调会被触发:

    @Override
    public void onDeviceChanged(XDevice xDevice, XDevice.Event event) {
       switch(event) {
           case SUBSCRIBE: // 与xDevice的订阅关系建立
               break;
           case UNSUBSCRIBE: // 与xDevice的订阅关系解除
               break;
       }
    }
@Override
    public void onEventNotify(EventNotify eventNotify) {
        switch (eventNotify.messageType) {
            ...
            case EventNotify.MSG_TYPE_SUBSCRIPTION_CHANGE: {
                EventNotifyHelper.SubscriptionChangeNotify notify = EventNotifyHelper.parseSubscriptionChangeNotify(eventNotify.payload);
                for (Device device :
                        DeviceManager.getInstance().getAllDevices()) {
                    if (device.getXDevice().getDeviceId() == notify.device_id) {
                        if (notify.sub == EventNotifyHelper.SubscriptionChangeNotify.SUBSCRIBED) {
                            // 与xDevice的订阅关系建立
                        }else if (notify.sub == EventNotifyHelper.SubscriptionChangeNotify.UNSUBSCRIBED) {
                            // 与xDevice的订阅关系解除
                        }
                    }
                }
            }
            ...
        }
        ...
    }

开发者选择其中一个进行处理即可。当接收到订阅关系变化的通知时,SDK内部已断开和设备的连接,开发者应主动或提示用户刷新设备列表。

注:以上两个回调依赖云端连接,是云端的推送消息,主要提供给APP开发者处理订阅关系被动建立或被动解除的情况(例如人为重置设备)。如果是用户主动添加或删除设备(XLinkAddDeviceTask或XLinkRemoveDeviceTask),那么在执行成功的时候就要进行后续处理(例如刷新设备列表,更新ui等等),不要等待云端通知再进行处理。

2.7 设备分享管理

通过XLinkShareDeviceTask可以将设备权限分享给其他在平台里已经注册的用户。

// 新建XLinkShareDeviceTask
XLinkShareDeviceTask task = XLinkShareDeviceTask.newBuilder()
        .setXDevice(device.getXDevice()) // 要分享出去的设备
        .setMode(XLinkRestfulEnum.ShareMode.ACCOUNT) // 分享模式。
        .setAccount(account) // 对方的账号
        .setExpired(expired) // 该次分享有效期,单位秒
        .setListener(new XLinkTaskListener<String>() {
            @Override
            public void onError(XLinkErrorCode xLinkErrorCode) {
                Log.d(TAG, "XLinkShareDeviceTask onError() called with: xLinkErrorCode = [" + xLinkErrorCode + "]");
            }

            @Override
            public void onStart() {
                if (getView() != null) {
                    getView().showLoading();
                }
            }

            @Override
            public void onComplete(String s) {
                Log.d(TAG, "XLinkShareDeviceTask onComplete() called with: s = [" + s + "]");
            }
        })
        .build();
XLinkSDK.startTask(task);

当接受分享方在线时,对方的XLinkCloudListener中的onEventNotify会收到类型为EventNotify.MSG_TYPE_DEVICE_SHARE的通知:

    @Override
    public void onEventNotify(EventNotify eventNotify) {
        // 当SDK连接上云端,并接收到云端推送时,会回掉这个方法。
        Log.d(TAG, "onEventNotify() called with: " + "eventNotify.messageType = [" + eventNotify.messageType + "]");
        switch (eventNotify.messageType) {
            case EventNotify.MSG_TYPE_DEVICE_SHARE:
                // 收到分享请求
                handleDeviceShareNotify(eventNotify);
                break;
            ....
        }
    }

开发者可通过EventNotifyHelper来获取分享的类型,如下所示:

    private void handleDeviceShareNotify(EventNotify eventNotify) {
        final EventNotifyHelper.DeviceShareNotify notify = EventNotifyHelper.parseDeviceShareNotify(eventNotify.payload);
        Log.d(TAG, "handleDeviceShareNotify: " + notify);
        ...
        switch (notify.type) {
            case EventNotifyHelper.DeviceShareNotify.TYPE_RECV_SHARE: //收到新的分享
                ...
                break;
            case EventNotifyHelper.DeviceShareNotify.TYPE_ACCEPT_SHARE: // 发出去的分享被接受
                ...
                break;
            case EventNotifyHelper.DeviceShareNotify.TYPE_CANCEL_SHARE: // 原有的分享被取消
                ...
                break;
            case EventNotifyHelper.DeviceShareNotify.TYPE_DENY_SHARE: // 发出去的分享被拒绝
                ...
                break;
        }
    }

开发者可以使用XLinkHandleShareDeviceTask对分享进行处理,如下所示:

XLinkHandleShareDeviceTask task = XLinkHandleShareDeviceTask.newBuilder()
                .setAction(XLinkHandleShareDeviceTask.Action.ACCEPT) // 接受该次分享
                .setAction(XLinkHandleShareDeviceTask.Action.ACCEPT_QRCODE) // 接受该次二维码分享
                .setAction(XLinkHandleShareDeviceTask.Action.DENY) // 拒绝这次分享
                .setAction(XLinkHandleShareDeviceTask.Action.CANCEL) // 取消已经分享出去的分享条目
                .setAction(XLinkHandleShareDeviceTask.Action.DELETE) // 删除该次分享条目
                .setInviteCode(notify.invite_code) // 待处理的分享的id
                .setUid(UserManager.getInstance().getUid()) // 当前用户的uid
                .setListener(new XLinkTaskListener<String>() {
                    @Override
                    public void onError(XLinkErrorCode xLinkErrorCode) {
                        ...
                    }

                    @Override
                    public void onStart() {
                        ...
                    }

                    @Override
                    public void onComplete(String s) {
                        ...
                    }
                })
                .build();
        XLinkSDK.startTask(task);

详情见demo中关于设备分享部分的代码及注释

2.8 Restful API

SDK包装了部分常用的Restful API,例如用户注册、登陆、找回密码等等。完整的Restful API文档在:Restful API文档
用户通过如下方式可调用Restful API:
XLinkRestful.getApplicationApi().*****
用户调用其提供的方法即可,例如:

// 用户登陆
UserAuthApi.UserAuthRequest request = new UserAuthApi.UserAuthRequest();
request.corp_id = mCorpId;
request.email = mEmail;
request.phone = mPhone;
request.password = mPwd;
XLinkRestful.getApplicationApi().authorizeUser(request)...

SDK使用retrofit2作为HTTP请求库,使用方法请参考官方文档:http://square.github.io/retrofit/

若SDK自带Restful API接口不能满足需求,开发者需自己实现,可通过如下方式:

使用OkHttpClient

// 使用SDK内部的HttpClient, 使用此client发送request会自动添加AccessToken
OkHttpClient yourOwClient = XLinkRestful.getApiHttpClient();

使用retrofit2

Retrofit.Builder builder = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    // 使用SDK内部的HttpClient, 使用此client发送request会自动添加AccessToken
                    .builder.client(XLinkRestful.getApiHttpClient());


Retrofit yourOwnRetrofit = builder.build();

其他方式

若开发者使用其他方式,要注意AccessToken必须从SDK取出,即当开发者调用需要accesstoken的接口时,必须使用XLinkSDK.getAccessToken()返回的accesstoken,并且不要缓存起来使用(例如保存在一个变量中)。

编写评论...