Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Haouziti textfield feature #14

Open
wants to merge 4 commits into
base: e11_save_chat
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions .idea/androidTestResultsUserPreferences.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 85 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# App_entwicklung_BFAX422A

Meine App-Erweiterung:

Meine App-Erweiterung inkludiert eine Texteingabe, welche die Spracheingabe ergänzt, indem sie einen String an ChatGPT schickt, statt die nur die Spracheingabe zu nutzen.
Sie verbessert die App, indem sie dem Nutzer erlaubt eine Alternative zu Spracheingabe zu verwenden, um mit ChatGPT zu kommunizieren.


Funktionale Anforderung (der Erweiterung):

- Funktion 1: Textfeld („id: Textfield“)  Der Benutzer bekommt Zugang zu einem Feld, indem er eine Nachricht an ChatGPT schreiben kann.

![image](https://github.com/YassineH03/app_entwicklung_BFAX422A/assets/147349679/45beebf3-8d90-4b3b-8300-59cc5ccda254)

Abb. 1

- Funktion 2: Knopf („id: send_Button“) Nachdem der Nutzer seine Nachricht im Textfeld
geschrieben hat, kann er mit dem Button die Nachricht an ChatGPT absenden, um eine Antwort zu erhalten.



![image](https://github.com/YassineH03/app_entwicklung_BFAX422A/assets/147349679/8ec94aa7-7e56-49b3-a61c-dfca8b699c20)


Abb. 2

Umsetzung der Erweiterung:

Die Umsetzung erfolgte, indem Zunächst die Komponenten Textfeld und Knopf implementiert werden (mit entsprechenden IDs) in der XML-Datei „main-Fragment“ müssen (siehe Abb. 1-2).


Daraufhin müssen wir Zugang zum Button als auch Textfeld, bzw. dem Inhalt des Textfeldes in unseren Quellcode bekommen. Dies ermöglichen wir, indem wir zwei Getter-Methoden implementieren und dabei aus der View die IDs der jeweiligen Komponenten verwenden (siehe Abb.3-4).


Bevor wir sagen können, wie der Button handeln soll, müssen wir zunächst eine Methode schreiben die einen String als Parameter hat (nämlich der Inhalt des Textfelds) und diesen ChatGPT schickt, bzw. dessen Antwort auch auf der TextView darstellt. Solch ein Codeabschnitt haben wir glücklicherweise schon in der Vorlesung geschrieben. Deshalb fehlte nur noch diesen Abschnitt in eine Methode auszulagern (siehe Abb. 5) und wieder zu Verwenden.


Zum Schluss fehlt nur noch das Verhalten des Buttons zu konfigurieren. Dieser soll nämlich beim Betätigen, den Text des Textfeldes an ChatGPT schicken bzw. den String in die zuvor erwähnte Methode packen und diese ausführen (siehe Abb. 6).



![image](https://github.com/YassineH03/app_entwicklung_BFAX422A/assets/147349679/4d26720e-e634-4b30-870d-89644c095a86)


Abb. 5


![image](https://github.com/YassineH03/app_entwicklung_BFAX422A/assets/147349679/cf80648e-b17b-4455-a41a-3c4bc5c28621)


Abb. 3


![image](https://github.com/YassineH03/app_entwicklung_BFAX422A/assets/147349679/b21e820d-284f-4153-b59e-67cbbf253d3b)


Abb. 4


![image](https://github.com/YassineH03/app_entwicklung_BFAX422A/assets/147349679/28c992fc-ffc6-4d50-bbe2-88e857c8b612)


Abb. 5


![image](https://github.com/YassineH03/app_entwicklung_BFAX422A/assets/147349679/fcb745b8-b03c-4936-bf0d-d739157a3beb)


Abb. 6


Komplikationen:

An der Stelle, an der es am meisten gehackt hat, war nicht die Erstellung der Bausteine (Textfeld, Button), sondern wie die Bausteine mit einer kommunizieren. Denn Zunächst war mein Ansatz den Aufbau wie in der „LaunchSpeechRecognition- Klasse“ aufzubauen und Intents zu verwenden (siehe LaunchTextfield- Klasse), jedoch ist mir nach kurzer Zeit klar geworden- nachdem ich nämlich recherchiert hatte zu was die Bausteine in der Lage waren, dass es ein viel zu umständlicher Ansatz war.


Lesson Learned:

Je besser man die Elemente versteht, die man verwendet, desto leichter und effektiver kann deren Nutzung sein.


Fazit:

Ich war in der Lage meine App-Erweiterung im gegeben Zeitrahmen umzusetzen, dabei war die Aufgabe sowohl herausfordernd als auch spaßig.

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public boolean onCreateOptionsMenu(Menu menu) {
return true;
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_item_settings) {
Expand Down
67 changes: 46 additions & 21 deletions app/src/main/java/de/fhdw/app_entwicklung/chatgpt/MainFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import org.w3c.dom.Text;

import java.util.List;
import java.util.Locale;

Expand All @@ -20,6 +23,7 @@
import de.fhdw.app_entwicklung.chatgpt.model.Message;
import de.fhdw.app_entwicklung.chatgpt.openai.ChatGpt;
import de.fhdw.app_entwicklung.chatgpt.speech.LaunchSpeechRecognition;
import de.fhdw.app_entwicklung.chatgpt.speech.LaunchTextfield;
import de.fhdw.app_entwicklung.chatgpt.speech.TextToSpeechTool;

public class MainFragment extends Fragment {
Expand All @@ -31,29 +35,35 @@ public class MainFragment extends Fragment {
private TextToSpeechTool textToSpeech;
private Chat chat;

private final ActivityResultLauncher<LaunchSpeechRecognition.SpeechRecognitionArgs> getTextFromSpeech = registerForActivityResult(
private final ActivityResultLauncher<LaunchSpeechRecognition.SpeechRecognitionArgs> getTextFromSpeech
= registerForActivityResult(
new LaunchSpeechRecognition(),
query -> {
Message userMessage = new Message(Author.User, query);
chat.addMessage(userMessage);
if (chat.getMessages().size() > 1) {
getTextView().append(CHAT_SEPARATOR);
}
getTextView().append(toString(userMessage));

MainActivity.backgroundExecutorService.execute(() -> {
String apiToken = prefs.getApiToken();
ChatGpt chatGpt = new ChatGpt(apiToken);
String answer = chatGpt.getChatCompletion(chat);

Message answerMessage = new Message(Author.Assistant, answer);
chat.addMessage(answerMessage);
getTextView().append(CHAT_SEPARATOR);
getTextView().append(toString(answerMessage));
textToSpeech.speak(answer);
});
sendQuestionAndDisplayAnswer(query);
});
//#########################################################################################

private void sendQuestionAndDisplayAnswer(String query) {
Message userMessage = new Message(Author.User, query);
chat.addMessage(userMessage);
if (chat.getMessages().size() > 1) {
getTextView().append(CHAT_SEPARATOR);
}
getTextView().append(toString(userMessage));

MainActivity.backgroundExecutorService.execute(() -> {
String apiToken = prefs.getApiToken();
ChatGpt chatGpt = new ChatGpt(apiToken);
String answer = chatGpt.getChatCompletion(chat);

Message answerMessage = new Message(Author.Assistant, answer);
chat.addMessage(answerMessage);
getTextView().append(CHAT_SEPARATOR);
getTextView().append(toString(answerMessage));
textToSpeech.speak(answer);
});
}
//#############################################################################################
public MainFragment() {
}

Expand All @@ -70,13 +80,19 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
prefs = new PrefsFacade(requireContext());
textToSpeech = new TextToSpeechTool(requireContext(), Locale.GERMAN);
chat = new Chat();
if (savedInstanceState != null) {

if (savedInstanceState != null) { //Speichert den Zustand des Chats in der View
chat = savedInstanceState.getParcelable(EXTRA_DATA_CHAT);
}

getAskButton().setOnClickListener(v ->
getTextFromSpeech.launch(new LaunchSpeechRecognition.SpeechRecognitionArgs(Locale.GERMAN)));
updateTextView();

//#############################################################################################################
getSendButton().setOnClickListener(v -> sendQuestionAndDisplayAnswer(getStringFromTextfield()));
updateTextView();
//##############################################################################################################
}

@Override
Expand Down Expand Up @@ -125,5 +141,14 @@ private Button getAskButton() {
//noinspection ConstantConditions
return getView().findViewById(R.id.button_ask);
}

//#############################################################################################
private Button getSendButton(){
return getView().findViewById(R.id.button_send);
}
//##############################################################################################
private String getStringFromTextfield(){
EditText Textfield = getView().findViewById(R.id.Textfield);
return Textfield.getText().toString();
}
//##############################################################################################
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package de.fhdw.app_entwicklung.chatgpt.speech;

import static android.app.Activity.RESULT_OK;

import android.content.Context;
import android.content.Intent;
import android.speech.RecognizerIntent;
import android.widget.EditText;

import androidx.activity.result.contract.ActivityResultContract;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;

public class LaunchTextfield extends ActivityResultContract<LaunchTextfield.TextfieldArgs, String> {


public static class TextfieldArgs
{
public final Locale locale;
public final String prompt;

public TextfieldArgs(Locale locale)
{
this(locale, null);
}

public TextfieldArgs(Locale locale, String prompt)
{
this.locale = locale;
this.prompt = prompt;
}
}
@NonNull
@Override// hier ist noch ein Problem
public Intent createIntent(@NonNull Context context, TextfieldArgs textfieldArgs) {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE,
textfieldArgs.locale.toString());

if (textfieldArgs.prompt != null) {
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, textfieldArgs.prompt);
}
return intent;
}

@Override //hier ist noch ein problem
public String parseResult(int i, @Nullable Intent intent) {
if (i == RESULT_OK && intent != null) {
ArrayList<String> result = intent.getStringArrayListExtra(
RecognizerIntent.EXTRA_RESULTS);
return Objects.requireNonNull(result).get(0);
}
return null;
}
// Die Klasse ist Bewusst erhalten geblieben zur Demonstrations der verschiedenen Lösungsansätze
}
29 changes: 28 additions & 1 deletion app/src/main/res/layout/fragment_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
tools:context=".MainActivity">

<TextView
android:id="@+id/textView"
Expand All @@ -33,8 +33,35 @@
android:text="@string/ask"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />

//#########################################################################################

<EditText
android:id="@+id/Textfield"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Texteingabe"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/button_send"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@+id/button_ask"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintVertical_bias="0.0" />
//########################################################################################
<Button
android:id="@+id/button_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Absenden"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintVertical_bias="0.0" />
//#######################################################################################
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<resources>
<string name="app_name" translatable="false">ChatGpt</string>
<string name="ask">Ask</string>
<string name="ask">Fragen</string>
<string name="settings">Settings</string>
</resources>