Estive a fazer um programa em Java, para Android, que permite o utilizador tirar uma foto e gravá-la no dispositivo.
Como em todos os projetos, surgiram muitos percalços, mas o mais complexo foi a dificuldade em gravar a foto.
O erro que surgia era o seguinte:
FileProvider - IllegalArgumentException: Failed to find configured root
E, aparentemente, tinha a ver com uma falta de permissões para escrever na diretoria pretendida, embora eu tenha feito tudo exatamente como estava indicado nos exemplos do Android developers.
Basicamente pode fazer-se tudo como está indicado no site do Android, exceto o conteúdo do ficheiro file_paths.xml, que deve ser alterado para o seguinte, conforme a resposta número seis desta página do stackoverflow.
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
Quanto ao resto do código, aqui fica o código Java, incluindo o processo de pedir permissões ao utilizador para usar a câmara e o sd card. Basta chamar a função takePhoto().
public void takePhoto() {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.CAMERA}, REQUEST_PERMISSION_CAMERA);
} else {
takePhoto2();
}
}
public void takePhoto2() {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_PERMISSION_READ_EXTERNAL_STORAGE);
} else {
takePhoto3();
}
}
public void takePhoto3() {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE);
} else {
takePhoto4();
}
}
public void takePhoto4() {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
) {
Log.d("ERROR", "No permissions!!!");
//Toast.makeText(this, "No permission to take photos", Toast.LENGTH_LONG).show();
return;
} else {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
photoFile = null;
photoFile = getFile();
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(this,"pt.ulusofona.c3places.fileprovider", photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
} else {
Toast.makeText(this, "Problems with the images folder", Toast.LENGTH_LONG).show();
}
}
}
}
String mCurrentPhotoPath;
File photoFolder;
String imageFileName;
File photoFile;
final static int REQUEST_TAKE_PHOTO = 121;
final static int MAX_IMAGE_DIM = 480;
private File getFile() {
photoFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
if(!photoFolder.exists()) { photoFolder.mkdir(); }
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
imageFileName = "JPEG_"+ timeStamp;
File image_file = null;
try {
image_file = File.createTempFile(imageFileName + "_",".jpg",photoFolder);
mCurrentPhotoPath = image_file.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
return image_file;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
switch(requestCode) {
case REQUEST_TAKE_PHOTO:
try {
Bitmap in = MediaStore.Images.Media.getBitmap(getContentResolver(),photoURI);
int max = Math.max(in.getWidth(), in.getHeight());
max = (int)(max/MAX_IMAGE_DIM);
int larg = (int)(in.getWidth()/max);
int alt = (int)(in.getHeight()/max);
Bitmap out = Bitmap.createScaledBitmap(in, larg, alt, false);
File file = new File(photoFolder, imageFileName + ".png");
FileOutputStream fOut;
fOut = new FileOutputStream(file);
out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
in.recycle();
out.recycle();
photoFile.delete();
}catch (Exception e){
e.printStackTrace();
}
break;
}
}
Na função onActivityResult(), antes de gravar a foto, redimensiono-a.