I'm learning MQTT and Android Studio.
I want to make a simple application in Android Studio but I'm fighting from 4 days and I can`t cope with it.
Application Description:
1 Button ---> Push ---> Send to mqtt topic / message ( "mqtt" / "test" )
That`s all.
Mqtt Broker = rpi (IP: namerpibrok.ddns.net )
Broker works fine and it does not need a password or username
Problem is with Aplication - that is my first work with Android Studio.
I did everything as described on the page: https://www.hivemq.com/blog/mqtt-client-library-enyclopedia-paho-android-service
Now, when I push the button .... nothing happens.
MqttAndroidClient client;
private static final String TAG = "LOG";
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
private Object bytes;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String clientId = MqttClient.generateClientId();
client = new MqttAndroidClient(this.getApplicationContext(), "rpidomwroled.ddns.net:1883", clientId);
MqttConnectOptions options = new MqttConnectOptions();
try {
IMqttToken token = client.connect(options);
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Toast.makeText(MainActivity.this,"Połączono", Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Toast.makeText(MainActivity.this,"Połączono", Toast.LENGTH_LONG).show();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
MqttAndroidClient client;
private static final String TAG = "LOG";
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
private Object bytes;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String clientId = MqttClient.generateClientId();
client = new MqttAndroidClient(this.getApplicationContext(), "rpidomwroled.ddns.net:1883", clientId);
MqttConnectOptions options = new MqttConnectOptions();
try {
IMqttToken token = client.connect(options);
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Toast.makeText(MainActivity.this,"Połączono", Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Toast.makeText(MainActivity.this,"Połączono", Toast.LENGTH_LONG).show();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
public void pub(View v)
{
String topic = "mqtt";
String payload = "mqtt";
byte[] encodedPayload = new byte[0];
try {
encodedPayload = payload.getBytes("UTF-8");
MqttMessage message = new MqttMessage(encodedPayload);
client.publish(topic, message);
} catch (UnsupportedEncodingException | MqttException e) {
e.printStackTrace();
}
}
}
Can anybody tell me what I'm doing wrong?
This code is worked for me
String topic = "mqtt";
MqttMessage message = new MqttMessage();
message.setPayload("Message from IoT dev".getBytes());
client.publish(topic, message);
you can get call backs in
client.setCallback(new IoTCallbacks() {
#Override
public void connectionLost(Throwable cause) {
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
Related
i am really new to Android and i was trying to use the Thread class with a message handler, in there i need to use the ApplicationContext but when i try to run it it crashes, here is the code that makes the application crash
if (!connected.isState()) {
client = new MqttAndroidClient(myContext.context, SERVERURI, CLIENTID);
try {
IMqttToken token = client.connect();
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
//we are connected
connected.setState(true);
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
//we are not connected
}
});
} catch (Exception e) {
e.printStackTrace();
}
return;
}
here is the myContext class
class myContext extends Application {
public static Context context;
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
}
what can i do to fix the problem?
You probably haven't told Android to use your custom Application class, so myContext.onCreate() isn't being called. To do this you need to add this to your <application> declaration in your manifest:
android:name=".myContext"
OP here.
in the end i solved it by sending a message containing the applicationContext in message.obj, here is the code now
if (!connected.isState()) {
client = new MqttAndroidClient((Context) msg.obj, SERVERURI, CLIENTID);
try {
IMqttToken token = client.connect();
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
//we are connected
connected.setState(true);
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
//we are not connected
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
return;
}
thanks to everybody for the suggestions and for keeping up with my inexperience
:-)
I own raspberry pi and android smartphone. I am trying to control raspburry pi GPIO with self-made application by android studio. The devices are able connect to each other via MQTT, but when I was trying to publish a message (on/off), it doesn't showed up in the raspberry pi terminal. There is no error detected. I have no clue, what I'm missing here. Thank you in advance for any suggestion.
public class MainActivity extends AppCompatActivity {
Switch aswitch;
MqttAndroidClient client;
TextView subText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String clientId = MqttClient.generateClientId();
client = new MqttAndroidClient(this.getApplicationContext(), "tcp://192.168.2.193:1883",clientId);
//client = new MqttAndroidClient(this.getApplicationContext(), "tcp://192.168.43.41:1883",clientId);
}
public void Switch(View v){
aswitch = (Switch) findViewById(R.id.simpleSwitch1);
aswitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked == true){
String topic = "rpi/gpio";
String payload = "On";
byte[] encodedPayload = new byte[0];
try {
encodedPayload = payload.getBytes(StandardCharsets.UTF_8);
MqttMessage message = new MqttMessage(encodedPayload);
message.setRetained(true);
client.publish(topic, message);
} catch (MqttException e) {
e.printStackTrace();
}
}else{
String topic = "rpi/gpio";
String payload = "Off";
byte[] encodedPayload = new byte[0];
try {
encodedPayload = payload.getBytes(StandardCharsets.UTF_8);
MqttMessage message = new MqttMessage(encodedPayload);
message.setRetained(true);
client.publish(topic, message);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
});
}
public void conn(View v){
try {
IMqttToken token = client.connect();
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Toast.makeText(MainActivity.this,"connected",Toast.LENGTH_LONG).show();
setSubscription();
}
private void setSubscription() {
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Toast.makeText(MainActivity.this,"connection failed",Toast.LENGTH_LONG).show();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
}
I need to implement a project, such as chat. We decided to use the Socket.IO library. FCM is not considered. To receive messages in the background using Service. Here:
public class SocketServiceProvider extends Service {
private Socket mSocket;
private final String EVENT_NEW_MESSAGE = "new_message";
private final String LOG_TAG = "SocketServiceProvider";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.e(LOG_TAG, "created()");
realm = Realm.getDefaultInstance();
startForeground(1, new Notification());
if (mSocket == null)
mSocket = BaseApplication.getSocket();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(LOG_TAG, "onStartedCommand()");
startSocket();
return START_STICKY;
}
private void startSocket() {
if (mSocket.connected()){
stopSocket();
}
mSocket.on(Socket.EVENT_CONNECT, onConnect);
mSocket.on(EVENT_NEW_MESSAGE, onNewMessage);
mSocket.connect();
}
private void stopSocket() {
mSocket.off();
mSocket.disconnect();
}
private Emitter.Listener onConnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
new Handler(Looper.getMainLooper()).post(() -> {
if (mSocket.connected()) {
isOnline = true;
Log.e(LOG_TAG, "Connected!");
}
});
}
};
private Emitter.Listener onNewMessage = args -> {
final JSONObject data = (JSONObject) args[0];
final String username;
final String message;
try {
username = data.getString("from");
message = data.getString("message");
} catch (JSONException e) {
Log.e("MainActivity", e.getMessage());
return;
}
Log.e(LOG_TAG, username + " wrote: " + message);
};
#Override
public void onDestroy() {
super.onDestroy();
Log.e(LOG_TAG, "onDestroy()");
stopSocket();
ContextCompat.startForegroundService(this, new Intent(this, SocketServiceProvider.class));
}
}
The only problem is that when the phone goes into Doze mode, messages do not come. Tried to wake up with AlarmManager in onTaskRemoved(), onDestroy(), unsuccessfully.
Even with onDestroy() tried to call BroadcastReceiver, so that it started back my Service, just did not understand why, but its onReceive() method does not work.
Here is my last option, the code that posted. There is I usе startForegroundService. And this option worked, at least not dying. Only in this case, the battery discharges quickly
Googled, Write that using JobIntentService can be implemented, but nowhere described in detail.
Question: How can this be done and how did you implement such tasks? And how can this be achieved with JobIntentService?
I'm doing a chat with the library smack Android 4.1.4. This library uses the XMPP protocol. To receive messages, you must authenticate to a server (for example openfire) and login using XMPPCONNECTION. All of this is quite simple if performed when the application starts. The problem comes when you have to receive messages when the application is closed. I tried to use an "Android service" to maintain this alive the connection between the client and the server. (In this case I did) but I do not think is the best method. Also because Android through service when the phone is switched off and on again the service does not restart by itself, and messages received while the phone was switched off will be lost. I attach the code Android. Do you have any advice ?. It would be useful to know how to do other chat applications such as whatsapp, badoo, facebook, telegram, etc ..
public class ServizioMessaggi extends Service {
public static final int NOTIFICATION_ID = 1;
static ChatManager chatmanager;
public static AbstractXMPPConnection connessione;
ConnettiServizio connetti;
MySQLiteHelper db;
String SharedPreferences = "Whisper";
public ServizioMessaggi() {
super();
}
#Override
public void onCreate() {
SharedPreferences sharedPref = getSharedPreferences(SharedPreferences, Context.MODE_PRIVATE);
connetti = new ConnettiServizio();
connetti.execute(sharedPref.getString("username",""),sharedPref.getString("password",""),"vps214588.ovh.net");
db = new MySQLiteHelper(this);
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public class ConnettiServizio extends AsyncTask<String,String,String> {
public AbstractXMPPConnection con;
#Override
protected String doInBackground(String... strings) {
con = new XMPPTCPConnection(strings[0],strings[1],strings[2]);
try {
con.connect();
con.login();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
connessione = con;
con.addConnectionListener(new ConnectionListener() {
#Override
public void connected(XMPPConnection connection) {
System.out.println("connected");
}
#Override
public void authenticated(XMPPConnection connection, boolean resumed) {
System.out.println("autenticathed");
}
#Override
public void connectionClosed() {
System.out.println("Connection Close");
}
#Override
public void connectionClosedOnError(Exception e) {
System.out.println("Connection Close whith error");
}
#Override
public void reconnectionSuccessful() {
System.out.println("reconnection ");
}
#Override
public void reconnectingIn(int seconds) {
}
#Override
public void reconnectionFailed(Exception e) {
System.out.println("recconnection failed");
}
});
ascolta();
}
}
private void ascolta() {
chatmanager = ChatManager.getInstanceFor(connetti.con);
chatmanager.addChatListener(new ChatManagerListener() {
public void chatCreated(final Chat chat, final boolean createdLocally) {
Log.i("chat creata", "****************");
chat.addMessageListener(new ChatMessageListener() {
public void processMessage(Chat chat, Message message) {
Log.i("messaggio arrivato", "****************");
//JOptionPane.showMessageDialog(null, "Rec: For " + chat.getParticipant() + " from " + message.getFrom() + "\n" + message.getBody());
String sender = message.getFrom();
System.out.println("Received message: " + (message != null ? message.getBody() : "NULL"));
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(ServizioMessaggi.this, Chat.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(ServizioMessaggi.this, 0,
notificationIntent, 0);
// scelta suoneria per notifica
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mBuilder =
(NotificationCompat.Builder) new NotificationCompat.Builder(ServizioMessaggi.this)
.setSmallIcon(R.drawable.ic_stat_notification)
.setColor(Color.argb(0,0,176,255))
.setTicker("Nuovo messaggio da " + message.getFrom())
.setContentTitle(sender.substring(0,sender.indexOf("#")))
.setContentText(message.getBody())
.setContentIntent(intent)
.setSound(sound);
// effettua la notifica
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
SimpleDateFormat s = new SimpleDateFormat("hh:mm:ss");
String ora = s.format(new Date());
//aggiungo il messaggio al database
Messaggio ms = new Messaggio();
ms.setUsername(message.getFrom().substring(0, message.getFrom().indexOf("/")));
ms.setIsmy("no");
ms.setTimestamp(ora);
ms.setMessaggio(message.getBody());
db.addMessaggio(ms);
if(ChatActivity.isvisible){
((Activity)ChatActivity.c).runOnUiThread(new Runnable() {
#Override
public void run() {
ChatActivity.updateListMessaggi();
}
});
} else {
}
}
});
}
});
}
}
Actually i am not solve yet this kind of stuff. But, i do way to change BackgroundService to ForegroundService for this case. Remember this will not solve any Android devices.
Unlike whatsapp, telegram, fb. They play in Native C (NDK) to force OS which permit app to run in backgroundservice.
You can dive in Telegram Source Code for this issue.
when app is closed we cannot maintain connection.
you have to receive message via push notification. And re connect it with server then ...
I'm creating an app in Android using Socket.IO. I am stuck at the Login itself. Here is my code for Login
public class MainActivity extends AppCompatActivity {
EditText uname_et, pwd_et;
Button log;
String username, password;
private Socket mSocket;
private Emitter.Listener onLogin = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e(args[0].toString(), "data");
Log.w("yes ", "in evtLogin");
// JSONObject data = (JSONObject) args[0];
}
};
{
try {
String URL = "http://MYIP:8081";
mSocket = IO.socket(URL);
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uname_et = (EditText) findViewById(R.id.username_input);
pwd_et = (EditText) findViewById(R.id.pwd);
log = (Button) findViewById(R.id.sign_in_button);
log.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
signin();
}
});
mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.i("Make Emit", "Emit");
Log.w(mSocket.connected() + " - ", "Connection status");
}
});
mSocket.on("evtLogin", onLogin);
mSocket.connect();
}
private void signin() {
username = uname_et.getText().toString();
password = pwd_et.getText().toString();
mSocket.emit("userName", username);
mSocket.emit("Password", password);
}
#Override
protected void onDestroy() {
super.onDestroy();
mSocket.off("evtLogin", onLogin);
}
}
I'm not sure that socket is even connected or not, I'm gettong logs from Socket.EVENT_CONNECT
08-31 12:22:22.062 13399-13441/com.fis.kotsocket I/Make Emit﹕ Emit
08-31 12:22:22.063 13399-13441/com.fis.kotsocket W/true -﹕ Connection status
But onLogin listener is not called.
As a newbie I am not sure what to do exactly.
js code
//code for login event
socket.on('evtLogin', function (loginData) {
console.log('loged');
User.findOne({'login.userName':loginData.userName,'login.password':loginData.password},function(err,user){
if(err){throw err;}
else {if(!user){
console.log('not a authenticated user');
}
else
{
var userType;
User.find({'login.userName':loginData.userName,'login.password':loginData.password},function(err,rslt){
if(err){throw err;}
else
{
userType = JSON.stringify(rslt[0]['userType'].userId);
socket.emit('evtUserType',userType);
}
})
}
}
});
console.log('done');
});
Your socket is not getting initialized.
Try this initialization:
private Socket mSocket;
{
try {
mSocket = IO.socket("enter url here");
} catch (URISyntaxException e) {}
}
Or it might be that you are not emitting the evtLogin event from your javascript code.