【发布时间】:2021-08-10 16:19:00
【问题描述】:
(免责声明:ANDROID STUDIO 的超级新手)我正在创建一个应用程序来扫描 ble 设备并将它们显示在列表中,但似乎没有发现任何设备并显示在列表视图中。任何帮助表示赞赏。我打算用找到的设备数量来更新 Textview。我还没有设置扫描过滤器,因为我仍在尝试找出我正在使用的标签的 UUID。我还将 min sdk 更改为 23,因为它在设置扫描模式、回调和匹配模式时给了我一个错误。
MainActivity.java
package com.example.tygatraxseconddraft;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
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.os.Bundle;
import android.os.ParcelUuid;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "TWESBTSCANNER";
public static final int REQUEST_ACCESS_COARSE_LOCATION = 1;
public static final int REQUEST_ENABLE_BLUETOOTH = 11;
private ListView listView;
private Button scanningBtn;
private BluetoothAdapter bluetoothAdapter;
private final ArrayList<String> mDeviceList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.device_list);
scanningBtn = findViewById(R.id.scanning_btn);
hasPermissions();
checkBluetoothState();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
listView = findViewById(R.id.device_list);
scanningBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();
final ScanCallback scanCallback = new ScanCallback() { //studio made it not private
@Override
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice device = result.getDevice();
// ...do whatever you want with this found device
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
// Ignore for now
}
@Override
public void onScanFailed(int errorCode) {
// Ignore for now
}
};
UUID SERVICE_DATA_UUID = UUID.fromString("00005246-0000-1000-8000-00805f9b34fb");//filter for the Nordic tags
UUID[] serviceUUIDs = new UUID[]{SERVICE_DATA_UUID};
List<ScanFilter> filters = null;
if (serviceUUIDs != null) {
filters = new ArrayList<>();
for (UUID serviceUUID : serviceUUIDs) {
ScanFilter filter = new ScanFilter.Builder()
.setServiceUuid(new ParcelUuid(serviceUUID))
.build();
filters.add(filter);
}
}
ScanSettings scanSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
.setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
.setReportDelay(0L)
.build();
if (scanner != null) {
scanner.startScan(null, scanSettings, scanCallback); // must set scan settings first
Log.d(TAG, "scan started");
} else {
Log.e(TAG, "could not get scanner object");
}
}
});
}
@Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
public final BroadcastReceiver mReceiver = new BroadcastReceiver() { //
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDeviceList.add(device.getName() + "\n" + device.getAddress());
Log.i("BT", device.getName() + "\n" + device.getAddress());
listView.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, mDeviceList));
}
}
};
private boolean hasPermissions() { //checks and asks for location permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (getApplicationContext().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[] { Manifest.permission.ACCESS_COARSE_LOCATION }, REQUEST_ACCESS_COARSE_LOCATION);
return false;
}
}
return true;
}
//ENABLE WHEN TESTING ON PHONE
private void checkBluetoothState() {
//gets the bluetooth adapter
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(bluetoothAdapter.isEnabled()){
Toast.makeText(this,"Bluetooth is enabled", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Please turn on Bluetooth", Toast.LENGTH_SHORT).show();
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BLUETOOTH);
}//requests permission if bluetooth is not enabled
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tygatraxseconddraft">
<!-- Request legacy Bluetooth permissions on older devices. -->
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!-- Needed only if your app looks for Bluetooth devices.
You must add an attribute to this permission, or declare the
ACCESS_FINE_LOCATION permission, depending on the results when you
check location usage in your app. -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<!-- Needed only if your app makes the device discoverable to Bluetooth
devices. -->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<!-- Needed only if your app communicates with already-paired Bluetooth
devices. -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION_LOCATION"/>
<!--Makes the app show up for only ble enabled devices-->
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true"/>
<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.TygaTraxsecondDraft">
<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>
Activity_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"
android:background="@color/white"
tools:context=".MainActivity">
<TextView
android:id="@+id/number_devices"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="@string/number_of_devices"
android:textColor="@color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/scanning_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="50dp"
android:text="@string/button_text"
android:textColor="#212121"
app:backgroundTint="@color/gray"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" />
<ListView
android:id="@+id/device_list"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="24dp"
app:layout_constraintBottom_toTopOf="@+id/scanning_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/number_devices" />
</androidx.constraintlayout.widget.ConstraintLayout>
如果需要的话 colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="gray">#7393B3</color>
</resources>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Tyga Trax (second draft)</string>
<string name="button_text">Scan</string>
<string name="number_of_devices">There are </string>
</resources>
【问题讨论】:
-
我看到您已经考虑过请求权限,但是您附近真的有 BLE 设备吗?请先使用通用 BLE 扫描仪应用程序(例如 nRF Connect)进行检查。请同时添加 manifest.xml,它丢失了
-
您的应用的目标 sdk 是什么?更高版本的权限要求更改
-
@MichaelKotzjan 我查看了
build.gradle文件,上面写着23:android { compileSdk 31 defaultConfig { applicationId "com.example.tygatraxseconddraft" minSdk 23 targetSdk 31 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" }
标签: java android bluetooth bluetooth-lowenergy