java - 蓝牙 LE 扫描仪没有结果
问题描述
我有这个问题:我正在为 LE 设备创建一个蓝牙扫描仪应用程序,以便扫描 ESP32 设备。该应用程序运行良好,但在某些设备(如我自己的设备)中,扫描仪没有给出任何结果。不用着急,因为我可以在我父亲的手机上测试它,它基本上已经完成了。问题是它是多么令人沮丧,特别是不知道原因。
这是扫描活动:
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.res.ResourcesCompat;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
import java.util.Objects;
public class ScanActivity extends AppCompatActivity implements ResultsListAdapter.OnResultClickListener {
private final static int REQUEST_ENABLE_BT = 69;
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
private static final int SIGNAL_STRENGTH = -75;
private static boolean scanning = false;
private ConstraintLayout parent;
private RecyclerView recyclerView;
private FloatingActionButton startScanButton, stopScanButton;
private ArrayList<ScanResult> results = new ArrayList<>();
private ArrayList<BluetoothDevice> devices = new ArrayList<>();
private BluetoothManager btManager;
private BluetoothAdapter btAdapter;
private BluetoothLeScanner btScanner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
getWindow().setStatusBarColor(ResourcesCompat.getColor(getResources(), R.color.colorAccentDark, null));
parent = findViewById(R.id.parent_activity_scan);
recyclerView = findViewById(R.id.scanner_recycler_view);
startScanButton = findViewById(R.id.start_scan_button);
stopScanButton = findViewById(R.id.stop_scan_button);
initRecyclerView();
startScanButton.setOnClickListener(v -> {
start();
});
stopScanButton.setOnClickListener(v -> {
stop();
});
btManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = Objects.requireNonNull(btManager).getAdapter();
btScanner = btAdapter.getBluetoothLeScanner();
if (btAdapter != null && !btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.coarse_location_access_title);
builder.setMessage(R.string.coarse_location_access_message);
builder.setPositiveButton(R.string.concede, null);
builder.setOnDismissListener(dialog -> requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION));
builder.show();
}
}
private void start() {
if (btAdapter != null && !btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
stop();
} else {
startScanButton.setVisibility(View.INVISIBLE);
stopScanButton.setVisibility(View.VISIBLE);
devices.clear();
results.clear();
recyclerView.getAdapter().notifyDataSetChanged();
scan(true);
}
}
private void stop() {
btScanner.stopScan(leScanCallback);
}
private void scan(final boolean enable) {
if (enable && !scanning) {
Handler handler = new Handler();
final Runnable runnable = () -> {
scanning = false;
Snackbar.make(parent, "Encontrados " + results.size() + " dispotivos.", BaseTransientBottomBar.LENGTH_LONG)
.setAction("", null)
.setBackgroundTint(ResourcesCompat.getColor(ScanActivity.this.getResources(), R.color.colorAccentDark, null))
.show();
startScanButton.setVisibility(View.VISIBLE);
stopScanButton.setVisibility(View.INVISIBLE);
AsyncTask.execute(() -> btScanner.stopScan(leScanCallback));
};
handler.postDelayed(runnable, 7500);
scanning = true;
btScanner.startScan(leScanCallback);
} else {
scanning = false;
btScanner.stopScan(leScanCallback);
}
}
private void initRecyclerView() {
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ResultsListAdapter adapter = new ResultsListAdapter(results, this);
recyclerView.setAdapter(adapter);
}
private final ScanCallback leScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
if (!devices.contains(result.getDevice()) && result.getRssi() > SIGNAL_STRENGTH) {
new Handler().post(() -> {
if (result.getDevice().getAddress().startsWith("A4:CF:12")) {
results.add(result);
devices.add(result.getDevice());
recyclerView.getAdapter().notifyDataSetChanged();
}
});
}
}
};
@Override
public void onResultClick(int position) {
BluetoothDevice device = results.get(position).getDevice();
DialogFragment dialogFragment = new ConfirmActionDialog();
Bundle args = new Bundle();
args.putString("confirm_action_dialog_message",
"¿Conectar con el dispositivo con dirección " + device.getAddress() + "?");
args.putInt("type", ConfirmActionDialog.CONNECTION_CODE);
args.putParcelable("object", device);
dialogFragment.setArguments(args);
dialogFragment.show(getSupportFragmentManager(), "Confirm connection");
}
@Override
public void onResultInfoClick(int position) {
DialogFragment dialogFragment = new InfoDialog();
Bundle args = new Bundle();
args.putParcelable("object", results.get(position).getDevice());
dialogFragment.setArguments(args);
dialogFragment.show(getSupportFragmentManager(), "InfoDialog");
}
}
如您所见,我请求位置和蓝牙权限。任何想法?
PS:
我的应用程序转到 min sdk 27 (Android 8.1)。我的设备是装有 Android 10 的小米米 9T。它在小米米 A2、Android 9&10 上也没有给出任何结果(最近更新了)。完美运行的设备是三星 Galaxy J7 (Android 9) 和小米 Mi 8 Pro (Android 9)
解决方案
你应该onScanFailed
在你的ScanCallback
. 它可能会为您提供扫描无法正常工作的原因。
推荐阅读
- c++ - 我可以只映射一个文件并修改它而不回写吗?
- python - 需要从另一个 txt 文件在现有 txt 文件中创建一个新列
- r - 如何根据多列值(重复值和字符串值)从 tibble 中删除行
- c# - WPF:仅更改 ListBox 中最后一项的 CornerRadius
- javascript - 根据单选按钮和复选框选择显示不同的文本
- c - scanf和gets有什么区别?
- websocket - 为什么我的 Socket.IO 服务器没有响应我的 Firecamp 和 C# 客户端?
- python - 如何在 Apache 服务器上托管 Dash 应用程序?
- c# - 如何使用 Powershell 在 Windows 10 上处理 LogonHours 属性?
- virtual-machine - 如何实现像 virtualbox 这样的虚拟化应用程序?