简体   繁体   English

Android“权限拒绝:无法使用相机”

[英]Android “Permission Denial: can't use the camera”

I'm following a tutorial on utilizing the camera in an Android app.我正在学习有关在 Android 应用程序中使用相机的教程。 I am getting the error "Permission Denial: can't use the camera" when running debug, both on emulator and physical device.在模拟器和物理设备上运行调试时,我收到错误“权限拒绝:无法使用相机” I have tried a variety of permissions in my manifest file.我在清单文件中尝试了各种权限。 It seems most people who have had this error have had a typo, a missing permission, or the permissions not in the right place in their manifest.似乎大多数遇到此错误的人都有拼写错误、缺少权限或权限不在其清单中的正确位置。

Here's my manifest file:这是我的清单文件:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.karudo.dbzrealpowerup" >

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera2" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".DBZHome"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".DBZStartPowerUp"
            android:label="@string/title_activity_dbzstart_power_up" >
        </activity>
    </application>

</manifest>

Here's my activity:这是我的活动:

package com.example.karudo.dbzrealpowerup;

import android.app.Activity;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Bundle;
import android.util.Size;
import android.view.Menu;
import android.view.MenuItem;
import android.view.TextureView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class DBZStartPowerUp extends Activity {

    private Size mPreviewSize;
    private String mCameraId;
    private TextureView mTextureView;
    private TextureView.SurfaceTextureListener mSurfaceTextureListener =
            new TextureView.SurfaceTextureListener() {

                @Override
                public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                    setupCamera(width, height);
                    openCamera();
                }

                @Override
                public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

                }

                @Override
                public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                    return false;
                }

                @Override
                public void onSurfaceTextureUpdated(SurfaceTexture surface) {

                }
            };

    private CameraDevice mCameraDevice;
    private CameraDevice.StateCallback mCameraDeviceStateCallback
            = new CameraDevice.StateCallback() {

        @Override
        public void onOpened(CameraDevice camera) {
            mCameraDevice = camera;
            Toast.makeText(getApplicationContext(), "Camera Opened!", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onDisconnected(CameraDevice camera) {
            camera.close();
            mCameraDevice = null;
        }

        @Override
        public void onError(CameraDevice camera, int error) {
            camera.close();
            mCameraDevice = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dbzstartpowerup);
        mTextureView = (TextureView) findViewById(R.id.dbzCameraPreview);
    }

    @Override
    public void onResume() {
        super.onResume();
        if(mTextureView.isAvailable()) {

        } else {
            mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_dbzstartpowerup, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void setupCamera(int width, int height) {
        CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            for(String cameraId : cameraManager.getCameraIdList()) {
                CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
                if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
                        CameraCharacteristics.LENS_FACING_FRONT) {
                    continue;
                }
                StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                mPreviewSize = getPreferredPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height);
                mCameraId = cameraId;
                return;
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private Size getPreferredPreviewSize(Size[] mapSizes, int width, int height) {
        List<Size> collectorSizes = new ArrayList<>();
        for(Size option : mapSizes) {
            if(width > height) {
                if(option.getWidth() > width &&
                        option.getHeight() > height) {
                    collectorSizes.add(option);
                }
            } else {
                if(option.getWidth() > height &&
                        option.getHeight() > width) {
                    collectorSizes.add(option);
                }
            }
        }
        if(collectorSizes.size() > 0) {
            return Collections.min(collectorSizes, new Comparator<Size>() {
                @Override
                public int compare(Size lhs, Size rhs) {
                    return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight());
                }
            });
        }
        return mapSizes[0];
    }

    private void openCamera() {
        CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
}

And the error in my logcat:我的 logcat 中的错误:

10-04 03:15:02.740     961-8780/? E/CameraService﹕ Permission Denial: can't use the camera pid=20601, uid=10059
10-04 03:15:02.741  20601-20601/com.example.karudo.dbzrealpowerup E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.karudo.dbzrealpowerup, PID: 20601
    java.lang.SecurityException: Lacking privileges to access camera service
            at android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:108)
            at android.hardware.camera2.legacy.CameraDeviceUserShim.connectBinderShim(CameraDeviceUserShim.java:336)
            at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:324)
            at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:454)
            at com.example.karudo.dbzrealpowerup.DBZStartPowerUp.openCamera(DBZStartPowerUp.java:163)
            at com.example.karudo.dbzrealpowerup.DBZStartPowerUp.access$100(DBZStartPowerUp.java:23)
            at com.example.karudo.dbzrealpowerup.DBZStartPowerUp$1.onSurfaceTextureAvailable(DBZStartPowerUp.java:34)
            at android.view.TextureView.getHardwareLayer(TextureView.java:368)
            at android.view.View.updateDisplayListIfDirty(View.java:15151)
            at android.view.View.draw(View.java:15948)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
            at android.view.View.updateDisplayListIfDirty(View.java:15169)
            at android.view.View.draw(View.java:15948)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
            at android.view.View.updateDisplayListIfDirty(View.java:15169)
            at android.view.View.draw(View.java:15948)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
            at android.view.View.updateDisplayListIfDirty(View.java:15169)
            at android.view.View.draw(View.java:15948)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
            at android.view.View.draw(View.java:16181)
            at com.android.internal.policy.PhoneWindow$DecorView.draw(PhoneWindow.java:2690)
            at android.view.View.updateDisplayListIfDirty(View.java:15174)
            at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281)
            at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287)
            at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322)
            at android.view.ViewRootImpl.draw(ViewRootImpl.java:2615)
            at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2434)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2067)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
            at android.view.Choreographer.doCallbacks(Choreographer.java:670)
            at android.view.Choreographer.doFrame(Choreographer.java:606)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:148)
            at android.app.ActivityThread.main(ActivityThread.java:5417)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

