From 2565cfb2881c2e65e285228b21e37cf3dfb2edaf Mon Sep 17 00:00:00 2001
From: m23pfeff <melvil.pfeffer@imt-atlantique.net>
Date: Mon, 16 Dec 2024 13:23:28 +0100
Subject: [PATCH] Form linked with google forms

---
 app/build.gradle.kts                          |   2 +
 app/src/main/AndroidManifest.xml              |   2 +
 .../example/myapplication/GoogleFormApi.java  |  32 +++
 .../OverlayDialogFragmentForm.java            | 230 ++++++++++++++++--
 app/src/main/res/layout/fragment_form.xml     |  29 ++-
 app/src/main/res/values/strings.xml           |   2 +
 gradle/libs.versions.toml                     |   3 +
 7 files changed, 277 insertions(+), 23 deletions(-)
 create mode 100644 app/src/main/java/com/example/myapplication/GoogleFormApi.java

diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 3244b42..a146d57 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -45,4 +45,6 @@ dependencies {
     testImplementation(libs.junit)
     androidTestImplementation(libs.ext.junit)
     androidTestImplementation(libs.espresso.core)
+    implementation(libs.retrofit2.retrofit)
+    implementation(libs.retrofit2.converter.gson)
 }
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5b94871..44c862e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,6 +12,8 @@
         android:maxSdkVersion="32" />
     <uses-permission android:name="android.permission.CAMERA" />
 
+    <uses-permission android:name="android.permission.INTERNET"/>
+
     <application
         android:allowBackup="true"
         android:dataExtractionRules="@xml/data_extraction_rules"
diff --git a/app/src/main/java/com/example/myapplication/GoogleFormApi.java b/app/src/main/java/com/example/myapplication/GoogleFormApi.java
new file mode 100644
index 0000000..93f7f4f
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/GoogleFormApi.java
@@ -0,0 +1,32 @@
+package com.example.myapplication;
+
+import retrofit2.Call;
+import retrofit2.http.Field;
+import retrofit2.http.FormUrlEncoded;
+import retrofit2.http.POST;
+
+public interface GoogleFormApi {
+
+    // Sends form data to the specified Google Form
+    @FormUrlEncoded
+    @POST("/forms/d/e/1FAIpQLScC1-0J39OuIBUedhf_xK_w7qYT8GXVtVpl7SvL4yCPN0VLWA/formResponse")
+    Call<Void> sendFormData(
+            // Birds fields
+            @Field("entry.592245432") String becasseauNumber,
+            @Field("entry.1372224824") String bernacheNumber,
+            @Field("entry.582994154") String goelandNumber,
+            @Field("entry.608828728") String mouetteNumber,
+            @Field("entry.2059411273") String pluvierNumber,
+            @Field("entry.2099434669") String cormoranNumber,
+            @Field("entry.1505904869") String foulqueNumber,
+            @Field("entry.1113424666") String tadorneNumber,
+            @Field("entry.1340159476") String chevalierNumber,
+
+            // Other fields
+            @Field("entry.311834827") String unknownSpecies,
+            @Field("entry.1710251376") String zone,
+            @Field("entry.1284627072") String surroundings,
+            @Field("entry.1321597415") String time
+    );
+}
+
diff --git a/app/src/main/java/com/example/myapplication/OverlayDialogFragmentForm.java b/app/src/main/java/com/example/myapplication/OverlayDialogFragmentForm.java
index 66be8c4..4efcdce 100644
--- a/app/src/main/java/com/example/myapplication/OverlayDialogFragmentForm.java
+++ b/app/src/main/java/com/example/myapplication/OverlayDialogFragmentForm.java
@@ -1,29 +1,64 @@
 package com.example.myapplication;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.DialogInterface;
 import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
+import android.widget.EditText;
 import android.widget.Spinner;
 import android.widget.TextView;
 import android.widget.TimePicker;
