Camera.open适用于Android 4.2.2,但在6.0.1上失败

时间:2016-09-15 09:49:33

标签: java android android-camera android-4.2-jelly-bean android-6.0.1-marshmallow

我有2个设备来测试我的应用:运行Android 4.2.2的Acer v370和6.0.1版本的Samsung Galaxy S6

该应用在Acer上工作正常,但在S6上立即崩溃。我正在使用 _camera = Camera.open(0); 并且调试说它此时崩溃了。

我得到的错误是:

09-15 11:24:33.491 15284-15284/com.user.qrReader E/AndroidRuntime: FATAL EXCEPTION: main
  Process: com.user.qrReader, PID: 15284
  java.lang.RuntimeException: Unable to resume activity {com.user.qrReader/com.user.qrReader.MainActivity}:
  java.lang.RuntimeException: Fail to connect to camera service
      at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4156)
      at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4250)
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3361)
      at android.app.ActivityThread.access$1100(ActivityThread.java:222)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:158)
      at android.app.ActivityThread.main(ActivityThread.java:7229)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
  Caused by: java.lang.RuntimeException: Fail to connect to camera service
      at android.hardware.Camera.<init>(Camera.java:568)
      at android.hardware.Camera.open(Camera.java:405)
      at com.user.qrReader.CameraPreview.openCamera(CameraPreview.java:206)
      at com.user.qrReader.CameraPreview.captureStart(CameraPreview.java:288)
      at com.user.qrReader.QRReaderAppManager.onResume(QRReaderAppManager.java:208)
      at com.user.qrReader.MainActivity.onResume(MainActivity.java:187)
      at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1286)
      at android.app.Activity.performResume(Activity.java:6987)
      at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4145)
      at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4250) 
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3361) 
      at android.app.ActivityThread.access$1100(ActivityThread.java:222) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) 
      at android.os.Handler.dispatchMessage(Handler.java:102) 
      at android.os.Looper.loop(Looper.java:158) 
      at android.app.ActivityThread.main(ActivityThread.java:7229) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

以下是我的清单中的权限:

<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />

我不能使用camera2因为我必须保持应用程序兼容至少android 4,我不知道去哪个方向。它必须是与新的android相关的东西,但我找不到什么。有什么想法吗?

编辑:您也可以在安装apk后手动执行此操作,方法是转到设置&gt;应用程序&gt;应用程序管理器&gt; {我的应用}&gt;权限&gt;允许相机。当然,如果你有解决方案,这很糟糕也没用,但是在调试的过程中它帮了我一点,所以我会把它留在这里。 谢谢你的回答。

4 个答案:

答案 0 :(得分:0)

“注意:如果您的应用程序定位到M及以上,并声明为使用未授予的CAMERA权限,则尝试使用此操作将导致SecurityException。”

这真的很奇怪。根本没有意义。该应用程序声明使用具有IMAGE_CAPTURE操作的意图的Camera权限,只需运行SecurityException。但是,如果您的应用未使用意图使用动作声明相机权限IMAGE_CAPTURE可以毫无问题地启动相机应用。

解决方法是检查应用程序是否包含清单中的相机权限,如果是,请在启动意图之前请求相机权限。

以下是检查清单中是否包含权限的方法,无论是否授予权限都无关紧要。

public boolean hasPermissionInManifest(Context context, String permissionName) {
final String packageName = context.getPackageName();
try {
    final PackageInfo packageInfo = context.getPackageManager()
            .getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
    final String[] declaredPermisisons = packageInfo.requestedPermissions;
    if (declaredPermisisons != null && declaredPermisisons.length > 0) {
        for (String p : declaredPermisisons) {
            if (p.equals(permissionName)) {
                return true;
            }
        }
    }
} catch (NameNotFoundException e) {

}
return false;

}

答案 1 :(得分:0)

自API 21以来,不推荐使用Camera类。

Camera class documentation

  

建议使用新的android.hardware.camera2 API   应用

可悲的是,我还没有经历过,所以我无法帮助更多。

还有一个小机会,尝试:

    Camera.open(); // Without argument

此致

答案 2 :(得分:0)