I'm new to app development and admittedly I'm no good at debugging, but my manifest permissions appear to be correct from what I've seen of other people's files (and the tutorial which is only 4 months old).我是应用程序开发的新手,不可否认,我不擅长调试,但从我看到的其他人的文件(以及仅 4 个月大的教程)来看,我的清单权限似乎是正确的。

Can anyone please tell me what I've done wrong?谁能告诉我我做错了什么?

Cheers, Lee.干杯,李。

UPDATE: I found via debugging that it crashes as soon as it reaches this method...更新:我通过调试发现它一到达这个方法就会崩溃......

private void openCamera() {
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }

} }

... specifically as soon as it runs the try statement. ...特别是一旦它运行 try 语句。

UPDATE 2: If I comment out the try/catch statements, the app doesn't crash, but the expected result (which is to print "Camera Opened!") doesn't happen.更新 2:如果我注释掉 try/catch 语句,应用程序不会崩溃,但预期的结果(即打印“Camera Opened!”)不会发生。 Any ideas?有任何想法吗?

UPDATE 3: My apologies, I just realized how dumb my above edit was.更新 3:我很抱歉,我刚刚意识到我上面的编辑是多么愚蠢。 It's obvious why it no longer crashes, but at least I now know I have to debug my cameraManager.openCamera parameters.很明显为什么它不再崩溃,但至少我现在知道我必须调试我的cameraManager.openCamera参数。 The code is there if anyone can have a look :)如果有人可以看看,代码就在那里:)

If you're using Android 6 Marshmallow this issue could be caused by the new permission management.如果您使用的是 Android 6 Marshmallow,则此问题可能是由新的权限管理引起的。 In my case I solved the problem by overriding the following activity method:在我的情况下,我通过覆盖以下活动方法解决了这个问题:

@Override
public void onRequestPermissionsResult(int requestCode,  String permissions[], int[] grantResults) {
    switch (requestCode) {
        case CAMERA_PERMISSION:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if(mClss != null) {
                    Intent intent = new Intent(this, ClassUsingCamera);
                    startActivity(intent);
                }
            } else {
                Toast.makeText(this, "Please grant camera permission to use the QR Scanner", Toast.LENGTH_SHORT).show();
            }
            return;
    }
}

I then launched the activity that requires the camera (ClassUsingCamera) with the following code:然后,我使用以下代码启动了需要相机 (ClassUsingCamera) 的活动:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
     ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION);
} else {
       Intent intent = new Intent(this, ClassUsingCamera);
       startActivity(intent);
        }

On the first app launch you'll get the popup asking you to grant the access to the camera.在第一次启动应用程序时,您会看到弹出窗口,要求您授予对相机的访问权限。

Another option is to use the PermissionsDispatcher as explained here https://github.com/hotchemi/PermissionsDispatcher另一种选择是使用 PermissionsDispatcher,如下所述https://github.com/hotchemi/PermissionsDispatcher

i got the same error only when i tried the app on devices with (Android 6.0.0) or emulator with (API 23).仅当我在配备 (Android 6.0.0) 的设备或配备 (API 23) 的模拟器上尝试该应用程序时,才会遇到相同的错误。 But with others it works fine.但与其他人一起工作正常。

that's because of android above M makes some changes in granted permissions on run-time application.那是因为 M 以上的 android 对运行时应用程序的授予权限进行了一些更改。

to do it, follow this few steps.要做到这一点,请按照以下几个步骤操作。

first : add this static variable.第一:添加这个静态变量。

private static final int REQUEST_CAMERA_RESULT = 1;

