Android java - Trying to show snackbar in new thread - java

Ive been trying to make my bluetooth connection thread be able to send messages to the user through snackbars, but they never appear on the screen.
In main method:
//listener for connect button
try {
Button btn_connect = findViewById(R.id.btn_connect);
btn_connect.setOnClickListener(view -> {
if(bluetoothService.isStarted()){
snackbarMsg(findViewById(R.id.btn_connect), "Bluetooth connection already established");
} else{
new Thread(() -> {
try {
Log.i(TAG, "New thread started");
bluetoothService.run(MainActivity.this);
Log.i(TAG,"Bluetooth service started");
snackbarMsg(findViewById(R.id.btn_connect), "Bluetooth service started");
} catch (Exception e) {
Log.e(TAG, "Bluetooth service failed", e);
}
}).start();
}
});
} catch (Exception exception){
Log.e(TAG, "Bluetooth service failed");
}
in BluetoothService class:
public void snackbarMsg (View view, String msg){
try {
Snackbar snackbar = Snackbar.make(view, msg, BaseTransientBottomBar.LENGTH_SHORT);
snackbar.show();
} catch (Exception exception){
Log.e(TAG, "Could not show snackbar", exception);
}
}
The view i send with the method is always of something on the main screen, so for example using "snackbarMsg(findViewById(R.id.button_send),"Failed to find bluetooth server");"
where button_send is on the screen i want to show the snackbar.
ive tried using runnables and extends thread and whatnot. But since i already have extensions on bluetoothservice class that didnt work, and runnable proved troublesome because i need to send context when starting the run method, and that context seemingly cant be sent at an earlier state, meaning i cant send that info when i create and object fom bluetoothservice at the beginning of the program.
Secondly: im not sure i even need a second thread, since my bluetooth connection is only sending data, not receiving, am i just doing useless work?

You need to run it on the UI/Main thread.
Use runOnUiThread(action: Runnable)
runOnUiThread(() -> snackbarMsg(view, "insert message"));

Related

Socket.io connection doesn't work for multiple fragments

I am creating a project with socket.io. It works really fine as long as there is just one fragment. However as I add more fragments in main activity, it starts creating multiple connections, which i think is not a good idea.
At first I connected to socket.io directly from fragments but that was creating one connection for each fragment. So I created a connection in Application class and used that in fragments which instantly solved multiple connection problem. But now a new problem has occurred.
In case of internet disconnection and reconnection, fragment doesn't get reestablished connection from Application class. I have been trying for over a week but no solution. strange thing is, i searched on internet and stackoverflow but not a single such question is ever asked.
here is connection code in Application class
synchronized public Socket getSocket() {
if (mSocket == null) {
try {
IO.Options opts = new IO.Options();
opts.reconnection = true;
opts.reconnectionDelay = 1000;
mSocket = IO.socket("http://ddbharti.in", opts);
mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "EVENT_CONNECT");
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "EVENT_DISCONNECT");
}
}).on(Socket.EVENT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "error");
}
});
mSocket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
return mSocket;
}
and this is how each fragment is connecting
socket = application.getSocket();
socket.emit("tag", tag);
If internet is working fine, this setup works flawlessly, loads in 300 milliseconds. However as i disconnect/reconnect internet or I keep internet disconnected and start the app and then connect to internet. Connection in Application class connects quickly, but due to some reason connection in current fragment just doesn't get it.
If i switch fragments then it starts listening to connection from Application class again.
So am i missing something here? How can i force fragment to get connection from application class again in case of reconnection without reloading whole fragment?
Any help is greatly appreciated.
So i created an event listner to listen to socket connection status and show ui accordingly. Just one connect with event listner was all that was needed.

How to fix dropped frames from a slow database connection?

button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
progressBar.setVisibility(View.VISIBLE);
button2 = (Button) findViewById(R.id.button);
button2.setVisibility(View.GONE);
Log.d("email", email);
email = emailView.getText().toString();
Log.d("email2", email);
password = passwordView.getText().toString();
connection.start();
try {
connection.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("00", "00");
Log.d("11", "11");
if (!validate()) {
onFailed();
clearForm((ViewGroup) findViewById(R.id.lin));
progressBar.setVisibility(View.INVISIBLE);
button2.setVisibility(View.VISIBLE);
} else {
screenSize();
}
}
});
}
I have an android app that I have been making for work which makes two calls to two different databases. One database is on site and is our and is super fast while the other connection is to an old database system off site. I have used Async and now I am using java threads (I find them easier to work with and alot more useful). I just want to know if there is a way to stop these dropped frames when connecting to the database when the user logs in because this creates a lag in when the log in button is submitted and then skips the progress spinner. The lag is around 2 second and normally drops around 300 frames.
I'm guessing that connection in the following is a Thread.
connection.start();
try {
connection.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
If so, then the problem is clear. When you call join() you block the UI thread. That is what causes the "lagging". If you want to avoid lagging and frame loss, you must not cause the UI thread to block.
The solution is something like this:
The listener should launch the thread (or whatever), put the UI into a "waiting to validate" state, and return.
The thread should establish the database connection, validate the credentials, then use runOnUiThread to take the UI out of the "waiting to validate" state.
If the user clicks the button while in "waiting to validate", ignore it.
The background thread could update the UI to indicate progress. And there needs to be some indication to the user that the validation step has passed or failed.

Connecting for the first time - reconnect

Currently this is not supported in paho java library, but I need this functionality in our application. For example, on application startup, we didn't have network connection, but after 30 seconds or so, we established connection successfully so I want my client to connect automatically.
My question is - what would be best approach to accomplish this? What I tried so far is to try to reconnect if something goes wrong during connect method. And since we use RxJava I have scheduled execution of the same method which is responsible for client connection. It will be easier if I paste the code.
private void connect(String brokerUrl) {
try {
LOG.info("Connecting to the broker...");
mqttClient.connect(connectionOptions, "Connecting", new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
LOG.info("Successfully conected to the broker.");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
LOG.error("Failed to connect to broker. Trying to reconnect in {} milliseconds...", connectionRetryTimeout, exception);
// try to reconnect in few seconds
Schedulers.io().scheduleDirect(() -> connect(brokerUrl), connectionRetryTimeout, TimeUnit.MILLISECONDS);
}
});
} catch (MqttException e) {
LOG.error("Connection error.", e);
}
}
What happens like this is that, when network connection is available I manage to connect automatically, but second thread is created which continues to retry to connect to broker. Does anyone already implemented this, or do you have any other suggestions?
The best way would be implementing a callback (asynchronous event based) that informs you as soon as teh network is available again
interface INetworkCallback{
void onNetworkStateChange(boolean newState);
}
and somewhere implement the interface

