How to communicate a service with a running thread in Android - android

my goal is to lunch a service that will take care for all of the application network needs.
i thought maybe to open 2 sockets for data transfer. i want the data to be handled asynchronously, so i was thinking my be i should run them in two separated threads, each for every socket, and that way the data could be streamed in two different "links" async..
so, i would appreciate two things:
a better overall design. maybe i completely got it all wrong..
can someone explain to me how can i communicate with those threds once i need to pass data to/from them to/from the main service? as far as i learnt (OS) i need to use SIGNALS:) (just kidding..)

Well, I can say i finally got it, just before giving up. Here is a super duper extremely simple app that runs a thread inside an activity and handles a bi-directional communication using two different Handlers for each entity!
The code:
public class MainActivity extends Activity {
//Properties:
private final String TAG = "Activity"; //Log tag
private MyThread mThread; //spawned thread
Bundle myB = new Bundle(); //used for creating the msgs
public Handler mHandler = new Handler(){ //handles the INcoming msgs
#Override public void handleMessage(Message msg)
{
myB = msg.getData();
Log.i(TAG, "Handler got message"+ myB.getInt("THREAD DELIVERY"));
}
};
//Methods:
//--------------------------
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mThread = new MyThread(mHandler);
mThread.start();
sendMsgToThread();
}
//--------------------------
void sendMsgToThread()
{
Message msg = mThread.getHandler().obtainMessage();
myB.putInt("MAIN DELIVERY", 321);
msg.setData(myB);
mThread.getHandler().sendMessage(msg);
}
}
//=========================================================================================
//=========================================================================================
public class MyThread extends Thread{
//Properties:
private final String TAG = "MyThread"; //Log tag
private Handler outHandler; //handles the OUTgoing msgs
Bundle myB = new Bundle(); //used for creating the msgs
private Handler inHandler = new Handler(){ //handles the INcoming msgs
#Override public void handleMessage(Message msg)
{
myB = msg.getData();
Log.i(TAG, "Handler got message"+ myB.getInt("MAIN DELIVERY"));
}
};
//Methods:
//--------------------------
public void run(){
sendMsgToMainThread(); //send to the main activity a msg
Looper.prepare();
Looper.loop();
//after this line nothing happens because of the LOOP!
Log.i(TAG, "Lost message");
}
//--------------------------
public MyThread(Handler mHandler) {
//C-tor that get a reference object to the MainActivity handler.
//this is how we know to whom we need to connect with.
outHandler = mHandler;
}
//--------------------------
public Handler getHandler(){
//a Get method which return the handler which This Thread is connected with.
return inHandler;
}
//--------------------------
private void sendMsgToMainThread(){
Message msg = outHandler.obtainMessage();
myB.putInt("THREAD DELIVERY", 123);
msg.setData(myB);
outHandler.sendMessage(msg);
}
}
//=========================================================================================
//=========================================================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.test.namespace"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".MainActivity" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
the output is:
01-26 06:25:40.683: I/Activity(19560): Handler got message123
01-26 06:25:40.683: I/MyThread(19560): Handler got message321
I figured this out while reading the offered post by endian, here.
I hope others will find this useful. good luck:)

Here is good post explaining threads and communication using handlers. Also, the same blog has a number of posts regarding various thread constructs in Android.
Another possibility is to use AsyncTasks. Find some explanation here

Related

onBackPressed() Internet no longer detected

