Android蓝牙自动配对Demo,亲测好使!!!

时间:2024-03-11 10:06:44

蓝牙自动配对,即搜索到其它蓝牙设备之后直接进行配对,不需要弹出配对确认框或者密钥输入框。


转载请注明出处http://blog.csdn.net/qq_25827845/article/details/52400782

 

源码下载地址:http://download.csdn.net/download/qq_25827845/9757403

 

经过最近一段时间得研究,针对网上给出的案例。总结了一个亲测好使的Demo。

说明如下:

1、本Demo用来连接蓝牙设备HC-05,如果你要连接其他蓝牙设备,注意修改相关名字以及修改设备初试pin值。

2、将Demo安装在Android手机上,点击按钮,可以实现与目标蓝牙设备的自动配对。

3、若目标蓝牙设备为Android手机的蓝牙,则只能保证本设备不弹出配对框,对方还是会弹出配对框。但是!!不管目标蓝牙点击“确认”or“取消”,在本设备中都显示已经成功配对。实测表明,确实已经配对了,可以进行数据传输。

4、由于使用了广播机制,所以需要在Androidmanifest.xml进行如下配置。

先配置蓝牙使用权限:

     <uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 

然后配置action,将需要用到的广播进行注册

<receiver android:name="com.ywq.broadcast.BluetoothReceiver" >
    <intent-filter android:priority="1000">
        <action android:name="android.bluetooth.device.action.PAIRING_REQUEST"/>
        <action android:name="android.bluetooth.device.action.FOUND" />
    </intent-filter>
</receiver>

 

程序运行流程:

1、点击按钮,判断蓝牙是否打开,,执行bluetoothAdapter.startDiscovery();由本地蓝牙设备扫描远程蓝牙设备,startDiscovery()方法是一个异步方法,调用后立即返回。该方法会进行蓝牙设备的搜索,持续12秒。

2、搜索时,系统会发送3个广播,分别为:ACTION_DISCOVERY_START:开始搜索 、ACTION_DISCOVERY_FINISHED:搜索结束、 ACTION_FOUND:找到设备,该Intent中包含两个extra fields;         

3、在广播接收类中BluetoothReceiver.Java中,当设备找到之后会执行其onReceive方法。

4、String action = intent.getAction(); //得到action,

第一次action的值为BluetoothDevice.ACTION_FOUND,当找到的设备是我们目标蓝牙设备时,调用createBond方法来进行配对。ClsUtils.createBond(btDevice.getClass(), btDevice);该方法执行后,系统会收到一个请求配对的广播,即android.bluetooth.device.action.PAIRING_REQUEST。最后进行自动配对操作。

5、配对操作借助工具类ClsUtils.java得到了Android蓝牙API中隐藏的方法,实现自动配对,不弹出配对框的功能。

 

 

代码如下:

MainActivity.java

  1. package com.example.mybuletooth;  
  2.   
  3. import android.app.Activity;  
  4. import android.bluetooth.BluetoothAdapter;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.view.View.OnClickListener;  
  8. import android.widget.Button;  
  9.   
  10. public class MainActivity extends Activity implements OnClickListener{  
  11.       
  12.     /** Called when the activity is first created. */   
  13.     private Button autopairbtn=null;  
  14.     private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();  
  15.   
  16.     @Override  
  17.     protected void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.activity_main);  
  20.           
  21.         autopairbtn=(Button) findViewById(R.id.button1);  
  22.         autopairbtn.setOnClickListener(this);  
  23.           
  24.     }  
  25.       
  26.     //设置按钮的监听方法  
  27.     @Override  
  28.     public void onClick(View arg0) {  
  29.           
  30.         if (!bluetoothAdapter.isEnabled())  
  31.         {  
  32.                 bluetoothAdapter.enable();//异步的,不会等待结果,直接返回。  
  33.         }else{  
  34.                 bluetoothAdapter.startDiscovery();  
  35.              }  
  36.           
  37.     }  
  38. }  

 

