手机BLE蓝牙通讯

Android的蓝牙开发,包括蓝牙的广播事件和扫描,蓝牙配对连接、数据传输等问题,本文着重讲BLE低功耗蓝牙4.0开发

AndroidMainifest权限:

    <uses-sdk
        android:minSdkVersion="18"
        android:targetSdkVersion="19" />

    <!--蓝牙权限-->
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <!--Android 5.0以上蓝牙好需要位置权限-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="andriod.permission.ACCESS_FINE_LOCATION"/>
    <!--设备支持BLE低功耗蓝牙 true -->
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"></uses-feature>

△低功耗蓝牙4.0开发:源码

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager;
public class MainActivity extends Activity {
	private BluetoothAdapter mBluetoothAdapter;
	private Handler mHandler=new Handler();
	private boolean mScanning;
	private BluetoothGatt mGatt;
	private BluetoothGattCharacteristic mGattCharacteristic;
	
	private ListView mlv;//自定义列表listview
	private BleAdapter mBleAdapter;//自定义适配器adapter
	private ArrayList<BluetoothDevice> mArray=new ArrayList<BluetoothDevice>();//自定义容器
	private EditText mEdit;//自定义edittext
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initUI();
		initBLE();
	}
	
	@Override
	protected void onDestroy() {
		if(mGatt!=null){
			mGatt.close();
			mGatt=null;
		}
		super.onDestroy();
	}
	
	//初始化自定义控件
	private void initUI(){
		findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if(mGatt!=null){
					mGatt.close();
					mGatt=null;
				}
				scanLe(true);
			}
		});
		
		mlv = (ListView) findViewById(R.id.listView1);
		mBleAdapter = new BleAdapter(MainActivity.this,mArray);
    	mlv.setAdapter(mBleAdapter);
    	mlv.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
				if(mGatt==null){
				mGatt = mArray.get(position).connectGatt(MainActivity.this, false, mGattCallback);
				}else{
				mGatt.connect();	
				}
				
				new AlertDialog.Builder(MainActivity.this)
				.setTitle("请输入内容")
				.setView(mEdit=new EditText(MainActivity.this))
				.setPositiveButton("确定", new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						mGattCharacteristic.setValue(mEdit.getText().toString().trim());
           			 	mGatt.writeCharacteristic(mGattCharacteristic);
					}
				})
				.show();
			}
		});
	}
	
	//初始化蓝牙4.0
	private void initBLE() {
		//如果不支持BLE则退出程序
		if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
		     Toast.makeText(this,"不支持低功耗蓝牙", Toast.LENGTH_SHORT).show();
		     finish();
		}
		//获取蓝牙适配器打开蓝牙
		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
		if (mBluetoothAdapter!=null&&!mBluetoothAdapter.isEnabled()) {
		mBluetoothAdapter.enable();//自动打开蓝牙
		}
	}
	
    //开始扫描BLE
    private void scanLe(boolean enable) {
        if (enable) {
            if (mBluetoothAdapter.isEnabled()) {
                if (mScanning){
                return;
                }
                mArray.clear();
                mScanning = true;
                mHandler.postDelayed(mScanRunnable, 5000);//5秒后关闭扫描
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
            	Toast.makeText(this,"蓝牙检测中", Toast.LENGTH_SHORT).show();
            }
        } else {
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
            mHandler.removeCallbacks(mScanRunnable);
            mScanning = false;
        }
    }
    
   //停止扫描BLE
    private final Runnable mScanRunnable = new Runnable() {
        @Override
        public void run() {
        	scanLe(false);
        }
    };
    
    //扫描结果
	private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
        /**@param device:识别的远程设备
         * @param rssi: 信号值为远程蓝牙设备的报告,0代表没有蓝牙设备
         * @param scanRecord:远程设备提供的配对号
         */
        @Override
        public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
            MainActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //保存到本地:用来展示扫描得到的内容
                	if(!mArray.contains(device)){
                	Log.e("onLeScan","===设备"+device.getName()+"="+device.getAddress()+"="+rssi);
                	mArray.add(device);
                	mBleAdapter.notifyDataSetChanged();
                	}
                }
            });
        }
    };
    
	//通知
	public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled){
		mGatt.setCharacteristicNotification(characteristic, enabled);
		BluetoothGattDescriptor clientConfig = characteristic.getDescriptor
					(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
		if (enabled){
			clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
		}else{
			clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
		}
		mGatt.writeDescriptor(clientConfig);
	}
    
    //数据通讯监听
    private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {//启动服务状态
                Log.e("======", "===开始启动服务:" + gatt.discoverServices());
            }
        };
        public void onServicesDiscovered(final BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS){//发现服务状态
                 Log.e("======", "===发现服务");
                 List<BluetoothGattService> services = mGatt.getServices();
                 for(final BluetoothGattService gattService:services) {
                	 List<BluetoothGattCharacteristic> characteristics = gattService.getCharacteristics();
                	 for (final BluetoothGattCharacteristic gattCharacteristic : characteristics) {
                			 if (gattCharacteristic.getUuid().toString().equals
                					 ("0000ffe1-0000-1000-8000-00805f9b34fb")){
                			 mGattCharacteristic=gattCharacteristic;
                			 mHandler.postDelayed(new Runnable(){
         						@Override
         						public void run()
         						{
         						gatt.readCharacteristic(gattCharacteristic);
         						}
         					}, 200);
                			 
                			 setCharacteristicNotification(gattCharacteristic,true);
                			 List<BluetoothGattDescriptor> descriptors = gattCharacteristic.getDescriptors();
                			 for (BluetoothGattDescriptor descriptor : descriptors)
                			 {
                				 gatt.readDescriptor(descriptor);
                			 }
                		 }
                	 }
                 }
             }
        };
        public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,
        			int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {//写入状态
                 Log.e("======", "===写入" +new String(characteristic.getValue()));
            }
        };
       public void onCharacteristicRead(BluetoothGatt gatt,final BluetoothGattCharacteristic characteristic,
    		   	   int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {//读取状态
            	Log.e("======","===读取" +new String(characteristic.getValue()));
            }
       }
      public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {
    		  	Log.e("======", "===获取数据" +new String(characteristic.getValue()));//获取数据
      };
    };

}
	/**
	 * 蓝牙限制20字节需将数据分包
	 * **/
	public int[] dataSeparate(int len)
	{   
		int[] lens = new int[2];
		lens[0]=len/20;
		lens[1]=len-20*lens[0];
		return lens;
	}
	/* 
	 * 发送按键的响应事件,主要发送文本框的数据
	 */
	@Override
	public void onClick(View v)
	{
		// TODO Auto-generated method stub
		byte[] buff = send_et.getText().toString().getBytes();
		int len = buff.length;
		int[] lens = dataSeparate(len);
		for(int i =0;i<lens[0];i++)
		{
		String str = new String(buff, 20*i, 20);
		mGattCharacteristic.setValue(str);//只能一次发送20字节,所以这里要分包发送
		//调用蓝牙服务的写特征值方法实现发送数据
		mBluetoothLeService.writeCharacteristic(mGattCharacteristic);
		}
		if(lens[1]!=0)
		{
			String str = new String(buff, 20*lens[0], lens[1]);
			mGattCharacteristic.setValue(str);
			//调用蓝牙服务的写特征值方法实现发送数据
			mBluetoothLeService.writeCharacteristic(mGattCharacteristic);
			
		}
	}

