Android中的线程导致手机崩溃

时间:2011-08-01 13:02:39

标签: android multithreading crash deadlock

我不知道此代码中的失败原因是因为我无法读取崩溃日志。我们不是在谈论应用程序崩溃,而是可能由于死锁线程或某种锁定导致的手机崩溃。建议欢迎!


背景

当我启动连接时,会显示一个对话框,当我按下“返回”按钮时,对话框会冻结,过了一会儿手机崩溃......

代码:

这是处理与设备连接的线程。我没有问题连接到设备。我所知道的是当我按下后退按钮时mmSocket.connect()正在运行。认为问题出在某处......

class ConnectThread extends Thread {

/**
 * 
 */
private Handler threadhandler;
private BluetoothDevice mmDevice;
private volatile BluetoothSocket mmSocket;
private Message toMain;
//      private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

public ConnectThread(Handler threadhandler, BluetoothDevice device) {

    this.threadhandler = threadhandler;
    this.mmDevice = device;


    // Get a BluetoothSocket to connect with the given BluetoothDevice
    try {
        Method m = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
        mmSocket = (BluetoothSocket) m.invoke(mmDevice, 1);

    }catch (NoSuchMethodException e) {

        e.printStackTrace();
    } catch (IllegalArgumentException e) {

        e.printStackTrace();
    } catch (IllegalAccessException e) {

        e.printStackTrace();
    } catch (InvocationTargetException e) {

        e.printStackTrace();
    }

}

public void run() {
    Looper.prepare();
    try {
        // Connect the device through the socket. This will block
        // until it succeeds or throws an exception

        mmSocket.connect();

        toMain = threadhandler.obtainMessage();
        toMain.arg1 = 1;
        threadhandler.sendMessage(toMain);


    } catch (SecurityException e) {

        Log.e("SecurityExcep", "Oh noes" , e);
        toMain = threadhandler.obtainMessage();
        toMain.arg1 = 2;
        threadhandler.sendMessage(toMain);
        Log.w("MESSAGE", e.getMessage());

    }catch (IOException e) {
        //Bad connection, let's get the hell outta here
        try {
            Log.e("IOExcep", "Oh noes" , e);
            Log.w("MESSAGE", e.getMessage());

            mmSocket.close();
            toMain = threadhandler.obtainMessage();
            toMain.arg1 = 2;
            toMain.obj = e.getMessage();
            threadhandler.sendMessage(toMain);


            return;
        } catch (IOException e1) {
            Log.e("IOExcep2", "Oh noes" , e);
        }
    }
    try {
        mmSocket.close();
    } catch (IOException e) {
        Log.d("CONNECT_CONSTRUCTOR", "Unable to close the socket", e);
    }

    toMain = threadhandler.obtainMessage();
    toMain.arg1 = 3;
    threadhandler.sendMessage(toMain);

    Looper.loop();
    return;
    // Now it should be paired.. only thing to do now is let the user commit to the rest
}

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

}

下一个代码是对话框创建者的片段,该帖子名为d

(...)

        case DIALOG_BT_ADDING:
        search_dialog = new ProgressDialog(this);
        search_dialog.setTitle(R.string.adding);
        search_dialog.setMessage(res.getText(R.string.bluetooth_add_accept));
        search_dialog.setIndeterminate(true);           
        search_dialog.setCancelable(true);
        search_dialog.setOnCancelListener(new OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                Log.i("THREAD CONNECT", "Is it alive?: " + d.isAlive());
                if(d != null && d.isAlive()){
                    d.cancel();
                    //d = null;
                }
                if(d2 != null && d2.isAlive()){
                    d2.cancel(false);
                    //d2 = null;

                }
                search_dialog.dismiss();
                showDialog(DIALOG_NEW_DEVICE_FOUND);

            }
        });         
        return search_dialog;
(...)

以下是执行ConnectThread - 类

的代码片段
private void connectBluetooth(boolean nextstage, IOException e1){
    if(!nextstage){
        showDialog(DIALOG_BT_ADDING);

        d = new ConnectThread(threadhandler, selected_car.getDevice());
        d.start();

    }
    else{
        if(e1 != null){

            d2 = new BluetoothCheckThread(checkthreadhandler,mBluetoothAdapter, 
                    5000, car_bt, after_bt);
            d2.start();
            search_dialog.dismiss();
        }
        else{
            showDialog(DIALOG_BT_ADDING_FAILED);
        }
    }
}

希望你们能帮帮我!谢谢你的反馈

3 个答案:

答案 0 :(得分:1)

好的,你从看似UI线程的地方调用BluetoothSocket.close()。这可能导致“冻结”。

当你说手机“崩溃”时你的意思是它重新启动吗?如果是这样,那么完全重新启动(屏幕会回到第一次打开手机时会发生什么)或运行时重启(手机通常显示某种动画,在Nexus设备上,它是四色颗粒喷雾)?如果它不是重启,你的意思是你只是得到一个允许你杀死应用程序的对话框吗?

在任何一种情况下,您可能希望获得对调用BluetoothSocket.connect()的线程的引用并调用Thread.interrupt()。我不确定BluetoothSocket是否可以中断,但我们希望如此。然后在中断之后,调用close(),这可能不应该在主线程上调用。

答案 1 :(得分:0)

尝试使用dialog.setOnKeyListener(),在keyCode_BACK上取消线程。试试这会有效。

答案 2 :(得分:-2)

看起来你正在呼叫连接并关闭BluetoothSocket,这是一个“不行”。这似乎导致了僵局。有关详细信息,请参阅此link