corrige o erro da camera e da ia não funcionar e mudar o layout futuramente

This commit is contained in:
2026-05-06 12:48:08 +01:00
parent a5ee481b39
commit e480abd98e
30 changed files with 1807 additions and 1039 deletions

View File

@@ -1,146 +1,108 @@
package com.example.pap;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.util.Base64;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.io.ByteArrayOutputStream;
import java.util.Collections;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class FotoActivity extends AppCompatActivity {
private ImageView ivFotoComida;
private Button btnTirarFoto, btnVoltar, btnAddManual, btnConfirmar;
private LinearLayout layoutResultadosIA;
private TextView tvTotalCalorias, tvNomePrato;
private RecyclerView recyclerView;
private IngredientesAdapter adapter;
private ArrayList<Ingrediente> listaIngredientes;
private Button btnTirarFoto, btnAnalisarIA, btnVoltarFoto;
private TextView tvResultadoIA;
private Bitmap imagemCapturada;
// Lançador da Câmara
private final ActivityResultLauncher<Intent> cameraLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
// Recebe a miniatura da foto
Bundle extras = result.getData().getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
ivFotoComida.setImageBitmap(imageBitmap);
// Inicia a simulação da IA
Toast.makeText(this, "A analisar a imagem com IA...", Toast.LENGTH_SHORT).show();
simularAnaliseIA();
}
}
);
// COLA A TUA CHAVE DO OPENROUTER AQUI (Aquela que tiraste sem telemóvel e sem VPN)
private final String MINHA_API_KEY = "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";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_foto);
// Inicializar vistas
ivFotoComida = findViewById(R.id.ivFotoComida);
btnTirarFoto = findViewById(R.id.btnTirarFotoComida);
btnVoltar = findViewById(R.id.btnVoltarFoto);
layoutResultadosIA = findViewById(R.id.layoutResultadosIA);
tvTotalCalorias = findViewById(R.id.tvTotalCalorias);
tvNomePrato = findViewById(R.id.tvNomePratoDetectado);
recyclerView = findViewById(R.id.recyclerViewIngredientes);
btnAddManual = findViewById(R.id.btnAddIngredienteManual);
btnConfirmar = findViewById(R.id.btnConfirmarRefeicao);
btnTirarFoto = findViewById(R.id.btnTirarFoto);
btnAnalisarIA = findViewById(R.id.btnAnalisarIA);
tvResultadoIA = findViewById(R.id.tvResultadoIA);
btnVoltarFoto = findViewById(R.id.btnVoltarFoto);
// Configurar a RecyclerView
listaIngredientes = new ArrayList<>();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new IngredientesAdapter(listaIngredientes);
recyclerView.setAdapter(adapter);
ActivityResultLauncher<Intent> cameraLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
Bundle extras = result.getData().getExtras();
imagemCapturada = (Bitmap) extras.get("data");
// Configurar o clique no botão de apagar (lixo) na lista
adapter.setOnItemClickListener(new IngredientesAdapter.OnItemClickListener() {
ivFotoComida.setPadding(0, 0, 0, 0);
ivFotoComida.setImageBitmap(imagemCapturada);
btnTirarFoto.setVisibility(View.GONE);
btnAnalisarIA.setVisibility(View.VISIBLE);
tvResultadoIA.setText("Prato detetado! Clica em Analisar.");
}
}
);
btnTirarFoto.setOnClickListener(v -> cameraLauncher.launch(new Intent(MediaStore.ACTION_IMAGE_CAPTURE)));
btnAnalisarIA.setOnClickListener(v -> { if (imagemCapturada != null) enviarParaIA(); });
btnVoltarFoto.setOnClickListener(v -> finish());
}
private void enviarParaIA() {
tvResultadoIA.setText("A procurar servidor livre e a analisar... ⏳");
btnAnalisarIA.setEnabled(false);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
imagemCapturada.compress(Bitmap.CompressFormat.JPEG, 60, outputStream);
String base64Image = Base64.encodeToString(outputStream.toByteArray(), Base64.NO_WRAP);
String dataUrl = "data:image/jpeg;base64," + base64Image;
String prompt = "Identifica a comida nesta imagem e diz-me as calorias e macronutrientes num pequeno parágrafo.";
ContentPart textPart = new ContentPart("text", prompt);
ContentPart imagePart = new ContentPart("image_url", new ImageUrl(dataUrl));
Message message = new Message("user", java.util.Arrays.asList(textPart, imagePart));
AiRequest request = new AiRequest(Collections.singletonList(message));
AiApi api = AiConfig.getRetrofit().create(AiApi.class);
api.analisarImagem("Bearer " + MINHA_API_KEY, request).enqueue(new Callback<AiResponse>() {
@Override
public void onDeleteClick(int position) {
removerIngrediente(position);
public void onResponse(Call<AiResponse> call, Response<AiResponse> response) {
btnAnalisarIA.setEnabled(true);
if (response.isSuccessful() && response.body() != null) {
try {
String resultado = response.body().choices.get(0).message.content;
tvResultadoIA.setText(resultado);
} catch (Exception e) { tvResultadoIA.setText("Erro ao ler texto da IA."); }
} else {
try {
String erroReal = response.errorBody() != null ? response.errorBody().string() : "Vazio";
tvResultadoIA.setText("ERRO: " + response.code() + "\n" + erroReal);
} catch (Exception e) { tvResultadoIA.setText("Erro desconhecido."); }
}
}
@Override
public void onFailure(Call<AiResponse> call, Throwable t) {
btnAnalisarIA.setEnabled(true);
tvResultadoIA.setText("Falha na ligação à Internet.");
}
});
btnTirarFoto.setOnClickListener(v -> abrirCamera());
btnVoltar.setOnClickListener(v -> finish());
// Botão para simular adicionar um ingrediente extra manualmente
btnAddManual.setOnClickListener(v -> {
listaIngredientes.add(new Ingrediente("Azeite Extra (1 c.sopa)", 120));
adapter.notifyItemInserted(listaIngredientes.size() - 1);
calcularTotal();
Toast.makeText(this, "Ingrediente adicionado!", Toast.LENGTH_SHORT).show();
});
btnConfirmar.setOnClickListener(v -> {
Toast.makeText(this, "Refeição registada no diário!", Toast.LENGTH_LONG).show();
finish(); // Fecha o ecrã após confirmar
});
}
private void abrirCamera() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
try {
cameraLauncher.launch(takePictureIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, "Erro ao abrir a câmara.", Toast.LENGTH_SHORT).show();
}
}
// Simula a resposta da IA após 2 segundos
private void simularAnaliseIA() {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
// 1. Mostra a área de resultados
layoutResultadosIA.setVisibility(View.VISIBLE);
btnTirarFoto.setText("Tirar Outra Foto");
// 2. Simula os dados detetados
tvNomePrato.setText("Prato detetado: Salada César com Frango");
listaIngredientes.clear();
listaIngredientes.add(new Ingrediente("Peito de Frango Grelhado (150g)", 240));
listaIngredientes.add(new Ingrediente("Alface Romana (200g)", 30));
listaIngredientes.add(new Ingrediente("Molho César (2 c.sopa)", 160));
listaIngredientes.add(new Ingrediente("Croutons (30g)", 120));
listaIngredientes.add(new Ingrediente("Queijo Parmesão (20g)", 80));
// 3. Atualiza a lista e o total
adapter.notifyDataSetChanged();
calcularTotal();
}, 2000); // Espera 2 segundos
}
// Remove um item da lista e atualiza o total
private void removerIngrediente(int position) {
Ingrediente removido = listaIngredientes.get(position);
listaIngredientes.remove(position);
adapter.notifyItemRemoved(position);
calcularTotal();
Toast.makeText(this, "Removido: " + removido.getNome(), Toast.LENGTH_SHORT).show();
}
// Percorre a lista e soma as calorias
private void calcularTotal() {
int total = 0;
for (Ingrediente ing : listaIngredientes) {
total += ing.getCalorias();
}
tvTotalCalorias.setText(total + " kcal");
}
}