then modify your openCamera method然后修改你的 openCamera 方法

private void openCamera() {
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        Log.v("CAMERA", mCameraId + " " + mCameraDeviceStateCallback);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
            if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
                    == PackageManager.PERMISSION_GRANTED){
                cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback,mBackgroundHandler);
            }
            else {
                if (shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA)){
                    Toast.makeText(this,"No Permission to use the Camera services", Toast.LENGTH_SHORT).show();
                }
                requestPermissions(new String[] {android.Manifest.permission.CAMERA},REQUEST_CAMERA_RESULT);
            }
        }
        else {
            cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
        }
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

feel free to change mBackgroundHandler to null, i just made it to handle camera work in background thread.随意将 mBackgroundHandler 更改为 null,我只是让它在后台线程中处理相机工作。

And,then Override this method然后覆盖这个方法

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode){
        case  REQUEST_CAMERA_RESULT:
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED){
                Toast.makeText(this, "Cannot run application because camera service permission have not been granted", Toast.LENGTH_SHORT).show();
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        break;
    }
}

Few points I can say :我可以说几点:

  1. If connection to the camera service is fails (For example if the camera is used by anyother application or device manger has disable the camera or any of the application could not able to release the camera.)如果连接到相机服务失败(例如,如果相机被任何其他应用程序使用或设备管理器禁用了相机或任何应用程序无法释放相机。)
  1. Make sure that your safely close/ release the camera inside your code.确保您在代码中安全关闭/释放相机。

  2. Have you tried checking if the camera is being used by something else or if your policy manager has some setting where the camera is turned off?您是否尝试检查相机是否正在被其他人使用,或者您的策略管理器是否有关闭相机的某些设置?

try to put this code your manifest.xml file.尝试将此代码放在您的 manifest.xml 文件中。

 <uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="19" />

<uses-permission
    android:name="android.permission.INTERNET"
    android:maxSdkVersion="19" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_DEBUG_APP"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

First Option you have regarding permissions is to go to the android settings of that specific application and grant it all permissions it requires from there.您对权限的第一个选项是转到该特定应用程序的 android 设置,并从那里授予它所需的所有权限。 Second option you have is to check whether that permission is required during runtime and request for permissions the app needs or an even better approach is to ask for a permission when a feature is run that requires that permission.您的第二个选择是检查在运行期间是否需要该权限并请求应用程序所需的权限,或者更好的方法是在运行需要该权限的功能时请求该权限。

Well go through some code that ask for app permissions when an activity opens.好吧,通过一些代码,在活动打开时请求应用程序权限。 But you can modify that code to ask for permission when a feature such as taking camera is required.但是,当需要拍摄相机等功能时,您可以修改该代码以请求许可。

And another thing is that some permissions such as Internet are granted automatically by the system therefore you don't need to ask for it.另一件事是,某些权限(例如 Internet)是由系统自动授予的,因此您无需请求。 However You will need to ask for some explicitly.但是,您需要明确要求一些。

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CAMERA"/>  

The above shows the permissions declared right above the opening application tag in the AndroidManifest.上面显示了在 AndroidManifest 中打开应用程序标签正上方声明的权限。

    public boolean hasFineLocationPermission(){
        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
            return true;
        }
        else{
            return false;
        }
    }

    public boolean hasExternalStoragePermission(){
        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        else{
            return false;
        }
    }

public boolean hasLocationForegroundService(){
    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.FOREGROUND_SERVICE) == PackageManager.PERMISSION_GRANTED){
        return true;
    }
    else{
        return false;
    }
}



public boolean hasReadPhoneStatePermission(){
    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED){
        return true;
    }
    else{
        return false;
    }
}

public boolean hasCameraPermission(){
    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
        return true;
    }
    else{
        return false;
    }
}

public boolean hasAccessNetworkState(){
    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_NETWORK_STATE) == PackageManager.PERMISSION_GRANTED){
        return true;
    }
    else{
        return false;
    }
}

We have some functions above.我们上面有一些函数。 What all the functions do is basically check if a certain permission is granted.所有功能所做的基本上是检查是否授予了某个权限。 If it is return true therefore there is no need to ask for that permission.如果返回 true,则无需请求该许可。 If not return false therefore well ask for that permission in a bit.如果不返回 false,那么请稍后请求该许可。 For example:例如:

if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){ return true; if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){ return true; } }

This checks If we have access to the camera and if we do it returns True and if not it will return false as shown in the function hasCameraPermission()这会检查我们是否有权访问相机,如果我们访问它,则返回 True,否则返回 false,如函数 hasCameraPermission() 所示

Now we can check that all permissions are granted using the function below:现在我们可以使用以下函数检查是否授予了所有权限:

