大家中秋快樂啊~~哈哈,今天繼續工程項目吧!
上篇我們已經實現了藍牙設備的掃描,本篇我們來通過list展示掃描到的設備並
實現點擊連接。
先貼出上篇的完整的MainActivity的方法:

package com.wbnq.shouhuan; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button saomiao , duanzhen , changzhen , buting , tingxia; private TextView jibu , dianliang , lianjiezhuangtai; BluetoothAdapter bluetoothAdapter; List<BluetoothDevice> deviceList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //藍牙管理,這是系統服務可以通過getSystemService(BLUETOOTH_SERVICE)的方法獲取實例 BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); //通過藍牙管理實例獲取適配器,然后通過掃描方法(scan)獲取設備(device) bluetoothAdapter = bluetoothManager.getAdapter(); } private void initView() { saomiao = (Button) findViewById(R.id.saomiao); duanzhen = (Button) findViewById(R.id.zhendong); changzhen = (Button) findViewById(R.id.changzhen); buting = (Button) findViewById(R.id.buting); tingxia = (Button) findViewById(R.id.tingxia); jibu = (TextView) findViewById(R.id.jibu); dianliang = (TextView) findViewById(R.id.dianliang); lianjiezhuangtai = (TextView) findViewById(R.id.lianjiezhuangtai); saomiao.setOnClickListener(this); duanzhen.setOnClickListener(this); changzhen.setOnClickListener(this); buting.setOnClickListener(this); tingxia.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.saomiao: //開始掃描前開啟藍牙 Intent turn_on = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(turn_on, 0); Toast.makeText(MainActivity.this, "藍牙已經開啟", Toast.LENGTH_SHORT).show(); Thread scanThread = new Thread(new Runnable() { @Override public void run() { Log.i("TAG", "run: saomiao ..."); saomiao(); } }); scanThread.start(); break; case R.id.zhendong: break; case R.id.changzhen: break; case R.id.buting: break; case R.id.tingxia: break; } } public void saomiao(){ deviceList.clear(); bluetoothAdapter.startLeScan(callback); } //掃描回調 public BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice bluetoothDevice, int i, byte[] bytes) { Log.i("TAG", "onLeScan: " + bluetoothDevice.getName() + "/t" + bluetoothDevice.getAddress() + "/t" + bluetoothDevice.getBondState()); //重復過濾方法,列表中包含不該設備才加入列表中,並刷新列表 if (!deviceList.contains(bluetoothDevice)) { //將設備加入列表數據中 deviceList.add(bluetoothDevice); } } }; }
這是上篇的,沒有在log下看到掃描消息的小伙伴看看出啥問題了吧~~
好了,第二篇正式開始。
先貼出來MyAdapter的代碼(這不是本節重點,請參閱前面關於adapter的寫法)

