拍照失败并显示“需要 android:camera”

Posted

技术标签:

【中文标题】拍照失败并显示“需要 android:camera”【英文标题】:Taking photo fails with "requires android:camera" 【发布时间】:2016-06-23 11:12:56 【问题描述】:

我用下面的代码拍照

Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photoPath = new File(getExternalFilesDir(null), "postcard.jpg");
takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                Uri.fromFile(photoPath));
log.debug("start camera for ", photoPath.getAbsolutePath());
startActivityForResult(takePhotoIntent, REQUEST_TAKE_PHOTO);

...

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    if (requestCode == REQUEST_TAKE_PHOTO) 
        if (resultCode == RESULT_OK) 
            log.debug("photo successfully created");
         else 
            log.error("problem to take photo resultCode=", resultCode);
        
     else 
        log.debug("not my request: ", requestCode);
    

这在 android 5 上运行良好,但在 Android 6 上失败并出现 resultCode=0 (RESULT_CANCELED) 和 logcat 错误消息:

03-09 07:56:13.759 878-3735/? W/ActivityManager:Appop 拒绝: 开始意图 act=android.media.action.IMAGE_CAPTURE flg=0x3 cmp=com.google.android.GoogleCamera/com.android.camera.CaptureActivity 剪辑=文本/uri列表 U:file:///storage/emulated/0/Android/data/censored.package.name.here/files/postcard.jpg (有附加功能)来自 ProcessRecord55cce35 21309:censored.package.name.here/u0a136 (pid=21309, uid=10136) 需要安卓:相机

我在 Android Manifest 中有以下内容:

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

我也检查一下应用是否真的有摄像头权限,这个检查通过了。

checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED

另外值得注意的是,我在项目中包含了一个也使用相机的 aar。这个包含的库在清单中有这个:

<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.flash" android:required="false"/>
<uses-feature android:name="android.hardware.screen.landscape" android:required="false" />
<uses-feature android:name="android.hardware.wifi" android:required="false"/>

有人知道错误消息的含义或如何解决此问题吗? Google 在这种情况下没有帮助。

到目前为止,我还没有通过一个小示例成功重现该问题。这似乎是与另一个应用程序部分的一些交互。

【问题讨论】:

***.com/questions/32789027/…希望这会有所帮助 @O'one 谢谢,但不,这是一个不同的问题。我获得了许可,而且错误消息也不同。 你可以通过将target sdk设置为22来尝试它,因为它也会在23上运行,如果它运行那么肯定会由于权限问题而发生。 @O'one 与目标 sdk 22 完全相同。 确保相机应用已启用相机和存储权限 【参考方案1】:

经过一天多的试验和调试,它现在可以工作了。代码还是一样的。

我想,通过设置收回相机权限,然后重新启用它就可以了,但我不完全确定。

如果有人遇到同样的问题,请将此作为答案发布。

【讨论】:

【参考方案2】:

-- 用于捕获图像、保存到 SD 卡、从图库中选择、压缩、旋转图像等的完整代码。200% 工作。

public class A extends AppCompatActivity implements View.OnClickListener, AsyncTaskCompleteListener 

    private static final String IMAGE_DIRECTORY = "/idyme";
    private static int MAX_IMAGE_DIMENSION = 200;
    private final String TAG = "RegisterFragment";
    private Button btnVerify, btnUploadImage;

    private String   ImgPath = null, filePath = null,
            profileImageFilePath, profileImageData = null,imageVideoType = "", imageVideoPath = "";
    private ImageView ivImage;
    private AQuery aQuery;
    private Uri uri = null;
    private ImageOptions imageOptions;
    ActionBar actionBar;



    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_vip_registration);


        ivImage = (ImageView) findViewById(R.id.ivProfile);
        aQuery = new AQuery(this);
        imageOptions = new ImageOptions();
        imageOptions.memCache = true;
        imageOptions.fileCache = true;
        imageOptions.fallback = R.drawable.userimage;






    

    @Override
    public void onClick(View v) 
        //  onRegisterButtonClick();

        switch (v.getId()) 

            case R.id.btnUploadImage:
                showPictureDialog();
        
    

    private void showPictureDialog() 
        AlertDialog.Builder pictureDialog = new AlertDialog.Builder(this);
        pictureDialog.setTitle(getResources().getString(
                R.string.dialog_chhose_photo));
        String[] pictureDialogItems = 
                getResources().getString(R.string.dialog_from_gallery),
                getResources().getString(R.string.dialog_from_camera);

        pictureDialog.setItems(pictureDialogItems,
                new DialogInterface.OnClickListener() 

                    @Override
                    public void onClick(DialogInterface dialog, int which) 
                        switch (which) 

                            case 0:
                                choosePhotoFromGallary();
                                break;

                            case 1:
                                takePhotoFromCamera();
                                break;

                        
                    
                );
        pictureDialog.show();
    

    private void choosePhotoFromGallary() 
        Intent galleryIntent = new Intent(Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

        startActivityForResult(galleryIntent, Constants.CHOOSE_PHOTO);


    

    private void takePhotoFromCamera() 
        Calendar cal = Calendar.getInstance();
        File file = new File(Environment.getExternalStorageDirectory(),
                (cal.getTimeInMillis() + ".jpg"));

        if (!file.exists()) 
            try 
                file.createNewFile();
             catch (IOException e) 
                e.printStackTrace();
            
         else 

            file.delete();
            try 
                file.createNewFile();
             catch (IOException e) 
                e.printStackTrace();
            
        
        //   uri = Uri.fromFile(file);
        uri = getOutputMediaFileUri();
        Intent cameraIntent = new Intent(
                android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        startActivityForResult(cameraIntent, Constants.TAKE_PHOTO);


    

    public Uri getOutputMediaFileUri() 
        return Uri.fromFile(getOutputMediaFile());
    

    private String getRealPathFromURI(Uri contentURI) 
        String result;

        String[] proj = MediaStore.Images.Media.DATA;
        Cursor cursor = this.getContentResolver().query(contentURI, proj, null, null, null);

        if (cursor == null)  // Source is Dropbox or other similar local file
            // path
            result = contentURI.getPath();
         else 
            cursor.moveToFirst();
            int idx = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            result = cursor.getString(idx);
            cursor.close();
        


        return result;


    


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) 

        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == this.RESULT_CANCELED) 
            return;
        
        if (requestCode == Constants.CHOOSE_PHOTO) 
            if (data != null) 
                Uri contentURI = data.getData();
                profileImageData = getRealPathFromURI(contentURI);
                // new AQuery(getApplicationContext()).id(ivMeme).image(
                // profileImageData, imageOptions);
                try 
                    String path = saveImage(scaleImage(this, contentURI));
                    imageVideoPath = path;
                    aQuery.id(R.id.ivProfile).image(
                            imageVideoPath, imageOptions);
                 catch (IOException e) 
                    e.printStackTrace();
                    Utils.showToast("Failed", this);
                

            

         else if (requestCode == Constants.TAKE_PHOTO) 


            // old
            if (uri != null) 
                profileImageFilePath = uri.getPath();
                if (profileImageFilePath != null
                        && profileImageFilePath.length() > 0) 
                    File myFile = new File(profileImageFilePath);
                    String path = saveImage(BitmapFactory
                            .decodeFile(profileImageFilePath));
                    imageVideoPath = path;
                    aQuery.id(R.id.ivProfile).image(
                            imageVideoPath, imageOptions);
                 else 
                   Utils.showToast("Failed", this);
                

             else 
                Utils.showToast("Failed", this);
            

        

    

    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();
            AppLog.Log("TAG", "File Saved::-> " + f.getAbsolutePath());
            return f.getAbsolutePath();
         catch (IOException e1) 
            e1.printStackTrace();
        
        return "";
    


