AWS Android PubSub - android

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.

Related

runOnUiThread is not executing

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

Chat App for Android using a XMPP Server and Firebase Cloud Messaging for Push Notifications

I'm trying to send custom IQ from register device to ejabberd xmpp server for FCM configuration but still i can't received FCM notification and receiving Error like "user not registered at XMPP".
Step 1 : Created class for Custom IQ
public class IQGetSomething extends IQ {
public static final String ELEMENT = "push";
public static final String NAMESPACE = "p1:push";
String refreshedToken;
String userName;
public IQGetSomething(String refreshedToken,String userName) {
super(ELEMENT, NAMESPACE);
setType(Type.set);
this.refreshedToken = refreshedToken;
this.userName = userName;
}
#Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
xml.rightAngleBracket();
xml.append("<keepalive max=\"120\"/>" +
"<session duration=\"60\"/>" +
"<body send=\"all\" groupchat=\"true\" from=" + "\"" + userName + "\"/>" +
"<status type=\"xa\">Text Message when in push mode</status>" +
"<offline>true</offline>" +
"<notification>"+
"<type>fcm</type>"+
"<id>" + refreshedToken + "</id>"+
"</notification>"+
"<appid>" + "com.appname"+ "</appid>");
return xml;
}
}
Step 2 : Send stanza to XMPP
#Override
public void authenticated(XMPPConnection connection, boolean resumed) {
SmackService.sConnectionState = ConnectionState.CONNECTED;
logI("Before n mostly after login $^&$^$...authenticated ");
logI("authenticated");
if (!mConnection.isSmEnabled()) {
mConnection.setUseStreamManagement(true);
mConnection.setUseStreamManagementResumption(true);
}
if (mConnection.isSmEnabled()) {
logI("stream M is enabled");
} else {
logI("stream M is not enabled");
}
final String refreshedToken = FirebaseInstanceId.getInstance().getToken();
IQGetSomething iqCustomPush = new IQGetSomething(refreshedToken, mUsername);
iqCustomPush.setStanzaId(refreshedToken);
Log.d("xml", iqCustomPush.toXML().toString());
try {
mConnection.sendStanza(iqCustomPush);
} catch (Exception e) {
e.printStackTrace();
}
}
Step 3 : Set Offline
public void setOffline() {
Presence presence = new Presence(Presence.Type.unavailable);
try {
mConnection.sendStanza(presence);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
}
**LOGCAT
01-18 17:48:29.719 10219-10441/com.appname D/xml:
<iq id='refresh_token' type='set'><push xmlns='p1:push'><keepalive max="120"/><session duration="60"/><body send="all" groupchat="true" from="user_id"/><status type="xa">Text Message when in push mode</status><offline>true</offline><notification><type>fcm</type><id>refresh_token</id></notification><appid>com.appname</appid></push></iq>**
Note :- I changed here my refreshtoken with text "refresh_token" and package name with "com.appname". If anything i'm doing wrong than help me.

Sending Email in Android using JavaMail API without using mailing APP

Sending Email in Android using JavaMail API without using the default/built-in app
Using this tutorial, I've loaded up the code into a sample android project and imported the libraries. Changed the parameters in the lines:
send.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
try {
GMailSender sender = new GMailSender("sender#gmail.com", "sender_password");
sender.sendMail("This is Subject", "This is Body", "sender#gmail.com", "recipient#gmail.com");
} catch (Exception e) {
Log.e("SendMail", e.getMessage(), e);
}
}
});
Wanted to test it out and in this code, the try block of code gets executed successfully when I press the button, but I don't receive the mail, nor do I get any errors. Since there's no readme or any guidelines as to how to use this code, I have no choice but to ask what I'm doing wrong.
Just to clear the confusion, I've put the senders email instead of sender#gmail.com, same goes for password and recipient#gmail.com.
I've also added the INTERNET permission to the manifest.
If you want to use mailgun instead you can do it like this:
public void sendEmailInBackground(final String subject, final String body, final String... toAddress) {
AsyncTask task = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
String hostname = "smpt.mailgun.org";
int port = 25;
String login = "login";
String password = "password";
String from = "from#example.com";
AuthenticatingSMTPClient client = null;
try {
client = new AuthenticatingSMTPClient();
// optionally set a timeout to have a faster feedback on errors
client.setDefaultTimeout(10 * 1000);
// you connect to the SMTP server
client.connect(hostname, port);
// you say helo and you specify the host you are connecting from, could be anything
client.ehlo("localhost");
// if your host accepts STARTTLS, we're good everything will be encrypted, otherwise we're done here
if (client.execTLS()) {
client.auth(AuthenticatingSMTPClient.AUTH_METHOD.LOGIN, login, password);
checkReply(client);
client.setSender(from);
checkReply(client);
String address = "";
if (toAddress != null) {
for (String to : toAddress) {
if(to != null && to.length() > 0) {
client.addRecipient(to);
if (address.length() == 0) {
address += ",";
}
address += to;
}
}
}
if(address.length() == 0){
logger.warning("No address specified for mail message");
return null;
}
checkReply(client);
Writer writer = client.sendMessageData();
if (writer != null) {
SimpleSMTPHeader header = new SimpleSMTPHeader(from, address, subject);
writer.write(header.toString());
writer.write(body);
writer.close();
if (!client.completePendingCommand()) {// failure
throw new IOException("Failure to send the email " + client.getReply() + client.getReplyString());
}
} else {
throw new IOException("Failure to send the email " + client.getReply() + client.getReplyString());
}
} else {
throw new IOException("STARTTLS was not accepted " + client.getReply() + client.getReplyString());
}
} catch (IOException | NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException e) {
logger.severe("Error sending email",e);
} finally {
if (client != null) {
try {
client.logout();
client.disconnect();
} catch (Exception e) {
logger.warning("Error closing email client: " + e.getMessage());
}
}
}
return null;
}
};
task.execute();
}
private static void checkReply(SMTPClient sc) throws IOException {
if (SMTPReply.isNegativeTransient(sc.getReplyCode())) {
throw new IOException("Transient SMTP error " + sc.getReplyString());
} else if (SMTPReply.isNegativePermanent(sc.getReplyCode())) {
throw new IOException("Permanent SMTP error " + sc.getReplyString());
}
}

