From e9b2c02134adcba68db54d4ff32c9f96996094c9 Mon Sep 17 00:00:00 2001 From: t22couch <thibaud.couchet@imt-atlantique.net> Date: Tue, 25 Mar 2025 16:40:55 +0100 Subject: [PATCH] UE TERMINEE MANQUE COMMENTAIRES --- app/src/main/AndroidManifest.xml | 4 + .../myfirstapplication/AddMarkerActivity.java | 139 ++++++++++++++++++ .../myfirstapplication/MapsFragment.java | 90 ++++++++---- .../MarkerDetailActivity.java | 30 ++++ .../myfirstapplication/MyMarkerData.java | 49 ++++++ .../main/res/layout/activity_add_marker.xml | 34 +++++ .../res/layout/activity_marker_detail.xml | 24 +++ 7 files changed, 344 insertions(+), 26 deletions(-) create mode 100644 app/src/main/java/fr/imt_atlantique/myfirstapplication/AddMarkerActivity.java create mode 100644 app/src/main/java/fr/imt_atlantique/myfirstapplication/MarkerDetailActivity.java create mode 100644 app/src/main/java/fr/imt_atlantique/myfirstapplication/MyMarkerData.java create mode 100644 app/src/main/res/layout/activity_add_marker.xml create mode 100644 app/src/main/res/layout/activity_marker_detail.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e610a7c..2d57f52 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,8 @@ <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> + <uses-permission android:name="android.permission.CAMERA" /> + <uses-feature android:name="android.hardware.camera" android:required="false"/> <queries> <intent> @@ -56,6 +58,8 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + <activity android:name=".AddMarkerActivity" /> + <activity android:name=".MarkerDetailActivity" /> </application> </manifest> \ No newline at end of file diff --git a/app/src/main/java/fr/imt_atlantique/myfirstapplication/AddMarkerActivity.java b/app/src/main/java/fr/imt_atlantique/myfirstapplication/AddMarkerActivity.java new file mode 100644 index 0000000..9912614 --- /dev/null +++ b/app/src/main/java/fr/imt_atlantique/myfirstapplication/AddMarkerActivity.java @@ -0,0 +1,139 @@ +package fr.imt_atlantique.myfirstapplication; + +import android.app.Activity; +import android.Manifest; +import android.app.AlertDialog; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.provider.MediaStore; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import java.io.ByteArrayOutputStream; + +public class AddMarkerActivity extends AppCompatActivity { + + private static final int REQUEST_IMAGE_CAPTURE = 1; + private static final int REQUEST_CAMERA_PERMISSION = 2; + private static final String KEY_TITLE = "key_title"; + private static final String KEY_IMAGE = "key_image"; + private Bitmap markerImage = null; + private double lat, lng; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_add_marker); + + EditText titleInput = findViewById(R.id.markerTitleInput); + ImageView photoPreview = findViewById(R.id.markerPhotoPreview); + Button takePhotoBtn = findViewById(R.id.takePhotoBtn); + Button validateBtn = findViewById(R.id.validateBtn); + + lat = getIntent().getDoubleExtra("lat", 0); + lng = getIntent().getDoubleExtra("lng", 0); + + takePhotoBtn.setOnClickListener(v -> { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) + != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.CAMERA}, + REQUEST_CAMERA_PERMISSION); + } else { + launchCamera(); + } + }); + + validateBtn.setOnClickListener(v -> { + Intent result = new Intent(); + result.putExtra("title", titleInput.getText().toString()); + result.putExtra("lat", lat); + result.putExtra("lng", lng); + + if (markerImage != null) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + markerImage.compress(Bitmap.CompressFormat.PNG, 100, stream); + result.putExtra("image", stream.toByteArray()); + } + + setResult(Activity.RESULT_OK, result); + finish(); + }); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK && data != null) { + markerImage = (Bitmap) data.getExtras().get("data"); + + ImageView preview = findViewById(R.id.markerPhotoPreview); + preview.setImageBitmap(markerImage); + } + } + + private void launchCamera() { + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if (takePictureIntent.resolveActivity(getPackageManager()) != null) { + startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + + if (requestCode == REQUEST_CAMERA_PERMISSION) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + launchCamera(); + } else { + Toast.makeText(this, "Permission caméra refusée", Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + + EditText titleInput = findViewById(R.id.markerTitleInput); + outState.putString(KEY_TITLE, titleInput.getText().toString()); + + if (markerImage != null) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + markerImage.compress(Bitmap.CompressFormat.PNG, 100, stream); + outState.putByteArray(KEY_IMAGE, stream.toByteArray()); + } + } + + @Override + protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + + EditText titleInput = findViewById(R.id.markerTitleInput); + ImageView photoPreview = findViewById(R.id.markerPhotoPreview); + + String restoredTitle = savedInstanceState.getString(KEY_TITLE); + if (restoredTitle != null) { + titleInput.setText(restoredTitle); + } + + byte[] imageBytes = savedInstanceState.getByteArray(KEY_IMAGE); + if (imageBytes != null) { + markerImage = android.graphics.BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); + photoPreview.setImageBitmap(markerImage); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/imt_atlantique/myfirstapplication/MapsFragment.java b/app/src/main/java/fr/imt_atlantique/myfirstapplication/MapsFragment.java index 2db2838..c6ae4b0 100644 --- a/app/src/main/java/fr/imt_atlantique/myfirstapplication/MapsFragment.java +++ b/app/src/main/java/fr/imt_atlantique/myfirstapplication/MapsFragment.java @@ -1,5 +1,7 @@ package fr.imt_atlantique.myfirstapplication; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.Toolbar; @@ -8,8 +10,12 @@ import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import android.Manifest; +import android.app.Activity; import android.app.AlertDialog; +import android.content.Intent; import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -21,6 +27,7 @@ import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; @@ -31,7 +38,7 @@ public class MapsFragment extends Fragment { private Toolbar toolbar; private GoogleMap mMap; - private final ArrayList<LatLng> markerPositions = new ArrayList<>(); + private final ArrayList<MyMarkerData> markerDataList = new ArrayList<>(); public MapsFragment() { // Required empty public constructor @@ -41,6 +48,28 @@ public class MapsFragment extends Fragment { return new MapsFragment(); } + private final ActivityResultLauncher<Intent> addMarkerLauncher = + registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { + if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { + Intent data = result.getData(); + double lat = data.getDoubleExtra("lat", 0); + double lng = data.getDoubleExtra("lng", 0); + String title = data.getStringExtra("title"); + byte[] imageBytes = data.getByteArrayExtra("image"); + + LatLng position = new LatLng(lat, lng); + MyMarkerData markerData = new MyMarkerData(position, title, imageBytes); + markerDataList.add(markerData); + + MarkerOptions markerOptions = new MarkerOptions().position(position).title(title); + if (imageBytes != null) { + Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); + markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap)); + } + mMap.addMarker(markerOptions); + } + }); + private OnMapReadyCallback callback = new OnMapReadyCallback() { /** @@ -56,9 +85,17 @@ public class MapsFragment extends Fragment { public void onMapReady(GoogleMap googleMap) { mMap = googleMap; // Redessine les anciens marqueurs si existants - for (LatLng position : markerPositions) { - googleMap.addMarker(new MarkerOptions().position(position) - .title("Lat: " + position.latitude + ", Lng: " + position.longitude)); + for (MyMarkerData data : markerDataList) { + MarkerOptions markerOptions = new MarkerOptions() + .position(data.position) + .title(data.title); + + if (data.imageBytes != null) { + Bitmap bitmap = BitmapFactory.decodeByteArray(data.imageBytes, 0, data.imageBytes.length); + markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap)); + } + + googleMap.addMarker(markerOptions); } // We check for the application "Call permission" if (ContextCompat.checkSelfPermission(requireContext(), @@ -81,26 +118,27 @@ public class MapsFragment extends Fragment { Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show(); } }); - googleMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() { - @Override - public void onMapLongClick(LatLng latLng) { - double latitude = latLng.latitude; - double longitude = latLng.longitude; - - String title = "Lat: " + latitude + ", Lng: " + longitude; - - // Crée le marker - MarkerOptions markerOptions = new MarkerOptions() - .position(latLng) - .title(title); - - // Ajoute le marker à la carte - googleMap.addMarker(markerOptions); - markerPositions.add(latLng); - - // Affiche un toast - Toast.makeText(requireContext(), "Marqueur ajouté à " + title, Toast.LENGTH_SHORT).show(); + googleMap.setOnMapLongClickListener(latLng -> { + Intent intent = new Intent(requireContext(), AddMarkerActivity.class); + intent.putExtra("lat", latLng.latitude); + intent.putExtra("lng", latLng.longitude); + addMarkerLauncher.launch(intent); + }); + googleMap.setOnMarkerClickListener(marker -> { + LatLng clickedPosition = marker.getPosition(); + + // Retrouver le bon MyMarkerData + for (MyMarkerData data : markerDataList) { + if (data.position.equals(clickedPosition)) { + Intent intent = new Intent(requireContext(), MarkerDetailActivity.class); + intent.putExtra("title", data.title); + intent.putExtra("image", data.imageBytes); + startActivity(intent); + return true; // on consomme l'événement + } } + + return false; // comportement par défaut sinon }); } catch (SecurityException e) { Log.e("MapsFragment", "Error while enabling location", e); @@ -125,9 +163,9 @@ public class MapsFragment extends Fragment { @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if (savedInstanceState != null) { - ArrayList<LatLng> savedMarkers = savedInstanceState.getParcelableArrayList("markers"); + ArrayList<MyMarkerData> savedMarkers = savedInstanceState.getParcelableArrayList("markers"); if (savedMarkers != null) { - markerPositions.addAll(savedMarkers); + markerDataList.addAll(savedMarkers); } } return inflater.inflate(R.layout.fragment_maps, container, false); @@ -164,6 +202,6 @@ public class MapsFragment extends Fragment { @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); - outState.putParcelableArrayList("markers", markerPositions); + outState.putParcelableArrayList("markers", markerDataList); } } \ No newline at end of file diff --git a/app/src/main/java/fr/imt_atlantique/myfirstapplication/MarkerDetailActivity.java b/app/src/main/java/fr/imt_atlantique/myfirstapplication/MarkerDetailActivity.java new file mode 100644 index 0000000..5ec8a7e --- /dev/null +++ b/app/src/main/java/fr/imt_atlantique/myfirstapplication/MarkerDetailActivity.java @@ -0,0 +1,30 @@ +package fr.imt_atlantique.myfirstapplication; + +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +public class MarkerDetailActivity extends AppCompatActivity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_marker_detail); + + TextView titleView = findViewById(R.id.markerDetailTitle); + ImageView imageView = findViewById(R.id.markerDetailImage); + + String title = getIntent().getStringExtra("title"); + byte[] imageBytes = getIntent().getByteArrayExtra("image"); + + titleView.setText(title); + + if (imageBytes != null) { + imageView.setImageBitmap(BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length)); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/imt_atlantique/myfirstapplication/MyMarkerData.java b/app/src/main/java/fr/imt_atlantique/myfirstapplication/MyMarkerData.java new file mode 100644 index 0000000..11ce1a8 --- /dev/null +++ b/app/src/main/java/fr/imt_atlantique/myfirstapplication/MyMarkerData.java @@ -0,0 +1,49 @@ +package fr.imt_atlantique.myfirstapplication; + +import android.graphics.Bitmap; +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.android.gms.maps.model.LatLng; + +public class MyMarkerData implements Parcelable { + public LatLng position; + public String title; + public byte[] imageBytes; // L’image compressée + + public MyMarkerData(LatLng position, String title, byte[] imageBytes) { + this.position = position; + this.title = title; + this.imageBytes = imageBytes; + } + + protected MyMarkerData(Parcel in) { + position = in.readParcelable(LatLng.class.getClassLoader()); + title = in.readString(); + imageBytes = in.createByteArray(); + } + + public static final Creator<MyMarkerData> CREATOR = new Creator<MyMarkerData>() { + @Override + public MyMarkerData createFromParcel(Parcel in) { + return new MyMarkerData(in); + } + + @Override + public MyMarkerData[] newArray(int size) { + return new MyMarkerData[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeParcelable(position, i); + parcel.writeString(title); + parcel.writeByteArray(imageBytes); + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_add_marker.xml b/app/src/main/res/layout/activity_add_marker.xml new file mode 100644 index 0000000..9470d46 --- /dev/null +++ b/app/src/main/res/layout/activity_add_marker.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="24dp"> + + <EditText + android:id="@+id/markerTitleInput" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="Titre du marqueur" /> + + <Button + android:id="@+id/takePhotoBtn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Prendre une photo" /> + + <ImageView + android:id="@+id/markerPhotoPreview" + android:layout_width="match_parent" + android:layout_height="200dp" + android:scaleType="centerCrop" + android:layout_marginTop="8dp" + android:background="#DDD" /> + + <Button + android:id="@+id/validateBtn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Valider" + android:layout_marginTop="16dp" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_marker_detail.xml b/app/src/main/res/layout/activity_marker_detail.xml new file mode 100644 index 0000000..4617e47 --- /dev/null +++ b/app/src/main/res/layout/activity_marker_detail.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:padding="24dp"> + + <TextView + android:id="@+id/markerDetailTitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Titre" + android:textSize="24sp" + android:textStyle="bold" + android:layout_marginBottom="16dp" /> + + <ImageView + android:id="@+id/markerDetailImage" + android:layout_width="match_parent" + android:layout_height="300dp" + android:scaleType="centerCrop" + android:contentDescription="Photo du marqueur" /> +</LinearLayout> \ No newline at end of file -- GitLab