Chirag Agrawal
Chirag Agrawal

Reputation: 353

How to start a new activity from a thread other than the Main thread in an Android Application?

I am developing an android game which can be played over bluetooth. I am able to pair the devices and complete the socket. But thats where the problem starts. After the connection is established and the socket is not null I want to start an activity at both server and client devices. I have tried various things but nothing seems to work. I am new to android programming and really need your help.

And this is my ServerThread.java

class ServerThread extends Thread {

private final BluetoothServerSocket mmServerSocket;
BluetoothAdapter mBluetoothAdapter;// = BluetoothAdapter.getDefaultAdapter();
final String NAME = "order and chaos";
final UUID MY_UUID = UUID.fromString("05c0bd24-c242-11e3-b4b6-b6ee55aeb395");
Context context;
public ServerThread(BluetoothAdapter mBluetoothAdapter,Context context) {
    // Use a temporary object that is later assigned to mmServerSocket,
    // because mmServerSocket is final
    this.context = context;
    this.mBluetoothAdapter = mBluetoothAdapter;
    BluetoothServerSocket tmp = null;
    try {
        // MY_UUID is the app's UUID string, also used by the client code
        tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
    } catch (IOException e) { }
    mmServerSocket = tmp;
}

public void run() {
    BluetoothSocket socket = null;
    // Keep listening until exception occurs or a socket is returned
    while (true) {
        try {
            socket = mmServerSocket.accept();
        } catch (IOException e) {
            break;
        }
        // If a connection was accepted
        if (socket != null) {
            // Do work to manage the connection (in a separate thread)



        }
    }

}

/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
    try {
        mmServerSocket.close();
    } catch (IOException e) { }
}
}

This is my ClientThread.java

public class ClientThread extends Thread
{

 private final BluetoothSocket mmSocket;
 private final BluetoothDevice mmDevice;
 BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 final UUID MY_UUID = UUID.fromString("05c0bd24-c242-11e3-b4b6-b6ee55aeb395");
 Context context;
    public ClientThread(BluetoothDevice device,BluetoothAdapter mBluetoothAdapter,Context context) {
        // Use a temporary object that is later assigned to mmSocket,
        // because mmSocket is final
        this.context = context;
        this.mBluetoothAdapter = mBluetoothAdapter;
        BluetoothSocket tmp = null;
        mmDevice = device;

        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try {
            // MY_UUID is the app's UUID string, also used by the server code
            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e) { }
        mmSocket = tmp;
    }

    public void run() {
        // Cancel discovery because it will slow down the connection
        mBluetoothAdapter.cancelDiscovery();

        try {
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
            mmSocket.connect();
        } catch (IOException connectException) {
            // Unable to connect; close the socket and get out
            try {
                mmSocket.close();
            } catch (IOException closeException) { }
            return;
        }

        ConnectedSocket con = new ConnectedSocket();
        con.start(1);
    }

    // Will cancel an in-progress connection, and close the socket 
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
 }

And this is the ConnectedSocket.java class which causing errors

 public class ConnectedSocket extends Thread{

GameActivity gt = new GameActivity();
private Looper myLooper;
int side;
public void start(int i)
{
    side = i;
}
public void run()
{
    Looper.prepare();

    // code that needed a separated thread
    if(side==0)
        gt.serverSide();
    if(side==1)
     gt.clientSide();

    myLooper = Looper.myLooper();
    Looper.loop();
    myLooper.quit(); 
}}

class GameActivity extends Activity{

public void serverSide()
{
    Intent i = new Intent(this,SetBoard.class);
    startActivity(i);
    Toast toast = Toast.makeText(getApplicationContext(),"You are order", Toast.LENGTH_LONG);
    toast.setGravity(Gravity.TOP|Gravity.LEFT, 50, 50);
    toast.show();
}

public void clientSide()
{
    Intent i = new Intent(this, SetBoard.class);
    startActivity(i);
    Toast toast = Toast.makeText(getApplicationContext(),"You are chaos", Toast.LENGTH_LONG);
    toast.setGravity(Gravity.TOP|Gravity.LEFT, 50, 50);
    toast.show();
}
 }