public void getApplicationPermissions(){

    List<String> listPermissionsNeeded = new ArrayList<>();
    if (!hasFineLocationPermission()){

        listPermissionsNeeded.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);

    }

    if (!hasExternalStoragePermission()){

        listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);

    }

    if (!hasLocationForegroundService()){
        listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);

    }
    if (!hasReadPhoneStatePermission()){
        listPermissionsNeeded.add(Manifest.permission.READ_PHONE_STATE);
    }

    if (!hasCameraPermission()){
        listPermissionsNeeded.add(Manifest.permission.CAMERA);
    }

    if (!hasAccessNetworkState()){
        listPermissionsNeeded.add(Manifest.permission.ACCESS_NETWORK_STATE);
    }

    Log.i("listPermissionsNeeded", String.valueOf(listPermissionsNeeded));

    if (!listPermissionsNeeded.isEmpty()){
        ActivityCompat.requestPermissions(this,listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),0);
    }
    else{
        Toast.makeText(this,"All Permissions Required Are Granted",Toast.LENGTH_SHORT).show();
    }

}

The code above first declares a list List<String> listPermissionsNeeded = new ArrayList<>();上面的代码首先声明了一个列表List<String> listPermissionsNeeded = new ArrayList<>(); of type String字符串类型

Then checks if:然后检查是否:

if (!hasCameraPermission()){
            listPermissionsNeeded.add(Manifest.permission.CAMERA);
        } 

Meaning: If Permission to camera has not been granted add that permission to the list by adding Manifest.permission.CAMERA含义:如果未授予相机权限,则通过添加Manifest.permission.CAMERA将该权限添加到列表中

If our permissionsList is Empty we'll just show the user a toast.如果我们的权限列表为空,我们将只向用户展示一个祝酒词。 However If it does have some permissions we Call the function ActivityCompat.requestPermissions() passing in context,our list and an identifier which in this case is 0:但是,如果它确实有一些权限,我们调用函数ActivityCompat.requestPermissions()传入上下文、我们的列表和一个标识符,在这种情况下为 0:

if (!listPermissionsNeeded.isEmpty()){
    ActivityCompat.requestPermissions(this,listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),0);
}
else{
    Toast.makeText(this,"All Permissions Required Are Granted",Toast.LENGTH_SHORT).show();
} 

When that requestPermissions is called another android method is called which is onRequestPermissionsResult() .当该 requestPermissions 被调用时,另一个 android 方法被调用,即onRequestPermissionsResult() We implement it as below:我们实现如下:

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

        if(requestCode=0){
         for (int i=0;i<grantResults.length;i++){
            if (grantResults[i] == -1){
                getApplicationPermissions();

            }
        }

        }

    }

The the request Code will be 0 and the grantResults will be the list we passed in the function: ActivityCompat.requestPermissions(this,listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),0);请求代码将为 0,grantResults 将是我们在函数中传递的列表: ActivityCompat.requestPermissions(this,listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),0);

When a permission is rejected by the user you will get back a value of -1 in the grantResult.当用户拒绝某个权限时,您将在 grantResult 中得到一个 -1 的值。 All I do in that function is loop through my grantResults and search for any permission that has been rejected and if there is a permission that has been rejected, I ask for it again and again and again.我在该函数中所做的只是遍历我的 grantResults 并搜索任何已被拒绝的权限,如果有已被拒绝的权限,我会一次又一次地请求它。 That is terrible for user experience.这对用户体验来说太糟糕了。 But you get the point.但你明白了。

Finally We need to check whether the version of Android being used is Android Marshmallow Api Level 23. From what I got, below android 6.0 You can get all permissions as long as you declare it in the Manifest, But starting From 6.0 and upwards You need to ask for the permissions.最后我们需要检查一下所使用的Android版本是否是Android Marshmallow Api Level 23。根据我得到的,在android 6.0以下只要在Manifest中声明就可以得到所有权限,但是从6.0开始就需要请求权限。 This way you can avoid a crash in api levels below that.通过这种方式,您可以避免低于该级别的 api 级别崩溃。 Am not 100% on this, I found conflicting info on this, but settled for that, somebody can correct me there.不是 100% 对此,我发现了有关此的相互矛盾的信息,但解决了这个问题,有人可以在那里纠正我。

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

        }

Hope I've not confused you.希望我没有让你感到困惑。 If you have any questions u can ask or I can send the github link housing that so that u can see how all the code joins up, ie if you need it.如果你有任何问题,你可以问,或者我可以发送 github 链接住房,以便你可以看到所有代码如何连接,即如果你需要它。

All Code was written in Java.所有代码都是用Java编写的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM