José  Chávez José Chávez - 14 days ago 10
Android Question

Access activity context from runnable interface

I have this setup

MainActivity Class creates BTHandler which is a utility class. It passes activity context and application context.

public class MainActivity extends Activity implements View.OnClickListener{

protected void onCreate(Bundle savedInstanceState) {
...
currentBT = new BTHandle(this, MainActivity.this);
}

public Handler handler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
...
super.handleMessage(msg);
}
};
}


This is the Utiliy class. It uses both context for some computation and when is required it creates ConnectThread, to start a connection with a BT device. It passes the activity context so ConnectThread can send a message through the Handler.

class BTHandle {
private final Context mainActivityContext;
private final Activity mainActivity;
...
public BTHandle(final Context context, final Activity activity){
mainActivityContext = context;
mainActivity = activity;
}
f(){
ConnectThread connectAsClient = new ConnectThread(mainActivityContext, BTDevice, mBluetoothAdapter, BTUuid);
new Thread(connectAsClient).start();
}

}


And Finally here comes the error. This is ConnectThread. I want to send a message from here to MainActivity. But compiler says it cant resolve handler. So I'm guessing the context doesn't come trough it.

public class ConnectThread implements Runnable {
private final Context mainActivity;
public ConnectThread(Context context, BluetoothDevice device, BluetoothAdapter adapter, UUID BT_UUID) {
...
mainActivity = context;
}

@Override
public void run() {
...
Message completeMessage = mainActivity.handler.obtainMessage(555, "CONNECTED");
completeMessage.sendToTarget();
}
}


How can I pass the context in the right way so ConnectThread can see handler?

Answer

You can either pass in the MainActivity object all the way down to ConnectRunnable i.e :

private final MainActivity mainActivity;
public ConnectThread(MainActivity context, BluetoothDevice device,
BluetoothAdapter adapter, UUID BT_UUID) {
 ...
 mainActivity = context;
 }

Or change your callback to:

 Message completeMessage = 
((MainActivity)(Activity)mainActivity)).handler.obtainMessage(555, "CONNECTED");

Also, your handler is bound to leak memory. Have a look at this for the fix: How to Leak a Context: Handlers & Inner Classes