android - picture - La cámara no funciona/se guarda cuando se usa Cache Uri como MediaStore.EXTRA_OUTPUT
onactivityresult camera android (3)
¿Por qué no guardarlo en un archivo nuevo?
final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "MyDir" + File.separator);
root.mkdirs();
final String fname = "img_"+ System.currentTimeMillis() + ".jpg";
final File sdImageMainDirectory = new File(root, fname);
mImageUri = Uri.fromFile(sdImageMainDirectory);
Y luego pasar ese uri al intento.
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
Estoy tratando de obtener la imagen completa después de tomar una foto de un Fragment
.
Si uso el Uri del archivo ( Uri.fromFile(file)
), la cámara no saldrá después de tomar la foto y tocar el botón "ok" (parece que no se puede escribir al Uri o quién sabe qué) .
Usando la String
File
, en la forma de ''/data/data/com.package.bla/cache/img198346262jpg''
, no funciona tan bien (el archivo está ahí, pero está vacío porque la cámara no está guardando nada) .
Lo que intenté hasta ahora:
- Eliminar el archivo después de crearlo, como lo hace este ejemplo . Sin embargo, el archivo no existe después de que la cámara sale.
- Agregado permiso de almacenamiento externo LEER, por si acaso
Así que no tengo idea de por qué la imagen no se está guardando y ya se gastó / perdió mucho tiempo probando y pensando por qué no está funcionando.
Fragmento:
private void launchCamera() {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File outputDir = getActivity().getCacheDir();
File file = null;
try {
file = File.createTempFile("img", "jpg", outputDir);
} catch (IOException e) {
e.printStackTrace();
}
if (file != null) {
mImageUri = Uri.fromFile(file); //using Uri is not even exiting the camera
//mImageUri = File.toString(); //If I use String instead of an Uri, it works better (ie, can accept camera photo)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(cameraIntent, RESULT_TAKE_IMAGE);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
Bitmap original = BitmapFactory.decodeFile(mImageUri.toString(), bounds);
}
}
Código editado, mImageUri. Como expliqué, si uso Uri ni siquiera puedo aceptar la foto en la aplicación de la cámara. El uso de una cadena me permitirá aceptar la foto, aunque la foto no está realmente guardada (es decir, el archivo tiene 0 bytes en su interior).
EXPLICACIÓN : El problema estaba relacionado con guardar en el directorio de caché. Tal vez sea un error, me falta un permiso o la aplicación de la cámara simplemente no puede guardar en el directorio de datos privados de su aplicación. Agregar permiso FLAG_GRANT_WRITE_URI_PERMISSION no lo resolvió. Publicaciones relacionadas: Almacene la imagen de la cámara en el directorio de caché de la aplicación privada Y Guarde los datos de la cámara en la caché cuando se inicie a través de la intención
ACTUALIZACIÓN Desde Android 2.2 en adelante, se puede usar el método getExternalCacheDir()
lugar de getCacheDir()
desde Android 26+ Uri.fromFile no funcionará, debes usar el proveedor de archivos en su lugar.
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
.........
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
res / xml / file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
</paths>
finalmente
final Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
// output file
File path = new File(Environment.getExternalStorageDirectory(), "tmp.mp4");
// com.mydomain.fileprovider is authorities (manifest)
// getUri from file
Uri uri = FileProvider.getUriForFile(this, "com.mydomain.fileprovider", path);
takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(takeVideoIntent, 99);
probado en Android 8.0 y 5.1.1
Actualización: en algunos dispositivos, la cámara incorporada no sería compatible con EXTRA_OUTPUT, por lo que si desea trabajar en todos los dispositivos, cree su propio módulo de cámara.
Intenta esto está trabajando a la perfección conmigo.
private String selectedImagePath = "";
final private int PICK_IMAGE = 1;
final private int CAPTURE_IMAGE = 2;
public Uri setImageUri() {
// Store image in dcim
File file = new File(Environment.getExternalStorageDirectory() + "/DCIM/", "image" + new Date().getTime() + ".png");
Uri imgUri = Uri.fromFile(file);
this.imgPath = file.getAbsolutePath();
return imgUri;
}
public String getImagePath() {
return imgPath;
}
btnGallery.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, ""), PICK_IMAGE);
}
});
btnCapture.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, setImageUri());
startActivityForResult(intent, CAPTURE_IMAGE);
}
});
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_CANCELED) {
if (requestCode == PICK_IMAGE) {
selectedImagePath = getAbsolutePath(data.getData());
imgUser.setImageBitmap(decodeFile(selectedImagePath));
} else if (requestCode == CAPTURE_IMAGE) {
selectedImagePath = getImagePath();
imgUser.setImageBitmap(decodeFile(selectedImagePath));
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
public Bitmap decodeFile(String path) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 70;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE)
scale *= 2;
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeFile(path, o2);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
public String getAbsolutePath(Uri uri) {
String[] projection = { MediaColumns.DATA };
@SuppressWarnings("deprecation")
Cursor cursor = managedQuery(uri, projection, null, null, null);
if (cursor != null) {
int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} else
return null;
}