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

App Erweiterung App Widget - Angela Gaugler #9

Open
wants to merge 8 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.

3 changes: 1 addition & 2 deletions .idea/misc.xml

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

123 changes: 123 additions & 0 deletions README.md

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

<application
android:allowBackup="true"
Expand All @@ -18,6 +19,11 @@
android:name=".PrefsActivity"
android:exported="false"
android:label="Settings" />
<activity
android:name=".speech.VoiceRecognition"
android:theme="@style/Theme.AppCompat.Transparent.NoActionBar"
android:launchMode="singleInstance"
android:exported="false"/>
<activity
android:name=".MainActivity"
android:exported="true">
Expand All @@ -27,6 +33,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".WidgetProvider"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/app_widget_info"/>
</receiver>
</application>

</manifest>
130 changes: 130 additions & 0 deletions app/src/main/java/de/fhdw/app_entwicklung/chatgpt/WidgetProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package de.fhdw.app_entwicklung.chatgpt;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;

import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import de.fhdw.app_entwicklung.chatgpt.model.Author;
import de.fhdw.app_entwicklung.chatgpt.model.Chat;
import de.fhdw.app_entwicklung.chatgpt.model.Message;
import de.fhdw.app_entwicklung.chatgpt.openai.ChatGpt;
import de.fhdw.app_entwicklung.chatgpt.speech.TextToSpeechTool;

public class WidgetProvider extends AppWidgetProvider {
public static final String VOICE_RESULT = "de.fhdw.app_entwicklung.chatgpt.VOICE_RESULT";
public static final String ACTION_STOP_AUDIO = "de.fhdw.app_entwicklung.chatgpt.ACTION_STOP_AUDIO";
public static final String ACTION_AUDIO_FINISHED = "de.fhdw.app_entwicklung.chatgpt.ACTION_AUDIO_FINISHED";

private static TextToSpeechTool tts;

private final ExecutorService backgroundExecutorService = Executors.newFixedThreadPool(2);

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}

private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.app_widget);

Intent intent = new Intent(context, WidgetProvider.class);
intent.setAction(VOICE_RESULT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_MUTABLE);


Intent voiceIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Stelle deine Frage an ChatGpt");
voiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pendingIntent);

PendingIntent clickAskButton = PendingIntent.getActivity(context, 0, voiceIntent, PendingIntent.FLAG_IMMUTABLE);

views.setOnClickPendingIntent(R.id.app_widget_button, clickAskButton);

Intent stopIntent = new Intent(context, WidgetProvider.class);
stopIntent.setAction(ACTION_STOP_AUDIO);
PendingIntent clickStopButton = PendingIntent.getBroadcast(context, 0, stopIntent, PendingIntent.FLAG_MUTABLE);

views.setOnClickPendingIntent(R.id.widget_stop_button, clickStopButton);

appWidgetManager.updateAppWidget(appWidgetId, views);
}


@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
Log.i("WIDGET", intent.getAction());

if (intent.getAction().equals(VOICE_RESULT)) {
if (tts == null) {
tts = new TextToSpeechTool(context, Locale.GERMAN);
}
Chat chat = new Chat();
PrefsFacade prefs = new PrefsFacade(context);

Bundle bundle = intent.getExtras();

if (bundle != null && intent.hasExtra(RecognizerIntent.EXTRA_RESULTS)) {
ArrayList<String> resultList = bundle.getStringArrayList(RecognizerIntent.EXTRA_RESULTS);
String result = Objects.requireNonNull(resultList).get(0);

backgroundExecutorService.execute(() -> {
Message userMessage = new Message(Author.User, result);
chat.addMessage(userMessage);
String apiToken = prefs.getApiToken();
ChatGpt chatGpt = new ChatGpt(apiToken);
String answer = chatGpt.getChatCompletion(chat);
toggleButtonVisibility(context, true);
tts.speak(answer);
});
}
}

if (intent.getAction().equals(ACTION_STOP_AUDIO)) {
if (tts != null) {
tts.stop();
toggleButtonVisibility(context, false);
}
}

