taking studio picture open intent data and action_image_capture android android-camera android-imageview

studio - Cámara Android: la intención de datos devuelve nulo



startactivityforresult camera (7)

Aplicación de cámara de trabajo simple que evita el problema de intento nulo

- todo el código modificado incluido en esta respuesta; cerca de tutorial de Android

Estuve pasando mucho tiempo sobre este tema, así que decidí crear una cuenta y compartir mis resultados contigo.

El tutorial oficial de Android "Taking Photos Simply" resultó no ser lo que prometía. El código provisto allí no funcionaba en mi dispositivo: un Samsung Galaxy S4 Mini GT-I9195 con Android 4.4.2 / KitKat / API Level 19.

Descubrí que el problema principal era la siguiente línea en el método invocado al capturar la foto ( dispatchTakePictureIntent en el tutorial):

takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);

Resultó en el intento subsecuentemente atrapado por onActivityResult siendo nulo.

Para resolver este problema, saqué mucha inspiración de las respuestas anteriores aquí y algunos mensajes útiles sobre github (sobre todo este de deepwinter , gracias a él, tal vez desee consultar su respuesta en una post estrechamente relacionada también).

Siguiendo estos agradables consejos, elegí la estrategia de eliminar la mencionada línea putExtra y hacer lo que correspondía para recuperar la imagen tomada de la cámara dentro del método onActivityResult (). Las líneas de código decisivas para recuperar el mapa de bits asociado con la imagen son:

Uri uri = intent.getData(); Bitmap bitmap = null; try { bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri); } catch (IOException e) { e.printStackTrace(); }

Creé una aplicación ejemplar que solo tiene la capacidad de tomar una foto, guardarla en la tarjeta SD y mostrarla. Creo que esto podría ser útil para personas en la misma situación que yo cuando tropecé con este tema, ya que las sugerencias de ayuda actuales se refieren principalmente a publicaciones github bastante extensas que hacen lo que se pregunta pero no son demasiado fáciles de supervisar para novatos como yo. Con respecto al sistema de archivos que Android Studio crea por defecto al crear un nuevo proyecto, solo tuve que cambiar tres archivos para mi propósito:

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.android.simpleworkingcameraapp.MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="takePicAndDisplayIt" android:text="Take a pic and display it." /> <ImageView android:id="@+id/image1" android:layout_width="match_parent" android:layout_height="200dp" /> </LinearLayout>

MainActivity.java:

package com.example.android.simpleworkingcameraapp; import android.content.Intent; import android.graphics.Bitmap; import android.media.Image; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.Toast; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class MainActivity extends AppCompatActivity { private ImageView image; static final int REQUEST_TAKE_PHOTO = 1; String mCurrentPhotoPath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); image = (ImageView) findViewById(R.id.image1); } // copied from the android development pages; just added a Toast to show the storage location private File createImageFile() throws IOException { // Create an image file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmm").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File image = File.createTempFile( imageFileName, /* prefix */ ".jpg", /* suffix */ storageDir /* directory */ ); // Save a file: path for use with ACTION_VIEW intents mCurrentPhotoPath = image.getAbsolutePath(); Toast.makeText(this, mCurrentPhotoPath, Toast.LENGTH_LONG).show(); return image; } public void takePicAndDisplayIt(View view) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (intent.resolveActivity(getPackageManager()) != null) { File file = null; try { file = createImageFile(); } catch (IOException ex) { // Error occurred while creating the File } startActivityForResult(intent, REQUEST_TAKE_PHOTO); } } @Override protected void onActivityResult(int requestCode, int resultcode, Intent intent) { if (requestCode == REQUEST_TAKE_PHOTO && resultcode == RESULT_OK) { Uri uri = intent.getData(); Bitmap bitmap = null; try { bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri); } catch (IOException e) { e.printStackTrace(); } image.setImageBitmap(bitmap); } } }

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.simpleworkingcameraapp"> <!--only added paragraph--> <uses-feature android:name="android.hardware.camera" android:required="true" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- only crucial line to add; for me it still worked without the other lines in this paragraph --> <uses-permission android:name="android.permission.CAMERA" /> <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"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>

