corrige o erro da camera e da ia não funcionar e mudar o layout futuramente
This commit is contained in:
@@ -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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user