对于检查权限,我创建了一个单独的类,如下所示:

  public class MarshMallowPermission {

    public static final int RECORD_PERMISSION_REQUEST_CODE = 1;
    public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 2;
    public static final int CAMERA_PERMISSION_REQUEST_CODE = 3;
    Activity activity;

    public MarshMallowPermission(Activity activity) {
        this.activity = activity;
    }

    public boolean checkPermissionForRecord(){
        int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO);
        if (result == PackageManager.PERMISSION_GRANTED){
            return true;
        } else {
            return false;
        }
    }

    public boolean checkPermissionForExternalStorage(){
        int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (result == PackageManager.PERMISSION_GRANTED){
            return true;
        } else {
            return false;
        }
    }

    public boolean checkPermissionForCamera(){
        int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
        if (result == PackageManager.PERMISSION_GRANTED){
            return true;
        } else {
            return false;
        }
    }

    public void requestPermissionForRecord(){
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.RECORD_AUDIO)){
           Toast.makeText(activity, "Microphone permission needed for recording. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
        } else {
            ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.RECORD_AUDIO},RECORD_PERMISSION_REQUEST_CODE);
        }
    }

    public void requestPermissionForExternalStorage(){
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
            Toast.makeText(activity, "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
        } else {
            ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
        }
    }

    public void requestPermissionForCamera(){
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)){
            Toast.makeText(activity, "Camera permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
        } else {
            ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE);
        }
    }
}

然后,获取

MarshMallowPermission marshMallowPermission = new MarshMallowPermission(this);


public void getPhotoFromCamera() {

    if (!marshMallowPermission.checkPermissionForCamera()) {
        marshMallowPermission.requestPermissionForCamera();
    } else {
        if (!marshMallowPermission.checkPermissionForExternalStorage()) {
            marshMallowPermission.requestPermissionForExternalStorage();
        } else {
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            File mediaStorageDir = new File(
                    Environment.getExternalStorageDirectory()
                            + File.separator
                            + getString(R.string.directory_name_corp_chat)
                            + File.separator
                            + getString(R.string.directory_name_images)
            );

            if (!mediaStorageDir.exists()) {
                mediaStorageDir.mkdirs();
            }

            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
                    Locale.getDefault()).format(new Date());
            try {
                mediaFile = File.createTempFile(
                        "IMG_" + timeStamp,  /* prefix */
                        ".jpg",         /* suffix */
                        mediaStorageDir      /* directory */
                );
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mediaFile));
                startActivityForResult(takePictureIntent, PICK_FROM_CAMERA);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

答案 3 :(得分:0)

这是在活动中。我检查权限并保存,将我的一些权限更改为CAMERA权限。这是一个有效的例子。

private static final int REQUEST_CODE_GET_ACCOUNTS = 101;
    private static final int REQUEST_AUDIO_PERMISSION = 102;

 @TargetApi(23)
public void checkAudioPermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        playerFragment.setupVisualizerFxAndUI();
        return;
    }
    if (this.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager
            .PERMISSION_GRANTED) {
        requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO},
                REQUEST_AUDIO_PERMISSION);
    } else {
        playerFragment.setupVisualizerFxAndUI();
    }
}

@TargetApi(23)
public void checkGmailPermission() {
    if (isDeviceOnline()) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            showGmailRecFragment(true);
            return;
        }
        if (this.checkSelfPermission(Manifest.permission.GET_ACCOUNTS) != PackageManager
                .PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.GET_ACCOUNTS},
                    REQUEST_CODE_GET_ACCOUNTS);
            return;
        } else {
            showGmailRecFragment(true);
        }
    } else {
        Utils.showToast(this, getString(R.string.no_internet));
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[]
        grantResults) {
    switch (requestCode) {
        case REQUEST_CODE_GET_ACCOUNTS:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                showGmailRecFragment(true);
            } else {
                Utils.showToast(this, getString(R.string.accounts_permision_denied));
            }
            break;
        case REQUEST_AUDIO_PERMISSION:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                playerFragment.setupVisualizerFxAndUI();
            } else {
                Utils.showToast(this, getString(R.string.audio_permission_denied));
            }
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            break;
    }
}

当我想要再次检查权限或用户拒绝它时,这是片段。这也保存了权限

private void setupViewVisualizer() {
    if (!isLiveTv && !homeVideo.isVideoType()) {
        ((PlayerActivity) activity).checkAudioPermission();
    } else {
        return;
    }
}