通过意图将图片拍摄到内部(app)存储为位图返回null

时间:2015-11-05 09:06:07

标签: android android-camera-intent internal-storage

范围:我想通过意图拍照并将照片保存到我应用的内部存储空间。 然后我想将一个缩放版本加载到一个字节数组(来自inputstream),将这个缩放后的图像作为字节数组保存到SQLight中。 保存到数据库后,我想删除图片。

(这个问题只是关于将图像保存到内部存储,范围仅限于此处,因为总会有人询问它)

问题:我坚持将图片保存到内部存储空间。

我会在调试会话中添加示例作为变量后面的注释,以显示测试时获得的值。

我有一个ImageView,它有一个启动takePictureIntent的onClickListener:

具有以下全局属性:

..

创建文件路径:

Uri mCurrentPhotoUri; //URI to file
File mCurrentPicture; //the current picture don't know if I need it somewhere but for complete understanding of code

imageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //Intent for the on-board camera
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        //device has camera
        if(takePictureIntent.resolveActivity(getPackageManager()) != null) {
            File photoFile = null;
            try {
                //create a file with path the code below
                photoFile = createImageFile(); //sets photoFile to: /data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
            } catch (IOException e) {
                e.printStackTrace();
            }
            //file has been created, set members and add Extra to intent, then start intent.
            if(photoFile != null) {
                mCurrentPicture = photoFile; // well, same as above
                mCurrentPhotoUri = Uri.fromFile(photoFile); // this looks somehow wrong, but I don't know much about URIs: file:///data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile)); //same URI as above that extra should be needed to tell the cam that I don't want to save to the default path but my app path
                startActivityForResult(takePictureIntent, 10); //start the intent and use requestcode 10 for onActivityResult ...
            }
        }
    }
});

因此相机打开,我可以拍照,我问是否要保存该照片(所有这些都来自内置相机应用程序,设备是三星星系注释)。

然后调用我的onActivityResult-Method: 我使用数据作为参数,因为我使用了迷你字节数组,但是使用自定义存储,它返回null 并且它不再被使用

//code from google developers with some changes. 
private File createImageFile() throws IOException {
        String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); //from today value: 20151105_092219
        String imageFilename = "JPEG_" + timestamp + "_"; // concat is this: JPEG_20151105_092219_
        File storageDir = this.getDir("photo", MODE_PRIVATE); //String path is: /data/data/my.app.project/app_photo
        storageDir.mkdirs();
        File image = File.createTempFile(imageFilename, ".jpg", storageDir); //String path is: /data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
        mCurrentPhotoPath = "file:" + image.getAbsolutePath(); //here I put the absolute path into static mCurrentPhotoPath, concate with the "file:" from googledeveloper guide: file:/data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
        return image;
}

方法setImageView:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        switch(requestcode) {
            ...
            case 10:
                setImageView(ivPreview1, data, 0);
                ivPreview.setVisibility(View.VISIBLE);
                break;
            ...
        }
    ...
    }
}

我用来解码文件的以下方法(自定义:http://developer.android.com/downloads/samples/DisplayingBitmaps.zip):

BitmapFactory.decodeFile(filename,options)的行;还会创建一个日志条目:D / skia:--- SkImageDecoder :: Factory返回null

private void setImageView(ImageView iv, Intent data, int index) {
        try {
            Uri u = mCurrentPhotoUri; //sets u to: file:///data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg

            File file = new File(u.getPath()); //sets file to: /data/data/my.app.project/app_photo/JPEG_20151105_092219_-1434131481.jpg
            Bitmap bm = null;
            ByteArrayOutputStream baos = null;
            int orientation = 0;
            if (file.exists()) { //this is true

                //found that somewhere in the developer training:
                ExifInterface exif = null;
                try {
                    exif = new ExifInterface(photoUri.getPath());
                } catch (IOException e) {
                    e.printStackTrace();
                }

                if(exif != null)
                    orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0); //is 0 (i didn't rotate the tablet)

                //resulution I want to resize the image to:
                int reqWidth = 960, reqHeight = 1280;

                //exchange values if orientation doesn't match landscape
                if (orientation == 0 || orientation == 270) {
                    int temp = reqWidth;
                    reqWidth = reqHeight;
                    reqHeight = temp;

                }
                //this I used before I changed to internal storage to change the size of the image code below
                bm = ImageManager.decodeSampledBitmapFromFile(u.getPath(), reqWidth, reqHeight); // returns null because of this everything following is null too.

                if (orientation == 90 || orientation == 180 || orientation == 270) {
                    Matrix matrix = new Matrix();
                    // rotate the Bitmap

                    if (orientation == 90)
                        matrix.postRotate(90F);
                    else if (orientation == 270)
                        matrix.postRotate(-90F);
                    else
                        matrix.postRotate(180F);

                    // recreate the new Bitmap
                    bm = Bitmap.createBitmap(bm, 0, 0,
                            bm.getWidth(), bm.getHeight(), matrix, true);
                }
                baos = new ByteArrayOutputStream();
                bm.compress(Bitmap.CompressFormat.JPEG, 50, baos);
            }

            iv.setImageBitmap(bm);

        } catch (Exception e) {
            e.printStackTrace();
                Log.e(TAG, "Could not take Photo: ", e);
        }
    }

我已经坚持了好几天了,现在我没有任何想法可以解决我的问题。这也是由于缺乏Android知识以及我无法在我的电脑上使用模拟器这一事实,所以我甚至无法查看应用程序文件夹以查看是否拍摄了照片。

1 个答案:

答案 0 :(得分:1)

尝试获取存储临时图像的路径,如下所示。这将返回您的应用程序文件夹位置。并添加权限。

 File dir = context.getExternalFilesDir(null)+"/"+"photo";
  

为相机访问添加用途功能。

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

官方documentation