Question

I have a client/server application that needs to be able to launch different Activities. I have a working TCP thread that runs continuously in the background and a working handler in my MainAcitivty which the TCP thread uses to send messages. The problem is getting that handler to launch anything other than strings. My TCP thread creates an object of the MainActivity on start up so it can access my handler which it must do since my handler is not static. Everything works fine if I run it from a button on my MainActivity but I get nullpointexceptions on everything when launched from my handler. I believe it dislikes my Context but I can’t find a work around. Thanks

Handler TCP_handler = new Handler()
{   
@Override
    public void handleMessage(Message msg) {

Message.obtain();
Bundle bundle = msg.getData();          

switch( msg.what ){
        case 1: 
            // this stuff works
    String aResponse1 = bundle.getString("messageStringL1");
        String aResponse2 = bundle.getString("messageStringL2");
        if(aResponse1 != null)
            textViewLineOne.setText(aResponse1);
        if(aResponse2 != null)
            textViewLineTwo.setText(aResponse2);

            break;
        case 2:  
            // Method 1
            // nullpointer exception error
            Intent i = new Intent(MainActivity.this, IdleScreen.class);      
        startActivity(i);

            // Method 2
            // nullpointer exception error
            Toast.makeText(MainContextSaved, "This is Toast!!!", Toast.LENGTH_SHORT).show();  

            // Method 3
            // this launches but can only write to the MainActivty textview 
            runOnUiThread(IdleScreenUI);    
            break;
}
    }
};


private Runnable IdleScreenUI = new Runnable() {
    @Override
    public void run() {

        // this is the new screen I want to display
            setContentView(R.layout.idlescreen );  // nullpointer exception error

            // this is a textview in the MainActivity and it works
            // textViewLineOne.setText("hello");   

        // null pointer exception error
            Toast.makeText(MainContextSaved, "This is Toast!!!", Toast.LENGTH_SHORT).show();  

    }
}; 
Was it helpful?

Solution

My TCP thread creates an object of the MainActivity on start up.

Even if you create the object of the activity , that is not a real activity context. thats why your unable to start the other activity.

If I understood your problem correctly, when you try to start the other activity from handler, the MainActivity is in foreground(in stack).

Assuming that you have launched the MainActivity and your TCP operations are done in background.

If your background TCP operations are done from a service,then when the MainActivity is started you can bind to the service and share the activity context to the service.

So now with the MainActivity context you can send Message to the handler.

Here is a sample I created..

CustomService.java

public class CustomService extends Service {
private final IBinder mIBinder = new LocalBinder();
// temporary handler
private Handler mHandler = new Handler();
// context to hold MainActivity handler 
private Context mActivityContext = null;

@Override
public int onStartCommand(Intent intent, int flag, int startId) {

    // for testing Iam sending an empty message to the handler after 10 seconds
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if (mActivityContext != null) {
                ((MainActivity) mActivityContext).TCP_handler.sendEmptyMessage(2);
            }
        }
    }, 10000);
    return START_STICKY;
}

@Override
public IBinder onBind(Intent intent) {
    return mIBinder;
}

public void setActivityContext(Activity activityContext) {
    mActivityContext = activityContext;
}

public class LocalBinder extends Binder {
    public CustomService getInstance() {
        return CustomService.this;
    }
  }
}

Now , you can start the service from activity and bind a service connection.

MainActivity.java

public class MainActivity extends ActionBarActivity {

CustomService customService = null;
TextView textViewLineOne;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // start the service, even if already running no problem.
    startService(new Intent(this, CustomService.class));
    // bind to the service.
    bindService(new Intent(this,
            CustomService.class), mConnection, Context.BIND_AUTO_CREATE);
}

private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        customService = ((CustomService.LocalBinder) iBinder).getInstance();
        // pass the activity context to the service
        customService.setActivityContext(MainActivity.this);
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        customService = null;
    }
};

@Override
protected void onDestroy() {
    super.onDestroy();
    if (customService != null) {
        // Detach the service connection.
        unbindService(mConnection);
    }
  }

  // Add your handler code stuff here..
}

OTHER TIPS

Handler class doesn't have a startActivity() method, does it! You can use a static context and store the value of the activity in it in onCreate() then call context.startActivity()

Intent mIntent = new Intent(context,YourActivity.class);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top