Kodeco Forums

Android: Intents Tutorial

In this Intents tutorial you'll learn what Intents are, the role they play in Android, and how to use them to communicate with other installed apps.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/1780-android-intents-tutorial

Hello… I need your opinion about why is not working this code… thanks… allways goes out in
Toast.makeText(getContext(), “Intent data y ruta de foto Uri estan vacias, saliendo”, Toast.LENGTH_LONG).show();

//PASO 2 INICIAR ACTIVIDAD DEL BOTON PARA LA CAPTURA
public boolean tomarfoto() {
try {
inicia_captura_Intent();
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}

//PASO 3 DE – TOMAR FOTO
public void inicia_captura_Intent() throws IOException {

    Intent tomarfotointent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//inicia captura foto
    newPhotoUri = Uri.fromFile(new File(String.valueOf(crearnombrefoto()))); // Inicia metodo para crear nombre de la foto y almacena nombre
    tomarfotointent.putExtra(MediaStore.EXTRA_OUTPUT, newPhotoUri); // asigna nombre a la foto y la pasa a la camara nativa
    startActivityForResult(tomarfotointent, REQUEST_TAKE_PHOTO);// Inicia la camara nativa
}

//PASO 4 DE – CREAR NOMBRE DE LA FOTO
public File crearnombrefoto() throws IOException {
String timeStamp = new SimpleDateFormat(“yyyyMMdd_HHmmss”,Locale.US).format(new Date());// Crea datos de fecha para nombre de la foto
String imageFileName = “JPEG_” + timeStamp + “_”;
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); //define ruta de almacenamiento
File image = File.createTempFile(imageFileName, “.jpg”, storageDir);//crea nombre de foto completo
mCurrentPhotoPath = “file:” + image.getAbsolutePath();//guarda en variable la ruta de almacenamiento y nombre de foto
return image;
}

//PASO 5 DE -- TOMAR FOTO
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_TAKE_PHOTO) {

        if (resultCode == Activity.RESULT_OK) {
            String resultPath = "";
            if (data == null) {
                if (this.newPhotoUri != null) {

                    Toast.makeText(getContext(), "ruta"+ newPhotoUri.getPath(), Toast.LENGTH_LONG).show();
                    resultPath = this.newPhotoUri.getPath();
                } else {
                    Toast.makeText(getContext(), "Intent data y ruta de foto Uri estan vacias, saliendo", Toast.LENGTH_LONG).show();
                    return;
                }
            } else {
                // Imagen capturada y guardada en la rutaUri especificada en el Intent
                Toast.makeText(getContext(), "Imagen guardada en: " + data.getData(), Toast.LENGTH_LONG).show();

                resultPath = data.getData().toString();
            }

        } else if (resultCode == Activity.RESULT_CANCELED) {
            // Usuario cancela la captura
            Toast.makeText(getContext(), "Cancelado por el usuario", Toast.LENGTH_LONG).show();

        } else {
            // Image capture failed
        }
    }

}

why ? local.properties

sdk.dir=/Users/Walsch/Library/Android/sdk

This code doesn’t run.
in TakePictureActivity.java:115 the app crashes.

is this intended?

It crashed on Huawei P9 Android Vesion 6.0 at createTempFile methods, could you help me about it?
try { imageFile = File.createTempFile( imageFileName, /* prefix */ FILE_SUFFIX_JPG, /* suffix */ storageDir /* directory */ ); } catch (IOException e) { e.printStackTrace(); }

For those of you who are seeing Null for imageFile, it is because after SDK 23, you need additional permission requests from code.

I am running this tutorial code on simulator and have the target SDK version in the gradle file to 22. That is a lazy and easy workaround.

Ok so I fixed the code so the tutorial will work on SDK23+. Basically you need to ask for a permission to write to external directory.

  1. Add the following line to build.grade (Module: app) and sync.
compile 'com.android.support:support-v4:25.0.0'
  1. Add import statements to TakePictureActivity