Tenga en cuenta que la solución que encontré para el problema también condujo a una simplificación del archivo de manifiesto de Android: los cambios sugeridos por el tutorial de Android en términos de agregar un proveedor ya no son necesarios ya que no estoy utilizando ninguno en mi código de Java. Por lo tanto, solo unas pocas líneas estándar -sobre todo con respecto a los permisos- tuvieron que agregarse al archivo de manifiesto.

También podría ser valioso señalar que la autoimportación de Android Studio puede no ser capaz de manejar java.text.SimpleDateFormat y java.util.Date . Tuve que importarlos a ambos manualmente.

Tengo una aplicación para Android que contiene múltiples actividades.

En uno de ellos estoy usando un botón que llamará a la cámara del dispositivo:

public void onClick(View view) { Intent photoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(photoIntent, IMAGE_CAPTURE); }

En la misma actividad, llamo al método OnActivityResult para el resultado de la imagen:

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == IMAGE_CAPTURE) { if (resultCode == RESULT_OK) { Bitmap image = (Bitmap) data.getExtras().get("data"); ImageView imageview = (ImageView) findViewById(R.id.pic); imageview.setImageBitmap(image); } else if (resultCode == RESULT_CANCELED) { Toast.makeText(this, "CANCELED ", Toast.LENGTH_LONG).show(); } } }

El problema es que los data intención son nulos y el método OnActivityResult se dirige directamente a (resultCode == RESULT_CANCELED) y la aplicación vuelve a la actividad anterior.

¿Cómo puedo solucionar este problema y, después de llamar a la cámara, la aplicación vuelve a la actividad actual que contiene un ImageView que contendrá la imagen tomada?

Gracias


El siguiente código funciona para mí:

Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(cameraIntent, 2);

Y aqui esta el resultado:

protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { super.onActivityResult(requestCode, resultCode, imageReturnedIntent); if(resultCode == RESULT_OK) { Uri selectedImage = imageReturnedIntent.getData(); ImageView photo = (ImageView) findViewById(R.id.add_contact_label_photo); Bitmap mBitmap = null; try { mBitmap = Media.getBitmap(this.getContentResolver(), selectedImage); } catch (IOException e) { e.printStackTrace(); } } }


Encontré una respuesta fácil. ¡¡funciona!!

o

private void openCameraForResult(int requestCode){ Intent photo = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri uri = Uri.parse("file:///sdcard/photo.jpg"); photo.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(photo,requestCode); } if (requestCode == CAMERA_REQUEST_CODE) { if (resultCode == Activity.RESULT_OK) { File file = new File(Environment.getExternalStorageDirectory().getPath(), "photo.jpg"); Uri uri = Uri.fromFile(file); Bitmap bitmap; try { bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri); bitmap = crupAndScale(bitmap, 300); // if you mind scaling pofileImageView.setImageBitmap(bitmap); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

si desea recortar y escalar esta imagen

public static Bitmap crupAndScale (Bitmap source,int scale){ int factor = source.getHeight() <= source.getWidth() ? source.getHeight(): source.getWidth(); int longer = source.getHeight() >= source.getWidth() ? source.getHeight(): source.getWidth(); int x = source.getHeight() >= source.getWidth() ?0:(longer-factor)/2; int y = source.getHeight() <= source.getWidth() ?0:(longer-factor)/2; source = Bitmap.createBitmap(source, x, y, factor, factor); source = Bitmap.createScaledBitmap(source, scale, scale, false); return source; }


Está pasando el código de acción para grabar el video, pero trata el resultado como una foto.


La aplicación de cámara predeterminada de Android devuelve un intento no nulo solo al reenviar una miniatura en el Intento devuelto. Si pasa EXTRA_OUTPUT con un URI para escribir, devolverá un intento null y la imagen estará en el URI que pasó.

Puede verificar esto mirando el código fuente de la aplicación de la cámara en GitHub:

Supongo que está pasando EXTRA_OUTPUT alguna manera, o la aplicación de la cámara en su teléfono funciona de manera diferente.



Probablemente porque tuviste algo como esto?

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri fileUri = CommonUtilities.getTBCameraOutputMediaFileUri(); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); startActivityForResult(takePictureIntent, 2);

Sin embargo, no debe incluir el resultado adicional en la intención, ya que los datos entran en el URI en lugar de en la variable de datos. Por esa razón, debes tomar las dos líneas en el medio, para que tengas

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(takePictureIntent, 2);

Eso es lo que me causó el problema, espero que haya sido de ayuda.