1. 程式人生 > >藍芽開啟和搜尋並顯示在列表

藍芽開啟和搜尋並顯示在列表

開始第一天,著手這個專案的學習。

首先寫一個簡單的佈局檔案,包含三個按鈕,一個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

-----------------------------------------------分割線---------------------------------------------