多个蓝牙套接字连接/关闭操作重新启动 Android 手机

发布于 2024-11-16 00:24:33 字数 9064 浏览 1 评论 0原文

我们使用 Android 手机通过蓝牙与传感器进行通信。手机需要定期连接传感器来收集生理数据,并且在两次连接之间传感器可以自动关闭以节省电量。

现在的问题是:大约500次后,系统重新启动。然后我们编写了一小段测试程序来模拟整个过程。这个小测试程序也会使 Android 手机崩溃。

有人可以帮我解决这个问题吗?谢谢!这是小测试程序。

package zhb.test.MhubTestBtConnect;

import java.io.IOException;
import java.util.Date;
import java.util.UUID;


import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MhubTestBtConnect extends Activity implements OnClickListener{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btnStart = (Button) findViewById(R.id.btn_start_test);
        btnStart.setOnClickListener(this);
        Button btnStop = (Button) findViewById(R.id.btn_stop_test);
        btnStop.setOnClickListener(this);

        fBeginView = (TextView) findViewById(R.id.begin_time);
        fBeginView.setText("off line");
        fEndView = (TextView) findViewById(R.id.end_time);
        fEndView.setText("off line");
        fShowView = (TextView) findViewById(R.id.show_status);
        fShowView.setText("off line");

        fShowRunTimesView = (TextView) findViewById(R.id.show_times_status);
        fShowRunTimesView.setText("off line");


        fInputMac = (EditText) findViewById(R.id.edit_add_mac);
        fInputMac.setText("00:19:5D:24:CB:A9");
        fDisconnectGap = (EditText) findViewById(R.id.edit_disconnect_gap);
        fDisconnectGap.setText("500");
        fconnectGap = (EditText) findViewById(R.id.edit_connect_gap);
        fconnectGap.setText("1000");

        fRunning = false;        
    }

    @Override
    public void onClick(View v)
    {
        switch ( v.getId() )
        {
            case R.id.btn_start_test:
                start();
                break;
            case R.id.btn_stop_test:
                stop();
                break;
            default:
                break;
        }       
    }

    private synchronized void start()
    {
        if ( fRunning == false )
        {
            fRunning = true;            


            fMac = fInputMac.getText().toString().toUpperCase();
            fConnectRunnable = new ConnectRunnable();           
            fBeginView.setText(new Date().toLocaleString());

            fConnectTimes = 0;
            fRunOkTimes = 0;
            new Thread(fConnectRunnable).start();
        }
    }

    private synchronized void stop()
    {
        if ( fRunning == true )
        {
            fRunning = false;

            fConnectRunnable.cancel();
            try
            {
                Thread.sleep(500);
            }
            catch (InterruptedException exception)
            {
                exception.printStackTrace();
            }


            fEndView.setText(new Date().toLocaleString());
        }
    }   

    private void connect()
    {
        Log.d(TAG,"---------- run "+fConnectTimes++ +" times");
        String UUID_STRING = "00001101-0000-1000-8000-00805F9B34FB";
        // may throws exception
        UUID uuid = UUID.fromString(UUID_STRING);

        // get adapter
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();        

        // get remote device
        BluetoothDevice btDevice = adapter.getRemoteDevice(fMac);
        if ( btDevice == null )
        {
            Log.e(TAG,"can't get remote device from given MAC : " + fMac);
            return;
        }
        int runResult = 0;
        // may throws exception
        fBtSocket = null;
        try
        {
            fBtSocket = btDevice.createRfcommSocketToServiceRecord(uuid);
            if ( adapter.isDiscovering() == true ) 
            {
                adapter.cancelDiscovery();
                Log.d(TAG,"cancel discover");
            }

            fBtSocket.connect();
            runResult = 1;
            Log.d(TAG,"connect socket OK");
            Log.d(TAG,"---------- run OK "+fRunOkTimes++ +" times");
        }
        catch (IOException exception)
        {       
            //adapter.cancelDiscovery();
            Log.d(TAG,"connect socket error",exception);
            if ( fBtSocket != null )
            {
                try
                {
                    fBtSocket.close();
                }
                catch (IOException exception1)
                {
                    Log.d(TAG,"close socket error",exception1);
                }
            }
            else
            {
                Log.d(TAG,"create socket NULL");
            }

            btDevice = null;
            //update ui
            Message msgRun = new Message();
            msgRun.what = R.id.show_status;
            msgRun.arg1 = SV_START_RUN;
            msgRun.arg2 = runResult;
            fMessHandler.sendMessage(msgRun);
        }

        //Note: You should always ensure that the device is not performing device discovery when you call connect(). 
        //If discovery is in progress, then the connection attempt will be significantly slowed and is more likely to fail.
        //adapter.cancelDiscovery();
    }
    private void close()
    {
        //update ui
        Message msgShut = new Message();
        msgShut.what = R.id.show_status;
        msgShut.arg1 = SV_SHUT_DOWN;
        fMessHandler.sendMessage(msgShut);

        if ( fBtSocket != null )
        {
            Log.d(TAG,"close socket");
            try
            {
                fBtSocket.close();
            }
            catch (IOException exception1)
            {
                Log.d(TAG,"close socket error",exception1);
            }
            fBtSocket = null;
        }
    }   
    private Handler fMessHandler = new Handler()
    {
        public void handleMessage(android.os.Message msg)
        {
            switch ( msg.what )
            {
                case R.id.show_status:
                    if ( msg.arg1 == SV_START_RUN )
                    {
                        if ( msg.arg2 == 1)
                            fShowView.setText("run OK");
                        else 
                            fShowView.setText("run Failed");

                        fShowRunTimesView.setText("run "+fConnectTimes+", OK "+fRunOkTimes);
                    }
                    else if ( msg.arg1 == SV_SHUT_DOWN )
                        fShowView.setText("shut down ...");

                    break;

                default:
                    break;
            }
        };
    };

    private long fConnectTimes;
    private long fRunOkTimes;
    private static final String TAG = "..MhubTestBtConnect";
    private BluetoothSocket fBtSocket;

    private ConnectRunnable fConnectRunnable;
    private String fMac;
    private boolean fRunning;

    private TextView fBeginView;
    private TextView fEndView;
    private TextView fShowView;
    private TextView fShowRunTimesView;
    private EditText fInputMac;
    private EditText fDisconnectGap;
    private EditText fconnectGap;

    private static final int SV_START_RUN = 1;
    private static final int SV_SHUT_DOWN = 2;

    private class ConnectRunnable implements Runnable
    {
        public ConnectRunnable()
        {           
            fCancelled = false;
        }
        @Override
        public void run()
        {           
            if (Looper.myLooper() == null) {
                Looper.prepare();
            }

            long afterConnectSleep = 500;
            long afterCloseSleep = 1000;
            try
            {
                afterCloseSleep = Integer.parseInt(fconnectGap.getText().toString());
                afterConnectSleep = Integer.parseInt(fDisconnectGap.getText().toString());
            }
            catch(Exception exception)
            {
                afterConnectSleep = 500;
                afterCloseSleep = 1000;
            }
            while ( fCancelled == false )
            {               
                connect();
                try
                {
                    Thread.sleep(afterConnectSleep);
                }
                catch (InterruptedException exception)
                {
                    exception.printStackTrace();
                }

                close();
                try
                {
                    Thread.sleep(afterCloseSleep);
                }
                catch (InterruptedException exception)
                {
                    exception.printStackTrace();
                }
            }
        }

        public void cancel()
        {
            fCancelled = true;
        }
        private boolean fCancelled;

    }
}

