简体   繁体   English

使用意图从相机捕获图像创建空图像文件

[英]Capture Image From Camera using intent creates empty Image file

I followed this tutorial: https://developer.android.com/training/camera/photobasics .我遵循了本教程: https://developer.android.com/training/camera/photobasics I had some errors, but I resolved them and the app was working fine.我有一些错误,但我解决了它们并且应用程序运行正常。 Once you took a picture, the picture would be saved in under this path: Android/data/<YourAppPackageName>/files/Pictures .拍照后,图片将保存在此路径下: Android/data/<YourAppPackageName>/files/Pictures However, after last OS update I'm getting an empty image file with size 0 B!但是,在上次操作系统更新后,我得到了一个大小为 0 B 的空图像文件!

How can I solve this issue?我该如何解决这个问题?

here is my github project: https://github.com/AlineJo/CameraGalleryImage.git这是我的 github 项目: https://github.com/AlineJo/CameraGalleryImage.git

here is my code:这是我的代码:

Manifest.xml清单.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.cameragalleryimage">
    <!--Permission to write to storage-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!--Inform google play that your app can take pictures-->
    <uses-feature
        android:name="android.hardware.camera"
        android:required="true" />


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!-- File provider is a generic way to store image file across different Android SDK, And it enable us to get uri-->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.example.cameragalleryimage.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/img_file_path"></meta-data>
        </provider>


        <activity android:name=".activities.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

UploadImageFragment上传图片片段

package com.example.cameragalleryimage.fragments;


import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;

import com.example.cameragalleryimage.R;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import static android.app.Activity.RESULT_OK;

/**
 * A simple {@link Fragment} subclass.
 */
public class UploadImageFragment extends Fragment implements ChooseDialogFragment.ChooseDialogInterface {


    private static final int PICK_IMAGE = 100;
    private static final int CAPTURE_IMAGE = 200;
    private static final int STORAGE_PERMISSION_REQUEST = 300;
    private Context mContext;
    private Uri mImageUri;
    private ImageView ivImg;

    private TextView tvProgress;
    private ProgressBar progressBar;
    private String mImagePath;

