在运行时如何检查权限而不抛出SecurityException?

103

我设计了一个函数,它可以从SD卡获取/设置资源,如果在SD卡中找不到,就从Asset中获取,如果可能的话,将Asset写回SD卡。
通过调用方法,此函数可以检查SD卡是否已挂载并可访问...

boolean bSDisAvalaible = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);

我的设计函数可能会在一个应用程序(项目)中被另一个应用程序使用,无论是否具有android.permission.WRITE_EXTERNAL_STORAGE权限。

然后我想检查当前应用程序是否具有这个特定的权限,而不需要处理SecurityException异常。

是否存在一种“好”的方法在运行时查询当前定义的权限?

11个回答

209

你可以使用Context.checkCallingOrSelfPermission()函数来实现这个功能。以下是一个例子:

private boolean checkWriteExternalPermission()
{
    String permission = android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
    int res = getContext().checkCallingOrSelfPermission(permission);
    return (res == PackageManager.PERMISSION_GRANTED);            
}

14
为什么您认为checkCallingOrSelfPermission()存在安全风险? - William
@inazaruk,如果系统没有授予权限,是否有可能授予权限? - Mr. Sajid Shaikh
2
不行。你不能在运行时给自己授权。 - Anubian Noob
3
وœ€ه¥½ن½؟用checkCallingPermission()و–¹و³•è€Œن¸چوک¯checkCallingOrSelfPermission()و–¹و³•م€‚ - hasanghaforian
10
现在有一个兼容性包装器:ContextCompat.checkSelfPermission。 - yoah
显示剩余3条评论

53

这也是另一种解决方案

PackageManager pm = context.getPackageManager();
int hasPerm = pm.checkPermission(
    android.Manifest.permission.WRITE_EXTERNAL_STORAGE, 
    context.getPackageName());
if (hasPerm != PackageManager.PERMISSION_GRANTED) {
   // do stuff
}

那我应该把这段代码放在那个if语句里吗?我写了这个代码是为了检测用户是否正在接听电话或处于通话中,然后静音音频。http://snag.gy/uIxsv.jpg - Ruchir Baronia
调用权限包和iPC有什么区别? - htafoya
1
非常感谢,非常有帮助。在Android 5.1.1上运行得很好。如果您尚未定义“context”,则可以将其替换为“getBaseContext()”。 - JamisonMan111

20

你也可以使用这个:

private boolean doesUserHavePermission()
{
    int result = context.checkCallingOrSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    return result == PackageManager.PERMISSION_GRANTED;
}

13

就像 Google 文档所述:

// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

9

分享我的方法,以防有人需要:

 /** Determines if the context calling has the required permission
 * @param context - the IPC context
 * @param permissions - The permissions to check
 * @return true if the IPC has the granted permission
 */
public static boolean hasPermission(Context context, String permission) {

    int res = context.checkCallingOrSelfPermission(permission);

    Log.v(TAG, "permission: " + permission + " = \t\t" + 
    (res == PackageManager.PERMISSION_GRANTED ? "GRANTED" : "DENIED"));

    return res == PackageManager.PERMISSION_GRANTED;

}

/** Determines if the context calling has the required permissions
 * @param context - the IPC context
 * @param permissions - The permissions to check
 * @return true if the IPC has the granted permission
 */
public static boolean hasPermissions(Context context, String... permissions) {

    boolean hasAllPermissions = true;

    for(String permission : permissions) {
        //you can return false instead of assigning, but by assigning you can log all permission values
        if (! hasPermission(context, permission)) {hasAllPermissions = false; }
    }

    return hasAllPermissions;

}

然后进行调用:

boolean hasAndroidPermissions = SystemUtils.hasPermissions(mContext, new String[] {
                android.Manifest.permission.ACCESS_WIFI_STATE,
                android.Manifest.permission.READ_PHONE_STATE,
                android.Manifest.permission.ACCESS_NETWORK_STATE,
                android.Manifest.permission.INTERNET,
        });

6

您应该按照以下方式检查权限(如Android权限中所述):

int result = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_PHONE_STATE);

然后,将您的结果与以下内容进行比较之一:
result == PackageManager.PERMISSION_DENIED

或者:

result == PackageManager.PERMISSION_GRANTED

谢谢。这很有帮助。 - Sudhir Singh Khanger

4

第一步 - 添加权限请求

    String[] permissionArrays = new String[]{Manifest.permission.CAMERA, 
    Manifest.permission.WRITE_EXTERNAL_STORAGE};
    int REQUEST_CODE = 101;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(permissionArrays, REQUEST_CODE );
        } else {
             // if already permition granted
            // PUT YOUR ACTION (Like Open cemara etc..)
        }
    }

第二步- 处理权限结果

     @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    boolean openActivityOnce = true;
    boolean openDialogOnce = true;
    if (requestCode == REQUEST_CODE ) {
        for (int i = 0; i < grantResults.length; i++) {
            String permission = permissions[i];

            isPermitted = grantResults[i] == PackageManager.PERMISSION_GRANTED;

            if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                // user rejected the permission

            }else {
                //  user grant the permission
                // you can perfome your action 
            }
        }
    }
}

2

对我而言正常运行的代码是:

  final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 102;
  if ((ContextCompat.checkSelfPermission(getActivity(),Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {

                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
            } else {
        // user already provided permission
                // perform function for what you want to achieve
     }

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    boolean canUseExternalStorage = false;

    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                canUseExternalStorage = true;
            }

            if (!canUseExternalStorage) {
                Toast.makeText(getActivity(), "Cannot use this feature without requested permission", Toast.LENGTH_SHORT).show();
            } else {
                // user now provided permission
                // perform function for what you want to achieve
            }
        }
      }
 }

1
if ((ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

        requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
                MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
    }
} 

1

在 Kotlin 中检查权限(运行时)

在清单文件中:(android.permission.WRITE_EXTERNAL_STORAGE)

    fun checkPermissions(){

      var permission_array=arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
      if((ContextCompat.checkSelfPermission(this,permission_array[0]))==PackageManager.PERMI   SSION_DENIED){
        requestPermissions(permission_array,0)
      }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

          if(requestCode==0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){

       //Do Your Operations Here

        ---------->
         //


          }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接