如何保持蓝牙连接后台?
Posted
技术标签:
【中文标题】如何保持蓝牙连接后台?【英文标题】:How to keep Bluetooth connection background? 【发布时间】:2018-09-18 15:30:13 【问题描述】:我在 android 应用中创建了一个蓝牙 Activity 类,它适用于所有蓝牙功能,例如:扫描、配对、连接、发送和接收数据。
真正的问题是 Activity 何时被销毁。蓝牙正在断开连接。
如何在整个应用程序中建立蓝牙连接。我想从其他活动向蓝牙发送数据。
帮我以简单的方式实现这个?
public class BTActivity extends AppCompatActivity
ArrayList<BluetoothDevice> devices = new ArrayList<>();
BluetoothAdapter mBluetoothAdapter;
BluetoothDevice mBluetoothDevice;
ArrayAdapter<BluetoothDevice> arrayAdapter;
ConnectThread c;
private static final String TAG = "MY_BT";
ListView lvPaired;
Button BluetoothOnOff, ScanBt, pairedlist, sendButton, btDisconnect, incrementBtn, decrementBtn;
EditText input_text;
TextView ConnectedTo;
FragmentManager fm = getSupportFragmentManager();
UUID BHANU_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bt);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
lvPaired = findViewById(R.id.btPairedLV);
pairedlist = findViewById(R.id.btPaired);
input_text = findViewById(R.id.user_input);
sendButton = findViewById(R.id.btnSend);
BluetoothOnOff = findViewById(R.id.offOn_bt);
ScanBt = findViewById(R.id.scan_bt);
ConnectedTo = findViewById(R.id.current_connected_bluetooth);
btDisconnect = findViewById(R.id.bt_disconnect);
incrementBtn = findViewById(R.id.incrementBtn);
decrementBtn = findViewById(R.id.decrementBtn);
onClickListener();
pairedList();
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(mReceiver, filter);
public void onClickListener()
pairedlist.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
if (arrayAdapter != null)
arrayAdapter.clear();
pairedList();
);
lvPaired.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
BluetoothDevice device = (BluetoothDevice) parent.getItemAtPosition(position);
c = new ConnectThread(device, true);
c.start();
);
sendButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
String text = input_text.getText().toString();
c.sendData(text);
input_text.setText("");
);
BluetoothOnOff.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
if (!mBluetoothAdapter.isEnabled())
mBluetoothAdapter.enable();
BluetoothOnOff.setText("ON");
else
mBluetoothAdapter.disable();
BluetoothOnOff.setText("OFF");
);
ScanBt.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
ScanFragment scanFragment = new ScanFragment();
scanFragment.show(fm,"ScanBT");
//ScanFragment scanFragment = new ScanFragment();
//scanFragment.show(fm,"Scan Fragment");
);
btDisconnect.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
c.cancel();
);
incrementBtn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
c.sendData("a");
);
decrementBtn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
c.sendData("b");
);
public void toast(String message)
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
@Override
protected void onDestroy()
unregisterReceiver(mReceiver);
super.onDestroy();
public void pairedList()
//arrayAdapter.clear();
devices.addAll(mBluetoothAdapter.getBondedDevices());
arrayAdapter = new ArrayAdapter<BluetoothDevice>(this, android.R.layout.simple_list_item_1,android.R.id.text1, devices);
lvPaired.setAdapter(arrayAdapter);
arrayAdapter.notifyDataSetChanged();
BroadcastReceiver mReceiver = new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action))
toast("connected");
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
ConnectedTo.setText(device.getName());
btDisconnect.setVisibility(View.VISIBLE);
//getActionBar().setSubtitle(device.getName());
Log.d("BT", "connected to");
else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action))
toast("disconnected");
ConnectedTo.setText("None");
btDisconnect.setVisibility(View.INVISIBLE);
// getActionBar().setSubtitle("");
Log.d("BT", "disconnected");
;
public class ConnectThread extends Thread
BluetoothDevice cDevice;
BluetoothSocket socket;
ConnectedThread ct;
ConnectThread(BluetoothDevice device, boolean insecureConnection)
cDevice = device;
try
if (insecureConnection)
socket = device.createInsecureRfcommSocketToServiceRecord(BHANU_UUID);
else
socket = device.createRfcommSocketToServiceRecord(BHANU_UUID);
catch (IOException e)
e.getMessage();
public void run()
mBluetoothAdapter.cancelDiscovery();
try
Log.d("BT", "Socket ready to connect");
socket.connect();
Log.d("BT", "Socket connected");
// out = socket.getOutputStream();
// input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
catch (final IOException e)
e.getMessage();
ct = new ConnectedThread(socket);
//ct.write("Q-smart".getBytes());
/*try
socket.close();
catch (final IOException closeException)
closeException.getMessage();
*/
private void sendData(String message)
Log.d(TAG,message);
if (socket != null)
ct.write(message.getBytes());
else
toast("Please connect to bluetooth first");
public void cancel()
try
socket.close();
catch (IOException e)
e.printStackTrace();
private class ConnectedThread extends Thread
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte[] mmBuffer; // mmBuffer store for the stream
public ConnectedThread(BluetoothSocket socket)
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams; using temp objects because
// member streams are final.
try
tmpIn = socket.getInputStream();
catch (IOException e)
Log.e(TAG, "Error occurred when creating input stream", e);
try
tmpOut = socket.getOutputStream();
catch (IOException e)
Log.e(TAG, "Error occurred when creating output stream", e);
mmInStream = tmpIn;
mmOutStream = tmpOut;
public void run()
mmBuffer = new byte[1024];
int numBytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs.
while (true)
try
// Read from the InputStream.
numBytes = mmInStream.read(mmBuffer);
// Send the obtained bytes to the UI activity.
/* Message readMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_READ, numBytes, -1,
mmBuffer);
readMsg.sendToTarget();*/
catch (IOException e)
Log.d(TAG, "Input stream was disconnected", e);
break;
// Call this from the main activity to send data to the remote device.
public void write(byte[] bytes)
try
mmOutStream.write(bytes);
// Share the sent message with the UI activity.
/* Message writtenMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
writtenMsg.sendToTarget();*/
catch (IOException e)
Log.e(TAG, "Error occurred when sending data", e);
// Send a failure message back to the activity.
/* Message writeErrorMsg =
mHandler.obtainMessage(MessageConstants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString("toast",
"Couldn't send data to the other device");
writeErrorMsg.setData(bundle);
mHandler.sendMessage(writeErrorMsg);*/
【问题讨论】:
【参考方案1】:是的,我找到了在 Android 中运行蓝牙背景的可行解决方案。 下面是我在我的 android 应用中使用的代码。
public class BluetoothServices extends Service
private BluetoothAdapter mBluetoothAdapter;
public static final String B_DEVICE = "MY DEVICE";
public static final String B_UUID = "00001101-0000-1000-8000-00805f9b34fb";
// 00000000-0000-1000-8000-00805f9b34fb
public static final int STATE_NONE = 0;
public static final int STATE_LISTEN = 1;
public static final int STATE_CONNECTING = 2;
public static final int STATE_CONNECTED = 3;
private ConnectBtThread mConnectThread;
private static ConnectedBtThread mConnectedThread;
private static Handler mHandler = null;
public static int mState = STATE_NONE;
public static String deviceName;
public static BluetoothDevice sDevice = null;
public Vector<Byte> packData = new Vector<>(2048);
//IBinder mIBinder = new LocalBinder();
@Nullable
@Override
public IBinder onBind(Intent intent)
//mHandler = getApplication().getHandler();
return mBinder;
public void toast(String mess)
Toast.makeText(this,mess,Toast.LENGTH_SHORT).show();
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder
BluetoothServices getService()
// Return this instance of LocalService so clients can call public methods
return BluetoothServices.this;
@Override
public int onStartCommand(Intent intent, int flags, int startId)
String deviceg = intent.getStringExtra("bluetooth_device");
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
connectToDevice(deviceg);
return START_STICKY;
private synchronized void connectToDevice(String macAddress)
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
if (mState == STATE_CONNECTING)
if (mConnectThread != null)
mConnectThread.cancel();
mConnectThread = null;
if (mConnectedThread != null)
mConnectedThread.cancel();
mConnectedThread = null;
mConnectThread = new ConnectBtThread(device);
toast("connecting");
mConnectThread.start();
setState(STATE_CONNECTING);
private void setState(int state)
mState = state;
if (mHandler != null)
// mHandler.obtainMessage();
public synchronized void stop()
setState(STATE_NONE);
if (mConnectThread != null)
mConnectThread.cancel();
mConnectThread = null;
if (mConnectedThread != null)
mConnectedThread.cancel();
mConnectedThread = null;
if (mBluetoothAdapter != null)
mBluetoothAdapter.cancelDiscovery();
stopSelf();
public void sendData(String message)
if (mConnectedThread!= null)
mConnectedThread.write(message.getBytes());
toast("sent data");
else
Toast.makeText(BluetoothServices.this,"Failed to send data",Toast.LENGTH_SHORT).show();
@Override
public boolean stopService(Intent name)
setState(STATE_NONE);
if (mConnectThread != null)
mConnectThread.cancel();
mConnectThread = null;
if (mConnectedThread != null)
mConnectedThread.cancel();
mConnectedThread = null;
mBluetoothAdapter.cancelDiscovery();
return super.stopService(name);
/*private synchronized void connected(BluetoothSocket mmSocket)
if (mConnectThread != null)
mConnectThread.cancel();
mConnectThread = null;
if (mConnectedThread != null)
mConnectedThread.cancel();
mConnectedThread = null;
mConnectedThread = new ConnectedBtThread(mmSocket);
mConnectedThread.start();
setState(STATE_CONNECTED);
*/
private class ConnectBtThread extends Thread
private final BluetoothSocket mSocket;
private final BluetoothDevice mDevice;
public ConnectBtThread(BluetoothDevice device)
mDevice = device;
BluetoothSocket socket = null;
try
socket = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString(B_UUID));
catch (IOException e)
e.printStackTrace();
mSocket = socket;
@Override
public void run()
mBluetoothAdapter.cancelDiscovery();
try
mSocket.connect();
Log.d("service","connect thread run method (connected)");
SharedPreferences pre = getSharedPreferences("BT_NAME",0);
pre.edit().putString("bluetooth_connected",mDevice.getName()).apply();
catch (IOException e)
try
mSocket.close();
Log.d("service","connect thread run method ( close function)");
catch (IOException e1)
e1.printStackTrace();
e.printStackTrace();
//connected(mSocket);
mConnectedThread = new ConnectedBtThread(mSocket);
mConnectedThread.start();
public void cancel()
try
mSocket.close();
Log.d("service","connect thread cancel method");
catch (IOException e)
e.printStackTrace();
private class ConnectedBtThread extends Thread
private final BluetoothSocket cSocket;
private final InputStream inS;
private final OutputStream outS;
private byte[] buffer;
public ConnectedBtThread(BluetoothSocket socket)
cSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try
tmpIn = socket.getInputStream();
catch (IOException e)
e.printStackTrace();
try
tmpOut = socket.getOutputStream();
catch (IOException e)
e.printStackTrace();
inS = tmpIn;
outS = tmpOut;
@Override
public void run()
buffer = new byte[1024];
int mByte;
try
mByte= inS.read(buffer);
catch (IOException e)
e.printStackTrace();
Log.d("service","connected thread run method");
public void write(byte[] buff)
try
outS.write(buff);
catch (IOException e)
e.printStackTrace();
private void cancel()
try
cSocket.close();
Log.d("service","connected thread cancel method");
catch (IOException e)
e.printStackTrace();
@Override
public void onDestroy()
this.stop();
super.onDestroy();
【讨论】:
Android 不会在一段时间(10 小时左右)后终止您的服务?我有这个问题,谢谢。 你如何从我的活动中访问它? 使用 Ibinder。使用服务连接将此服务连接到您的活动以上是关于如何保持蓝牙连接后台?的主要内容,如果未能解决你的问题,请参考以下文章
当应用程序未运行(终止/终止)时,如何保持核心位置和核心蓝牙运行?