我陷入了一个问题。我尝试了Stack Overflow和其他网站的一些提示。
我想编写一个应用程序,该应用程序搜索周围的所有蓝牙设备,如果找到了匹配的设备(以MAC地址作为参考,该应用程序将开始连接。)>
因此,我已经编写了一个测试应用程序以测试发现功能。但是不幸的是,在我的Android 10设备上启动发现过程存在一个大问题。我有一个较旧的Samsung S3 Mini,上面装有Android 4.1.2(SDK 16),我的代码可以正常工作。在Android 10设备上,startDiscovery()
返回false,与Android 4设备不同,后者返回true。他们在android开发人员页面上说,如果发生错误,则false为返回值。 BroadcastReceiver应该可以正常工作,因为Android 9手机上的应用程序检测到设置中已启动蓝牙搜索。问题仅在于startDiscovery()
函数(在我看来)。
我正在开始发现过程之前检查所有权限和蓝牙状态。但是我认为,它不能是书面代码,因为它可以在旧设备上完美运行。也许我缺少一些较新的设备。
正如Thomas Morris在下面解释的那样,在Android 10中,您需要由用户打开位置。在Android 9或更低版本中,Thomas Morris的回答是正确的,因为在29以下的所有SDK中,仅需要权限,而无需启用的位置服务。
是否有解决方案可以避免要求用户自行打开位置?
这是我的MainActivity:
public class MainActivity extends AppCompatActivity { final String TAG = "MainActivity"; BluetoothAdapter bluetoothAdapter; int status = 0; //0 = start discovering, 1 = cancel discovering public static final int REQUEST_ACCESS_COARSE_LOCATION = 1; public static final int REQUEST_ENABLE_BLUETOOTH = 11; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND)); registerReceiver(receiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED)); registerReceiver(receiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)); bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); checkBluetoothState(); final Button test = findViewById(R.id.testbutton); test.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(status == 0) { if(bluetoothAdapter != null && bluetoothAdapter.isEnabled()) { if (checkCoarseLocationPermission()) { Boolean result = bluetoothAdapter.startDiscovery(); //start discovering and show result of function Toast.makeText(getApplicationContext(), "Start discovery result: " + result, Toast.LENGTH_SHORT).show(); Log.d(TAG, "Start discovery: " + result); test.setText("Stop"); status = 1; } }else{ checkBluetoothState(); } }else{ Log.d(TAG,"Stop"); status = 0; bluetoothAdapter.cancelDiscovery(); test.setText("Start"); } } }); checkCoarseLocationPermission(); } private boolean checkCoarseLocationPermission() { //checks all needed permissions if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_ACCESS_COARSE_LOCATION); return false; }else{ return true; } } private void checkBluetoothState() { //checks if bluetooth is available and if it´s enabled or not if(bluetoothAdapter == null){ Toast.makeText(getApplicationContext(), "Bluetooth not available", Toast.LENGTH_SHORT).show(); }else{ if(bluetoothAdapter.isEnabled()){ if(bluetoothAdapter.isDiscovering()){ Toast.makeText(getApplicationContext(), "Device is discovering...", Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(getApplicationContext(), "Bluetooth is enabled", Toast.LENGTH_SHORT).show(); } }else{ Toast.makeText(getApplicationContext(), "You need to enabled bluetooth", Toast.LENGTH_SHORT).show(); Intent enabledIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enabledIntent, REQUEST_ENABLE_BLUETOOTH); } } } // Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address Log.d(TAG,"Device found: " + deviceName + "|" + deviceHardwareAddress); Toast.makeText(getApplicationContext(), "FOUND: " + deviceName + "|" + deviceHardwareAddress, Toast.LENGTH_SHORT).show(); } if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { //report user Log.d(TAG,"Started"); Toast.makeText(getApplicationContext(), "STARTED", Toast.LENGTH_SHORT).show(); } if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //change button back to "Start" status = 0; final Button test = findViewById(R.id.testbutton); test.setText("Start"); //report user Log.d(TAG,"Finished"); Toast.makeText(getApplicationContext(), "FINISHED", Toast.LENGTH_SHORT).show(); } if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)){ final int extra = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,-1); if(extra == (BluetoothAdapter.STATE_ON)) { if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } Boolean b = bluetoothAdapter.startDiscovery(); Toast.makeText(getApplicationContext(), "Start discovery" + b, Toast.LENGTH_SHORT).show(); } } } }; @Override protected void onDestroy() { super.onDestroy(); if (bluetoothAdapter.isDiscovering()){ bluetoothAdapter.cancelDiscovery(); } unregisterReceiver(receiver); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ super.onActivityResult(requestCode,resultCode,data); if(requestCode == REQUEST_ENABLE_BLUETOOTH){ checkBluetoothState(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){ super.onRequestPermissionsResult(requestCode,permissions,grantResults); switch (requestCode){ case REQUEST_ACCESS_COARSE_LOCATION: if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ Toast.makeText(getApplicationContext(),"Permission granted",Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(getApplicationContext(),"Permission denied",Toast.LENGTH_SHORT).show(); } } } }
这是我的清单:
<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>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
我陷入了一个问题。我尝试了Stack Overflow和其他网站的一些提示。我想编写一个应用程序,该应用程序搜索周围的所有蓝牙设备以及匹配的设备...
在应用程序上启用位置权限。为此,请转到: