【问题标题】:Thread in Android causes phone crashAndroid中的线程导致手机崩溃
【发布时间】:2011-10-17 10:42:30
【问题描述】:

我不知道这段代码中有什么失败,因为我无法阅读崩溃日志。我们不是在谈论应用程序崩溃,而是电话崩溃可能是由死锁线程或某种锁定引起的。欢迎提出建议!


背景:

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

代码:

这是处理与设备连接的线程。我完全没有连接到设备的问题。我所知道的是,当我按下后退按钮时,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) { }
}

}

接下来的代码是来自对话创建者的sn-p,线程被称为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-class的代码的sn-p

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);
        }
    }
}

希望大家能帮帮我!感谢您的任何反馈

【问题讨论】:

  • 我不认为你的代码在做你认为的那样。你能解释一下你认为它在做什么吗?你为什么在你的线程中搞乱 Loopers?在调用 Looper.quit() 之前,您所拥有的 run() 调用永远不会完成。这个 ConnectThread() 是从哪里开始的?
  • 我认为我的代码正在与蓝牙单元配对。这是它的主要和唯一目的,它也是这样做的。在连接过程中,我想将消息发送到与当前实现的 UI 线程一起使用的处理程序。对话框显示连接等超时/主机关闭等时间。但是当我在添加过程中按下后退按钮时会出现问题。Looper 可能是问题吗?
  • 是的,我不明白你为什么在这里使用 Looper,因为你没有发送带有 Looper 的线程任何消息。它也不清楚 ConnectThread() 是在哪里/如何启动的,你是在调用 run() 还是 start()?
  • Loopers 已删除,但问题仍然存在。在mmSocket.connect() 进度期间调用mmSocket.close() 时失败。观察 mmSocket.connect() 是一个锁定调用.. 这就是问题所在!

标签: android multithreading crash deadlock


【解决方案1】:

好的,您正在从看起来像 UI 线程的地方调用 BluetoothSocket.close()。这可能是导致“冻结”的原因。

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

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

【讨论】:

  • 不,我不是......调用 cancel() 并且在 cancel() 中我用mmSocket.close().. UI 冻结不会导致手机崩溃。系统会识别出 UI 没有发生任何事情,并且用户无法执行任何操作,从而导致系统对话框要求“等待”或“强制关闭”……这是另外一回事:S
  • 确实,我没有意识到 BT 套接字上的close() 会中断阻塞的呼叫。您能否更详细地描述“崩溃”,也许按照我的建议?
【解决方案2】:

尝试在 keyCode_BACK 上使用dialog.setOnKeyListener() 取消线程。试试这个就行了。

【讨论】:

  • 对话框取消时不调用onCancelListener吗?通过按后退按钮,我正在取消对话框,对吗?
  • 取消对话框同按返回键:developer.android.com/reference/android/app/…
  • 在对话框运行时停止,从而在对话框中调用OnCancel()
  • 而不是取消线程尝试使用 handler.removeCallBack(runnable);
  • 不是由处理程序启动的,为什么要执行 removeCallback?
【解决方案3】:

看起来您正在 BluetoothSocket 上调用 connect 和 close,这是一个“不不”。这似乎导致了僵局。请参阅此link 了解更多信息。

【讨论】:

  • 哇,所以问题是 tldr(太长了,没看过),但您发布了一个答案,该答案基于您在浏览现有答案时收集的假设......欢迎来到网站,但你会得到很多这样的答案的负面代表。
  • 不要只是投反对票。尝试阅读 OP 的问题并点击我的链接。我没有发布,因为我认为它不会有用。我的手机崩溃的关闭功能也遇到过类似的问题。我花时间查找链接并发布它。也许我有点讽刺,但如果你阅读了问题和示例代码,你应该明白为什么。
猜你喜欢
  • 2013-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
  • 2019-05-03
相关资源
最近更新 更多