Java tutorial
/** * Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://aws.amazon.com/apache2.0 * * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and * limitations under the License. */ package com.zorba.bt.app; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import com.amazonaws.auth.CognitoCachingCredentialsProvider; import com.amazonaws.mobileconnectors.iot.AWSIotKeystoreHelper; import com.amazonaws.mobileconnectors.iot.AWSIotMqttClientStatusCallback; import com.amazonaws.mobileconnectors.iot.AWSIotMqttLastWillAndTestament; import com.amazonaws.mobileconnectors.iot.AWSIotMqttManager; import com.amazonaws.mobileconnectors.iot.AWSIotMqttNewMessageCallback; import com.amazonaws.mobileconnectors.iot.AWSIotMqttQos; import com.amazonaws.regions.Region; import com.amazonaws.services.iot.AWSIotClient; import com.amazonaws.services.iot.model.AttachPrincipalPolicyRequest; import com.amazonaws.services.iot.model.CreateKeysAndCertificateRequest; import com.amazonaws.services.iot.model.CreateKeysAndCertificateResult; import com.zorba.bt.app.bluetooth.AwsConnection; import com.zorba.bt.app.bluetooth.BtHwLayer; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.KeyStore; import java.util.UUID; public class AwsIotActivity extends ZorbaActivity { static final String LOG_TAG = AwsIotActivity.class.getCanonicalName(); EditText txtSubcribe; EditText txtMessage; TextView tvLastMessage; TextView tvClientId; TextView tvStatus; Button btnConnect; Button btnSubscribe; Button btnPublish; Button btnDisconnect; AWSIotClient mIotAndroidClient; AWSIotMqttManager mqttManager; String clientId; String keystorePath; String keystoreName; String keystorePassword; KeyStore clientKeyStore = null; String certificateId; CognitoCachingCredentialsProvider credentialsProvider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mtdebug); txtSubcribe = (EditText) findViewById(R.id.txtSubcribe); txtMessage = (EditText) findViewById(R.id.txtMessage); Bundle bundle = this.getIntent().getExtras(); String deviceName = bundle.getString("deviceName"); //deviceName = "88:4A:EA:2E:1D:7B"; txtSubcribe.setText(deviceName); tvLastMessage = (TextView) findViewById(R.id.tvLastMessage); tvClientId = (TextView) findViewById(R.id.tvClientId); tvStatus = (TextView) findViewById(R.id.tvStatus); btnConnect = (Button) findViewById(R.id.btnConnect); btnConnect.setOnClickListener(connectClick); btnConnect.setEnabled(false); btnPublish = (Button) findViewById(R.id.btnPublish); btnPublish.setOnClickListener(publishClick); btnDisconnect = (Button) findViewById(R.id.btnDisconnect); btnDisconnect.setOnClickListener(disconnectClick); // MQTT client IDs are required to be unique per AWS IoT account. // This UUID is "practically unique" but does not _guarantee_ // uniqueness. clientId = UUID.randomUUID().toString(); tvClientId.setText(clientId); // Initialize the AWS Cognito credentials provider credentialsProvider = new CognitoCachingCredentialsProvider(getApplicationContext(), // context AwsConnection.COGNITO_POOL_ID, // Identity Pool ID AwsConnection.MY_REGION // Region ); Region region = Region.getRegion(AwsConnection.MY_REGION); // MQTT Client mqttManager = new AWSIotMqttManager(clientId, AwsConnection.CUSTOMER_SPECIFIC_ENDPOINT); // Set keepalive to 10 seconds. Will recognize disconnects more quickly but will also send // MQTT pings every 10 seconds. mqttManager.setKeepAlive(10); // Set Last Will and Testament for MQTT. On an unclean disconnect (loss of connection) // AWS IoT will publish this message to alert other clients. AWSIotMqttLastWillAndTestament lwt = new AWSIotMqttLastWillAndTestament("my/lwt/topic", "Android client lost connection", AWSIotMqttQos.QOS0); mqttManager.setMqttLastWillAndTestament(lwt); // IoT Client (for creation of certificate if needed) mIotAndroidClient = new AWSIotClient(credentialsProvider); mIotAndroidClient.setRegion(region); keystorePath = getFilesDir().getPath(); keystoreName = AwsConnection.KEYSTORE_NAME; keystorePassword = AwsConnection.KEYSTORE_PASSWORD; certificateId = AwsConnection.CERTIFICATE_ID; // To load cert/key from keystore on filesystem 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); } 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(AwsConnection.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"); subscribe(); } 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"); } } }); } }); tvLastMessage.setText(""); } catch (final Exception e) { Log.e(LOG_TAG, "Connection error.", e); tvStatus.setText("Error! " + e.getMessage()); } } }; View.OnClickListener publishClick = new View.OnClickListener() { @Override public void onClick(View v) { String publishPrefix = ((EditText) findViewById(R.id.sender)).getText().toString().trim(); final String topic = txtSubcribe.getText().toString().trim() + publishPrefix; final String msg = txtMessage.getText().toString(); String str = txtMessage.getText().toString(); if (str.length() % 2 == 1) { CommonUtils.AlertBox(AwsIotActivity.this, "Write Error", "Write even digits"); return; } try { int numberBytes = str.length() / 2; byte wbytes[] = new BigInteger(str, 16).toByteArray(); System.out.println("num..." + numberBytes + " wbytes=" + wbytes.length); //BtHwLayer.getInstance(PubSubActivity.this).sendRawBytes(wbytes); mqttManager.publishData(wbytes, topic, AWSIotMqttQos.QOS0); } catch (Exception e) { CommonUtils.getInstance().writeLog(str + ":" + e.getMessage()); CommonUtils.AlertBox(AwsIotActivity.this, "Write Error", e.getMessage()); Log.e(LOG_TAG, "Publish error.", e); } try { } catch (Exception e) { } } }; View.OnClickListener disconnectClick = new View.OnClickListener() { @Override public void onClick(View v) { try { mqttManager.disconnect(); } catch (Exception e) { Log.e(LOG_TAG, "Disconnect error.", e); } } }; private void subscribe() { String subcribePrefix = ((EditText) findViewById(R.id.receiver)).getText().toString().trim(); final String topic = txtSubcribe.getText().toString().trim() + subcribePrefix; Log.d(LOG_TAG, "topic = " + topic); try { mqttManager.subscribeToTopic(topic, AWSIotMqttQos.QOS0, new AWSIotMqttNewMessageCallback() { @Override public void onMessageArrived(final String topic, final byte[] data) { runOnUiThread(new Runnable() { @Override public void run() { try { String message = new String(data, "UTF-8"); Log.d(LOG_TAG, "Message arrived:"); Log.d(LOG_TAG, " Topic: " + topic); Log.d(LOG_TAG, " Message: " + message); tvLastMessage.setText(tvLastMessage.getText().toString() + "," + message); tvLastMessage.setText(tvLastMessage.getText().toString() + "," + CommonUtils.getPrintBytes("Subcriber:", data)); } catch (UnsupportedEncodingException e) { Log.e(LOG_TAG, "Message encoding error.", e); } } }); } }); } catch (Exception e) { Log.e(LOG_TAG, "Subscription error.", e); } } }