I'm trying to create an app, and part of it is using the camera to take a picture, which will automatically be shortened and saved in folders separated by year / month / imgHora.jpg.
For older versions the code worked, but for newer versions it is giving error. I have seen several similar questions in English and Portuguese, but I could not solve it, if someone can give me a help thank you. I've tried using Provider, but I just added everything. The main error is this:
android.os.FileUriExposedException: file: ///storage/emulated/0/Pictures/CamMur/2018/October/28_182120.jpg exposed beyond app through ClipData.Item.getUri ()
Regarding:
mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(caminho)));
Another thing, I want you to click on the button again, it will generate a new image. If someone has a solution that is better than mine, welcome. Without it, the first time I enter the program and click the button it generates an image and saves it, but if I click again on the button it overlaps the previous photo.
Intent intent = getIntent();
finish();
startActivity(intent);
Complete code:
package com.example.admin.camera;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
public static final int PROCESSO_TIRAR_FOTO = 10;
private Context context;
private ImageView iv_foto;
private Button btn_tf;
private int largura;
private int altura;
private String caminho;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.telainicial);
iniciarVariaveis(savedInstanceState);
iniciarAcoes();
}
@Override
//se a tela morrer, faz cast e recria a tela;
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("largura", largura);
outState.putInt("altura", altura);
outState.putString("caminho", caminho);
super.onSaveInstanceState(outState);
}
private void iniciarVariaveis(Bundle savedInstanceState) {
//bundle variavel de cache
context = getBaseContext();
//
iv_foto = findViewById(R.id.iv_foto);
btn_tf = findViewById(R.id.btn_tf);
//Permissão para acessar camera
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.CAMERA}, 0);
}
//
//Analisa savedInstance para recuperar os valores e inicializar as variaveis
if (savedInstanceState != null) {
altura = savedInstanceState.getInt("altura");
largura = savedInstanceState.getInt("largura");
//
caminho = savedInstanceState.getString("caminho");
} else {
File path;
File dir;
String timeYear;
String timeMoth;
String timeDayHour;
String timeAll;
timeYear = new SimpleDateFormat("yyyy", Locale.getDefault()).format(new Date());
timeMoth = new SimpleDateFormat("MMMM", Locale.getDefault()).format(new Date());
timeDayHour ="/" + new SimpleDateFormat("dd_HHmmss", Locale.getDefault()).format(new Date()) + ".jpg";
timeAll = "CamMur/" +timeYear + "/" + timeMoth ;
//Cria pasta com nome CamMUR e um arquivo temporário foto.jpg
path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
dir = new File(path, timeAll);
if (!dir.exists()) {
if (!dir.mkdirs()) {
Log.d("LabCamera", "Pasta não criada");
}
}
caminho = dir.getPath() + timeDayHour ;
}
}
private void iniciarAcoes() {
btn_tf.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = getIntent();
finish();
startActivity(intent);
largura = iv_foto.getWidth();
altura = iv_foto.getHeight();
//
//chamar camera
//não é de forma explicita, pois não sei a classe que chama a camera
Intent mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//saida da foto pro caminho criado;
mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(caminho)));
//
startActivityForResult(mIntent, PROCESSO_TIRAR_FOTO);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PROCESSO_TIRAR_FOTO && resultCode == RESULT_OK) {
configurarImagem(resultCode);
} else {
Toast.makeText(context, "Operação Cancelada", Toast.LENGTH_SHORT).show();
}
}
private void configurarImagem(int resultCode) {
int larguraFOTO;
int alturaFOTO;
//Não gera um bitmap. Ele inicializa a variavel options com as informações
// vindas da imagem: altura e largura;
BitmapFactory.Options options = new BitmapFactory.Options();
//não consome a foto
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(caminho, options);
larguraFOTO = options.outWidth;
alturaFOTO = options.outHeight;
//Divide a largura da foto pela largura do ImageView
int escala = Math.min(larguraFOTO /largura, alturaFOTO/altura);
options.inJustDecodeBounds = false;
options.inSampleSize = escala;
//GERA O BITMAP
Bitmap bm = BitmapFactory.decodeFile(caminho, options);
iv_foto.setImageBitmap(bm);
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.admin.camera">
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<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"
android:configChanges="orientation"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>