Ómer
Intento hacer un botón que abra la cámara y tome una foto. mi código está aquí
//for imports check on bottom of this code block
public class HomeProfileActivity extends AppCompatActivity {
//Button camera
public static final String TAG = HomeProfileActivity.class.getSimpleName();
public static final int REQUEST_TAKE_PHOTO = 0;
public static final int REQUEST_TAKE_VIDEO = 1;
public static final int REQUEST_PICK_PHOTO = 2;
public static final int REQUEST_PICK_VIDEO = 3;
public static final int MEDIA_TYPE_IMAGE = 4;
public static final int MEDIA_TYPE_VIDEO = 5;
private Uri mMediaUri;
private ImageView photobutton;
private Button buttonUploadImage, buttonTakeImage;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_profile);
ButterKnife.bind(this);
}
@OnClick(R.id.buttonTakeImage)
void takePhoto() {
mMediaUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
if (mMediaUri == null) {
Toast.makeText(this,
"There was a problem accessing your device's external storage.",
Toast.LENGTH_LONG).show();
}
else {
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, mMediaUri);
startActivityForResult(takePhotoIntent, REQUEST_TAKE_PHOTO);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK){
if (requestCode == REQUEST_TAKE_PHOTO) {
Intent intent = new Intent(this, ViewImageActivity.class);
intent.setData(mMediaUri);
startActivity(intent);
}
}
else if (resultCode != RESULT_CANCELED){
Toast.makeText(this, "Sorry, there was an error", Toast.LENGTH_SHORT).show();
}
}
private Uri getOutputMediaFileUri(int mediaType) {
// check for external storage
if (isExternalStorageAvailable()) {
// get the URI
// 1. Get the external storage directory
File mediaStorageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
// 2. Create a unique file name
String fileName = "";
String fileType = "";
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
if (mediaType == MEDIA_TYPE_IMAGE) {
fileName = "IMG_" + timeStamp;
fileType = ".jpg";
} else if (mediaType == MEDIA_TYPE_VIDEO) {
fileName = "VID_" + timeStamp;
fileType = ".mp4";
} else {
return null;
}
// 3. Create the file
File mediaFile;
try {
mediaFile = File.createTempFile(fileName, fileType, mediaStorageDir);
Log.i(TAG, "File: " + Uri.fromFile(mediaFile));
// 4. Return the file's URI
return Uri.fromFile(mediaFile);
}
catch (IOException e) {
Log.e(TAG, "Error creating file: " +
mediaStorageDir.getAbsolutePath() + fileName + fileType);
}
}
// something went wrong
return null;
}
private boolean isExternalStorageAvailable(){
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)){
return true;
}
else {
return false;
}
}
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import butterknife.ButterKnife;
import butterknife.OnClick;
yo tambien tengo un problema con startActivityForResult
en el método onclick y la importación java.text.SimpleDateFormat;
también salte en el tiempo de ejecución de excepción. Estoy trabajando con buildtoolsversion sdk 25
raul sondarva
Además de la solución que utiliza FileProvider, hay otra forma de evitar esto. Simplemente pon
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
en el método Application.onCreate(). De esta forma, la máquina virtual ignora la exposición del URI del archivo.
-
Esto funcionó para mí, gracias, ¿algo que deba saber para un posible problema futuro o estoy bien por un tiempo?
– Thiago Queiroz
17 de agosto de 2017 a las 11:48
-
StrictMode está deshabilitado de forma predeterminada y los usuarios deben ingresar al “Modo de desarrollador” en su Android para habilitarlo. Eso hace que la solución de usar StrictMode sea irrelevante.
– Tamtom
26 de diciembre de 2017 a las 10:32
-
Gracias, trabajando para mí. Dispositivo de prueba Android: 7.0 targetSdkVersion 26
– DILSHAD AHMAD
21 de junio de 2018 a las 18:59
-
¡Trabajado como un encanto!
– GeekConGafas
7 de agosto de 2019 a las 17:48
-
¿Debería envolver esto solo con SDK versión 24 o superior?
– Abu Nayem
18 de mayo de 2020 a las 6:13
Jared
Esta información es de:
FileUriExposedException
Esto solo se lanza para aplicaciones que apuntan a N o superior. Las aplicaciones destinadas a versiones anteriores del SDK pueden compartir file:// Uri, pero se desaconseja enfáticamente.
Entonces si tu app/build.gradle
archivo compileSdkVersion
(objetivo de compilación) es Android N (API nivel 24) o superior, este error se produce si escribe un archivo al que posiblemente puedan acceder otras aplicaciones. Lo más importante, así es como se supone que debe hacerlo en el futuro:
tomado de aquí:
proveedor de archivos
Cambiar:
return Uri.fromFile(mediaFile);
ser
return FileProvider.getUriForFile(getApplicationContext(), getPackageName()+".fileprovider", mediaFile);
Nota: si controlas mydomain.com
también podrías reemplazar getPackageName()+".fileprovider"
con "com.mydomain.fileprovider"
(lo mismo ocurre con su AndroidManifest.xml
abajo.
También debe agregar lo siguiente a su AndroidManifest.xml
archivo justo antes de su </application>
etiqueta
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
Entonces necesitas agregar un archivo llamado filepaths.xml
para usted app/src/main/res/xml
directorio con los siguientes contenidos
<paths>
<external-files-path name="Pictures" path="Pictures" />
</paths>
Nota: para cualquier otra persona, usamos external-files-path
arriba, ya que Omer usó getExternalFilesDir(Environment.DIRECTORY_PICTURES)
en el código. Para cualquier otra ubicación, consulte proveedor de archivos en la sección “Especificación de archivos disponibles” y cambie external-files-path
a uno de los siguientes según la ubicación de sus archivos:
files-path
cache-path
external-path
external-files-path
external-cache-path
También, revisa Pictures
arriba para que sea el nombre de su carpeta.
Un antipatrón importante que debe evitar es que debe NO usar if (Build.VERSION.SDK_INT < 24) {
permitirte hacerlo a la antigua, porque no es su versión de Android que requiere esto, es su versión de compilación (Me perdí esto la primera vez que lo codifiqué).
Sé que esto es más trabajo, sin embargo, esto permite que Android permita solo la otra aplicación con la que está compartiendo, acceso temporal al archivo, que es más seguro para la privacidad del usuario.
-
Solo edición rápida: la ruta = “imágenes” distingue entre mayúsculas y minúsculas. Al usar Environment.DIRECTORY_PICTURES en mi extremo, tuve que ponerlo en mayúsculas como path=”Pictures”, de lo contrario no podría encontrar una ruta.
–David Sanders
10 de noviembre de 2017 a las 22:59
-
@DaveSanders Gracias por notarlo, actualicé mi respuesta para reflejar el caso de Environment.DIRECTORY_PICTURES, que se evalúa como “Imágenes” (caso del título)
– Jared
15 de diciembre de 2017 a las 2:51
-
por favor, no esa versión de androidX de
FileProvider
tiene paqueteandroidx.core.content.FileProvider
– avispón2319
22 de abril de 2021 a las 11:04
Add the below code where the SharingIntent called:-
if(Build.VERSION.SDK_INT>=24){
try{
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
shareImage(Uri.fromFile(new File(Path)));
}catch(Exception e){
e.printStackTrace();
}
}
Uri.fromFile()
no funcionará en Android 7.0+, con untargetSdkVersion
de 24 o superior. UsarFileProvider
en cambio, como demuestro en esta aplicación de muestra. Ver también esta entrada de blog y esta entrada de blog.– CommonsWare
15 de febrero de 2017 a las 14:30
Consulte la respuesta en esta pregunta: stackoverflow.com/questions/38200282/…
– Spark.Bao
16 de febrero de 2017 a las 3:12
Fácil explicación disponible aquí: enlace
– Conoce a Vora
2 de marzo de 2017 a las 11:35