Android: Implementing a synchronous/blocking API using Messengers for IPC

I have a background service that runs in its own separate process using
android:process=":deamon"
In the manifest entry for the service. I want to communicate with the the service (remote process) from my activity and receive data from it.
I'm doing that by sending messages to and from the remote process as described in http://developer.android.com/guide/components/bound-services.html#Messenger and as they suggested I followed
If you want the service to respond, then you need to also create a Messenger in the client. >Then when the client receives the onServiceConnected() callback, it sends a Message to the >service that includes the client's Messenger in the replyTo parameter of the send() method.
The thing is, I need to provide a blocking/synchronous API to get data from my remote service, how can my "get" function block the caller and then return the data received in my incoming Handler ?
What would be the best approach to do that ?
This is code for messaging part of Client
SparseArray<CountDownLatch> lockArray = new SparseArray<>();
SparseArray<Bundle> msgDataArray = new SparseArray<>();
public Bundle sendAndWaitResponse(Message msg) throws
RemoteException, InterruptedException {
int msgId = msg.arg2;
Log.d("PlatformConnector", "Sending message to service, Type: "
+ msg.what + ", msgId: " + msg.arg2);
CountDownLatch latch = new CountDownLatch(1);
lockArray.put(msgId, latch);
platformMessenger.send(msg);
latch.await();
Bundle response = msgDataArray.get(msgId);
lockArray.delete(msgId);
msgDataArray.delete(msgId);
return response;
}
void storeResponseAndNotify(Message msg) {
int msgId = msg.arg2;
// Because the message itself is recycled after Handler returns,
// we should store only the data of message
msgDataArray.put(msgId, msg.getData());
lockArray.get(msgId).countDown();
}
private class ClientMessageHandler extends Handler {
#Override
public void handleMessage(Message msg) {
storeResponseAndNotify(msg);
}
}
This is example of utilizing above code.
RandomInt.getNextInt() is my custom static method, which generates random integer with Random.nextInt().
public JSONObject doSomething(JSONObject object) {
Message msg = Message.obtain(null, Constants.MESSAGE_SOMETHING, 0, RandomInt.getNextInt());
Bundle bundle = new Bundle();
bundle.putString(Constants.MESSAGE_DATA_SOMETHING, object.toString());
msg.setData(bundle);
try {
Bundle responseData = sendAndWaitResponse(msg);
return new JSONObject(responseData.getString(Constants.MESSAGE_DATA_RETURN));
} catch (RemoteException e) {
Log.e(TAG, "Failed to send message to platform");
e.printStackTrace();
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted while waiting message from platform");
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
Sequence is as follows,
The Client prepares Message and set its arg2 as some random integer
(this integer will be the message id for synchronization).
The Client prepares new CountDownLatch and put it to LockArray.
the Client sends message with sendAndWaitResponse(). It sends message to service via Messenger and invokes latch.await().
Service processes receives message and prepare reply message. The arg2 of this reply message should be same as received message.
Service sends reply message to client via Messenger in replyTo.
Client message handler handles the message with storeResponseAndNotify.
When the blocking of Client thread is finished, the response data would be already prepared in msgDataArray.
CountDownLatch is simple switch to block and unblock the thread.
(http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)
SparseArray is similar to HashMap, but more memory-efficient for smaller sets.
(http://developer.android.com/reference/android/util/SparseArray.html)
Be careful not to block the thread of Messenger. Messenger runs in single thread and if you block from the handleMessage(), it will block all other messages and cause deaklock problem.

How to implement shutdown hook handler in google appengine

How to implement shutdown hook handler in google appengine . Im not understanding their doc here https://developers.google.com/appengine/docs/java/backends/overview#Shutdown. what i need is, i need to be notified in the code when backend is stopped due to any to reason.
this is my code
try{
while (haveMoreWork() &&
!LifecycleManager.getInstance().isShuttingDown()) {
process(); // this is my function to read all the data.if it fails because of termination.i need to be notified.
}catch(Exception e){
log.log(Level.SEVERE, e.getMessage(), e);
log.severe("error occured"+e);
log.info("failed ");
}
You need to use the hook instead of the status report:
LifecycleManager.getInstance().setShutdownHook(new ShutdownHook() {
public void shutdown() {
// code
}
});

Categories