我是Android应用程序的新手。我已经制作了BLE扫描器来检测BLE设备。我已经使用stopLeScan和startLeScan函数根据我正在遵循的教程对其进行编码。但是我无法检测到任何BLE设备。当我编码时,我发现这些功能现在已经过时了。是因为我使用过时的功能吗?还是我的代码中有其他问题?如果它已过时,请您告诉我如何对其进行修改以使其起作用? 仅供参考:我正在android pie上运行它。
我已经看过Android开发人员示例,不同的stackoverflow解决方案。我遵循的教程如下: https://github.com/kaviles/BLE_Tutorials/tree/master/Android/01
这是我的清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ble_scanner">
<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"/>
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
这是mainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
private final static String TAG = MainActivity.class.getSimpleName();
public static final int REQUEST_ENABLE_BT = 1;
private HashMap<String, BTLE_Device> mBTDevicesHashMap;
private ArrayList<BTLE_Device> mBTDevicesArrayList;
private ListAdapter_BTLE_Devices adapter;
private Button btn_Scan;
private BroadcastReceiver_BTState mBTStateUpdateReceiver;
private Scanner_BTLE mBTLeScanner;
private static final int LOCATION_REQUEST = 255;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
Utils.toast(getApplicationContext(),"BLE not supported");
finish();
}
mBTStateUpdateReceiver = new BroadcastReceiver_BTState(getApplicationContext());
mBTLeScanner = new Scanner_BTLE(this,15000,-150);
mBTDevicesHashMap = new HashMap<>();
mBTDevicesArrayList = new ArrayList<>();
adapter = new ListAdapter_BTLE_Devices(this, R.layout.btle_device_list_item, mBTDevicesArrayList);
ListView listView = new ListView(this);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
btn_Scan = (Button) findViewById(R.id.btn_scan);
((ScrollView)findViewById(R.id.device_list)).addView(listView);
findViewById(R.id.btn_scan).setOnClickListener(this);
}
@Override
protected void onStart(){
super.onStart();
registerReceiver(mBTStateUpdateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
@Override
protected void onResume(){
super.onResume();
}
@Override
protected void onPause(){
super.onPause();
stopScan();
}
protected void onStop(){
super.onStop();
unregisterReceiver(mBTStateUpdateReceiver);
stopScan();
}
@Override
protected void onDestroy(){
super.onDestroy();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == REQUEST_ENABLE_BT){
if (resultCode == RESULT_OK){
Utils.toast(getApplicationContext(),"Bluetooth is ready to use");
}
else if (resultCode == RESULT_CANCELED){
Utils.toast(getApplicationContext(),"Please turn on Bluetooth");
}
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Context context = view.getContext();
// stopScan();
//
// String name = mBTDevicesArrayList.get(position).getName();
// String address = mBTDevicesArrayList.get(position).getAddress();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_scan:
Utils.toast(getApplicationContext(),"Scan button pressed");
if(!mBTLeScanner.isScanning()){
startScan();
} else {
stopScan();
}
break;
default:
break;
}
}
public void addDevice(BluetoothDevice device, int rssi) {
String address = device.getAddress();
if(!mBTDevicesHashMap.containsKey(address)){
BTLE_Device btle_device = new BTLE_Device(device);
btle_device.setRssi(rssi);
mBTDevicesHashMap.put(address, btle_device);
mBTDevicesArrayList.add(btle_device);
} else {
mBTDevicesHashMap.get(address).setRssi(rssi);
}
adapter.notifyDataSetChanged();
}
public void startScan(){
btn_Scan.setText("Scanning...");
mBTDevicesArrayList.clear();
mBTDevicesHashMap.clear();
adapter.notifyDataSetChanged();
mBTLeScanner.start();
}
public void stopScan() {
btn_Scan.setText("Scan Again");
mBTLeScanner.stop();
}
@TargetApi(23)
private void verifyPermissionAndScan() {
if (ContextCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED) {
startScan();
} else {
requestPermissions(new String[] {ACCESS_COARSE_LOCATION}, LOCATION_REQUEST);
}
}
@Override
public void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults) {
if (requestCode != LOCATION_REQUEST) return;
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
startScan();
} else {
Toast.makeText(this, R.string.location_permission_toast, Toast.LENGTH_LONG).show();
}
}
}
这是带有适配器的Java类文件:
public class Scanner_BTLE {
private MainActivity ma;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private long scanPeriod;
private int signalStrength;
public Scanner_BTLE(MainActivity mainActivity, long scanPeriod, int signalStrength) {
ma = mainActivity;
mHandler = new Handler();
this.scanPeriod = scanPeriod;
this.signalStrength = signalStrength;
final BluetoothManager bluetoothManager = (BluetoothManager) ma.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}
public boolean isScanning() {
return mScanning;
}
public void start() {
if (!Utils.checkBluetooth(mBluetoothAdapter)) {
Utils.requestUserBluetooth(ma);
ma.stopScan();
} else {
scanLeDevice(true);
}
}
public void stop() {
scanLeDevice(false);
}
private void scanLeDevice(final boolean enable) {
if (enable && !mScanning) {
Utils.toast(ma.getApplication(), "Starting BLE scan...");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Utils.toast(ma.getApplicationContext(), "Stopping BLE scan...");
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
ma.stopScan();
}
}, scanPeriod);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
final int new_rssi = rssi;
if (rssi > signalStrength) {
mHandler.post(new Runnable() {
@Override
public void run() {
ma.addDevice(device, new_rssi);
}
});
}
}
};
}
其余文件均按照本教程中的说明进行操作。
这是我的主要XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:paddingTop="20dp"
android:paddingBottom="20dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:orientation="vertical"
tools:context=".MainActivity">
<ScrollView
android:id="@+id/device_list"
android:layout_width="match_parent"
android:layout_height="515dp"
android:fillViewport="true">
</ScrollView>
<Button
android:id="@+id/btn_scan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/start_scan" />
</LinearLayout>
这是我的设备列表信息XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="4"
android:textColor="@android:color/black"
android:id="@+id/tv_name"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@android:color/black" android:id="@+id/tv_rssi"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@android:color/black"
android:id="@+id/tv_macaddr"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
我没有看到任何错误消息。所以我有点困惑该怎么办,我做错了。