New to MQTT protocol. My code is working fine on eclipse platform. Now, trying to write publisher mqtt client for android and subscriber is running on eclipse. App is getting closed after launch. Please help me in the following code.
public class MainActivity extends AppCompatActivity
{
String text="HELOOO";
TextView textReply;
private MqttClient client;
public static final String TOPIC = "data";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
client = new MqttClient("http://IP-address:1883", MqttClient.generateClientId());
} catch (MqttException e) {
e.printStackTrace();
System.exit(1);
}
try {
client.connect();
MqttMessage mssg=new MqttMessage();
mssg.setPayload(text.getBytes());
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
System.exit(1);
}
}
}
Changes made after #arjun suggestions
public class MainActivity extends AppCompatActivity {
String text="HELOOO";
TextView textReply;
private MqttClient client;
public static final String TOPIC = "iot_data";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Publisher myClientTask = new Publisher();
myClientTask.execute();
}
}
class Publisher extends AsyncTask<Void, Void, Void>{
String text="helloo";
#Override
protected Void doInBackground(Void... voids) {
try {
MqttClient client = new MqttClient("tcp://Ip:1883", MqttClient.generateClientId());
client.connect();
MqttMessage mssg=new MqttMessage();
mssg.setPayload(text.getBytes());
client.publish("iot_data",mssg);
client.disconnect();
}catch(Exception e)
{
}
return null;
}
}
Maybe it has to do with that you are not specifying an ip adress properly on the client which leads to an exception where you do a system.exit(1);
Related
I'm trying Smack 4.2 on Android and I have a problem with the IncomingListener.
I created a class MyXMPP totaly dedicated to XMPP work.
( I just have one android activity. )
In this activity, in OnCreate(), I connected to XMPP server using my class MyXMPP and I retrieved my ChatManager in my a final value to place on an IncomingChatMessageListener().
Everything works well in the first try. But when I pause my activity and relaunch it, it's like the older listener remains. So at this moment, I receive messages in double.
If I pause again my application, it's like I have 3 listeners and so on.
I precise I have no problem whith connection to my server.
Here my code :
Android activity :
public class TestMessagingActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_messaging);
MyXMPPP.getInstance().init("test", "test");
MyXMPPP.getInstance().connect();
final ChatManager chatManager = MyXMPPP.getInstance().getChatManager();
chatManager.addIncomingListener(new IncomingChatMessageListener() {
#Override
public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
final AsyncTask<Message, Void, Void> mReceiveMessage = new AsyncTask<Message, Void, Void>() {
#Override
protected Void doInBackground(Message... params) {
ChatMessage chatMessage = new ChatMessage(params[0].getBody(), false);
Log.v("TAG", "index=message arrived");
Log.v("TAG", params[0].getBody());
return null;
}
#Override
protected void onPostExecute(Void res) {
}
};
mReceiveMessage.execute(message);
}
});
}
}
MyXMPP class :
public class MyXMPPP {
private static final String DOMAIN = "test.com";
private AbstractXMPPConnection connection;
private XMPPConnectionListener connectionListener = new XMPPConnectionListener();
private ChatManager chatManager;
private Presence presence;
boolean isConnected=false;
boolean chatManagerCreated=false;
private static MyXMPPP instance =null;
public synchronized static MyXMPPP getInstance() {
if(instance==null){
instance = new MyXMPPP();
}
return instance;
}
public void init(String user, String password) {
XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
configBuilder.setUsernameAndPassword(user, password);
configBuilder.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
configBuilder.setKeystoreType(null);
try {
configBuilder.setXmppDomain(DOMAIN);
} catch (XmppStringprepException e) {
e.printStackTrace();
}
connection = new XMPPTCPConnection(configBuilder.build());
connection.addConnectionListener(connectionListener);
}
public void connect() {
if (isConnected == false) {
AsyncTask<Void, Void, Boolean> connectionThread = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {
try {
connection.connect();
connection.login();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
};
connectionThread.execute();
}
}
public AbstractXMPPConnection getConnection() {
return connection;
}
public void createChatManager()
{
if(chatManagerCreated==false)
{
chatManager=ChatManager.getInstanceFor(connection);
chatManagerCreated=true;
Log.v("TAG", "index=chat manager created");
}
}
public ChatManager getChatManager()
{
return chatManager;
}
public void sendMessage(String message, EntityBareJid jid)
{
if(chatManagerCreated==true)
{
Chat chat = chatManager.chatWith(jid);
try {
chat.send(message);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean getIsConnected(){
return isConnected;
}
public class XMPPConnectionListener implements ConnectionListener{
#Override
public void connected(XMPPConnection connection) {
}
#Override
public void authenticated(XMPPConnection connection, boolean resumed) {
isConnected=true;
createChatManager();
presence = new Presence(Presence.Type.available, "Online", 24, Presence.Mode.available);
try {
connection.sendStanza(presence);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void connectionClosed() {
isConnected=false;
}
#Override
public void connectionClosedOnError(Exception e) {
isConnected=false;
}
#Override
public void reconnectionSuccessful() {
}
#Override
public void reconnectingIn(int seconds) {
}
#Override
public void reconnectionFailed(Exception e) {
}
}
}
Is this problem normal ?
When I put the listener to on the chatManager in the XMPP class, I don't have this problem. But I would like to do work in my activity / in my view, so having the listener here seems to be better.
I need some advice.
Thank you.
Nico.
I am basically trying to send a message from my android to my server and the server to send back a response to my android app. I followed THIS tutorial.
Just a simple exercise to introduce myself in to SignalR using Azure Web API and Android.
My Complete Server code in C#:
public class TestHub: Hub {
public void SendMessage(string name, string message) {
// Call the broadcastMessage method to update clients.
Clients.All.broadcastMessage(name, message);
}
public void SendClientMessage(CustomType obj) {
Clients.All.broadcastMessage("From Server", "Server got the message bro");
}
public class CustomType {
public string Name;
public int Id;
}
}
Complete Android Java code:
public class MainActivity extends AppCompatActivity {
Handler handler;
TextView statustext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
statustext = (TextView) findViewById(R.id.status);
Platform.loadPlatformComponent(new AndroidPlatformComponent());
// Change to the IP address and matching port of your SignalR server.
String host = "https://My-Service-name.azure-mobile.net/";
HubConnection connection = new HubConnection(host);
HubProxy hub = connection.createHubProxy("TestHub");
SignalRFuture < Void > awaitConnection = connection.start();
try {
awaitConnection.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
hub.subscribe(this);
try {
hub.invoke("SendMessage", "Client", "Hello Server!").get();
hub.invoke("SendClientMessage",
new CustomType() {
{
Name = "Android Homie";
Id = 42;
}
}).get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
}
//I have no idea what the following method is for. Just followed the tutorial.. (blindly)
public void UpdateStatus(String status) {
final String fStatus = status;
handler.post(new Runnable() {
#Override
public void run() {
statustext.setText(fStatus);
}
});
}
public class CustomType {
public String Name;
public int Id;
}
}
Problems with this:
1. I get an exception:
java.util.concurrent.ExecutionException:
microsoft.aspnet.signalr.client.transport.NegotiationException: There
was a problem in the negotiation with the server
2. I feel like I haven't properly called the server from the Java code.
Should the URL be:
https://My-Service-name.azure-mobile.net/
or
https://My-Service-name.azure-mobile.net/api/signalr
Can someone clarify these doubts and help me set it up?
I don't know what happen with my source code about Socket in Android, when I use method
.isConnected()
My app always force close. And here my source code
public class MyActivity extends Activity {
private String IP;
private int PORT;
private Socket socket;
private PrintWriter printWriter;
private TextView text;
private EditText fieldIp;
private EditText fieldPort;
private Button connect;
private FrameLayout frameIP;
private String message;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
frameIP = (FrameLayout)findViewById(R.id.frameIP);
connect = (Button)findViewById(R.id.connect);
fieldIp = (EditText)findViewById(R.id.ip);
fieldPort = (EditText)findViewById(R.id.port);
text = (TextView)findViewById(R.id.keterangan);
connect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
IP = fieldIp.getText().toString();
PORT = Integer.parseInt(fieldPort.getText().toString());
SocketConnect socketConnect = new SocketConnect(IP,PORT);
socketConnect.execute();
}
});
}
private class SocketConnect extends AsyncTask<Void, Void, Boolean> {
String ip;
int port;
public SocketConnect(String a, int b){
this.ip = a;
this.port = b;
}
#Override
protected Boolean doInBackground(Void... params) {
try {
socket = new Socket();
socket.connect(new InetSocketAddress(ip,port));
if(socket.isConnected())
{
text.setText("Connected!");
}
else
{
text.setText("Failed to connect!");
}
} catch (IOException e) {
Log.e("MyActivity",e.getMessage());
}
finally {
startActivity(new Intent(getApplicationContext(),ListViewText.class));
}
return null;
}
}
}
And I use this in AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
I hope you can help me guys :(
Change the doInBackground method as follows...
#Override
protected Boolean doInBackground(Void... params) {
boolean success = true;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(ip, port));
} catch (Exception e) {
success = false;
Log.e("MyActivity", e.getMessage());
}
return success;
}
Then add an onPostExecute method...
#Override
protected void onPostExecute(boolean result) {
if(result) {
text.setText("Connected!");
startActivity(new Intent(MyActivity.this, ListViewText.class));
}
else {
text.setText("Failed to connect!");
}
}
First thing you are calling UI operation outside of UI thread (that is why AsyncTask was created, to handle background job only in doInBackground) So problem about displaying text un TextView is solved...
But more important thing:
Never open Socket in AsyncTask. On Android developer site you can find following:
If you need to keep threads running for long periods of time, it is
highly recommended you use the various APIs provided by the
java.util.concurrent package such as Executor, ThreadPoolExecutor and
FutureTask.)
And that is exactly what you want to do. So use Service, Thread or those mentioned above instead.
I'm using asynctask to make connection between client (runnning on my android device) and server(running on my pc). When i launch the app i have to click on button to connect them, and my server pc program should show me in console device if client is connected but doesn't appear; my android client doesn't connect to my pc server.
Android client:
public class MainActivity extends ActionBarActivity {
Button send;
EditText txt;
TextView testo;
String response = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
send = (Button) findViewById(R.id.send);
//txt = (EditText) findViewById(R.id.editText);
testo = (TextView) findViewById(R.id.textView1);
}
class AddStringTask extends AsyncTask<Void, String, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... unused) {
try {
Socket socketClient = new Socket("10.10.0.151",4321); //ipaddress of my pc server
} catch (UnknownHostException e) {
e.printStackTrace();
response = e.toString();
} catch (IOException e) {
e.printStackTrace();
response = e.toString();
}
testo.setText(response);
return (null);
}
#SuppressWarnings("unchecked")
#Override
protected void onProgressUpdate(String... item) {
}
#Override
protected void onPostExecute(Void unused) {
testo.setText(response);
}
}
public void buttonClick(View v){
new AddStringTask().execute();
}
}
Pc server:
public class Server {
public static Socket connection;
public static void main(String[] args) throws IOException {
System.out.println("Starting server on port number: 4321...");
ServerSocket server = new ServerSocket(4321);
while(true){
System.out.println("Waiting for clients...");
connection = server.accept();
System.out.println("Connected to: "+connection.getInetAddress().getHostAddress());
connection.close();
}
}
}
In my AndroidManifest.xml i've just added
<uses-permission android:name="android.permission.INTERNET"/>
If i launch client from pc in my server console i see the device connected but on android doesn't work..why?
Thanks
It's most likely the ip in the android side is wrong. use a private ip eg: 192.168.1.x. theese types of ip require you be on the same network. i think what you're trying to do is access the server from outside of the network and that requires port fkrwarding.
I'm try to writing an online game with a socket connection.
So I use asynctask to make a socket connection.
SocketServer.java
public class SocketServer{
private MyCustomListener listener;
private String ip = "127.0.0.1";
private int port = 4444;
#SuppressWarnings("unused")
private Context context;
private SocketAsync socketAsync;
private String dataInput, username;
public SocketServer(Context context) {
this.context = context;
}
public void setOnRecieveMsgListener(MyCustomListener listener) {
this.listener = listener;
}
public void connect() {
socketAsync = new SocketAsync();
socketAsync.execute();
}
public void sentData(String x, String y, String z) {
dataInput = null;
JSONObject object = new JSONObject();
// JSON Encode
socketAsync.sentJSON(object);
}
private class SocketAsync extends AsyncTask<Void, Void, String> {
private Socket socket;
private PrintWriter printWriter;
#Override
protected String doInBackground(Void... params) {
try {
socket = new Socket(InetAddress.getByName(ip),port);
OutputStreamWriter streamOut = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
printWriter = new PrintWriter(streamOut);
streamOut.flush();
BufferedReader streamIn = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
Looper.prepare();
while(socket.isConnected()) {
try {
dataInput = streamIn.readLine();
listener.onRecieveMessage(new MyListener(dataInput));
}
catch(Exception e) {}
}
Looper.loop();
}
catch(Exception e) {}
return null;
}
public void sentJSON(JSONObject object) {
if(socket.isConnected()) {
try {
printWriter.println(object.toString());
printWriter.flush();
}
catch(Exception e) {}
}
}
}
}
Login.class
public class Login extends Activity implements MyCustomListener {
JSONObject object;
SocketServer socketserver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
socketserver = new SocketServer(this);
socketserver.setOnRecieveMsgListener(this);
socketserver.connect();
button();
}
private void button() {
Button loginBt = (Button)findViewById(R.id.login_bt);
final EditText un = (EditText)findViewById(R.id.username);
final EditText ps = (EditText)findViewById(R.id.password);
final String[] logindata = new String[2];
loginBt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
logindata[0] = un.getText().toString();
logindata[1] = ps.getText().toString();
socketserver.setUsername(logindata[0]);
socketserver.sentData("SERVER", "TEST", "login");
}
});
}
private void toMainScreen() {
Intent x = new Intent(this,Main.class);
startActivity(x);
}
#Override
public void onRecieveMessage(MyListener ml) {
try {
JSONObject json = new JSONObject(ml.getMsgStr());
System.out.println(json.getString("content"));
if(json.getString("content").equals("TRUE")) {
toMainScreen();
}
else
Toast.makeText(getApplicationContext(), "Login Fail", Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
Log.e("## JSON DECODE", e.toString());
e.printStackTrace();
}
}
}
Main.class
public class Main extends Activity implements MyCustomListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//do some thing
}
#Override
public void onRecieveMessage(MyListener ml) {
System.out.println("MAIN : " + ml.getMsgStr());
}
}
so how can I pass object "socketserver" from login class to main class?
or is there an other way to do something like this?
sorry for my poor english.
You should not try to pass an instance of SocketServer around. One of it's properties is context which means you should not used it outside the original context it was created in (i.e. activity it was created in) or you'll have memory leaks.
Your SocketServer class needs IP and port. This is the kind of information that you should pass between activities and then use that to create another instance of your SocketServer class.