这是我的代码
try {
if (AWSIotKeystoreHelper.isKeystorePresent(keystorePath, keystoreName)) {
if (AWSIotKeystoreHelper.keystoreContainsAlias(certificateId, keystorePath,
keystoreName, keystorePassword)) {
Log.i(LOG_TAG, "Certificate " + certificateId
+ " found in keystore - using for MQTT.");
// load keystore from file into memory to pass on connection
clientKeyStore = AWSIotKeystoreHelper.getIotKeystore(certificateId,
keystorePath, keystoreName, keystorePassword);
btnConnect.setEnabled(true);
mqttManager.setAutoReconnect(false);
} else {
Log.i(LOG_TAG, "Key/cert " + certificateId + " not found in keystore.");
}
} else {
Log.i(LOG_TAG, "Keystore " + keystorePath + "/" + keystoreName + " not found.");
}
} catch (Exception e) {
Log.e(LOG_TAG, "An error occurred retrieving cert/key from keystore.", e);
}
if (clientKeyStore == null) {
Log.i(LOG_TAG, "Cert/key was not found in keystore - creating new key and certificate.");
new Thread(new Runnable() {
@Override
public void run() {
try {
// Create a new private key and certificate. This call
// creates both on the server and returns them to the
// device.
CreateKeysAndCertificateRequest createKeysAndCertificateRequest =
new CreateKeysAndCertificateRequest();
createKeysAndCertificateRequest.setSetAsActive(true);
final CreateKeysAndCertificateResult createKeysAndCertificateResult;
createKeysAndCertificateResult =
mIotAndroidClient.createKeysAndCertificate(createKeysAndCertificateRequest);
Log.i(LOG_TAG,
"Cert ID: " +
createKeysAndCertificateResult.getCertificateId() +
" created.");
// store in keystore for use in MQTT client
// saved as alias "default" so a new certificate isn't
// generated each run of this application
AWSIotKeystoreHelper.saveCertificateAndPrivateKey(certificateId,
createKeysAndCertificateResult.getCertificatePem(),
createKeysAndCertificateResult.getKeyPair().getPrivateKey(),
keystorePath, keystoreName, keystorePassword);
// load keystore from file into memory to pass on
// connection
clientKeyStore = AWSIotKeystoreHelper.getIotKeystore(certificateId,
keystorePath, keystoreName, keystorePassword);
// Attach a policy to the newly created certificate.
// This flow assumes the policy was already created in
// AWS IoT and we are now just attaching it to the
// certificate.
AttachPrincipalPolicyRequest policyAttachRequest =
new AttachPrincipalPolicyRequest();
policyAttachRequest.setPolicyName(AWS_IOT_POLICY_NAME);
policyAttachRequest.setPrincipal(createKeysAndCertificateResult
.getCertificateArn());
mIotAndroidClient.attachPrincipalPolicy(policyAttachRequest);
runOnUiThread(new Runnable() {
@Override
public void run() {
btnConnect.setEnabled(true);
}
});
} catch (Exception e) {
Log.e(LOG_TAG,
"Exception occurred when generating new private key and certificate.",
e);
}
}
}).start();
}
}
View.OnClickListener connectClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(LOG_TAG, "clientId = " + clientId);
try {
mqttManager.connect(clientKeyStore, new AWSIotMqttClientStatusCallback() {
@Override
public void onStatusChanged(final AWSIotMqttClientStatus status,
final Throwable throwable) {
Log.d(LOG_TAG, "Status = " + String.valueOf(status));
runOnUiThread(new Runnable() {
@Override
public void run() {
if (status == AWSIotMqttClientStatus.Connecting) {
tvStatus.setText("Connecting...");
} else if (status == AWSIotMqttClientStatus.Connected) {
tvStatus.setText("Connected");
} else if (status == AWSIotMqttClientStatus.Reconnecting) {
if (throwable != null) {
Log.e(LOG_TAG, "Connection error.", throwable);
}
tvStatus.setText("Reconnecting");
} else if (status == AWSIotMqttClientStatus.ConnectionLost) {
if (throwable != null) {
Log.e(LOG_TAG, "Connection error.", throwable);
}
tvStatus.setText("Disconnected");
} else {
tvStatus.setText("Disconnected");
}
}
});
}
});
} catch (final Exception e) {
Log.e(LOG_TAG, "Connection error.", e);
tvStatus.setText("Error! " + e.getMessage());
}
}
};
当我尝试使用Android手机与AWS Iot Mqtt Broker连接时,出现如下错误:
E / com.amazonaws.demo.androidpubsub.PubSubActivity:连接错误。 连接丢失(32109)-java.io.EOFException 在org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:146) 在java.lang.Thread.run(Thread.java:818) 引起原因:java.io.EOFException 在java.io.DataInputStream.readByte(DataInputStream.java:77) 在org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:65) 在org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:107) 在java.lang.Thread.run(Thread.java:818)
答案 0 :(得分:0)
上述异常可能是由于多种原因引起的,例如网络连接丢失,连接或订阅的策略限制等。不幸的是,Mqtt paho客户端并不总是完美地传播连接异常,因此可能很难找到根本原因只是这个例外的问题。您似乎正在关注this示例应用程序。我能够使该应用程序按照README说明进行操作。以下是我怀疑可能导致此问题的一些要点:
确保将以下IAM策略附加到身份池创建过程中创建的未经身份验证的角色
{ “ Version”:“ 2012-10-17”, “声明”:[ { “效果”:“允许”, “动作”:[ “ iot:AttachPrincipalPolicy”, “ iot:CreateKeysAndCertificate” ], “资源”:[ “ *” ] } ] }
确保将以下IoT策略附加到设备证书
{ “ Version”:“ 2012-10-17”, “声明”:[ { “效果”:“允许”, “ Action”:“ iot:Connect”, “资源”:“ ” }, { “效果”:“允许”, “动作”:[ “ iot:Publish”, “ iot:Subscribe”, “ iot:接收” ], “资源”:“ ” } ] }
希望有帮助!
答案 1 :(得分:0)
正如已经建议的那样,该问题几乎可以肯定是由于未附加适当的策略而引起的,但是由于AWS示例代码中错误的错误处理而使问题更加复杂。上面的代码首先在设备密钥库中查找保存的证书,如果找到,则尝试使用该证书进行连接。如果无法在预期的密钥库名称下找到证书,则它将创建一个新证书,将其保存在密钥库中,然后尝试将基本策略附加到该证书。如果从AWS上获取策略有任何问题,那么您会在密钥库中留有一个配置错误的条目,而AWS提供的代码将永远无法从中恢复。我花了很多时间尝试策略,但没有成功,直到我真正地跟踪代码并意识到对我指定的策略没有影响-代码忽略了它,并在密钥库中使用了配置错误的策略!
在上面的代码的catch块中,添加以下内容
AWSIotKeystoreHelper.deleteKeystoreAlias(certificateId,
keystorePath, keystoreName, keystorePassword);
这将确保不会挂有配置不正确的证书来绊倒您。
就最初的错误而言,问题可能出在您指定的策略的名称和上下文上。我在IAM中创建了策略,但这些策略未被识别-实际上,您需要按照Roshan所述在IoT Core Security上下文中创建IoT策略,并在PubSub示例代码中指定名称。