private static File getOutputMediaFile() 

        // External sdcard location
        File mediaStorageDir = new File(
                Environment
                        .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                IMAGE_DIRECTORY);

        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists()) 
            if (!mediaStorageDir.mkdirs()) 
                Log.d(IMAGE_DIRECTORY, "Oops! Failed create " + IMAGE_DIRECTORY
                        + " directory");
                return null;
            
        

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
                Locale.getDefault()).format(new Date());
        File mediaFile;
        mediaFile = new File(mediaStorageDir.getPath() + File.separator
                + "VID_" + timeStamp + ".mp4");

        return mediaFile;
    

    public static Bitmap scaleImage(Context context, Uri photoUri)
            throws IOException 
        InputStream is = context.getContentResolver().openInputStream(photoUri);
        BitmapFactory.Options dbo = new BitmapFactory.Options();
        dbo.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(is, null, dbo);
        is.close();

        int rotatedWidth, rotatedHeight;
        int orientation = getOrientation(context, photoUri);

        if (orientation == 90 || orientation == 270) 
            rotatedWidth = dbo.outHeight;
            rotatedHeight = dbo.outWidth;
         else 
            rotatedWidth = dbo.outWidth;
            rotatedHeight = dbo.outHeight;
        

        Bitmap srcBitmap;
        is = context.getContentResolver().openInputStream(photoUri);
        if (rotatedWidth > MAX_IMAGE_DIMENSION
                || rotatedHeight > MAX_IMAGE_DIMENSION) 
            float widthRatio = ((float) rotatedWidth)
                    / ((float) MAX_IMAGE_DIMENSION);
            float heightRatio = ((float) rotatedHeight)
                    / ((float) MAX_IMAGE_DIMENSION);
            float maxRatio = Math.max(widthRatio, heightRatio);

            // Create the bitmap from file
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = (int) maxRatio;
            srcBitmap = BitmapFactory.decodeStream(is, null, options);
         else 
            srcBitmap = BitmapFactory.decodeStream(is);
        
        is.close();

        /*
         * if the orientation is not 0 (or -1, which means we don't know), we
         * have to do a rotation.
         */
        if (orientation > 0) 
            Matrix matrix = new Matrix();
            matrix.postRotate(orientation);

            srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0,
                    srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
        

        String type = context.getContentResolver().getType(photoUri);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        if (type.equals("image/png")) 
            srcBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
         else if (type.equals("image/jpg") || type.equals("image/jpeg")) 
            srcBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        
        byte[] bMapArray = baos.toByteArray();
        baos.close();
        return BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
    


    public static int getOrientation(Context context, Uri photoUri) 
        /* it's on the external media. */
        Cursor cursor = context.getContentResolver().query(photoUri,
                new String[]MediaStore.Images.ImageColumns.ORIENTATION,
                null, null, null);

        if (cursor.getCount() != 1) 
            return -1;
        

        cursor.moveToFirst();
        return cursor.getInt(0);
    


-- 需要权限:

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />

【讨论】:

你没看懂,这就是我在做的,哪一个不行。

以上是关于拍照失败并显示“需要 android:camera”的主要内容,如果未能解决你的问题,请参考以下文章

拍照并显示在视图上

拍照并在视图上显示

HarmonyOSJS鸿蒙Js camera怎么拍照并使用image显示出来

如何拍照以显示在`ImageView`中并保存图片?

用/相机意图拍照并在imageView和textView中显示?

Android调用相机实现拍照并裁剪图片,调用手机中的相冊图片并裁剪图片