+import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.fragment.app.DialogFragment;
 
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
 public class OverlayDialogFragmentForm extends DialogFragment {
+    private String zoneSelected;
+    private boolean isZoneSelected = false;
+
+    private String time;
+    private boolean isTimeSelected = false;
+
+    private String finalPredictionOutput;
+
+    private String becasseauCounter = "0";
+    private String bernacheCounter = "0";
+    private String goelandCounter = "0";
+    private String mouetteCounter = "0";
+    private String pluvierCounter = "0";
+    private String cormoranCounter = "0";
+    private String foulqueCounter = "0";
+    private String tadorneCounter = "0";
+    private String chevalierCounter = "0";
+
+    private String surroundingsDescription;
+
+    // Linking the Google Forms
+    private final Retrofit retrofit = new Retrofit.Builder().baseUrl("https://docs.google.com/").addConverterFactory(GsonConverterFactory.create()).build();
+
+    private final GoogleFormApi api = retrofit.create(GoogleFormApi.class);
+
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
         // Inflate the layout for this dialog fragment
         View view = inflater.inflate(R.layout.fragment_form, container, false);
-        return inflater.inflate(R.layout.fragment_form, container, false);
+        return view;
     }
 
     @Override
@@ -33,20 +68,6 @@ public class OverlayDialogFragmentForm extends DialogFragment {
             getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
             getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent); // Transparent background
         }
-        Button goBackButton=(Button) this.getView().findViewById(R.id.submit_form_button);
-
-        View.OnClickListener listenerGoBackButton=new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                goBack();
-            }
-        };
-
-        goBackButton.setOnClickListener(listenerGoBackButton);
-    }
-
-    private void goBack() {
-        this.getDialog().dismiss();
     }
 
     @Override
@@ -65,13 +86,188 @@ public class OverlayDialogFragmentForm extends DialogFragment {
         // Set the list of options in the dropdown menu
         zoneSelector.setAdapter(adapter);
 
+        // If an item is selected we retain its value
+        zoneSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                zoneSelected = parent.getItemAtPosition(position).toString();
+                isZoneSelected = true;
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+                isZoneSelected = false;
+            }
+        });
+
+
         // Set the time picker settings
         TimePicker timePicker = view.findViewById(R.id.time_picker);
         timePicker.setIs24HourView(true);
+        time = timePicker.getHour() + ":" + timePicker.getMinute();
+        // If time is changed we retain its value
+        timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
+            @Override
+            public void onTimeChanged(TimePicker timePicker, int i, int i1) {
+                time = timePicker.getHour() + ":" + timePicker.getMinute();
+                isTimeSelected = true;
+            }
+        });
 
         // Display the result in the form
+        finalPredictionOutput = PhotoPage.getPredictionOutput();
         TextView predictionDisplay = view.findViewById(R.id.prediction_output);
-        String predictionText = "Nous avons détecté sur votre photo :\n" + PhotoPage.getPredictionOutput();
+        String predictionText = "Nous avons détecté sur votre photo :\n" + finalPredictionOutput;
         predictionDisplay.setText(predictionText);
