From aa516b2a5c2c489ac35236777a11876aa7d21db7 Mon Sep 17 00:00:00 2001 From: Deekshith Reddy Ramreddygari Date: Wed, 10 Jul 2019 11:59:25 -0700 Subject: [PATCH 01/24] Initial commit --- .../.gitignore | 9 + .../app/.gitignore | 1 + .../app/build.gradle | 61 ++ .../app/proguard-rules.pro | 21 + .../mlapitest/ExampleInstrumentedTest.java | 26 + .../app/src/main/AndroidManifest.xml | 36 ++ .../app/src/main/assets/book_a_room.wav | Bin 0 -> 31058 bytes .../com/example/mlapitest/AppController.java | 54 ++ .../adapter/ChatRecyclerViewAdapter.java | 69 +++ .../example/mlapitest/model/ChatMsgModel.java | 28 + .../service/MyFirebaseInstanceIDService.java | 18 + .../service/MyFirebaseMessagingService.java | 46 ++ .../example/mlapitest/ui/ChatActivity.java | 230 ++++++++ .../example/mlapitest/ui/MainActivity.java | 149 +++++ .../example/mlapitest/ui/WelcomeActivity.java | 156 +++++ .../example/mlapitest/utils/ApiRequest.java | 554 ++++++++++++++++++ .../utils/KnowledgebaseManagement.java | 97 +++ .../app/src/main/res/drawable-hdpi/ic_mic.png | Bin 0 -> 609 bytes .../src/main/res/drawable-hdpi/ic_send.png | Bin 0 -> 1832 bytes .../app/src/main/res/drawable-mdpi/ic_mic.png | Bin 0 -> 395 bytes .../src/main/res/drawable-mdpi/ic_send.png | Bin 0 -> 1041 bytes .../drawable-v24/ic_launcher_foreground.xml | 34 ++ .../src/main/res/drawable-xhdpi/ic_mic.png | Bin 0 -> 872 bytes .../src/main/res/drawable-xhdpi/ic_send.png | Bin 0 -> 2186 bytes .../src/main/res/drawable-xxhdpi/ic_mic.png | Bin 0 -> 1373 bytes .../src/main/res/drawable-xxhdpi/ic_send.png | Bin 0 -> 4073 bytes .../src/main/res/drawable-xxxhdpi/ic_mic.png | Bin 0 -> 2026 bytes .../src/main/res/drawable-xxxhdpi/ic_send.png | Bin 0 -> 4927 bytes .../res/drawable/ic_launcher_background.xml | 170 ++++++ .../src/main/res/drawable/rounded_corner.xml | 7 + .../res/drawable/rounded_corner_edittext.xml | 14 + .../app/src/main/res/layout/activity_chat.xml | 78 +++ .../app/src/main/res/layout/activity_main.xml | 39 ++ .../src/main/res/layout/activity_welcome.xml | 155 +++++ .../layout/custom_chat_recyclerview_item.xml | 43 ++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3056 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5024 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2096 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2858 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4569 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7098 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6464 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10676 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9250 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15523 bytes .../app/src/main/res/values/colors.xml | 6 + .../app/src/main/res/values/strings.xml | 4 + .../app/src/main/res/values/styles.xml | 11 + .../example/mlapitest/ExampleUnitTest.java | 17 + .../build.gradle | 28 + .../gradle.properties | 19 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + .../gradlew | 160 +++++ .../gradlew.bat | 90 +++ ...mobile-mobile_proxy_server-android_app.zip | Bin 0 -> 195808 bytes .../settings.gradle | 1 + 59 files changed, 2447 insertions(+) create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/.gitignore create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/.gitignore create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/build.gradle create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/proguard-rules.pro create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/androidTest/java/com/example/mlapitest/ExampleInstrumentedTest.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/AndroidManifest.xml create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/assets/book_a_room.wav create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/AppController.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/adapter/ChatRecyclerViewAdapter.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/model/ChatMsgModel.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/service/MyFirebaseInstanceIDService.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/service/MyFirebaseMessagingService.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/ChatActivity.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/MainActivity.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/WelcomeActivity.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/utils/ApiRequest.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/utils/KnowledgebaseManagement.java create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-hdpi/ic_mic.png create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-hdpi/ic_send.png create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-mdpi/ic_mic.png create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-mdpi/ic_send.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xhdpi/ic_mic.png create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xhdpi/ic_send.png create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xxhdpi/ic_mic.png create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xxhdpi/ic_send.png create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xxxhdpi/ic_mic.png create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xxxhdpi/ic_send.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable/rounded_corner.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable/rounded_corner_edittext.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/activity_chat.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/activity_main.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/activity_welcome.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/custom_chat_recyclerview_item.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/values/colors.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/values/strings.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/values/styles.xml create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/test/java/com/example/mlapitest/ExampleUnitTest.java create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/build.gradle create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/gradle.properties create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/gradle/wrapper/gradle-wrapper.jar create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/gradle/wrapper/gradle-wrapper.properties create mode 100755 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/gradlew create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/gradlew.bat create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app.zip create mode 100644 samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/settings.gradle diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/.gitignore b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/.gitignore new file mode 100644 index 00000000..39fb081a --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/.gitignore b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/build.gradle b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/build.gradle new file mode 100644 index 00000000..d83f32ce --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/build.gradle @@ -0,0 +1,61 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.example.mlapitest" + minSdkVersion 26 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + multiDexEnabled true + } + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + packagingOptions { + exclude 'META-INF/DEPENDENCIES' + exclude 'META-INF/LICENSE' + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/license.txt' + exclude 'META-INF/NOTICE' + exclude 'META-INF/NOTICE.txt' + exclude 'META-INF/notice.txt' + exclude 'META-INF/ASL2.0' + exclude 'META-INF/INDEX.LIST' + exclude 'META-INF/io.netty.versions.properties' + } +} + +dependencies { + + configurations.all { + resolutionStrategy.force 'com.android.support:support-annotations:25.3.0' + } + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.0.0' + implementation 'com.google.android.material:material:1.0.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + + implementation 'com.google.firebase:firebase-core:17.0.0' + implementation 'com.google.firebase:firebase-auth:18.0.0' + implementation 'com.firebaseui:firebase-ui-auth:4.1.0' + implementation 'com.google.firebase:firebase-messaging:19.0.1' + implementation 'com.google.firebase:firebase-functions:18.0.0' + implementation 'com.android.volley:volley:1.1.1' + implementation 'com.google.cloud:google-cloud-dialogflow:0.96.0-alpha' + implementation group: 'io.grpc', name: 'grpc-okhttp', version: '1.21.0' + implementation group: 'io.grpc', name: 'grpc-netty', version: '1.21.0' + + implementation "com.google.firebase:firebase-database:18.0.0" +} + + +apply plugin: 'com.google.gms.google-services' diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/proguard-rules.pro b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/androidTest/java/com/example/mlapitest/ExampleInstrumentedTest.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/androidTest/java/com/example/mlapitest/ExampleInstrumentedTest.java new file mode 100644 index 00000000..685b7e9e --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/androidTest/java/com/example/mlapitest/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.example.mlapitest; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.example.mlapitest", appContext.getPackageName()); + } +} diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/AndroidManifest.xml b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..f7dc9ce9 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/assets/book_a_room.wav b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/assets/book_a_room.wav new file mode 100755 index 0000000000000000000000000000000000000000..9124e9279460a0057df91202a5d0e5e147b60813 GIT binary patch literal 31058 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 Nh$0A1lK;Pd{tuoqdJX^p literal 0 HcmV?d00001 diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/AppController.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/AppController.java new file mode 100644 index 00000000..462d5971 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/AppController.java @@ -0,0 +1,54 @@ +package com.example.mlapitest; + +import android.app.Application; + +import com.google.firebase.functions.FirebaseFunctions; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +public class AppController extends Application { + + public static final String TOKEN_RECEIVED = "TOKEN_RECEIVED"; + public static final String PROJECT_ID = "PROJECT_ID"; + public static final String SESSION_ID = "sessionId"; + public static String firebaseInstanceId = ""; + + public static String token = ""; + public static Date exipryTime; + + /** + * function to call the firebase function which will send the fcm message containing token and expiry time to the device + */ + public static void callFirebaseFunction() { + Map data = new HashMap<>(); + data.put("deviceId", AppController.firebaseInstanceId); + FirebaseFunctions firebaseFunctions; + firebaseFunctions = FirebaseFunctions.getInstance(); + + firebaseFunctions + .getHttpsCallable("getOAuthToken") + .call(data); + } + + /** + * function to convert string to date + * @param dt : string date + * @return : converted date object + */ + public static Date getDateFromStrinng(String dt) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + try { + Date date = format.parse(dt); + return date; + } catch (ParseException e) { + e.printStackTrace(); + } + return null; + } + + +} diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/adapter/ChatRecyclerViewAdapter.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/adapter/ChatRecyclerViewAdapter.java new file mode 100644 index 00000000..763e349f --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/adapter/ChatRecyclerViewAdapter.java @@ -0,0 +1,69 @@ +package com.example.mlapitest.adapter; + +import android.content.Context; +import androidx.recyclerview.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.example.mlapitest.R; +import com.example.mlapitest.model.ChatMsgModel; + +import java.util.ArrayList; + +public class ChatRecyclerViewAdapter extends RecyclerView.Adapter { + + private ArrayList chatMsgModels; + private Context context; + + public ChatRecyclerViewAdapter(Context context, ArrayList chatMsgModels) { + this.context = context; + this.chatMsgModels = chatMsgModels; + + } + + @Override + public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.custom_chat_recyclerview_item, parent, false); + + return new MyViewHolder(itemView); + } + + @Override + public void onBindViewHolder(MyViewHolder holder, final int position) { + final ChatMsgModel chatMsgModel = chatMsgModels.get(position); + + if(chatMsgModel.getType()==1) { // Message Sent + holder.tvMsgSent.setText(chatMsgModel.getMsg()); + holder.tvMsgSent.setVisibility(View.VISIBLE); + holder.tvMsgReceived.setVisibility(View.GONE); + } else { + holder.tvMsgReceived.setText(chatMsgModel.getMsg()); + holder.tvMsgReceived.setVisibility(View.VISIBLE); + holder.tvMsgSent.setVisibility(View.GONE); + } + + + } + + @Override + public int getItemCount() { + return chatMsgModels.size(); + } + + public class MyViewHolder extends RecyclerView.ViewHolder { + RelativeLayout rlMain; + TextView tvMsgSent; + TextView tvMsgReceived; + + public MyViewHolder(View view) { + super(view); + rlMain = view.findViewById(R.id.rlMain); + tvMsgSent = view.findViewById(R.id.tvMsgSent); + tvMsgReceived = view.findViewById(R.id.tvMsgReceived); + } + } +} \ No newline at end of file diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/model/ChatMsgModel.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/model/ChatMsgModel.java new file mode 100644 index 00000000..b12505a5 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/model/ChatMsgModel.java @@ -0,0 +1,28 @@ +package com.example.mlapitest.model; + +public class ChatMsgModel { + + private String msg; + private int type; + + public ChatMsgModel(String msg, int type) { + this.msg = msg; + this.type = type; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } +} diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/service/MyFirebaseInstanceIDService.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/service/MyFirebaseInstanceIDService.java new file mode 100644 index 00000000..a212b4e4 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/service/MyFirebaseInstanceIDService.java @@ -0,0 +1,18 @@ +package com.example.mlapitest.service; + +import com.example.mlapitest.AppController; +import com.google.firebase.messaging.FirebaseMessagingService; + +public class MyFirebaseInstanceIDService extends FirebaseMessagingService { + private static final String TAG = MyFirebaseInstanceIDService.class.getSimpleName(); + + @Override + public void onNewToken(String s) { + super.onNewToken(s); + String refreshedToken = s; + + AppController.firebaseInstanceId = refreshedToken; + + } + +} \ No newline at end of file diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/service/MyFirebaseMessagingService.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/service/MyFirebaseMessagingService.java new file mode 100644 index 00000000..d35a850a --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/service/MyFirebaseMessagingService.java @@ -0,0 +1,46 @@ +package com.example.mlapitest.service; + +import android.content.Intent; +import android.util.Log; + +import com.example.mlapitest.AppController; +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; + +import org.json.JSONObject; + +public class MyFirebaseMessagingService extends FirebaseMessagingService { + + private static final String TAG = MyFirebaseMessagingService.class.getSimpleName(); + + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + Log.e("FirebaseMessage", "From: " + remoteMessage.getFrom()); + + if (remoteMessage == null) + return; + + // Check if message contains a notification payload. + if (remoteMessage.getNotification() != null) { + Log.e(TAG, "Notification Body: " + remoteMessage.getNotification().getBody()); + handleNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody()); + } + } + + /** + * function to save the token data in the AppController + * @param title : expiry time received from FCM + * @param message : token received from FCM + */ + private void handleNotification(String title, String message) { + AppController.exipryTime = AppController.getDateFromStrinng(title); + AppController.token = message; + + Intent intent = new Intent(AppController.TOKEN_RECEIVED); + sendBroadcast(intent); + } + + private void handleDataMessage(JSONObject json) { + Log.e(TAG, "push json: " + json.toString()); + } +} \ No newline at end of file diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/ChatActivity.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/ChatActivity.java new file mode 100644 index 00000000..f8a8cc8a --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/ChatActivity.java @@ -0,0 +1,230 @@ +package com.example.mlapitest.ui; + +import android.Manifest; +import android.app.ProgressDialog; +import android.content.ActivityNotFoundException; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.os.Handler; +import android.speech.RecognizerIntent; +import android.text.TextUtils; +import android.view.MenuItem; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.example.mlapitest.AppController; +import com.example.mlapitest.R; +import com.example.mlapitest.adapter.ChatRecyclerViewAdapter; +import com.example.mlapitest.model.ChatMsgModel; +import com.example.mlapitest.utils.ApiRequest; +import com.google.firebase.auth.FirebaseAuth; + +import java.util.ArrayList; + +public class ChatActivity extends AppCompatActivity { + + private static ChatRecyclerViewAdapter chatRecyclerViewAdapter; + private static ArrayList chatMsgModels; + private static RecyclerView rvChats; + private ApiRequest apiRequest; + + private String type = ""; + + private EditText etMsg; + private ImageButton btnSend; + private ImageButton btnMic; + + private ProgressDialog progressDialog; + + // Broadcast receiver to hide the progress dialog when token is received + private BroadcastReceiver br = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + progressDialog.dismiss(); + } + }; + + // function to addMessage in the recyclerview + public static void addMsg(String msg, int type) { + chatMsgModels.add(new ChatMsgModel(msg, type)); + chatRecyclerViewAdapter.notifyDataSetChanged(); + scrollToBottom(); + } + + // function to scroll the recyclerview at the bottom after each message sent or received + private static void scrollToBottom() { + new Handler().post(new Runnable() { + @Override + public void run() { + if (chatMsgModels.size() > 0) { + rvChats.smoothScrollToPosition(chatMsgModels.size() - 1); + } + } + }); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat); + + getSupportActionBar().setTitle("Chat"); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + checkPermissions(); + + type = this.getIntent().getStringExtra("type"); + + initViews(); + setupRecyclerView(); + initListeners(); + + apiRequest = new ApiRequest(); + + } + + private void initViews() { + progressDialog = new ProgressDialog(this); + progressDialog.setTitle("Loading"); + progressDialog.setMessage("Waiting for the token"); + progressDialog.setCancelable(false); + progressDialog.setCanceledOnTouchOutside(false); + + + etMsg = findViewById(R.id.etMsg); + btnSend = findViewById(R.id.btnSend); + btnMic = findViewById(R.id.btnMic); + rvChats = findViewById(R.id.rvChat); + } + + private void setupRecyclerView() { + rvChats.setLayoutManager(new LinearLayoutManager(this)); + chatMsgModels = new ArrayList<>(); + + chatRecyclerViewAdapter = new ChatRecyclerViewAdapter(this, chatMsgModels); + rvChats.setAdapter(chatRecyclerViewAdapter); + } + + private void initListeners() { + btnSend.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + sendMsg(type, etMsg.getText().toString()); + scrollToBottom(); + } + }); + + btnMic.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + promptSpeechInput(); + } + }); + } + + /** + * function to send the message + * @param type : type of message sentiment | tts | knowledge + * @param msg : message sent from user + */ + private void sendMsg(String type, String msg) { + if (!TextUtils.isEmpty(msg)) { + // check if the token is received and expiry time is received and not expired + if (AppController.exipryTime != null && !AppController.token.equals("") && AppController.exipryTime.getTime() > System.currentTimeMillis()) { + addMsg(msg, 1); + etMsg.setText(""); + apiRequest.callAPI(this, AppController.token, AppController.exipryTime, type, msg); + } else { + // get new token if expired or not received + getNewToken(); + } + } else { + Toast.makeText(this, "Please enter or say some message to send.", Toast.LENGTH_SHORT).show(); + } + } + + private void getNewToken() { + progressDialog.show(); + AppController.callFirebaseFunction(); + } + + private void promptSpeechInput() { + Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, + RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); + intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1000); + intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US"); + intent.putExtra(RecognizerIntent.EXTRA_PROMPT, + "Speak"); + try { + startActivityForResult(intent, 101); + } catch (ActivityNotFoundException a) { + Toast.makeText(getApplicationContext(), + "Not Supported", + Toast.LENGTH_SHORT).show(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == 101) { + ArrayList result = data + .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); + sendMsg(type, result.get(0)); + } + } + } + + public void checkPermissions() { + + ArrayList arrPerm = new ArrayList<>(); + arrPerm.add(Manifest.permission.INTERNET); + arrPerm.add(Manifest.permission.RECORD_AUDIO); + + + if (!arrPerm.isEmpty()) { + String[] permissions = new String[arrPerm.size()]; + permissions = arrPerm.toArray(permissions); + ActivityCompat.requestPermissions(this, permissions, 1); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onResume() { + super.onResume(); + IntentFilter intentFilter = new IntentFilter(AppController.TOKEN_RECEIVED); + registerReceiver(br, intentFilter); + } + + @Override + protected void onPause() { + super.onPause(); + if (br != null) { + try { + unregisterReceiver(br); + } catch (Exception ex) { + + } + } + } +} diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/MainActivity.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/MainActivity.java new file mode 100644 index 00000000..d1eb9b19 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/MainActivity.java @@ -0,0 +1,149 @@ +package com.example.mlapitest.ui; + +import android.content.Intent; +import android.content.res.AssetManager; +import android.os.Bundle; +import android.os.Environment; +import androidx.appcompat.app.AppCompatActivity; +import android.view.View; +import android.widget.TextView; + +import com.android.volley.RequestQueue; +import com.android.volley.toolbox.Volley; +import com.example.mlapitest.AppController; +import com.example.mlapitest.R; +import com.example.mlapitest.utils.ApiRequest; +import com.firebase.ui.auth.AuthUI; +import com.firebase.ui.auth.IdpResponse; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.List; + +public class MainActivity extends AppCompatActivity { + + // Firebase Login + private static final int RC_SIGN_IN = 123; + + // User + private static FirebaseUser firebaseUser; + private ApiRequest apiRequest; + + + public static TextView resultsTextView; + public static RequestQueue requestQueue; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + // Instantiate the RequestQueue. + requestQueue = Volley.newRequestQueue(this); + resultsTextView = findViewById(R.id.result_text); + + findViewById(R.id.login_button).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // Choose authentication providers + List providers = Arrays.asList( + new AuthUI.IdpConfig.GoogleBuilder().build()); + + // Create and launch sign-in intent + startActivityForResult( + AuthUI.getInstance() + .createSignInIntentBuilder() + .setAvailableProviders(providers) + .build(), + RC_SIGN_IN); + } + }); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == RC_SIGN_IN) { + IdpResponse response = IdpResponse.fromResultIntent(data); + + if (resultCode == RESULT_OK) { + System.out.println("SUCCESS"); + // Successfully signed in + firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + apiRequest = new ApiRequest(); + setupButtons(); + + + // ... + } else { + System.out.println("FAILURE"); + + // Sign in failed. If response is null the user canceled the + // sign-in flow using the back button. Otherwise check + // response.getError().getErrorCode() and handle the error. + // ... + } + } + } + + private void setupButtons() { + findViewById(R.id.make_request).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + AssetManager am = getAssets(); + InputStream inputStream = am.open("book_a_room.wav"); + File file = createFileFromInputStream(inputStream); + if(AppController.exipryTime!=null && !AppController.token.equals("") && AppController.exipryTime.getTime()>System.currentTimeMillis()) { + apiRequest.callAudioAPI(v.getContext(), AppController.token, AppController.exipryTime, file.getPath()); + } else { + getNewToken(); + } + } catch(Exception ex) { + ex.printStackTrace(); + } + } + }); + + findViewById(R.id.clear_output).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + resultsTextView.setText(null); + } + }); + } + + private void getNewToken() { + AppController.callFirebaseFunction(); + } + + private File createFileFromInputStream(InputStream inputStream) { + + try{ + File f = new File(Environment.getExternalStorageDirectory().getPath() + "/book_a_room.wav"); + OutputStream outputStream = new FileOutputStream(f); + byte buffer[] = new byte[1024]; + int length = 0; + + while((length=inputStream.read(buffer)) > 0) { + outputStream.write(buffer,0,length); + } + + outputStream.close(); + inputStream.close(); + + return f; + }catch (IOException e) { + //Logging exception + } + + return null; + } +} diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/WelcomeActivity.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/WelcomeActivity.java new file mode 100644 index 00000000..1b0d1cae --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/ui/WelcomeActivity.java @@ -0,0 +1,156 @@ +package com.example.mlapitest.ui; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; + +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.Toast; + +import com.android.volley.RequestQueue; +import com.android.volley.toolbox.Volley; +import com.example.mlapitest.AppController; +import com.example.mlapitest.R; +import com.firebase.ui.auth.AuthUI; +import com.firebase.ui.auth.IdpResponse; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.iid.InstanceIdResult; + +import java.util.Arrays; +import java.util.List; + +public class WelcomeActivity extends AppCompatActivity { + + private static final int RC_SIGN_IN = 123; + public static RequestQueue requestQueue; + private static FirebaseUser firebaseUser; + private Button btnNext; + private CheckBox chkTTS; + private CheckBox chkSentiment; + private CheckBox chkKnowledge; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_welcome); + + getSupportActionBar().setTitle("Dialog Flow Sample"); + + btnNext = findViewById(R.id.btnNext); + chkTTS = findViewById(R.id.chkTTS); + chkSentiment = findViewById(R.id.chkSentiment); + chkKnowledge = findViewById(R.id.chkKnowledge); + + // Instantiate the RequestQueue. + requestQueue = Volley.newRequestQueue(this); + + List providers = Arrays.asList( + new AuthUI.IdpConfig.GoogleBuilder().build()); + + + // Sign in code + startActivityForResult( + AuthUI.getInstance() + .createSignInIntentBuilder() + .setAvailableProviders(providers) + .build(), + RC_SIGN_IN); + + chkKnowledge.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + if (b) { + chkSentiment.setChecked(false); + chkTTS.setChecked(false); + } + } + }); + + chkSentiment.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + if (b) { + chkKnowledge.setChecked(false); + chkTTS.setChecked(false); + } + } + }); + + chkTTS.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + if (b) { + chkSentiment.setChecked(false); + chkKnowledge.setChecked(false); + } + } + }); + + getFirebaseInstanceId(); + } + + private void getFirebaseInstanceId() { + FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(InstanceIdResult instanceIdResult) { + String deviceToken = instanceIdResult.getToken(); + AppController.firebaseInstanceId = deviceToken; + Log.i("fcmId", deviceToken); + } + }); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == RC_SIGN_IN) { + IdpResponse response = IdpResponse.fromResultIntent(data); + if (resultCode == RESULT_OK) { + System.out.println("SUCCESS"); + firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + setupButtons(); + } else { + System.out.println("FAILURE"); + } + } + } + + private void setupButtons() { + btnNext.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //String path = "android.resource://" + getPackageName() + "/" + R.raw.book_a_room; + + Intent intent = new Intent(WelcomeActivity.this, ChatActivity.class); + + // According to the selection of checkbox send the type of feature + if (chkTTS.isChecked()) { + intent.putExtra("type", "tts"); + } else if (chkKnowledge.isChecked()) { + intent.putExtra("type", "knowledge"); + } else if (chkSentiment.isChecked()) { + intent.putExtra("type", "sentiment"); + } + + if(!intent.hasExtra("type")) { + Toast.makeText(WelcomeActivity.this, "Please select a type to continue.", Toast.LENGTH_SHORT).show(); + return; + } + startActivity(intent); + } + }); + } + +} diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/utils/ApiRequest.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/utils/ApiRequest.java new file mode 100644 index 00000000..f1b82187 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/utils/ApiRequest.java @@ -0,0 +1,554 @@ +package com.example.mlapitest.utils; + +import android.content.Context; +import android.os.AsyncTask; +import android.widget.Toast; + +import com.example.mlapitest.AppController; +import com.example.mlapitest.ui.ChatActivity; +import com.example.mlapitest.ui.MainActivity; +import com.google.api.client.util.Maps; +import com.google.api.gax.core.FixedCredentialsProvider; +import com.google.api.gax.rpc.BidiStream; +import com.google.auth.Credentials; +import com.google.auth.oauth2.AccessToken; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.dialogflow.v2.AudioEncoding; +import com.google.cloud.dialogflow.v2.DetectIntentRequest; +import com.google.cloud.dialogflow.v2.DetectIntentResponse; +import com.google.cloud.dialogflow.v2.InputAudioConfig; +import com.google.cloud.dialogflow.v2.OutputAudioConfig; +import com.google.cloud.dialogflow.v2.OutputAudioEncoding; +import com.google.cloud.dialogflow.v2.QueryInput; +import com.google.cloud.dialogflow.v2.QueryParameters; +import com.google.cloud.dialogflow.v2.QueryResult; +import com.google.cloud.dialogflow.v2.SentimentAnalysisRequestConfig; +import com.google.cloud.dialogflow.v2.SessionName; +import com.google.cloud.dialogflow.v2.SessionsClient; +import com.google.cloud.dialogflow.v2.SessionsSettings; +import com.google.cloud.dialogflow.v2.StreamingDetectIntentRequest; +import com.google.cloud.dialogflow.v2.StreamingDetectIntentResponse; +import com.google.cloud.dialogflow.v2.TextInput; +import com.google.cloud.dialogflow.v2beta1.KnowledgeAnswers; +import com.google.cloud.dialogflow.v2beta1.KnowledgeBaseName; +import com.google.firebase.functions.FirebaseFunctions; +import com.google.protobuf.ByteString; + +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + + +public class ApiRequest { + private String TAG = "API_REQUEST"; + + // Variables needed to request an auth token + private FirebaseFunctions firebaseFunctions; + + // Variables needed to retrieve an auth token + private SimpleDateFormat simpleDateFormat; + private String token = null; + private Date tokenExpiration = null; + + public ApiRequest() { + firebaseFunctions = FirebaseFunctions.getInstance(); + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + } + + /** + * function to call: detect Intent Sentiment Analysis | Detect Intent With TTS | KnowledgeBase + * @param context : context + * @param accessToken : access token received from fcm + * @param expiryTime : expiry time received from fcm + * @param type : type of api call + * @param arg : message from user + */ + public void callAPI(Context context, String accessToken, Date expiryTime, String type, String arg) { + Toast.makeText(context, "Calling the API", Toast.LENGTH_SHORT).show(); + this.token = accessToken; + this.tokenExpiration = expiryTime; + if (type.equals("sentiment")) { + detectIntentSentimentAnalysis(arg); + } else if (type.equals("tts")) { + detectIntentWithTexttoSpeech(arg); + } else if (type.equals("knowledge")) { + new MyKnowledgeBaseRequest().execute(arg); + } + } + + /** + * function to call the detect input stream + * @param context : context + * @param accessToken : access token received from fcm + * @param expiryTime : expiry time received from fcm + * @param filePath : file path of the audio to be sent to dialog flow + */ + public void callAudioAPI(Context context, String accessToken, Date expiryTime, String filePath) { + Toast.makeText(context, "Calling the API", Toast.LENGTH_SHORT).show(); + this.token = accessToken; + this.tokenExpiration = expiryTime; + detectIntentStream(filePath); + } + + /** + * function to detect intent audio + * @param audioFilePath : path to the audio file + */ + public void detectIntentAudio(String audioFilePath) { + Map queryResults = Maps.newHashMap(); + // Instantiates a client + + try { + AccessToken accessToken = new AccessToken(token, tokenExpiration); + Credentials credentials = GoogleCredentials.create(accessToken); + FixedCredentialsProvider fixedCredentialsProvider = FixedCredentialsProvider.create(credentials); + + SessionsSettings sessionsSettings = SessionsSettings.newBuilder().setCredentialsProvider(fixedCredentialsProvider).build(); + + // Instantiates a client + try (SessionsClient sessionsClient = SessionsClient.create(sessionsSettings)) { + // Set the session name using the sessionId (UUID) and projectID (my-project-id) + SessionName session = SessionName.of(AppController.PROJECT_ID, AppController.SESSION_ID); + System.out.println("Session Path: " + session.toString()); + + // Note: hard coding audioEncoding and sampleRateHertz for simplicity. + // Audio encoding of the audio content sent in the query request. + AudioEncoding audioEncoding = AudioEncoding.AUDIO_ENCODING_LINEAR_16; + int sampleRateHertz = 16000; + + // Instructs the speech recognizer how to process the audio content. + InputAudioConfig inputAudioConfig = InputAudioConfig.newBuilder() + .setAudioEncoding(audioEncoding) // audioEncoding = AudioEncoding.AUDIO_ENCODING_LINEAR_16 + .setLanguageCode("en-US") // languageCode = "en-US" + .setSampleRateHertz(sampleRateHertz) // sampleRateHertz = 16000 + .build(); + + // Build the query with the InputAudioConfig + QueryInput queryInput = QueryInput.newBuilder().setAudioConfig(inputAudioConfig).build(); + + // Read the bytes from the audio file + byte[] inputAudio = Files.readAllBytes(Paths.get(audioFilePath)); + + // Build the DetectIntentRequest + DetectIntentRequest request = DetectIntentRequest.newBuilder() + .setSession(session.toString()) + .setQueryInput(queryInput) + .setInputAudio(ByteString.copyFrom(inputAudio)) + .build(); + + // Performs the detect intent request + DetectIntentResponse response = sessionsClient.detectIntent(request); + + // Display the query result + QueryResult queryResult = response.getQueryResult(); + System.out.println("===================="); + System.out.format("Query Text: '%s'\n", queryResult.getQueryText()); + System.out.format("Detected Intent: %s (confidence: %f)\n", + queryResult.getIntent().getDisplayName(), queryResult.getIntentDetectionConfidence()); + System.out.format("Fulfillment Text: '%s'\n", queryResult.getFulfillmentText()); + MainActivity.resultsTextView.setText(queryResult.getFulfillmentText()); + } catch (Exception ex) { + ex.printStackTrace(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + /** + * function to detect input stream + * @param audioFilePath : path to audio file + */ + private void detectIntentStream(String audioFilePath) { + + try { + AccessToken accessToken = new AccessToken(token, tokenExpiration); + Credentials credentials = GoogleCredentials.create(accessToken); + FixedCredentialsProvider fixedCredentialsProvider = FixedCredentialsProvider.create(credentials); + + SessionsSettings sessionsSettings = SessionsSettings.newBuilder().setCredentialsProvider(fixedCredentialsProvider).build(); + + // Instantiates a client + try (SessionsClient sessionsClient = SessionsClient.create(sessionsSettings)) { + // Set the session name using the sessionId (UUID) and projectID (my-project-id) + SessionName session = SessionName.of(AppController.PROJECT_ID, AppController.SESSION_ID); + System.out.println("Session Path: " + session.toString()); + + // Note: hard coding audioEncoding and sampleRateHertz for simplicity. + // Audio encoding of the audio content sent in the query request. + AudioEncoding audioEncoding = AudioEncoding.AUDIO_ENCODING_LINEAR_16; + int sampleRateHertz = 16000; + + // Instructs the speech recognizer how to process the audio content. + InputAudioConfig inputAudioConfig = InputAudioConfig.newBuilder() + .setAudioEncoding(audioEncoding) // audioEncoding = AudioEncoding.AUDIO_ENCODING_LINEAR_16 + .setLanguageCode("en-US") // languageCode = "en-US" + .setSampleRateHertz(sampleRateHertz) // sampleRateHertz = 16000 + .build(); + + QueryInput queryInput = QueryInput.newBuilder().setAudioConfig(inputAudioConfig).build(); + + // Create the Bidirectional stream + BidiStream bidiStream = + sessionsClient.streamingDetectIntentCallable().call(); + + // The first request must **only** contain the audio configuration: + bidiStream.send(StreamingDetectIntentRequest.newBuilder() + .setSession(session.toString()) + .setQueryInput(queryInput) + .build()); + + try (FileInputStream audioStream = new FileInputStream(audioFilePath)) { + // Subsequent requests must **only** contain the audio data. + // Following messages: audio chunks. We just read the file in fixed-size chunks. In reality + // you would split the user input by time. + byte[] buffer = new byte[4096]; + int bytes; + while ((bytes = audioStream.read(buffer)) != -1) { + bidiStream.send( + StreamingDetectIntentRequest.newBuilder() + .setInputAudio(ByteString.copyFrom(buffer, 0, bytes)) + .build()); + } + } + + // Tell the service you are done sending data + bidiStream.closeSend(); + + for (StreamingDetectIntentResponse response : bidiStream) { + QueryResult queryResult = response.getQueryResult(); + System.out.println("===================="); + System.out.format("Intent Display Name: %s\n", queryResult.getIntent().getDisplayName()); + System.out.format("Query Text: '%s'\n", queryResult.getQueryText()); + System.out.format("Detected Intent: %s (confidence: %f)\n", + queryResult.getIntent().getDisplayName(), queryResult.getIntentDetectionConfidence()); + System.out.format("Fulfillment Text: '%s'\n", queryResult.getFulfillmentText()); + if (!queryResult.getFulfillmentText().equals("")) { + MainActivity.resultsTextView.setText("Fulfillment Text: " + queryResult.getFulfillmentText()); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } catch (Throwable ex) { + ex.printStackTrace(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + // [END dialogflow_detect_intent_streaming] + + /** + * function to detect input sentiment analysis + * @param msg : message sent from user + */ + private void detectIntentSentimentAnalysis(String msg) { + List texts = new ArrayList<>(); + texts.add(msg); + try { + AccessToken accessToken = new AccessToken(token, tokenExpiration); + Credentials credentials = GoogleCredentials.create(accessToken); + FixedCredentialsProvider fixedCredentialsProvider = FixedCredentialsProvider.create(credentials); + + SessionsSettings sessionsSettings = SessionsSettings.newBuilder().setCredentialsProvider(fixedCredentialsProvider).build(); + // Instantiates a client + try (SessionsClient sessionsClient = SessionsClient.create(sessionsSettings)) { + // Set the session name using the sessionId (UUID) and projectID (my-project-id) + SessionName session = SessionName.of(AppController.PROJECT_ID, AppController.SESSION_ID); + System.out.println("Session Path: " + session.toString()); + + // Detect intents for each text input + for (String text : texts) { + // Set the text (hello) and language code (en-US) for the query + TextInput.Builder textInput = TextInput.newBuilder().setText(text).setLanguageCode("en-US"); + + // Build the query with the TextInput + QueryInput queryInput = QueryInput.newBuilder().setText(textInput).build(); + + // + SentimentAnalysisRequestConfig sentimentAnalysisRequestConfig = + SentimentAnalysisRequestConfig.newBuilder().setAnalyzeQueryTextSentiment(true).build(); + + QueryParameters queryParameters = + QueryParameters.newBuilder() + .setSentimentAnalysisRequestConfig(sentimentAnalysisRequestConfig) + .build(); + DetectIntentRequest detectIntentRequest = + DetectIntentRequest.newBuilder() + .setSession(session.toString()) + .setQueryInput(queryInput) + .setQueryParams(queryParameters) + .build(); + + // Performs the detect intent request + DetectIntentResponse response = sessionsClient.detectIntent(detectIntentRequest); + + // Display the query result + QueryResult queryResult = response.getQueryResult(); + + System.out.println("===================="); + System.out.format("Query Text: '%s'\n", queryResult.getQueryText()); + System.out.format( + "Detected Intent: %s (confidence: %f)\n", + queryResult.getIntent().getDisplayName(), queryResult.getIntentDetectionConfidence()); + System.out.format("Fulfillment Text: '%s'\n", queryResult.getFulfillmentText()); + System.out.format( + "Sentiment Score: '%s'\n", + queryResult.getSentimentAnalysisResult().getQueryTextSentiment().getScore()); + //MainActivity.resultsTextView.setText(queryResult.getFulfillmentText()); + ChatActivity.addMsg(queryResult.getFulfillmentText(), 0); + } + } catch (Throwable ex) { + ex.printStackTrace(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + // [END dialogflow_detect_intent_with_sentiment_analysis] + + /** + * function to detect input with TTS + * @param queryMsg : message sent from user + */ + private void detectIntentWithTexttoSpeech(String queryMsg) { + List texts = new ArrayList<>(); + texts.add(queryMsg); + try { + AccessToken accessToken = new AccessToken(token, tokenExpiration); + Credentials credentials = GoogleCredentials.create(accessToken); + FixedCredentialsProvider fixedCredentialsProvider = FixedCredentialsProvider.create(credentials); + + SessionsSettings sessionsSettings = SessionsSettings.newBuilder().setCredentialsProvider(fixedCredentialsProvider).build(); + // Instantiates a client + try (SessionsClient sessionsClient = SessionsClient.create(sessionsSettings)) { + // Set the session name using the sessionId (UUID) and projectID (my-project-id) + SessionName session = SessionName.of(AppController.PROJECT_ID, AppController.SESSION_ID); + System.out.println("Session Path: " + session.toString()); + + // Detect intents for each text input + for (String text : texts) { + // Set the text (hello) and language code (en-US) for the query + TextInput.Builder textInput = TextInput.newBuilder().setText(text).setLanguageCode("en-US"); + + // Build the query with the TextInput + QueryInput queryInput = QueryInput.newBuilder().setText(textInput).build(); + + // + OutputAudioEncoding audioEncoding = OutputAudioEncoding.OUTPUT_AUDIO_ENCODING_LINEAR_16; + int sampleRateHertz = 16000; + OutputAudioConfig outputAudioConfig = + OutputAudioConfig.newBuilder() + .setAudioEncoding(audioEncoding) + .setSampleRateHertz(sampleRateHertz) + .build(); + + DetectIntentRequest dr = + DetectIntentRequest.newBuilder() + .setQueryInput(queryInput) + .setOutputAudioConfig(outputAudioConfig) + .setSession(session.toString()) + .build(); + + // Performs the detect intent request + // DetectIntentResponse response = sessionsClient.detectIntent(session, + // queryInput,outputAudioConfig); + DetectIntentResponse response = sessionsClient.detectIntent(dr); + + // Display the query result + QueryResult queryResult = response.getQueryResult(); + + System.out.println("===================="); + System.out.format("Query Text: '%s'\n", queryResult.getQueryText()); + System.out.format( + "Detected Intent: %s (confidence: %f)\n", + queryResult.getIntent().getDisplayName(), queryResult.getIntentDetectionConfidence()); + System.out.format("Fulfillment Text: '%s'\n", queryResult.getFulfillmentText()); + ChatActivity.addMsg(queryResult.getFulfillmentText(), 0); + } + } catch (Throwable ex) { + ex.printStackTrace(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + /** + * function to detect intent knowledge + * @param knowledgebaseId : Knowledge base id + * @param msg : Message sent from user + */ + private void detectIntentKnowledge(String knowledgebaseId, + String msg) { + List texts = new ArrayList<>(); + texts.add(msg); + try { + AccessToken accessToken = new AccessToken(token, tokenExpiration); + Credentials credentials = GoogleCredentials.create(accessToken); + FixedCredentialsProvider fixedCredentialsProvider = FixedCredentialsProvider.create(credentials); + com.google.cloud.dialogflow.v2beta1.SessionsSettings sessionsSettings = com.google.cloud.dialogflow.v2beta1.SessionsSettings.newBuilder().setCredentialsProvider(fixedCredentialsProvider).build(); + // Instantiates a client + try (com.google.cloud.dialogflow.v2beta1.SessionsClient sessionsClient = com.google.cloud.dialogflow.v2beta1.SessionsClient.create(sessionsSettings)) { + // Set the session name using the sessionId (UUID) and projectID (my-project-id) + SessionName session = SessionName.of(AppController.PROJECT_ID, AppController.SESSION_ID); + System.out.println("Session Path: " + session.toString()); + + // Detect intents for each text input + for (String text : texts) { + // Set the text and language code (en-US) for the query + com.google.cloud.dialogflow.v2beta1.TextInput.Builder textInput = com.google.cloud.dialogflow.v2beta1.TextInput.newBuilder().setText(text).setLanguageCode("en-US"); + // Build the query with the TextInput + com.google.cloud.dialogflow.v2beta1.QueryInput queryInput = com.google.cloud.dialogflow.v2beta1.QueryInput.newBuilder().setText(textInput).build(); + + KnowledgeBaseName knowledgeBaseName = KnowledgeBaseName.of(AppController.PROJECT_ID, knowledgebaseId); + com.google.cloud.dialogflow.v2beta1.QueryParameters queryParameters = + com.google.cloud.dialogflow.v2beta1.QueryParameters.newBuilder() + .addKnowledgeBaseNames(knowledgeBaseName.toString()) + .build(); + + com.google.cloud.dialogflow.v2beta1.DetectIntentRequest detectIntentRequest = + com.google.cloud.dialogflow.v2beta1.DetectIntentRequest.newBuilder() + .setSession(session.toString()) + .setQueryInput(queryInput) + .setQueryParams(queryParameters) + .build(); + // Performs the detect intent request + com.google.cloud.dialogflow.v2beta1.DetectIntentResponse response = sessionsClient.detectIntent(detectIntentRequest); + + // Display the query result + com.google.cloud.dialogflow.v2beta1.QueryResult queryResult = response.getQueryResult(); + + System.out.format("Knowledge results:\n"); + System.out.format("====================\n"); + System.out.format("Query Text: '%s'\n", queryResult.getQueryText()); + System.out.format( + "Detected Intent: %s (confidence: %f)\n", + queryResult.getIntent().getDisplayName(), queryResult.getIntentDetectionConfidence()); + System.out.format("Fulfillment Text: '%s'\n", queryResult.getFulfillmentText()); + KnowledgeAnswers knowledgeAnswers = queryResult.getKnowledgeAnswers(); + for (KnowledgeAnswers.Answer answer : knowledgeAnswers.getAnswersList()) { + System.out.format(" - Answer: '%s'\n", answer.getAnswer()); + System.out.format(" - Confidence: '%s'\n", answer.getMatchConfidence()); + ChatActivity.addMsg(answer.getAnswer(), 0); + } + if (knowledgeAnswers.getAnswersCount() == 0) { + ChatActivity.addMsg("No Response", 0); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + /** + * function to get the detect the intent + */ + private void detectIntent() { + Map queryResults = Maps.newHashMap(); + // Instantiates a client + + AccessToken accessToken = new AccessToken(token, tokenExpiration); + Credentials credentials = GoogleCredentials.create(accessToken); + FixedCredentialsProvider fixedCredentialsProvider = FixedCredentialsProvider.create(credentials); + try { + SessionsSettings sessionsSettings = SessionsSettings.newBuilder().setCredentialsProvider(fixedCredentialsProvider).build(); + + try (SessionsClient sessionsClient = SessionsClient.create(sessionsSettings)) { + // Set the session name using the sessionId (UUID) and projectID (my-project-id) + SessionName session = SessionName.of(AppController.PROJECT_ID, AppController.SESSION_ID); + System.out.println("Session Path: " + session.toString()); + + List texts = new ArrayList<>(); + texts.add("book a room"); + // Detect intents for each text input + for (String text : texts) { + // Set the text (hello) and language code (en-US) for the query + TextInput textInput = TextInput.newBuilder() + .setText(text) + .setLanguageCode("en-US") + .build(); + + // Build the query with the TextInput + QueryInput queryInput = QueryInput.newBuilder() + .setText(textInput) + .build(); + + // Performs the detect intent request + DetectIntentResponse response = sessionsClient.detectIntent(session, queryInput); + + // Display the query result + QueryResult queryResult = response.getQueryResult(); + + System.out.println("===================="); + System.out.format("Query Text: '%s'\n", queryResult.getQueryText()); + System.out.format("Detected Intent: %s (confidence: %f)\n", + queryResult.getIntent().getDisplayName(), queryResult.getIntentDetectionConfidence()); + System.out.format("Fulfillment Text: '%s'\n", queryResult.getFulfillmentText()); + + queryResults.put(text, queryResult); + MainActivity.resultsTextView.setText(queryResult.getFulfillmentText()); + + } + } catch (IOException e) { + e.printStackTrace(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * AsyncTask class to get the knowledgebase id + */ + private class MyKnowledgeBaseRequest extends AsyncTask { + + private String msg = ""; + + @Override + protected String doInBackground(String... args) { + msg = args[0]; + + try { + AccessToken accessToken = new AccessToken(token, tokenExpiration); + Credentials credentials = GoogleCredentials.create(accessToken); + FixedCredentialsProvider fixedCredentialsProvider = FixedCredentialsProvider.create(credentials); + com.google.cloud.dialogflow.v2beta1.KnowledgeBasesSettings sessionsSettings = com.google.cloud.dialogflow.v2beta1.KnowledgeBasesSettings.newBuilder().setCredentialsProvider(fixedCredentialsProvider).build(); + + ArrayList ids = KnowledgebaseManagement.listKnowledgeBases(AppController.PROJECT_ID, sessionsSettings); + + if (ids.size() > 0) { + + return ids.get(0); + + } + + } catch (Exception ex) { + return ""; + } + + return ""; + } + + @Override + protected void onPostExecute(String str) { + super.onPostExecute(str); + + if (!str.equals("")) { + detectIntentKnowledge(str.substring(str.lastIndexOf("/") + 1), msg); + } + } + } + +} diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/utils/KnowledgebaseManagement.java b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/utils/KnowledgebaseManagement.java new file mode 100644 index 00000000..f25638ee --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/java/com/example/mlapitest/utils/KnowledgebaseManagement.java @@ -0,0 +1,97 @@ +package com.example.mlapitest.utils; + + +import com.google.cloud.dialogflow.v2beta1.KnowledgeBase; +import com.google.cloud.dialogflow.v2beta1.KnowledgeBaseName; +import com.google.cloud.dialogflow.v2beta1.KnowledgeBasesClient; +import com.google.cloud.dialogflow.v2beta1.KnowledgeBasesSettings; +import com.google.cloud.dialogflow.v2beta1.ProjectName; + +import java.util.ArrayList; + +public class KnowledgebaseManagement { + + // [START dialogflow_list_knowledge_base] + /** + * List Knowledge bases + * + * @param projectId Project/agent id. + */ + public static ArrayList listKnowledgeBases(String projectId, KnowledgeBasesSettings knowledgeBasesSettings) throws Exception { + ArrayList ids = new ArrayList<>(); + // Instantiates a client + try (KnowledgeBasesClient knowledgeBasesClient = KnowledgeBasesClient.create(knowledgeBasesSettings)) { + // Set the entity type name using the projectID (my-project-id) and entityTypeId (KIND_LIST) + ProjectName projectName = ProjectName.of(projectId); + for (KnowledgeBase knowledgeBase : + knowledgeBasesClient.listKnowledgeBases(projectName).iterateAll()) { + System.out.format(" - Display Name: %s\n", knowledgeBase.getDisplayName()); + System.out.format(" - Knowledge ID: %s\n", knowledgeBase.getName()); + ids.add(knowledgeBase.getName()); + } + } + + return ids; + } + // [END dialogflow_list_knowledge_base] + + // [START dialogflow_create_knowledge_base] + /** + * Create a Knowledge base + * + * @param projectId Project/agent id. + * @param displayName Name of the knowledge base. + */ + public static void createKnowledgeBase(String projectId, String displayName) throws Exception { + // Instantiates a client + try (KnowledgeBasesClient knowledgeBasesClient = KnowledgeBasesClient.create()) { + + KnowledgeBase knowledgeBase = KnowledgeBase.newBuilder().setDisplayName(displayName).build(); + ProjectName projectName = ProjectName.of(projectId); + KnowledgeBase response = knowledgeBasesClient.createKnowledgeBase(projectName, knowledgeBase); + System.out.format("Knowledgebase created:\n"); + System.out.format("Display Name: %s \n", response.getDisplayName()); + System.out.format("Knowledge ID: %s \n", response.getName()); + } + } + // [END dialogflow_create_knowledge_base] + + // [START dialogflow_get_knowledge_base] + + /** + * @param knowledgeBaseId Knowledge base id. + * @param projectId Project/agent id. + * @throws Exception + */ + public static void getKnowledgeBase(String projectId, String knowledgeBaseId) throws Exception { + + // Instantiates a client + try (KnowledgeBasesClient knowledgeBasesClient = KnowledgeBasesClient.create()) { + KnowledgeBaseName knowledgeBaseName = KnowledgeBaseName.of(projectId, knowledgeBaseId); + KnowledgeBase response = knowledgeBasesClient.getKnowledgeBase(knowledgeBaseName); + System.out.format("Got Knowledge Base:\n"); + System.out.format(" - Display Name: %s\n", response.getDisplayName()); + System.out.format(" - Knowledge ID: %s\n", response.getName()); + } + } + // [END dialogflow_get_knowledge_base] + // [START dialogflow_delete_knowledge_base] + + /** + * @param knowledgeBaseId Knowledge base id. + * @param projectId Project/agent id. + * @throws Exception + */ + public static void deleteKnowledgeBase(String projectId, String knowledgeBaseId) + throws Exception { + // Instantiates a client + try (KnowledgeBasesClient knowledgeBasesClient = KnowledgeBasesClient.create()) { + KnowledgeBaseName knowledgeBaseName = KnowledgeBaseName.of(projectId, knowledgeBaseId); + knowledgeBasesClient.deleteKnowledgeBase(knowledgeBaseName); + System.out.format("KnowledgeBase has been deleted.\n"); + } + } + // [END dialogflow_delete_knowledge_base] + + // [START run_application] +} diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-hdpi/ic_mic.png b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-hdpi/ic_mic.png new file mode 100755 index 0000000000000000000000000000000000000000..626b816a43982abaf94ae08aaf5a126a055d956e GIT binary patch literal 609 zcmV-n0-pVeP)f_!wQ3!mymw#SyU%^ktG!3($KGpyf2_UE-e<%#ZzIzjze-@L9jp#i2MQIaDO4z6 z@$l+Ev4n*IsslX)oPo7io$sIHDSj0SK4$nZ90>47umW)%Er7qm`L0O}gTOi*Y=Li7 z3lf*`q)QiuL0~U7_W*exSO0ec2e6?B$Va$b3A7X#MhaC2`bn|sz&L8v6q?KwitWNm zyuh=Zct1Aw0Pzr4^4%J&!pq!d^n?3v-_kX(4ZCm;*D~r>>}Jd#kKeeCyV-9Kw%`Wt z41|81N&1bm97pj6XLImE9K*bSf_=$8AM<(iS%!0X-S5Or|569$;3VeaG~Q+4**K0x zdH(@t@ICLB-~_(n6uwOrftYs(b|#om^L>Jug#~&22|x0Bak>_yZ{pUV;A32=1I^rr za{nJ`GMZcG25{47W-j=BnO<=|xL5+dO9GKHhY@SyCxS?9o8KnDrHE~ItcxHLIe(#* zQUmko%7Fk7hnJ{8QCa5qs6wB!VnrqDr@aGF@3$wx+pX_Ir)f0I6zUXcuV9tHq{uwMB-MfH vK%oLPg$e~M9$pNkl~GfE`(JDA zU7^%`5fERaN`okY^JxSna3yd)3HTgVvbc1>nVC$cj7AyH37^j?x?$Gh%uKEW7l2<7 z=1|REsimXnXrwS<7o72oX+!uK!!&BxB(HKOh36Gb*RH_1laB%05$4l}HB{0nwfs{w zWO|usPvE>mk02}{!bZwyqA!<<-IbFCXO}{|4hl;!tRun!syHXL+$}~cOa+|FM*;o~ zYy>tCVGA)1O9Quy37{WvUOu`T?*(=fVFl%Em$BR`27u{;a~Y|-9tBPV-y*D)23iXl zV5Y!%-M9tASsYfm7r`SK?kRtG@*LYifWZK<$O&YEh0AQkhc~FaNejy*F2Rk3yCs~ft<|O zP8=q1U0Ih#B_C162}W}}m!VzQ!MQLG0v{0J7*(8NG;P^-v(Xz-z!7n=8}|%|uRT3ZM&aDeyed4=4lr0FGxh zE`*A|0&K>yHIwzyKzlk`CJt^s!-??_F`^h8`{US?OoNFr33w9dp8#48|DAFQ8&FNC z9tV43p^+LE_^liFIB~O%C`TEJLw|$_9jNS#TcX1gbT9$oQ9xl<0MU>@RZ-oVNVG1b zjCoSe)l@9dx5b!cL};Tg4iWo-n(x&XAwrCoi19J-KmurIsHwbTw)?7}zGLgg4xh@~ zHf!B$^9`=oCwI}o!oI>34C4~k>FuSK90b6-D7RmH2jjWfot()jxSn9!b+(&Afr*CW)~jKuIR#=^V*oejefp3WLj;TVRw zwsu^>ZW+fVeb-Qc>jmm4VvOk|pLAvw#CRE@CPVX7V2kapJeYam2RD;P5MD`0CDos< z2JMI8b>QI)fm1QP3T%Dk^H6{@v#7yP3k>rJbd^48S;H|rlh|x@ZS+c_On8;%0hb~C zPL!?G)2tgtV8EFrw4ki7+A|!gcpmK;C!H#yrjfA6g|_K~v}K zb2dJ(+a<}Uc%H?3z-z#O1Q?Yd3PUYrP(qUEd$~XE^K$jBhk!Szpp_b0x+|V%{ADbh z*}Q<^eT1PHhI9gw3HM1wRwUOqe(vuRd55NC2J{?qDTKvTahGx%A#~snON3nacno0- zhR1<{Hm;59ELVeN{7Xq@LP_?~nDr)b6=5-b`GT?hl}hd|9^@}z2<=qULDa^i|Hq}( zKpny;u$H4jR9(znV}cB)D~1Y8L#lY;r;=HID`#W*8j_KGr>4i2Q7hr4g5GBfjAqfE|ZQtH)W?`p)a8~ldhXr_P_ zD!67~4zSY}Y^pe)t-5QWxax6)sTlTA&SC1fo~hbGcXl3ja2quFNQC_ius45lcDgC7 z;FcnM2JFxD+Li1|8U}E#Sk(o81u%nZPGxKDDim;9kvfggXsc3_xR8pvPZoloenGT2 zz2>QBLH@*H5&hUKZ`u2_foeelr-{Nnz#sNX;(K(waEaOKRk5-8awxtVBWrJR3+lR0mhjlWM%LPlzGciBl)E)IK*=`J*a9FRu zO9Luki>9RlPJyX4txWtYA(a)!gRJhe`7I_3PET=vudax2keEI8l-3#AY)&c{&+ZAF zrgJpd{*I`*MgFr$OW99KBFsecQI_W_4q!lrJbwAZe2ae5l!W2Ra@`NPfuhf zirN)>vuL*s#YDo|X+YyE&rj(m5C2&4Dm%x?4`6S?TSjpl_;CvGBIqY8& W<3ZB_S%#zl0000G%c)224<=yd-=DBcI0Dz{Ch8OcW+YW-<^uGB}yYL_~RM z={9-l$=>@pJd?d9yLM~c*MDDo-D@?db2QXhUkOk;P&!bH13ef*6Ap1%=)xje zljtLsaGe*TD8L}5D#UiM_gw%Z7^@K5$96pd4zN`Me5C^ec*ZG)Fl-IUaw%}aqiTLMXf9|NofdGhk5Dx6(DYtsT p9w?$ywWbya{tHM6P&!aL@CMmQG$De|hvEPL002ovPDHLkV1mf^rNsaM literal 0 HcmV?d00001 diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-mdpi/ic_send.png b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-mdpi/ic_send.png new file mode 100755 index 0000000000000000000000000000000000000000..6c9e2983ebcecc70d502cb10f0c8ebb6633ab0f0 GIT binary patch literal 1041 zcmV+s1n&EZP)_i;5_z3^8p=%WQJTKF-l&>70G`oHJ)9J}@_P*0Z1AcRy>dwVw5a zi)_S2#^VxD(RVbG7c4gED&2O*pc6$GTu)yl>)net@s+SsmuF+pPxU4i_4it!s>V~; ztZbu&#$&+AqKZGCuJZxa+8q&wb$R#y;*RxzQn*CofUrkmU99$Pk#{T$P_6zG!bT-q zTP9=` zc9ZRZYbH>w{zS=AoyKQ7I<^X^3U>e>3TtA-!P(fcRs)@72pc4J=(D?($$IvH&Y~U0 za-H@Wax9_}SeiE40aO+LCEnL#Z9L%DW)Za$sLJpc)+-s)YgY_Nqh;<<1fX+kNA4Fs zh!GQcsEP(uWk~DAPle?%;`c_t(gR+fNkc*}E<;ITF>XRPI;S4kuH*WP!do7)BSLz# znRa9nnY^UmNzdUrVZKBe3$U>A0#tevnVwZoP#v|mVgGdQm|MgYWWP|B)&-|QU&oa* z5?z1tLE)1ashqU`GjapfUzcQqr4o0Zu?-y(gP50Peg>OoFdnPCSG8>^PzFJg^&ZCK zH7=XF^EC~+@PrOGTj1v+04>9?#5`dRy0EB0px-3!G1vZ<0!_8ZmefScPDv%AUOx4| znFf>RmF(7QTQwo)21>T-anyVzvhu8xIvg`^E^e@d*9W4@nuHKSm%Ek>jc%h;;lFb%4?r!u|a!XPXcdNuL zl~Bywnp~6RJ8!nlc3}rzjS*?xH+`zA>73THoz345;d34Ciy^<#OqPVtLvpXf*8R1vyh~H!%;T&5d`Iyr$E(+3uJ&3n;xi zI;>=`vL|QDt)|<>nYdh<%^x$zm=%sRyJ48u^%@0A?_1NlYLh;DV!*My3%6=s7NFB^ z6+Xh+SmldWiD|}j>j9-L+9z}vHSB0n+^W%UDD8c{jaT#;E7EmimL06!p&zhUm#1RL zH(4eZ(I%1&mPjlz$F?FxtGq8O(-A!H!`m_M5>PwddLwIIbUXA9f)OpOSoDUq00000 LNkvXXu0mjfY`^m5 literal 0 HcmV?d00001 diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000..c7bd21db --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xhdpi/ic_mic.png b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xhdpi/ic_mic.png new file mode 100755 index 0000000000000000000000000000000000000000..960326842ffb0e24e2b3b57becad88fab6f5634a GIT binary patch literal 872 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 M07*qoM6N<$g3*5nM*si- literal 0 HcmV?d00001 diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xxhdpi/ic_mic.png b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xxhdpi/ic_mic.png new file mode 100755 index 0000000000000000000000000000000000000000..7184522f6d04ce6166e5cbd352a2abc772bf19f2 GIT binary patch literal 1373 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 bo#X!i3lj+F%Ye8@00000NkvXXu0mjf%T~6P literal 0 HcmV?d00001 diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xxxhdpi/ic_mic.png b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable-xxxhdpi/ic_mic.png new file mode 100755 index 0000000000000000000000000000000000000000..227df2b00741fb6c6d74033a6ef4b622a1b8567f GIT binary patch literal 2026 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 y + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable/rounded_corner.xml b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable/rounded_corner.xml new file mode 100644 index 00000000..982884bd --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable/rounded_corner.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable/rounded_corner_edittext.xml b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable/rounded_corner_edittext.xml new file mode 100644 index 00000000..2619e851 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/drawable/rounded_corner_edittext.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/activity_chat.xml b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/activity_chat.xml new file mode 100644 index 00000000..8f469d41 --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/activity_chat.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/activity_main.xml b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..ac283a2f --- /dev/null +++ b/samples-refs_heads_mobile-auth-mobile-mobile_proxy_server-android_app/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,39 @@ + + + + + + + +