传统蓝牙:

1.打开蓝牙设备BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

mBluetoothAdapter.cancelDiscovery();
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);  
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery();//搜索附近蓝牙

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
  public void onReceive(Context context, Intent intent) {
  String action = intent.getAction();  
  if (BluetoothDevice.ACTION_FOUND.equals(action)){
  //找到设备时 通过EXTRA_DEVICE附加域来得到一个BluetoothDevice设备  
  BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  //信号强度  
  int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE); 
  }else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)){
  //蓝牙配对或取消配对时的状态
  }  
  }
};
device.connectGatt(act, false, new BluetoothGattCallback() {
 public void onConnectionStateChange(android.bluetooth.BluetoothGatt gatt, int status, int newState) {
 if(status == 0&&newState == 2) {
 gatt.discoverServices();//搜索蓝牙周围服务
 }else{
 //"搜索失败"
 }
 };
 public void onServicesDiscovered(android.bluetooth.BluetoothGatt gatt, int status) {
 if(status == BluetoothGatt.GATT_SUCCESS){
 Iterator var4 = gatt.getServices().iterator();
 while(var4.hasNext()) {
 BluetoothGattService var3;
 BluetoothGattCharacteristic var5;
 BluetoothGattService next = (BluetoothGattService)var4.next();
 if((var3 = next).getUuid().equals(UUID.fromString("0000180f-0000-1000-8000-00805f9b34fb")) 
  && (var5 = var3.getCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb"))) != null) {
 gatt.readCharacteristic(var5);
 //"获取电量中…"
 }
 }
 }
 };
 public void onCharacteristicRead(final android.bluetooth.BluetoothGatt gatt, final android.bluetooth.BluetoothGattCharacteristic characteristic, final in t status) {
 act.runOnUiThread(new Runnable() {
 @Override
 public void run() {
 if(characteristic!=null&&status == BluetoothGatt.GATT_SUCCESS){
 //characteristic.getIntValue(17, 0)+"%电量"
 gatt.close();
 }
 }
 });
 };
} );
/** 
 * 根据Rssi获得返回的距离,返回数据单位为m 
 * @param rssi 
 * @return 
 */  
public static double getDistance(int rssi){  
    int iRssi = Math.abs(rssi);  
    double power = (iRssi-A_Value)/(10*n_Value); //A_Value=59发射端和接收端相隔1米时的信号强度,n_Value=2.0环境衰减因子
    return Math.pow(10,power);  
}

2.蓝牙连接有两种方式,可直接配对

String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";     
UUID uuid = UUID.fromString(SPP_UUID); 
mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress);
BluetoothSocket socket= mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);//UUID连接!服务端为listenUsingRfcommWithServiceRecord("name",uuid)
mBluetoothAdapter.cancelDiscovery();  
socket.connect();
mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress);
Method m = mBluetoothDevice.getClass().getMethod(
		    		"createRfcommSocket", new Class[] { int.class });
BluetoothSocket socket = (BluetoothSocket) m.invoke(mBluetoothDevice, 1);//1-30端口连接!
mBluetoothAdapter.cancelDiscovery();  
socket.connect(); 
Method method = mBluetoothDevice.getClass().getMethod("createBond");//配对createBond/取消配对removeBond
Boolean returnValue = (Boolean) method.invoke(mBluetoothDevice);

3.蓝牙数据传输getInputStream getOutputStream

os = accept.getOutputStream();//输出流
os.write("连接成功success".getBytes());
is = socket.getInputStream();//输入流  
byte[] buffer=new byte[512];
int len=0;
ByteArrayBuffer bab = new ByteArrayBuffer(len);
while(-1!=(len=is.read(buffer))){
bab.append(buffer, 0, len);
}
String string = new String(bab.toByteArray(),"utf-8");

注意:BluetoothSocket的等耗时操作需要另外开启线程再进行!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值