FAQ about Link SDK for Android
This topic provides answers to some frequently asked questions (FAQ) about Link SDK for Android.
How do I configure ClientId, Username, and Passwd for Link SDK for Android to connect a device to IoT Platform?
For information about how to configure ClientId, Username, and Passwd for Link SDK for Android to connect a device to IoT Platform, see Paho-MQTT Android connection example.
How do I use Link SDK for Android to submit multiple properties or events in the same message?
Link SDK for Android uses a hash map to submit properties. Each key-value pair includes the name of a property that you want to submit and the value of the property. You can specify multiple properties as key-value pairs in a hash map. This way, you can submit multiple properties or events in the same message. In the following sample code, the reportData.put method is used to specify multiple properties. Sample code:
// Report device properties.
Map<String, ValueWrapper> reportData = new HashMap<>();
// The identifier is the property identifier defined in IoT Platform, and valueWrapper is the property value.
reportData.put(identifier1, valueWrapper1); // This is an example. For more information, see the demo.
reportData.put(identifier2, valueWrapper2); // This is an example. For more information, see the demo.
LinkKit.getInstance().getDeviceThing().thingPropertyPost(reportData, new IPublishResourceListener() {
@Override
public void onSuccess(String resID, Object iotSend) {
// The properties are reported successfully.
}
@Override
public void onError(String resID, AError aError) {
// Failed to report the properties.
}
});
What do I do if the error code 4201 is returned when I send an RRPC response?
The following figure shows a sample log that is related to the error code.
714 10591-10591/com.haier.intelrefriger D/ConnectSDK: send() common request
714 10591-10591/com.haier.intelrefriger D/PersistentConnect: send()
715 10591-10591/com.haier.intelrefriger D/MqttNet: getConnectState()
715 10591-10591/com.haier.intelrefriger D/MqttNet: getConnectState() paho state = true
728 10591-10591/com.haier.intelrefriger E/MqttSendExecutor: asyncSend(): convert payload obj to byte array error
728 10591-10591/com.haier.intelrefriger W/System.err: java.io.NotSerializableException: org.json.JSONObject
728 10591-10591/com.haier.intelrefriger W/System.err: at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:xxx)
729 10591-10591/com.haier.intelrefriger W/System.err: at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:34xxx)
729 10591-10591/com.haier.intelrefriger W/System.err: at k.linksdk.channel.core.persistent.mqtt.send.b.asyncSend(MqttSendExecutor.java:124)
729 10591-10591/com.haier.intelrefriger W/System.err: at com.aliyun.alink.linksdk.channel.core.persistent.mqtt.b.asyncSenxxx
729 10591-10591/com.haier.intelrefriger W/System.err: at k.linksdk.channel.core.persistent.PersistentNet.asyncSend(PersistentNet.java:75)
This issue occurs if the JSON data that you constructed is invalid. As a result, an error occurs during data conversion. To resolve the issue, convert the data that you want to send to valid JSON data, and then resend the data as a revert-RPC (RRPC) response.
When I dynamically register a sub-device of a gateway in the IoT Platform console, IoT Platform returns a message that indicates a successful registration. However, an empty list is returned. Why does this issue occur?
Causes
The dynamic registration feature is disabled for the sub-device.
The sub-device is attached to another gateway.
Solution
Check whether the dynamic registration feature is enabled for the sub-device and whether the sub-device is attached to another gateway. If the sub-device is attached to another gateway, detach the sub-device from the gateway, and then dynamically register the sub-device again.
When I dynamically register three sub-devices of a gateway, IoT Platform returns a message that indicates a successful registration. However, only the details of two sub-devices are returned. Why does this issue occur?
Causes
The dynamic registration feature is disabled for the sub-device whose details are not returned.
The sub-device is attached to another gateway.
The identity verification information of the sub-device is invalid.
Solution
Check whether the dynamic registration feature is enabled for the sub-device and whether the sub-device is attached to another gateway. Make sure that the identity verification information of the sub-device is valid, and then dynamically register the sub-device again.
What do I do if the following error message appears when I dynamically register a device: SSLHandshakeException: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: null?
The error message indicates that the dynamic registration request failed to reach IoT Platform. The Message Queuing Telemetry Transport (MQTT) verification fails because the device time was invalid. Check the device time and make sure that it is valid. Then, try again.
How does MQTT reconnection work?
If you enable the MQTT reconnection feature for an MQTT connection that is established between a device and IoT Platform, the system automatically re-establishes an MQTT connection after the device is disconnected from IoT Platform. The first retry interval is 1 second. The subsequent retry interval is twice the previous retry interval from the second retry. For example, the second retry interval is 2 seconds, the third retry interval is 4 seconds, and the fourth retry interval is 8 seconds. This rule applies to subsequent retry intervals until the maximum retry interval is reached. The maximum retry interval is 128 seconds. The maximum retry interval is used for all subsequent retries. Therefore, the system uses the following retry intervals: 1, 2, 4, 8, 16, 32, 64, 128, 128, 128, ...
How do I check whether an MQTT connection is closed?
After an MQTT connection is closed, logs similar to those in the following example are generated:
// Disconnection notification
2020-01-17 11:51:40.607 32730-32730/com.aliyun.alink.devicesdk.demo D/LK-DM-DeviceManager: onConnectStateChange() called with: s = [LINK_PERSISTENT], connectState = [DISCONNECTED]
// Disconnection cause. The SDK may not be able to detect the specific cause of every disconnection. The disconnect error code from the open source library is retained here.
2020-01-17 11:56:30.807 2617-2671/com.aliyun.alink.devicesdk.demo W/LK-core-PersistentEventDispatch: mqtt disconnected, method = [null], content = [null], errorCode = [32109], message = [Connection lost,Connection lost (32109) - javax.net.ssl.SSLException: Read error: ssl=0x7dbe00f708: I/O error during system call, Software caused connection abort]
How do I disable the automatic MQTT reconnection feature of the SDK?
You can use the following code to disable the automatic MQTT reconnection feature of the SDK:
MqttConfigure.automaticReconnect = false;How do I check whether the SDK initiates an automatic reconnection request in logs?
The following log indicates that the Paho SDK automatically initiates a reconnection request. However, the time when the request was initiated is invisible to the upper layer.
2020-01-17 11:38:19.007 32730-32730/com.aliyun.alink.devicesdk.demo I/LK-core-IoTMqttAsyncClient: mqtt-paho connect start, userContext = [null], callback = [com.aliyun.alink.linksdk.channel.core.persistent.mqtt.MqttNet$3@18e0bf], [ clientId = lp_test&a14NQ******|securemode=2,_v=1.7.0,lan=Android,os=9,signmethod=hmacsha1,ext=1,timestamp=1579232298867|]How do I obtain the reconnection result of the SDK in logs?
You can obtain the reconnection result of the SDK from logs similar to those in the following example:
// Paho log
2020-01-07 14:57:06.097 9955-9955/com.aliyun.alink.devicesdk.demo D/LK-core-MqttDefaulCallback: connectComplete, reconnect=true, client=com.aliyun.alink.linksdk.channel.core.itls.IoTMqttAsyncClient@c212ad5,threadId=Thread[main,5,main]
// channel-core log
2020-01-07 14:57:05.095 9955-10005/com.aliyun.alink.devicesdk.demo I/LK-core-MqttDefaulCallback: mqtt connectComplete,reconnect = true ,ssl://a14NQ******.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883
How do I immediately reconnect an Android device to IoT Platform?
After the Link SDK for Android disconnects, the default time before a quick reconnection attempt is 65 seconds. In some scenarios, you may need to reconnect immediately after a disconnection. To do this, use the following code:
LinkKit.getInstance().reconnect();
What are the logs of heartbeat requests and heartbeat responses?
Sample logs of heartbeat requests and heartbeat responses:
// Heartbeat request sent successfully.
2020-01-17 14:04:00.090 9442-9490/com.aliyun.alink.devicesdk.demo D/LK-core-MqttPaho: fine, c= org.eclipse.paho.client.mqttv3.internal.CommsSender , method = run , msg = 802, inserts = Ping,PINGREQ, throwable = null
// Heartbeat response received from IoT Platform.
2020-01-17 14:04:00.103 9442-9489/com.aliyun.alink.devicesdk.demo D/LK-core-MqttPaho: fine, c= org.eclipse.paho.client.mqttv3.internal.Token , method = markComplete , msg = 404, inserts = Ping,PINGRESP msgId 0,null, throwable = null
Can I specify custom heartbeat information?
Yes.
-
You can implement the
MqttPingSenderinterface to customize the heartbeat. For more information, see theTimerPingSenderclass. The TimerPingSender class is an example implementation that lets you schedule the next heartbeat or stop sending them.NoteThe point in time to send a heartbeat must be within the keepalive period of the connection.
Sample code:
// PrivateMqttPingSender implements the MqttPingSender interface. MqttConfigure.pingSender = new PrivateMqttPingSender(); -
On some Android devices, heartbeats may not be sent on time when the device is in sleep mode, which can cause it to go offline. To address this, implement the
AlarmMqttPingSenderinterface for a custom heartbeat.ImportantThis method periodically wakes up the Android system, which may increase power consumption.
Why is the system unable to find a log-related class when I use the SDK?
If the system fails to find a log-related class, an error message appears. The following figure shows a sample error message.
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.aliyun.alink.linksdk:iot-linkkit:1.6.6'
implementation 'com.google.code.gson:gson:2.8.1' // Duplicate dependency
implementation 'com.aliyun.alink.linksdk:breeze:1.2.3'
implementation 'com.aliyun.alink.linksdk:breeze-biz:1.1.0'
implementation 'com.aliyun.alink.linksdk:breeze-ota:1.2.1'
implementation 'com.android.support:multidex:1.0.3'
implementation 'com.google.code.gson:gson:2.8.1' // Duplicate dependency
implementation files('libs/ev-driver-sdk-1.8.jar')
implementation files('libs/Module_Android_DemoPower_1.7.5.1.jar')
```
```text
W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x9ecc9b20)
E/AndroidRuntime: FATAL EXCEPTION: main
Process: hulu.cabinet, PID: 2503
java.lang.NoClassDefFoundError: com.aliyun.alink.linksdk.tools.log.LogcatLogStrategy
at com.aliyun.alink.linksdk.tools.ALog.<clinit>(ALog.java:28)
at com.hulu.cabinet.common.Application.App.onCreate(App.java:86)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1007)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4344)
at android.app.ActivityThread.access$1500(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
The error message indicates that the number of methods in the code exceeds 65,536 and multidex is not supported. In this case, the class is not packed.
What do I do if the following error message appears when I compile the SDK: Task :app:processDebugMainManifest FAILED?
The following information shows the complete error message:
> Task :app:processDebugMainManifest FAILED
/Users/xicai.cxc/Downloads/testApplication/app/src/main/AndroidManifest.xml:8:9-36 Error:
Attribute application@allowBackup value=(false) from AndroidManifest.xml:8:9-36
is also present at [com.aliyun.alink.linksdk:android_alink_id2:1.1.3] AndroidManifest.xml:24:9-35 value=(true).
To resolve the issue, perform the following steps. For more information, see Environment requirements and configurations.
-
In the root directory of the Android project, open the
./AndroidManifest.xmlfile and modify themanifestsection based on the following code:<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" ...> Modify the
applicationsection based on the following code:<application tools:replace="android:allowBackup"
After I call a TSL feature-related operation to send a command to a device, why is the command unable to run as expected even though a value is returned by the onSuccess callback?
If a value is returned by the onSuccess callback, a response is returned by the device regardless of whether the command in the request runs as expected. The response that is returned by the device may fail to reach IoT Platform due to specific causes, such as unstable network connections.
To check whether an issue occurs, log on to the IoT Platform console and view the related logs. For more information, see IoT Platform logs.
We recommend that you do not implement business logic for Thing Specification Language (TSL) feature-related commands based on the value that is returned by the onSuccess callback. You can use the onNotify callback in IConnectNotifyListener in the InitManager.java class to process downstream requests and implement the business logic based on the execution results in the requests.