How to monitor LiveData hasActiveObservers()? - java

I have MyRepository that obtains a live feed from a server via a socket.
It provides its data to MyViewModel via a MutableLiveData object which can be observed from a Fragment.
To avoid wasting resources, I don't want MyRepository to be obtaining data from the server when there are no observers.
I'd like to know how to monitor MyRepository's MutableLiveData, so if there are no observers then MyRepository can stop retrieving data from the server. Similarly, if an observer is added, then data retrieval can (re)start.
Currently, I'm just using a basic Thread (see the createObserversMonitorThread() method) as the monitor:
public class MyRepository {
private static final String TAG = MyRepository.class.getSimpleName();
private MutableLiveData<String> mutableLiveData;
private Socket mSocket = null;
public MyRepository(Application application) {
mutableLiveData = new MutableLiveData<>();
createSocket();
createObserversMonitorThread();
}
private void createObserversMonitorThread() {
Thread thread = new Thread() {
#Override
public void run() {
try {
while (isAlive()) {
if (mutableLiveData.hasActiveObservers()) {
// We have observers, so connect to the server.
if (!mSocket.connected()) {
mSocket.connect();
}
}
else {
// We don't have observers, so disconnect from the server.
if (mSocket.connected()) {
mSocket.disconnect();
}
}
// Wait until next loop.
Thread.sleep(1000);
}
}
catch(Exception e) {
Log.e(TAG, "Exception", e);
}
}
};
thread.setName("MutableLiveData Observers Monitor");
thread.setPriority(1);
thread.setDaemon(true);
thread.start();
}
public LiveData<String> getMutableLiveData() {
return mutableLiveData;
}
/**
* This method posts retrieved data to mutableLiveData.
*/
private void createSocket() {
try {
mSocket = IO.socket(Constants.SERVER_URL);
mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "Connected.");
}
}).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
if (args[0] instanceof Exception) {
Log.e(TAG, "Connect error: ", (Exception)args[0]);
}
else {
Log.e(TAG, "Connect error: " + args[0]);
}
}
}).on(Socket.EVENT_RECONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "Reconnected.");
}
}).on(Socket.EVENT_RECONNECT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
if (args[0] instanceof Exception) {
Log.e(TAG, "Reconnect error: ", (Exception)args[0]);
}
else {
Log.e(TAG, "Reconnect error: " + args[0]);
}
}
}).on(Socket.EVENT_MESSAGE, new Emitter.Listener() {
#Override
public void call(Object... args) {
//Log.d(TAG, "Data received.");
String s = (String) args[0];
mutableLiveData.postValue(s);
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "Disconnected.");
}
}).on(Socket.EVENT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
if (args[0] instanceof Exception) {
Log.e(TAG, "Error: ", (Exception)args[0]);
}
else {
Log.e(TAG, "Error: " + args[0]);
}
}
});
}
catch(Exception e) {
Log.e(TAG, "Could not create socket", e);
}
}
}
It works, but is there a better way?
UPDATE
Solution, thanks to EpicPandaForce's answer:
public class MyRepository {
private static final String TAG = MyRepository.class.getSimpleName();
private MutableLiveData<String> mutableLiveData;
private Socket mSocket = null;
public MyRepository(Application application) {
createSocket();
mutableLiveData = new MutableLiveData<String>() {
#Override
protected void onActive() {
super.onActive();
// Connect to server. This will (re)start data being posted on mutableLiveData.
if (!mSocket.connected()) {
mSocket.connect();
}
}
#Override
protected void onInactive() {
super.onInactive();
// Disconnect from server. This will stop data being posted on mutableLiveData.
if (mSocket.connected()) {
mSocket.disconnect();
}
}
};
}
public LiveData<String> getMutableLiveData() {
return mutableLiveData;
}
/**
* This method posts retrieved data to mutableLiveData.
*/
private void createSocket() {
// Same code as before.
}
}

You can use extends LiveData<T> or extends MutableLiveData<T> to get ahold of onActive() callback where you are notified if you have at least 1 active observer, and onInactive() callback when you went from 1 to 0 active observers.
That way you don't even need to ask for hasActiveObservers().

Related

Android socket io event and Channel

How to add event and channel?
private void initSocketConnection() {
try {
mSocket = IO.socket("URL");
connectSocket();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
private void connectSocket() {
try {
mSocket.connect();
mSocket.on(Socket.EVENT_CONNECT, onConnect);
mSocket.on(Socket.EVENT_CONNECT_ERROR, onError);
mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
} catch (Exception e) {
e.printStackTrace();
}
}
private Emitter.Listener onDisconnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("SOCKET_TEST", "DISCONNECTION SUCCESSFULL");
}
};
/**
* Receiver class for socket connected event
*/
private Emitter.Listener onConnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("SOCKET_TEST", "CONNECTION SUCCESSFULL");
}
};
/**
* Receiver for socket failed events
*/
private Emitter.Listener onError = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("SOCKET_TEST", "CONNECTION FAIL " + args.toString());
}
};
I send a request, returns 32:44/socket.io,"Invalid namespace"
need to send event and channel
I use the library https://github.com/socketio/socket.io-client-java I do everything according to the documentation but nothing works.
Instead of creating a socket with just:
val socket = IO.socket("https://something.com/socket.io")
try the next code:
val opts = IO.Options()
opts.path = "/socket.io"
val socket = IO.socket("https://something.com", opts)
I had the same issue getting 4/socket.io, "Invalid namespace" trying to connect to the socket, and the code above fixed it.

