代码:
我使用以下代码从here获取目标API级别23(以及最低API级别18)。
private final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action))
{
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceNameTextView.setText(bluetoothDevice.getName());
}
}
};
在按下按钮的事件中,我打电话:
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery(); // was initialized successsfully
我的AndroidManifest.xml包含:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
设备:
事实:
有什么问题?
更新1: 由于可能必须在运行时请求API级别23权限。伊维特向我指出了这一点,谢谢!不幸的是,它没有解决我的问题。
与她的理论有关的是:
mBluetoothAdapter.startDiscovery()
返回true,表示成功(请参阅here)。
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity , Manifest.permission.BLUETOOTH_ADMIN);
if(permissionCheck == PackageManager.PERMISSION_GRANTED)
Log.i("info", "Permission granted!");
else
Log.i("info", "Permission not granted!");
使用BLUETOOTH_ADMIN
和BLUETOOTH
运行此代码会同时返回:
获得许可!
答案 0 :(得分:4)
在进行一些研究时,我在官方文档中找到了有关Android 6.0(API级别23)更改的following article。
通过访问附近外部设备的硬件标识符 蓝牙和Wi-Fi扫描,您的应用程序现在必须具有 ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限:
- WifiManager.getScanResults()
- BluetoothDevice.ACTION_FOUND
- BluetoothLeScanner.startScan()
因此,我一直缺少权限ACCESS_FINE_LOCATION
和ACCESS_COARSE_LOCATION
。但仅仅在 AndroidManifest.xml 文件中添加它们是不够的。你必须像Yvette建议的那样在运行时请求这些权限。
您可以找到here如何做到这一点,或者只使用我编写的这段代码来获取蓝牙发现所需的权限。
final int CODE = 5; // app defined constant used for onRequestPermissionsResult
String[] permissionsToRequest =
{
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.BLUETOOTH,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
};
boolean allPermissionsGranted = true;
for(String permission : permissionsToRequest)
{
allPermissionsGranted = allPermissionsGranted && (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED);
}
if(!allPermissionsGranted)
{
ActivityCompat.requestPermissions(this, permissionsToRequest, CODE);
}
mBluetoothAdapter.startDiscovery();
此代码假设用户授予权限(为简单起见)。如果您希望应用程序在未授予权限时表现不同,请参阅&#34;处理权限请求响应&#34;在此article。
答案 1 :(得分:1)
听起来你并没有为sdk 23及更高版本管理runtime permissions。 sdk为23的手机将静默忽略任何需要运行时权限或崩溃的请求。
另请参阅文档System Permissions。
如果您的应用在其清单中列出了正常权限(即,不会对用户的隐私或设备的操作造成太大风险的权限),系统会自动授予这些权限。如果您的应用在其清单中列出了危险权限(即可能会影响用户隐私或设备正常运行的权限),系统会要求用户明确授予这些权限。 Android发出请求的方式取决于系统版本以及应用所针对的系统版本:
如果设备运行的是Android 6.0(API级别23)或更高版本,并且应用程序的targetSdkVersion为23或更高,则应用程序会在运行时请求用户的权限。用户可以随时撤消权限,因此应用程序需要在每次运行时检查其是否具有权限。有关在应用程序中请求权限的详细信息,请参阅“使用系统权限”培训指南。 如果设备运行的是Android 5.1(API级别22)或更低版本,或者应用程序的targetSdkVersion为22或更低,系统会要求用户在用户安装应用程序时授予权限。如果您向应用程序的更新版本添加新权限,系统会要求用户在用户更新应用程序时授予该权限。用户安装应用程序后,他们撤销权限的唯一方法是卸载应用程序。 通常,权限失败会导致SecurityException被抛回应用程序。但是,并不能保证无处不在。例如,sendBroadcast(Intent)方法在方法调用返回后将数据传递给每个接收者时检查权限,因此如果存在权限失败,您将不会收到异常。但是,几乎在所有情况下,都会在系统日志中打印权限失败。
Android系统提供的权限可以在Manifest.permission中找到。任何应用程序也可以定义和强制执行自己的权限,因此这不是所有可能权限的综合列表。
在此期间,可能会在多个地方强制执行特定许可 你的程序的操作:
在致电系统时,要阻止申请 执行某些功能。
开始活动时,要防止 启动其他应用程序活动的应用程序。
这两个 发送和接收广播,控制谁可以接收你的 广播或谁可以发送广播给你。
访问和时 在内容提供商上运营。
绑定或启动服务。
至于应用程序崩溃:
Everything every Android Developer must know about new Android's Runtime Permission
现在你头脑中的下一个问题。我的申请会崩溃吗?
通过Android团队从神发出的这种善意。当我们调用一个需要在targetSdkVersion小于23的应用程序上撤销权限用户的函数时,不会抛出任何异常。相反,它只是什么都不做。对于返回值的函数,它将返回null或0,具体取决于大小写。
但不要太高兴。虽然应用程序不会因调用函数而崩溃。它可能仍然可以从该应用程序下一步返回的值中崩溃。
这些答案中的更多详情Require dangerous permissions during installation When asking for runtime permission for location
答案 2 :(得分:0)
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.BLUETOOTH)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.BLUETOOTH)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.BLUETOOTH},
MY_PERMISSIONS_REQUEST_BLUETOOTH // this variable should be a unique int identifier of your chosing);
// MY_PERMISSIONS_REQUEST_BLUETOOTH is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
您的活动应实施onRequestPermissionsResult
方法
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
您可以对BLUETOOTH_ADMIN
权限