浅谈android蓝牙4.0BLE开发

  最近公司在做智能穿戴设备,用到了蓝牙4.0,当时就震惊了,完全没用过啊。智能硬着头皮自己上了,还好研究了几天之后终于明白了,下面把这几天的经验写一下。

  在android里面,蓝牙4.0的编程和之前有很大不同,不在需要socket,serverSocket,也就是说没有了服务器/客户端的概念,而且手机和蓝牙设备也不再需要配对,可以直接连接。

  蓝牙4.0的编程分为几个步骤:

  1.   获取蓝牙管理类对象;
  2.   获取蓝牙适配器对象;
  3.   搜索蓝牙设备;
  4.   连接蓝牙设备;
  5.   调用连接回调函数。
  一、获取蓝牙管理类对象

 private BluetoothManager manager;
 manager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);</span>

      二、获取蓝牙适配器对象

private BluetoothAdapter adapter;
adapter = manager.getAdapter();</span>

三、搜索蓝牙设备

bluetoothAdapter.startLeScan(callback);</span>

callback是搜索结果的回调对象,其实现如下:

private BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() {
			
		@Override
		public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
			// TODO Auto-generated method stub
			//如果搜索到了蓝牙设备,则在界面上添加蓝牙设备
			if(dialog != null)
				dialog.dismiss();
			adapter.addDevice(device);
			adapter.notifyDataSetChanged();
				
		}
	};

在这里我实现了一个adapter类,继承自BaseAdapter。adapter里面有一ArrayList对象,用来存储BluetoothDevice对象。

 

四、连接蓝牙设备

device.connectGatt(this, false, gattCallback);

五、调用连接回调函数
其实就是实现上面代码中的gattCallback对象,这里注意,gattCallback里面有9个方法,但是不需要每个都重写,自己需要哪个重写哪个,但是onConnectionStateChange方法一定要实现,因为蓝牙设备连接成功后,自动调用的方法就是这个。

private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {

		@Override
		public void onConnectionStateChange(BluetoothGatt gatt, int status,
				int newState) {
			// TODO Auto-generated method stub
			super.onConnectionStateChange(gatt, status, newState);
			if(newState == BluetoothProfile.STATE_CONNECTED){
				System.out.println("connected");
				gatt.discoverServices();
			}
		}
}

因为我要实现向蓝牙设备写数据,要先发现蓝牙设备提供的服务,所以实现了gatt.discoverServices(),这个方法会回调gattCallback里面的onServicesDiscovered方法。

 public void onServicesDiscovered(BluetoothGatt gatt, int status) {
			// TODO Auto-generated method stub
			super.onServicesDiscovered(gatt, status);
			System.out.println("discovered");
			if(status == BluetoothGatt.GATT_SUCCESS){
				BluetoothGattService service = gatt.getService(UUID.fromString(SERVER_UUID));
				if(service != null){
					characteristic = service.getCharacteristic(UUID.fromString(UUID_AVAILABLE));
					gatt.setCharacteristicNotification(characteristic, true);
					characteristic.setValue("gfrd");
					gatt.writeCharacteristic(characteristic);
				}
				
			}
		}

这里面获得服务的UUID和获得数据传输的UUID是不一样的,具体多少看蓝牙设备的设置,然后

gatt.writeCharacteristic(characteristic)方法会调用gattCallback里面的onCharacteristicWrite方法,这个方法我没有重写,因为暂时不需要。


android蓝牙4.0编程简单,主要是要搞清楚步骤,还有就是最后连接设备之后的调用关系,设备连接之后调用的方法一定是onConnectionStateChange方法,在这里面实现你需要的操作,然后结果在对应的回调函数里面获取即可。

下面贴完整代码:
 
    首先是主activity类:
<pre name="code" class="java"> public static class BluetoothDeviceAvtivity extends ListActivity{
		
		private LeDeviceListAdapter adapter;//自己实现的ListActivity的adapter;
		private ProgressDialog dialog;
		private ServiceConnection conn;
		private BluetoothManager manager;
		private BluetoothAdapter bluetoothAdapter;
		
		
		
		//连接蓝牙设备返回的参数
		private BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() {
			
			@SuppressLint("NewApi") @Override
			public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
				// TODO Auto-generated method stub
				//如果搜索到了蓝牙设备,则在界面上添加蓝牙设备
				if(dialog != null)
					dialog.dismiss();
				adapter.addDevice(device);
				adapter.notifyDataSetChanged();
				
			}
		};

		@Override
		protected void onCreate(Bundle savedInstanceState) {
			// TODO Auto-generated method stub
			super.onCreate(savedInstanceState);
			adapter = new LeDeviceListAdapter();
			manager = (BluetoothManager)getSystemService(BLUETOOTH_SERVICE);
			bluetoothAdapter = manager.getAdapter();
			scanDevice();
			setListAdapter(adapter);
		}

		/**
		 * 当用户点击了一个蓝牙设备时,连接蓝牙设备
		 * @param l
		 * @param v
		 * @param position
		 * @param id
		 */
		@Override
		protected void onListItemClick(ListView l, View v, int position, long id) {
			// TODO Auto-generated method stub
			super.onListItemClick(l, v, position, id);
			bluetoothAdapter.stopLeScan(callback);
			BluetoothDevice device = adapter.getBluetoothDevice(position);
			if(device != null){
				bluetoothDevice = device;
				connectDevice();
				finish();
			}
		}
		
		/** 
		 * TODO扫描蓝牙设备,2秒后停止
		 * @throw
		 * @return void
		 */
		@SuppressLint("NewApi") public void scanDevice(){
			showProgress();
			bluetoothAdapter.startLeScan(callback);
		}
		
		public void showProgress(){
			if(dialog == null){
				dialog = new ProgressDialog(this);
			}
			dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
			dialog.setIndeterminate(true);
			dialog.setCancelable(false);
			dialog.setMessage("正在搜索蓝牙设备");
			dialog.show();
		}
		
		/** 
		 * TODO连接蓝牙设备,如果设备没有绑定,首先绑定
		 * @throw
		 * @return void
		 */
		@SuppressLint("NewApi") public void connectDevice(){
			if(bluetoothDevice == null){
				new AlertDialog.Builder(this).setTitle("提示").setMessage("无法连接到该设备").setPositiveButton("确定", new OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// TODO Auto-generated method stub
						dialog.dismiss();
					}
				}).show();
			}else{
				String bluetoothName = bluetoothDevice.getName();
				String bluetoothAddress = bluetoothDevice.getAddress();
				Intent intent = new Intent(this, BluetoothServer.class);
				intent.putExtra("name", bluetoothName);
				intent.putExtra("address", bluetoothAddress);
				conn = new ServiceConnection() {
					
					@Override
					public void onServiceDisconnected(ComponentName name) {
						// TODO Auto-generated method stub
						new AlertDialog.Builder(BluetoothDeviceAvtivity.this).setTitle("提示").setMessage("蓝牙设备无法连接")
						.setPositiveButton("重新扫描", new OnClickListener() {
							
							@Override
							public void onClick(DialogInterface dialog, int which) {
								// TODO Auto-generated method stub
								scanDevice();
								setListAdapter(adapter);
							}
						}).setNegativeButton("取消", new OnClickListener() {
							
							@Override
							public void onClick(DialogInterface dialog, int which) {
								// TODO Auto-generated method stub
								dialog.dismiss();
								finish();
							}
						}).show();
					}
					
					@Override
					public void onServiceConnected(ComponentName name, IBinder service) {
						// TODO Auto-generated method stub
						Toast.makeText(BluetoothDeviceAvtivity.this, "蓝牙设备已连接", Toast.LENGTH_SHORT).show();
					}
				};
				bindService(intent, conn, Service.BIND_AUTO_CREATE);
			}
		}
		
		
		@Override
		protected void onDestroy() {
			// TODO Auto-generated method stub
			super.onDestroy();
			if(conn != null)
				unbindService(conn);
		}


		/**
		 * TODO自定义的ListView的适配器
		 * @author  DingChang
		 * @data:  2015-6-8 上午10:58:47
		 * @version:  V1.0
		 */
		public class LeDeviceListAdapter extends BaseAdapter{
			
			private ArrayList<BluetoothDevice> arrayList;
			private LayoutInflater mInflater;
			
			public LeDeviceListAdapter(){
				super();
				arrayList = new ArrayList<BluetoothDevice>();
				mInflater = BluetoothDeviceAvtivity.this.getLayoutInflater();
			}
			
			public void addDevice(BluetoothDevice device){
				if(!arrayList.contains(device))
					arrayList.add(device);
			}
			
			public BluetoothDevice getBluetoothDevice(int position) {
				return arrayList.get(position);
			}

			@Override
			public int getCount() {
				// TODO Auto-generated method stub
				return arrayList.size();
			}

			@Override
			public Object getItem(int position) {
				// TODO Auto-generated method stub
				return arrayList.get(position);
			}

			@Override
			public long getItemId(int position) {
				// TODO Auto-generated method stub
				return position;
			}

			@SuppressLint("InflateParams") @Override
			public View getView(int position, View convertView, ViewGroup parent) {
				// TODO Auto-generated method stub
				ViewHolder viewHolder;
				 if (convertView == null) {
		                convertView = mInflater.inflate(R.layout.adapter_layout, null);
		                viewHolder = new ViewHolder();
		                viewHolder.addressTextView = (TextView) convertView.findViewById(R.id.blueDeviceAddress);
		                viewHolder.nameTextView = (TextView) convertView.findViewById(R.id.blueDeviceName);
		                convertView.setTag(viewHolder);
		            } else {
		                viewHolder = (ViewHolder) convertView.getTag();
		            }

		            BluetoothDevice device = arrayList.get(position);
		            final String deviceName = device.getName();
		            if (deviceName != null && deviceName.length() > 0)
		                viewHolder.nameTextView.setText(deviceName);
		            else
		                viewHolder.nameTextView.setText("未知设备");
		            viewHolder.addressTextView.setText(device.getAddress());
				return convertView;
			}
			
		}
		
	}
	public static class ViewHolder{
		TextView nameTextView;
		TextView addressTextView;
	}
