以下是开发中的几个关键步骤:
1,首先开启蓝牙
2,搜索可用设备
3,创建蓝牙socket,获取输入输出流
4,读取和写入数据
5,断开连接关闭蓝牙
下面是一个demo
效果图:
SearchDeviceActivity.java
- package com.hello.project;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Set;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.bluetooth.BluetoothAdapter;
- import android.bluetooth.BluetoothDevice;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.ArrayAdapter;
- import android.widget.Button;
- import android.widget.ListView;
- public class SearchDeviceActivity extends Activity implements OnItemClickListener{
- private BluetoothAdapter blueadapter=null;
- private DeviceReceiver mydevice=new DeviceReceiver();
- private List<String> deviceList=new ArrayList<String>();
- private ListView deviceListview;
- private Button btserch;
- private ArrayAdapter<String> adapter;
- private boolean hasregister=false;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.finddevice);
- setView();
- setBluetooth();
- }
- private void setView(){
- deviceListview=(ListView)findViewById(R.id.devicelist);
- adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, deviceList);
- deviceListview.setAdapter(adapter);
- deviceListview.setOnItemClickListener(this);
- btserch=(Button)findViewById(R.id.start_seach);
- btserch.setOnClickListener(new ClinckMonitor());
- }
- @Override
- protected void onStart() {
- //注册蓝牙接收广播
- if(!hasregister){
- hasregister=true;
- IntentFilter filterStart=new IntentFilter(BluetoothDevice.ACTION_FOUND);
- IntentFilter filterEnd=new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- registerReceiver(mydevice, filterStart);
- registerReceiver(mydevice, filterEnd);
- }
- super.onStart();
- }
- @Override
- protected void onDestroy() {
- if(blueadapter!=null&&blueadapter.isDiscovering()){
- blueadapter.cancelDiscovery();
- }
- if(hasregister){
- hasregister=false;
- unregisterReceiver(mydevice);
- }
- super.onDestroy();
- }
- /**
- * Setting Up Bluetooth
- */
- private void setBluetooth(){
- blueadapter=BluetoothAdapter.getDefaultAdapter();
- if(blueadapter!=null){ //Device support Bluetooth
- //确认开启蓝牙
- if(!blueadapter.isEnabled()){
- //请求用户开启
- Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- startActivityForResult(intent, RESULT_FIRST_USER);
- //使蓝牙设备可见,方便配对
- Intent in=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
- in.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 200);
- startActivity(in);
- //直接开启,不经过提示
- blueadapter.enable();
- }
- }
- else{ //Device does not support Bluetooth
- AlertDialog.Builder dialog = new AlertDialog.Builder(this);
- dialog.setTitle("No bluetooth devices");
- dialog.setMessage("Your equipment does not support bluetooth, please change device");
- dialog.setNegativeButton("cancel",
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- }
- });
- dialog.show();
- }
- }
- /**
- * Finding Devices
- */
- private void findAvalibleDevice(){
- //获取可配对蓝牙设备
- Set<BluetoothDevice> device=blueadapter.getBondedDevices();
- if(blueadapter!=null&&blueadapter.isDiscovering()){
- deviceList.clear();
- adapter.notifyDataSetChanged();
- }
- if(device.size()>0){ //存在已经配对过的蓝牙设备
- for(Iterator<BluetoothDevice> it=device.iterator();it.hasNext();){
- BluetoothDevice btd=it.next();
- deviceList.add(btd.getName()+'\n'+btd.getAddress());
- adapter.notifyDataSetChanged();
- }
- }else{ //不存在已经配对过的蓝牙设备
- deviceList.add("No can be matched to use bluetooth");
- adapter.notifyDataSetChanged();
- }
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch(resultCode){
- case RESULT_OK:
- findAvalibleDevice();
- break;
- case RESULT_CANCELED:
- break;
- }
- super.onActivityResult(requestCode, resultCode, data);
- }
- private class ClinckMonitor implements OnClickListener{
- @Override
- public void onClick(View v) {
- if(blueadapter.isDiscovering()){
- blueadapter.cancelDiscovery();
- btserch.setText("repeat search");
- }else{
- findAvalibleDevice();
- blueadapter.startDiscovery();
- btserch.setText("stop search");
- }
- }
- }
- /**
- * 蓝牙搜索状态广播监听
- * @author Andy
- *
- */
- private class DeviceReceiver extends BroadcastReceiver{
- @Override
- public void onReceive(Context context, Intent intent) {
- String action =intent.getAction();
- if(BluetoothDevice.ACTION_FOUND.equals(action)){ //搜索到新设备
- BluetoothDevice btd=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- //搜索没有配过对的蓝牙设备
- if (btd.getBondState() != BluetoothDevice.BOND_BONDED) {
- deviceList.add(btd.getName()+'\n'+btd.getAddress());
- adapter.notifyDataSetChanged();
- }
- }
- else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){ //搜索结束
- if (deviceListview.getCount() == 0) {
- deviceList.add("No can be matched to use bluetooth");
- adapter.notifyDataSetChanged();
- }
- btserch.setText("repeat search");
- }
- }
- }
- @Override
- public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
- Log.e("msgParent", "Parent= "+arg0);
- Log.e("msgView", "View= "+arg1);
- Log.e("msgChildView", "ChildView= "+arg0.getChildAt(pos-arg0.getFirstVisiblePosition()));
- final String msg = deviceList.get(pos);
- if(blueadapter!=null&&blueadapter.isDiscovering()){
- blueadapter.cancelDiscovery();
- btserch.setText("repeat search");
- }
- AlertDialog.Builder dialog = new AlertDialog.Builder(this);// 定义一个弹出框对象
- dialog.setTitle("Confirmed connecting device");
- dialog.setMessage(msg);
- dialog.setPositiveButton("connect",
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- BluetoothMsg.BlueToothAddress=msg.substring(msg.length()-17);
- if(BluetoothMsg.lastblueToothAddress!=BluetoothMsg.BlueToothAddress){
- BluetoothMsg.lastblueToothAddress=BluetoothMsg.BlueToothAddress;
- }
- Intent in=new Intent(SearchDeviceActivity.this,BluetoothActivity.class);
- startActivity(in);
- }
- });
- dialog.setNegativeButton("cancel",
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- BluetoothMsg.BlueToothAddress = null;
- }
- });
- dialog.show();
- }
- }
BluetoothMsg.java
- package com.hello.project;
- public class BluetoothMsg {
- /**
- * 蓝牙连接类型
- * @author Andy
- *
- */
- public enum ServerOrCilent{
- NONE,
- SERVICE,
- CILENT
- };
- //蓝牙连接方式
- public static ServerOrCilent serviceOrCilent = ServerOrCilent.NONE;
- //连接蓝牙地址
- public static String BlueToothAddress = null,lastblueToothAddress=null;
- //通信线程是否开启
- public static boolean isOpen = false;
- }
finddevice.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id = "@+id/devices"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom = "true"
- android:id= "@+id/bt_bottombar">
- <Button android:id="@+id/start_seach"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@+id/start_service"
- android:text="Began to search"/>
- </RelativeLayout>
- <ListView
- android:id="@+id/devicelist"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:scrollingCache="false"
- android:divider="#ffc6c6c6"
- android:layout_weight="1.0"
- android:layout_above = "@id/bt_bottombar"
- android:layout_below="@id/devices"
- />
- </RelativeLayout>
BluetoothActivity.java
- package com.hello.project;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.UUID;
- import android.app.Activity;
- import android.bluetooth.BluetoothAdapter;
- import android.bluetooth.BluetoothDevice;
- import android.bluetooth.BluetoothServerSocket;
- import android.bluetooth.BluetoothSocket;
- import android.content.Context;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.inputmethod.InputMethodManager;
- import android.widget.AdapterView;
- import android.widget.ArrayAdapter;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ListView;
- import android.widget.Toast;
- import android.widget.AdapterView.OnItemClickListener;
- public class BluetoothActivity extends Activity{
- /* 一些常量,代表服务器的名称 */
- public static final String PROTOCOL_SCHEME_RFCOMM = "btspp";
- private ListView mListView;
- private Button sendButton;
- private Button disconnectButton;
- private EditText editMsgView;
- private ArrayAdapter<String> mAdapter;
- private List<String> msgList=new ArrayList<String>();
- Context mContext;
- private BluetoothServerSocket mserverSocket = null;
- private ServerThread startServerThread = null;
- private clientThread clientConnectThread = null;
- private BluetoothSocket socket = null;
- private BluetoothDevice device = null;
- private readThread mreadThread = null;;
- private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.chat);
- mContext = this;
- init();
- }
- private void init() {
- mAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, msgList);
- mListView = (ListView) findViewById(R.id.list);
- mListView.setAdapter(mAdapter);
- mListView.setFastScrollEnabled(true);
- editMsgView= (EditText)findViewById(R.id.MessageText);
- editMsgView.clearFocus();
- sendButton= (Button)findViewById(R.id.btn_msg_send);
- sendButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- String msgText =editMsgView.getText().toString();
- if (msgText.length()>0) {
- sendMessageHandle(msgText);
- editMsgView.setText("");
- editMsgView.clearFocus();
- //close InputMethodManager
- InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(editMsgView.getWindowToken(), 0);
- }else
- Toast.makeText(mContext, "发送内容不能为空!", Toast.LENGTH_SHORT).show();
- }
- });
- disconnectButton= (Button)findViewById(R.id.btn_disconnect);
- disconnectButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- // TODO Auto-generated method stub
- if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.CILENT)
- {
- shutdownClient();
- }
- else if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.SERVICE)
- {
- shutdownServer();
- }
- BluetoothMsg.isOpen = false;
- BluetoothMsg.serviceOrCilent=BluetoothMsg.ServerOrCilent.NONE;
- Toast.makeText(mContext, "已断开连接!", Toast.LENGTH_SHORT).show();
- }
- });
- }
- private Handler LinkDetectedHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- //Toast.makeText(mContext, (String)msg.obj, Toast.LENGTH_SHORT).show();
- if(msg.what==1)
- {
- msgList.add((String)msg.obj);
- }
- else
- {
- msgList.add((String)msg.obj);
- }
- mAdapter.notifyDataSetChanged();
- mListView.setSelection(msgList.size() - 1);
- }
- };
- @Override
- protected void onResume() {
- BluetoothMsg.serviceOrCilent=BluetoothMsg.ServerOrCilent.CILENT;
- if(BluetoothMsg.isOpen)
- {
- Toast.makeText(mContext, "连接已经打开,可以通信。如果要再建立连接,请先断开!", Toast.LENGTH_SHORT).show();
- return;
- }
- if(BluetoothMsg.serviceOrCilent==BluetoothMsg.ServerOrCilent.CILENT)
- {
- String address = BluetoothMsg.BlueToothAddress;
- if(!address.equals("null"))
- {
- device = mBluetoothAdapter.getRemoteDevice(address);
- clientConnectThread = new clientThread();
- clientConnectThread.start();
- BluetoothMsg.isOpen = true;
- }
- else
- {
- Toast.makeText(mContext, "address is null !", Toast.LENGTH_SHORT).show();
- }
- }
- else if(BluetoothMsg.serviceOrCilent==BluetoothMsg.ServerOrCilent.SERVICE)
- {
- startServerThread = new ServerThread();
- startServerThread.start();
- BluetoothMsg.isOpen = true;
- }
- super.onResume();
- }
- //开启客户端
- private class clientThread extends Thread {
- @Override
- public void run() {
- try {
- //创建一个Socket连接:只需要服务器在注册时的UUID号
- // socket = device.createRfcommSocketToServiceRecord(BluetoothProtocols.OBEX_OBJECT_PUSH_PROTOCOL_UUID);
- socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
- //连接
- Message msg2 = new Message();
- msg2.obj = "请稍候,正在连接服务器:"+BluetoothMsg.BlueToothAddress;
- msg2.what = 0;
- LinkDetectedHandler.sendMessage(msg2);
- socket.connect();
- Message msg = new Message();
- msg.obj = "已经连接上服务端!可以发送信息。";
- msg.what = 0;
- LinkDetectedHandler.sendMessage(msg);
- //启动接受数据
- mreadThread = new readThread();
- mreadThread.start();
- }
- catch (IOException e)
- {
- Log.e("connect", "", e);
- Message msg = new Message();
- msg.obj = "连接服务端异常!断开连接重新试一试。";
- msg.what = 0;
- LinkDetectedHandler.sendMessage(msg);
- }
- }
- };
- //开启服务器
- private class ServerThread extends Thread {
- @Override
- public void run() {
- try {
- /* 创建一个蓝牙服务器
- * 参数分别:服务器名称、UUID */
- mserverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM,
- UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
- Log.d("server", "wait cilent connect...");
- Message msg = new Message();
- msg.obj = "请稍候,正在等待客户端的连接...";
- msg.what = 0;
- LinkDetectedHandler.sendMessage(msg);
- /* 接受客户端的连接请求 */
- socket = mserverSocket.accept();
- Log.d("server", "accept success !");
- Message msg2 = new Message();
- String info = "客户端已经连接上!可以发送信息。";
- msg2.obj = info;
- msg.what = 0;
- LinkDetectedHandler.sendMessage(msg2);
- //启动接受数据
- mreadThread = new readThread();
- mreadThread.start();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- };
- /* 停止服务器 */
- private void shutdownServer() {
- new Thread() {
- @Override
- public void run() {
- if(startServerThread != null)
- {
- startServerThread.interrupt();
- startServerThread = null;
- }
- if(mreadThread != null)
- {
- mreadThread.interrupt();
- mreadThread = null;
- }
- try {
- if(socket != null)
- {
- socket.close();
- socket = null;
- }
- if (mserverSocket != null)
- {
- mserverSocket.close();/* 关闭服务器 */
- mserverSocket = null;
- }
- } catch (IOException e) {
- Log.e("server", "mserverSocket.close()", e);
- }
- };
- }.start();
- }
- /* 停止客户端连接 */
- private void shutdownClient() {
- new Thread() {
- @Override
- public void run() {
- if(clientConnectThread!=null)
- {
- clientConnectThread.interrupt();
- clientConnectThread= null;
- }
- if(mreadThread != null)
- {
- mreadThread.interrupt();
- mreadThread = null;
- }
- if (socket != null) {
- try {
- socket.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- socket = null;
- }
- };
- }.start();
- }
- //发送数据
- private void sendMessageHandle(String msg)
- {
- if (socket == null)
- {
- Toast.makeText(mContext, "没有连接", Toast.LENGTH_SHORT).show();
- return;
- }
- try {
- OutputStream os = socket.getOutputStream();
- os.write(msg.getBytes());
- } catch (IOException e) {
- e.printStackTrace();
- }
- msgList.add(msg);
- mAdapter.notifyDataSetChanged();
- mListView.setSelection(msgList.size() - 1);
- }
- //读取数据
- private class readThread extends Thread {
- @Override
- public void run() {
- byte[] buffer = new byte[1024];
- int bytes;
- InputStream mmInStream = null;
- try {
- mmInStream = socket.getInputStream();
- } catch (IOException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- while (true) {
- try {
- // Read from the InputStream
- if( (bytes = mmInStream.read(buffer)) > 0 )
- {
- byte[] buf_data = new byte[bytes];
- for(int i=0; i<bytes; i++)
- {
- buf_data[i] = buffer[i];
- }
- String s = new String(buf_data);
- Message msg = new Message();
- msg.obj = s;
- msg.what = 1;
- LinkDetectedHandler.sendMessage(msg);
- }
- } catch (IOException e) {
- try {
- mmInStream.close();
- } catch (IOException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- break;
- }
- }
- }
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.CILENT)
- {
- shutdownClient();
- }
- else if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.SERVICE)
- {
- shutdownServer();
- }
- BluetoothMsg.isOpen = false;
- BluetoothMsg.serviceOrCilent = BluetoothMsg.ServerOrCilent.NONE;
- }
- }
chat.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id = "@+id/container"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:id= "@+id/edit_bottombar"
- android:layout_alignParentBottom = "true">
- <Button android:id="@+id/btn_disconnect"
- android:layout_width="65dp"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft ="true"
- android:text="断开"/>
- <Button android:id="@+id/btn_msg_send"
- android:layout_width="65dp"
- android:layout_height="wrap_content"
- android:layout_alignParentRight ="true"
- android:text="发送"/>
- <EditText
- android:layout_width="fill_parent"
- android:layout_height = "wrap_content"
- android:layout_toLeftOf="@id/btn_msg_send"
- android:layout_toRightOf="@+id/btn_disconnect"
- android:hint = "说点什么呢?"
- android:textSize="15dip"
- android:id = "@+id/MessageText"/>
- </RelativeLayout>
- <ListView
- android:id="@+id/list"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:scrollingCache="false"
- android:divider="#ffc6c6c6"
- android:layout_weight="1.0"
- android:layout_above = "@id/edit_bottombar"
- android:layout_below="@id/container"
- />
- </RelativeLayout>
最后别忘了加入权限
- <uses-permission android:name="android.permission.BLUETOOTH"/>
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
- <uses-permission android:name="android.permission.READ_CONTACTS"/>
扩展:蓝牙后台配对实现(网上看到的整理如下)
- static public boolean createBond(Class btClass, BluetoothDevice btDevice)
- throws Exception {
- Method createBondMethod = btClass.getMethod("createBond");
- Log.i("life", "createBondMethod = " + createBondMethod.getName());
- Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
- return returnValue.booleanValue();
- }
- static public boolean setPin(Class btClass, BluetoothDevice btDevice,
- String str) throws Exception {
- Boolean returnValue = null;
- try {
- Method removeBondMethod = btClass.getDeclaredMethod("setPin",
- new Class[] { byte[].class });
- returnValue = (Boolean) removeBondMethod.invoke(btDevice,
- new Object[] { str.getBytes() });
- Log.i("life", "returnValue = " + returnValue);
- } catch (SecurityException e) {
- // throw new RuntimeException(e.getMessage());
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- // throw new RuntimeException(e.getMessage());
- e.printStackTrace();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return returnValue;
- }
- // 取消用户输入
- static public boolean cancelPairingUserInput(Class btClass,
- BluetoothDevice device) throws Exception {
- Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
- // cancelBondProcess()
- Boolean returnValue = (Boolean) createBondMethod.invoke(device);
- Log.i("life", "cancelPairingUserInputreturnValue = " + returnValue);
- return returnValue.booleanValue();
- }
然后监听蓝牙配对的广播 匹配“android.bluetooth.device.action.PAIRING_REQUEST”这个action
然后调用上面的setPin(mDevice.getClass(), mDevice, "1234"); // 手机和蓝牙采集器配对
createBond(mDevice.getClass(), mDevice);
cancelPairingUserInput(mDevice.getClass(), mDevice);
mDevice是你要去连接的那个蓝牙的对象 , 1234为配对的pin码