BluetoothReceiver.java

  1. package com.ywq.broadcast;  
  2.   
  3. import com.ywq.tools.ClsUtils;  
  4. import android.bluetooth.BluetoothDevice;  
  5. import android.content.BroadcastReceiver;  
  6. import android.content.Context;  
  7. import android.content.Intent;  
  8. import android.util.Log;  
  9.   
  10.   
  11. public class BluetoothReceiver extends BroadcastReceiver{  
  12.   
  13.     String pin = "1234";  //此处为你要连接的蓝牙设备的初始密钥,一般为1234或0000  
  14.     public BluetoothReceiver() {  
  15.           
  16.     }  
  17.   
  18.     //广播接收器,当远程蓝牙设备被发现时,回调函数onReceiver()会被执行   
  19.     @Override  
  20.     public void onReceive(Context context, Intent intent) {  
  21.           
  22.         String action = intent.getAction(); //得到action  
  23.         Log.e("action1=", action);  
  24.         BluetoothDevice btDevice=null;  //创建一个蓝牙device对象  
  25.          // 从Intent中获取设备对象  
  26.         btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);   
  27.           
  28.         if(BluetoothDevice.ACTION_FOUND.equals(action)){  //发现设备  
  29.             Log.e("发现设备:", "["+btDevice.getName()+"]"+":"+btDevice.getAddress());  
  30.               
  31.             if(btDevice.getName().contains("HC-05"))//HC-05设备如果有多个,第一个搜到的那个会被尝试。  
  32.             {  
  33.                 if (btDevice.getBondState() == BluetoothDevice.BOND_NONE) {    
  34.                       
  35.                     Log.e("ywq", "attemp to bond:"+"["+btDevice.getName()+"]");  
  36.                     try {  
  37.                         //通过工具类ClsUtils,调用createBond方法  
  38.                         ClsUtils.createBond(btDevice.getClass(), btDevice);  
  39.                     } catch (Exception e) {  
  40.                         // TODO Auto-generated catch block  
  41.                         e.printStackTrace();  
  42.                     }  
  43.                 }  
  44.             }else  
  45.                 Log.e("error", "Is faild");  
  46.         }else if(action.equals("android.bluetooth.device.action.PAIRING_REQUEST")) //再次得到的action,会等于PAIRING_REQUEST  
  47.         {  
  48.             Log.e("action2=", action);  
  49.             if(btDevice.getName().contains("HC-05"))  
  50.             {  
  51.                 Log.e("here", "OKOKOK");  
  52.                   
  53.                 try {  
  54.                       
  55.                     //1.确认配对  
  56.                     ClsUtils.setPairingConfirmation(btDevice.getClass(), btDevice, true);  
  57.                     //2.终止有序广播  
  58.                     Log.i("order...", "isOrderedBroadcast:"+isOrderedBroadcast()+",isInitialStickyBroadcast:"+isInitialStickyBroadcast());  
  59.                     abortBroadcast();//如果没有将广播终止,则会出现一个一闪而过的配对框。  
  60.                     //3.调用setPin方法进行配对...  
  61.                     boolean ret = ClsUtils.setPin(btDevice.getClass(), btDevice, pin);  
  62.                       
  63.                 } catch (Exception e) {  
  64.                     // TODO Auto-generated catch block  
  65.                     e.printStackTrace();  
  66.                 }  
  67.             }else  
  68.                 Log.e("提示信息", "这个设备不是目标蓝牙设备");  
  69.               
  70.         }  
  71.     }  
  72. }  