</pre><pre name="code" class="java">      然后就是后台实现蓝牙连接,数据传输的Service类:
<pre name="code" class="java">public class BluetoothServer extends Service {
	
	private BluetoothAdapter adapter;
	private BluetoothManager manager;
	private BluetoothDevice device;
	private final static String UUID_AVAILABLE = "00001002-0000-1000-8000-00805f9b34fb";
	private final static String SERVER_UUID = "00001000-0000-1000-8000-00805f9b34fb";
	private BluetoothGattCharacteristic characteristic;
	
	@SuppressLint("NewApi") private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {

		@Override
		public void onConnectionStateChange(BluetoothGatt gatt, int status,
				int newState) {
			// TODO Auto-generated method stub
			super.onConnectionStateChange(gatt, status, newState);
			if(status == BluetoothProfile.STATE_CONNECTED && newState == BluetoothProfile.STATE_DISCONNECTED){
				stopSelf();
			}
			if(newState == BluetoothProfile.STATE_CONNECTED){
				System.out.println("connected");
				gatt.discoverServices();
			}
		}

		@Override
		public void onServicesDiscovered(BluetoothGatt gatt, int status) {
			// TODO Auto-generated method stub
			super.onServicesDiscovered(gatt, status);
			System.out.println("discovered");
			if(status == BluetoothGatt.GATT_SUCCESS){
				BluetoothGattService service = gatt.getService(UUID.fromString(SERVER_UUID));
				if(service != null){
					characteristic = service.getCharacteristic(UUID.fromString(UUID_AVAILABLE));
					gatt.setCharacteristicNotification(characteristic, true);
					characteristic.setValue("gfrd");
					gatt.writeCharacteristic(characteristic);
				}
				
			}
		}

		@Override
		public void onCharacteristicWrite(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic, int status) {
			// TODO Auto-generated method stub
			super.onCharacteristicWrite(gatt, characteristic, status);
			System.out.println("write");
		}

		
			
	};
	
	@SuppressLint("NewApi") @Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		//String name = arg0.getStringExtra("name");
		String addressString = arg0.getStringExtra("address");
		device = adapter.getRemoteDevice(addressString);
		device.connectGatt(this, false, gattCallback);
		//boolean b = bluetoothGatt.discoverServices();
		
		//System.out.println(b);
		return null;
	}

	@SuppressLint("NewApi") @Override
	public void onCreate() {
		// TODO Auto-generated method stub
		manager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
		adapter = manager.getAdapter();
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}

	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub
		return super.onUnbind(intent);
	}
	
}


 
</pre><br /><br /><br /><pre>
 

 
 
 


 

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值