These are the errors I am getting

04-13 12:39:36.680: E/AndroidRuntime(30346): FATAL EXCEPTION: Thread-12
04-13 12:39:36.680: E/AndroidRuntime(30346): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-13 12:39:36.680: E/AndroidRuntime(30346):    at android.os.Handler.<init>(Handler.java:121)
04-13 12:39:36.680: E/AndroidRuntime(30346):    at android.app.Activity.<init>(Activity.java:686)
04-13 12:39:36.680: E/AndroidRuntime(30346):    at com.chirag.sudoku.GameActivity.<init>(ConnectedSocket.java:34)
04-13 12:39:36.680: E/AndroidRuntime(30346):    at com.chirag.sudoku.ConnectedSocket.<init>(ConnectedSocket.java:11)        
04-13 12:39:36.680: E/AndroidRuntime(30346):    at com.chirag.sudoku.ClientThread.run(ClientThread.java:53)     
04-13 12:39:36.740: D/dalvikvm(30346): GC_CONCURRENT freed 217K, 47% free 2971K/5575K, external 3501K/4547K, paused 4ms+3ms         
04-13 12:39:46.790: E/ActivityThread(30346): Activity com.chirag.sudoku.BluetoothMode has leaked IntentReceiver com.chirag.sudoku.BluetoothMode$1@4054b6c0 that was originally registered here. Are you missing a call to unregisterReceiver()?
04-13 12:39:46.790: E/ActivityThread(30346): android.app.IntentReceiverLeaked: Activity com.chirag.sudoku.BluetoothMode has leaked IntentReceiver com.chirag.sudoku.BluetoothMode$1@4054b6c0 that was originally registered here. Are you missing a call to unregisterReceiver()?
04-13 12:39:46.790: E/ActivityThread(30346):    at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:756)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:551)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:871)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.app.ContextImpl.registerReceiver(ContextImpl.java:858)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.app.ContextImpl.registerReceiver(ContextImpl.java:852)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:318)
04-13 12:39:46.790: E/ActivityThread(30346):    at com.chirag.sudoku.BluetoothMode.find(BluetoothMode.java:142)
04-13 12:39:46.790: E/ActivityThread(30346):    at java.lang.reflect.Method.invokeNative(Native Method)
04-13 12:39:46.790: E/ActivityThread(30346):    at java.lang.reflect.Method.invoke(Method.java:507)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.view.View$1.onClick(View.java:2180)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.view.View.performClick(View.java:2585)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.view.View$PerformClick.run(View.java:9299)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.os.Handler.handleCallback(Handler.java:587)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.os.Handler.dispatchMessage(Handler.java:92)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.os.Looper.loop(Looper.java:130)
04-13 12:39:46.790: E/ActivityThread(30346):    at android.app.ActivityThread.main(ActivityThread.java:3770)
04-13 12:39:46.790: E/ActivityThread(30346):    at java.lang.reflect.Method.invokeNative(Native Method)
04-13 12:39:46.790: E/ActivityThread(30346):    at java.lang.reflect.Method.invoke(Method.java:507)
04-13 12:39:46.790: E/ActivityThread(30346):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
04-13 12:39:46.790: E/ActivityThread(30346):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:670)
04-13 12:39:46.790: E/ActivityThread(30346):    at dalvik.system.NativeStart.main(Native Method)

Please tell me how to fix it. I have even tried to launch activity directly by extending Activity class by ConnectedSocket class. But that gives the same error.

Upvotes: 0

Views: 916

Answers (2)

r4jiv007
r4jiv007

Reputation: 3104

this may work :-

Handler handler = new Handler();
Runnable run= new Runnable() {

    @Override
    public void run() {

           Intent in = new Intent(context, YourActivity.class);
           in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
           startActivity(in);

    }
};
handler.post(run);

Upvotes: 1

ahmed_khan_89
ahmed_khan_89

Reputation: 2773

in your thread , you put the context of the current class :

Intent in = new Intent(CurrentActivity.this, YourActivity.class);
startActivity(in);

or you can as well take the parameter as a parameter...

Upvotes: 0

Related Questions