I am trying to run this code but code inside my runOnUi thread is not executing. I am using evernote-android-job.
He is the code which runs periodically:
public class TempJob extends Job {
public static final String TAG = "job_temp_mqtt";
#Override
#NonNull
protected Result onRunJob(#NonNull Params params) {
Log.d("I'm here", "Position 0");
Looper.prepare();
PubSubActivityTemp worker = new PubSubActivityTemp();
Log.d("I'm here", "Position 1");
worker.exe();
return Result.SUCCESS;
}
public static void scheduleJob() {
Set<JobRequest> jobRequests =
JobManager.instance().getAllJobRequestsForTag(TempJob.TAG);
if (!jobRequests.isEmpty()) {
Log.d("Check: ", "Job is not Empty");
// return;
}
new JobRequest.Builder(TempJob.TAG)
.setPeriodic(TimeUnit.MINUTES.toMillis(15),
TimeUnit.MINUTES.toMillis(7))
.setUpdateCurrent(true) // calls
cancelAllForTag(NoteSyncJob.TAG) for you
.setRequiredNetworkType(JobRequest.NetworkType.ANY)
.setRequirementsEnforced(true)
.build()
.schedule();
}
}
Here is the code from the activity:
public class PubSubActivityTemp extends Activity {
static final String LOG_TAG = GraphSelectType.class.getCanonicalName();
// --- Constants to modify per your configuration ---
// IoT endpoint
// AWS Iot CLI describe-endpoint call returns: XXXXXXXXXX.iot.
<region>.amazonaws.com
private static final String CUSTOMER_SPECIFIC_ENDPOINT = "*************-
ats.iot.us-east-1.amazonaws.com";
// Cognito pool ID. For this app, pool needs to be unauthenticated pool
with
// AWS IoT permissions.
private static final String COGNITO_POOL_ID = "us-east-
1:*************-75c2-4258-b663-21*********83e";
// Name of the AWS IoT policy to attach to a newly created certificate
private static final String AWS_IOT_POLICY_NAME = "PubSub******Cert";
// Region of AWS IoT
private static final Regions MY_REGION = Regions.US_EAST_1;
// Filename of KeyStore file on the filesystem
private static final String KEYSTORE_NAME = "iot_keystore";
// Password for the private key in the KeyStore
private static final String KEYSTORE_PASSWORD = "password";
// Certificate and key aliases in the KeyStore
private static final String CERTIFICATE_ID = "default";
TextView tvStatus;
// TextView tvLastMessage;
Handler mHandler;
AWSIotClient mIotAndroidClient;
AWSIotMqttManager mqttManager;
String clientId;
String keystorePath;
String keystoreName;
String keystorePassword;
KeyStore clientKeyStore = null;
String certificateId;
CognitoCachingCredentialsProvider credentialsProvider;
int tracker = 0; //0 is on, 1 is off
private String topic = "Simran*****";
private String msg0 = "on";
private String msg1 = "off";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void exe() {
Log.d("I'm here", "Position 2");
new Thread() {
public void run() {
Log.d("I'm here", "Position 3");
runOnUiThread(() -> {
Log.d("I'm here", "Position 4");
Toast.makeText(PubSubActivityTemp.this, "Storage not
available", Toast.LENGTH_SHORT).show();
});
Log.d("I'm here", "Position 5");
}
}.start();
}
public void mqtt() {
// tvStatus = (TextView) findViewById(R.id.tvStatus);
// tvLastMessage = (TextView) findViewById(R.id.tvLastMessage);
// 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();
// Initialize the AWS Cognito credentials provider
credentialsProvider = new CognitoCachingCredentialsProvider(
// getApplicationContext(), // context
TempApplication.getAppContext(),
COGNITO_POOL_ID, // Identity Pool ID
MY_REGION // Region
);
Region region = Region.getRegion(MY_REGION);
// MQTT Client
mqttManager = new AWSIotMqttManager(clientId,
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 = KEYSTORE_NAME;
keystorePassword = KEYSTORE_PASSWORD;
certificateId = 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(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();
}
connect();
subscribe();
}
public void connect() {
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());
}
}
public void subscribe() {
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(message);
} catch (UnsupportedEncodingException e) {
Log.e(LOG_TAG, "Message encoding
error.", e);
}
}
});
}
});
} catch (Exception e) {
Log.e(LOG_TAG, "Subscription error.", e);
}
}
}
Here is the output from logcat. I ahve filtered out only necessary output. I am not getting any warning or errors:
09-30 11:55:23.662 5705-6268/com.simran.powermanagement D/I'm here:
Position 0
09-30 11:55:23.663 5705-6268/com.simran.powermanagement D/I'm here:
Position 1
Position 2
09-30 11:55:23.665 5705-6269/com.simran.powermanagement D/I'm here:
Position 3
09-30 11:55:23.665 5705-6269/com.simran.powermanagement D/I'm here:
Position 5
Toast needs context and when you instantiate an Activity class using new you just create a java class that it has no context.if you need some method of your activity you must send your activity or its context object to your Job class and use it for create your activity. like this :
public class PubSubActivityTemp extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
yourJob job=new yourJob (this);
}
}
in your job class :
public class TempJob extends Job {
Activity activity;
public TempJob (Activity activity){
this.activity=activity;
PubSubActivityTemp worker=(PubSubActivityTemp)activity;
}
}
if you you don't want to create your job in PubSubActivityTemp i suggest you use this way to instantiate PubSubActivityTemp :
first create a class that extends Application class :
public class Myapp extends Application{
public PubSubActivityTemp pubSubActivityTemp;
}
in AndroidManifast.xml file in <application> tag use this class for name attribute :
<application name=".Myapp ">
in your PubSubActivityTemp onCreate() methode :
public class PubSubActivityTemp extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApp myApp=(MyApp) getApplicationContext();// or getApplication();
myApp.pubSubActivityTemp=this;
}
}
in every class you need PubSubActivityTemp activity just send to it getApplicationContext as Context an in it :
public class TempJob extends Job {
Activity activity;// or use Context context;
public TempJob (Activity activity){
this.activity=activity;
MyApp myApp=(MyApp)activity.getApplicationContext();
PubSubActivityTemp worker=myApp.pubSubActivityTemp;
}
}
in another class that you need job :
public class AnotherActivity extends Activity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TempJob job=new TempJob(this);
}
}
and if you just want to find out some code working you can log it with Log.v()instead Toast
Related
I cannot get the official aws-pubsub sdk to run. I have replaced all the necessary credentials. How can I set publishing and subscribing using my Android device on Amazon IoT? I have seen every link available on the web but still cannot get it to work. Here is an idea of my project:
The company is creating air filters that transmit data on regular basis through BLE module to the android app. Now I have to use this app to publish data to Amazon IoT as soon as it gets data from the BLE.
package com.example.parasrawat2124.amazonmqtt;
import android.support.v7.app.AppCompatActivity;
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.regions.Regions;
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 java.io.UnsupportedEncodingException;
import java.security.KeyStore;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
static final String LOG_TAG = MainActivity.class.getCanonicalName();
// --- Constants to modify per your configuration ---
// IoT endpoint
// AWS Iot CLI describe-endpoint call returns: XXXXXXXXXX.iot.<region>.amazonaws.com
private static final String CUSTOMER_SPECIFIC_ENDPOINT = "a1j3ds5m9dpp07.iot.us-west-2.amazonaws.com";
// Cognito pool ID. For this app, pool needs to be unauthenticated pool with
// AWS IoT permissions.
private static final String COGNITO_POOL_ID = "us-west-2_iQ1FI8tfj";
// Name of the AWS IoT policy to attach to a newly created certificate
private static final String AWS_IOT_POLICY_NAME = "PMQTT";
// Region of AWS IoT
private static final Regions MY_REGION = Regions.US_EAST_1;
// Filename of KeyStore file on the filesystem
private static final String KEYSTORE_NAME = "iot_keystore";
// Password for the private key in the KeyStore
private static final String KEYSTORE_PASSWORD = "password";
// Certificate and key aliases in the KeyStore
private static final String CERTIFICATE_ID = "default";
EditText txtSubcribe;
EditText txtTopic;
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.activity_main);
txtSubcribe = (EditText) findViewById(R.id.txtSubsribe);
txtTopic = (EditText) findViewById(R.id.txtTopic);
txtMessage = (EditText) findViewById(R.id.txtMessage);
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);
btnSubscribe = (Button) findViewById(R.id.btnSubscribe);
btnSubscribe.setOnClickListener(subscribeClick);
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
COGNITO_POOL_ID, // Identity Pool ID
MY_REGION // Region
);
Region region = Region.getRegion(MY_REGION);
// MQTT Client
mqttManager = new AWSIotMqttManager(clientId, 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 = KEYSTORE_NAME;
keystorePassword = KEYSTORE_PASSWORD;
certificateId = 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(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());
}
}
};
View.OnClickListener subscribeClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
final String topic = txtSubcribe.getText().toString();
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(message);
} catch (UnsupportedEncodingException e) {
Log.e(LOG_TAG, "Message encoding error.", e);
}
}
});
}
});
} catch (Exception e) {
Log.e(LOG_TAG, "Subscription error.", e);
}
}
};
View.OnClickListener publishClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
final String topic = txtTopic.getText().toString();
final String msg = txtMessage.getText().toString();
try {
mqttManager.publishString(msg, topic, AWSIotMqttQos.QOS0);
} catch (Exception e) {
Log.e(LOG_TAG, "Publish error.", 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);
}
}
};
}
And my console message:
07-23 12:06:20.595 18136-18168/com.example.parasrawat2124.amazonmqtt D/CognitoCachingCredentialsProvider: Clearing credentials from SharedPreferences
07-23 12:06:20.898 18136-18168/com.example.parasrawat2124.amazonmqtt E/com.example.parasrawat2124.amazonmqtt.MainActivity: Exception occurred when generating new private key and certificate.
com.amazonaws.AmazonServiceException: 1 validation error detected: Value 'us-west-2_iQ1FI8tfj' at 'identityPoolId' failed to satisfy constraint: Member must satisfy regular expression pattern: [\w-]+:[0-9a-f-]+ (Service: AmazonCognitoIdentity; Status Code: 400; Error Code: ValidationException; Request ID: b696c58e-8e42-11e8-b181-f1f1e5db8378)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:730)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:405)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:212)
at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.invoke(AmazonCognitoIdentityClient.java:566)
at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.getId(AmazonCognitoIdentityClient.java:448)
at com.amazonaws.auth.AWSAbstractCognitoIdentityProvider.getIdentityId(AWSAbstractCognitoIdentityProvider.java:172)
at com.amazonaws.auth.AWSEnhancedCognitoIdentityProvider.refresh(AWSEnhancedCognitoIdentityProvider.java:76)
at com.amazonaws.auth.CognitoCredentialsProvider.retryRefresh(CognitoCredentialsProvider.java:693)
at com.amazonaws.auth.CognitoCredentialsProvider.startSession(CognitoCredentialsProvider.java:665)
at com.amazonaws.auth.CognitoCredentialsProvider.getCredentials(CognitoCredentialsProvider.java:444)
at com.amazonaws.auth.CognitoCachingCredentialsProvider.getCredentials(CognitoCachingCredentialsProvider.java:485)
at com.amazonaws.auth.CognitoCachingCredentialsProvider.getCredentials(CognitoCachingCredentialsProvider.java:77)
at com.amazonaws.services.iot.AWSIotClient.invoke(AWSIotClient.java:7048)
at com.amazonaws.services.iot.AWSIotClient.createKeysAndCertificate(AWSIotClient.java:1119)
at com.example.parasrawat2124.amazonmqtt.MainActivity$1.run(MainActivity.java:177)
at java.lang.Thread.run(Thread.java:764)
I am sorry for asking a question based on such few credentials. I figured out the actual problem. The steps given in the official Github Readme file are correct but you need to consider some options below in case you encounter errors:
Don't use the default value of keystore credentials as written in the readme file. Create your own Keystore and then put those new credentials and alias in the app.
After the last step which is creating a policy in IoT , I would recommend creating a thing and a certificate and attach this policy to that certificate. This was the problem that occurred in my case.
I am trying to use the basic Eclipse Paho MQTT client version 1.1.0 to connect to a CloudAMQP RabbitMQ instance, subscribe to a topic, and receive messages (which I send from the web admin console).
It works well if the application sends all message payloads to the Log output.
If the application adds the message to a TextView, the message appears, but the connection is dropped immediately and no more message are received.
The full project is available at GitHub. A simple example is below.
There is a service-based MQTT Paho client, but I thought that for very simple applications the basic client should be able to receive and show messages in the Android app UI.
...
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttClientPersistence;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
public class MainActivity extends AppCompatActivity implements MqttCallback {
private static final String TAG = "main";
private Connection connection;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
configureUI();
}
private Button buttonConnect;
private TextView messageWindow;
private void configureUI() {
buttonConnect = (Button) findViewById(R.id.buttonConnect);
messageWindow = (TextView) findViewById(R.id.messageWindow);
buttonConnect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String s = "***";
String d = "test";
String u = "***";
String p = "***";
if (connection != null && connection.isConnected()) {
connection.disconnect();
connection = null;
messageWindow.setText(String.format("Disconnected from server %s",
new Object[]{s}));
return;
}
messageWindow.setText(String.format("Connecting to server %s as user %s",
new Object[]{s, u}));
connection = new Connection(MainActivity.this, MainActivity.this, s, u, p);
connection.connect();
if (connection.isConnected()) {
messageWindow.append("\n\n");
messageWindow.append(String.format("Connected, listening for messages from topic %s",
new Object[]{d}));
connection.subscribe(d);
}
}
});
}
#Override
public void connectionLost(Throwable cause) {
Log.e(TAG, "connectionLost" + cause.getMessage());
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
String msg = new String(message.getPayload());
Log.i(TAG, "Message Arrived: " + msg);
// messageWindow.append(msg);
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.i(TAG, "Delivery Complete!");
}
class Connection {
private static final String TAG = "conn";
private static final String protocol = "tcp://";
private static final int port = 1883;
private static final int version = MqttConnectOptions.MQTT_VERSION_3_1_1;
private static final int keepAliveSeconds = 20 * 60;
private final Context context;
private MqttClient client;
private final String server;
private final String user;
private final String pass;
private final MqttConnectOptions options = new MqttConnectOptions();
public Connection(Context ctx, MqttCallback mqttCallback, String server, String user, String pass) {
this.context = ctx;
this.server = server;
this.user = user;
this.pass = pass;
MqttClientPersistence memPer = new MemoryPersistence();
try {
String url = protocol + server + ":" + port;
client = new MqttClient(url, MqttClient.generateClientId(), memPer);
client.setCallback(mqttCallback);
} catch (MqttException e) {
e.printStackTrace();
}
options.setUserName(user + ":" + user);
options.setPassword(pass.toCharArray());
options.setMqttVersion(version);
options.setKeepAliveInterval(keepAliveSeconds);
}
void connect() {
Log.i(TAG, "buttonConnect");
try {
client.connect(options);
} catch (MqttException ex) {
Log.e(TAG, "Connection attempt failed with reason code = " + ex.getReasonCode() + ":" + ex.getCause());
}
}
public boolean isConnected() {
return client.isConnected();
}
public void disconnect() {
try {
client.disconnect();
} catch (MqttException e) {
Log.e(TAG, "Disconnect failed with reason code = " + e.getReasonCode());
}
}
void subscribe(String dest) {
try {
client.subscribe(dest);
} catch (MqttException e) {
Log.e(TAG, "Subscribe failed with reason code = " + e.getReasonCode());
}
}
}
}
I would guess this is because you are trying to update the TextView from a none UI thread.
Try wrapping the messageWindow.append(msg); in a runOnUiThread call.
public void messageArrived(String topic, MqttMessage message) throws Exception {
String msg = new String(message.getPayload());
Log.i(TAG, "Message Arrived: " + msg);
runOnUiThread(new Runnable(){
public void run() {
messageWindow.append(msg);
}
});
}
I know this kind of questions are maybe too old, but I got stock with this silly thing.
I have an AsyncTask class which is a subclass of an activity class, and right now I want to call it from another class: following codes shows what I mean:
public class STA extends Activity {
public class ListSpdFiles extends AsyncTask<Void, Void, String[]> {
private static final String TAG = "ListSpdFiles: ";
/**
* Status code returned by the SPD on operation success.
*/
private static final int SUCCESS = 4;
private String initiator;
private String path;
private SecureApp pcas;
private boolean isConnected = false; // connected to PCAS service?
private PcasConnection pcasConnection = new PcasConnection() {
#Override
public void onPcasServiceConnected() {
Log.d(TAG, "pcasServiceConnected");
latch.countDown();
}
#Override
public void onPcasServiceDisconnected() {
Log.d(TAG, "pcasServiceDisconnected");
}
};
private CountDownLatch latch = new CountDownLatch(1);
public ListSpdFiles(String initiator, String path) {
this.initiator = initiator;
this.path = path;
}
private void init() {
Log.d(TAG, "starting task");
pcas = new AndroidNode(getApplicationContext(), pcasConnection);
isConnected = pcas.connect();
}
private void term() {
Log.d(TAG, "terminating task");
if (pcas != null) {
pcas.disconnect();
pcas = null;
isConnected = false;
}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
init();
}
#Override
protected String[] doInBackground(Void... params) {
// check if connected to PCAS Service
if (!isConnected) {
Log.v(TAG, "not connected, terminating task");
return null;
}
// wait until connection with SPD is up
try {
if (!latch.await(20, TimeUnit.SECONDS)) {
Log.v(TAG, "unable to connected within allotted time, terminating task");
return null;
}
} catch (InterruptedException e) {
Log.v(TAG, "interrupted while waiting for connection in lsdir task");
return null;
}
// perform operation (this is where the actual operation is called)
try {
return lsdir();
} catch (DeadServiceException e) {
Log.i(TAG, "service boom", e);
return null;
} catch (DeadDeviceException e) {
Log.i(TAG, "device boom", e);
return null;
}
}
#Override
protected void onPostExecute(String[] listOfFiles) {
super.onPostExecute(listOfFiles);
if (listOfFiles == null) {
Log.i(TAG, "task concluded with null list of files");
// tv.setText("task concluded with a null list of files");
} else {
Log.i(TAG, "task concluded with the following list of files: "
+ Arrays.toString(listOfFiles));
//tv.setText("List of files received is:\n" + Arrays.toString(listOfFiles));
}
term();
}
#Override
protected void onCancelled(String[] listOfFiles) {
super.onCancelled(listOfFiles);
Log.i(TAG, "lsdir was canceled");
term();
}
/**
* Returns an array of strings containing the files available at the given path, or
* {#code null} on failure.
*/
private String[] lsdir() throws DeadDeviceException, DeadServiceException {
Result<List<String>> result = pcas.lsdir(initiator, path); // the lsdir call to the
final Global globalVariable = (Global) getApplicationContext();
if (globalVariable.getPasswordButt() == false) {
// Calling Application class (see application tag in AndroidManifest.xml)
// Get name and email from global/application context
final boolean isusername = globalVariable.getIsUsername();
if (isusername == true) {
String username = "/" + getLastAccessedBrowserPage() + ".username" + ".txt";
//String password = "/" + CurrentURL + "password" + ".txt";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
pcas.readFile(initiator, username, baos);
Log.i(TAG, "OutputStreampassword: "
+ new String(baos.toByteArray()));
String name = new String(baos.toByteArray());
if (!name.equalsIgnoreCase("")) {
globalVariable.setUsername(name);
// getCurrentInputConnection().setComposingText(name, 1);
// updateCandidates();
}
globalVariable.setIsUsername(false);
} else if (isusername == false)
Log.i(TAG, "Wrong Input Type For Username.");
// globalVariable.setUsernameButt(false);
} else if (globalVariable.getPasswordButt() == true) {
// Calling Application class (see application tag in AndroidManifest.xml)
// final Global globalVariable = (Global) getApplicationContext();
// Get name and email from global/application context
final boolean ispassword = globalVariable.getIsPassword();
if (ispassword == true) {
// String username = "/" + CurrentURL + "username" + ".txt";
String password = "/" + getLastAccessedBrowserPage() + ".password" + ".txt";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
pcas.readFile(initiator, password, baos);
Log.i(TAG, "OutputStreampassword: "
+ new String(baos.toByteArray()));
String name = new String(baos.toByteArray());
if (!name.equalsIgnoreCase("")) {
globalVariable.setPassword(name);
//getCurrentInputConnection().setComposingText(name, 1);
// updateCandidates();
}
globalVariable.setIsPassword(false);
} else if (ispassword == false)
Log.i(TAG, "Wrong Input Type For Password.");
globalVariable.setPasswordButt(false);
// boolpassword=false;
}
//}
if (result.getState() != SUCCESS) {
Log.v(TAG, "operation failed");
return null;
}
if (result.getValue() == null) {
Log.v(TAG, "operation succeeded but operation returned null list");
return null;
}
return result.getValue().toArray(new String[0]);
}
}
public String getLastAccessedBrowserPage() {
String Domain = null;
Cursor webLinksCursor = getContentResolver().query(Browser.BOOKMARKS_URI, Browser.HISTORY_PROJECTION, null, null, Browser.BookmarkColumns.DATE + " DESC");
int row_count = webLinksCursor.getCount();
int title_column_index = webLinksCursor.getColumnIndexOrThrow(Browser.BookmarkColumns.TITLE);
int url_column_index = webLinksCursor.getColumnIndexOrThrow(Browser.BookmarkColumns.URL);
if ((title_column_index > -1) && (url_column_index > -1) && (row_count > 0)) {
webLinksCursor.moveToFirst();
while (webLinksCursor.isAfterLast() == false) {
if (webLinksCursor.getInt(Browser.HISTORY_PROJECTION_BOOKMARK_INDEX) != 1) {
if (!webLinksCursor.isNull(url_column_index)) {
Log.i("History", "Last page browsed " + webLinksCursor.getString(url_column_index));
try {
Domain = getDomainName(webLinksCursor.getString(url_column_index));
Log.i("Domain", "Last page browsed " + Domain);
return Domain;
} catch (URISyntaxException e) {
e.printStackTrace();
}
break;
}
}
webLinksCursor.moveToNext();
}
}
webLinksCursor.close();
return null;
}
public String getDomainName(String url) throws URISyntaxException {
URI uri = new URI(url);
String domain = uri.getHost();
return domain.startsWith("www.") ? domain.substring(4) : domain;
}}
Would you please tell me what should I do to fix this code?
Looking over the code I did not see anywhere you referenced anything from the Activity itself besides the application context so you can move the ListSpdFiles class to its own java file and pass it a context into the constructor when you make a new instance of it.
Put this class in a ListSpdFiles.java file so it is no longer an inner class.
public class ListSpdFiles extends AsyncTask<Void, Void, String[]> {
Context applicationContext;
public ListSpdFiles(Context context, String initiator, String path) {
this.initiator = initiator;
this.path = path;
applicationContext = context.getApplicationContext();
}
// The rest of your code still goes here. Replace other calls to
// getApplicationContext() with the new applicationContext field
}
You can now use this class anywhere a Context is available. You create a new instance by doing:
ListSpdFiles listSpdFilesTask = new ListSpdFiles(context, "someInitiator", "somePath");
listSpdFilesTask.execute();
I'm using the socialAuth plugin to connect a user to linkdin within my app. I have the connection set up correctly and retrieves data. However, I'm unsure how I can get my main activity to wait until the socialAuthListeners have fired and finished. I know a little about threading but I haven't used it with listeners before. Here's my code:
public class LinkdinAuth {
private static final String TAG = "TEST";
// SocialAuth Components
SocialAuthAdapter adapter;
ProgressDialog mDialog;
private Context context;
private boolean loggedIn = false;
private Bundle LinkdinData;
public LinkdinAuth(Context C){
this.context = C;
LinkdinData = new Bundle();
adapter = new SocialAuthAdapter(new ResponseListener());
}
public void adapterAuthorize(View v){
adapter.authorize(v.getContext(), Provider.LINKEDIN);
}
private final class ResponseListener implements DialogListener
{
public void onComplete(Bundle values) {
String providerName = values.getString(SocialAuthAdapter.PROVIDER);
Log.d("Main", "providername = " + providerName);
mDialog = new ProgressDialog(context);
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.setMessage("Loading...");
//Get profile information
adapter.getUserProfileAsync(new ProfileDataListener());
// get Job and Education information
mDialog.show();
adapter.getCareerAsync(new CareerListener());
loggedIn = true;
Log.d("Main", "LOGGED IN = " + loggedIn );
Toast.makeText(context, providerName + " connected", Toast.LENGTH_SHORT).show();
}
#Override
public void onBack() {
Log.d("Main", "Dialog Closed by pressing Back Key");
}
#Override
public void onCancel() {
Log.d("Main", "Cancelled");
}
#Override
public void onError(SocialAuthError e) {
Log.d("Main", "Error");
e.printStackTrace();
}
}
// To receive the profile response after authentication
private final class ProfileDataListener implements SocialAuthListener<Profile> {
#Override
public void onExecute(String provider, Profile t) {
Log.d("Sign Up", "Receiving Data");
mDialog.dismiss();
Profile profileMap = t;
LinkdinData.putString("Validated ID", profileMap.getValidatedId() );
LinkdinData.putString("First Name", profileMap.getFirstName());
LinkdinData.putString("Last Name", profileMap.getLastName());
LinkdinData.putString("Email", profileMap.getEmail());
LinkdinData.putString("Country", profileMap.getCountry());
LinkdinData.putString("Language", profileMap.getLanguage());
LinkdinData.putString("Location", profileMap.getLocation());
LinkdinData.putString("Profile Image URL", profileMap.getProfileImageURL());
}
#Override
public void onError(SocialAuthError arg0) {
// TODO Auto-generated method stub
}
}
private final class CareerListener implements SocialAuthListener<Career> {
#Override
public void onExecute(String provider, Career t) {
Log.d("Custom-UI", "Receiving Data");
mDialog.dismiss();
Career careerMap = t;
//get education
Log.d("Main", "Education:");
if(careerMap.getEducations() != null){
for(Education E: careerMap.getEducations()){
Log.d("Main", "School = " +E.getSchoolName() );
Log.d("Main", "Major = " + E.getFieldOfStudy() );
Log.d("Main", "Degree = " + E.getDegree() );
Log.d("Main", "Start Date = " + E.getStartDate() );
Log.d("Main", "End Date = " + E.getEndDate() );
}
}
Log.d("SignUp", "Career");
if(careerMap.getPositions() != null){
for(Position P: careerMap.getPositions()){
LinkdinData.putString("Company Name", P.getCompanyName() );
LinkdinData.putString("Job Title", P.getTitle() );
Log.d("Main", "Industry = " + P.getIndustry() );
Log.d("Main", "Start Date = " + P.getStartDate() );
Log.d("Main", "End Date = " + P.getEndDate() );
}
}
}
#Override
public void onError(SocialAuthError e) {
}
}
public boolean isLoggedIn(){
return loggedIn;
}
public Bundle getLinkdinData(){
return LinkdinData;
}
So, as you can see. I have 2 listeners that get data after authorization goes through. And my main activity makes creates an instance, calls the adapterAuthroizeMethod and then if the user logs in a flag is set. Then getLinkedData is called. However I would like it to wait until I know the listeners have fired before calling getlinkdinData. Here's what my Main Activity does after a button press:
L.adapterAuthorize(v);
loggedInWithLinkdin = L.isLoggedIn();
Bundle B = L.getLinkdinData();
Intent i = new Intent(getBaseContext(), UserRegistration.class);
i.putExtra("linkdin bundle", B);
//startActivity(i);
Any ideas?
thanks
Well, not a recommend solution but more of a hack.
Here is what you can do.
Wrap the aync call around this construct :
AtomicBoolean done = new AtomicBoolean(false);
Global ans; // the return value holder
try{
result = someAsyncCall(query, new Thread()); // this new thread is for listener callback
result.setResultListener(result -> {
// do something with result.
ans = result.getAns() ; // set global ans
done.set(true);
synchronized (done) {
done.notifyAll(); // notify the main thread which is waiting
}
});
}
catch (Exception e ) {
Log(e);
}
synchronized (done) {
while (done.get() == false) {
done.wait(); // wait here until the listener fires
}
}
return ans; // return global ans
I am working on Autobahn Web socket communication. There is a carousel view in my application, and there are four images. When users click on of the images, then connects to server with websocket and send message. But the problem is that when I select the images, it connects to server correctly, but client(android device) connects to the websocket every single time when the message is sent.
Here is my code..
if (pos == 0) {
product_photo.setImageResource(R.drawable.myoffers_0);
product_photo.setOnClickListener(new ImageButton.OnClickListener(){
public void onClick(View v){
String id = "Product0";
Log.d(TAG, "Current product is : " + id);
A.sendMessage(id);
}
});
}
Websocket.class
public class WebSocket_Connector extends Activity{
private static final String TAG = "ECHOCLIENT";
private static final String TAG1 = "My app";
public final WebSocketConnection mConnection = new WebSocketConnection();
private String tmpString = "";
public void connect(final String wsuri) {
Log.d(TAG, "Connecting to: " + wsuri);
try {
mConnection.connect(wsuri, new WebSocketHandler() {
#Override
public void onOpen() {
Log.d(TAG, "Status: Connected to " + wsuri );
Log.d(TAG, "Connection successful!\n");
mConnection.sendTextMessage(tmpString);
tmpString = "";
}
#Override
public void onTextMessage(String payload) {
Log.d(TAG, "Got echo: " + payload);
}
#Override
public void onClose(int code, String reason) {
Log.d(TAG, "Connection closed.");
}
});
} catch (WebSocketException e) {
Log.d(TAG, e.toString());
}
}
public void sendMessage(String message) {
if (mConnection.isConnected()) {
Log.d(TAG1, "Messeage is sent : " + message);
mConnection.sendTextMessage(message);
}
else {
tmpString = message;
connect("ws://xxx.xxx.x.xxx:xxxx");
}
}
}
It doens't go to 'if (mConnection.isConnected())' here..always goes to else.