原文:https://blog.csdn.net/qq_40511184/article/details/122698077
因為android studio升級,下面程式碼中的startactivityresult函式有變化 ,不能使用,需要更換為
public ActivityResultLauncher<Intent> register;
ActivityResultLauncher<Intent> startBlueTooth = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>()
- 首先在app/src/main/AndroidManifest.xml中新增許可權
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.btapp"> <!-- 先前的藍芽許可權需求--> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- 安卓12新增的藍芽許可權--> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- 定位許可權, 藍芽搜尋需要--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.BTapp"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
- Acitivity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/button3" android:layout_width="0dp" android:layout_height="wrap_content" android:text="是否支援藍芽" app:layout_constraintEnd_toStartOf="@+id/guideline2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/button4" android:layout_width="0dp" android:layout_height="wrap_content" android:text="當前藍芽狀態" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@+id/guideline2" app:layout_constraintTop_toTopOf="parent" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_begin="205dp" /> <Button android:id="@+id/button7" android:layout_width="0dp" android:layout_height="wrap_content" android:text="開啟藍芽" app:layout_constraintEnd_toStartOf="@+id/guideline2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button3" /> <Button android:id="@+id/button8" android:layout_width="0dp" android:layout_height="wrap_content" android:text="關閉藍芽" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@+id/guideline2" app:layout_constraintTop_toBottomOf="@+id/button4" /> <Button android:id="@+id/button9" android:layout_width="0dp" android:layout_height="wrap_content" android:text="使藍芽可見" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button7" /> <Button android:id="@+id/button10" android:layout_width="0dp" android:layout_height="wrap_content" android:text="搜尋可見藍芽" app:layout_constraintEnd_toStartOf="@+id/guideline2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button9" /> <Button android:id="@+id/button11" android:layout_width="0dp" android:layout_height="wrap_content" android:text="檢視已繫結藍芽" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@+id/guideline2" app:layout_constraintTop_toBottomOf="@+id/button9" /> <ListView android:id="@+id/listview1" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" /> <TextView android:id="@+id/textView" android:layout_width="0dp" android:layout_height="wrap_content" android:background="#00BCD4" android:gravity="center" android:text="藍芽列表" android:textSize="24sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button10" /> </androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.example.btapp; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; 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.os.Build; 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.TextView; import android.widget.Toast; import java.lang.reflect.Method; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { // 常量 private static final int REQ_PERMISSION_CODE = 1; // 例項化藍芽控制器 public BlueToothController btController = new BlueToothController(); // 彈窗 private Toast mToast; // 藍芽許可權列表 public ArrayList<String> requestList = new ArrayList<>(); // 搜尋藍芽廣播 private IntentFilter foundFilter; // public ArrayAdapter adapter1; //定義一個列表,存藍芽裝置的地址。 public ArrayList<String> arrayList=new ArrayList<>(); //定義一個列表,存藍芽裝置地址,用於顯示。 public ArrayList<String> deviceName=new ArrayList<>(); // 藍芽狀態改變廣播 private BroadcastReceiver receiver = new BroadcastReceiver(){ @Override public void onReceive(Context context, Intent intent) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); switch (state){ case BluetoothAdapter.STATE_OFF: showToast("STATE_OFF"); break; case BluetoothAdapter.STATE_ON: showToast("STATE_ON"); break; case BluetoothAdapter.STATE_TURNING_OFF: showToast("STATE_TURNING_OFF"); break; case BluetoothAdapter.STATE_TURNING_ON: showToast("STATE_TURNING_ON"); break; default: showToast("UnKnow STATE"); unregisterReceiver(this); break; } } }; // 搜尋藍芽廣播 private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { String s; BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device.getBondState() == 12) { s = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:已配對" + "\n"; } else if (device.getBondState() == 10){ s = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:未配對" +"\n"; }else{ s = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:未知" + "\n"; } if (!deviceName.contains(s)) { deviceName.add(s);//將搜尋到的藍芽名稱和地址新增到列表。 arrayList.add(device.getAddress());//將搜尋到的藍芽地址新增到列表。 adapter1.notifyDataSetChanged();//更新 } }else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){ showToast("搜尋結束"); unregisterReceiver(this); }else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){ showToast("開始搜尋"); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 藍芽狀態改變資訊 IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); // 註冊廣播 registerReceiver(receiver, filter); //搜尋藍芽的廣播 foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); // 獲取ListView元件 ListView listView = (ListView) findViewById(R.id.listview1); // 例項化ArrayAdapter物件 adapter1 = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, deviceName); // 新增到ListView元件中 listView.setAdapter(adapter1); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { CharSequence content = ((TextView) view).getText(); String con = content.toString(); String[] conArray = con.split("\n"); String rightStr = conArray[1].substring(5, conArray[1].length()); BluetoothDevice device = btController.find_device(rightStr); if (device.getBondState() == 10) { btController.cancelSearch(); String s = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:未配對" + "\n"; deviceName.remove(s); device.createBond(); s = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:已配對" + "\n"; deviceName.add(s); adapter1.notifyDataSetChanged(); showToast("配對:" + device.getName()); } else{ btController.cancelSearch(); String s2 = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:已配對" + "\n"; if(deviceName.contains(s2)) { unpairDevice(device); deviceName.remove(s2); s2 = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:未配對" +"\n"; deviceName.add(s2); adapter1.notifyDataSetChanged(); showToast("取消配對:" + device.getName()); } } } }); // 透過id獲取“是否支援藍芽”按鈕 Button button_1 = (Button) findViewById(R.id.button3); // 繫結按鈕點選事件處理函式 button_1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 獲取藍芽許可權 getPermision(); // 判斷是否支援藍芽 boolean ret = btController.isSupportBlueTooth(); // 彈窗顯示結果 showToast("是否支援藍芽" + ret); } }); // 透過id獲取“當前藍芽狀態”按鈕 Button button_2 = (Button) findViewById(R.id.button4); // 繫結按鈕點選事件處理函式 button_2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 獲取藍芽許可權 getPermision(); // 判斷當前藍芽狀態 boolean ret = btController.getBlueToothStatus(); // 彈窗顯示結果 showToast("當前藍芽狀態:" + ret); } }); // 透過id獲取"開啟藍芽"按鈕 Button button_3 = (Button) findViewById(R.id.button7); // 繫結按鈕點選事件處理函式 button_3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { turnONbt(); } }); // 透過id獲取”關閉藍芽“按鈕 Button button_4 = (Button) findViewById(R.id.button8); // 繫結按鈕點選事件處理函式 button_4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 獲取藍芽許可權 getPermision(); // 關閉藍芽 btController.turnOffBlueTooth(); } }); // 透過id獲取”使藍芽可見“按鈕 Button button_5 = (Button) findViewById(R.id.button9); // 繫結按鈕點選事件處理函式 button_5.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 藍芽可見 BTVisible(); } }); // 透過id獲取”搜尋可見藍芽“按鈕 Button button_6 = (Button) findViewById(R.id.button10); // 繫結按鈕點選事件處理函式 button_6.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 獲取藍芽許可權 getPermision(); // 註冊廣播 registerReceiver(bluetoothReceiver, foundFilter); // 初始化各列表 arrayList.clear(); deviceName.clear(); adapter1.notifyDataSetChanged(); // 開始搜尋 btController.findDevice(); } }); // 透過id獲取”檢視已繫結藍芽“按鈕 Button button_7 = (Button) findViewById(R.id.button11); // 繫結按鈕點選事件處理函式 button_7.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 獲取藍芽許可權 getPermision(); // 初始化各列表 deviceName.clear(); arrayList.clear(); adapter1.notifyDataSetChanged(); // 獲取已繫結藍芽 ArrayList<BluetoothDevice> bluetoothDevices = btController.getBondedDeviceList(); // 更新列表 for (int i = 0; i < bluetoothDevices.size(); i++){ BluetoothDevice device = bluetoothDevices.get(i); arrayList.add(device.getAddress()); if (device.getBondState() == 12) { deviceName.add("裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:已配對" + "\n"); } else if (device.getBondState() == 10){ deviceName.add("裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:未配對" +"\n"); }else{ deviceName.add("裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:未知" + "\n"); } adapter1.notifyDataSetChanged(); } } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ super.onActivityResult(requestCode, resultCode, data); if(resultCode == RESULT_OK){ showToast("open successfully"); } else{ showToast("open unsuccessfully"); } } /** * 嘗試取消配對 * @param device */ private void unpairDevice(BluetoothDevice device) { try { Method m = device.getClass() .getMethod("removeBond", (Class[]) null); m.invoke(device, (Object[]) null); } catch (Exception e) { e.printStackTrace(); } } /** * 開啟藍芽 */ public void turnONbt(){ // 獲取藍芽許可權 getPermision(); // 開啟藍芽 btController.turnOnBlueTooth(this,1); } /** * 設定藍芽可見 */ public void BTVisible(){ // 獲取藍芽許可權 getPermision(); // 開啟藍芽可見 btController.enableVisibly(this); } /** * 動態申請許可權 */ public void getPermision(){ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){ requestList.add(Manifest.permission.BLUETOOTH_SCAN); requestList.add(Manifest.permission.BLUETOOTH_ADVERTISE); requestList.add(Manifest.permission.BLUETOOTH_CONNECT); requestList.add(Manifest.permission.ACCESS_FINE_LOCATION); requestList.add(Manifest.permission.ACCESS_COARSE_LOCATION); requestList.add(Manifest.permission.BLUETOOTH); } if(requestList.size() != 0){ ActivityCompat.requestPermissions(this, requestList.toArray(new String[0]), REQ_PERMISSION_CODE); } } /** * Toast彈窗顯示 * @param text 顯示文字 */ public void showToast(String text){ // 若Toast控制元件未初始化 if( mToast == null){ // 則初始化 mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT); } // 否則 else{ // 修改顯示文字 mToast.setText(text); } // 顯示 mToast.show(); } }
list_item.xml
<?xml version="1.0" encoding="UTF-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:textSize="18sp" > </TextView>
BlueToothController.java
package com.example.btapp; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.Toast; import java.lang.reflect.Method; import java.util.ArrayList; /** * 藍芽介面卡 */ public class BlueToothController { // 成員變數 private BluetoothSocket btSocket; private BluetoothAdapter mAdapter; private String TAG = ""; public static final int RECV_VIEW = 0; public static final int NOTICE_VIEW = 1; /** * 建構函式 */ public BlueToothController(){ // 獲取本地的藍芽介面卡 mAdapter = BluetoothAdapter.getDefaultAdapter(); } /** * 是否支援藍芽 * @return true支援,false不支援 */ public boolean isSupportBlueTooth(){ // 若支援藍芽,則本地介面卡不為null if(mAdapter != null){ return true; } // 否則不支援 else{ return false; } } /** * 判斷當前藍芽狀態 * @return true為開啟,false為關閉 */ public boolean getBlueToothStatus(){ // 斷言?為了避免mAdapter為null導致return出錯 assert (mAdapter != null); // 藍芽狀態 return mAdapter.isEnabled(); } /** * 開啟藍芽 */ public void turnOnBlueTooth(Activity activity, int requestCode){ if(!mAdapter.isEnabled()) { Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); activity.startActivityForResult(intent, requestCode); } } /** * 關閉藍芽 * @return */ public void turnOffBlueTooth() { if(mAdapter.isEnabled()) { mAdapter.disable(); } } /** * 開啟藍芽可見性 * @param context */ public void enableVisibly(Context context){ Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); context.startActivity(discoverableIntent); } /** * 查詢裝置 */ public boolean findDevice(){ assert(mAdapter!=null); if(mAdapter.isDiscovering()){ mAdapter.cancelDiscovery(); return false; }else { return mAdapter.startDiscovery(); } } /** * 獲取繫結裝置 * @return */ public ArrayList<BluetoothDevice> getBondedDeviceList(){ return new ArrayList<BluetoothDevice>(mAdapter.getBondedDevices()); } /** * 根據藍芽地址找到相應的裝置 * @param addr * @return */ public BluetoothDevice find_device(String addr){ return mAdapter.getRemoteDevice(addr); } /** * 連線裝置 */ public void connect_init(BluetoothDevice device){ mAdapter.cancelDiscovery(); try{ Method clientMethod = device.getClass().getMethod("createRfcommSocketToServiceRecord", new Class[]{int.class}); btSocket = (BluetoothSocket)clientMethod.invoke(device, 1); connect(btSocket); }catch (Exception e){ e.printStackTrace(); } } public void connect(final BluetoothSocket btSocket){ try { if (btSocket.isConnected()){ Log.e(TAG, "connect: 已經連線"); return; } btSocket.connect(); if (btSocket.isConnected()){ Log.e(TAG, "connect: 連線成功"); }else{ Log.e(TAG, "connect: 連線失敗"); btSocket.close(); } }catch (Exception e){e.printStackTrace();} } public void cancelSearch() { mAdapter.cancelDiscovery(); } }
ListView的列表點選事件
- 新增點選監聽
@Override protected void onCreate(Bundle savedInstanceState) { listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { CharSequence content = ((TextView) view).getText(); String con = content.toString(); String[] conArray = con.split("\n"); String rightStr = conArray[1].substring(5, conArray[1].length()); BluetoothDevice device = btController.find_device(rightStr); if (device.getBondState() == 10) { btController.cancelSearch(); String s = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:未配對" + "\n"; deviceName.remove(s); device.createBond(); s = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:已配對" + "\n"; deviceName.add(s); adapter1.notifyDataSetChanged(); showToast("配對:" + device.getName()); } else{ btController.cancelSearch(); String s2 = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:已配對" + "\n"; if(deviceName.contains(s2)) { unpairDevice(device); deviceName.remove(s2); s2 = "裝置名:" + device.getName() + "\n" + "裝置地址:" + device.getAddress() + "\n" + "連線狀態:未配對" +"\n"; deviceName.add(s2); adapter1.notifyDataSetChanged(); showToast("取消配對:" + device.getName()); } } } }); } /** * 嘗試取消配對 * @param device */ private void unpairDevice(BluetoothDevice device) { try { Method m = device.getClass() .getMethod("removeBond", (Class[]) null); m.invoke(device, (Object[]) null); } catch (Exception e) { e.printStackTrace(); } }