在Android 10上启动意图时,相机崩溃

4

我正在尝试将拍照功能添加到我的应用程序中,这应该相当简单,但是我在Android 10上遇到了问题。

我按照https://developer.android.com/training/camera/photobasics中的实现细节进行操作(目前我只实现了基本功能,即启动相机应用程序并返回缩略图的位图)。

这在旧版模拟设备上都有效,但是当我在我的Google Pixel物理设备和模拟的Pixel 2上进行测试(两者均运行Android 10),在调用startActivity后会崩溃:

btnCam.setOnClickListener(v -> {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
    }
});

问题在于,崩溃的不是我的应用程序,而是相机应用程序。如果我在崩溃后查看logcat,则会收到以下消息:
2020-02-02 17:11:29.059 15592-15592/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.google.android.GoogleCamera, PID: 15592
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.google.android.GoogleCamera/com.google.android.apps.camera.legacy.app.activity.CaptureActivity}: java.lang.NullPointerException: Attempt to get length of null array
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.lang.NullPointerException: Attempt to get length of null array
        at com.google.android.apps.camera.legacy.app.activity.CaptureActivity.onCreate(PG:12)
        at android.app.Activity.performCreate(Activity.java:7802)
        at android.app.Activity.performCreate(Activity.java:7791)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930

根据错误提示java.lang.NullPointerException: Attempt to get length of null array,我认为代码期望得到某种输入,但我未提供。然而,我并没有找到需要提供任何额外参数的说明(我知道你可以指定可选参数来指定将结果照片写入的位置,但没有任何说明这是必需的)。

是否有人了解如何在安卓10上解决此问题?

谢谢


尝试不同的相机应用程序。商店里有很多选择。 - blackapps
这并不是一个真正的选择,我不能强制所有使用我的应用程序的用户安装第三方应用程序才能使用相机。 - Darc
当然,你只会为自己这样做。只是测试一下,这样你就会知道了。用户可能更喜欢不同的相机应用程序,那么你的应用程序也应该能够正常工作。 - blackapps
是的,但绝大多数用户将使用默认相机应用程序,因此我需要支持它,而不是随意的第三方应用程序(如果第三方应用程序可以工作,那并不重要)。 - Darc
你找到解决问题的方法了吗?我遇到了一个空指针问题,但在使用Android 9及以下版本时却能正常运行,为什么在Android 10和11上不行呢? - MadhanMohan
2个回答

2
根据另一篇文章的说法,这是相机应用程序中的一个错误,最近已经得到了纠正。当您使用相机应用程序拍照时,您的应用程序无需请求使用相机的权限。
但是,如果您需要在API 29模拟器或设备上运行您的应用程序,在错误修复被推出之前,您可以在AndroidManifest.xml中添加任何类型的权限(即使是虚假的)<uses-permission>
<manifest ...>
   <uses-permission android:name="BLAH" />
   ...

</manifest>

哇!你是我的英雄!我浪费了很多时间试图找到解决这个尴尬问题的方法! - Iogui

0

首先,您需要检查相机权限,并在清单文件中添加相机权限。请按照以下代码进行检查:

  1. 在AndroidManifest.xml文件中添加

  2. 检查相机权限。

private static final int CAMERA_REQUEST = 100;  
if(ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)!=PackageManager.PERMISSION_GRANTED){
      ActivityCompat.requestPermissions(this,
      newString[]{
        Manifest.permission.CAMERA
      },
      MY_CAMERA_PERMISSION_CODE);
    }else{
        Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(cameraIntent, CAMERA_REQUEST);
    }
  • public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    
        switch (requestCode) {
    
            case MY_CAMERA_PERMISSION_CODE: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    showPictureDialog();
                } else {
                    Snackbar snackbar = Snackbar
                            .make(relativeLayout, "请允许权限", Snackbar.LENGTH_LONG)
                            .setAction("设置", new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    Intent intent = new Intent();
                                    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                    Uri uri = Uri.fromParts("package", getPackageName(), null);
                                    intent.setData(uri);
                                    startActivity(intent);
                                }
                            });
                    snackbar.show();
                }
            }
        }
    }
  • 4.

         @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    
            callbackManager.onActivityResult(requestCode, resultCode, data);
    
             if (requestCode == CAMERA_REQUEST) {
                Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
                circleImageView.setImageBitmap(thumbnail);
                saveImage(thumbnail);
                Toast.makeText(SignUpActivity.this, "Image Saved!", Toast.LENGTH_SHORT).show();
            }
        }
    
    1. 将图片保存到存储器中
        public String saveImage(Bitmap myBitmap) {
    
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
            File wallpaperDirectory = new File(Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
            // have the object build the directory structure, if needed.
            if (!wallpaperDirectory.exists()) {
                wallpaperDirectory.mkdirs();
            }
    
            try {
                File f = new File(wallpaperDirectory, Calendar.getInstance()
                        .getTimeInMillis() + ".jpg");
                f.createNewFile();
                FileOutputStream fo = new FileOutputStream(f);
                fo.write(bytes.toByteArray());
                MediaScannerConnection.scanFile(this,
                        new String[]{f.getPath()},
                        new String[]{"image/jpeg"}, null);
                fo.close();
                Log.d("TAG", "File Saved::--->" + f.getAbsolutePath());
    
                return f.getAbsolutePath();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            return "";
        }
    

    现在我只是有点烦,我本来以为我已经更新了清单文件,而且它在旧的模拟器上也能工作,所以我甚至没有想到去检查,但问题就出在这里,我漏掉了愚蠢的相机权限。无论如何,感谢您详细的答案,我还忘记了请求运行时权限是一件事,所以感谢您提供的示例。 - Darc
    尽管这个答案确实提供了有关如何请求权限的有用信息,但所提供的解决方案是错误的,因为通过意图调用相机应用程序不需要相机权限。 接受的答案应该是下面的@tronman! - Iogui

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