Doubts regarding the use of the camera, via Intent

Asked

Viewed 1,332 times

1

Good afternoon everyone, I started an internship a couple of months ago and both this community and the foreign Stack have been my best friends on this new journey.

Currently I am developing an app by Android IDE Studio 2.1.2 and have come across some problems using the camera’s native API in the project. I need to take a photo with the camera, save this photo in some folder, cache preferably, and not make this photo available on the media or for any other application, only mine.

I’ve used the Intent straight from the camera and every solution I seek I catch 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, he’s safe in the mobile gallery. I try to create a cache folder to save the photo, but it gives error when creating the directory. And if you create the directory, save in a folder to the photos of the APP and also shows in the media.

I don’t know if I have to use the programmatic mode to use the camera or if what I want I can solve with the native Intent of the camera.

EDIT: I’ll put in the last code 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 commented on 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 photo preview in a thumbnail.

  • If you pass one path does not need the date, the photo is recorded on path. Without knowing what code you’re using It’s hard to know what’s wrong.

  • Note that in order to use the lines you have commented on you have to add the permission WRITE_EX TERNAL_STORAGE in the Androidmanifest.xml: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />&#xA;

  • are already added

  • In one of the searches I did I saw that to use the file saved only in my APP, you have to save them in the internal memory. So that way that I maintain control, secrecy and when the APP is deleted, the photos will also be. If you still have it in the folder, because I want to use a Cache folder.

  • The camera application cannot write to the internal memory of your application, it has no permissions.

  • In some researches I saw that to save in internal memory the APP does not need permissions. As I am opening the camera by APP then it could not record the image in internal memory?

  • This is true for your application. Although it is "called" by its application the camera is another application.

  • Then I need to use the fully programmed camera. Open the camera, open preview screen, preview and tals? Does this resolve?

  • Yes but it’s a bit complicated. If you want the photos to be deleted by uninstalling the app and not appear "in the media" File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(&#xA; Environment.DIRECTORY_PICTURES), "MyCameraApp"); use File mediaStorageDir = new File(getExternalFilesDir(), "MyCameraApp");

Show 4 more comments

1 answer

2


The camera app is not allowed to record on Storage of its application.

But it can(See note) engrave on the Sxternal assigned to its application.

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

The following code allows you to use the camera application to take a photo and present it in a Imageview.

The image is recorded in Primary Shared/Xternal Storage device, in the area reserved for your application.

The full path depends on the device and it will be something like:

/Storage/sdcard0/Android/data/name.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 for 24 or higher should take into account changes to permissions that impact file sharing. See how in this reply.

  • If you want to save photos in a publish folder (so the photo won’t be deleted when your app is uninstalled) use Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES).

  • Thank you friend! Your solution solved my problems. I’m now studying this code and looking for a way to not burst the smartphone memory while showing the photos in the app’s Activity

  • Resize them, pass low values(necessary) to the method decodeSampledBitmapFromFile(), will not burst.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.