Send a string through WiFi-Direct between two android devices

It is now over a month that I'm trying to send a string using WiFi-Direct between two android devices, but I'm still struggling hard to understand what I'm doing wrong.
I've looked around forums but they often don't give much detail on how to achieve what I want.
I also went through those two guides from the android developer's website:
Create P2P connections with Wi-Fi Direct
Wi-Fi Direct (peer-to-peer or P2P) overview
I'm using one activity - ActivityConnection - where I toggle the visibility of views depending on whether the user previously chose to send or to receive the string.
Immediatly, on the client side, discoverPeers() looks for any device with WiFi-Direct turned on and displays them on a ListView. Once the user chooses a device and presses the send button, the connection makes itself and the string is sent.
On the server side, the server is immediatly launched using my AsyncServerTask class. There, it waits for a client to connect and to retrieve its sent string.
My main problem is that, after choosing the device and tapping on the send button, the server side isn't receiving anything.
My second problem is that, sometimes, devices aren't being discovered and the listview stays empty.
Am I missing something? Or maybe doing something wrong?
Here's my current code.
I took the liberty to get rid of any line I thought to be out of context to make it easier to read.
ActivityConnection
public class ActivityConnection extends AppCompatActivity implements NewPeersListener {
public static final String CONNECTION_ACTOR = "actor";
public static final String SEND_INFO = "send";
public static final String RECEIVE_INFO = "receive";
ListView listViewDevices;
private IntentFilter intentFilter;
private WifiP2pManager manager;
private WifiP2pManager.Channel channel;
private WiFiDirectBroadcastReceiver receiver;
public List <WifiP2pDevice> listDevices;
private WifiP2pDevice selectedDevice;
#Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
confirm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
connectToSelectedDevice();
}
});
Intent intent = this.getIntent();
String actor = intent.getStringExtra(CONNECTION_ACTOR);
this.intentFilter = new IntentFilter();
this.intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
this.intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
this.intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
this.intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
this.manager = (WifiP2pManager) this.getSystemService(Context.WIFI_P2P_SERVICE);
this.channel = this.manager.initialize(this, this.getMainLooper(), null);
this.receiver = new WiFiDirectBroadcastReceiver(this.manager, this.channel, this);
this.listDevices = new ArrayList <> ();
if (actor.equals(SEND_INFO)) {
DeviceAdapter adapter = new DeviceAdapter(ActivityConnection.this, R.layout.device_item, this.listDevices);
this.listViewDevices.setAdapter(adapter);
this.listViewDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedDevice = listDevices.get(position);
}
});
this.discoverPeers();
}
else if (actor.equals(RECEIVE_INFO)) {
new ServerAsyncTask(this).execute();
}
}
#Override
protected void onResume() {
super.onResume();
this.receiver = new WiFiDirectBroadcastReceiver(this.manager, this.channel, this);
this.registerReceiver(this.receiver, this.intentFilter);
}
#Override
protected void onPause() {
super.onPause();
this.unregisterReceiver(this.receiver);
}
public void resultReceived (String result) {
Toast.makeText(ActivityConnection.this, "Received! :)", Toast.LENGTH_SHORT).show();
}
private void discoverPeers () {
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
// The discovery process succeeded
}
#Override
public void onFailure(int reason) {
// The discovery process DID NOT succeed
Toast.makeText(ActivityConnection.this, "Discovery process DID NOT succeed. Please verify that WiFi-Direct is active.", Toast.LENGTH_LONG).show();
}
});
}
private void connectToSelectedDevice () {
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = this.selectedDevice.deviceAddress;
this.manager.connect(this.channel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
// Send string
Intent serviceIntent = new Intent(ActivityConnection.this, TransferService.class);
serviceIntent.setAction(TransferService.ACTION_SEND_STRING);
serviceIntent.putExtra(TransferService.EXTRAS_GROUP_OWNER_ADDRESS, getMacAddress());
serviceIntent.putExtra(TransferService.EXTRAS_GROUP_OWNER_PORT, 8090);
startService(serviceIntent);
onBackPressed();
}
#Override
public void onFailure(int reason) {
Toast.makeText(ActivityConnection.this, "Connection failed. Try again.", Toast.LENGTH_SHORT).show();
}
});
}
#NonNull
private String getMacAddress () {
try {
List <NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equalsIgnoreCase("wlan0")) continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
return "";
}
StringBuilder result = new StringBuilder();
for (byte b : macBytes) {
result.append(String.format("%02X:",b));
}
if (result.length() > 0) {
result.deleteCharAt(result.length() - 1);
}
return result.toString();
}
} catch (Exception e) {
}
return "02:00:00:00:00:00";
}
#Override
public void newPeers (WifiP2pDeviceList wifiP2pDeviceList) {
this.listDevices = new ArrayList <> (wifiP2pDeviceList.getDeviceList());
DeviceAdapter adapter = new DeviceAdapter(ActivityConnection.this, R.layout.device_item, this.listDevices);
this.listViewDevices.setAdapter(adapter);
}
}
WiFiDirectBroadcastReceiver
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
private WifiP2pManager manager;
private WifiP2pManager.Channel channel;
private ActivityConnection activity;
private List <NewPeersListener> listeners;
public WiFiDirectBroadcastReceiver(WifiP2pManager manager, WifiP2pManager.Channel channel, ActivityConnection activity) {
super();
this.manager = manager;
this.channel = channel;
this.activity = activity;
this.listeners = new ArrayList <> ();
this.listeners.add(activity);
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
// Wi-Fi P2P is enabled
} else {
// Wi-Fi P2P is not enabled
Toast.makeText(this.activity, "Please turn on WiFi-Direct (or WiFi-P2P).", Toast.LENGTH_SHORT).show();
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
// Request available peers from the wifi p2p manager.
if (this.manager != null) {
this.manager.requestPeers(this.channel, new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peers) {
for (NewPeersListener listener : listeners) {
listener.newPeers(peers);
}
}
});
}
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
// Respond to new connection or disconnections
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
// Respond to this device's wifi state changing
}
}
}
ServerAsyncTask (server)
public class ServerAsyncTask extends AsyncTask<Void, Void, String> {
private ServerSocket serverSocket;
private Socket clientSocket;
private DataInputStream stream;
private WeakReference <Context> contextWeakReference;
ServerAsyncTask (Context context) {
this.contextWeakReference = new WeakReference <> (context);
}
#Override
protected String doInBackground (Void... params) {
try {
this.serverSocket = new ServerSocket(8090);
this.clientSocket = this.serverSocket.accept();
this.stream = new DataInputStream(this.clientSocket.getInputStream());
String received = this.stream.readUTF();
this.serverSocket.close();
return received;
} catch (IOException e) {
Log.e(TransferService.TAG, Objects.requireNonNull(e.getMessage()));
return null;
} finally {
if (this.stream != null) {
try {
this.stream.close();
} catch (IOException e) {
Log.e(TransferService.TAG, Objects.requireNonNull(e.getMessage()));
}
}
if (this.clientSocket != null) {
try {
this.clientSocket.close();
} catch (IOException e) {
Log.e(TransferService.TAG, Objects.requireNonNull(e.getMessage()));
}
}
if (this.serverSocket != null) {
try {
this.serverSocket.close();
} catch (IOException e) {
Log.e(TransferService.TAG, Objects.requireNonNull(e.getMessage()));
}
}
}
}
/*
* (non-Javadoc)
* #see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
#Override
protected void onPostExecute (String result) {
super.onPostExecute(result);
((ActivityConnection) this.contextWeakReference.get()).resultReceived(result);
}
}
TransferService (client)
public class TransferService extends IntentService {
public static final String TAG = "WIFI_DIRECT";
private static final int SOCKET_TIMEOUT = 5000;
public static final String ACTION_SEND_STRING = "sendString";
public static final String EXTRAS_GROUP_OWNER_ADDRESS = "go_host";
public static final String EXTRAS_GROUP_OWNER_PORT = "go_port";
public TransferService (String name) {
super(name);
}
public TransferService () {
super("TransferService");
}
#Override
protected void onHandleIntent (Intent intent) {
Context context = getApplicationContext();
if (intent.getAction().equals(ACTION_SEND_STRING)) {
String toSend = "string to send";
String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
Socket socket = null;
DataOutputStream stream = null;
try {
// Create a client socket with the host, port, and timeout information.
socket = new Socket();
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Log.d(TAG, "Client connected socket - " + socket.isConnected());
// Send string
stream = new DataOutputStream(socket.getOutputStream());
stream.writeUTF(toSend);
stream.close();
Toast.makeText(context, "Sent! :)", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Log.e(TAG, Objects.requireNonNull(e.getMessage()));
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
}
In the ActivityConnetion class, I was giving a MAC address instead of an IP address. I don't know why I didn't see this, nor why I did it in the first place. So I looked around this forum and found out how to get the IP address of the WiFi-Direct's group owner: Wifi Direct Group Owner Address .
To get the code running, I went into the ActivityConnetion class, delete the getMacAddress() method and replaced this line:
serviceIntent.putExtra(TransferService.EXTRAS_GROUP_OWNER_ADDRESS, getMacAddress());
with this line:
serviceIntent.putExtra(TransferService.EXTRAS_GROUP_OWNER_ADDRESS, "192.168.49.1");
As the group owner's IP is always the same, one can write it down directly. As doing so can stop working if the IP changes, I would recommend looking for the group owner's IP instead. The link above show's how to do it.

Unable to invoke target function on server side using SignalR Android client. java.lang.reflect.InvocationTargetException

I am using signalR android client in my app. The code was working fine all of a sudden, my code is unable to invoke server side funcitons. It gives java.lang.reflect.InvocationTargetException exception.
Here is my code,
public class SignalRService extends Service {
private microsoft.aspnet.signalr.client.hubs.HubConnection mHubConnection;
private microsoft.aspnet.signalr.client.hubs.HubProxy mHubProxy;
private Handler mHandler; // to display Toast message
private final IBinder mBinder = new LocalBinder(); // Binder given to clients
public static final String BROADCAST_ACTION = "com.android.com.simplechatwithsignalr";
public SignalRService() {
}
#Override
public void onCreate() {
super.onCreate();
mHandler = new Handler(Looper.getMainLooper());
// GlobalBus.getBus().register(this);
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable e) {
Log.i("hoo", "uncaughtException: " + e.getMessage());
}
});
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int result = super.onStartCommand(intent, flags, startId);
SubsrciptionHandlerAsync subsrciptionHandlerAsync = new SubsrciptionHandlerAsync();
subsrciptionHandlerAsync.execute("run");
return result;
}
#Override
public void onDestroy() {
try {
mHubConnection.stop();
} catch (Exception e) {
Log.i("destroying connection", "onDestroy: " + e.getMessage());
}
// GlobalBus.getBus().unregister(this);
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
// Return the communication channel to the service.
// startSignalR();
return mBinder;
}
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
public SignalRService getService() {
// Return this instance of SignalRService so clients can call public methods
return SignalRService.this;
}
}
/**
* method for clients (activities)
*/
public void startSignalR() {
Platform.loadPlatformComponent(new AndroidPlatformComponent());
String serverUrl = "https://signalr.shifa4u.com/";
serverUrl = serverUrl + "signalr";
String CONNECTION_QUERYSTRING = "access_token=" + "eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjYzNyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJzaGFoaWQubXJkQGhvdG1haWwuY29tIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9hY2Nlc3Njb250cm9sc2VydmljZS8yMDEwLzA3L2NsYWltcy9pZGVudGl0eXByb3ZpZGVyIjoiQVNQLk5FVCBJZGVudGl0eSIsIkFzcE5ldC5JZGVudGl0eS5TZWN1cml0eVN0YW1wIjoiMDY0Mjk4YTktNWIzNy00MGIxLWI1OTEtMzQwNGUzYTQ5YTE5IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiQ3VzdG9tZXIiLCJ1aWQiOiIyNjM3IiwibmJmIjoxNTUxNzg4NDc2LCJleHAiOjE1NTI5OTgwNzYsImlzcyI6Imh0dHBzOi8vYXBpLnNoaWZhNHUuY29tIiwiYXVkIjoiYWFkNGRjMDczOWI2NGM1MjlhYjg2YzIxMjZlZDM0MWMifQ.q0OAU8L9YRjkP5ampzdp7Ji8Vy-Wjd0Wf0hs3kTg3pg" + "&Is_Guest_User=NO";
mHubConnection = new microsoft.aspnet.signalr.client.hubs.HubConnection(serverUrl, CONNECTION_QUERYSTRING, false, new Logger() {
#Override
public void log(String message, LogLevel level) {
System.out.println(message);
}
});
mHubConnection.connected(new Runnable() {
#Override
public void run() {
System.out.println("CONNECTED");
Log.i("Initail Connect", "run: " + "Initial Connect");
}
});
mHubConnection.closed(new Runnable() {
#Override
public void run() {
Log.i("CLosed", "run: Disconnected");
}
});
mHubConnection.error(new ErrorCallback() {
#Override
public void onError(Throwable throwable) {
Log.i("Signal R throwable", "onError: " + throwable);
}
});
String SERVER_HUB_CHAT = "IntegratedHUB";
mHubProxy = mHubConnection.createHubProxy(SERVER_HUB_CHAT);
ClientTransport clientTransport = new ServerSentEventsTransport(mHubConnection.getLogger());
SignalRFuture<Void> signalRFuture = mHubConnection.start(clientTransport);
try {
signalRFuture.get();
} catch (InterruptedException | ExecutionException e) {
Log.e("SimpleSignalR", e.toString());
return;
}
try {
welcome();
// welcome();
} catch (Exception e) {
Log.i("Exception", "startSignalR: " + e.getMessage());
}
mHubProxy.on("connectionSucceeded", new SubscriptionHandler1<String>() {
#Override
public void run(final String msg) {
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "connectionSucceeded", Toast.LENGTH_SHORT).show();
Log.i("connectionSucceeded", "run: " + "connectionSucceeded");
invokeUpdateCall("");
}
});
}
}, String.class);
mHubProxy.on("guestConnectionSucceeded", new SubscriptionHandler1<String>() {
#Override
public void run(final String msg) {
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "guest", Toast.LENGTH_SHORT).show();
Log.i("connectionSucceeded", "run: " + "guest");
invokeUpdateCall("");
}
});
}
}, String.class);
mHubProxy.on("organizerConnectedForMobileClient", new SubscriptionHandler3<Long, String, String>() {
#Override
public void run(Long urgentCallId, String token, String resourceId) {
Log.i("organizerConnected", "run: " + "organizerConnected");
// Toast.makeText(SignalRService.this, "Organizer connected", Toast.LENGTH_SHORT).show();
/* Shifa4U.mySharePrefrence.setUrgentCallId(urgentCallId);
Shifa4U.mySharePrefrence.setToken(token);
Shifa4U.mySharePrefrence.setResourceId(resourceId);
mHandler.post(new Runnable() {
#Override
public void run() {
Events.ConnectWithDoctor connectWithDoctor =
new Events.ConnectWithDoctor("");
GlobalBus.getBus().post(connectWithDoctor);
}
});*/
}
}, Long.class, String.class, String.class);
mHubProxy.on("connectionFailed", new SubscriptionHandler1<String>() {
#Override
public void run(final String msg) {
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Connnection Failed", Toast.LENGTH_SHORT).show();
}
});
}
}, String.class);
mHubProxy.on("greatMessage", new SubscriptionHandler1<String>() {
#Override
public void run(final String msg) {
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Greatest message " + msg, Toast.LENGTH_SHORT).show();
}
});
}
}, String.class);
}
public void invokeOnConnectedHub(String message) {
String SERVER_METHOD_SEND = "OnConnectedHub";
if (mHubConnection.getState().toString().equals("Connected")) {
try {
mHubProxy.invoke(SERVER_METHOD_SEND).done(new Action<Void>() {
#Override
public void run(Void obj) throws Exception {
System.out.println("SENT!");
}
});
} catch (Exception e) {
Log.i("", "On Connected HUB: " + e.getMessage());
}
}
}
public void welcome() {
String SERVER_METHOD_SEND = "Welcome";
if (mHubConnection.getState().toString().equals("Connected")) {
try {
mHubProxy.invoke(SERVER_METHOD_SEND).done(new Action<Void>() {
#Override
public void run(Void obj) throws Exception {
System.out.println("SENT!");
}
});
} catch (Exception e) {
Log.i("", "On Connected HUB: " + e.getMessage());
}
}
}
public void invokeUpdateCall(String message) {
String SERVER_METHOD_SEND = "UpdateCallRoom";
// mHubProxy.invoke(SERVER_METHOD_SEND);
try {
mHubProxy.invoke(SERVER_METHOD_SEND).done(new Action<Void>()
{
#Override public void run(Void obj) throws Exception
{
System.out.println("SENT!");
}
});
}
catch (Exception e)
{
Log.i("", "UpdateCallRoom: "+e.getMessage());
}
}
}
class SubsrciptionHandlerAsync extends AsyncTask {
#Override
protected String doInBackground(String... strings) {
try {
SignalRService signalRService = new SignalRService();
signalRService.startSignalR();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
Here is the stack trace.
I/System.out: serverSentEvents - Found new data: data: {"C":"d-8BC122A6-B,1F|IU,0|IV,1","M":[{"H":"IntegratedHUB","M":"greatMessage","A":["Welcome"]}]}
serverSentEvents - Trigger onData: {"C":"d-8BC122A6-B,1F|IU,0|IV,1","M":[{"H":"IntegratedHUB","M":"greatMessage","A":["Welcome"]}]}
HubConnection - Received data:
I/System.out: MessageId received: d-8BC122A6-B,1F|IU,0|IV,1
Invoking OnReceived with: null
HubConnection - Processing message
I/System.out: HubConnection - Getting HubInvocation from message
I/System.out: HubConnection - Message for: integratedhub
I/System.out: HubConnection - Invoking event: greatmessage with arguments
["Welcome"]
I/System.out: HubConnection - Error: java.lang.reflect.InvocationTargetException
I/Signal R throwable: onError: java.lang.reflect.InvocationTargetException
I/System.out: serverSentEvents - Response received
serverSentEvents - Read response to the end
I/System.out: serverSentEvents - Trigger onData with data: {"I":"0"}
On function not works and throw exception when it calls. Use subscribe function instead of that. That's work for me.
hub.subscribe("name of your event").addReceivedHandler(new Action<JsonElement[]>(){
#Override
public void run(JsonElement obj) throws Exception {
// do something
}
});

Use Common MQTT class for Android APP

I am an novice android developer, I am using MQTT protocol for my android app.
I have found a code from internet for MQTT.But problem is that i have to use this MQTT Code for every activity which is redundant.I want to make a common java class
which can be call called any time whenever i need MQTT connection and communication.I have already tried but failed.Please anyone suggest me how to approach this?The code is given below
com.example.ab.mushroomv2;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class DashboardActivity extends AppCompatActivity {
final Context context = this;
//private EditText result;
private static final String TAG = "DA";
ProgressBar p_temp;
TextView progressingTemp;
MqttAndroidClient client;
String clientId;
static String topicTemp = "mushroom/temp";
String subMsg, top;
static String host = "tcp://iot.eclipse.org:1883";
Handler progressHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
p_temp = (ProgressBar) findViewById(R.id.progress_bar_temp);
progressingTemp = (TextViewfindViewById(R.id.progress_circle_temp_text);
establish();
client.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable cause) {
establish();
}
#Override
public void messageArrived(String topic, MqttMessage message) throws
Exception {
subMsg = new String(message.getPayload());
top=new String(topic);
if(top.contains("temp"))
{
double a=Double.parseDouble(subMsg);
final int msgTemp = (int) a;
Log.d(TAG, String.valueOf(msgTemp));
new Thread(new Runnable() {
public void run() {
progressHandler.post(new Runnable() {
public void run() {
p_temp.setProgress(msgTemp);
progressingTemp.setText("" + msgTemp + " ℃
");
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
}
public void establish() {
clientId = MqttClient.generateClientId();
client = new MqttAndroidClient(this.getApplicationContext(), host,
clientId);
try {
IMqttToken token = client.connect();
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Toast.makeText(DashboardActivity.this, "Client Connected",
Toast.LENGTH_SHORT).show();
try {
client.subscribe(topicTemp, 0);
} catch (MqttException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable
exception) {
Toast.makeText(DashboardActivity.this, "Client failed to
Connect", Toast.LENGTH_SHORT).show();
// establish();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
}
You need to create a singleton class. Here is an sample.
public class SocketIO {
private static final String TAG = SocketIO.class.getSimpleName();
private static SocketIO instance;
private Socket socket;
private SocketIO() {
try {
socket = IO.socket("http://ur_url_here");
} catch (URISyntaxException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
}
public static synchronized SocketIO getInstance() {
if (instance == null) {
instance = new SocketIO();
}
return instance;
}
public Socket getSocket() {
return socket;
}
public void open() {
if (socket != null)
socket.open();
}
public void close() {
if (socket != null)
socket.close();
}}

Can't send message and receive using java socket while connected to Network Service Discovery

I am using Network Service Discovery service to discovery peer and connected to them using socket so , so socket created successfully but i am not able to send message or receive message so below is my code
MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private NSDHelper mNsdHelper;
private int port;
private Context mContext;
ChatConnection mConnection;
private Button mDiscover, advertise_btn, connect_btn;
private Handler mUpdateHandler;
private TextView mStatusView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStatusView = (TextView) findViewById(R.id.status);
mContext = MainActivity.this;
mUpdateHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
String chatLine = msg.getData().getString("msg");
addChatLine(chatLine);
}
};
mConnection = new ChatConnection(mUpdateHandler);
mNsdHelper = new NSDHelper(this);
mNsdHelper.initNSD();
advertise_btn = (Button) findViewById(R.id.advertise_btn);
connect_btn = (Button) findViewById(R.id.connect_btn);
advertise_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Register service
if (mConnection.getLocalPort() > -1) {
mNsdHelper.registerService(mConnection.getLocalPort());
} else {
Log.d(TAG, "ServerSocket isn't bound.");
}
}
});
connect_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NsdServiceInfo service = mNsdHelper.getChosenServiceInfo();
if (service != null) {
Log.d(TAG, "Connecting.");
mConnection.connectToServer(service.getHost(),
service.getPort());
} else {
Log.d(TAG, "No service to connect to!");
}
}
});
mDiscover = (Button) findViewById(R.id.discover_btn);
mDiscover.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mNsdHelper.discoverServices();
}
});
}
public void clickSend(View v) {
EditText messageView = (EditText) this.findViewById(R.id.chatInput);
if (messageView != null) {
String messageString = messageView.getText().toString();
if (!messageString.isEmpty()) {
mConnection.sendMessage(messageString);
}
messageView.setText("");
}
}
public void addChatLine(String line) {
mStatusView.append("\n" + line);
}
#Override
protected void onPause() {
if (mNsdHelper != null) {
mNsdHelper.stopDiscovery();
}
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
if (mNsdHelper != null) {
mNsdHelper.discoverServices();
}
}
#Override
protected void onDestroy() {
mNsdHelper.tearDown();
mConnection.tearDown();
super.onDestroy();
}
}
ChatConnection
public class ChatConnection {
private Handler mUpdateHandler;
private ChatServer mChatServer;
private ChatClient mChatClient;
private static final String TAG = "ChatConnection";
private Socket mSocket;
private int mPort = -1;
public ChatConnection(Handler handler) {
mUpdateHandler = handler;
mChatServer = new ChatServer(handler);
}
public void tearDown() {
mChatServer.tearDown();
mChatClient.tearDown();
}
public void connectToServer(InetAddress address, int port) {
mChatClient = new ChatClient(address, port);
}
public void sendMessage(String msg) {
if (mChatClient != null) {
mChatClient.sendMessage(msg);
}
}
public int getLocalPort() {
return mPort;
}
public void setLocalPort(int port) {
mPort = port;
}
public synchronized void updateMessages(String msg, boolean local) {
Log.e(TAG, "Updating message: " + msg);
if (local) {
msg = "me: " + msg;
} else {
msg = "them: " + msg;
}
Bundle messageBundle = new Bundle();
messageBundle.putString("msg", msg);
Message message = new Message();
message.setData(messageBundle);
mUpdateHandler.sendMessage(message);
}
private synchronized void setSocket(Socket socket) {
Log.d(TAG, "setSocket being called.");
if (socket == null) {
Log.d(TAG, "Setting a null socket.");
}
if (mSocket != null) {
if (mSocket.isConnected()) {
try {
mSocket.close();
} catch (IOException e) {
// TODO(alexlucas): Auto-generated catch block
e.printStackTrace();
}
}
}
mSocket = socket;
}
private Socket getSocket() {
return mSocket;
}
private class ChatServer {
ServerSocket mServerSocket = null;
Thread mThread = null;
public ChatServer(Handler handler) {
mThread = new Thread(new ServerThread());
mThread.start();
}
public void tearDown() {
mThread.interrupt();
try {
mServerSocket.close();
} catch (IOException ioe) {
Log.e(TAG, "Error when closing server socket.");
}
}
class ServerThread implements Runnable {
#Override
public void run() {
try {
// Since discovery will happen via Nsd, we don't need to care which port is
// used. Just grab an available one and advertise it via Nsd.
mServerSocket = new ServerSocket(0);
setLocalPort(mServerSocket.getLocalPort());
while (!Thread.currentThread().isInterrupted()) {
Log.d(TAG, "ServerSocket Created, awaiting connection");
setSocket(mServerSocket.accept());
Log.d(TAG, "Connected.");
if (mChatClient == null) {
int port = mSocket.getPort();
InetAddress address = mSocket.getInetAddress();
connectToServer(address, port);
}
}
} catch (IOException e) {
Log.e(TAG, "Error creating ServerSocket: ", e);
e.printStackTrace();
}
}
}
}
private class ChatClient {
private InetAddress mAddress;
private int PORT;
private final String CLIENT_TAG = "ChatClient";
private Thread mSendThread;
private Thread mRecThread;
public ChatClient(InetAddress address, int port) {
Log.d(CLIENT_TAG, "Creating chatClient");
this.mAddress = address;
this.PORT = port;
mSendThread = new Thread(new SendingThread());
mSendThread.start();
}
class SendingThread implements Runnable {
BlockingQueue<String> mMessageQueue;
private int QUEUE_CAPACITY = 10;
public SendingThread() {
mMessageQueue = new ArrayBlockingQueue<String>(QUEUE_CAPACITY);
}
#Override
public void run() {
try {
if (getSocket() == null) {
setSocket(new Socket(mAddress, PORT));
Log.d(CLIENT_TAG, "Client-side socket initialized.");
} else {
Log.d(CLIENT_TAG, "Socket already initialized. skipping!");
}
mRecThread = new Thread(new ReceivingThread());
mRecThread.start();
} catch (UnknownHostException e) {
Log.d(CLIENT_TAG, "Initializing socket failed, UHE", e);
} catch (IOException e) {
Log.d(CLIENT_TAG, "Initializing socket failed, IOE.", e);
}
while (true) {
try {
String msg = mMessageQueue.take();
sendMessage(msg);
} catch (InterruptedException ie) {
Log.d(CLIENT_TAG, "Message sending loop interrupted, exiting");
}
}
}
}
class ReceivingThread implements Runnable {
#Override
public void run() {
BufferedReader input;
try {
input = new BufferedReader(new InputStreamReader(
mSocket.getInputStream()));
while (!Thread.currentThread().isInterrupted()) {
String messageStr = null;
messageStr = input.readLine();
if (messageStr != null) {
Log.d(CLIENT_TAG, "Read from the stream: " + messageStr);
updateMessages(messageStr, false);
} else {
Log.d(CLIENT_TAG, "The nulls! The nulls!");
break;
}
}
input.close();
} catch (IOException e) {
Log.e(CLIENT_TAG, "Server loop error: ", e);
}
}
}
public void tearDown() {
try {
getSocket().close();
} catch (IOException ioe) {
Log.e(CLIENT_TAG, "Error when closing server socket.");
}
}
public void sendMessage(String msg) {
try {
Socket socket = getSocket();
if (socket == null) {
Log.d(CLIENT_TAG, "Socket is null, wtf?");
} else if (socket.getOutputStream() == null) {
Log.d(CLIENT_TAG, "Socket output stream is null, wtf?");
}
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(getSocket().getOutputStream())), true);
out.println(msg);
out.flush();
updateMessages(msg, true);
} catch (UnknownHostException e) {
Log.d(CLIENT_TAG, "Unknown Host", e);
} catch (IOException e) {
Log.d(CLIENT_TAG, "I/O Exception", e);
} catch (Exception e) {
Log.d(CLIENT_TAG, "Error3", e);
}
Log.d(CLIENT_TAG, "Client sent message: " + msg);
}
}
}
NSDHelper
public class NSDHelper {
private static final String TAG = NSDHelper.class.getSimpleName();
NsdManager mNsdManager;
public static final String SERVICE_TYPE = "_geoStorm._tcp.";
public String mServiceName = "DROIDDEVICE";
NsdManager.DiscoveryListener mDiscoveryListener;
NsdManager.RegistrationListener mRegistrationListener;
NsdManager.ResolveListener mResolveListener;
NsdServiceInfo mService;
private Context mContext;
public NSDHelper(Context _context) {
mContext = _context;
mNsdManager = (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
}
public void initNSD() {
initializeResolveListener();
initializeDiscoveryListener();
initializeRegistrationListener();
}
/**
* This method is to register NSD
*
* #param port
*/
public void registerService(int port) {
NsdServiceInfo nsdServiceInfo = new NsdServiceInfo();
nsdServiceInfo.setPort(port);
nsdServiceInfo.setServiceName(mServiceName);
nsdServiceInfo.setServiceType(SERVICE_TYPE);
mNsdManager.registerService(nsdServiceInfo, NsdManager.PROTOCOL_DNS_SD,
mRegistrationListener);
}
public void initializeResolveListener() {
mResolveListener = new NsdManager.ResolveListener() {
#Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.e(TAG, "Resolve failed" + errorCode);
}
#Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
Log.e(TAG, "Resolve Succeeded. " + serviceInfo);
if (serviceInfo.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same IP.");
return;
}
mService = serviceInfo;
}
};
}
public void initializeDiscoveryListener() {
mDiscoveryListener = new NsdManager.DiscoveryListener() {
#Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
#Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
#Override
public void onDiscoveryStarted(String serviceType) {
Toast.makeText(mContext, "Discovery Started Successfully ",
Toast.LENGTH_LONG).show();
Log.d(TAG, "Service discovery started");
}
#Override
public void onDiscoveryStopped(String serviceType) {
Log.i(TAG, "Discovery stopped: " + serviceType);
Toast.makeText(mContext, "Discovery stopped", Toast.LENGTH_LONG).show();
}
#Override
public void onServiceFound(NsdServiceInfo serviceInfo) {
Log.d(TAG, "Service discovery success" + serviceInfo);
if (!serviceInfo.getServiceType().equals(SERVICE_TYPE)) {
Toast.makeText(mContext, "Unknown Service Type", Toast.LENGTH_LONG).show();
} else if (serviceInfo.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same machine: " + mServiceName);
} else if (serviceInfo.getServiceName().contains(mServiceName)) {
mNsdManager.resolveService(serviceInfo, mResolveListener);
}
Log.d(TAG, serviceInfo.getPort() + "");
// Log.d(TAG, new InetSocketAddress(serviceInfo.getHost());)
}
#Override
public void onServiceLost(NsdServiceInfo serviceInfo) {
Log.e(TAG, "service lost" + serviceInfo);
Toast.makeText(mContext, "service Lost" + serviceInfo, Toast.LENGTH_LONG).show();
if (mService == serviceInfo) {
mService = null;
}
}
};
}
public void initializeRegistrationListener() {
mRegistrationListener = new NsdManager.RegistrationListener() {
#Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
}
#Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
}
#Override
public void onServiceRegistered(NsdServiceInfo serviceInfo) {
mServiceName = serviceInfo.getServiceName();
}
#Override
public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
}
};
}
public void discoverServices() {
if (mNsdManager != null)
mNsdManager.discoverServices(
SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}
public void stopDiscovery() {
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
public NsdServiceInfo getChosenServiceInfo() {
return mService;
}
public void tearDown() {
mNsdManager.unregisterService(mRegistrationListener);
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
mNsdManager = null;
mRegistrationListener = null;
}
}
I need help in this that how i can send message using socket , coz i stuck i am not getting any nothing , any help would be appreciated.

Categories