if (intent.getAction().equals(ACTION_AUDIO_FINISHED)) {
toggleButtonVisibility(context, false);
}
}

void toggleButtonVisibility(Context context, boolean started) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.app_widget);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, WidgetProvider.class));

if (started) {
views.setViewVisibility(R.id.app_widget_button, View.GONE);
views.setViewVisibility(R.id.widget_stop_button, View.VISIBLE);
} else {
views.setViewVisibility(R.id.app_widget_button, View.VISIBLE);
views.setViewVisibility(R.id.widget_stop_button, View.GONE);
}

appWidgetManager.updateAppWidget(appWidgetIds, views);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package de.fhdw.app_entwicklung.chatgpt.speech;

import static de.fhdw.app_entwicklung.chatgpt.WidgetProvider.ACTION_AUDIO_FINISHED;

import android.content.Context;
import android.content.Intent;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
import android.util.Log;

import androidx.annotation.NonNull;

import java.util.Locale;

public class TextToSpeechTool implements TextToSpeech.OnInitListener{
import de.fhdw.app_entwicklung.chatgpt.WidgetProvider;

public class TextToSpeechTool implements TextToSpeech.OnInitListener {
private final TextToSpeech textToSpeech;
private boolean ttsAvailable = false;
private final Locale locale;
Expand All @@ -17,6 +23,26 @@ public TextToSpeechTool(@NonNull Context context, Locale locale)
{
textToSpeech = new TextToSpeech(context, this);
this.locale = locale;

textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String s) {

}

@Override
public void onDone(String s) {
Log.i("TTS", "DONE");
Intent intent = new Intent(context, WidgetProvider.class);
intent.setAction(ACTION_AUDIO_FINISHED);
context.sendBroadcast(intent);
}

@Override
public void onError(String s) {

}
});
}

@Override
Expand All @@ -35,7 +61,7 @@ public void onInit(int status) {

public void speak(String text) {
if (ttsAvailable) {
textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, null);
textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID);
}
}