工具类ClsUtils.java

  1. package com.ywq.tools;  
  2.   
  3. /************************************ 蓝牙配对函数 * **************/  
  4.   
  5. import java.lang.reflect.Method;    
  6. import java.lang.reflect.Field;    
  7. import android.bluetooth.BluetoothDevice;    
  8. import android.util.Log;    
  9.     
  10. public class ClsUtils     
  11. {    
  12.     /**  
  13.      * 与设备配对 参考源码:platform/packages/apps/Settings.git  
  14.      * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java  
  15.      */    
  16.     static public boolean createBond(Class btClass, BluetoothDevice btDevice)    
  17.     throws Exception    
  18.     {    
  19.         Method createBondMethod = btClass.getMethod("createBond");    
  20.         Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);    
  21.         return returnValue.booleanValue();    
  22.     }    
  23.      
  24.     /**  
  25.      * 与设备解除配对 参考源码:platform/packages/apps/Settings.git  
  26.      * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java  
  27.      */    
  28.     static public boolean removeBond(Class<?> btClass, BluetoothDevice btDevice)    
  29.             throws Exception    
  30.     {    
  31.         Method removeBondMethod = btClass.getMethod("removeBond");    
  32.         Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);    
  33.         return returnValue.booleanValue();    
  34.     }    
  35.      
  36.     static public boolean setPin(Class<? extends BluetoothDevice> btClass, BluetoothDevice btDevice,    
  37.             String str) throws Exception    
  38.     {    
  39.         try    
  40.         {    
  41.             Method removeBondMethod = btClass.getDeclaredMethod("setPin",    
  42.                     new Class[]    
  43.                     {byte[].class});    
  44.             Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice,    
  45.                     new Object[]    
  46.                     {str.getBytes()});    
  47.             Log.e("returnValue", "" + returnValue);    
  48.         }    
  49.         catch (SecurityException e)    
  50.         {    
  51.             // throw new RuntimeException(e.getMessage());    
  52.             e.printStackTrace();    
  53.         }    
  54.         catch (IllegalArgumentException e)    
  55.         {    
  56.             // throw new RuntimeException(e.getMessage());    
  57.             e.printStackTrace();    
  58.         }    
  59.         catch (Exception e)    
  60.         {    
  61.             // TODO Auto-generated catch block    
  62.             e.printStackTrace();    
  63.         }    
  64.         return true;    
  65.      
  66.     }    
  67.      
  68.     // 取消用户输入    
  69.     static public boolean cancelPairingUserInput(Class<?> btClass,    
  70.             BluetoothDevice device)  throws Exception    
  71.     {    
  72.         Method createBondMethod = btClass.getMethod("cancelPairingUserInput");    
  73. //        cancelBondProcess(btClass, device);  
  74.         Boolean returnValue = (Boolean) createBondMethod.invoke(device);    
  75.         return returnValue.booleanValue();    
  76.     }    
  77.      
  78.     // 取消配对    
  79.     static public boolean cancelBondProcess(Class<?> btClass,    
  80.             BluetoothDevice device)    
  81.      
  82.     throws Exception    
  83.     {    
  84.         Method createBondMethod = btClass.getMethod("cancelBondProcess");    
  85.         Boolean returnValue = (Boolean) createBondMethod.invoke(device);    
  86.         return returnValue.booleanValue();    
  87.     }   
  88.       
  89.     //确认配对  
  90.       
  91.     static public void setPairingConfirmation(Class<?> btClass,BluetoothDevice device,boolean isConfirm)throws Exception   
  92.     {  
  93.         Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation",boolean.class);   
  94.         setPairingConfirmation.invoke(device,isConfirm);  
  95.     }  
  96.       
  97.      
  98.     /**  
  99.      *  
  100.      * @param clsShow  
  101.      */    
  102.     static public void printAllInform(Class clsShow)    
  103.     {    
  104.         try    
  105.         {    
  106.             // 取得所有方法    
  107.             Method[] hideMethod = clsShow.getMethods();    
  108.             int i = 0;    
  109.             for (; i < hideMethod.length; i++)    
  110.             {    
  111.                 Log.e("method name", hideMethod[i].getName() + ";and the i is:"    
  112.                         + i);    
  113.             }  
  114.             // 取得所有常量    
  115.             Field[] allFields = clsShow.getFields();    
  116.             for (i = 0; i < allFields.length; i++)    
  117.             {    
  118.                 Log.e("Field name", allFields[i].getName());    
  119.             }  
  120.         }    
  121.         catch (SecurityException e)    
  122.         {    
  123.             // throw new RuntimeException(e.getMessage());    
  124.             e.printStackTrace();    
  125.         }    
  126.         catch (IllegalArgumentException e)    
  127.         {    
  128.             // throw new RuntimeException(e.getMessage());    
  129.             e.printStackTrace();    
  130.         }    
  131.         catch (Exception e)    
  132.         {    
  133.             // TODO Auto-generated catch block    
  134.             e.printStackTrace();    
  135.         }    
  136.     }    
  137. }    