+
+        String[] numberBySpecies = finalPredictionOutput.split("\n");
+
+        // See how many birds of each species were identified
+        if (finalPredictionOutput.contains("Bécasseau Sanderling")) {
+            for (String species : numberBySpecies) {
+                if (species.contains("Bécasseau Sanderling")) {
+                    becasseauCounter = species.split(" : ")[1];
+                }
+            }
+        }
+
+        if (finalPredictionOutput.contains("Bernache Cravant")) {
+            for (String species : numberBySpecies) {
+                if (species.contains("Bernache Cravant")) {
+                    bernacheCounter = species.split(" : ")[1];
+                }
+            }
+        }
+
+        if (finalPredictionOutput.contains("Goéland Argenté")) {
+            for (String species : numberBySpecies) {
+                if (species.contains("Goéland Argenté")) {
+                    goelandCounter = species.split(" : ")[1];
+                }
+            }
+        }
+
+        if (finalPredictionOutput.contains("Mouette Rieuse")) {
+            for (String species : numberBySpecies) {
+                if (species.contains("Mouette Rieuse")) {
+                    mouetteCounter = species.split(" : ")[1];
+                }
+            }
+        }
+
+        if (finalPredictionOutput.contains("Pluvier Argenté")) {
+            for (String species : numberBySpecies) {
+                if (species.contains("Pluvier Argenté")) {
+                    pluvierCounter = species.split(" : ")[1];
+                }
+            }
+        }
+
+        if (finalPredictionOutput.contains("Grand Cormoran")) {
+            for (String species : numberBySpecies) {
+                if (species.contains("Grand Cormoran")) {
+                    cormoranCounter = species.split(" : ")[1];
+                }
+            }
+        }
+
+        if (finalPredictionOutput.contains("Foulque Macroule")) {
+            for (String species : numberBySpecies) {
+                if (species.contains("Foulque Macroule")) {
+                    foulqueCounter = species.split(" : ")[1];
+                }
+            }
+        }
+
+        if (finalPredictionOutput.contains("Tadorne de Belon")) {
+            for (String species : numberBySpecies) {
+                if (species.contains("Tadorne de Belon")) {
+                    tadorneCounter = species.split(" : ")[1];
+                }
+            }
+        }
+
+        if (finalPredictionOutput.contains("Chevalier Gambette")) {
+            for (String species : numberBySpecies) {
+                if (species.contains("Chevalier Gambette")) {
+                    chevalierCounter = species.split(" : ")[1];
+                }
+            }
+        }
+
+        EditText surroundings = view.findViewById(R.id.location_input);
+        surroundings.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+                surroundingsDescription = "Pas de description fournie";
+            }
+
+            @Override
+            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+                surroundingsDescription = surroundings.getText().toString();
+            }
+
+            @Override
+            public void afterTextChanged(Editable editable) {
+                surroundingsDescription = surroundings.getText().toString();
+            }
+        });
+
+
+
+        Button submitButton=(Button) this.getView().findViewById(R.id.submit_form_button);
+
+        View.OnClickListener listenerSubmitButton=new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                Call<Void> call = api.sendFormData(becasseauCounter, bernacheCounter, goelandCounter, mouetteCounter, pluvierCounter, cormoranCounter,
+                        foulqueCounter, tadorneCounter, chevalierCounter, "test", zoneSelected.split("\n")[0], surroundingsDescription, "14:30");
+
+                call.enqueue(new Callback<Void>() {
+                    @Override
+                    public void onResponse(Call<Void> call, Response<Void> response) {
+                        try {
+                            if (response.isSuccessful()) {
+                                Toast.makeText(getContext(), "Successful", Toast.LENGTH_SHORT).show();
+                            } else {
+                                Toast.makeText(getContext(), "Unsuccessful" + response.code() , Toast.LENGTH_SHORT).show();
+
+                                new AlertDialog.Builder(getContext())
+                                        .setTitle("Delete entry")
+                                        .setMessage(becasseauCounter + "\n" + bernacheCounter + "\n" + goelandCounter + "\n" + mouetteCounter+ "\n"
+                                                        + pluvierCounter + "\n" + cormoranCounter + "\n" + foulqueCounter + "\n"
+                                                + tadorneCounter + "\n" + chevalierCounter + "\n" + "test" + "\n" + zoneSelected.split("\n")[0] + "\n" + surroundingsDescription + "\n" + "14:30")
+
+                                        // Specifying a listener allows you to take an action before dismissing the dialog.
+                                        // The dialog is automatically dismissed when a dialog button is clicked.
+                                        .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+                                            public void onClick(DialogInterface dialog, int which) {
+                                                // Continue with delete operation
+                                            }
+                                        })
+
+                                        // A null listener allows the button to dismiss the dialog and take no further action.
+                                        .setNegativeButton(android.R.string.no, null)
+                                        .setIcon(android.R.drawable.ic_dialog_alert)
+                                        .show();
+                            }
+                        } catch (Exception e) {
+                            Toast.makeText(getContext(), "Error: ${e.message}", Toast.LENGTH_SHORT).show();
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(Call<Void> call, Throwable t) {
+                        try {
+                            Toast.makeText(getContext(), "Error: ${t.message}", Toast.LENGTH_SHORT).show();
+                        } catch (Exception e) {
+                            Toast.makeText(getContext(), "Error: ${e.message}", Toast.LENGTH_SHORT).show();
+                        }
+                    }
+                });
+            }
+        };
+
+        submitButton.setOnClickListener(listenerSubmitButton);
     }
 }
