藍芽開啟和搜尋並顯示在列表
阿新 • • 發佈:2019-01-03
開始第一天,著手這個專案的學習。
首先寫一個簡單的佈局檔案,包含三個按鈕,一個listView列表顯示搜尋到的藍芽
樣式如圖:
佈局檔案如下:
<?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"> <Button android:id="@+id/turn_on" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="turn on" android:textAllCaps="false"/> <Button android:id="@+id/turn_off" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="turn off" android:textAllCaps="false"/> <Button android:id="@+id/search_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="search" android:textAllCaps="false"/> <ListView android:id="@+id/search_result" android:layout_width="match_parent" android:layout_height="wrap_content"></ListView> </LinearLayout>
我將兩個功能的程式碼暫寫在MainActivity中,如下:
package com.example.hitmi.bluetoothtest; import android.Manifest; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Build; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; 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.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.Toast; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import static android.app.PendingIntent.getActivity; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1; private String TAG ="MainActivity"; IntentFilter intentFilter; ListView listView; private List<String> bluetoothList = new ArrayList<String>(); BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); ArrayAdapter<String> adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button turnOn = (Button)findViewById(R.id.turn_on); Button turnOff = (Button)findViewById(R.id.turn_off); Button search = (Button)findViewById(R.id.search_button); turnOn.setOnClickListener(this); turnOff.setOnClickListener(this); search.setOnClickListener(this); //安卓6以後使用藍芽要用定位許可權 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Android M Permission check if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION); } } //藍芽廣播註冊 registerBluetooth(); //listView佈局載入 adapter =new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,bluetoothList); listView = (ListView) findViewById(R.id.search_result); listView.setAdapter(adapter); //listView點選函式 listClick(); } //listView點選的實現 void listClick(){ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { } }); } //廣播註冊的實現 void registerBluetooth(){ // 設定廣播資訊過濾 intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothDevice.ACTION_FOUND); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //註冊廣播 registerReceiver(bluetoothReceiver, intentFilter); } //安卓6回撥(有bug) @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case PERMISSION_REQUEST_COARSE_LOCATION: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { Log.d(TAG,"回撥request"); //TODO request success/ } break; } } //button點選的實現 @Override public void onClick(View view){ switch (view.getId()){ case R.id.turn_on: { if(mBluetoothAdapter==null){ Toast.makeText(this,"當前裝置不支援藍芽功能",Toast.LENGTH_SHORT).show(); } if(!mBluetoothAdapter.isEnabled()){ /* Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivity(i);*/ mBluetoothAdapter.enable(); } //開啟被其它藍芽裝置發現的功能 if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); //設定為一直開啟 i.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120); startActivity(i); } } break; case R.id.turn_off: // break; case R.id.search_button: Log.d(TAG,"有點選search_button"); if (bluetoothList==null||!bluetoothList.isEmpty()) bluetoothList.clear(); //如果當前在搜尋,就先取消搜尋 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } //開啟搜尋 mBluetoothAdapter.startDiscovery(); break; default: break; } } //註冊銷燬 @Override protected void onDestroy(){ super.onDestroy(); unregisterReceiver(bluetoothReceiver); } //藍芽開始搜尋的回撥 private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.d(TAG,"有回撥"); if (action.equals(BluetoothDevice.ACTION_FOUND)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); //已匹配的裝置 if (device.getBondState() == BluetoothDevice.BOND_BONDED) { //此處的adapter是列表的adapter,不是BluetoothAdapter bluetoothList.add(device.getName()+":"+device.getAddress()+"(已配對裝置)"); adapter.notifyDataSetChanged(); }else { bluetoothList.add(device.getName()+":"+device.getAddress()+"(未配對裝置)"); adapter.notifyDataSetChanged(); } } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { Toast.makeText(MainActivity.this,"開始搜尋",Toast.LENGTH_SHORT).show(); } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { Toast.makeText(MainActivity.this,"搜尋完畢",Toast.LENGTH_SHORT).show(); } } }; }
網上類似的程式碼很多,我重點講兩個問題
1.安卓6.0以後藍芽使用許可權要加上定位許可權
在第一嘗試寫這個程式碼時,我copy的是網上有些年份的程式碼,沒有加入定位許可權,導致startDiscovery方法無法回撥BroadcastReceiver,使得搜尋功能一直無法實現。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Android M Permission check if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION); } }
這段程式碼是判斷手機是不是6.0以上,是則要開定位許可權
而我使用的的許可權有:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
2.listView列表重複新增
在startDiscovery方法回撥問題解決,listView能顯示出藍芽後我開開心心的蹦蹦跳跳的回家了。結果第二天一來一看,我去,重複添加了。這個時候我在搜尋按鈕的點選事件中判斷listView是否為空,不為空則清空再搜尋,程式碼如下:
if (bluetoothList==null||!bluetoothList.isEmpty())
bluetoothList.clear();
第一個功能寫出來,邁出第一步——2019.01.03
-----------------------------------------------分割線---------------------------------------------