Android : Message sent from seperate thread has obj set to null - android

I have a UI created in an activity which creates a handler for receiving messages.
I then launch a second thread for network communication. This second thread sends messages back to the UI thread via the UI threads handler.
All works OK as long as I send integer values.
However, if I set the objvalue to an object such as a string, when it arrives in the handler it has been set back to null.
The handler is declared like this :
private static class MsgHandler extends Handler
{
private CommsActivity m_parent;
public MsgHandler(CommsActivity parent)
{
m_parent = parent;
}
#Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
case R.integer.msg_progress :
m_parent.ShowProgress(msg.arg1);
break;
case R.integer.msg_error :
m_parent.ShowError(msg.arg1, (String)msg.obj);
break;
}
}
}
When I need to send a message from the second thread, I call it in this manner :
msg = m_hMsgHandler.obtainMessage();
msg.what = m_iNormalMsgId;
msg.arg1 = R.integer.activation_lockout;
msg.obj = new String(strResponse);
msg.sendToTarget();
The MsgHandlerinstance is passed into the thread runnable as a parameter and stored for later use.
I have also tried using a Bundle instance, but this also is set to NULL.
Note that I am working with Android 4.4.
What do I need to do to overcome this limitation ?

try to send message using handler.
hope it helps
msg = m_hMsgHandler.obtainMessage();
msg.what = m_iNormalMsgId;
msg.arg1 = R.integer.activation_lockout;
msg.obj = new String(strResponse);
m_hMsgHandler.sendMessage(msg);
and check, that you process exactly this message (I see in yuor samples set msg.what = m_iNormalMsgId but in switch process case R.integer.msg_progress like msg.arg1 = R.integer.activation_lockout;)

This is how I'd try it:
m_hMsgHandler.sendMessage(
m_hMsgHandler.obtainMessage(
m_iNormalMsgId,
R.integer.activation_lockout,
0,
new String(strResponse)
);

Related

Can we pass messages to UI thread without reference to UI handler?

I have a complex class system, with many classes trying to update UI elements, so i searching for most efficient way to achieve this.In my opinion, using handler is the best solution (if you know the better way - please share it ). But there is some problem. If i use this code in separate thread - sended messages seems to be lost(without any warning), and UI handler don't dispatch them:
Handler handler = new Handler(Looper.getMainLooper());
Message message = handler.obtainMessage();
Parameters p = new Parameters(-1, -1);
p.setObdProtocols(ObdProtocols.values()[protocolPointer]);
message.obj = p;
handler.sendMessage(message);
This is code for UI handler:
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.d("OBD2DEBUGMODE", "MainActivity.handler: handling message: "+msg.what);
Parameters temp = (Parameters) msg.obj;
rpmTxt.setText(""+temp.getRpm());
throtleText.setText(""+temp.getThrotlePosition());
if(temp.getObdProtocols()!=null) {
protoTxt.setText(temp.getObdProtocols().toString());
}
}
};
Above code is not working... Why couldn't i just pass messages to UI thread queue holding reference to UI Looper? How can i update UI thread without passing some objects to background threads?

Android: How to Switch on Runnable in Message Queue?