Paho Android client drops connection when a message is shown

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);
}
});
}

Image is not attached in quickblox for android

I have made a demo for sending image to private chat using QuickBlox, I am struggling to attach an image with the chat message, I have gone through its document and have used the below Links, with no luck
Attach an image
My code is as below:
chatMessage = new QBChatMessage();
sendButton = (Button) findViewById(R.id.chatSendButton);
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String messageText = messageEditText.getText().toString();
if (TextUtils.isEmpty(messageText)) {
return;
}
// Send chat message
//
// send a message
// ...
int fileId = R.raw.ic_launcher;
InputStream is = ChatActivity.this.getResources()
.openRawResource(fileId);
File file = FileHelper.getFileInputStream(is,
"sample_file.png", "myFile");
Boolean fileIsPublic = true;
QBContent.uploadFileTask(file, fileIsPublic, messageText,
new QBEntityCallbackImpl<QBFile>() {
#Override
public void onSuccess(QBFile qbFile, Bundle params) {
String publicUrl = qbFile.getPublicUrl();
System.out
.println("==========image uploaded success++++++++"
+ publicUrl);
id = qbFile.getId();
System.out
.println("===================image id+++++++++++"
+ id + "");
}
#Override
public void onError(List<String> errors) {
System.out
.println("==========image uploaded Errors++++++++"
+ errors.toString());
}
}, new QBProgressCallback() {
#Override
public void onProgressUpdate(int progress) {
}
});
QBAttachment atach = new QBAttachment("image");
atach.setId(id+"");
ArrayList<QBAttachment> aryatch = new ArrayList<QBAttachment>();
aryatch.add(atach);
chatMessage.setAttachments(aryatch);
chatMessage.setBody(messageText);
chatMessage.setProperty(PROPERTY_SAVE_TO_HISTORY, "1");
chatMessage.setDateSent(new Date().getTime() / 1000);
try {
chat.sendMessage(chatMessage);
} catch (XMPPException e) {
Log.e(TAG, "failed to send a message", e);
} catch (SmackException sme) {
Log.e(TAG, "failed to send a message", sme);
}
messageEditText.setText("");
if (dialog.getType() == QBDialogType.PRIVATE) {
showMessage(chatMessage);
}
}
});
Well it clear where the mistake is
your id is null here
atach.setId(id+"");
because it will != nil only in onSuccess block of uploadFileTask
So the right way is to forward all attachments logic inside onSuccess block of uploadFileTask
Because these QuickBlox request are asynchronous

Categories

Resources