我正在编写一个应用程序,该应用程序的唯一功能是充当低功耗蓝牙的接收器。如果用户不允许BLE,则该应用程序无用。首次启动该应用程序时,我希望它向用户询问位置权限(因为Android要求BLE使用它)。我打开了权限对话框,但在用户阅读对话框时,应用程序的其余部分继续,启动BLEScanner等。我希望应用程序在用户阅读对话框并决定要做什么时暂停。这是我的设置:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}
//More UI preparation stuff
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
}
}
}
其中的“ PermissionDialog”是一个不同的类,该类使用DialogFragment解释为什么应用程序需要该权限,然后关闭/重新启动该应用程序。在这种情况下,该应用程序的其余部分将继续,在用户仍在阅读弹出的权限对话框的同时尝试做蓝牙工作!天真的,我认为我可以使用同步锁来做到这一点,如下所示,但是在这种情况下,永远不会调用回调:
private final Object initLock = new Object();
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}
Log.i("Lock", "At the lock!");
try {
synchronized (initLock) {
initLock.wait();
}
}
catch (InterruptedException e) {
//TODO find out what to do here
}
Log.i("Lock", "Past the lock!");
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
synchronized (initLock){
initLock.notify();
}
}
else{
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
}
}
}
}
执行此操作的正确方法是什么?我有一些想法,但它们都涉及范围。我是否需要制作另一个继承AppCompatActivity的类来获得权限并将其称为线程?但是,我怎么知道onRequestPermissionResult回调会去哪里呢?我很茫然。
答案 0 :(得分:1)
将//More UI preparation stuff
中的代码放入新方法。授予权限后,说“ init()
”
private void init(){
//More UI preparation stuff
}
然后在onCreate
内,如果已经授予许可,则调用init();
,否则请求许可。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
} else {
init();
}
}
现在在onRequestPermissionsResult
内部处理用户的响应-如果用户已授权,则初始化UI,否则阻止功能和/或将问题通知用户。
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
init();
} else{
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
}
}
}
}
PS:出于相同的目的,我准备了一个库,该库使此过程更加容易。看看my library.
答案 1 :(得分:0)
您可以使用EasyPermissions并实现EasyPermissions.PermissionCallbacks来解决它。
并在要运行的方法之前添加此注释:@AfterPermissionGranted
例如:
AfterPermissionGranted(PERMISSION_REQUESTCODE_BASE)
private void requestPerminssions(){
if(EasyPermissions.hasPermissions(this,PERMISSIONS)){
int hasCityData=config.getInt("isDataEmpty",0);
if(hasCityData==0){
new CountryInfoThread().execute();
}else {
new LocalPositionThread().execute();
}
}
}
答案 2 :(得分:0)
我最终使用了一个私有变量:
private boolean readyToStart = false;
通过这种方式:
@Override
protected void onCreate(Bundle savedInstanceState) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}
else{
readyToStart = true;
}
}
@Override
protected void onResume() {
super.onResume();
if (readyToStart) {
startBluetooth();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[],
int[] grantResults) {
Log.i("Permission", "Callback made");
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
else{
startBluetooth();
}
}
}
}
}