I have searched the java API on Thread, Handler, HandlerThread, Looper , as well as SO, and cannot find an answer. Of course, I have also used Eclipse's debugger to step and inspect my 'msg'.
Situation: If you protect your data model from concurrency issues by allowing only one worker thread to have access to it, how would you then differentiate between a Runnable versus a Message in its handleMessage(Message msg) if you were enqueueing both Messages and Runnables in the same message queue?
Q. While my Runnables execute as planned after being posted via handler.postDelayed(myRunnable), I would like to inspect the contents of the Runnable while my worker thread is switching upon it so that I can update my data model appropriately.
I welcome all feedback and appreciate your time!
Below is the entire contents of 'msg' as shown from Eclipe's debugger. Is there even enough information here to switch on the Runnable?
msg Message (id=830030887816)
arg1 0
arg2 0
callback null
data Bundle (id=830030968104)
mAllowFds true
mClassLoader BootClassLoader (id=830023329296)
packages HashMap (id=830023329320)
parent null
mFdsKnown true
mHasFds false
mMap HashMap (id=830030980304)
mParcelledData null
flags 1
next null
obj null
replyTo null
target IncomingHandler (id=830031033176)
what 0
when 180369888
Below is my worker thread's handleMessage(). Specifically, I instantiated a HandlerThread as my worker thread and bound it's getLooper() to my worker thread Handler.
#Override
public void handleMessage(Message msg) {
// If this is a Runnable then I need to call my method.
// This next line is a hack to test for Runnable.
// I would like to know how to inspect this Runnable
if (0 == msg.arg2 && 0 == msg.arg1 && 0 == msg.what)
incrementStateMachineBecauseRunnableStarted();
// Determine which action to take
// http://stackoverflow.com/questions/5021246/conveniently-map-between-enum-and-int-string
switch (Cmd.values()[msg.what]) {
case RECEIVE_NEW_LIST_EMPLOYEES:
receiveNewListEmployees(msg);
break;
case UPDATE_ONE_EMPLOYEE_STATE:
updateOneEmployeeState(msg);
break;
default:
Log.e(this.getClass().getName(), "unexpected message.";
break;
}
This is how I enqueue my Runnable (I run this code on my worker thread, so it is sending a message to itself, to be processed later in handleMessage(Message msg)):
// Create a new Runnable for this employee
PostUpdate update = new PostUpdate(employee);
// Post this Runnable with a sort delay
postDelayed(update, WAIT_BEFORE_PUSH_MS);
... and this is how I enqueue my Messages (from another thread):
Message msg = mHandler.obtainMessage();
msg.what = Cmd.RECEIVE_NEW_LIST_EMPLOYEES.ordinal();
msg.arg1 = 77; // deliberately inserting debug value
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(Cmd.RECEIVE_NEW_LIST_EMPLOYEES.toString(), mEmployees);
msg.setData(bundle);
mHandler.sendMessage(msg);
Finally, my Runnable:
private class PostUpdate implements Runnable {
private final Employee mEmployee;
public PostUpdate(Employee employee) {
mEmployee = employee;
}
#Override
public void run() {
// Post update through network to MySql server
mDao.setState(mEmployee);
}
}
My conclusion from using the debugger and inspecting the elements is that you cannot determine in handleMessage() whether a message or a runnable is being processed.
I found empirically (through elimination) that all my Runnables had a msg.what == 0 when I set all my messages to have msg.what to be something other than 0. Use with care!

Posting a Message to a running Thread using Handlers

I have code which calls a new Thread that connects to an IRC server. The thread has loop to listen for response from the IRC server and calls a method 'ProcessData' to action the response.
On my UI I want to be able to 'QUIT' the IRC server in onStop and onPause. The trouble I have is that when I use a Handler to post a message to my IRC thread which sends a QUIT command to the IRC server it tells me that I am performing network operations on the UI thread.
The handler is setup in my IRCManager class (this class extends Thread and is the class I run on a separate thread.
public Handler networkHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
try {
processData((String) msg.obj);
} catch (IOException e) {
Log.e(TAG, "network handler given an object NOT of type String");
}
super.handleMessage(msg);
}
};
I use the handler from the main activity and instantiate it just after starting the network thread
irc.start();
networkHandler = irc.networkHandler;
In the onPause event I send a message to the handler
Message msg = new Message();
msg.obj = IRCManager.QUIT;
networkHandler.sendMessage(msg);
EDIT: Here is the processData method
void processData(String data) throws IOException {
if (data.contains("PING")) {
String pingId = data.substring(6, data.length());
sendMessage(pong + pingId + "\n");
isConnected = true;
Message msg = new Message();
msg.what = 1;
msg.obj = "test";
handler.sendMessage(msg);
} else if (data.contains("Welcome")) {
sendMessage("PRIVMSG " + BOT_NAME + " JOIN " + siteId + "\n");
} else if (data.contains(IRCManager.QUIT)) {
disconnect();
} else if (isClientConnected()) {
Message msg = new Message();
msg.what = 2;
msg.obj = "test";
handler.sendMessage(msg);
}
}
It seems that the handler isn't linking properly to the thread. Can anyone shed any light on how I can do this?
My thread actually spends 99% of it's time in a while loop checking the inputstream from the IRC server. This may also have something to do with it.
You're creating the instance of the Handler, networkHandler, here:
public Handler networkHandler = new Handler() {
It'll be therefore associated with the UI thread.
And, when you say:
I use the handler from the main activity and instantiate it just after starting the network thread
irc.start();
networkHandler = irc.networkHandler;
You're not creating the instance of the Handler there; you're just grabbing a reference to it.
You actually need to create the instance of the Handler in the run() method of your non-UI Thread.
Try to use another constructor with new Handler(new Handler.Callback() ) inside

Put string in Handler

I've a little problem.I try to give a string to a handler.
I tried it with bundle.putString("key","String"); , but if i try to get the string, i got a nullpointerException. Can somebody tell me what i'm doing wrong?
Code:
Message msg = new Message();
Bundle b = new Bundle();
b.putString("note","4.25");
b.putString("fach", "Math");
Log.d("DEBUG ",b.getString("note")+" "+fach); //--> Here isn't a nullPointerException
msg.setData(b);
handler.sendMessage(msg);
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle b = msg.getData();
Log.d("DEBUG,HANDLER","note "+b.getString("note")+" fach"+b.getString("fach")); //Throws 2 times null
}
}
Hope you can help me. Sorry for the bad english :)
This isn't a lot of code to go on, but I would try using Message.obtain() instead of new Message(). I'm not convinced that the message you're receiving in handleMessage() is the one you sent in handler.sendMessage(). Both the sendMessage() and the handleMessage() have to be called on the same Thread, and you have to make sure you haven't put any other Message objects in the handler's MessageQueue.

What is the Message in WebView.requestFocusNodeHref (Message hrefMsg)?

I am trying to get the url of the image touched by a user in a WebView.
I use getHitTestResult() but I need to handle cases where getHitTestResult() return UNKNOWN_TYPE.
The documentation suggests requestFocusNodeHref (Message hrefMsg) but I don't understand what the Message should be.
Thank you for any idea.
Answering my own question here.
So this is how it works. The message in question must be sent to a Handler that will handle the request.
/*
* Used to get the result of requestFocusNodeHref(msg)
*/
class MyHandler extends Handler{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String src = msg.getData().getString("src");
launchImageSaveAs(src);
}
}
Then, somewhere in your code, for example in OnLongClickListener you create a new message and set the handler as a target and finally call requestFocusNodeHref
if(result.getType() == HitTestResult.UNKNOWN_TYPE){
Message msg = new Message();
msg.setTarget(new MyHandler());
webview.requestFocusNodeHref(msg);
}

Categories

Resources