Expand All @@ -53,4 +79,5 @@ public void destroy()
}
}


}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions app/src/main/res/drawable/openai_logomark_white_small.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="25dp"
android:height="25dp"
android:viewportWidth="320"
android:viewportHeight="320">
<path
android:fillColor="#FFFFFFFF"
android:pathData="m297.06,130.97c7.26,-21.79 4.76,-45.66 -6.85,-65.48 -17.46,-30.4 -52.56,-46.04 -86.84,-38.68 -15.25,-17.18 -37.16,-26.95 -60.13,-26.81 -35.04,-0.08 -66.13,22.48 -76.91,55.82 -22.51,4.61 -41.94,18.7 -53.31,38.67 -17.59,30.32 -13.58,68.54 9.92,94.54 -7.26,21.79 -4.76,45.66 6.85,65.48 17.46,30.4 52.56,46.04 86.84,38.68 15.24,17.18 37.16,26.95 60.13,26.8 35.06,0.09 66.16,-22.49 76.94,-55.86 22.51,-4.61 41.94,-18.7 53.31,-38.67 17.57,-30.32 13.55,-68.51 -9.94,-94.51zM176.78,299.08c-14.03,0.02 -27.62,-4.89 -38.39,-13.88 0.49,-0.26 1.34,-0.73 1.89,-1.07l63.72,-36.8c3.26,-1.85 5.26,-5.32 5.24,-9.07v-89.83l26.93,15.55c0.29,0.14 0.48,0.42 0.52,0.74v74.39c-0.04,33.08 -26.83,59.9 -59.91,59.97zM47.94,244.05c-7.03,-12.14 -9.56,-26.37 -7.15,-40.18 0.47,0.28 1.3,0.79 1.89,1.13l63.72,36.8c3.23,1.89 7.23,1.89 10.47,0l77.79,-44.92v31.1c0.02,0.32 -0.13,0.63 -0.38,0.83l-64.41,37.19c-28.69,16.52 -65.33,6.7 -81.92,-21.95zM31.17,104.96c7,-12.16 18.05,-21.46 31.21,-26.29 0,0.55 -0.03,1.52 -0.03,2.2v73.61c-0.02,3.74 1.98,7.21 5.23,9.06l77.79,44.91 -26.93,15.55c-0.27,0.18 -0.61,0.21 -0.91,0.08l-64.42,-37.22c-28.63,-16.58 -38.45,-53.21 -21.95,-81.89zM252.43,156.45 L174.64,111.53 201.57,95.99c0.27,-0.18 0.61,-0.21 0.91,-0.08l64.42,37.19c28.68,16.57 38.51,53.26 21.94,81.94 -7.01,12.14 -18.05,21.44 -31.2,26.28v-75.81c0.03,-3.74 -1.96,-7.2 -5.2,-9.06zM279.23,116.11c-0.47,-0.29 -1.3,-0.79 -1.89,-1.13l-63.72,-36.8c-3.23,-1.89 -7.23,-1.89 -10.47,0l-77.79,44.92v-31.1c-0.02,-0.32 0.13,-0.63 0.38,-0.83l64.41,-37.16c28.69,-16.55 65.37,-6.7 81.91,22 6.99,12.12 9.52,26.31 7.15,40.1zM110.72,171.54 L83.78,155.99c-0.29,-0.14 -0.48,-0.42 -0.52,-0.74v-74.39c0.02,-33.12 26.89,-59.96 60.01,-59.94 14.01,0 27.57,4.92 38.34,13.88 -0.49,0.26 -1.33,0.73 -1.89,1.07l-63.72,36.8c-3.26,1.85 -5.26,5.31 -5.24,9.06l-0.04,89.79zM125.35,140 L160,119.99 194.65,139.99v40.01l-34.65,20 -34.65,-20z"
tools:ignore="VectorPath" />
</vector>
8 changes: 8 additions & 0 deletions app/src/main/res/drawable/rounded_corners.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<corners android:radius="50dp" />
</shape>
</item>
</selector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/square.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector android:height="25dp" android:viewportHeight="19.173"
android:viewportWidth="19.173" android:width="25dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffff"
android:pathData="M5.379,5.173h8.414v8.828h-8.414z" android:strokeWidth="0.118931"/>
</vector>
34 changes: 34 additions & 0 deletions app/src/main/res/layout/app_widget.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/Theme.Material3.DynamicColors.DayNight">


<Button
android:id="@+id/app_widget_button"
android:layout_width="160dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:background="@drawable/rounded_corners"
android:backgroundTint="@color/design_default_color_secondary_variant"
android:drawableStart="@drawable/openai_logomark_white_small"
android:padding="10dp"
android:text="Frag ChatGpt"
android:textColor="@color/white"
/>

<Button
android:id="@+id/widget_stop_button"
android:layout_width="160dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:background="@drawable/rounded_corners"
android:backgroundTint="@color/design_default_color_error"
android:drawableStart="@drawable/square"
android:padding="10dp"
android:text="Stop ChatGpt"
android:textColor="@color/white"
android:visibility="gone" />

</RelativeLayout>
11 changes: 11 additions & 0 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.AppCompat.Transparent.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
</resources>
14 changes: 14 additions & 0 deletions app/src/main/res/xml/app_widget_info.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/app_widget"
android:minHeight="40dp"
android:minWidth="110dp"
android:targetCellWidth="2"
android:targetCellHeight="1"
android:resizeMode="none"
android:updatePeriodMillis="36000000"
android:widgetCategory="home_screen"
android:previewLayout="@layout/app_widget"
android:previewImage="@drawable/widget_preview"
>
</appwidget-provider>
1 change: 0 additions & 1 deletion app/src/main/res/xml/root_preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<EditTextPreference
app:key="api_token"
app:title="API Token"
app:defaultValue="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"
app:useSimpleSummaryProvider="true" />

</PreferenceCategory>
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.1.0' apply false
id 'com.android.library' version '8.1.0' apply false
id 'com.android.application' version '8.0.2' apply false
id 'com.android.library' version '8.0.2' apply false
}
Binary file added images/askButton.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/stopButton.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/widget_updates_all.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.