    public UploadImageFragment() {
        // Required empty public constructor
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        mContext = context;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View parentView = inflater.inflate(R.layout.fragment_upload_image, container, false);

        ivImg = parentView.findViewById(R.id.iv_img);
        tvProgress = parentView.findViewById(R.id.tv_progress);
        progressBar = parentView.findViewById(R.id.progressBar);


        Button btnChoose = parentView.findViewById(R.id.btn_choose);
        Button btnUpload = parentView.findViewById(R.id.btn_upload);

        btnChoose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ChooseDialogFragment dialog = new ChooseDialogFragment();
                dialog.setChooseDialogListener(UploadImageFragment.this);
                dialog.show(getChildFragmentManager(), ChooseDialogFragment.class.getSimpleName());
            }
        });


        btnUpload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mImageUri == null) {
                    Toast.makeText(mContext, "Please take an image", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(mContext, "Image URI Found : " + mImageUri.toString(), Toast.LENGTH_LONG).show();
                }
            }
        });
        return parentView;
    }


    @Override
    public void onGalleryButtonClick() {
        Intent i = new Intent();
        i.setType("image/*"); // specify the type of data you expect
        i.setAction(Intent.ACTION_GET_CONTENT); // we need to get content from another act.
        startActivityForResult(Intent.createChooser(i, "choose App"), PICK_IMAGE);
    }

    @Override
    public void onCameraButtonClick() {
        if (isPermissionGranted()) {
            openCamera();
        } else {
            showRunTimePermission();
        }
    }

    private void openCamera() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) {
            // Create the File where the photo should go
            File photoFile = null;
            try {
                photoFile = createImageFile();
            } catch (IOException ex) {
                // Error occurred while creating the File
                Log.d("capture_error", ex.toString());
            }

            // Continue only if the File was successfully created
            if (photoFile != null) {
                mImageUri = FileProvider.getUriForFile(mContext,
                        "com.example.cameragalleryimage.fileprovider",
                        photoFile);

                startActivityForResult(takePictureIntent, CAPTURE_IMAGE);
            }
        }
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && data != null) {
            if (requestCode == CAPTURE_IMAGE) {//img from camera
                Bundle extras = data.getExtras();
                Bitmap imageBitmap = (Bitmap) extras.get("data");
                ivImg.setImageBitmap(imageBitmap);
            } else if (requestCode == PICK_IMAGE) {// img from gallery
                try {
                    Uri imgUri = data.getData();
                    InputStream imageStream = mContext.getContentResolver().openInputStream(imgUri);//2
                    Bitmap selectedImageBitmap = BitmapFactory.decodeStream(imageStream);//3}
                    mImageUri = imgUri;
                    ivImg.setImageBitmap(selectedImageBitmap);

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }

        } else {
            Toast.makeText(mContext, "Unexpected Error Happened while selecting  picture!", Toast.LENGTH_SHORT).show();

        }


    }


    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "IMG_" + timeStamp + "_";
        File storageDir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);// mContext.getExternalCacheDir();
        File image = File.createTempFile(
                imageFileName,  /* prefix */
                ".jpg",         /* suffix */
                storageDir      /* directory */
        );

        // Save a file: path for use with ACTION_VIEW intents
        mImagePath = image.getAbsolutePath();
        return image;
    }


    private boolean isPermissionGranted() {
        return ActivityCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
    }

    public void showRunTimePermission() {
        // Permission is not Granted !
        // we should Request the Permission!
        // put all permissions you need in this Screen into string array
        String[] permissionsArray = {Manifest.permission.WRITE_EXTERNAL_STORAGE};

        //here we requet the permission
        requestPermissions(permissionsArray, STORAGE_PERMISSION_REQUEST);
    }

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

        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // user grants the Permission!
            // you can call the function to write/read to storage here!
            openCamera();

        } else {
            // user didn't grant the Permission we need
            Toast.makeText(mContext, "Please Grant the Permission To use this Feature!", Toast.LENGTH_LONG).show();
        }
    }


}

img_file_path.xml img_file_path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path
        name="my_images"
        path="/" />
    <!--    Android/data/com.example.cameragalleryimage/files/Pictures-->
</paths>

If you are updated to Android10.如果你更新到Android10。 Then use below code snippet.然后使用下面的代码片段。

<application android:requestLegacyExternalStorage="true" ... >
    ...
  </application> 

Super thanks to @CommonsWare and @blackapps comments I was able to get uri and display the captured image非常感谢@CommonsWare 和@blackapps 评论,我能够获取 uri 并显示捕获的图像

You can find the updated GitHub project here: https://github.com/AlineJo/CameraGalleryImage.git您可以在此处找到更新的 GitHub 项目: https://github.com/AlineJo/CameraGalleryImage.git

here is the code I changed:这是我更改的代码:

package com.example.cameragalleryimage.fragments;


import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;

import com.bumptech.glide.Glide;
import com.example.cameragalleryimage.R;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import static android.app.Activity.RESULT_OK;

/**
 * A simple {@link Fragment} subclass.
 */
public class UploadImageFragment extends Fragment implements ChooseDialogFragment.ChooseDialogInterface {


    private static final int PICK_IMAGE = 100;
    private static final int CAPTURE_IMAGE = 200;
    private static final int STORAGE_PERMISSION_REQUEST = 300;
    private Context mContext;
    private Uri mImageUri;
    private ImageView ivImg;

    private TextView tvProgress;
    private ProgressBar progressBar;
    private String mImagePath;

    private File photoFile;

