真是应该值得庆祝一下,为了个毕设,本人真是呕心沥血啊!就在刚才,终于完成了蓝牙成功配对的工作,在此将全过程记录下来,以便日后查阅。
蓝牙通讯的全过程大多资料上都有介绍,无非就是先打开蓝牙、搜索设备、被设备搜索、进行配对,这里我就不在多说啦,将部分代码附上
现在Manifest.xml中添加两个权限:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
开启本地蓝牙设备:
蓝牙关闭:
上面两步相对来说简单,至于蓝牙搜索问题,我新建了一个activity窗口,用于显示搜索到的蓝牙设备,并在新窗口中实现选中配对过程,首先,说一下设备搜索,
由主窗口调用adapter.startDiscovery();//adapter为本地蓝牙适配器;再调用startActivityForResult (new Intent(MainActivity.this, Device.class), 1);
开启新创建的Device.class。startDiscovery();是异步完成的,每次搜索到一个设备,便会向系统发送一个广播通知,所以这里要新创建一个广播接收对象,用来
接收所发现的设备信息。代码如下
--------------------------------------------------------------------------------------
其中广播接收的信息被保存到str中,再转存到lst_Devices中。
对于搜索过程中,屏幕实时显示,用了一个list_view来实现的,具体如下:
ListView list_Devices; //用于显示搜索到的设备参数
List<String> lst_Devices = new ArrayList<String>();
final ArrayAdapter<String> adt_Devices;
list_Devices = (ListView) this.findViewById(R.id.listview);
adt_Devices = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, lst_Devices);
list_Devices.setAdapter(adt_Devices);
将list_view的数据源锁定到lst_Devices,至于adt_Devices我也不太清楚了,例子上面都是这么写的。
至于设备配对问题,看似简单,可总是抛出service discovery failed异常
后来在网上找到了解决办法,但是为什么这么做,我也不知道,代码如下:
至此蓝牙配对完成,下一步该是通讯了,有待研究,将代码附上,由于此项目尚未完成,所以部分代码还没有写完,此代码只实现了蓝牙搜索配对
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package android.app; import java.util.*; import android.app.Activity; import android.bluetooth.*; import android.content.*; //import android.net.Uri; import android.os.*; import android.view.View; import android.widget.*; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final TextView text = (TextView)this.findViewById(R.id.textview);//用一个textview来提示使用者 //获取本地蓝牙适配器 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if(adapter == null) text.setText("本机器没有蓝牙适配器"); else { if(adapter.isEnabled()) text.setText("蓝牙适配器已开启"); else text.setText("请开启蓝牙适配器"); //此按钮用于关闭电灯 Button button_Close = (Button)this.findViewById(R.id.button1); button_Close.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click } }); //此按钮用于打开电灯 Button button_Open = (Button)this.findViewById(R.id.button4); button_Open.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click } }); //此按钮用于调节灯光的亮度 Button button_Up = (Button)this.findViewById(R.id.button2); button_Up.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click } }); //此按钮用于调节灯光的暗度 Button button_Down = (Button)this.findViewById(R.id.button3); button_Down.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click } }); //此按钮仅负责打开蓝牙适配器 Button button_OpenBluetooth = (Button)this.findViewById(R.id.button5); button_OpenBluetooth.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(!adapter.isEnabled()) { //创建一个intent对象,调用系统信息提示用户打开蓝牙 Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); //启动系统调用开始启动蓝牙(打开的过程是异步完成的) startActivity(intent); } else { text.setText("蓝牙适配器已启动"); } } }); //此按钮仅负责关闭蓝牙适配器 Button button_CloseBluetooth = (Button)this.findViewById(R.id.button6); button_CloseBluetooth.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click if(adapter.isEnabled()) { //text.setText(adapter.getAddress()); adapter.disable(); text.setText("蓝牙适配器已关闭"); } } }); //此按钮负责在已建立的配对中,选择要进行通讯的设备,并建立通讯连接,尚未完成 Button button_Socket = (Button)this.findViewById(R.id.button7); button_Socket.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click if(adapter.isEnabled()) { Set<BluetoothDevice> devices = adapter.getBondedDevices(); if(devices.size() > 0) { //利用迭代,将与本机连接的蓝牙设备输出给bluetoothDevice,并且打印其MAX地址 for(Iterator iterator = devices.iterator(); iterator.hasNext();) { BluetoothDevice bluetoothDevice = (BluetoothDevice) iterator.next(); text.setText(bluetoothDevice.getName()); } } else text.setText("没有已配对的连接,请先配对!"); } else text.setText("请先开启蓝牙适配器!"); } }); //此按钮的最初想法是用于扫描周围设备,并进行配对,已完成搜索并提取地址,配对还未实现 Button button_Search = (Button)this.findViewById(R.id.button8); button_Search.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(adapter.isEnabled()) { if(!adapter.isDiscovering()) { // Perform action on click //开启本地蓝牙搜索功能 adapter.startDiscovery(); //开启Device窗口 //startActivity(new Intent(MainActivity.this, Device.class)); //启动一个新的窗口用于显示搜索到的设备,并且实现设备配对 //上面那个函数用于无参数无返回值的调用新class,下面这个调用时用于有返回值的调用 startActivityForResult (new Intent(MainActivity.this, Device.class), 1); } else adapter.cancelDiscovery(); } else text.setText("请先开启蓝牙适配器!"); } }); } } //重写此函数,android平台会自动调用此函数,用于处理新窗口返回的参数 protected void onActivityResult(int requestCode, int resultCode, Intent data) { String result = data.getExtras().getString("result");//得到新Activity 关闭后返回的数据 } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package android.app; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.UUID; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnCreateContextMenuListener; import android.webkit.URLUtil; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; public class Device extends Activity { String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB"; BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); BluetoothSocket btSocket; String con_Device = new String();//用于存储已配对的设备参数 ListView list_Devices; //用于显示搜索到的设备参数 List<String> lst_Devices = new ArrayList<String>(); int i = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.device); final TextView text_device = (TextView)this.findViewById(R.id.text_device); final ArrayAdapter<String> adt_Devices; list_Devices = (ListView) this.findViewById(R.id.listview); adt_Devices = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, lst_Devices); list_Devices.setAdapter(adt_Devices); //注册一个广播接收器,因为MainActivity启动蓝牙扫描的时候,会异步进行,没检查到一个设备就会发送一个广播,注册的广播接收器用于接收扫描是发出的信号 IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // When discovery finds a device if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // Add the name and address to an array adapter to show in a ListView String str= device.getName() + "|" +device.getAddress(); if (lst_Devices.indexOf(str) == -1)// 防止重复添加 lst_Devices.add(str); // 获取设备名称和mac地址 adt_Devices.notifyDataSetChanged(); System.out.println(device.getName()); } } }; registerReceiver(mReceiver,intentFilter); Button button_StopSearch = (Button)this.findViewById(R.id.button_1); button_StopSearch.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click if(!adapter.isDiscovering()) { // Perform action on click adapter.startDiscovery(); } else adapter.cancelDiscovery(); } }); Button button_Return = (Button)this.findViewById(R.id.button_2); button_Return.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click Intent intent = new Intent();//数据是使用Intent返回 intent.putExtra("result", con_Device);//把选择的数据存放在str_data中,供使用 Device.this.setResult(RESULT_OK, intent);//设置返回数据 Device.this.finish();//关闭Activity } }); list_Devices.setOnItemClickListener(new Connection_Build()); } //此类用于实现listview的OnItemClickListener,用于处理选中的设备进行配对,尚未完成 public class Connection_Build implements OnItemClickListener { UUID uuid; public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub adapter.cancelDiscovery(); System.out.println(lst_Devices.get(arg2)); String str = lst_Devices.get(arg2); String[] values = str.split("\\|"); String address=values[1]; System.out.println(address); //Log.e("address",values[1]); uuid = UUID.fromString(SPP_UUID); BluetoothDevice btDev = adapter.getRemoteDevice(address); BluetoothSocket tmp = null; // Get a BluetoothSocket to connect with the given BluetoothDevice try { // MY_UUID is the app's UUID string, also used by the server code Method m = btDev.getClass().getMethod("createRfcommSocket", new Class[] {int.class}); tmp = (BluetoothSocket) m.invoke(btDev, 1); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } btSocket = tmp; try { // Connect the device through the socket. This will block // until it succeeds or throws an exception btSocket.connect(); } catch (IOException e) { // Unable to connect; close the socket and get out try { btSocket.close(); System.out.println(" 1" + e); } catch (IOException closeException) { } } } } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <AbsoluteLayout 8 android:id="@+id/AbsoluteLayout1" 9 android:layout_width="match_parent" 10 android:layout_height="480dp" > 11 12 13 14 15 <ListView 16 android:id="@+id/listview" 17 android:layout_width="wrap_content" 18 android:layout_height="300dp" 19 android:layout_y="70dp" > 20 " 21 22 </ListView> 23 24 <Button 25 android:id="@+id/button_1" 26 android:layout_width="wrap_content" 27 android:layout_height="wrap_content" 28 android:layout_x="14dp" 29 android:layout_y="14dp" 30 android:text="停止搜索" /> 31 32 <Button 33 android:id="@+id/button_2" 34 android:layout_width="84dp" 35 android:layout_height="wrap_content" 36 android:layout_x="220dp" 37 android:layout_y="18dp" 38 android:text="返回" /> 39 40 <TextView 41 android:id="@+id/text_device" 42 android:layout_width="match_parent" 43 android:layout_height="107dp" 44 android:layout_y="372dp" 45 android:text="tiaoshi"> 46 47 </TextView>" 48 49 </AbsoluteLayout> 50 51 </LinearLayout>
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <?xml version="1.0" encoding="utf-8"?> 2 <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:id="@+id/AbsoluteLayout1" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:background="@drawable/myimg" > 7 8 <TextView 9 android:id="@+id/textview" 10 android:layout_width="289dp" 11 android:layout_height="72dp" 12 android:layout_x="12dp" 13 android:layout_y="18dp" 14 android:gravity="center" 15 android:text="提示信息" 16 android:textSize="20dp" 17 android:textColor="@color/red"/> 18 19 <Button 20 android:id="@+id/button3" 21 android:layout_width="wrap_content" 22 android:layout_height="wrap_content" 23 android:layout_x="134dp" 24 android:layout_y="276dp" 25 android:text="调暗" /> 26 27 <Button 28 android:id="@+id/button2" 29 android:layout_width="wrap_content" 30 android:layout_height="wrap_content" 31 android:layout_x="136dp" 32 android:layout_y="115dp" 33 android:text="调亮" /> 34 35 <Button 36 android:id="@+id/button1" 37 android:layout_width="wrap_content" 38 android:layout_height="wrap_content" 39 android:layout_x="208dp" 40 android:layout_y="181dp" 41 android:text="关灯" /> 42 43 <Button 44 android:id="@+id/button4" 45 android:layout_width="wrap_content" 46 android:layout_height="wrap_content" 47 android:layout_x="62dp" 48 android:layout_y="184dp" 49 android:text="开灯" /> 50 51 <Button 52 android:id="@+id/button5" 53 android:layout_width="wrap_content" 54 android:layout_height="wrap_content" 55 android:layout_x="28dp" 56 android:layout_y="382dp" 57 android:text="打开蓝牙" /> 58 59 <Button 60 android:id="@+id/button8" 61 android:layout_width="wrap_content" 62 android:layout_height="wrap_content" 63 android:layout_x="121dp" 64 android:layout_y="344dp" 65 android:text="收索设备" /> 66 67 <Button 68 android:id="@+id/button7" 69 android:layout_width="wrap_content" 70 android:layout_height="wrap_content" 71 android:layout_x="120dp" 72 android:layout_y="417dp" 73 android:text="建立通讯" /> 74 75 <Button 76 android:id="@+id/button6" 77 android:layout_width="wrap_content" 78 android:layout_height="wrap_content" 79 android:layout_x="218dp" 80 android:layout_y="380dp" 81 android:text="关闭蓝牙" /> 82 83 </AbsoluteLayout> 84 85 86