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

Posted

技术标签:

【中文标题】如何在运行时检查权限而不抛出 SecurityException?【英文标题】:How permission can be checked at runtime without throwing SecurityException? 【发布时间】:2011-11-04 10:38:35 【问题描述】:

我设计了一个可以从 SD 获取/设置资源的函数,如果从 sd 中找不到,则从 Asset 中获取它,如果可能,将资产写回 SD 此函数可以通过方法调用检查 SD 是否已安装且可访问...

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

我设计的功能可以从一个应用程序(项目)使用到另一个应用程序(有或没有 android.permission.WRITE_EXTERNAL_STORAGE)

然后我想检查当前应用程序是否具有此特定权限而不使用 SecurityException。

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

【问题讨论】:

【参考方案1】:

您可以为此使用Context.checkCallingorSelfPermission() 函数。这是一个例子:

private boolean checkWriteExternalPermission()

    String permission = android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
    int res = getContext().checkCallingOrSelfPermission(permission);
    return (res == PackageManager.PERMISSION_GRANTED);            

【讨论】:

此方法可能存在安全风险。 @TalMihr 为什么你认为 `checkCallingOrSelfPermission()' 会带来安全风险? 没有。你不能在运行时给自己一个权限。 最好使用checkCallingPermission()而不是checkCallingOrSelfPermission()方法。 现在有一个兼容性包装器:ContextCompat.checkSelfPermission【参考方案2】:

这也是另一种解决方案

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

【讨论】:

那么我应该把这段代码包装在 if 语句中吗?我这样做是为了查看用户是否正在接听电话或正在通话中以使音频静音:snag.gy/uIxsv.jpg 调用包获得许可和iPC有什么区别? 非常感谢,非常有帮助。在 Android 5.1.1 上像魅力一样工作。如果您还没有定义“上下文”,您可以将“上下文”替换为“getBaseContext()”。【参考方案3】:

你也可以这样用:

private boolean doesUserHavePermission()

    int result = context.checkCallingOrSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    return result == PackageManager.PERMISSION_GRANTED;

【讨论】:

【参考方案4】:

点赞谷歌documentation:

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

【讨论】:

【参考方案5】:

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

 /** 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】:

适合我的代码是:-

  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
            
        
      
 

【讨论】:

【参考方案7】:

您应该通过以下方式检查权限(如此处所述Android permissions):

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

然后,将您的结果与以下任一结果进行比较:

result == PackageManager.PERMISSION_DENIED

或:

result == PackageManager.PERMISSION_GRANTED

【讨论】:

谢谢。这很有帮助。【参考方案8】:

启用 GPS 定位 Android Studio

    在 AndroidManifest.Xml 中添加权限条目

    MapsActivity.java

    public class MapsActivity extends FragmentActivity implements OnMapReadyCallback 
    
    private GoogleMap mMap;
    private Context context;
    private static final int PERMISSION_REQUEST_CODE = 1;
    Activity activity;
    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    private GoogleApiClient client;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        context = getApplicationContext();
        activity = this;
        super.onCreate(savedInstanceState);
        requestPermission();
        checkPermission();
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    
    
    
    @Override
    public void onMapReady(GoogleMap googleMap) 
        mMap = googleMap;
        LatLng location = new LatLng(0, 0);
        mMap.addMarker(new MarkerOptions().position(location).title("Marker in Bangalore"));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(location));
        mMap.setMyLocationEnabled(true);
    
    
    private void requestPermission() 
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION)) 
            Toast.makeText(context, "GPS permission allows us to access location data. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
         else 
            ActivityCompat.requestPermissions(activity, new String[]Manifest.permission.ACCESS_FINE_LOCATION, PERMISSION_REQUEST_CODE);
        
    
    
    private boolean checkPermission() 
        int result = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
        if (result == PackageManager.PERMISSION_GRANTED) 
            return true;
         else 
            return false;
        
    
    

【讨论】:

【参考方案9】:
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);
    
 

【讨论】:

【参考方案10】:

在 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

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


          
    

【讨论】:

【参考方案11】:

第 1 步 - 添加权限请求

    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..)
        
    

第 2 步 - 处理权限结果

     @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 
            
        
    

【讨论】:

以上是关于如何在运行时检查权限而不抛出 SecurityException?的主要内容,如果未能解决你的问题,请参考以下文章

我迁移到空安全,我无法运行“flutter pub run build_runner build”而不抛出错误

IMAPI:如果图像大小超过可用空间,如何获取图像大小而不抛出异常?

回滚而不抛出异常?

如何让 Weblogic 10 更喜欢 myApp.war:/WEB-INF/lib/ 中的罐子而不抛出 VerifyErrors?

UserManager 退出函数而不抛出任何异常

HttpClient.SendAsync 方法退出而不抛出异常