单片机与手机应用进行蓝牙通讯
生活随笔
收集整理的這篇文章主要介紹了
单片机与手机应用进行蓝牙通讯
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
單片機連接手機應用客戶端進行藍牙通訊:
學習了!!!!分享:
package com.severn;import java.util.ArrayList;import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast;import com.severn.ui.Ble_Activity;/*** @Description: TODO<MainActivity類實現打開藍牙、掃描藍牙>*/ public class MainActivity extends Activity implements OnClickListener {// 掃描藍牙按鈕private Button scan_btn;// 藍牙適配器BluetoothAdapter mBluetoothAdapter;// 藍牙信號強度private ArrayList<Integer> rssis;// 自定義AdapterLeDeviceListAdapter mleDeviceListAdapter;// listview顯示掃描到的藍牙信息ListView lv;// 描述掃描藍牙的狀態private boolean mScanning;private boolean scan_flag;private Handler mHandler;int REQUEST_ENABLE_BT = 1;// 藍牙掃描時間private static final long SCAN_PERIOD = 10000;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 初始化控件init();// 初始化藍牙init_ble();scan_flag = true;// 自定義適配器mleDeviceListAdapter = new LeDeviceListAdapter();// 為listview指定適配器lv.setAdapter(mleDeviceListAdapter);/* listview點擊函數 */lv.setOnItemClickListener(new AdapterView.OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> arg0, View v, int position,long id){// TODO Auto-generated method stubfinal BluetoothDevice device = mleDeviceListAdapter.getDevice(position);if (device == null)return;final Intent intent = new Intent(MainActivity.this,Ble_Activity.class);intent.putExtra(Ble_Activity.EXTRAS_DEVICE_NAME,device.getName());intent.putExtra(Ble_Activity.EXTRAS_DEVICE_ADDRESS,device.getAddress());if (mScanning){/* 停止掃描設備 */mBluetoothAdapter.stopLeScan(mLeScanCallback);mScanning = false;}try{// 啟動Ble_ActivitystartActivity(intent);} catch (Exception e){e.printStackTrace();// TODO: handle exception}}});}/*** @Title: init* @Description: TODO(初始化UI控件)* @return void* @throws*/private void init(){scan_btn = this.findViewById(R.id.scan_dev_btn);scan_btn.setOnClickListener(this);lv = this.findViewById(R.id.lv);mHandler = new Handler();}/*** @Title: init_ble* @Description: TODO(初始化藍牙)* @return void* @throws*/private void init_ble(){// 手機硬件支持藍牙if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){Toast.makeText(this, "不支持BLE", Toast.LENGTH_SHORT).show();finish();}// Initializes Bluetooth adapter.// 獲取手機本地的藍牙適配器final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);mBluetoothAdapter = bluetoothManager.getAdapter();// 打開藍牙權限if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()){Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}}/** 按鈕響應事件*/@Overridepublic void onClick(View v){// TODO Auto-generated method stubif (scan_flag){mleDeviceListAdapter = new LeDeviceListAdapter();lv.setAdapter(mleDeviceListAdapter);scanLeDevice(true);} else{scanLeDevice(false);scan_btn.setText("掃描設備");}}/*** @Title: scanLeDevice* @Description: TODO(掃描藍牙設備 )* @param enable* (掃描使能,true:掃描開始,false:掃描停止)* @return void* @throws*/private void scanLeDevice(final boolean enable){if (enable){// Stops scanning after a pre-defined scan period.mHandler.postDelayed(new Runnable(){@Overridepublic void run(){mScanning = false;scan_flag = true;scan_btn.setText("掃描設備");Log.i("SCAN", "stop.....................");mBluetoothAdapter.stopLeScan(mLeScanCallback);}}, SCAN_PERIOD);/* 開始掃描藍牙設備,帶mLeScanCallback 回調函數 */Log.i("SCAN", "begin.....................");mScanning = true;scan_flag = false;scan_btn.setText("停止掃描");mBluetoothAdapter.startLeScan(mLeScanCallback);} else{Log.i("Stop", "stoping................");mScanning = false;mBluetoothAdapter.stopLeScan(mLeScanCallback);scan_flag = true;}}/*** 藍牙掃描回調函數 實現掃描藍牙設備,回調藍牙BluetoothDevice,可以獲取name MAC等信息* * **/private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback(){@Overridepublic void onLeScan(final BluetoothDevice device, final int rssi,byte[] scanRecord){// TODO Auto-generated method stubrunOnUiThread(new Runnable(){@Overridepublic void run(){/* 講掃描到設備的信息輸出到listview的適配器 */mleDeviceListAdapter.addDevice(device);mleDeviceListAdapter.notifyDataSetChanged();}});}};/*** @Description: TODO<自定義適配器Adapter,作為listview的適配器>* @version: V1.0*/private class LeDeviceListAdapter extends BaseAdapter {private ArrayList<BluetoothDevice> mLeDevices;private LayoutInflater mInflator;public LeDeviceListAdapter(){super();//rssis = new ArrayList();mLeDevices = new ArrayList();mInflator = getLayoutInflater();}public void addDevice(BluetoothDevice device){if (!mLeDevices.contains(device)){mLeDevices.add(device);}}public BluetoothDevice getDevice(int position){return mLeDevices.get(position);}public void clear(){mLeDevices.clear();rssis.clear();}@Overridepublic int getCount(){return mLeDevices.size();}@Overridepublic Object getItem(int i){return mLeDevices.get(i);}@Overridepublic long getItemId(int i){return i;}/*** 重寫getview* * **/@Overridepublic View getView(int i, View view, ViewGroup viewGroup){// General ListView optimization code.// 加載listview每一項的視圖view = mInflator.inflate(R.layout.listitem, null);// 初始化三個textview顯示藍牙信息//TextView deviceAddress = view// .findViewById(R.id.tv_deviceAddr);TextView deviceName = view.findViewById(R.id.tv_deviceName);//TextView rssi =view.findViewById(R.id.tv_rssi);BluetoothDevice device = mLeDevices.get(i);//deviceAddress.setText(device.getAddress());deviceName.setText(device.getName());//rssi.setText("" + rssis.get(i));return view;}}}main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="${relativePackage}.${activityClass}" ><Button android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="20dip"android:layout_marginRight="20dip"android:layout_marginTop="30dip"android:text="掃描設備"android:id="@+id/scan_dev_btn"/><ListViewandroid:id="@+id/lv"android:layout_marginTop="100dip"android:layout_marginLeft="20dip"android:layout_marginRight="20dip"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginBottom="50dip" > </ListView></RelativeLayout>listyview.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" android:background="@drawable/bg_button"><LinearLayoutandroid:layout_width="match_parent"android:background="#00BA79"android:layout_height="wrap_content" ><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#ffffff"android:textSize="25dp"android:text="設備名稱:" /><TextViewandroid:id="@+id/tv_deviceName"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#ffffff"android:textSize="25dp"android:text="TextView" /></LinearLayout></LinearLayout>Ble_activity
package com.severn.ui;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import com.severn.service.*; import android.app.Activity; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ScrollView; import android.widget.TextView;import com.severn.R; import com.severn.service.BluetoothLeService;/** * @Description: TODO<Ble_Activity實現連接BLE,發送和接受BLE的數據> */ public class Ble_Activity extends Activity implements OnClickListener {private final static String TAG = Ble_Activity.class.getSimpleName();//藍牙4.0的UUID,其中0000ffe1-0000-1000-8000-00805f9b34fb是廣州匯承信息科技有限公司08藍牙模塊的UUIDpublic static String HEART_RATE_MEASUREMENT = "0000ffe1-0000-1000-8000-00805f9b34fb";public static String EXTRAS_DEVICE_NAME = "DEVICE_NAME";;public static String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";public static String EXTRAS_DEVICE_RSSI = "RSSI";//藍牙連接狀態private boolean mConnected = false;private String status = "disconnected";//藍牙名字private String mDeviceName;//藍牙地址private String mDeviceAddress;//藍牙信號值private String mRssi;private Bundle b;private String rev_str = "";//藍牙service,負責后臺的藍牙服務private static BluetoothLeService mBluetoothLeService;//文本框,顯示接受的內容private TextView rev_tv, connect_state;//發送按鈕private Button send_btn;//文本編輯框private EditText send_et;private ScrollView rev_sv;private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();//藍牙特征值private static BluetoothGattCharacteristic target_chara = null;private Handler mhandler = new Handler();private Handler myHandler = new Handler(){// 2.重寫消息處理函數public void handleMessage(Message msg){switch (msg.what){// 判斷發送的消息case 1:{// 更新ViewString state = msg.getData().getString("connect_state");connect_state.setText(state);break;}}super.handleMessage(msg);}};@Overrideprotected void onCreate(Bundle savedInstanceState){// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.ble_activity);b = getIntent().getExtras();//從意圖獲取顯示的藍牙信息mDeviceName = b.getString(EXTRAS_DEVICE_NAME);mDeviceAddress = b.getString(EXTRAS_DEVICE_ADDRESS);//mRssi = b.getString(EXTRAS_DEVICE_RSSI);/* 啟動藍牙service */Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);init();}@Overrideprotected void onDestroy(){super.onDestroy();//解除廣播接收器unregisterReceiver(mGattUpdateReceiver);mBluetoothLeService = null;}// Activity出來時候,綁定廣播接收器,監聽藍牙連接服務傳過來的事件@Overrideprotected void onResume(){super.onResume();//綁定廣播接收器registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());if (mBluetoothLeService != null){ //根據藍牙地址,建立連接final boolean result = mBluetoothLeService.connect(mDeviceAddress);Log.d(TAG, "Connect request result=" + result);}}/** * @Title: init * @Description: TODO(初始化UI控件) * @param 無* @return void * @throws */ private void init(){rev_sv = (ScrollView) this.findViewById(R.id.rev_sv);rev_tv = (TextView) this.findViewById(R.id.rev_tv);connect_state = (TextView) this.findViewById(R.id.connect_state);send_btn = (Button) this.findViewById(R.id.send_btn);send_et = (EditText) this.findViewById(R.id.send_et);connect_state.setText(status);send_btn.setOnClickListener(this);}/* BluetoothLeService綁定的回調函數 */private final ServiceConnection mServiceConnection = new ServiceConnection(){@Overridepublic void onServiceConnected(ComponentName componentName,IBinder service){mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();if (!mBluetoothLeService.initialize()){Log.e(TAG, "Unable to initialize Bluetooth");finish();}// 根據藍牙地址,連接設備mBluetoothLeService.connect(mDeviceAddress);}@Overridepublic void onServiceDisconnected(ComponentName componentName){mBluetoothLeService = null;}};/*** 廣播接收器,負責接收BluetoothLeService類發送的數據*/private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver(){@Overridepublic void onReceive(Context context, Intent intent){final String action = intent.getAction();if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))//Gatt連接成功{mConnected = true;status = "connected";//更新連接狀態updateConnectionState(status);System.out.println("BroadcastReceiver :" + "device connected");} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED//Gatt連接失敗.equals(action)){mConnected = false;status = "disconnected";//更新連接狀態updateConnectionState(status);System.out.println("BroadcastReceiver :"+ "device disconnected");} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED//發現GATT服務器.equals(action)){// Show all the supported services and characteristics on the// user interface.//獲取設備的所有藍牙服務displayGattServices(mBluetoothLeService.getSupportedGattServices());System.out.println("BroadcastReceiver :"+ "device SERVICES_DISCOVERED");} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action))//有效數據{ //處理發送過來的數據displayData(intent.getExtras().getString(BluetoothLeService.EXTRA_DATA));System.out.println("BroadcastReceiver onData:"+ intent.getStringExtra(BluetoothLeService.EXTRA_DATA));}}};/* 更新連接狀態 */private void updateConnectionState(String status){Message msg = new Message();msg.what = 1;Bundle b = new Bundle();b.putString("connect_state", status);msg.setData(b);//將連接狀態更新的UI的textview上myHandler.sendMessage(msg);System.out.println("connect_state:" + status);}/* 意圖過濾器 */private static IntentFilter makeGattUpdateIntentFilter(){final IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);return intentFilter;}/** * @Title: displayData * @Description: TODO(接收到的數據在scrollview上顯示) * @param @param rev_string(接受的數據)* @return void * @throws */ private void displayData(String rev_string){rev_str += rev_string;runOnUiThread(new Runnable(){@Overridepublic void run(){rev_tv.setText(rev_str);rev_sv.scrollTo(0, rev_tv.getMeasuredHeight());System.out.println("rev:" + rev_str);}});}/** * @Title: displayGattServices * @Description: TODO(處理藍牙服務) * @param 無 * @return void * @throws */ private void displayGattServices(List<BluetoothGattService> gattServices){if (gattServices == null)return;String uuid = null;// 服務數據,可擴展下拉列表的第一級數據ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();// 特征數據(隸屬于某一級服務下面的特征值集合)ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>();// 部分層次,所有特征值集合mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();// Loops through available GATT Services.for (BluetoothGattService gattService : gattServices){// 獲取服務列表HashMap<String, String> currentServiceData = new HashMap<String, String>();uuid = gattService.getUuid().toString();// 查表,根據該uuid獲取對應的服務名稱。SampleGattAttributes這個表需要自定義。gattServiceData.add(currentServiceData);System.out.println("Service uuid:" + uuid);ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<HashMap<String, String>>();// 從當前循環所指向的服務中讀取特征值列表List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>();// Loops through available Characteristics.// 對于當前循環所指向的服務中的每一個特征值for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics){charas.add(gattCharacteristic);HashMap<String, String> currentCharaData = new HashMap<String, String>();uuid = gattCharacteristic.getUuid().toString();if (gattCharacteristic.getUuid().toString().equals(HEART_RATE_MEASUREMENT)){// 測試讀取當前Characteristic數據,會觸發mOnDataAvailable.onCharacteristicRead()mhandler.postDelayed(new Runnable(){@Overridepublic void run(){// TODO Auto-generated method stubmBluetoothLeService.readCharacteristic(gattCharacteristic);}}, 200);// 接受Characteristic被寫的通知,收到藍牙模塊的數據后會觸發mOnDataAvailable.onCharacteristicWrite()mBluetoothLeService.setCharacteristicNotification(gattCharacteristic, true);target_chara = gattCharacteristic;// 設置數據內容// 往藍牙模塊寫入數據// mBluetoothLeService.writeCharacteristic(gattCharacteristic);}List<BluetoothGattDescriptor> descriptors = gattCharacteristic.getDescriptors();for (BluetoothGattDescriptor descriptor : descriptors){System.out.println("---descriptor UUID:"+ descriptor.getUuid());// 獲取特征值的描述mBluetoothLeService.getCharacteristicDescriptor(descriptor);// mBluetoothLeService.setCharacteristicNotification(gattCharacteristic,// true);}gattCharacteristicGroupData.add(currentCharaData);}// 按先后順序,分層次放入特征值集合中,只有特征值mGattCharacteristics.add(charas);// 構件第二級擴展列表(服務下面的特征值)gattCharacteristicData.add(gattCharacteristicGroupData);}}/*** 將數據分包* * **/public int[] dataSeparate(int len){ int[] lens = new int[2];lens[0]=len/20;lens[1]=len-20*lens[0];return lens;}/* * 發送按鍵的響應事件,主要發送文本框的數據*/@Overridepublic void onClick(View v){// TODO Auto-generated method stubbyte[] 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);target_chara.setValue(str);//只能一次發送20字節,所以這里要分包發送//調用藍牙服務的寫特征值方法實現發送數據mBluetoothLeService.writeCharacteristic(target_chara);}if(lens[1]!=0){String str = new String(buff, 20*lens[0], lens[1]);target_chara.setValue(str);//調用藍牙服務的寫特征值方法實現發送數據mBluetoothLeService.writeCharacteristic(target_chara);}}}ble_activity.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><LinearLayout android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="狀態:"android:layout_marginLeft="10dip"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/connect_state"/></LinearLayout><ScrollViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:id="@+id/rev_sv"><TextView android:layout_width="fill_parent"android:layout_height="wrap_content"android:id="@+id/rev_tv"/></ScrollView><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:orientation="horizontal" ><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:id="@+id/send_et"android:typeface="normal" ></EditText><Buttonandroid:id="@+id/send_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="3"android:text="send" /></LinearLayout></LinearLayout>BluetoothLeService.class
package com.severn.service;import java.util.ArrayList; import java.util.List; import java.util.UUID;import android.app.Service; 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.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.hardware.Sensor; import android.os.Binder; import android.os.IBinder; import android.util.Log;/** * @Description: TODO<藍牙服務,負責在后臺實現藍牙的連接,數據的發送接受> */ public class BluetoothLeService extends Service {private final static String TAG = "BluetoothLeService";// luetoothLeService.class.getSimpleName();private List<Sensor> mEnabledSensors = new ArrayList<Sensor>();//藍牙相關類private BluetoothManager mBluetoothManager;private BluetoothAdapter mBluetoothAdapter;private String mBluetoothDeviceAddress;private BluetoothGatt mBluetoothGatt;private int mConnectionState = STATE_DISCONNECTED;private static final int STATE_DISCONNECTED = 0;private static final int STATE_CONNECTING = 1;private static final int STATE_CONNECTED = 2;public final static String ACTION_GATT_CONNECTED = "com.hc_ble.bluetooth.le.ACTION_GATT_CONNECTED";public final static String ACTION_GATT_DISCONNECTED = "com.hc_ble.bluetooth.le.ACTION_GATT_DISCONNECTED";public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.hc_ble.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";public final static String ACTION_DATA_AVAILABLE = "com.hc_ble.bluetooth.le.ACTION_DATA_AVAILABLE";public final static String EXTRA_DATA = "com.hc_ble.bluetooth.le.EXTRA_DATA";// public final static UUID UUID_HEART_RATE_MEASUREMENT =zzzzzzzzzzzzz// UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);private OnDataAvailableListener mOnDataAvailableListener;// Implements callback methods for GATT events that the app cares about. For// example,// connection change and services discovered.public interface OnDataAvailableListener {public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status);public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic);public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic);}public void setOnDataAvailableListener(OnDataAvailableListener l){mOnDataAvailableListener = l;}/* 連接遠程設備的回調函數 */private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback(){@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status,int newState){String intentAction;if (newState == BluetoothProfile.STATE_CONNECTED)//連接成功{intentAction = ACTION_GATT_CONNECTED;mConnectionState = STATE_CONNECTED;/* 通過廣播更新連接狀態 */broadcastUpdate(intentAction);Log.i(TAG, "Connected to GATT server.");// Attempts to discover services after successful connection.Log.i(TAG, "Attempting to start service discovery:"+ mBluetoothGatt.discoverServices());} else if (newState == BluetoothProfile.STATE_DISCONNECTED)//連接失敗{intentAction = ACTION_GATT_DISCONNECTED;mConnectionState = STATE_DISCONNECTED;Log.i(TAG, "Disconnected from GATT server.");broadcastUpdate(intentAction);}}/** 重寫onServicesDiscovered,發現藍牙服務* * */@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status){if (status == BluetoothGatt.GATT_SUCCESS)//發現到服務{broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);Log.i(TAG, "--onServicesDiscovered called--");} else{Log.w(TAG, "onServicesDiscovered received: " + status);System.out.println("onServicesDiscovered received: " + status);}}/** 特征值的讀寫* */@Overridepublic void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status){if (status == BluetoothGatt.GATT_SUCCESS){Log.i(TAG, "--onCharacteristicRead called--");//從特征值讀取數據byte[] sucString = characteristic.getValue();String string = new String(sucString);//將數據通過廣播到Ble_ActivitybroadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);}}/** 特征值的改變* */@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic){broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);}/** 特征值的寫* */@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status){// 以下語句實現 發送完數據或也顯示到界面上//broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);}/** 讀描述值* */@Overridepublic void onDescriptorRead(BluetoothGatt gatt,BluetoothGattDescriptor descriptor, int status){// TODO Auto-generated method stub// super.onDescriptorRead(gatt, descriptor, status);Log.w(TAG, "----onDescriptorRead status: " + status);byte[] desc = descriptor.getValue();if (desc != null){Log.w(TAG, "----onDescriptorRead value: " + new String(desc));}}/** 寫描述值* */@Overridepublic void onDescriptorWrite(BluetoothGatt gatt,BluetoothGattDescriptor descriptor, int status){// TODO Auto-generated method stub// super.onDescriptorWrite(gatt, descriptor, status);Log.w(TAG, "--onDescriptorWrite--: " + status);}/** 讀寫藍牙信號值* */@Overridepublic void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status){// TODO Auto-generated method stub// super.onReadRemoteRssi(gatt, rssi, status);Log.w(TAG, "--onReadRemoteRssi--: " + status);broadcastUpdate(ACTION_DATA_AVAILABLE, rssi);}@Overridepublic void onReliableWriteCompleted(BluetoothGatt gatt, int status){// TODO Auto-generated method stub// super.onReliableWriteCompleted(gatt, status);Log.w(TAG, "--onReliableWriteCompleted--: " + status);}};//廣播意圖private void broadcastUpdate(final String action, int rssi){final Intent intent = new Intent(action);intent.putExtra(EXTRA_DATA, String.valueOf(rssi));sendBroadcast(intent);}//廣播意圖private void broadcastUpdate(final String action){final Intent intent = new Intent(action);sendBroadcast(intent);}/* 廣播遠程發送過來的數據 */public void broadcastUpdate(final String action,final BluetoothGattCharacteristic characteristic){final Intent intent = new Intent(action);//從特征值獲取數據final byte[] data = characteristic.getValue();if (data != null && data.length > 0){final StringBuilder stringBuilder = new StringBuilder(data.length);for (byte byteChar : data){stringBuilder.append(String.format("%02X ", byteChar));Log.i(TAG, "***broadcastUpdate: byteChar = " + byteChar);}intent.putExtra(EXTRA_DATA, new String(data));System.out.println("broadcastUpdate for read data:"+ new String(data));}sendBroadcast(intent);}public class LocalBinder extends Binder {public BluetoothLeService getService(){return BluetoothLeService.this;}}@Overridepublic IBinder onBind(Intent intent){return mBinder;}@Overridepublic boolean onUnbind(Intent intent){close();return super.onUnbind(intent);}private final IBinder mBinder = new LocalBinder();/*** Initializes a reference to the local Bluetooth adapter.* * @return Return true if the initialization is successful.*//* service 中藍牙初始化 */public boolean initialize(){// For API level 18 and above, get a reference to BluetoothAdapter// through// BluetoothManager.if (mBluetoothManager == null){ //獲取系統的藍牙管理器mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);if (mBluetoothManager == null){Log.e(TAG, "Unable to initialize BluetoothManager.");return false;}}mBluetoothAdapter = mBluetoothManager.getAdapter();if (mBluetoothAdapter == null){Log.e(TAG, "Unable to obtain a BluetoothAdapter.");return false;}return true;}/*** Connects to the GATT server hosted on the Bluetooth LE device.* * @param address* The device address of the destination device.* * @return Return true if the connection is initiated successfully. The* connection result is reported asynchronously through the* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}* callback.*/// 連接遠程藍牙public boolean connect(final String address){if (mBluetoothAdapter == null || address == null){Log.w(TAG,"BluetoothAdapter not initialized or unspecified address.");return false;}// Previously connected device. Try to reconnect.if (mBluetoothDeviceAddress != null&& address.equals(mBluetoothDeviceAddress)&& mBluetoothGatt != null){Log.d(TAG,"Trying to use an existing mBluetoothGatt for connection.");if (mBluetoothGatt.connect())//連接藍牙,其實就是調用BluetoothGatt的連接方法{mConnectionState = STATE_CONNECTING;return true;} else{return false;}}/* 獲取遠端的藍牙設備 */final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);if (device == null){Log.w(TAG, "Device not found. Unable to connect.");return false;}// We want to directly connect to the device, so we are setting the// autoConnect// parameter to false./* 調用device中的connectGatt連接到遠程設備 */mBluetoothGatt = device.connectGatt(this, false, mGattCallback);Log.d(TAG, "Trying to create a new connection.");mBluetoothDeviceAddress = address;mConnectionState = STATE_CONNECTING;System.out.println("device.getBondState==" + device.getBondState());return true;}/*** Disconnects an existing connection or cancel a pending connection. The* disconnection result is reported asynchronously through the* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}* callback.*//** 取消連接* * *//** * @Title: disconnect * @Description: TODO(取消藍牙連接) * @param 無* @return void * @throws */ public void disconnect(){if (mBluetoothAdapter == null || mBluetoothGatt == null){Log.w(TAG, "BluetoothAdapter not initialized");return;}mBluetoothGatt.disconnect();}/*** After using a given BLE device, the app must call this method to ensure* resources are released properly.*//** * @Title: close * @Description: TODO(關閉所有藍牙連接) * @param 無* @return void * @throws */ public void close(){if (mBluetoothGatt == null){return;}mBluetoothGatt.close();mBluetoothGatt = null;}/*** Request a read on a given {@code BluetoothGattCharacteristic}. The read* result is reported asynchronously through the* {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}* callback.* * @param characteristic* The characteristic to read from.*//** * @Title: readCharacteristic * @Description: TODO(讀取特征值) * @param @param characteristic(要讀的特征值)* @return void 返回類型 * @throws */ public void readCharacteristic(BluetoothGattCharacteristic characteristic){if (mBluetoothAdapter == null || mBluetoothGatt == null){Log.w(TAG, "BluetoothAdapter not initialized");return;}mBluetoothGatt.readCharacteristic(characteristic);}// 寫入特征值public void writeCharacteristic(BluetoothGattCharacteristic characteristic){if (mBluetoothAdapter == null || mBluetoothGatt == null){Log.w(TAG, "BluetoothAdapter not initialized");return;}mBluetoothGatt.writeCharacteristic(characteristic);}// 讀取RSSipublic void readRssi(){if (mBluetoothAdapter == null || mBluetoothGatt == null){Log.w(TAG, "BluetoothAdapter not initialized");return;}mBluetoothGatt.readRemoteRssi();}/*** Enables or disables notification on a give characteristic.* * @param characteristic* Characteristic to act on.* @param enabled* If true, enable notification. False otherwise.*//** * @Title: setCharacteristicNotification * @Description: TODO(設置特征值通變化通知) * @param @param characteristic(特征值)* @param @param enabled (使能) * @return void * @throws */ public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled){if (mBluetoothAdapter == null || mBluetoothGatt == null){Log.w(TAG, "BluetoothAdapter not initialized");return;}mBluetoothGatt.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);}mBluetoothGatt.writeDescriptor(clientConfig);}/** * @Title: getCharacteristicDescriptor * @Description: TODO(得到特征值下的描述值) * @param @param 無* @return void * @throws */ public void getCharacteristicDescriptor(BluetoothGattDescriptor descriptor){if (mBluetoothAdapter == null || mBluetoothGatt == null){Log.w(TAG, "BluetoothAdapter not initialized");return;}mBluetoothGatt.readDescriptor(descriptor);}/*** Retrieves a list of supported GATT services on the connected device. This* should be invoked only after {@code BluetoothGatt#discoverServices()}* completes successfully.* * @return A {@code List} of supported services.*//** * @Title: getSupportedGattServices * @Description: TODO(得到藍牙的所有服務) * @param @return 無* @return List<BluetoothGattService> * @throws */ public List<BluetoothGattService> getSupportedGattServices(){if (mBluetoothGatt == null)return null;return mBluetoothGatt.getServices();}}Androidmainfest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.severn"android:versionCode="1"android:versionName="1.2" ><uses-permission android:name="android.permission.BLUETOOTH"/><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/><uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/><applicationandroid:allowBackup="true"android:icon="@drawable/hc"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name=".MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name=".ui.Ble_Activity"></activity><service android:name="com.huicheng.service.BluetoothLeService" android:enabled="true"></service></application></manifest>總結
以上是生活随笔為你收集整理的单片机与手机应用进行蓝牙通讯的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SAP 自动记账 零星记录
- 下一篇: 根据标注点坐标范围计算显示缩放级别zoo