手把手教你Android手机与BLE终端通信--搜索

由于代码量大,这次只写搜索,以后接着写连接和发送数据。

    1,界面上只有一个按钮和一个listview

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <RelativeLayout   
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:layout_width="match_parent"   
  5.     android:layout_height="match_parent"  
  6.     android:background="#ffff"  
  7.     >  
  8.     <Button   
  9.         android:id="@+id/btn_search"  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content"  
  12.         android:text="搜索"  
  13.         android:layout_marginTop="40dp"  
  14.         android:layout_marginLeft="40dp"  
  15.         android:background="@null"  
  16.         android:textColor="#ff2222ff"  
  17.         android:textSize="32sp"/>  
  18.       
  19.     <ListView android:id="@+id/list_devices"  
  20.         android:layout_width="match_parent"  
  21.         android:layout_height="wrap_content"  
  22.         android:layout_marginTop="20dp"  
  23.         android:layout_below="@id/btn_search"  
  24.         android:layout_marginLeft="40dp">  
  25.           
  26.     </ListView>  
  27.       
  28. </RelativeLayout>  
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" 
    android:layout_height="match_parent"
    android:background="#ffff"
    >
    <Button 
        android:id="@+id/btn_search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="搜索"
        android:layout_marginTop="40dp"
        android:layout_marginLeft="40dp"
        android:background="@null"
        android:textColor="#ff2222ff"
        android:textSize="32sp"/>
    
    <ListView android:id="@+id/list_devices"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_below="@id/btn_search"
        android:layout_marginLeft="40dp">
        
    </ListView>
    
</RelativeLayout>



2, MainActivity 首先初始化蓝牙并打开 service service 用于后台和界面的沟通。

  1. //开始服务  
  2.         intentService = new Intent(MainActivity.this,BLEService.class);     
  3.         startService(intentService);  
  4.         // 初始化蓝牙  
  5.         BluetoothController.getInstance().initBLE();  
//开始服务
		intentService = new Intent(MainActivity.this,BLEService.class);   
		startService(intentService);
		// 初始化蓝牙
		BluetoothController.getInstance().initBLE();
  下面是initBle方法,初始化蓝牙,注释要看哦。

  1. /**  
  2.      * 初始化蓝牙  
  3.      * @return  
  4.      */  
  5.     public  boolean initBLE(){  
  6.         //检查当前手机是否支持ble 蓝牙,如果不支持退出程序  
  7.         //App.app可能会报错,清单文件中不要忘了配置application  
  8.         if (!App.app.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {  
  9.             return false;  
  10.         }  
  11.         // 初始化 Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上版本)  
  12.         final BluetoothManager bluetoothManager = (BluetoothManager) App.app.getSystemService(Context.BLUETOOTH_SERVICE);  
  13.         bleAdapter = bluetoothManager.getAdapter();  
  14.         // 检查设备上是否支持蓝牙  
  15.         if (bleAdapter == null) return false;  
  16.         else return true;  
  17.     }   
/**
	 * 初始化蓝牙
	 * @return
	 */
	public  boolean initBLE(){
		//检查当前手机是否支持ble 蓝牙,如果不支持退出程序
		//App.app可能会报错,清单文件中不要忘了配置application
		if (!App.app.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
			return false;
		}
		// 初始化 Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上版本)
		final BluetoothManager bluetoothManager = (BluetoothManager) App.app.getSystemService(Context.BLUETOOTH_SERVICE);
		bleAdapter = bluetoothManager.getAdapter();
		// 检查设备上是否支持蓝牙
		if (bleAdapter == null) return false;
		else return true;
	} 

3, 点击 MainActivity 搜索按钮开启异步任务,调用搜索方法

  1. search = (Button) findViewById(R.id.btn_search);  
  2.         search.setOnClickListener(new OnClickListener() {  
  3.   
  4.             @Override  
  5.             public void onClick(View arg0) {  
  6.                 if(!BluetoothController.getInstance().initBLE()){//手机不支持蓝牙  
  7.                     Toast.makeText(MainActivity.this, "您的手机不支持蓝牙",  
  8.                             Toast.LENGTH_SHORT).show();  
  9.                     return;//手机不支持蓝牙就啥也不用干了,关电脑睡觉去吧  
  10.                 }  
  11.                 if (!BluetoothController.getInstance().isBleOpen()) {// 如果蓝牙还没有打开  
  12.                     Toast.makeText(MainActivity.this, "请打开蓝牙",  
  13.                             Toast.LENGTH_SHORT).show();  
  14.                     return;  
  15.                 }  
  16.                 new GetDataTask().execute();// 搜索任务  
  17.   
  18.             }  
  19.         });  
search = (Button) findViewById(R.id.btn_search);
		search.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				if(!BluetoothController.getInstance().initBLE()){//手机不支持蓝牙
					Toast.makeText(MainActivity.this, "您的手机不支持蓝牙",
							Toast.LENGTH_SHORT).show();
					return;//手机不支持蓝牙就啥也不用干了,关电脑睡觉去吧
				}
				if (!BluetoothController.getInstance().isBleOpen()) {// 如果蓝牙还没有打开
					Toast.makeText(MainActivity.this, "请打开蓝牙",
							Toast.LENGTH_SHORT).show();
					return;
				}
				new GetDataTask().execute();// 搜索任务

			}
		});