diff --git a/app/src/main/res/layout/fragment_form.xml b/app/src/main/res/layout/fragment_form.xml
index c255bdd..f3ff830 100644
--- a/app/src/main/res/layout/fragment_form.xml
+++ b/app/src/main/res/layout/fragment_form.xml
@@ -32,7 +32,7 @@
         <Spinner
             android:id="@+id/zone_selector"
             android:layout_width="match_parent"
-            android:layout_height="40dp"
+            android:layout_height="50dp"
             android:layout_marginTop="15dp" />
 
         <Button
@@ -45,9 +45,8 @@
             android:text="@string/zone_info_text"
             android:textSize="12sp" />
 
-        <!-- Title for the form -->
         <TextView
-            android:id="@+id/form_title"
+            android:id="@+id/surroundings"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
@@ -67,9 +66,28 @@
             android:padding="20dp"
             android:textColor="#000000" />
 
-        <!-- Date Picker (Optional) -->
+        <TextView
+            android:id="@+id/unknown_species"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:layout_marginTop="20dp"
+            android:text="@string/unknown_species_text"
+            android:gravity="center"
+            android:textColor="#333333"
+            android:textSize="18sp"
+            android:textStyle="bold" />
+
+        <EditText
+            android:id="@+id/unknown_species_input"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="15dp"
+            android:hint="@string/unknown_species_question"
+            android:padding="20dp"
+            android:textColor="#000000"
+            android:editable="false" />
 
-        <!-- Submit Button -->
         <TextView
             android:id="@+id/form_date"
             android:layout_width="wrap_content"
@@ -82,7 +100,6 @@
             android:textStyle="bold" />
 
         <TimePicker
-
             android:id="@+id/time_picker"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c745eda..e2d549b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -88,6 +88,8 @@
     <string name="zone_info_text">Plus d\'info sur les zones</string>
     <string name="corresponding_zone_text">Saisissez la zone correspondante</string>
     <string name="display_prediction_text">Si rien ne s\'affiche ici, c\'est que la détection d\'espèces n\'a pas fonctionné.</string>
+    <string name="unknown_species_text">Si rien ne s\'affiche en haut de l\'écran et que vous connaissez l\'espèce en question, écrivez cela ici. Sinon écrivez je ne sais pas.</string>
+    <string name="unknown_species_question">Quelle est cette espèce ?</string>
     <string-array name="zone_array">
         <item>Zone 1</item>
         <item>Zone 2</item>
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 6a037e2..c82554b 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -11,6 +11,7 @@ flexboxVersion= "3.0.0"
 readmoretextviewVersion= "1.0.2"
 litertGpu = "1.0.1"
 uiGraphicsAndroid = "1.7.5"
+retrofit = "2.9.0"
 
 [libraries]
 junit = { group = "junit", name = "junit", version.ref = "junit" }
@@ -24,6 +25,8 @@ flexboxlayout = {group="com.google.android.flexbox", name="flexbox", version.ref
 readmoretextview = {group="com.github.colourmoon", name="readmore-textview", version.ref="readmoretextviewVersion"}
 litert-gpu = { group = "com.google.ai.edge.litert", name = "litert-gpu", version.ref = "litertGpu" }
 ui-graphics-android = { group = "androidx.compose.ui", name = "ui-graphics-android", version.ref = "uiGraphicsAndroid" }
+retrofit2-retrofit = {group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit"}
+retrofit2-converter-gson = {group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit"}
 
 [plugins]
 android-application = { id = "com.android.application", version.ref = "agp" }
-- 
GitLab