We are using android phones to communicate with sensors via bluetooth. The phone needs to connect the sensor periodically to collect physiological data and between two connections the sensors can be switched off automatically to save power.

Now the problem is: after around 500 times, the system reboots. We then wrote a small piece of test program to simulate the whole process. The small test program, too, crashes the android phone.

Can anybody please help me on this ? Thanks! Here is the small test program.

package zhb.test.MhubTestBtConnect;

import java.io.IOException;
import java.util.Date;
import java.util.UUID;


import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MhubTestBtConnect extends Activity implements OnClickListener{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btnStart = (Button) findViewById(R.id.btn_start_test);
        btnStart.setOnClickListener(this);
        Button btnStop = (Button) findViewById(R.id.btn_stop_test);
        btnStop.setOnClickListener(this);

        fBeginView = (TextView) findViewById(R.id.begin_time);
        fBeginView.setText("off line");
        fEndView = (TextView) findViewById(R.id.end_time);
        fEndView.setText("off line");
        fShowView = (TextView) findViewById(R.id.show_status);
        fShowView.setText("off line");

        fShowRunTimesView = (TextView) findViewById(R.id.show_times_status);
        fShowRunTimesView.setText("off line");


        fInputMac = (EditText) findViewById(R.id.edit_add_mac);
        fInputMac.setText("00:19:5D:24:CB:A9");
        fDisconnectGap = (EditText) findViewById(R.id.edit_disconnect_gap);
        fDisconnectGap.setText("500");
        fconnectGap = (EditText) findViewById(R.id.edit_connect_gap);
        fconnectGap.setText("1000");

        fRunning = false;        
    }

    @Override
    public void onClick(View v)
    {
        switch ( v.getId() )
        {
            case R.id.btn_start_test:
                start();
                break;
            case R.id.btn_stop_test:
                stop();
                break;
            default:
                break;
        }       
    }

    private synchronized void start()
    {
        if ( fRunning == false )
        {
            fRunning = true;            


            fMac = fInputMac.getText().toString().toUpperCase();
            fConnectRunnable = new ConnectRunnable();           
            fBeginView.setText(new Date().toLocaleString());

            fConnectTimes = 0;
            fRunOkTimes = 0;
            new Thread(fConnectRunnable).start();
        }
    }

    private synchronized void stop()
    {
        if ( fRunning == true )
        {
            fRunning = false;

            fConnectRunnable.cancel();
            try
            {
                Thread.sleep(500);
            }
            catch (InterruptedException exception)
            {
                exception.printStackTrace();
            }


            fEndView.setText(new Date().toLocaleString());
        }
    }   

    private void connect()
    {
        Log.d(TAG,"---------- run "+fConnectTimes++ +" times");
        String UUID_STRING = "00001101-0000-1000-8000-00805F9B34FB";
        // may throws exception
        UUID uuid = UUID.fromString(UUID_STRING);

        // get adapter
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();        

        // get remote device
        BluetoothDevice btDevice = adapter.getRemoteDevice(fMac);
        if ( btDevice == null )
        {
            Log.e(TAG,"can't get remote device from given MAC : " + fMac);
            return;
        }
        int runResult = 0;
        // may throws exception
        fBtSocket = null;
        try
        {
            fBtSocket = btDevice.createRfcommSocketToServiceRecord(uuid);
            if ( adapter.isDiscovering() == true ) 
            {
                adapter.cancelDiscovery();
                Log.d(TAG,"cancel discover");
            }

            fBtSocket.connect();
            runResult = 1;
            Log.d(TAG,"connect socket OK");
            Log.d(TAG,"---------- run OK "+fRunOkTimes++ +" times");
        }
        catch (IOException exception)
        {       
            //adapter.cancelDiscovery();
            Log.d(TAG,"connect socket error",exception);
            if ( fBtSocket != null )
            {
                try
                {
                    fBtSocket.close();
                }
                catch (IOException exception1)
                {
                    Log.d(TAG,"close socket error",exception1);
                }
            }
            else
            {
                Log.d(TAG,"create socket NULL");
            }

            btDevice = null;
            //update ui
            Message msgRun = new Message();
            msgRun.what = R.id.show_status;
            msgRun.arg1 = SV_START_RUN;
            msgRun.arg2 = runResult;
            fMessHandler.sendMessage(msgRun);
        }

        //Note: You should always ensure that the device is not performing device discovery when you call connect(). 
        //If discovery is in progress, then the connection attempt will be significantly slowed and is more likely to fail.
        //adapter.cancelDiscovery();
    }
    private void close()
    {
        //update ui
        Message msgShut = new Message();
        msgShut.what = R.id.show_status;
        msgShut.arg1 = SV_SHUT_DOWN;
        fMessHandler.sendMessage(msgShut);

        if ( fBtSocket != null )
        {
            Log.d(TAG,"close socket");
            try
            {
                fBtSocket.close();
            }
            catch (IOException exception1)
            {
                Log.d(TAG,"close socket error",exception1);
            }
            fBtSocket = null;
        }
    }   
    private Handler fMessHandler = new Handler()
    {
        public void handleMessage(android.os.Message msg)
        {
            switch ( msg.what )
            {
                case R.id.show_status:
                    if ( msg.arg1 == SV_START_RUN )
                    {
                        if ( msg.arg2 == 1)
                            fShowView.setText("run OK");
                        else 
                            fShowView.setText("run Failed");

                        fShowRunTimesView.setText("run "+fConnectTimes+", OK "+fRunOkTimes);
                    }
                    else if ( msg.arg1 == SV_SHUT_DOWN )
                        fShowView.setText("shut down ...");

                    break;

                default:
                    break;
            }
        };
    };

    private long fConnectTimes;
    private long fRunOkTimes;
    private static final String TAG = "..MhubTestBtConnect";
    private BluetoothSocket fBtSocket;

    private ConnectRunnable fConnectRunnable;
    private String fMac;
    private boolean fRunning;

    private TextView fBeginView;
    private TextView fEndView;
    private TextView fShowView;
    private TextView fShowRunTimesView;
    private EditText fInputMac;
    private EditText fDisconnectGap;
    private EditText fconnectGap;

    private static final int SV_START_RUN = 1;
    private static final int SV_SHUT_DOWN = 2;

    private class ConnectRunnable implements Runnable
    {
        public ConnectRunnable()
        {           
            fCancelled = false;
        }
        @Override
        public void run()
        {           
            if (Looper.myLooper() == null) {
                Looper.prepare();
            }

            long afterConnectSleep = 500;
            long afterCloseSleep = 1000;
            try
            {
                afterCloseSleep = Integer.parseInt(fconnectGap.getText().toString());
                afterConnectSleep = Integer.parseInt(fDisconnectGap.getText().toString());
            }
            catch(Exception exception)
            {
                afterConnectSleep = 500;
                afterCloseSleep = 1000;
            }
            while ( fCancelled == false )
            {               
                connect();
                try
                {
                    Thread.sleep(afterConnectSleep);
                }
                catch (InterruptedException exception)
                {
                    exception.printStackTrace();
                }

                close();
                try
                {
                    Thread.sleep(afterCloseSleep);
                }
                catch (InterruptedException exception)
                {
                    exception.printStackTrace();
                }
            }
        }

        public void cancel()
        {
            fCancelled = true;
        }
        private boolean fCancelled;

    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

荆棘i 2024-11-23 00:24:33

这是我不久前报告的一个错误,涉及蓝牙连接失败(确切地说是 512)和内存泄漏导致“引用表溢出。当我回到我的电脑时,我会挖掘链接=)

链接:http://code.google.com/p/android/issues/detail?id =8676

解决方案:首先执行蓝牙发现以查看设备是否在范围内,以避免蓝牙连接失败。如果是,则取消发现并连接到它。

This is a bug I reported a while back regarding failed bluetooth connects (512 to be exact) and a memory leak leading to "referencetable overflow. I'll dig up the link when I'm back at my PC =)

Link: http://code.google.com/p/android/issues/detail?id=8676

Solution: avoid failed bluetooth connects by performing a Bluetooth discovery first to see if the device is in range. If so, cancel discovery and connect to it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文