异步任务中只有一句,开始搜索

  1. private class GetDataTask extends AsyncTask<Void, Void, String[]> {  
  2.   
  3.         @Override  
  4.         protected String[] doInBackground(Void... params) {  
  5.             if(BluetoothController.getInstance().isBleOpen()){  
  6.                 BluetoothController.getInstance().startScanBLE();  
  7.             };// 开始扫描  
  8.             return null;  
  9.         }  
  10.   
  11.         @Override  
  12.         protected void onPostExecute(String[] result) {  
  13.             super.onPostExecute(result);  
  14.         }  
  15.     }  
private class GetDataTask extends AsyncTask<Void, Void, String[]> {

		@Override
		protected String[] doInBackground(Void... params) {
			if(BluetoothController.getInstance().isBleOpen()){
				BluetoothController.getInstance().startScanBLE();
			};// 开始扫描
			return null;
		}

		@Override
		protected void onPostExecute(String[] result) {
			super.onPostExecute(result);
		}
	}

4, 初始化,搜索等蓝牙操作都在controller类中。搜索代码中设置5秒后停止搜索,搜索成功回调中发消息给service, service发广播给MainActivity更新listview.

不要忘了注册service和广播receiver

  1. /**  
  2.      * 开始扫描蓝牙  
  3.      */  
  4.     public  void startScanBLE(){  
  5.         bleAdapter.startLeScan(bleScanCallback);  
  6.         if(serviceHandler!=null)  
  7.             serviceHandler.sendEmptyMessageDelayed(ConstantUtils.WM_STOP_SCAN_BLE, 5000);  
  8.         }  
/**
	 * 开始扫描蓝牙
	 */
	public  void startScanBLE(){
		bleAdapter.startLeScan(bleScanCallback);
		if(serviceHandler!=null)
			serviceHandler.sendEmptyMessageDelayed(ConstantUtils.WM_STOP_SCAN_BLE, 5000);
	    }
bleScanCallback是搜索成功后的回调,搜索成功后发消息给service,让它发广播更新界面

  1. /**  
  2.      * 搜索蓝牙回调  
  3.      */  
  4.     BluetoothAdapter.LeScanCallback bleScanCallback =new BluetoothAdapter.LeScanCallback() {  
  5.         @Override  
  6.         public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {  
  7.             // device就是搜索到的设备  
  8.             String name=device.getName();  
  9.             if(name==null) return;  
  10.             if(BluetoothController.this.serviceHandler!=null&&!name.isEmpty()){  
  11.                 Message msg=new Message();  
  12.                 msg.what=ConstantUtils.WM_UPDATE_BLE_LIST;  
  13.                 msg.obj=device;  
  14.                 BluetoothController.this.serviceHandler.sendMessage(msg);  
  15.             }  
  16.         }  
  17.     };  
/**
	 * 搜索蓝牙回调
	 */
	BluetoothAdapter.LeScanCallback bleScanCallback =new BluetoothAdapter.LeScanCallback() {
		@Override
		public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {
			// device就是搜索到的设备
			String name=device.getName();
			if(name==null) return;
			if(BluetoothController.this.serviceHandler!=null&&!name.isEmpty()){
				Message msg=new Message();
				msg.what=ConstantUtils.WM_UPDATE_BLE_LIST;
				msg.obj=device;
				BluetoothController.this.serviceHandler.sendMessage(msg);
			}
		}
	};