import android.support.v4.content.ContextCompat;
import android.support.v4.app.ActivityCompat;
  1. Modify the following functions in TakePictureActivity to ask for permission. If no permission is granted, tapping takePictureImageView does nothing.
private void takePictureWithCamera() {
    if (appHasExternalStorageWritePermission()) {
        // create intent to capture image from camera
        Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File photoFile = createImageFile();
        selectedPhotoPath = Uri.parse(photoFile.getAbsolutePath());
        captureIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
        startActivityForResult(captureIntent, TAKE_PHOTO_REQUEST_CODE);
    } else {
        acquireExternalStorageWritePermissionIfNeeded();
    }
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == TAKE_PHOTO_REQUEST_CODE && resultCode == RESULT_OK) {
        setImageViewWithImage();
    }
}
private boolean appHasExternalStorageWritePermission() {
    return ContextCompat.checkSelfPermission(TakePictureActivity.this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            == PackageManager.PERMISSION_GRANTED;
}
private void acquireExternalStorageWritePermissionIfNeeded() {
    // Here, thisActivity is the current activity
    if (!appHasExternalStorageWritePermission()) {
        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(TakePictureActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            // Show an explanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.
        } else {
            // No explanation needed, we can request the permission.
            ActivityCompat.requestPermissions(TakePictureActivity.this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE);
            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    }
}
@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted, yay! Do the
                // contacts-related task you need to do.
                takePictureWithCamera();
            } else {
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }
        // other 'case' lines to check for other
        // permissions this app might request
    }
}

Optionally you can write to internal storage if external storage is not available (not tested)
a. in TakePictureActivity

private File createImageFile() {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    String state = Environment.getExternalStorageState();
    File imageFile = null;
    File storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES + APP_PICTURE_DIRECTORY);
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        storageDir.mkdirs();
        try {
            imageFile = File.createTempFile(
                    imageFileName,  /* prefix */
                    FILE_SUFFIX_JPG,         /* suffix */
                    storageDir      /* directory */
            );
        } catch (IOException e) {
            //ask for permission here if the permission was denied
            // Log data here
            //ContextWrapper cw = new ContextWrapper(getApplicationContext());
            //imageFile = new File(cw.getFilesDir(), imageFileName);
        }
    } else {
        ContextWrapper cw = new ContextWrapper(getApplicationContext());
        imageFile = new File(cw.getFilesDir(), imageFileName);
    }
    return imageFile;
}

b. in EnterTextActivity

private void saveImageToGallery(Bitmap memeBitmap) {
    if (!originalImage) {
        // save bitmap to file
        String state = Environment.getExternalStorageState();
        File imageFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES + APP_PICTURE_DIRECTORY), memeBitmap + FILE_SUFFIX_JPG);
        if (!Environment.MEDIA_MOUNTED.equals(state)) {
            ContextWrapper cw = new ContextWrapper(getApplicationContext());
            imageFile = new File(cw.getFilesDir(), memeBitmap + FILE_SUFFIX_JPG);
        }
        try {
            // create outputstream, compress image and write to file, flush and close outputstream
            FileOutputStream fos = new FileOutputStream(imageFile);
            memeBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fos);
            fos.flush();
            fos.close();
        } catch (IOException e) {
            Toast.makeText(this, getResources().getText(R.string.save_image_failed).toString(), Toast.LENGTH_SHORT).show();
        }
        // Create intent to request newly created file to be scanned, pass picture uri and broadcast intent
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        mediaScanIntent.setData(Uri.fromFile(imageFile));
        sendBroadcast(mediaScanIntent);
        Toast.makeText(this, getResources().getText(R.string.save_image_succeeded).toString(), Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(this, getResources().getText(R.string.add_meme_message).toString(), Toast.LENGTH_SHORT).show();
    }
}

Not coded: it is a good idea to delete the temporary file after saving the file, or when users tap back from EnterTextActivity to not increase the app directory size.