Questions about using the camera, via Intent

1

Good afternoon everyone, I started a training course about two months ago and both this community and the foreign Stack have been my best friends on this new journey.

Currently I'm developing an application through the IDE Android Studio 2.1.2 and I came across some issues when using the native camera API in the project. I need to take a picture with the camera, save this photo in some folder, preferably cache, and do not make this photo available in the media or any other application, just mine.

I've already used the Direct Intent of the camera and every solution I'm looking for I lock at some point.

If I choose a Path to save the photo, the date of onResultActivity comes as Null. If I save without passing the path, it gets saved in the cell gallery. I try to create a cache folder to save the photo, but it gives an error when creating the directory. And if you create the directory, saved in a folder for the APP photos and also shows in the media.

I do not know if I have to use the programmatic mode to use the camera or if what I want I can resolve with the camera's native Intent.

EDIT: I will put the last code that I executed for better understanding.

private void abrirCamera(){
    // create Intent to take a picture and return control to the calling application
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    //fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
    //intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

    // start the image capture Intent
    startActivityForResult(intent, CAM_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAM_REQUEST) {
        if (resultCode == RESULT_OK) {
            // Image captured and saved to fileUri specified in the Intent
            //Toast.makeText(this, "Image saved to:\n" +
            //        data.getData(), Toast.LENGTH_LONG).show();

            Bundle extras = data.getExtras();
            bitmap = (Bitmap) extras.get("data");
            img.setImageBitmap(bitmap);

            AtualizaCor task = new AtualizaCor();
            task.execute(new String[] { "http://www.vogella.com/index.html" });
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the image capture
        } else {
            // Image capture failed, advise user
        }
    }
}

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
    return Uri.fromFile(getOutputMediaFile(type));
}

/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                "IMG_"+ timeStamp + ".jpg");
    } else {
        return null;
    }

    return mediaFile;
}

I've commented these two lines here:

//fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
//intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

Because they were bringing the date as Null. And I need it to leave a preview of the photo in a thumbnail.

    
asked by anonymous 16.08.2016 / 17:49

1 answer

2

The camera application is not allowed to write to the internal storage of your application.

But you can (See note) write to the external storage that is assigned to your application.

Files saved in this area will be deleted when your application is uninstalled and will not appear in Gallery.

The following code allows you to use the camera application to take a picture and display it in an ImageView .

The image is saved in the primary shared / external storage of the device in the area reserved for your application.

The full path depends on the device and will be anything like this:

  

/storage/sdcard0/Android/data/nome.da.sua.package/files/Pictures/MyCameraApp/IMG_20160817_000919.jpg

public class MainActivity extends AppCompatActivity {

    private static final int CAM_REQUEST = 1;
    private ImageView img;
    private Uri fileUri;

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

        img = (ImageView)findViewById(R.id.imagem);
        abrirCamera();
    }

    private void abrirCamera(){

        // cria um Uri com o caminho do arquivo para guardar a foto
        //ex: /storage/sdcard0/Android/data/nome.da.sua.package/files/Pictures/MyCameraApp/IMG_20160817_000919.jpg
        fileUri = getOutputPictureUri("MyCameraApp");

        if(fileUri != null) {

            // Cria o intent para chamar a câmara
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            // seta o caminho do arquivo para guardar a foto
            intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

            // inicia a captura da foto
            startActivityForResult(intent, CAM_REQUEST);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CAM_REQUEST) {
            if (resultCode == RESULT_OK) {

                //Lê a foto gravada, redimensiona para 300x300 e coloca-a
                // na ImageView
                img.setImageBitmap(decodeSampledBitmapFromFile(fileUri, 300, 300));

            } else if (resultCode == RESULT_CANCELED) {
                Toast.makeText(this, "Captura da foto cancelada", Toast.LENGTH_LONG)
                     .show();
            } else {
                Toast.makeText(this, "Captura da foto falhou", Toast.LENGTH_LONG)
                     .show();
            }
        }
    }

    // Retorna um Uri com o caminho do arquivo para guardar a foto
    private Uri getOutputPictureUri(String pasta){

        String mm = Environment.MEDIA_MOUNTED;
        String externalStorageState = Environment.getExternalStorageState();
        if(!Environment.MEDIA_MOUNTED.equals(externalStorageState) ||
           Environment.MEDIA_MOUNTED_READ_ONLY.equals(externalStorageState)){
            return null;
        }


        File mediaStorageDir = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), pasta);

        // Cria a pasta se não existir
        if (! mediaStorageDir.exists()){
            if (! mediaStorageDir.mkdirs()){
                Toast.makeText(this,pasta, Toast.LENGTH_LONG).show();
                return null;
            }
        }

        // Cria o path completo com o nome da foto
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                                  "IMG_"+ timeStamp + ".jpg");
        return Uri.fromFile(mediaFile);
    }

    public static Bitmap decodeSampledBitmapFromFile(Uri fileUri,
                                                     int reqWidth, int reqHeight) {

        String path = fileUri.getPath();

        // Primeiro faz o decode com inJustDecodeBounds=true para obter as dimensões
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        // Calcula as novas dimensões
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Faz o decode do bitmap e redimensiona
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(path);
    }

    public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {

        // Altura e largura da imagem
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            //Calcula o maior valor de inSampleSize, que é uma potência de 2,
            // que mantém altura e o comprimento maiores do que os valores pedidos.
            while ((halfHeight / inSampleSize) >= reqHeight
                    && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }
}

Notes:

  • If the application is to run on devices with API Level below 19, the following permission is required:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
  • If targetSdkVersion is 24 or higher, you should consider changes to permissions that impact file sharing. See how this response .

  • If you want to save the photos in a public folder (so that the photo is not deleted when your app is uninstalled) use Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES) .

17.08.2016 / 01:58