其中的serviceHandler是在service中初始化的,所以它会发消息到service中。

  1. Handler handler = new Handler() {  
  2.         public void handleMessage(android.os.Message msg) {  
  3.             switch (msg.what) {  
  4.               
  5.             case ConstantUtils.WM_STOP_SCAN_BLE://搜索5秒后停止搜索  
  6.                 bleCtrl.stopScanBLE();  
  7.                 break;  
  8.             case ConstantUtils.WM_UPDATE_BLE_LIST://回调发来的更新列表消息  
  9.                 //更新蓝牙列表广播  
  10.                 Intent intent=new Intent(ConstantUtils.ACTION_UPDATE_DEVICE_LIST);  
  11.                 BluetoothDevice device=(BluetoothDevice)msg.obj;  
  12.                 intent.putExtra("name",device.getName());  
  13.                 intent.putExtra("address", device.getAddress());  
  14.                 sendBroadcast(new Intent(intent));  
  15.                 break;  
  16.               
  17.             }  
  18.         }  
  19.     };  
Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			
			case ConstantUtils.WM_STOP_SCAN_BLE://搜索5秒后停止搜索
				bleCtrl.stopScanBLE();
				break;
			case ConstantUtils.WM_UPDATE_BLE_LIST://回调发来的更新列表消息
				//更新蓝牙列表广播
				Intent intent=new Intent(ConstantUtils.ACTION_UPDATE_DEVICE_LIST);
				BluetoothDevice device=(BluetoothDevice)msg.obj;
				intent.putExtra("name",device.getName());
				intent.putExtra("address", device.getAddress());
				sendBroadcast(new Intent(intent));
				break;
			
			}
		}
	};
5,  MainActivity 收到更新列表的消息后更新列表,更新列表时一定要先判断 Listview 中是否已经有那个设备了,否则会搜的很多次那个设备,然后你的手机就卡了,说不定还要害你重启手机呢,至少得关了这个app了。

  1. public class MsgReceiver extends BroadcastReceiver {  
  2.         @Override  
  3.         public void onReceive(Context context, Intent intent) {  
  4.             if (intent.getAction().equalsIgnoreCase(  
  5.                     ConstantUtils.ACTION_UPDATE_DEVICE_LIST)) {  
  6.                 String name = intent.getStringExtra("name");  
  7.                 String address = intent.getStringExtra("address");  
  8.                 boolean found=false;//记录该条记录是否已在list中,  
  9.                 for(EntityDevice device:list){  
  10.                     if(device.getAddress().equals(address)){  
  11.                         found=true;  
  12.                         break;  
  13.                         }  
  14.                 }// for  
  15.                 if(!found){  
  16.                     EntityDevice temp = new EntityDevice();  
  17.                     temp.setName(name);  
  18.                     temp.setAddress(address);  
  19.                     list.add(temp);  
  20.                     adapter.notifyDataSetChanged();  
  21.                 }  
  22.             }  
  23.         }  
  24.     }  
public class MsgReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equalsIgnoreCase(
					ConstantUtils.ACTION_UPDATE_DEVICE_LIST)) {
				String name = intent.getStringExtra("name");
				String address = intent.getStringExtra("address");
				boolean found=false;//记录该条记录是否已在list中,
				for(EntityDevice device:list){
					if(device.getAddress().equals(address)){
						found=true;
						break;
						}
				}// for
				if(!found){
					EntityDevice temp = new EntityDevice();
					temp.setName(name);
					temp.setAddress(address);
					list.add(temp);
					adapter.notifyDataSetChanged();
				}
			}
		}
	}

不要忘了注册和注销这个receiver

我们的实体类,暂存设备

  1. public class EntityDevice {  
  2.       
  3.     private String name;  
  4.     private String address;  
  5.     public String getName() {  
  6.         return name;  
  7.     }  
  8.     public void setName(String name) {  
  9.         this.name = name;  
  10.     }  
  11.     public String getAddress() {  
  12.         return address;  
  13.     }  
  14.     public void setAddress(String address) {  
  15.         this.address = address;  
  16.     }  
  17.   
  18. }  
public class EntityDevice {
	
	private String name;
	private String address;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}

}


一定要注意:

1,这是蓝牙和串口连接,不是和另外一个手机的蓝牙连接。

2,由于安卓6.0以上的权限管理问题,需要以下三个权限(6.0以前只要后两个就可以):     

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

完整代码链接:

http://pan.baidu.com/s/1mi71vWO


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值