多个蓝牙套接字连接/关闭操作重新启动 Android 手机
我们使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是我不久前报告的一个错误,涉及蓝牙连接失败(确切地说是 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.