【问题标题】:How permission can be checked at runtime without throwing SecurityException?如何在运行时检查权限而不抛出 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。

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

【问题讨论】:

    标签: android security permissions runtime


    【解决方案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

            1. 在 AndroidManifest.Xml 中添加权限条目

            1. 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 
                              }
                          }
                      }
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-08-13
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-05-09
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-11-12
                    相关资源
                    最近更新 更多