    public UploadImageFragment() {
        // Required empty public constructor
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        mContext = context;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View parentView = inflater.inflate(R.layout.fragment_upload_image, container, false);

        ivImg = parentView.findViewById(R.id.iv_img);
        tvProgress = parentView.findViewById(R.id.tv_progress);
        progressBar = parentView.findViewById(R.id.progressBar);


        Button btnChoose = parentView.findViewById(R.id.btn_choose);
        Button btnUpload = parentView.findViewById(R.id.btn_upload);

        btnChoose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ChooseDialogFragment dialog = new ChooseDialogFragment();
                dialog.setChooseDialogListener(UploadImageFragment.this);
                dialog.show(getChildFragmentManager(), ChooseDialogFragment.class.getSimpleName());
            }
        });


        btnUpload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mImageUri == null) {
                    Toast.makeText(mContext, "Please take an image", Toast.LENGTH_SHORT).show();
                }
               else {
                    Toast.makeText(mContext, "Image URI Found : " + mImageUri.toString(), Toast.LENGTH_LONG).show();
                }
            }
        });
        return parentView;
    }


    @Override
    public void onGalleryButtonClick() {
        Intent i = new Intent();
        i.setType("image/*"); // specify the type of data you expect
        i.setAction(Intent.ACTION_GET_CONTENT); // we need to get content from another act.
        startActivityForResult(Intent.createChooser(i, "choose App"), PICK_IMAGE);
    }

    @Override
    public void onCameraButtonClick() {
        if (isPermissionGranted()) {
            openCamera();
        } else {
            showRunTimePermission();
        }
    }

    private void openCamera() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) {
            // Create the File where the photo should go

            photoFile = null;
            try {
                photoFile = createFileInstance();
            } catch (IOException ex) {
                // Error occurred while creating the File
                Log.d("capture_error", ex.toString());
            }

            // Continue only if the File was successfully created
            if (photoFile != null) {
                mImageUri = FileProvider.getUriForFile(mContext,
                        "com.example.cameragalleryimage.fileprovider",
                        photoFile);


                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); //this code was messing, However adding this code will make "Intent data" (in "onActivityResult") to be null
                Glide.with(mContext).load(mImageUri).into(ivImg);//solution ask glide to load the image using uri

                startActivityForResult(takePictureIntent, CAPTURE_IMAGE);

            }
        }
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && data != null) {
            if (requestCode == PICK_IMAGE) {// img from gallery
                try {
                    Uri imgUri = data.getData();
                    InputStream imageStream = mContext.getContentResolver().openInputStream(imgUri);//2
                    Bitmap selectedImageBitmap = BitmapFactory.decodeStream(imageStream);//3}
                    mImageUri = imgUri;
                    ivImg.setImageBitmap(selectedImageBitmap);

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }

        } else {
            if (requestCode == CAPTURE_IMAGE) {
                if (photoFile.length() == 0) {
                    Toast.makeText(mContext, "You took an image, but you canceled it!", Toast.LENGTH_SHORT).show();
                    mImageUri = null;
                }

            }
        }


    }


    private File createFileInstance() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "IMG_" + timeStamp + "_";
        File storageDir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);// mContext.getExternalCacheDir();
        File image = new File(storageDir.toString()+"/"+imageFileName+".png");
        // Save a file: path for use with ACTION_VIEW intents
        mImagePath = image.getAbsolutePath();
        return image;
    }


    private boolean isPermissionGranted() {
        return ActivityCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
    }

    public void showRunTimePermission() {
        // Permission is not Granted !
        // we should Request the Permission!
        // put all permissions you need in this Screen into string array
        String[] permissionsArray = {Manifest.permission.WRITE_EXTERNAL_STORAGE};

        //here we requet the permission
        requestPermissions(permissionsArray, STORAGE_PERMISSION_REQUEST);
    }

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

        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // user grants the Permission!
            // you can call the function to write/read to storage here!
            openCamera();

        } else {
            // user didn't grant the Permission we need
            Toast.makeText(mContext, "Please Grant the Permission To use this Feature!", Toast.LENGTH_LONG).show();
        }
    }


}

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

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