zoukankan      html  css  js  c++  java
  • 蓝牙从搜索到成功配对的全过程

    真是应该值得庆祝一下,为了个毕设,本人真是呕心沥血啊!就在刚才,终于完成了蓝牙成功配对的工作,在此将全过程记录下来,以便日后查阅。

    蓝牙通讯的全过程大多资料上都有介绍,无非就是先打开蓝牙、搜索设备、被设备搜索、进行配对,这里我就不在多说啦,将部分代码附上

    现在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异常

    后来在网上找到了解决办法,但是为什么这么做,我也不知道,代码如下:

    至此蓝牙配对完成,下一步该是通讯了,有待研究,将代码附上,由于此项目尚未完成,所以部分代码还没有写完,此代码只实现了蓝牙搜索配对

    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 关闭后返回的数据
        }
    }
    MainActivity
    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) { }    
                }  
            }    
        }
    }
    Device
     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>
    Device
     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     
    main
  • 相关阅读:
    Nginx在linux环境下(centos7)的安装、负载均衡设置
    ocr识别开源软件tesseract试用记录
    Nginx在windows环境下的安装、负载均衡设置
    一个测试程序迭代的故事05
    一个测试程序迭代的故事04
    一个测试程序迭代的故事03
    一个测试程序迭代的故事02
    一个测试程序迭代的故事01
    Delphi5和Delphi7属性编辑器内存泄漏问题的解决
    使用Calibre自带工具批量转换电子书格式
  • 原文地址:https://www.cnblogs.com/s-hk/p/3437225.html
Copyright © 2011-2022 走看看