package com.wbnq.shouhuan; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.List; /** * Created by guwei on 16-9-2. */ public class MyAdapter extends BaseAdapter{ public List<BluetoothDevice> mlist; private LayoutInflater mInflater; public MyAdapter(Context context , List<BluetoothDevice> list){ mlist = list; mInflater = LayoutInflater.from(context); } //獲取傳入的數組大小 @Override public int getCount() { return mlist.size(); } //獲取第N條數據 @Override public Object getItem(int i) { return mlist.get(i); } //獲取item id @Override public long getItemId(int i) { return i; } //主要方法 @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHolder viewHolder = new ViewHolder(); if(view == null){ //首先為view綁定布局 view = mInflater.inflate(R.layout.devices_item , null); viewHolder.name = (TextView) view.findViewById(R.id.bluetoothname); viewHolder.uuid = (TextView) view.findViewById(R.id.uuid); viewHolder.status = (TextView) view.findViewById(R.id.status); view.setTag(viewHolder); }else{ viewHolder = (ViewHolder) view.getTag(); } BluetoothDevice bd = mlist.get(i); viewHolder.name.setText(bd.getName()); viewHolder.uuid.setText(bd.getAddress()); //viewHolder.status.setText(R.string.noconnect); return view; } class ViewHolder{ private TextView name , uuid , status; } }
item布局代碼 devices_item.xml

<?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"> <ImageView android:id="@+id/bluetoothicon" android:layout_width="37dp" android:layout_height="50dp" android:background="@mipmap/ic_bluetooth_black_36dp" /> <TextView android:id="@+id/bluetoothname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_toRightOf="@+id/bluetoothicon" android:text="name" android:textColor="#000000" android:textSize="19dp" /> <TextView android:id="@+id/uuid" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/bluetoothname" android:layout_marginLeft="5dp" android:layout_marginTop="5dp" android:layout_toRightOf="@id/bluetoothicon" android:text="uuid" android:textSize="15dp" /> <TextView android:id="@+id/status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="5dp" android:layout_toRightOf="@id/bluetoothname" android:text="" android:textColor="#ff0000" /> </RelativeLayout>
在布局文件中添加一下listview控件
並且在MainActivity添加監聽。
然后在掃描回調中添加list.setAdapter(new MyAdapter(MainActivity.this , deviceList));
就可以順利的將得到的列表用list展示出來啦~~
//掃描回調 public BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice bluetoothDevice, int i, byte[] bytes) { Log.i("TAG", "onLeScan: " + bluetoothDevice.getName() + "/t" + bluetoothDevice.getAddress() + "/t" + bluetoothDevice.getBondState()); //重復過濾方法,列表中包含不該設備才加入列表中,並刷新列表 if (!deviceList.contains(bluetoothDevice)) { //將設備加入列表數據中 deviceList.add(bluetoothDevice); list.setAdapter(new MyAdapter(MainActivity.this , deviceList)); } } };
看下效果:點擊掃描后
想要連接設備就要在list的監聽事件中添加下面的方法:
這里的bluetoothdevice就是用來存放每個item的內容的
上篇也說明了,想要連接設備就要使用bluetoothDevice的connectGatt方法:
該方法包含三個參數:
參數一 : context 上下文 這里傳 MainActivity即可
參數二: autoConnect 是否自動重連 一般填 false
參數三: gattcallback 是BluetoothGattCallback回調,該方法由系統提供,我們只需要重寫方法即可
該方法的返回值為bluetoothGatt類型。
//item 監聽事件 list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { bluetoothDevice = deviceList.get(i); //連接設備的方法,返回值為bluetoothgatt類型 bluetoothGatt = bluetoothDevice.connectGatt(MainActivity.this, false, gattcallback); lianjiezhuangtai.setText("連接" + bluetoothDevice.getName() + "中..."); } });
重寫gatt回調方法:
BluetoothGattCallback

private BluetoothGattCallback gattcallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicRead(gatt, characteristic, status); } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); } @Override public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorRead(gatt, descriptor, status); } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorWrite(gatt, descriptor, status); } @Override public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { super.onReliableWriteCompleted(gatt, status); } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { super.onReadRemoteRssi(gatt, rssi, status); } @Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { super.onMtuChanged(gatt, mtu, status); } } ;
我們這里主要用到
onConnectionStateChange
onServicesDiscovered
onCharacteristicWrite
首先通過onConnectionStateChange獲取連接的狀態:
public void onConnectionStateChange(BluetoothGatt gatt, int status, final int newState) { super.onConnectionStateChange(gatt, status, newState); runOnUiThread(new Runnable() { @Override public void run() { String status; switch (newState) { //已經連接 case BluetoothGatt.STATE_CONNECTED: lianjiezhuangtai.setText("已連接"); //該方法用於獲取設備的服務,尋找服務 //bluetoothGatt.discoverServices(); break; //正在連接 case BluetoothGatt.STATE_CONNECTING: lianjiezhuangtai.setText("正在連接"); break; //連接斷開 case BluetoothGatt.STATE_DISCONNECTED: lianjiezhuangtai.setText("已斷開"); break; //正在斷開 case BluetoothGatt.STATE_DISCONNECTING: lianjiezhuangtai.setText("斷開中"); break; } //pd.dismiss(); } }); }
參數中的 newstate就是連接的狀態。
連接狀態一共分成四種:
一: 已連接
二: 正在連接
三: 正在斷開
四: 已斷開
不過實際使用中正在連接和正在斷開的狀態並沒有真正的返回給我們的程序,
不過兩個狀態已經夠我們使用了~
連接狀態通過連接狀態的textview展示一下,我們現在快來看看效果吧~
整體代碼:
MainActivity.class:

package com.wbnq.shouhuan; 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.BluetoothManager; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button saomiao , duanzhen , changzhen , buting , tingxia; private TextView jibu , dianliang , lianjiezhuangtai; private ListView list; BluetoothAdapter bluetoothAdapter; BluetoothGatt bluetoothGatt; List<BluetoothDevice> deviceList = new ArrayList<>(); BluetoothDevice bluetoothDevice; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //藍牙管理,這是系統服務可以通過getSystemService(BLUETOOTH_SERVICE)的方法獲取實例 BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); //通過藍牙管理實例獲取適配器,然后通過掃描方法(scan)獲取設備(device) bluetoothAdapter = bluetoothManager.getAdapter(); } private void initView() { saomiao = (Button) findViewById(R.id.saomiao); duanzhen = (Button) findViewById(R.id.zhendong); changzhen = (Button) findViewById(R.id.changzhen); buting = (Button) findViewById(R.id.buting); tingxia = (Button) findViewById(R.id.tingxia); list = (ListView) findViewById(R.id.list); jibu = (TextView) findViewById(R.id.jibu); dianliang = (TextView) findViewById(R.id.dianliang); lianjiezhuangtai = (TextView) findViewById(R.id.lianjiezhuangtai); saomiao.setOnClickListener(this); duanzhen.setOnClickListener(this); changzhen.setOnClickListener(this); buting.setOnClickListener(this); tingxia.setOnClickListener(this); //item 監聽事件 list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { bluetoothDevice = deviceList.get(i); //連接設備的方法,返回值為bluetoothgatt類型 bluetoothGatt = bluetoothDevice.connectGatt(MainActivity.this, false, gattcallback); lianjiezhuangtai.setText("連接" + bluetoothDevice.getName() + "中..."); } }); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.saomiao: //開始掃描前開啟藍牙 Intent turn_on = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(turn_on, 0); Toast.makeText(MainActivity.this, "藍牙已經開啟", Toast.LENGTH_SHORT).show(); Thread scanThread = new Thread(new Runnable() { @Override public void run() { Log.i("TAG", "run: saomiao ..."); saomiao(); } }); scanThread.start(); break; case R.id.zhendong: break; case R.id.changzhen: break; case R.id.buting: break; case R.id.tingxia: break; case R.id.list: break; } } public void saomiao(){ deviceList.clear(); bluetoothAdapter.startLeScan(callback); } //掃描回調 public BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice bluetoothDevice, int i, byte[] bytes) { Log.i("TAG", "onLeScan: " + bluetoothDevice.getName() + "/t" + bluetoothDevice.getAddress() + "/t" + bluetoothDevice.getBondState()); //重復過濾方法,列表中包含不該設備才加入列表中,並刷新列表 if (!deviceList.contains(bluetoothDevice)) { //將設備加入列表數據中 deviceList.add(bluetoothDevice); list.setAdapter(new MyAdapter(MainActivity.this , deviceList)); } } }; private BluetoothGattCallback gattcallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, final int newState) { super.onConnectionStateChange(gatt, status, newState); runOnUiThread(new Runnable() { @Override public void run() { String status; switch (newState) { //已經連接 case BluetoothGatt.STATE_CONNECTED: lianjiezhuangtai.setText("已連接"); //該方法用於獲取設備的服務,尋找服務 bluetoothGatt.discoverServices(); break; //正在連接 case BluetoothGatt.STATE_CONNECTING: lianjiezhuangtai.setText("正在連接"); break; //連接斷開 case BluetoothGatt.STATE_DISCONNECTED: lianjiezhuangtai.setText("已斷開"); break; //正在斷開 case BluetoothGatt.STATE_DISCONNECTING: lianjiezhuangtai.setText("斷開中"); break; } //pd.dismiss(); } }); } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicRead(gatt, characteristic, status); } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); } @Override public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorRead(gatt, descriptor, status); } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorWrite(gatt, descriptor, status); } @Override public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { super.onReliableWriteCompleted(gatt, status); } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { super.onReadRemoteRssi(gatt, rssi, status); } @Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { super.onMtuChanged(gatt, mtu, status); } } ; }
實現效果:
好啦!!我們功能已經實現了一大部分了呢!!
下節我們就來獲取手環中
我走的步數 , 和電池的電量吧~~
大家加油啦~~~