I have an application that detects if internet is available or not.
I have changed the behaviour of the back button to avoid closing the application when pressed. The issue I'm facing is that when I have 4G or WIFI running and I run the app, it detects that internet is available, however, when I press the back button, the app is put on the background and internet is no longer detected by it.
I noticed that if I remove the permissions in the manifest file, the application works fine, it detects internet both when it is running and when put on background, but I need those permissions for making http post requests later.
Any help on this please?
Thanks.
MainActivity.java
public class MainActivity extends AppCompatActivity {
Timer timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
#Override
public void onBackPressed() {
this.moveTaskToBack(true);
}
private void init() {
timer = new Timer();
Tasker task = new Tasker(MainActivity.this, timer);
task.execute();
}
}
Tasker .java
public class Tasker extends AsyncTask<Void,Void,String> {
final Handler handler = new Handler();
static Timer timer;
Context context;
Toast toast;
private TimerTask doAsynchronousTask;
public Tasker(MainActivity context, Timer timer) {
this.timer = timer;
this.context = context;
}
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... voids) {
doTimerTask();
return null;
}
#Override
protected void onPostExecute(String response) {
}
private void showToast(String message){
toast = Toast.makeText(context, message, Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
if(!((Activity) context).isFinishing()){
toast.show();
}
}
private void doTimerTask() {
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#SuppressWarnings("unchecked")
public void run() {
if(haveNetworkConnection()){
showToast("Online");
}else{
showToast("Offline");
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 10000);
}
private boolean haveNetworkConnection() {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
return isConnected;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.e.myapplication">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
Actually, it may not be your desirable answer, but I think there is a way simpler way to do what you really want to do using a Broadcast receiver. you don't need to check network state using the timer. here's the link
I would suggest you to use a WorkManager or AlarmManager, or even Services for background related periodic tasks.
Using the Timer-AsyncTask combination is not a feasible approach and it could lead to many problems, one of which being it could easily be terminated by Android once it's in background.
My top pick would be WorkManager as it handles the condition for the tasks for you nicely, for example, if you want to only launch your task if there's internet connection, then you simply add a Work Constraint to your work request like this
Constraint networkConstraint = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
workRequest.setConstraints(constraints)
And your task will only be executed if the network is connected. BTW, they don't need to be manually re-set after reboot like AlarmManagers does.
However, there are downsides to it, one of them being the perodic requests can only occur every 15 minutes, which you can circumvent (though not recommended) by setting more one time work requests in each perodic request with smaller intervals of delayed start time.
Anyways, stop using the AsyncTask approach you are using now, and use one of the "legitimate" approaches Android approves to do background tasks, I recommend WorkManager, but based on your situation, you can choose whatever approach you like as long as it's meant to work in background.

Android Thread vs AsyncTask vs IntentService called from BLE onCharacteristicChanged()

I have an Android app from which I receive BLE data (every 62ms via notifications). The app can save data via a BufferedWriter to a file. Upon each onCharacteristicChanged() callback, I call either an AsyncTask, Thread or an IntentService to do a file write if the user enabled file save.
The AsyncTask seems to work fine. But the docs say execute must be invoked on the UI thread, and I'm calling it from the BLE callback. Is that a problem? And how should I fix it?
Using Thread causes this error: GKI_exception out of buffers https://code.google.com/p/android/issues/detail?id=65455 (except my code is not scanning but receiving notifications) and if the file save is long, I need to power cycle the Nexus 7 (the app and BLE become totally unresponsive). Why does the Thread not work and how can I fix it?
The IntentService never goes to the onHandleIntent(). What are the issues here?
Here is some code:
...
_context = this.getApplicationContext();
...
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
...
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
...
int mode = 1;
if (mode==0) // Asynctask
new doFileWriteTask().execute(strBuild.toString());
else if (mode==1) // Thread
{
final String str = strBuild.toString();
new Thread(new Runnable() {
public void run() {
try {
_writer.write(str);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
else if (mode==2) // intentService
{
Intent mServiceIntent = new Intent(_context, writeFileService.class);
mServiceIntent.putExtra("foo", strBuild.toString());
startService(mServiceIntent);
}
}
...
};
private class doFileWriteTask extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... strings) {
try {
_writer.write(strings[0]);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private class writeFileService extends IntentService {
public writeFileService() {
super("writeFileService");
}
#Override
protected void onHandleIntent(Intent workIntent) {
String dataString = workIntent.getStringExtra("foo");
try {
_writer.write(dataString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
...
But the docs say execute must be invoked on the UI thread, and I'm calling it from the BLE callback. Is that a problem? And how should I fix it?
The framework triggers the AsyncTask callback methods on the same thread it was called from (presumed to be the main thread). It doesn't really affect the background work, but you could see problems if you started trying to use onPostExecute() and the like. AsyncTask probably isn't the best choice to be called from a thread that you don't have control over.
Why does the Thread not work and how can I fix it?
I can't say exactly why you are still seeing errors, through spawning a series of private unsynchronized threads will probably lead to other headaches. If you want to use a single worker thread, a better choice would be to use a single HandlerThread that you can post to from your event callbacks using a Handler, something like:
…
_workerThread = new HandlerThread("Worker");
_workerThread.start();
_handler = new Handler(_workerThread.getLooper(), new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
String str = (String) msg.obj;
_writer.write(str);
return true;
}
});
…
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
…
Message msg = Message.obtain(_handler, 0, strBuild.toString());
_handler.sendMessage(msg);
…
}
That solution is quite a bit more code, but given the frequency of writes this is probably the most efficient choice.
The IntentService never goes to the onHandleIntent(). What are the issues here?
You should pretty much never implement a top level Android component (activity, service, content provider, receiver) as an inner class, because they have to be declared in your manifest as well (and the XML syntax for inner classes is ugly). If your service does not have a matching entry in the manifest, then you will never see it start. You might want to have a look at the docs on using services.
At a minimum, a Service written as an inner class must be public static to work. Otherwise the framework cannot see it and cannot instantiate it using a default constructor (non-static inner classes mess with the constructor). Unless you are calling startService() inside of a try/catch right now, I'm surprised it isn't crashing when you attempt this.
IntentService is probably the simplest of your three choices because it is the most decoupled and the framework will handle queueing up work and tearing down the threads when all the incoming work is done.

Intermitent NullPointerException when using AlarmManager in Android

I've developed a small Android application which uses an AlarmManager to call a Handler Thread that synchronizes some information from the mobile device with a remote server. This process happens every 15 minutes.
When I use the HandlerThread without the aid of the AlarmManager, everything ALWAYS works fine. But when I try to put these two to work together, SOMETIMES it works and SOMETIMES I get the following error :
W/System.err(10557): java.lang.NullPointerException
W/System.err(10557):at Synchronizer.queueSyncEverything(Synchronizer.java:109)
W/System.err(10557): at SyncService.onHandleIntent(SyncService.java:33)
W/System.err(10557): at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
W/System.err(10557): at android.os.Handler.dispatchMessage(Handler.java:99)<BR/>
W/System.err(10557): at android.os.Looper.loop(Looper.java:137)
W/System.err(10557): at android.os.HandlerThread.run(HandlerThread.java:60)
The code is really simple as you can see in the following snippets:
//Method from SyncService, a class which extends IntentService
protected void onHandleIntent(Intent intent) {
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
if(cm.getActiveNetworkInfo() == null){
return;
}
if(mSynchronizer == null){
mSynchronizer = new Synchronizer(getApplicationContext(), this);
mSynchronizer.start();
mSynchronizer.getLooper();
}
mSynchronizer.queueSyncEverything();
}
//Method from Synchronizer, a class which extends HandlerThread
public void queueSyncEverything(){
try{
mHandler.obtainMessage(MESSAGE_SYNC_EVERYTHING).sendToTarget();
}
catch(Exception e){
mListener.onError();
e.printStackTrace();
}
}
I already checked if the Handler or the Looper are null, but they're all fine.
EDIT:
As #DavidWasser suggested, I did some more testing and discovered that sometimes mHandler is null. This variable is set inside the method onLooperPrepared from Synchronizer (which extends from HandlerThread) as you can see here:
#Override
protected void onLooperPrepared(){
mHandler = new Handler(){
#Override
public void handleMessage(Message msg){
if(msg.what == MESSAGE_SYNC_EVERYTHING){
handleSyncEverything();
mListener.onFinished();
}
}
};
}
The constructor of this class, as #DavidWasser asked, is just:
public Synchronizer(Synchronizer.Listener listener){
super(TAG);
mListener = listener;
}
mListener is just an delegate-like object who receives events sent by the Synchronizer class, like when the Synchronization is finished. TAG is just a name to make it easier to debug. Maybe my main difficulty is to understand how the class HandlerThread works and when is it the right time to set its Handler object.
P.S.: This way of setting up the HandlerThread I got by reading the book "Android Programming: The Big Nerd Ranch Guide".
Don't initialize mHandler in onLooperPrepared() as this method could be called after the call to getLooper() returns. This is a small timing window that could bite you.
Instead create a method in Synchronizer like this:
public void createHandler() {
mHander = new Handler(getLooper()) {
#Override
public void handleMessage(Message msg){
if(msg.what == MESSAGE_SYNC_EVERYTHING){
handleSyncEverything();
mListener.onFinished();
}
}
};
}
and call this method in onHandleIntent() instead of calling mSynchronizer.getLooper().
This will ensure that mHandler is initialized before you call queueSyncEverything().
NOTE: You don't need to override onLooperPrepared() at all.

Use of Handler Android

Which is the better way to use a handler. Any advantages. All examples I have come across seem to give the inline version.
Using implements Handler.Callback in the class and implementing interface method.
or
Using inline code version
private Handler mHandler = new Handler(){ ....};
The common term or these inline class definitions is Anonymous Classes.
You can read more about the discussion on these in Java/Android: anonymous local classes vs named classes
Essentially the main differences are readbility, speed of coding, re-use and scope.
From a resource point of view the anonymous class creation may cause an overhead in the garbage collector as discussed in Avoid Creating Unnecessary Objects. I am not certain on the exact details of anonymous class creation, however, it is logical that implementing the interface on the class is more efficient.
#WilliamTMallard has provided an example of what NOT to do. In his example, a long and syntacticly complex handler should be implementented on the class rather than anonymous handler because it is harder to read and edit when defined inline.
http://developer.android.com/reference/android/os/Handler.html
package : android.os
public class
Handler
extends Object
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
There are two main uses for a Handler:
to schedule messages and runnables to be executed as some point
in the future; and
to enqueue an action to be performed on a different thread than
your own.
Exmaple 1
use handler in app splash page.
if (!isFirstIn) {
mHandler.sendEmptyMessageDelayed(GO_HOME, SPLASH_DELAY_MILLIS);
} else {
mHandler.sendEmptyMessageDelayed(GO_GUIDE, SPLASH_DELAY_MILLIS);
}
/**************************************************************************************
*1. Handler
*/
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if(isAuto){
switch (msg.what) {
case GO_HOME:
goHome();
break;
case GO_GUIDE:
goGuide();
break;
}
}
super.handleMessage(msg);
}
};
private void goHome() {
Intent intent = new Intent(SplashActivity.this, MainAct.class);
SplashActivity.this.startActivity(intent);
SplashActivity.this.finish();
}
private void goGuide() {
Intent intent = new Intent(SplashActivity.this, GuideActivity.class);
SplashActivity.this.startActivity(intent);
SplashActivity.this.finish();
}
Example 2
use Handler request network in child thread if the request work may takes time.
new Thread(new Runnable(){
#Override
public void run() {
String versionPath = Parameters.getCheckVersionPath();
String result = RequestHelper.doGet(versionPath, null);
Message msg = new Message();
Bundle data = new Bundle();
data.putString("result",result);
msg.setData(data);
handler1.sendMessage(msg);
}
}).start();
handler1 = new Handler(){
#Override
public void handleMessage(Message msg) {
String result = msg.getData().getString("result");
JSONObject obj;
try {
obj = new JSONObject(result);
Map<String, String> versionInfo = Helper.getSoftwareVersion(obj);
if (versionInfo != null) {
newVersion = versionInfo.get("version");
updateUrl = versionInfo.get("url");
}
} catch (JSONException e) {
Log.w("net work error!", e);
}
}
};
Example 3
use Handler and Timer to update progress bar.
logobar = (ImageView) findViewById(R.id.splash_bar);//progress bar.
logobarClipe = (ClipDrawable) logobar.getBackground();
timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
updateLogoBarHandler.sendEmptyMessage(0);
}}, 0, rate);
/**************************************************************************************
*2. Handler
*/
//update progress bar.
private Handler updateLogoBarHandler = new Handler() {
public void handleMessage(Message msg) {
if(logobarClipe.getLevel() < 10000){
//1.update image.
logobarClipe.setLevel(logobarClipe.getLevel() + rate*2);
//2.update text.
float percent = logobarClipe.getLevel() /100;
String percentTxtVerbose = String.valueOf(percent);
String percentTxt = percentTxtVerbose.substring(0, percentTxtVerbose.indexOf('.')) + "%";
bartxt.setText(percentTxt);
}else{
timer.cancel();
}
super.handleMessage(msg);
}
};
This really isn't an answer to the above question because I don't know what "the best way" is, and it likely depends on what you're doing. However, I'll explain what I'm doing and why.
I'm writing an app that serves as a remote controller. There are several activities that will interact with the controlled device, and different things need to happen based on the result of the command and the activity it came from. Two things I didn't like about handlers are A) that they end up being a sort of "kitchen sink" construct, implementing functionality from different sources, and B) that they separated an action (the send of the command in my case) from the processing of the result of that action. However, using an anonymous (right term? I'm such a noob.) handler as a parameter allows me to keep the logic together. Here's the pseudocode for my approach:
command = "Wake up!";
mDeviceInterface.write(command, new Handler() {
#Override
public void handleMessage(Message msg) {
switch(msg.what) {
case DeviceInterface.MESSAGE_TIMEOUT: // Process the timeout.
announce("Device not responding.");
break;
case DeviceInterface.MESSAGE_READ: // Process the response.
byte[] readBuf = (byte[]) msg.obj;
if (readBuf[0] == 0x05) {
// Success, update device status.
} else {
announce("Error!");
break;
}
}
}
});
(Always remember, this is probably worth exactly what you've paid for it. ;) )
There is a danger in using anonymous classes in Android. As described in this blog post -
In Java, non-static inner and anonymous classes hold an implicit
reference to their outer class.
And here comes an opportunity for a leak.
So, the short answer would be: implement the interface methods or use static inner classes (which don't hold an outer class reference).
For instance, a leak-safe Handler could look like this:
private static class ChangeTextHandler extends Handler {
private final WeakReference activity;
public ChangeTextHandler(MainActivity activity) {
this.activity = new WeakReference<>(activity);
}
#Override
public void handleMessage(Message msg) {
MainActivity activity = this.activity.get();
if (activity == null) {
Log.e(TAG, "Activity is null ChangeTextHandler.handleMessage()!");
return;
}
final String text = (String) msg.getData().get(BUNDLE_KEY);
if (!TextUtils.isEmpty(text)) {
switch (msg.what) {
// do something
}
}
}
}
I made a blog post around usage of Handlers, so might be worth checking as well :)

How to update UI via Handler

So, I am getting an error that I am updating the UI from the wrong thread. This of course was not my intention. My case is quite long, but I will try to do it justice with code snippets. My end goal is to run an expensive task in a separate thread and post update that happen along the way and at the end to my listView.
public class test extends Activity {
private ArrayAdapter<String> _mOutArrayAdapter;
private ListView _mOutView;
private EditText _mCmdEditText;
private Button _mRunButton;
private Interpreter _interpreter;
// Need handler for callbacks to the UI thread
public final Handler _mHandler = new Handler() {
public void handleMessage(Message msg) {
_mOutArrayAdapter.add(msg.getData().getString("text"));
};
};
// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateResultsInUi();
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_interpreter = new Interpreter(true);
_mOutView = (ListView)findViewById(R.id.out);
_mCmdEditText = (EditText)findViewById(R.id.edit_command);
_mRunButton = (Button)findViewById(R.id.button_run);
_mOutArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
_mOutView.setAdapter(_mOutArrayAdapter);
_mOutArrayAdapter.clear();
_interpreter.setOutputAdapter(_mOutArrayAdapter);
Thread t = new Thread() {
public void run() {
_mResults = _interpreter.executeExpression("startup;",_mHandler);
_mHandler.post(mUpdateResults);
}
};
t.start();
);
And then inside inpterpreter I do this:
public class Interpreter
{
private static Handler _mHandler;
public String executeExpression(String expression, Handler handler)
{
_mHandler = handler;
//Do a bunch of stuff that sometimes calls displayText from this class or from others
return answer;
}
public void displayText(String text)
{
Message msg = new Message();
Bundle bndl = new Bundle();
bndl.putString("text", text);
msg.setData(bndl);
_mHandler.dispatchMessage(msg);
}
}
The display of the final answer works. And the dispatchMessage is ending up triggering handleMessage, but it throw an error that I cannot modify the UI from outside of the UI thread which I know is illegal. So, what am I doing wrong?
Thanks!
_mHandler.dispatchMessage(msg);
dispatchMessage() causes the Handler to be run on the current thread.
http://developer.android.com/reference/android/os/Handler.html
dispatchMessage(Message msg)
Handle system messages here.
You should be using _mHandler.sendMessage(msg); It will put the message on the queue to be run by the Thread that declared the Handler.
sendMessage(Message msg)
Pushes a message onto the end of the message queue after all pending messages before the current time.
I would strongly suggest you stick with an AsyncTask (or one of the droid-fu versions if you need rotation/background support) unless you know what you're getting into. It'll help you cleanly keep track of what code is running in your UI thread and what code is in the background task, and save you a lot of confusion that dealing with Threads and Handlers yourself can cause.
Handler's post method requires a Runnable object in parameter, and scheduling execution of that runnable block. Instead you can use Handler.sendEmptyMessage() or Handler.sendMessage() to send a message to Handler. SO change your code to following:
Thread t = new Thread() {
public void run() {
_mResults = _interpreter.executeExpression("startup;",_mHandler);
Message msg= _mHandler.obtainMessage();
msg.obj= _mResults;
_mHandler.sendMessage(msg);
}
};

Categories

Resources