Androidmanifest.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.example.mybuletooth"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="8"  
  9.         android:targetSdkVersion="21" />  
  10.       
  11.     <uses-permission android:name="android.permission.BLUETOOTH"/>  
  12.     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>  
  13.   
  14.     <application  
  15.         android:allowBackup="true"  
  16.         android:icon="@drawable/ic_launcher"  
  17.         android:label="@string/app_name"  
  18.         android:theme="@style/AppTheme" >  
  19.         <activity  
  20.             android:name=".MainActivity"  
  21.             android:label="@string/app_name" >  
  22.             <intent-filter>  
  23.                 <action android:name="android.intent.action.MAIN" />  
  24.   
  25.                 <category android:name="android.intent.category.LAUNCHER" />  
  26.             </intent-filter>  
  27.         </activity>  
  28.           
  29.         <receiver android:name="com.ywq.broadcast.BluetoothReceiver" >  
  30.             <intent-filter android:priority="1000">  
  31.                 <action android:name="android.bluetooth.device.action.PAIRING_REQUEST"/>  
  32.                 <action android:name="android.bluetooth.device.action.FOUND" />  
  33.             </intent-filter>  
  34.         </receiver>  
  35.     </application>  
  36.   
  37. </manifest>  



布局配置文件activity_main.xml

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="@dimen/activity_vertical_margin"  
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  7.     android:paddingRight="@dimen/activity_horizontal_margin"  
  8.     android:paddingTop="@dimen/activity_vertical_margin"  
  9.     tools:context="com.example.mybuletooth.MainActivity" >  
  10.   
  11.     <Button  
  12.         android:id="@+id/button1"  
  13.         android:layout_width="wrap_content"  
  14.         android:layout_height="wrap_content"  
  15.         android:layout_alignParentLeft="true"  
  16.         android:layout_alignParentTop="true"  
  17.         android:layout_marginLeft="54dp"  
  18.         android:layout_marginTop="56dp"  
  19.         android:text="自动配对" />  
  20.   
  21.     <TextView  
  22.         android:id="@+id/textView1"  
  23.         android:layout_width="wrap_content"  
  24.         android:layout_height="wrap_content"  
  25.         android:layout_centerVertical="true"  
  26.         android:text="点击按钮,自动搜索蓝牙设备,并且进行配对" />  
  27.   
  28. </RelativeLayout>  



针对网上其它帖子中的demo不好使的原因,在此给出一些我的看法,是不是这样不敢保证,至少部分是这些原因吧。。。

1、出现一个一闪而过的配对框怎么办?

答:那是因为广播没有停止,须得调用abortBroadcast();将广播停止。

2、自动配对框还是会弹出来怎么办?

答:网上好多帖子代码有误,或者没有说清楚。请注意相关配置和工具类中函数的使用。

 

 

这是本人亲测好使的自动配对Demo,仅供参考,希望对大家有所帮助。有问题可以联系我。

 


 

重要更新:********************************************************************************


2016-10-20 ,今天和一个咨询我的小伙伴详细的聊了会儿天。他的问题是,下图所示的if语句块进不去。

 

它的btDevice.getBondState( )=12,但是BluetoothDevice.BOND_NONE=10,这不是肯定进不去么。哭

其中,查阅SDK,可以看到BluetoothDevice的这几个函数和数字的含义是什么。

参考网址:http://www.cnblogs.com/over140/archive/2010/12/21/1912482.html

如下所示:

 

 

 

我一看,天呐,很明显的低级错误。我让他打开设置看看,是否显示已经配对。结果自然是已经配对了。

产生原因:这个demo在跑之前,他已经在手机-设置-蓝牙中手动把目标蓝牙配对了。那还玩个毛呀大哭

 

当手动取消配对后,程序运行正常,log打印和预期一样,自动配对实现。

 

 

 

提示:

通过这个小失误,可以看出,评论里好多说这也不行,那也不行的。既然好多人都说好使,那你为什么就不行呢?还是多从自身找问题吧,心思缜密点,避免这种低级失误。大哥,你是程序猿好不好。

                                         

 

 

源码下载地址:http://download.csdn.net/download/qq_25827845/9757403


如果对你有帮助,记得点赞哦~欢迎大家关注我的博客,有问题可以进群366533258讨论哈~