├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── ailib
├── build.gradle
├── gradle.properties
├── proguard-rules.txt
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── ai
│ │ │ └── api
│ │ │ ├── AIListener.java
│ │ │ ├── DefaultAIListener.java
│ │ │ ├── PartialResultsListener.java
│ │ │ ├── android
│ │ │ ├── AIConfiguration.java
│ │ │ ├── AIDataService.java
│ │ │ ├── AIService.java
│ │ │ ├── GsonFactory.java
│ │ │ └── SessionIdStorage.java
│ │ │ ├── services
│ │ │ ├── GoogleRecognitionServiceImpl.java
│ │ │ └── SpeaktoitRecognitionServiceImpl.java
│ │ │ ├── ui
│ │ │ ├── AIButton.java
│ │ │ ├── AIDialog.java
│ │ │ ├── MaskedColorView.java
│ │ │ ├── SoundLevelButton.java
│ │ │ └── SoundLevelCircleDrawable.java
│ │ │ └── util
│ │ │ ├── BluetoothController.java
│ │ │ ├── RecognizerChecker.java
│ │ │ ├── VersionConfig.java
│ │ │ └── VoiceActivityDetector.java
│ └── res
│ │ ├── color
│ │ └── mic_colors.xml
│ │ ├── drawable-xxhdpi
│ │ ├── cube.png
│ │ ├── microphone_control.png
│ │ ├── speaker.png
│ │ └── speaker_silent.png
│ │ ├── drawable
│ │ └── mic_control.xml
│ │ ├── layout
│ │ └── aidialog.xml
│ │ ├── raw
│ │ └── version_config.json
│ │ └── values
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ ├── java
│ └── ai
│ │ └── api
│ │ └── test
│ │ ├── ProtocolProdTest.java
│ │ ├── ProtocolTestBase.java
│ │ ├── VADTest.java
│ │ └── compatibility
│ │ ├── SimpleProtocolTestingService.java
│ │ ├── V20150415ProtocolTest.java
│ │ ├── default_protocol_model
│ │ ├── AIResponseDefault.java
│ │ ├── MetadataDefault.java
│ │ └── ResultDefault.java
│ │ └── v20150204_protocol_model
│ │ ├── AIResponseV20150204.java
│ │ └── ResultV20150204.java
│ └── resources
│ ├── debug0.wav
│ ├── log.raw
│ ├── noiseAndNotification.raw
│ ├── noiseOnly.raw
│ ├── silence.raw
│ ├── speech.raw
│ └── what_is_your_name.raw
├── apiAISampleApp
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── ai
│ │ └── api
│ │ └── sample
│ │ ├── AIApplication.java
│ │ ├── AIButtonSampleActivity.java
│ │ ├── AIDialogSampleActivity.java
│ │ ├── AISampleAppWidget.java
│ │ ├── AIServiceSampleActivity.java
│ │ ├── AISettingsActivity.java
│ │ ├── AITextSampleActivity.java
│ │ ├── AIWidgetActivity.java
│ │ ├── BaseActivity.java
│ │ ├── Config.java
│ │ ├── LanguageConfig.java
│ │ ├── MainActivity.java
│ │ ├── SettingsManager.java
│ │ └── TTS.java
│ └── res
│ ├── drawable-hdpi
│ ├── ic_launcher.png
│ └── recording_shape.xml
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ └── ic_launcher.png
│ ├── drawable
│ └── view_alpha_selector.xml
│ ├── layout
│ ├── activity_aibutton_sample.xml
│ ├── activity_aidialog_sample.xml
│ ├── activity_aiservice_sample.xml
│ ├── activity_aitext_sample.xml
│ ├── activity_main.xml
│ ├── activity_settings.xml
│ ├── activity_widget_sample.xml
│ └── ai_app_widget.xml
│ ├── menu
│ ├── main.xml
│ ├── menu_aibutton_sample.xml
│ └── menu_aiservice_sample.xml
│ ├── raw
│ ├── test_cancel.wav
│ ├── test_start.wav
│ └── test_stop.mp3
│ ├── values-w820dp
│ └── dimens.xml
│ ├── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ └── ai_app_widget_info.xml
├── build.gradle
├── docs
├── images
│ ├── AppScreenshot.png
│ ├── BuildTools19.1.png
│ ├── DebugButton.png
│ ├── Dependencies.png
│ ├── Dependencies2.png
│ ├── LayoutDesigner.png
│ ├── ListenButton.png
│ ├── MinSDK.png
│ ├── NewModule.png
│ ├── NewModuleDlg.png
│ ├── NewProject.png
│ ├── NewProjectDialog.png
│ ├── PlainText.png
│ ├── ResultViewText.png
│ ├── SDKManager.png
│ └── apiKeys.png
└── integration.md
├── gradle-mvn-push.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 | ailib/build
19 | sampleApp/build
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Android Studio files
28 | .idea
29 | *.iml
30 |
31 | .DS_Store
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | jdk: oraclejdk8
3 | sudo: false
4 |
5 | android:
6 | components:
7 | # Uncomment the lines below if you want to
8 | # use the latest revision of Android SDK Tools
9 | - platform-tools
10 | - tools
11 |
12 | # The BuildTools version used by your project
13 | - build-tools-25.0.1
14 |
15 | # The SDK version used to compile your project
16 | - android-24
17 |
18 | # Additional components
19 | - extra-google-google_play_services
20 | - extra-google-m2repository
21 | - extra-android-m2repository
22 | - addon-google_apis-google-23
23 |
24 | # Specify at least one system image,
25 | # if you need to run emulator(s) during your tests
26 | - sys-img-armeabi-v7a-android-19
27 | - sys-img-x86-android-17
28 | branches:
29 | only:
30 | - master
31 | - dev
32 |
33 | script:
34 | - echo "Travis branch is $TRAVIS_BRANCH"
35 | - echo "Travis branch is in pull request $TRAVIS_PULL+REQUEST"
36 | - ./gradlew test
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to become a contributor and submit your own code
2 |
3 | ## Contributor License Agreements
4 |
5 | We'd love to accept your sample apps and patches! Before we can take them, we
6 | have to jump a couple of legal hurdles.
7 |
8 | Please fill out either the individual or corporate Contributor License Agreement
9 | (CLA).
10 |
11 | * If you are an individual writing original source code and you're sure you
12 | own the intellectual property, then you'll need to sign an [individual CLA](https://developers.google.com/open-source/cla/individual).
13 | * If you work for a company that wants to allow you to contribute your work,
14 | then you'll need to sign a [corporate CLA](https://developers.google.com/open-source/cla/corporate).
15 |
16 | Follow either of the two links above to access the appropriate CLA and
17 | instructions for how to sign and return it. Once we receive it, we'll be able to
18 | accept your pull requests.
19 |
20 | ## Contributing A Patch
21 |
22 | 1. Submit an issue describing your proposed change to the repo in question.
23 | 1. The repo owner will respond to your issue promptly.
24 | 1. If your proposed change is accepted, and you haven't already done so, sign a
25 | Contributor License Agreement (see details above).
26 | 1. Fork the desired repo, develop and test your code changes.
27 | 1. Ensure that your code adheres to the existing style in the sample to which
28 | you are contributing. Refer to the
29 | [Google Cloud Platform Samples Style Guide](https://github.com/GoogleCloudPlatform/Template/wiki/style.html) for the
30 | recommended coding standards for this organization.
31 | 1. Ensure that your code has an appropriate set of unit tests which all pass.
32 | 1. Submit a pull request.
33 |
--------------------------------------------------------------------------------
/ailib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.neenbedankt.android-apt'
3 |
4 | android {
5 | compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
6 | buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
7 |
8 | defaultConfig {
9 | minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
10 | targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
11 | versionCode Integer.parseInt(project.VERSION_CODE)
12 | versionName project.VERSION_NAME
13 | }
14 | compileOptions {
15 | sourceCompatibility JavaVersion.VERSION_1_7
16 | targetCompatibility JavaVersion.VERSION_1_7
17 | }
18 | buildTypes {
19 | release {
20 | // proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
21 | buildConfigField "int", "TESTS_SDK", "22"
22 | }
23 | debug{
24 | buildConfigField "int", "TESTS_SDK", "22"
25 | }
26 | }
27 | productFlavors {
28 | }
29 |
30 | packagingOptions {
31 | }
32 | }
33 |
34 | dependencies {
35 | repositories {
36 | mavenLocal()
37 | mavenCentral()
38 | }
39 | compile fileTree(dir: 'libs', include: ['*.jar'])
40 | compile 'com.android.support:support-v4:23.2.1'
41 | compile 'ai.api:libai:1.6.11'
42 |
43 | testCompile 'org.slf4j:slf4j-android:1.7.25'
44 | testCompile "junit:junit:4.12"
45 | testCompile "org.assertj:assertj-core:1.7.0"
46 | testCompile "org.robolectric:robolectric:3.1.2"
47 | }
48 |
49 | apply from: '../gradle-mvn-push.gradle'
50 |
51 | // block for building library jars
52 | android.libraryVariants.all { variant ->
53 | def name = variant.buildType.name
54 | def task = project.tasks.create "jar${name.capitalize()}", Jar
55 | task.dependsOn variant.javaCompile
56 | task.from variant.javaCompile.destinationDir
57 | artifacts.add('archives', task);
58 | }
--------------------------------------------------------------------------------
/ailib/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=API.AI Android SDK
2 | POM_ARTIFACT_ID=sdk
3 | POM_PACKAGING=aar
--------------------------------------------------------------------------------
/ailib/proguard-rules.txt:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/xvir/sdk/android/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the ProGuard
5 | # include property in project.properties.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | -keep class ai.api.model.** { *; }
20 |
21 | ##---------------Begin: proguard configuration for Gson ----------
22 | # Gson uses generic type information stored in a class file when working with fields. Proguard
23 | # removes such information by default, so configure it to keep all of it.
24 | -keepattributes Signature
25 |
26 | # For using GSON @Expose annotation
27 | -keepattributes *Annotation*
28 |
29 | # Gson specific classes
30 | -keep class sun.misc.Unsafe { *; }
31 |
32 | ##---------------End: proguard configuration for Gson ----------
--------------------------------------------------------------------------------
/ailib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/AIListener.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api;
18 |
19 | import ai.api.android.AIService;
20 | import ai.api.model.AIError;
21 | import ai.api.model.AIResponse;
22 |
23 | /**
24 | * Listener interface for working with API.AI service. Create implementation of it and use with {@link AIService AIService}
25 | */
26 | public interface AIListener {
27 |
28 | /**
29 | * Event fires when entire process finished successfully, and returns result object
30 | *
31 | * @param result the result object, contains server answer
32 | */
33 | void onResult(AIResponse result);
34 |
35 | /**
36 | * Event fires if something going wrong while recognition or access to the AI server
37 | *
38 | * @param error the error description object
39 | */
40 | void onError(AIError error);
41 |
42 | /**
43 | * Event fires every time sound level changed. Use it to create visual feedback. There is no guarantee that this method will
44 | * be called.
45 | *
46 | * @param level the new RMS dB value
47 | */
48 | void onAudioLevel(float level);
49 |
50 | /**
51 | * Event fires when recognition engine start listening
52 | */
53 | void onListeningStarted();
54 |
55 | /**
56 | * Event fires when recognition engine cancel listening
57 | */
58 | void onListeningCanceled();
59 |
60 | /**
61 | * Event fires when recognition engine finish listening
62 | */
63 | void onListeningFinished();
64 | }
65 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/DefaultAIListener.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api;
18 |
19 | /**
20 | * Use this class instead of AIListener if you don't want to process all recognition events. Only onResult and onError required.
21 | */
22 | public abstract class DefaultAIListener implements AIListener {
23 |
24 | @Override
25 | public void onAudioLevel(final float level) {
26 |
27 | }
28 |
29 | @Override
30 | public void onListeningStarted() {
31 |
32 | }
33 |
34 | @Override
35 | public void onListeningFinished() {
36 |
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/PartialResultsListener.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api;
18 |
19 | import java.util.List;
20 |
21 | public interface PartialResultsListener {
22 | void onPartialResults(final List partialResults);
23 | }
24 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/android/AIConfiguration.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.android;
18 |
19 | import android.content.res.AssetFileDescriptor;
20 | import android.text.TextUtils;
21 |
22 | import java.net.Proxy;
23 |
24 | public class AIConfiguration extends ai.api.AIConfiguration {
25 | public enum RecognitionEngine {
26 |
27 | /**
28 | * Google Speech Recognition integrated into Android OS
29 | *
30 | * @deprecated Use System instead
31 | */
32 | @Deprecated
33 | Google,
34 |
35 | /**
36 | * Default system recognition
37 | */
38 | System,
39 |
40 | /**
41 | * Speaktoit recognition engine
42 | *
43 | * @deprecated Use System instead
44 | * will be support until 01.02.2017
45 | */
46 | @Deprecated
47 | Speaktoit
48 | }
49 |
50 | private final RecognitionEngine recognitionEngine;
51 |
52 | /**
53 | * Speaktoit recognition start sound resouce descriptor
54 | */
55 | private AssetFileDescriptor recognizerStartSound;
56 |
57 | /**
58 | * Speaktoit recognition stop sound resouce descriptor
59 | */
60 | private AssetFileDescriptor recognizerStopSound;
61 |
62 | /**
63 | * Speaktoit recognition cancel sound resource descriptor
64 | */
65 | private AssetFileDescriptor recognizerCancelSound;
66 |
67 | private boolean voiceActivityDetectionEnabled = true;
68 |
69 | private boolean normalizeInputSound = false;
70 |
71 | public AIConfiguration(final String clientAccessToken, final SupportedLanguages language, final RecognitionEngine recognitionEngine) {
72 | super(clientAccessToken, language);
73 |
74 | this.recognitionEngine = recognitionEngine;
75 |
76 | if (recognitionEngine == RecognitionEngine.Speaktoit
77 | && language == SupportedLanguages.Korean) {
78 | throw new UnsupportedOperationException("Only System recognition supported for Korean language");
79 | }
80 | }
81 |
82 | public RecognitionEngine getRecognitionEngine() {
83 | return recognitionEngine;
84 | }
85 |
86 | public boolean isVoiceActivityDetectionEnabled() {
87 | return voiceActivityDetectionEnabled;
88 | }
89 |
90 | /**
91 | * With setting this field to false you can disable voice activity detection for Speaktoit recognition.
92 | * This option does not affect System recognition.
93 | * @param voiceActivityDetectionEnabled
94 | */
95 | public void setVoiceActivityDetectionEnabled(final boolean voiceActivityDetectionEnabled) {
96 | this.voiceActivityDetectionEnabled = voiceActivityDetectionEnabled;
97 | }
98 |
99 | /**
100 | * With setting this field to true you can enable sound amplification if it's too quiet. This option improves recognition quality on some devices.
101 | * This option does not affect System recognition.
102 | * @param normalizeInputSound
103 | */
104 | public void setNormalizeInputSound(final boolean normalizeInputSound) {
105 | this.normalizeInputSound = normalizeInputSound;
106 | }
107 |
108 | public boolean isNormalizeInputSound() {
109 | return normalizeInputSound;
110 | }
111 |
112 | public AssetFileDescriptor getRecognizerStartSound() {
113 | return recognizerStartSound;
114 | }
115 |
116 | public void setRecognizerStartSound(final AssetFileDescriptor recognizerStartSound) {
117 | this.recognizerStartSound = recognizerStartSound;
118 | }
119 |
120 | public AssetFileDescriptor getRecognizerStopSound() {
121 | return recognizerStopSound;
122 | }
123 |
124 | public void setRecognizerStopSound(final AssetFileDescriptor recognizerStopSound) {
125 | this.recognizerStopSound = recognizerStopSound;
126 | }
127 |
128 | public AssetFileDescriptor getRecognizerCancelSound() {
129 | return recognizerCancelSound;
130 | }
131 |
132 | public void setRecognizerCancelSound(final AssetFileDescriptor recognizerCancelSound) {
133 | this.recognizerCancelSound = recognizerCancelSound;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/android/AIDataService.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.android;
18 |
19 | import android.content.Context;
20 | import android.support.annotation.NonNull;
21 |
22 | import com.google.gson.Gson;
23 |
24 | import java.util.TimeZone;
25 |
26 | import ai.api.AIServiceContext;
27 |
28 | /**
29 | * Do simple requests to the AI Service
30 | */
31 | public class AIDataService extends ai.api.AIDataService {
32 |
33 |
34 | public static final String TAG = AIDataService.class.getName();
35 |
36 | @NonNull
37 | private final Context context;
38 |
39 | @NonNull
40 | private final AIConfiguration config;
41 |
42 | @NonNull
43 | private final Gson gson = GsonFactory.getGson();
44 |
45 | public AIDataService(@NonNull final Context context, @NonNull final AIConfiguration config) {
46 | super(config, new AIAndroidServiceContext(context));
47 | this.context = context;
48 | this.config = config;
49 | }
50 |
51 | private static class AIAndroidServiceContext implements AIServiceContext {
52 |
53 | private final String sessionId;
54 |
55 | public AIAndroidServiceContext(final Context context) {
56 | sessionId = SessionIdStorage.getSessionId(context);
57 | }
58 |
59 | public String getSessionId() {
60 | return sessionId;
61 | }
62 |
63 | public TimeZone getTimeZone() { return TimeZone.getDefault(); }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/android/AIService.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.android;
18 |
19 | import android.Manifest;
20 | import android.content.Context;
21 |
22 | import java.util.Collection;
23 | import java.util.List;
24 |
25 | import ai.api.AIListener;
26 | import ai.api.AIServiceException;
27 | import ai.api.RequestExtras;
28 | import ai.api.model.AIContext;
29 | import ai.api.model.AIError;
30 | import ai.api.model.AIRequest;
31 | import ai.api.model.AIResponse;
32 | import ai.api.model.Entity;
33 | import ai.api.services.GoogleRecognitionServiceImpl;
34 | import ai.api.services.SpeaktoitRecognitionServiceImpl;
35 | import android.content.pm.PackageManager;
36 | import android.support.v4.content.ContextCompat;
37 |
38 | /**
39 | * Main SDK class for working with API.AI service.
40 | */
41 | public abstract class AIService {
42 |
43 | private static final String TAG = AIService.class.getName();
44 |
45 | protected final AIConfiguration config;
46 | protected final Context context;
47 |
48 | protected final AIDataService aiDataService;
49 |
50 | private AIListener listener;
51 |
52 | /**
53 | * Use this method to get ready to work instance
54 | * @param context
55 | * @param config
56 | * @return instance of AIService implementation
57 | */
58 | public static AIService getService(final Context context, final AIConfiguration config) {
59 | if (config.getRecognitionEngine() == AIConfiguration.RecognitionEngine.Google) {
60 | return new GoogleRecognitionServiceImpl(context, config);
61 | }
62 | if (config.getRecognitionEngine() == AIConfiguration.RecognitionEngine.System) {
63 | return new GoogleRecognitionServiceImpl(context, config);
64 | }
65 | else if (config.getRecognitionEngine() == AIConfiguration.RecognitionEngine.Speaktoit) {
66 | return new SpeaktoitRecognitionServiceImpl(context, config);
67 | } else {
68 | throw new UnsupportedOperationException("This engine still not supported");
69 | }
70 | }
71 |
72 | protected AIService(final AIConfiguration config, final Context context) {
73 | this.config = config;
74 | this.context = context;
75 |
76 | aiDataService = new AIDataService(context, config);
77 | }
78 |
79 | /**
80 | * Starts listening process
81 | */
82 | public abstract void startListening();
83 |
84 | /**
85 | * Starts listening process. Request to the AI service will be done with specified contexts.
86 | */
87 | public abstract void startListening(List contexts);
88 |
89 | /**
90 | * Starts listening process. Request to the AI service will be done with specified extra data.
91 | * @param requestExtras extras can hold additional contexts and entities
92 | */
93 | public abstract void startListening(RequestExtras requestExtras);
94 |
95 | /**
96 | * Stop listening and start request to the AI service with current recognition results
97 | */
98 | public abstract void stopListening();
99 |
100 | /**
101 | * Cancel listening process and don't request to AI service
102 | */
103 | public abstract void cancel();
104 |
105 | /**
106 | * Sets listener, which used to notify about process steps
107 | * @param listener {@link AIListener AIListener} implementation
108 | */
109 | public void setListener(final AIListener listener) {
110 | this.listener = listener;
111 | }
112 |
113 | protected void onResult(final AIResponse response) {
114 | if (listener != null) {
115 | listener.onResult(response);
116 | }
117 | }
118 |
119 | protected void onError(final AIError error) {
120 | if (listener != null) {
121 | listener.onError(error);
122 | }
123 | }
124 |
125 | protected void onAudioLevelChanged(final float audioLevel) {
126 | if (listener != null) {
127 | listener.onAudioLevel(audioLevel);
128 | }
129 | }
130 |
131 | protected void onListeningStarted() {
132 | if (listener != null) {
133 | listener.onListeningStarted();
134 | }
135 | }
136 |
137 | protected void onListeningCancelled() {
138 | if (listener != null) {
139 | listener.onListeningCanceled();
140 | }
141 | }
142 |
143 | protected void onListeningFinished() {
144 | if (listener != null) {
145 | listener.onListeningFinished();
146 | }
147 | }
148 |
149 | public void pause() {
150 |
151 | }
152 |
153 | public void resume(){
154 |
155 | }
156 |
157 | public AIResponse textRequest(final AIRequest request) throws AIServiceException {
158 | return aiDataService.request(request);
159 | }
160 |
161 | public AIResponse textRequest(final String textRequest, final RequestExtras requestExtras) throws AIServiceException {
162 | final AIRequest aiRequest = new AIRequest(textRequest);
163 | if (requestExtras != null) {
164 | requestExtras.copyTo(aiRequest);
165 | }
166 | return aiDataService.request(aiRequest);
167 | }
168 |
169 | /**
170 | * Forget all old contexts
171 | * @return true if operation succeed, false otherwise
172 | */
173 | public boolean resetContexts() {
174 | return aiDataService.resetContexts();
175 | }
176 |
177 | /**
178 | * Upload user entity for using while session
179 | * @param userEntity entity to upload
180 | * @return uploading result
181 | * @throws AIServiceException
182 | */
183 | public AIResponse uploadUserEntity(final Entity userEntity) throws AIServiceException {
184 | return aiDataService.uploadUserEntity(userEntity);
185 | }
186 |
187 | /**
188 | * Upload user entities for using while session
189 | * @param userEntities collection of user entities
190 | * @return uploading result
191 | * @throws AIServiceException if request to the API.AI service failed
192 | */
193 | public AIResponse uploadUserEntities(final Collection userEntities) throws AIServiceException {
194 | return aiDataService.uploadUserEntities(userEntities);
195 | }
196 |
197 | protected boolean checkPermissions() {
198 | boolean granted = true;
199 | try {
200 | granted = ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;
201 | } catch (final Throwable ignored) {
202 | }
203 | return granted;
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/android/GsonFactory.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.android;
18 |
19 | import com.google.gson.Gson;
20 | import com.google.gson.GsonBuilder;
21 |
22 | import java.text.SimpleDateFormat;
23 | import java.util.Locale;
24 |
25 | public class GsonFactory {
26 |
27 | public static Gson getGson(){
28 | return ai.api.GsonFactory.getDefaultFactory().getGson();
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/android/SessionIdStorage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.android;
18 |
19 | import android.content.Context;
20 | import android.content.SharedPreferences;
21 | import android.text.TextUtils;
22 |
23 | import java.util.UUID;
24 |
25 | public abstract class SessionIdStorage {
26 | private static final String PREF_NAME = "APIAI_preferences";
27 | private static final String SESSION_ID = "sessionId";
28 |
29 | public synchronized static String getSessionId(final Context context) {
30 | final SharedPreferences sharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
31 | final String sessionId = sharedPreferences.getString(SESSION_ID, "");
32 | if (!TextUtils.isEmpty(sessionId)) {
33 | return sessionId;
34 | } else {
35 | final SharedPreferences.Editor editor = sharedPreferences.edit();
36 | final String value = UUID.randomUUID().toString();
37 | editor.putString(SESSION_ID, value);
38 | editor.commit();
39 | return value;
40 | }
41 |
42 | }
43 |
44 | public static synchronized void resetSessionId(final Context context) {
45 | final SharedPreferences sharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
46 | final SharedPreferences.Editor editor = sharedPreferences.edit();
47 | editor.putString(SESSION_ID, "");
48 | editor.commit();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/ui/AIDialog.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.ui;
18 |
19 | import android.app.Dialog;
20 | import android.content.Context;
21 | import android.os.Handler;
22 | import android.os.Looper;
23 | import android.text.TextUtils;
24 | import android.view.Window;
25 | import android.widget.TextView;
26 |
27 | import java.util.List;
28 |
29 | import ai.api.android.AIConfiguration;
30 | import ai.api.android.AIService;
31 | import ai.api.AIServiceException;
32 | import ai.api.PartialResultsListener;
33 | import ai.api.R;
34 | import ai.api.model.AIError;
35 | import ai.api.model.AIRequest;
36 | import ai.api.model.AIResponse;
37 |
38 | public class AIDialog {
39 |
40 | private static final String TAG = AIDialog.class.getName();
41 |
42 | private final Context context;
43 | private final AIConfiguration config;
44 |
45 | private AIDialogListener resultsListener;
46 | private final Dialog dialog;
47 | private final AIButton aiButton;
48 | private final TextView partialResultsTextView;
49 |
50 | private final Handler handler;
51 |
52 | public interface AIDialogListener {
53 | void onResult(final AIResponse result);
54 | void onError(final AIError error);
55 | void onCancelled();
56 | }
57 |
58 | public AIDialog(final Context context, final AIConfiguration config) {
59 | this(context, config, R.layout.aidialog);
60 | }
61 |
62 | public AIDialog(final Context context, final AIConfiguration config, final int customLayout) {
63 | this.context = context;
64 | this.config = config;
65 | dialog = new Dialog(context);
66 | handler = new Handler(Looper.getMainLooper());
67 |
68 | dialog.setCanceledOnTouchOutside(true);
69 | dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
70 | dialog.setContentView(customLayout);
71 |
72 | partialResultsTextView = (TextView) dialog.findViewById(R.id.partialResultsTextView);
73 |
74 | aiButton = (AIButton) dialog.findViewById(R.id.micButton);
75 | aiButton.initialize(config);
76 | setAIButtonCallback(aiButton);
77 | }
78 |
79 | public void setResultsListener(final AIDialogListener resultsListener) {
80 | this.resultsListener = resultsListener;
81 | }
82 |
83 | public Dialog getDialog() {
84 | return dialog;
85 | }
86 |
87 | public void showAndListen() {
88 | handler.post(new Runnable() {
89 | @Override
90 | public void run() {
91 | resetControls();
92 | dialog.show();
93 | startListening();
94 | }
95 | });
96 | }
97 |
98 | public AIResponse textRequest(final AIRequest request) throws AIServiceException {
99 | return aiButton.textRequest(request);
100 | }
101 |
102 | public AIResponse textRequest(final String request) throws AIServiceException {
103 | return textRequest(new AIRequest(request));
104 | }
105 |
106 | private void resetControls() {
107 | if (partialResultsTextView != null) {
108 | partialResultsTextView.setText("");
109 | }
110 | }
111 |
112 | private void setAIButtonCallback(final AIButton aiButton) {
113 | aiButton.setResultsListener(new AIButton.AIButtonListener() {
114 | @Override
115 | public void onResult(final AIResponse result) {
116 |
117 | AIDialog.this.close();
118 |
119 | if (resultsListener != null) {
120 | resultsListener.onResult(result);
121 | }
122 | }
123 |
124 | @Override
125 | public void onError(final AIError error) {
126 | if (resultsListener != null) {
127 | resultsListener.onError(error);
128 | }
129 | }
130 |
131 | @Override
132 | public void onCancelled() {
133 |
134 | AIDialog.this.close();
135 |
136 | if (resultsListener != null) {
137 | resultsListener.onCancelled();
138 | }
139 | }
140 | });
141 |
142 | aiButton.setPartialResultsListener(new PartialResultsListener() {
143 | @Override
144 | public void onPartialResults(final List partialResults) {
145 | final String result = partialResults.get(0);
146 | if (!TextUtils.isEmpty(result)) {
147 | handler.post(new Runnable() {
148 | @Override
149 | public void run() {
150 | if (partialResultsTextView != null) {
151 | partialResultsTextView.setText(result);
152 | }
153 | }
154 | });
155 | }
156 | }
157 | });
158 |
159 | }
160 |
161 | private void startListening() {
162 | if (aiButton != null) {
163 | aiButton.startListening();
164 | }
165 | }
166 |
167 | public void close() {
168 | handler.post(new Runnable() {
169 | @Override
170 | public void run() {
171 | dialog.dismiss();
172 | }
173 | });
174 | }
175 |
176 | /**
177 | * Get AIService object for making different data requests
178 | * @return
179 | */
180 | public AIService getAIService() {
181 | return aiButton.getAIService();
182 | }
183 |
184 | /**
185 | * Disconnect aiDialog from the recognition service.
186 | * Use pause/resume methods when you have permanent reference to the AIDialog object in your Activity.
187 | * pause() call should be added to the onPause() method of the Activity.
188 | * resume() call should be added to the onResume() method of the Activity.
189 | */
190 | public void pause() {
191 | if (aiButton != null) {
192 | aiButton.pause();
193 | }
194 | }
195 |
196 | /**
197 | * Reconnect aiDialog to the recognition service.
198 | * Use pause/resume methods when you have permanent reference to the AIDialog object in your Activity.
199 | * pause() call should be added to the onPause() method of the Activity.
200 | * resume() call should be added to the onResume() method of the Activity.
201 | */
202 | public void resume() {
203 | if (aiButton != null) {
204 | aiButton.resume();
205 | }
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/ui/MaskedColorView.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.ui;
18 |
19 | import android.annotation.TargetApi;
20 | import android.content.Context;
21 | import android.content.res.ColorStateList;
22 | import android.content.res.TypedArray;
23 | import android.graphics.Color;
24 | import android.graphics.PorterDuff;
25 | import android.os.Build;
26 | import android.util.AttributeSet;
27 | import android.widget.ImageView;
28 |
29 | import ai.api.R;
30 |
31 | /**
32 | * ImageView
33 | * src used as a mask, and MaskedColorView_mainColor as a color or state color list
34 | */
35 | public class MaskedColorView extends ImageView {
36 | private ColorStateList colorStateList = null;
37 |
38 | public MaskedColorView(final Context context) {
39 | super(context, null);
40 | }
41 |
42 | public MaskedColorView(final Context context, final AttributeSet attrs) {
43 | super(context, attrs, android.R.attr.imageButtonStyle);
44 | configure(attrs);
45 | }
46 |
47 | public MaskedColorView(final Context context, final AttributeSet attrs, final int defStyle) {
48 | super(context, attrs, defStyle);
49 | configure(attrs);
50 | }
51 |
52 | @TargetApi(11)
53 | @Override
54 | protected void drawableStateChanged() {
55 | super.drawableStateChanged();
56 | setColorFilter(getCurrentColor(getDrawableState()), PorterDuff.Mode.SRC_ATOP);
57 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
58 | jumpDrawablesToCurrentState();
59 | }
60 | }
61 |
62 | public void setColorStateList(final ColorStateList colorStateList) {
63 | this.colorStateList = colorStateList;
64 | }
65 |
66 | private int getCurrentColor(final int[] stateSet) {
67 | return colorStateList == null
68 | ? Color.MAGENTA
69 | : colorStateList.getColorForState(stateSet, colorStateList.getDefaultColor());
70 | }
71 |
72 | private void configure(final AttributeSet attrs) {
73 | if (attrs != null) {
74 | final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaskedColorView);
75 | try {
76 | final ColorStateList csl = a.getColorStateList(R.styleable.MaskedColorView_mainColor);
77 | if (csl != null) {
78 | colorStateList = csl;
79 | }
80 | } finally {
81 | a.recycle();
82 | }
83 | }
84 | }
85 |
86 | protected String getDebugState() {
87 | return "====\ncsl is " + (colorStateList != null ? "NOT" : "") + " null";
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/ui/SoundLevelButton.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.ui;
18 |
19 | import android.annotation.TargetApi;
20 | import android.content.Context;
21 | import android.content.res.TypedArray;
22 | import android.os.Build;
23 | import android.support.annotation.NonNull;
24 | import android.support.annotation.Nullable;
25 | import android.util.AttributeSet;
26 | import android.view.View;
27 |
28 | import ai.api.R;
29 |
30 | public class SoundLevelButton extends MaskedColorView {
31 |
32 | private static final String TAG = SoundLevelButton.class.getName();
33 |
34 | protected static final int[] STATE_LISTENING = new int[] { R.attr.state_listening };
35 |
36 | private final SoundLevelCircleDrawable backgroundDrawable;
37 | protected boolean listening = false;
38 |
39 | @SuppressWarnings("UnusedDeclaration")
40 | public SoundLevelButton(@NonNull final Context context) {
41 | super(context);
42 | backgroundDrawable = new SoundLevelCircleDrawable(getParams(context, null));
43 | setCircleBackground(backgroundDrawable);
44 | init();
45 | }
46 |
47 | @SuppressWarnings("UnusedDeclaration")
48 | public SoundLevelButton(@NonNull final Context context, @Nullable final AttributeSet attrs) {
49 | super(context, attrs);
50 | backgroundDrawable = new SoundLevelCircleDrawable(getParams(context, attrs));
51 | setCircleBackground(backgroundDrawable);
52 | init();
53 | }
54 |
55 | @SuppressWarnings("UnusedDeclaration")
56 | public SoundLevelButton(@NonNull final Context context, @Nullable final AttributeSet attrs, final int defStyle) {
57 | super(context, attrs, defStyle);
58 | backgroundDrawable = new SoundLevelCircleDrawable(getParams(context, attrs));
59 | setCircleBackground(backgroundDrawable);
60 | init();
61 | }
62 |
63 | private void init() {
64 | setOnClickListener(new OnClickListener() {
65 | @Override
66 | public void onClick(final View v) {
67 | SoundLevelButton.this.onClick(v);
68 | }
69 | });
70 | }
71 |
72 | protected void onClick(final View v) {
73 |
74 | }
75 |
76 | @Nullable
77 | private SoundLevelCircleDrawable.Params getParams(@NonNull final Context context, @Nullable final AttributeSet attrs) {
78 | if (attrs != null) {
79 | final TypedArray viewAttrs = context.obtainStyledAttributes(attrs, R.styleable.SoundLevelButton);
80 |
81 | try {
82 | this.listening = viewAttrs.getBoolean(R.styleable.SoundLevelButton_state_listening, false);
83 |
84 | final float maxRadius = viewAttrs.getDimension(R.styleable.SoundLevelButton_maxRadius, -1);
85 | final float minRadius = viewAttrs.getDimension(R.styleable.SoundLevelButton_minRadius, -1);
86 | final float circleCenterX = viewAttrs.getDimension(R.styleable.SoundLevelButton_circleCenterX, -1);
87 | final float circleCenterY = viewAttrs.getDimension(R.styleable.SoundLevelButton_circleCenterY, -1);
88 | final int centerColor = viewAttrs.getColor(R.styleable.SoundLevelButton_centerColor, SoundLevelCircleDrawable.CENTER_COLOR_DEF);
89 | final int haloColor = viewAttrs.getColor(R.styleable.SoundLevelButton_haloColor, SoundLevelCircleDrawable.HALO_COLOR_DEF);
90 | return new SoundLevelCircleDrawable.Params(maxRadius, minRadius, circleCenterX, circleCenterY, centerColor, haloColor);
91 | } finally {
92 | viewAttrs.recycle();
93 | }
94 | }
95 | return null;
96 | }
97 |
98 | @Override
99 | public int[] onCreateDrawableState(final int extraSpace) {
100 | final int[] state = super.onCreateDrawableState(extraSpace + 1);
101 | if (listening) mergeDrawableStates(state, STATE_LISTENING);
102 | return state;
103 | }
104 |
105 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
106 | private void setCircleBackground(final SoundLevelCircleDrawable soundLevelCircleDrawable) {
107 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
108 | //noinspection deprecation
109 | setBackgroundDrawable(soundLevelCircleDrawable);
110 | else
111 | setBackground(soundLevelCircleDrawable);
112 | }
113 |
114 | public void setDrawSoundLevel(final boolean drawSoundLevel) {
115 | listening = drawSoundLevel;
116 | backgroundDrawable.setDrawSoundLevel(drawSoundLevel);
117 | refreshDrawableState();
118 | postInvalidate();
119 | }
120 |
121 | protected void setDrawCenter(final boolean drawCenter) {
122 | this.backgroundDrawable.setDrawCenter(drawCenter);
123 | }
124 |
125 | public void setSoundLevel(final float soundLevel) {
126 | backgroundDrawable.setSoundLevel(soundLevel);
127 | postInvalidate();
128 | }
129 |
130 | @Override
131 | protected String getDebugState() {
132 | return super.getDebugState() + "\ndrawSL: " + listening;
133 | }
134 |
135 | protected float getMinRadius() {
136 | return backgroundDrawable.getMinRadius();
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/ui/SoundLevelCircleDrawable.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.ui;
18 |
19 | import android.graphics.Canvas;
20 | import android.graphics.Color;
21 | import android.graphics.ColorFilter;
22 | import android.graphics.Paint;
23 | import android.graphics.PixelFormat;
24 | import android.graphics.Rect;
25 | import android.graphics.drawable.Drawable;
26 | import android.support.annotation.Nullable;
27 |
28 | public class SoundLevelCircleDrawable extends Drawable {
29 | public static final int HALO_COLOR_DEF = Color.argb(16, 0x0, 0x0, 0x0);
30 | public static final int CENTER_COLOR_DEF = 0xffF26C29;
31 | private static final float MIN_VALUE = 1f / 2;
32 | private static final float MAX_VALUE = 10;
33 | private static final float INITIAL_VALUE = 2.5f;
34 |
35 | private final float maxRadius;
36 | private final float minRadius;
37 | private final float circleCenterX;
38 | private final float circleCenterY;
39 | private float minMicLevel = MIN_VALUE;
40 | private float maxMicLevel = MAX_VALUE;
41 |
42 | private boolean drawSoundLevel = false;
43 |
44 | private final Paint paintIndicatorHalo;
45 | private final Paint paintIndicatorCenter;
46 | private float smoothedLevel = INITIAL_VALUE;
47 | private final Rect bounds = new Rect();
48 | private boolean drawCenter = false;
49 |
50 | private static Paint newColorPaint(final int color) {
51 | final Paint paint = new Paint();
52 | paint.setStyle(Paint.Style.FILL);
53 | paint.setAntiAlias(true);
54 | paint.setColor(color);
55 | return paint;
56 | }
57 |
58 | public SoundLevelCircleDrawable() {
59 | this(null);
60 | }
61 |
62 | public SoundLevelCircleDrawable(@Nullable final Params params) {
63 | final int centerColor;
64 | final int haloColor;
65 | if (params != null) {
66 | this.maxRadius = params.maxRadius;
67 | this.minRadius = params.minRadius;
68 | this.circleCenterX = params.circleCenterX;
69 | this.circleCenterY = params.circleCenterY;
70 | centerColor = params.centerColor;
71 | haloColor = params.haloColor;
72 | } else {
73 | this.maxRadius = -1;
74 | this.minRadius = -1;
75 | this.circleCenterX = -1;
76 | this.circleCenterY = -1;
77 | centerColor = CENTER_COLOR_DEF;
78 | haloColor = HALO_COLOR_DEF;
79 | }
80 | paintIndicatorHalo = newColorPaint(haloColor);
81 | paintIndicatorCenter = newColorPaint(centerColor);
82 | }
83 |
84 | @SuppressWarnings("MagicNumber")
85 | @Override
86 | public void draw(final Canvas canvas) {
87 | if (drawSoundLevel || drawCenter) {
88 | canvas.save();
89 | try {
90 | if (this.maxRadius < 0 || this.circleCenterX < 0 || this.circleCenterY < 0)
91 | canvas.getClipBounds(bounds);
92 |
93 | canvas.drawColor(Color.TRANSPARENT);
94 | final float levelInFraction = (smoothedLevel - minMicLevel) / (maxMicLevel - minMicLevel);
95 | final float maxRadius = this.maxRadius < 0 ? bounds.width() / 2f : this.maxRadius;
96 | final float minRadius = this.minRadius < 0 ? maxRadius * (65 / 112.5f) : this.minRadius;
97 | final float soundMinRadius = minRadius * 0.8f; //to hide halo on silence
98 | final float rangeRadius = maxRadius - soundMinRadius;
99 | final float soundRadius = soundMinRadius + rangeRadius * levelInFraction;
100 | final float x = this.circleCenterX < 0 ? bounds.width() / 2f : this.circleCenterX;
101 | final float y = this.circleCenterY < 0 ? bounds.height() / 2f : this.circleCenterY;
102 | if (drawSoundLevel)
103 | canvas.drawCircle(x, y, soundRadius, paintIndicatorHalo);
104 | if (drawCenter || drawSoundLevel)
105 | canvas.drawCircle(x, y, minRadius, paintIndicatorCenter);
106 | } finally {
107 | canvas.restore();
108 | }
109 | }
110 | }
111 |
112 | @Override
113 | public void setAlpha(final int ignored) {
114 | //ignore
115 | }
116 |
117 | @Override
118 | public void setColorFilter(final ColorFilter ignored) {
119 | //ignore
120 | }
121 |
122 | @Override
123 | public int getOpacity() {
124 | return PixelFormat.TRANSLUCENT;
125 | }
126 |
127 | /**
128 | * @param drawSoundLevel true to draw
129 | * @return true if drawSoundLevel changed
130 | */
131 | public boolean setDrawSoundLevel(final boolean drawSoundLevel) {
132 | if (this.drawSoundLevel != drawSoundLevel) {
133 | this.drawSoundLevel = drawSoundLevel;
134 | if (drawSoundLevel) {
135 | minMicLevel = MIN_VALUE;
136 | maxMicLevel = MAX_VALUE;
137 | smoothedLevel = INITIAL_VALUE;
138 | }
139 | return true;
140 | } else
141 | return false;
142 | }
143 |
144 | public void setDrawCenter(final boolean drawCenter) {
145 | this.drawCenter = drawCenter;
146 | }
147 |
148 | public void setSoundLevel(final float soundLevel) {
149 | final float positiveSoundLevel = Math.abs(soundLevel);
150 |
151 | if (positiveSoundLevel < minMicLevel) {
152 | minMicLevel = (minMicLevel + positiveSoundLevel) / 2; // average
153 | }
154 |
155 | if (positiveSoundLevel > maxMicLevel) {
156 | maxMicLevel = (maxMicLevel + positiveSoundLevel) / 2; // average
157 | }
158 |
159 | final float alpha = 0.2f;
160 | smoothedLevel = (smoothedLevel * (1 - alpha) + (positiveSoundLevel * alpha));
161 |
162 | if (smoothedLevel > maxMicLevel) {
163 | smoothedLevel = maxMicLevel;
164 | } else if (smoothedLevel < minMicLevel) {
165 | smoothedLevel = minMicLevel;
166 | }
167 | }
168 |
169 | public float getMinRadius() {
170 | return minRadius;
171 | }
172 |
173 | public static class Params {
174 | public final float maxRadius;
175 | public final float minRadius;
176 | public final float circleCenterX;
177 | public final float circleCenterY;
178 | private final int centerColor;
179 | private final int haloColor;
180 |
181 | public Params(final float maxRadius, final float minRadius, final float circleCenterX, final float circleCenterY, final int centerColor, final int haloColor) {
182 | this.maxRadius = maxRadius;
183 | this.minRadius = minRadius;
184 | this.circleCenterX = circleCenterX;
185 | this.circleCenterY = circleCenterY;
186 | this.centerColor = centerColor;
187 | this.haloColor = haloColor;
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/util/RecognizerChecker.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.util;
18 |
19 | import android.content.ComponentName;
20 | import android.content.Context;
21 | import android.content.Intent;
22 | import android.content.pm.PackageInfo;
23 | import android.content.pm.PackageManager;
24 | import android.content.pm.ResolveInfo;
25 | import android.content.pm.ServiceInfo;
26 | import android.os.Build;
27 | import android.speech.RecognitionService;
28 |
29 | import java.util.LinkedList;
30 | import java.util.List;
31 |
32 | public class RecognizerChecker {
33 |
34 | public static final String GOOGLE_RECOGNIZER_PACKAGE_NAME = "com.google.android.googlequicksearchbox";
35 | public static final String GOOGLE_VOICE_SEARCH_PACKAGE_NAME = "com.google.android.voicesearch";
36 |
37 | public static ComponentName findGoogleRecognizer(final Context context) {
38 | return findRecognizerByPackage(context, getPackageName());
39 | }
40 |
41 | private static ComponentName findRecognizerByPackage(final Context context, final String prefPackage) {
42 | final PackageManager pm = context.getPackageManager();
43 | final List available = pm != null ? pm.queryIntentServices(new Intent(RecognitionService.SERVICE_INTERFACE), 0) : new LinkedList();
44 | final int numAvailable = available.size();
45 |
46 | if (numAvailable == 0) {
47 | // no available voice recognition services found
48 | return null;
49 | } else {
50 | if (prefPackage != null) {
51 | for (final ResolveInfo anAvailable : available) {
52 | final ServiceInfo serviceInfo = anAvailable.serviceInfo;
53 |
54 | if (serviceInfo != null && prefPackage.equals(serviceInfo.packageName)) {
55 | return new ComponentName(serviceInfo.packageName, serviceInfo.name);
56 | }
57 | }
58 | }
59 | // Do not pick up first available, but use default one
60 | return null;
61 | }
62 | }
63 |
64 | public static String getGoogleRecognizerVersion(final Context context) {
65 | try {
66 | final PackageManager pm = context.getPackageManager();
67 |
68 | final ComponentName recognizerComponentName = findGoogleRecognizer(context);
69 | if (recognizerComponentName != null) {
70 | final PackageInfo packageInfo = pm.getPackageInfo(recognizerComponentName.getPackageName(), 0);
71 | final String versionName = packageInfo.versionName;
72 | return versionName;
73 | }
74 |
75 | return "";
76 | } catch (final PackageManager.NameNotFoundException ignored) {
77 | return "";
78 | }
79 | }
80 |
81 | public static boolean isGoogleRecognizerAvailable(final Context context) {
82 | return findGoogleRecognizer(context) != null;
83 | //return false;
84 | }
85 |
86 | private static String getPackageName() {
87 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
88 | return GOOGLE_RECOGNIZER_PACKAGE_NAME;
89 | } else {
90 | return GOOGLE_VOICE_SEARCH_PACKAGE_NAME;
91 | }
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/util/VersionConfig.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.util;
18 |
19 | import android.content.Context;
20 | import android.text.TextUtils;
21 |
22 | import java.util.HashMap;
23 | import java.util.Map;
24 | import java.util.regex.Pattern;
25 |
26 | import ai.api.android.GsonFactory;
27 |
28 | public class VersionConfig {
29 |
30 | private static final String TAG = VersionConfig.class.getName();
31 | private static final Pattern DOT_PATTERN = Pattern.compile(".", Pattern.LITERAL);
32 |
33 | private static final Map configuration = new HashMap<>();
34 |
35 | static {
36 | configuration.put("5.9.26", new VersionConfig(true, true));
37 | configuration.put("4.7.13", new VersionConfig(false, false));
38 | }
39 |
40 | private boolean destroyRecognizer = true;
41 | private boolean autoStopRecognizer = false;
42 |
43 | private VersionConfig() {
44 | }
45 |
46 | private VersionConfig(final boolean destroyRecognizer, final boolean autoStopRecognizer) {
47 | this.destroyRecognizer = destroyRecognizer;
48 | this.autoStopRecognizer = autoStopRecognizer;
49 | }
50 |
51 | public static VersionConfig init(final Context context) {
52 | return getConfigByVersion(context);
53 | }
54 |
55 | private static VersionConfig getConfigByVersion(final Context context) {
56 | final long number = numberFromBuildVersion(RecognizerChecker.getGoogleRecognizerVersion(context));
57 |
58 | final VersionConfig config = new VersionConfig();
59 | long prevVersionNumber = 0;
60 |
61 | for (final Map.Entry configEntry : configuration.entrySet()) {
62 | final String versionName = configEntry.getKey();
63 |
64 | if (!TextUtils.isEmpty(versionName)) {
65 | final long versionNumber = numberFromBuildVersion(versionName);
66 | if (number >= versionNumber && prevVersionNumber < versionNumber) {
67 | config.destroyRecognizer = configEntry.getValue().destroyRecognizer;
68 | config.autoStopRecognizer = configEntry.getValue().autoStopRecognizer;
69 | prevVersionNumber = versionNumber;
70 | }
71 | }
72 | }
73 |
74 | return config;
75 | }
76 |
77 | public boolean isDestroyRecognizer() {
78 | return destroyRecognizer;
79 | }
80 |
81 | public boolean isAutoStopRecognizer() {
82 | return autoStopRecognizer;
83 | }
84 |
85 | private static long numberFromBuildVersion(final String buildVersion) {
86 | if (TextUtils.isEmpty(buildVersion))
87 | return 0;
88 |
89 | final String[] parts = DOT_PATTERN.split(buildVersion);
90 |
91 | final StringBuilder builder = new StringBuilder();
92 | for (int i = 0; i < Math.min(3, parts.length); i++) {
93 | builder.append(parts[i]);
94 | }
95 | try {
96 | return Long.parseLong(builder.toString());
97 | } catch (final NumberFormatException ignored) {
98 | return 0;
99 | }
100 | }
101 |
102 | @Override
103 | public String toString() {
104 | return GsonFactory.getGson().toJson(this);
105 | }
106 | }
--------------------------------------------------------------------------------
/ailib/src/main/java/ai/api/util/VoiceActivityDetector.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.util;
18 |
19 | import android.util.Log;
20 |
21 | import java.nio.ByteBuffer;
22 | import java.nio.ByteOrder;
23 | import java.nio.ShortBuffer;
24 |
25 | public class VoiceActivityDetector {
26 |
27 | public static final String TAG = VoiceActivityDetector.class.getName();
28 |
29 | public static final int FRAME_SIZE_IN_BYTES = 320;
30 | private static final int SEQUENCE_LENGTH_MILLIS = 30;
31 | private static final int MIN_SPEECH_SEQUENCE_COUNT = 3;
32 | private static final long MIN_SILENCE_MILLIS = 800;
33 | private static final long MAX_SILENCE_MILLIS = 3500;
34 | private static final long SILENCE_DIFF_MILLIS = MAX_SILENCE_MILLIS - MIN_SILENCE_MILLIS;
35 | private static final int NOISE_FRAMES = 15;
36 | public static final int NOISE_BYTES = NOISE_FRAMES * FRAME_SIZE_IN_BYTES;
37 | private static final double ENERGY_FACTOR = 3.1;
38 | private static final int MIN_CZ = 5;
39 | private static final int MAX_CZ = 15;
40 |
41 | private final int sampleRate;
42 |
43 | private SpeechEventsListener eventsListener;
44 |
45 | private double noiseEnergy = 0.0;
46 |
47 | private long lastActiveTime = -1;
48 |
49 | /**
50 | * last time active frame hit sequence.
51 | */
52 | private long lastSequenceTime = 0;
53 |
54 | /**
55 | * number of active frame in sequence.
56 | */
57 | private int sequenceCounter = 0;
58 |
59 | /**
60 | * current processed time in millis
61 | */
62 | private long time = 0;
63 |
64 | private int frameNumber;
65 |
66 | private long silenceMillis = MAX_SILENCE_MILLIS;
67 |
68 | private boolean speechActive = false;
69 | private boolean enabled = true;
70 | private boolean process = true;
71 |
72 | private double sum = 0;
73 | private int size = 0;
74 |
75 | public VoiceActivityDetector(final int sampleRate) {
76 | this.sampleRate = sampleRate;
77 | }
78 |
79 | public void processBuffer(final byte[] buffer, final int bytesRead) {
80 | if (!process) {
81 | return;
82 | }
83 |
84 | final ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, bytesRead).order(ByteOrder.LITTLE_ENDIAN);
85 | final ShortBuffer shorts = byteBuffer.asShortBuffer();
86 |
87 | final boolean active = isFrameActive(shorts);
88 |
89 | final int frameSize = bytesRead / 2; // 16 bit encoding
90 | time = frameNumber * frameSize * 1000 / sampleRate;
91 |
92 | if (active) {
93 | if (lastActiveTime >= 0 && (time - lastActiveTime) < SEQUENCE_LENGTH_MILLIS) {
94 | if (++sequenceCounter >= MIN_SPEECH_SEQUENCE_COUNT) {
95 | if (!speechActive) {
96 | onSpeechBegin();
97 | }
98 |
99 | lastSequenceTime = time;
100 | silenceMillis = Math.max(MIN_SILENCE_MILLIS, silenceMillis - SILENCE_DIFF_MILLIS / 4);
101 | }
102 | } else {
103 | sequenceCounter = 1;
104 | }
105 | lastActiveTime = time;
106 | } else {
107 | if (time - lastSequenceTime > silenceMillis) {
108 | if (speechActive) {
109 | onSpeechEnd();
110 | } else {
111 | onSpeechCancel();
112 | }
113 | }
114 | }
115 | }
116 |
117 | private boolean isFrameActive(final ShortBuffer frame) {
118 |
119 | int lastSign = 0;
120 | int czCount = 0;
121 | double energy = 0.0;
122 |
123 | final int frameSize = frame.limit();
124 | size += frameSize;
125 |
126 | for (int i = 0; i < frameSize; i++) {
127 | final short raw = frame.get(i);
128 | final double amplitude = (double) raw / (double) Short.MAX_VALUE;
129 | energy += (float) amplitude * (float) amplitude / (double) frameSize;
130 |
131 | sum += raw * raw;
132 |
133 | final int sign = (float) amplitude > 0 ? 1 : -1;
134 | if (lastSign != 0 && sign != lastSign) {
135 | czCount++;
136 | }
137 | lastSign = sign;
138 | }
139 |
140 | boolean result = false;
141 | if (++frameNumber < NOISE_FRAMES) {
142 | noiseEnergy += (energy / (double) NOISE_FRAMES);
143 | } else {
144 | if (czCount >= MIN_CZ && czCount <= MAX_CZ) {
145 | if (energy > noiseEnergy * ENERGY_FACTOR) {
146 | result = true;
147 | }
148 | }
149 | }
150 |
151 | return result;
152 | }
153 |
154 | public double calculateRms() {
155 | final double rms = Math.sqrt(sum / size) / 100;
156 | sum = 0;
157 | size = 0;
158 | return rms;
159 | }
160 |
161 | public void reset() {
162 | time = 0;
163 | frameNumber = 0;
164 |
165 | noiseEnergy = 0.0;
166 | lastActiveTime = -1;
167 | lastSequenceTime = 0;
168 | sequenceCounter = 0;
169 | silenceMillis = MAX_SILENCE_MILLIS;
170 |
171 | speechActive = false;
172 | process = true;
173 | }
174 |
175 | public void setSpeechListener(final SpeechEventsListener eventsListener) {
176 | this.eventsListener = eventsListener;
177 | }
178 |
179 | private void onSpeechEnd() {
180 | Log.v(TAG, "onSpeechEnd");
181 |
182 | speechActive = false;
183 | process = false;
184 |
185 | if (enabled) {
186 | if (eventsListener != null) {
187 | eventsListener.onSpeechEnd();
188 | }
189 | }
190 | }
191 |
192 | private void onSpeechCancel() {
193 | Log.v(TAG, "onSpeechCancel");
194 |
195 | speechActive = false;
196 | process = false;
197 |
198 | if (eventsListener != null) {
199 | eventsListener.onSpeechCancel();
200 | }
201 | }
202 |
203 | private void onSpeechBegin() {
204 | Log.v(TAG, "onSpeechBegin");
205 |
206 | speechActive = true;
207 |
208 | if (eventsListener != null) {
209 | eventsListener.onSpeechBegin();
210 | }
211 | }
212 |
213 | /**
214 | * If enabled, voice activity detector fires onSpeechEnd events.
215 | * This option does not affect onSpeechBegin and onChangeLevel events
216 | *
217 | * @param enabled new option values
218 | */
219 | public void setEnabled(final boolean enabled) {
220 | this.enabled = enabled;
221 | }
222 |
223 | /**
224 | * Used to notify about speech begin/end events
225 | */
226 | public interface SpeechEventsListener {
227 | void onSpeechBegin();
228 |
229 | void onSpeechCancel();
230 |
231 | void onSpeechEnd();
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/ailib/src/main/res/color/mic_colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ailib/src/main/res/drawable-xxhdpi/cube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/main/res/drawable-xxhdpi/cube.png
--------------------------------------------------------------------------------
/ailib/src/main/res/drawable-xxhdpi/microphone_control.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/main/res/drawable-xxhdpi/microphone_control.png
--------------------------------------------------------------------------------
/ailib/src/main/res/drawable-xxhdpi/speaker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/main/res/drawable-xxhdpi/speaker.png
--------------------------------------------------------------------------------
/ailib/src/main/res/drawable-xxhdpi/speaker_silent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/main/res/drawable-xxhdpi/speaker_silent.png
--------------------------------------------------------------------------------
/ailib/src/main/res/drawable/mic_control.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ailib/src/main/res/layout/aidialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
22 |
23 |
24 |
25 |
38 |
39 |
51 |
52 |
--------------------------------------------------------------------------------
/ailib/src/main/res/raw/version_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "googleApp": [
3 | {
4 | "version": "5.9.26",
5 | "destroyRecognizer": true
6 | },
7 | {
8 | "version": "4.7.13",
9 | "destroyRecognizer": false
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/ailib/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/ailib/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #f26c29
4 | #20000000
5 | #FF2a91be
6 |
7 | #ffffffff
8 |
9 |
--------------------------------------------------------------------------------
/ailib/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 152dp
4 | 35dp
5 | 76dp
6 |
7 |
--------------------------------------------------------------------------------
/ailib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AILib
3 |
4 | Speak
5 |
6 |
--------------------------------------------------------------------------------
/ailib/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
24 |
25 |
26 |
33 |
34 |
--------------------------------------------------------------------------------
/ailib/src/test/java/ai/api/test/ProtocolProdTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.test;
18 |
19 | import org.junit.runner.RunWith;
20 | import org.robolectric.RobolectricTestRunner;
21 | import org.robolectric.annotation.Config;
22 |
23 | import ai.api.BuildConfig;
24 |
25 | @Config(constants = BuildConfig.class, manifest = Config.NONE, sdk = BuildConfig.TESTS_SDK)
26 | @RunWith(RobolectricTestRunner.class)
27 | public class ProtocolProdTest extends ProtocolTestBase {
28 |
29 | // Testing keys
30 | protected static final String ACCESS_TOKEN = "3485a96fb27744db83e78b8c4bc9e7b7";
31 |
32 | protected String getAccessToken() {
33 | return ACCESS_TOKEN;
34 | }
35 |
36 | @Override
37 | protected String getSecondAccessToken() {
38 | return "968235e8e4954cf0bb0dc07736725ecd";
39 | }
40 |
41 | protected String getRuAccessToken(){
42 | return "07806228a357411d83064309a279c7fd";
43 | }
44 |
45 | protected String getBrAccessToken(){
46 | // TODO
47 | return "";
48 | }
49 |
50 | protected String getPtBrAccessToken(){
51 | return "42db6ad6a51c47088318a8104833b66c";
52 | }
53 |
54 | @Override
55 | protected String getJaAccessToken() {
56 | // TODO
57 | return "";
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/ailib/src/test/java/ai/api/test/VADTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.test;
18 |
19 | import org.junit.Test;
20 | import org.junit.runner.RunWith;
21 | import org.robolectric.RobolectricTestRunner;
22 | import org.robolectric.annotation.Config;
23 |
24 | import java.io.InputStream;
25 |
26 | import ai.api.BuildConfig;
27 | import ai.api.util.VoiceActivityDetector;
28 |
29 | import static org.junit.Assert.assertFalse;
30 | import static org.junit.Assert.assertTrue;
31 |
32 | @Config(constants = BuildConfig.class, manifest = Config.NONE, sdk = BuildConfig.TESTS_SDK)
33 | @RunWith(RobolectricTestRunner.class)
34 | public class VADTest {
35 |
36 | private static final int SAMPLE_RATE = 16000;
37 |
38 | boolean voiceDetected = false;
39 | boolean speechStarted = false;
40 |
41 | @Test
42 | public void testSpeechDetect() {
43 | final VoiceActivityDetector vad = new VoiceActivityDetector(SAMPLE_RATE);
44 |
45 | final InputStream inputStream = getClass().getClassLoader().getResourceAsStream("speech.raw");
46 |
47 | voiceDetected = false;
48 | speechStarted = false;
49 |
50 | vad.setSpeechListener(new VoiceActivityDetector.SpeechEventsListener() {
51 | @Override
52 | public void onSpeechBegin() {
53 | speechStarted = true;
54 | }
55 |
56 | @Override
57 | public void onSpeechCancel() {
58 |
59 | }
60 |
61 | @Override
62 | public void onSpeechEnd() {
63 | voiceDetected = true;
64 | }
65 | });
66 |
67 | try {
68 | final byte[] frame = new byte[VoiceActivityDetector.FRAME_SIZE_IN_BYTES];
69 | while (inputStream.read(frame, 0, frame.length) == frame.length) {
70 | vad.processBuffer(frame, frame.length);
71 | }
72 |
73 | assertTrue(speechStarted);
74 | assertTrue(voiceDetected);
75 |
76 | } catch (final Exception e) {
77 | e.printStackTrace();
78 | assertTrue(e.getMessage(), false);
79 | }
80 | }
81 |
82 | @Test
83 | public void testSilence() {
84 | final VoiceActivityDetector vad = new VoiceActivityDetector(SAMPLE_RATE);
85 |
86 | final InputStream inputStream = getClass().getClassLoader().getResourceAsStream("silence.raw");
87 |
88 | voiceDetected = false;
89 |
90 | vad.setSpeechListener(new VoiceActivityDetector.SpeechEventsListener() {
91 | @Override
92 | public void onSpeechBegin() {
93 | }
94 |
95 | @Override
96 | public void onSpeechCancel() {
97 | }
98 |
99 | @Override
100 | public void onSpeechEnd() {
101 | voiceDetected = true;
102 | }
103 |
104 | });
105 |
106 | try {
107 | final byte[] frame = new byte[VoiceActivityDetector.FRAME_SIZE_IN_BYTES];
108 | while (inputStream.read(frame, 0, frame.length) == frame.length) {
109 | vad.processBuffer(frame, frame.length);
110 | }
111 |
112 | assertFalse(voiceDetected);
113 |
114 | } catch (final Exception e) {
115 | e.printStackTrace();
116 | assertTrue(e.getMessage(), false);
117 | }
118 | }
119 |
120 | // @Test TODO enable after VAD improvement
121 | public void testNoise() {
122 | final VoiceActivityDetector vad = new VoiceActivityDetector(SAMPLE_RATE);
123 |
124 | final InputStream inputStream = getClass().getClassLoader().getResourceAsStream("noiseOnly.raw");
125 |
126 | voiceDetected = false;
127 |
128 | vad.setSpeechListener(new VoiceActivityDetector.SpeechEventsListener() {
129 | @Override
130 | public void onSpeechBegin() {
131 |
132 | }
133 |
134 | @Override
135 | public void onSpeechCancel() {
136 |
137 | }
138 |
139 | @Override
140 | public void onSpeechEnd() {
141 | voiceDetected = true;
142 | }
143 |
144 | });
145 |
146 | try {
147 | final byte[] frame = new byte[VoiceActivityDetector.FRAME_SIZE_IN_BYTES];
148 | while (inputStream.read(frame, 0, frame.length) == frame.length) {
149 | vad.processBuffer(frame, frame.length);
150 | }
151 |
152 | assertFalse(voiceDetected);
153 |
154 | } catch (final Exception e) {
155 | e.printStackTrace();
156 | assertTrue(e.getMessage(), false);
157 | }
158 | }
159 |
160 | @Test
161 | public void testEnabled() {
162 | final VoiceActivityDetector vad = new VoiceActivityDetector(SAMPLE_RATE);
163 | vad.setEnabled(false);
164 |
165 | final InputStream inputStream = getClass().getClassLoader().getResourceAsStream("speech.raw");
166 |
167 | voiceDetected = false;
168 | speechStarted = false;
169 |
170 | vad.setSpeechListener(new VoiceActivityDetector.SpeechEventsListener() {
171 | @Override
172 | public void onSpeechBegin() {
173 | speechStarted = true;
174 | }
175 |
176 | @Override
177 | public void onSpeechCancel() {
178 |
179 | }
180 |
181 | @Override
182 | public void onSpeechEnd() {
183 | voiceDetected = true;
184 | }
185 |
186 | });
187 |
188 | try {
189 | final byte[] frame = new byte[VoiceActivityDetector.FRAME_SIZE_IN_BYTES];
190 | while (inputStream.read(frame, 0, frame.length) == frame.length) {
191 | vad.processBuffer(frame, frame.length);
192 | }
193 |
194 | assertTrue(speechStarted);
195 | assertFalse(voiceDetected);
196 |
197 | } catch (final Exception e) {
198 | e.printStackTrace();
199 | assertTrue(e.getMessage(), false);
200 | }
201 | }
202 |
203 | }
204 |
--------------------------------------------------------------------------------
/ailib/src/test/java/ai/api/test/compatibility/SimpleProtocolTestingService.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.test.compatibility;
18 |
19 | import android.content.Context;
20 |
21 | import java.io.InputStream;
22 | import java.net.MalformedURLException;
23 |
24 | import ai.api.android.AIConfiguration;
25 | import ai.api.android.AIDataService;
26 | import ai.api.AIServiceException;
27 |
28 | public class SimpleProtocolTestingService extends AIDataService {
29 | public SimpleProtocolTestingService(final Context context, final AIConfiguration config) {
30 | super(context, config);
31 | }
32 |
33 | public String doDefaultProtocolTextRequest(final String requestJson) throws MalformedURLException, AIServiceException {
34 | return doTextRequest(requestJson);
35 | }
36 |
37 | public String doDefaultProtocolSoundRequest(final InputStream voiceStream, final String queryData) throws MalformedURLException, AIServiceException {
38 | return doSoundRequest(voiceStream, queryData);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ailib/src/test/java/ai/api/test/compatibility/V20150415ProtocolTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.test.compatibility;
18 |
19 | import org.junit.Ignore;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.robolectric.RobolectricTestRunner;
23 | import org.robolectric.RuntimeEnvironment;
24 | import org.robolectric.annotation.Config;
25 |
26 | import java.util.Collections;
27 | import java.util.List;
28 |
29 | import ai.api.android.AIConfiguration;
30 | import ai.api.android.AIDataService;
31 | import ai.api.AIServiceException;
32 | import ai.api.BuildConfig;
33 | import ai.api.model.AIContext;
34 | import ai.api.model.AIRequest;
35 | import ai.api.model.AIResponse;
36 |
37 | import static org.junit.Assert.assertEquals;
38 |
39 | /**
40 | * Test for backward compatibility to the first protocol version ("20150415")
41 | */
42 | @Config(constants = BuildConfig.class, manifest = Config.NONE, sdk = BuildConfig.TESTS_SDK)
43 | @RunWith(RobolectricTestRunner.class)
44 | @Ignore
45 | public class V20150415ProtocolTest {
46 | private static final String PROTOCOL_VERSION = "20150415";
47 |
48 | @Test
49 | public void legacyContextsWithoutParametersTest() throws AIServiceException {
50 | final AIConfiguration config = new AIConfiguration(
51 | "3485a96fb27744db83e78b8c4bc9e7b7",
52 | AIConfiguration.SupportedLanguages.English,
53 | AIConfiguration.RecognitionEngine.System);
54 |
55 | config.setProtocolVersion(PROTOCOL_VERSION);
56 |
57 | final AIDataService aiDataService = new AIDataService(RuntimeEnvironment.application, config);
58 |
59 | final AIContext weatherContext = new AIContext("weather");
60 | weatherContext.setParameters(Collections.singletonMap("location", "London"));
61 |
62 | final List contexts = Collections.singletonList(weatherContext);
63 |
64 | final AIRequest aiRequest = new AIRequest();
65 | aiRequest.setQuery("and for tomorrow");
66 | aiRequest.setContexts(contexts);
67 |
68 | final AIResponse aiResponse = aiDataService.request(aiRequest);
69 |
70 | // Old protocol doesn't support parameters, so response will not contains city name
71 | assertEquals("Weather in for tomorrow", aiResponse.getResult().getFulfillment().getSpeech());
72 |
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/ailib/src/test/java/ai/api/test/compatibility/default_protocol_model/AIResponseDefault.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.test.compatibility.default_protocol_model;
18 |
19 | import com.google.gson.annotations.SerializedName;
20 |
21 | import java.io.Serializable;
22 | import java.util.Date;
23 |
24 | import ai.api.model.Status;
25 |
26 | public class AIResponseDefault implements Serializable {
27 |
28 | /**
29 | * Unique identifier of the result.
30 | */
31 | @SerializedName("id")
32 | private String id;
33 |
34 | @SerializedName("timestamp")
35 | private Date timestamp;
36 |
37 | /**
38 | * Result object
39 | */
40 | @SerializedName("result")
41 | private ResultDefault result;
42 |
43 | @SerializedName("status")
44 | private Status status;
45 |
46 | /**
47 | * Unique identifier of the result.
48 | */
49 | public String getId() {
50 | return id;
51 | }
52 |
53 | public void setId(final String id) {
54 | this.id = id;
55 | }
56 |
57 | public Date getTimestamp() {
58 | return timestamp;
59 | }
60 |
61 | public void setTimestamp(final Date timestamp) {
62 | this.timestamp = timestamp;
63 | }
64 |
65 | /**
66 | * Result object
67 | */
68 | public ResultDefault getResult() {
69 | return result;
70 | }
71 |
72 | public void setResult(final ResultDefault result) {
73 | this.result = result;
74 | }
75 |
76 | public Status getStatus() {
77 | return status;
78 | }
79 |
80 | public void setStatus(final Status status) {
81 | this.status = status;
82 | }
83 |
84 | public boolean isError() {
85 | if (status != null && status.getCode() != null && status.getCode() >= 400) {
86 | return true;
87 | }
88 |
89 | return false;
90 | }
91 |
92 | @Override
93 | public String toString() {
94 | return String.format("AIResponse{id='%s', timestamp=%s, result=%s, status=%s}",
95 | id,
96 | timestamp,
97 | result,
98 | status);
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/ailib/src/test/java/ai/api/test/compatibility/default_protocol_model/MetadataDefault.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.test.compatibility.default_protocol_model;
18 |
19 | import com.google.gson.annotations.SerializedName;
20 |
21 | import java.io.Serializable;
22 |
23 | public class MetadataDefault implements Serializable {
24 |
25 | /**
26 | * Name of the intent that produced this result
27 | */
28 | @SerializedName("intentName")
29 | private String intentName;
30 |
31 | /**
32 | * Id of the intent that produced this result
33 | */
34 | @SerializedName("intentId")
35 | private String intentId;
36 |
37 | /**
38 | * Currently active contexts
39 | */
40 | @SerializedName("contexts")
41 | private String[] contexts;
42 |
43 | /**
44 | * Name of the intent that produced this result
45 | */
46 | public String getIntentName() {
47 | return intentName;
48 | }
49 |
50 | public void setIntentName(final String intentName) {
51 | this.intentName = intentName;
52 | }
53 |
54 | /**
55 | * Id of the intent that produced this result
56 | */
57 | public String getIntentId() {
58 | return intentId;
59 | }
60 |
61 | public void setIntentId(final String intentId) {
62 | this.intentId = intentId;
63 | }
64 |
65 | public String[] getContexts() {
66 | return contexts;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ailib/src/test/java/ai/api/test/compatibility/default_protocol_model/ResultDefault.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.test.compatibility.default_protocol_model;
18 |
19 | import com.google.gson.JsonElement;
20 | import com.google.gson.annotations.SerializedName;
21 |
22 | import java.io.Serializable;
23 | import java.util.HashMap;
24 |
25 | public class ResultDefault implements Serializable {
26 |
27 | @SerializedName("speech")
28 | private String speech;
29 |
30 | @SerializedName("action")
31 | private String action;
32 |
33 | /**
34 | * This field will be deserialized as hashMap container with all parameters and it's values
35 | */
36 | @SerializedName("parameters")
37 | private HashMap parameters;
38 |
39 | @SerializedName("metadata")
40 | private MetadataDefault metadata;
41 |
42 | /**
43 | * The query that was used to produce this result
44 | */
45 | @SerializedName("resolvedQuery")
46 | private String resolvedQuery;
47 |
48 | public String getSpeech() {
49 | return speech;
50 | }
51 |
52 | public void setSpeech(final String speech) {
53 | this.speech = speech;
54 | }
55 |
56 | public String getAction() {
57 | return action;
58 | }
59 |
60 | public void setAction(final String action) {
61 | this.action = action;
62 | }
63 |
64 | public MetadataDefault getMetadata() {
65 | return metadata;
66 | }
67 |
68 | public void setMetadata(final MetadataDefault metadata) {
69 | this.metadata = metadata;
70 | }
71 |
72 | public HashMap getParameters() {
73 | return parameters;
74 | }
75 |
76 | /**
77 | * The query that was used to produce this result
78 | */
79 | public String getResolvedQuery() {
80 | return resolvedQuery;
81 | }
82 |
83 | public void setResolvedQuery(final String resolvedQuery) {
84 | this.resolvedQuery = resolvedQuery;
85 | }
86 |
87 | @Override
88 | public String toString() {
89 | return String.format("Result {speech='%s', action='%s', resolvedQuery='%s'}",
90 | speech,
91 | action,
92 | resolvedQuery);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/ailib/src/test/java/ai/api/test/compatibility/v20150204_protocol_model/AIResponseV20150204.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.test.compatibility.v20150204_protocol_model;
18 |
19 | import com.google.gson.annotations.SerializedName;
20 |
21 | import java.io.Serializable;
22 | import java.util.Date;
23 |
24 | import ai.api.model.Result;
25 | import ai.api.model.Status;
26 |
27 | public class AIResponseV20150204 implements Serializable {
28 |
29 | /**
30 | * Unique identifier of the result.
31 | */
32 | @SerializedName("id")
33 | private String id;
34 |
35 | @SerializedName("timestamp")
36 | private Date timestamp;
37 |
38 | /**
39 | * Result object
40 | */
41 | @SerializedName("result")
42 | private ResultV20150204 result;
43 |
44 | @SerializedName("status")
45 | private Status status;
46 |
47 | /**
48 | * Unique identifier of the result.
49 | */
50 | public String getId() {
51 | return id;
52 | }
53 |
54 | public void setId(final String id) {
55 | this.id = id;
56 | }
57 |
58 | public Date getTimestamp() {
59 | return timestamp;
60 | }
61 |
62 | public void setTimestamp(final Date timestamp) {
63 | this.timestamp = timestamp;
64 | }
65 |
66 | /**
67 | * Result object
68 | */
69 | public ResultV20150204 getResult() {
70 | return result;
71 | }
72 |
73 | public void setResult(final ResultV20150204 result) {
74 | this.result = result;
75 | }
76 |
77 | public Status getStatus() {
78 | return status;
79 | }
80 |
81 | public void setStatus(final Status status) {
82 | this.status = status;
83 | }
84 |
85 | public boolean isError() {
86 | if (status != null && status.getCode() != null && status.getCode() >= 400) {
87 | return true;
88 | }
89 |
90 | return false;
91 | }
92 |
93 | @Override
94 | public String toString() {
95 | return String.format("AIResponse{id='%s', timestamp=%s, result=%s, status=%s}",
96 | id,
97 | timestamp,
98 | result,
99 | status);
100 | }
101 |
102 | public void cleanup() {
103 | if (result != null) {
104 | result.trimParameters();
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/ailib/src/test/java/ai/api/test/compatibility/v20150204_protocol_model/ResultV20150204.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.test.compatibility.v20150204_protocol_model;
18 |
19 | import android.support.annotation.NonNull;
20 | import android.text.TextUtils;
21 |
22 | import com.google.gson.JsonElement;
23 | import com.google.gson.JsonPrimitive;
24 | import com.google.gson.annotations.SerializedName;
25 |
26 | import java.io.Serializable;
27 | import java.text.ParseException;
28 | import java.util.Date;
29 | import java.util.HashMap;
30 | import java.util.LinkedList;
31 | import java.util.List;
32 |
33 | import ai.api.model.AIOutputContext;
34 | import ai.api.model.Fulfillment;
35 | import ai.api.model.Metadata;
36 | import ai.api.util.ParametersConverter;
37 |
38 | public class ResultV20150204 implements Serializable {
39 |
40 | private static final String DATE_FORMAT_ERROR_MESSAGE = "'%s' parameter has value '%s' and can't be parsed as a Date";
41 |
42 | @SerializedName("speech")
43 | private String speech;
44 |
45 | @SerializedName("action")
46 | private String action;
47 |
48 | /**
49 | * This field will be deserialized as hashMap container with all parameters and it's values
50 | */
51 | @SerializedName("parameters")
52 | private HashMap parameters;
53 |
54 | /**
55 | * Currently active contexts
56 | */
57 | @SerializedName("contexts")
58 | private AIOutputContext[] contexts;
59 |
60 |
61 | @SerializedName("metadata")
62 | private Metadata metadata;
63 |
64 | /**
65 | * The query that was used to produce this result
66 | */
67 | @SerializedName("resolvedQuery")
68 | private String resolvedQuery;
69 |
70 | public String getSpeech() {
71 | return speech;
72 | }
73 |
74 | public void setSpeech(final String speech) {
75 | this.speech = speech;
76 | }
77 |
78 | @NonNull
79 | public String getAction() {
80 | if (action == null) {
81 | return "";
82 | }
83 | return action;
84 | }
85 |
86 | public void setAction(final String action) {
87 | this.action = action;
88 | }
89 |
90 | public Metadata getMetadata() {
91 | return metadata;
92 | }
93 |
94 | public void setMetadata(final Metadata metadata) {
95 | this.metadata = metadata;
96 | }
97 |
98 | public HashMap getParameters() {
99 | return parameters;
100 | }
101 |
102 | public String getStringParameter(final String name) {
103 | return getStringParameter(name, "");
104 | }
105 |
106 | public String getStringParameter(final String name, final String defaultValue) {
107 | if (parameters.containsKey(name)) {
108 | final String parameterValue = parameters.get(name).getAsString();
109 | return parameterValue;
110 | }
111 | return defaultValue;
112 | }
113 |
114 | public Date getDateParameter(final String name) throws ParseException {
115 | return getDateParameter(name, null);
116 | }
117 |
118 | public Date getDateParameter(final String name, final Date defaultValue) throws IllegalArgumentException {
119 | if (parameters.containsKey(name)) {
120 | final String parameterStringValue = parameters.get(name).getAsString();
121 |
122 | if (TextUtils.isEmpty(parameterStringValue)) {
123 | return defaultValue;
124 | }
125 |
126 | try {
127 | return ParametersConverter.parseDate(parameterStringValue);
128 | } catch (final ParseException pe) {
129 | throw new IllegalArgumentException(String.format(DATE_FORMAT_ERROR_MESSAGE, name, parameterStringValue), pe);
130 | }
131 |
132 | }
133 | return defaultValue;
134 | }
135 |
136 | public Date getDateTimeParameter(final String name) throws ParseException {
137 | return getDateTimeParameter(name, null);
138 | }
139 |
140 | public Date getDateTimeParameter(final String name, final Date defaultValue) throws IllegalArgumentException {
141 | if (parameters.containsKey(name)) {
142 | final String parameterStringValue = parameters.get(name).getAsString();
143 |
144 | if (TextUtils.isEmpty(parameterStringValue)) {
145 | return defaultValue;
146 | }
147 |
148 | try {
149 | return ParametersConverter.parseDateTime(parameterStringValue);
150 | } catch (final ParseException pe) {
151 | throw new IllegalArgumentException(String.format(DATE_FORMAT_ERROR_MESSAGE, name, parameterStringValue), pe);
152 | }
153 |
154 | }
155 | return defaultValue;
156 | }
157 |
158 | public Date getTimeParameter(final String name) throws ParseException {
159 | return getTimeParameter(name, null);
160 | }
161 |
162 | public Date getTimeParameter(final String name, final Date defaultValue) throws IllegalArgumentException {
163 | if (parameters.containsKey(name)) {
164 | final String parameterStringValue = parameters.get(name).getAsString();
165 |
166 | if (TextUtils.isEmpty(parameterStringValue)) {
167 | return defaultValue;
168 | }
169 |
170 | try {
171 | return ParametersConverter.parseTime(parameterStringValue);
172 | } catch (final ParseException pe) {
173 | throw new IllegalArgumentException(String.format(DATE_FORMAT_ERROR_MESSAGE, name, parameterStringValue), pe);
174 | }
175 |
176 | }
177 | return defaultValue;
178 | }
179 |
180 | public int getIntParameter(final String name) {
181 | return getIntParameter(name, 0);
182 | }
183 |
184 | public int getIntParameter(final String name, final int defaultValue) {
185 | if (parameters.containsKey(name)) {
186 | final String parameterStringValue = parameters.get(name).getAsString();
187 |
188 | if (TextUtils.isEmpty(parameterStringValue)) {
189 | return defaultValue;
190 | }
191 |
192 | return ParametersConverter.parseInteger(parameterStringValue);
193 | }
194 | return defaultValue;
195 | }
196 |
197 | public float getFloatParameter(final String name) {
198 | return getFloatParameter(name, 0);
199 | }
200 |
201 | public float getFloatParameter(final String name, final float defaultValue) {
202 | if (parameters.containsKey(name)) {
203 | final String parameterStringValue = parameters.get(name).getAsString();
204 |
205 | if (TextUtils.isEmpty(parameterStringValue)) {
206 | return defaultValue;
207 | }
208 |
209 | return ParametersConverter.parseFloat(parameterStringValue);
210 | }
211 | return defaultValue;
212 | }
213 |
214 | public AIOutputContext[] getContexts() {
215 | return contexts;
216 | }
217 |
218 | /**
219 | * The query that was used to produce this result
220 | */
221 | public String getResolvedQuery() {
222 | return resolvedQuery;
223 | }
224 |
225 | public void setResolvedQuery(final String resolvedQuery) {
226 | this.resolvedQuery = resolvedQuery;
227 | }
228 |
229 | void trimParameters() {
230 | if (parameters != null) {
231 | final List parametersToTrim = new LinkedList();
232 | for (final String key : parameters.keySet()) {
233 | final JsonElement jsonElement = parameters.get(key);
234 | if (jsonElement != null && jsonElement.isJsonPrimitive()) {
235 | if (((JsonPrimitive) jsonElement).isString() && TextUtils.isEmpty(jsonElement.getAsString())) {
236 | parametersToTrim.add(key);
237 | }
238 | }
239 | }
240 | for (final String key : parametersToTrim) {
241 | parameters.remove(key);
242 | }
243 | }
244 | }
245 |
246 | @Override
247 | public String toString() {
248 | return String.format("Result {speech='%s', action='%s', resolvedQuery='%s'}",
249 | speech,
250 | action,
251 | resolvedQuery);
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/ailib/src/test/resources/debug0.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/test/resources/debug0.wav
--------------------------------------------------------------------------------
/ailib/src/test/resources/log.raw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/test/resources/log.raw
--------------------------------------------------------------------------------
/ailib/src/test/resources/noiseAndNotification.raw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/test/resources/noiseAndNotification.raw
--------------------------------------------------------------------------------
/ailib/src/test/resources/noiseOnly.raw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/test/resources/noiseOnly.raw
--------------------------------------------------------------------------------
/ailib/src/test/resources/silence.raw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/test/resources/silence.raw
--------------------------------------------------------------------------------
/ailib/src/test/resources/speech.raw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/test/resources/speech.raw
--------------------------------------------------------------------------------
/ailib/src/test/resources/what_is_your_name.raw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/ailib/src/test/resources/what_is_your_name.raw
--------------------------------------------------------------------------------
/apiAISampleApp/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'com.neenbedankt.android-apt'
3 |
4 | android {
5 | compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
6 | buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
7 |
8 | defaultConfig {
9 | applicationId 'ai.api.sample'
10 | minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
11 | targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
12 | versionCode Integer.parseInt(project.VERSION_CODE)
13 | versionName project.VERSION_NAME
14 | }
15 | buildTypes {
16 | release {
17 | //proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | productFlavors {
21 | }
22 |
23 | packagingOptions {
24 | }
25 | }
26 |
27 | repositories {
28 | mavenLocal()
29 | mavenCentral()
30 |
31 | maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
32 | }
33 |
34 | dependencies {
35 | compile fileTree(dir: 'libs', include: ['*.jar'])
36 | compile 'com.android.support:appcompat-v7:23.2.1'
37 | // compile 'ai.api:sdk:2.0.7@aar'
38 | // this line is for testing purposes
39 | compile project(':ailib')
40 | }
41 |
--------------------------------------------------------------------------------
/apiAISampleApp/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/xvir/sdk/android/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
32 |
35 |
36 |
37 |
41 |
44 |
45 |
46 |
50 |
53 |
54 |
55 |
59 |
62 |
63 |
64 |
68 |
69 |
70 |
71 |
75 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/AIApplication.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.app.Application;
20 | import android.content.Context;
21 | import android.util.Log;
22 |
23 | import ai.api.util.BluetoothController;
24 |
25 | public class AIApplication extends Application {
26 |
27 | private static final String TAG = AIApplication.class.getSimpleName();
28 |
29 | private int activitiesCount;
30 | private BluetoothControllerImpl bluetoothController;
31 | private SettingsManager settingsManager;
32 |
33 | @Override
34 | public void onCreate() {
35 | super.onCreate();
36 | bluetoothController = new BluetoothControllerImpl(this);
37 | settingsManager = new SettingsManager(this);
38 | }
39 |
40 | public BluetoothController getBluetoothController() {
41 | return bluetoothController;
42 | }
43 |
44 | public SettingsManager getSettingsManager() {
45 | return settingsManager;
46 | }
47 |
48 | protected void onActivityResume() {
49 | if (activitiesCount++ == 0) { // on become foreground
50 | if (settingsManager.isUseBluetooth()) {
51 | bluetoothController.start();
52 | }
53 | }
54 | }
55 |
56 | protected void onActivityPaused() {
57 | if (--activitiesCount == 0) { // on become background
58 | bluetoothController.stop();
59 | }
60 | }
61 |
62 | private boolean isInForeground() {
63 | return activitiesCount > 0;
64 | }
65 |
66 | private class BluetoothControllerImpl extends BluetoothController {
67 |
68 | public BluetoothControllerImpl(Context context) {
69 | super(context);
70 | }
71 |
72 | @Override
73 | public void onHeadsetDisconnected() {
74 | Log.d(TAG, "Bluetooth headset disconnected");
75 | }
76 |
77 | @Override
78 | public void onHeadsetConnected() {
79 | Log.d(TAG, "Bluetooth headset connected");
80 |
81 | if (isInForeground() && settingsManager.isUseBluetooth()
82 | && !bluetoothController.isOnHeadsetSco()) {
83 | bluetoothController.start();
84 | }
85 | }
86 |
87 | @Override
88 | public void onScoAudioDisconnected() {
89 | Log.d(TAG, "Bluetooth sco audio finished");
90 | bluetoothController.stop();
91 |
92 | if (isInForeground() && settingsManager.isUseBluetooth()) {
93 | bluetoothController.start();
94 | }
95 | }
96 |
97 | @Override
98 | public void onScoAudioConnected() {
99 | Log.d(TAG, "Bluetooth sco audio started");
100 | }
101 |
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/AIButtonSampleActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.content.Intent;
20 | import android.os.Bundle;
21 | import android.util.Log;
22 | import android.view.Menu;
23 | import android.view.MenuItem;
24 | import android.widget.TextView;
25 |
26 | import com.google.gson.Gson;
27 | import com.google.gson.JsonElement;
28 |
29 | import java.util.HashMap;
30 | import java.util.Map;
31 |
32 | import ai.api.android.AIConfiguration;
33 | import ai.api.android.GsonFactory;
34 | import ai.api.model.AIError;
35 | import ai.api.model.AIResponse;
36 | import ai.api.model.Metadata;
37 | import ai.api.model.Result;
38 | import ai.api.model.Status;
39 | import ai.api.ui.AIButton;
40 |
41 | public class AIButtonSampleActivity extends BaseActivity implements AIButton.AIButtonListener {
42 |
43 | public static final String TAG = AIButtonSampleActivity.class.getName();
44 |
45 | private AIButton aiButton;
46 | private TextView resultTextView;
47 |
48 | private Gson gson = GsonFactory.getGson();
49 |
50 | @Override
51 | protected void onCreate(final Bundle savedInstanceState) {
52 | super.onCreate(savedInstanceState);
53 | setContentView(R.layout.activity_aibutton_sample);
54 |
55 | resultTextView = (TextView) findViewById(R.id.resultTextView);
56 | aiButton = (AIButton) findViewById(R.id.micButton);
57 |
58 | final AIConfiguration config = new AIConfiguration(Config.ACCESS_TOKEN,
59 | AIConfiguration.SupportedLanguages.English,
60 | AIConfiguration.RecognitionEngine.System);
61 |
62 | config.setRecognizerStartSound(getResources().openRawResourceFd(R.raw.test_start));
63 | config.setRecognizerStopSound(getResources().openRawResourceFd(R.raw.test_stop));
64 | config.setRecognizerCancelSound(getResources().openRawResourceFd(R.raw.test_cancel));
65 |
66 | aiButton.initialize(config);
67 | aiButton.setResultsListener(this);
68 | }
69 |
70 | @Override
71 | protected void onPause() {
72 | super.onPause();
73 |
74 | // use this method to disconnect from speech recognition service
75 | // Not destroying the SpeechRecognition object in onPause method would block other apps from using SpeechRecognition service
76 | aiButton.pause();
77 | }
78 |
79 | @Override
80 | protected void onResume() {
81 | super.onResume();
82 |
83 | // use this method to reinit connection to recognition service
84 | aiButton.resume();
85 | }
86 |
87 | @Override
88 | public boolean onCreateOptionsMenu(final Menu menu) {
89 | getMenuInflater().inflate(R.menu.menu_aibutton_sample, menu);
90 | return true;
91 | }
92 |
93 | @Override
94 | public boolean onOptionsItemSelected(final MenuItem item) {
95 | final int id = item.getItemId();
96 |
97 | //noinspection SimplifiableIfStatement
98 | if (id == R.id.action_settings) {
99 | startActivity(AISettingsActivity.class);
100 | return true;
101 | }
102 | return super.onOptionsItemSelected(item);
103 | }
104 |
105 | @Override
106 | public void onResult(final AIResponse response) {
107 | runOnUiThread(new Runnable() {
108 | @Override
109 | public void run() {
110 | Log.d(TAG, "onResult");
111 |
112 | resultTextView.setText(gson.toJson(response));
113 |
114 | Log.i(TAG, "Received success response");
115 |
116 | // this is example how to get different parts of result object
117 | final Status status = response.getStatus();
118 | Log.i(TAG, "Status code: " + status.getCode());
119 | Log.i(TAG, "Status type: " + status.getErrorType());
120 |
121 | final Result result = response.getResult();
122 | Log.i(TAG, "Resolved query: " + result.getResolvedQuery());
123 |
124 | Log.i(TAG, "Action: " + result.getAction());
125 | final String speech = result.getFulfillment().getSpeech();
126 | Log.i(TAG, "Speech: " + speech);
127 | TTS.speak(speech);
128 |
129 | final Metadata metadata = result.getMetadata();
130 | if (metadata != null) {
131 | Log.i(TAG, "Intent id: " + metadata.getIntentId());
132 | Log.i(TAG, "Intent name: " + metadata.getIntentName());
133 | }
134 |
135 | final HashMap params = result.getParameters();
136 | if (params != null && !params.isEmpty()) {
137 | Log.i(TAG, "Parameters: ");
138 | for (final Map.Entry entry : params.entrySet()) {
139 | Log.i(TAG, String.format("%s: %s", entry.getKey(), entry.getValue().toString()));
140 | }
141 | }
142 | }
143 |
144 | });
145 | }
146 |
147 | @Override
148 | public void onError(final AIError error) {
149 | runOnUiThread(new Runnable() {
150 | @Override
151 | public void run() {
152 | Log.d(TAG, "onError");
153 | resultTextView.setText(error.toString());
154 | }
155 | });
156 | }
157 |
158 | @Override
159 | public void onCancelled() {
160 | runOnUiThread(new Runnable() {
161 | @Override
162 | public void run() {
163 | Log.d(TAG, "onCancelled");
164 | resultTextView.setText("");
165 | }
166 | });
167 | }
168 |
169 | private void startActivity(Class> cls) {
170 | final Intent intent = new Intent(this, cls);
171 | startActivity(intent);
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/AIDialogSampleActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.content.Intent;
20 | import android.os.Bundle;
21 | import android.util.Log;
22 | import android.view.Menu;
23 | import android.view.MenuItem;
24 | import android.view.View;
25 | import android.widget.TextView;
26 |
27 | import com.google.gson.Gson;
28 | import com.google.gson.JsonElement;
29 |
30 | import java.util.HashMap;
31 | import java.util.Map;
32 |
33 | import ai.api.android.AIConfiguration;
34 | import ai.api.android.GsonFactory;
35 | import ai.api.model.AIError;
36 | import ai.api.model.AIResponse;
37 | import ai.api.model.Metadata;
38 | import ai.api.model.Result;
39 | import ai.api.model.Status;
40 | import ai.api.ui.AIDialog;
41 |
42 | public class AIDialogSampleActivity extends BaseActivity implements AIDialog.AIDialogListener {
43 |
44 | private static final String TAG = AIDialogSampleActivity.class.getName();
45 |
46 | private TextView resultTextView;
47 | private AIDialog aiDialog;
48 |
49 | private Gson gson = GsonFactory.getGson();
50 |
51 | @Override
52 | public void onCreate(final Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | setContentView(R.layout.activity_aidialog_sample);
55 |
56 | resultTextView = (TextView) findViewById(R.id.resultTextView);
57 |
58 | final AIConfiguration config = new AIConfiguration(Config.ACCESS_TOKEN,
59 | AIConfiguration.SupportedLanguages.English,
60 | AIConfiguration.RecognitionEngine.System);
61 |
62 | aiDialog = new AIDialog(this, config);
63 | aiDialog.setResultsListener(this);
64 | }
65 |
66 | @Override
67 | public void onResult(final AIResponse response) {
68 | runOnUiThread(new Runnable() {
69 | @Override
70 | public void run() {
71 | Log.d(TAG, "onResult");
72 |
73 | resultTextView.setText(gson.toJson(response));
74 |
75 | Log.i(TAG, "Received success response");
76 |
77 | // this is example how to get different parts of result object
78 | final Status status = response.getStatus();
79 | Log.i(TAG, "Status code: " + status.getCode());
80 | Log.i(TAG, "Status type: " + status.getErrorType());
81 |
82 | final Result result = response.getResult();
83 | Log.i(TAG, "Resolved query: " + result.getResolvedQuery());
84 |
85 | Log.i(TAG, "Action: " + result.getAction());
86 | final String speech = result.getFulfillment().getSpeech();
87 | Log.i(TAG, "Speech: " + speech);
88 | TTS.speak(speech);
89 |
90 | final Metadata metadata = result.getMetadata();
91 | if (metadata != null) {
92 | Log.i(TAG, "Intent id: " + metadata.getIntentId());
93 | Log.i(TAG, "Intent name: " + metadata.getIntentName());
94 | }
95 |
96 | final HashMap params = result.getParameters();
97 | if (params != null && !params.isEmpty()) {
98 | Log.i(TAG, "Parameters: ");
99 | for (final Map.Entry entry : params.entrySet()) {
100 | Log.i(TAG, String.format("%s: %s", entry.getKey(), entry.getValue().toString()));
101 | }
102 | }
103 | }
104 |
105 | });
106 | }
107 |
108 | @Override
109 | public void onError(final AIError error) {
110 | runOnUiThread(new Runnable() {
111 | @Override
112 | public void run() {
113 | resultTextView.setText(error.toString());
114 | }
115 | });
116 | }
117 |
118 | @Override
119 | public void onCancelled() {
120 | runOnUiThread(new Runnable() {
121 | @Override
122 | public void run() {
123 | resultTextView.setText("");
124 | }
125 | });
126 | }
127 |
128 | @Override
129 | protected void onPause() {
130 | if (aiDialog != null) {
131 | aiDialog.pause();
132 | }
133 | super.onPause();
134 | }
135 |
136 | @Override
137 | protected void onResume() {
138 | if (aiDialog != null) {
139 | aiDialog.resume();
140 | }
141 | super.onResume();
142 | }
143 |
144 | public void buttonListenOnClick(final View view) {
145 | aiDialog.showAndListen();
146 | }
147 |
148 |
149 |
150 | @Override
151 | public boolean onCreateOptionsMenu(final Menu menu) {
152 | getMenuInflater().inflate(R.menu.menu_aibutton_sample, menu);
153 | return true;
154 | }
155 |
156 | @Override
157 | public boolean onOptionsItemSelected(final MenuItem item) {
158 | final int id = item.getItemId();
159 |
160 | //noinspection SimplifiableIfStatement
161 | if (id == R.id.action_settings) {
162 | startActivity(AISettingsActivity.class);
163 | return true;
164 | }
165 | return super.onOptionsItemSelected(item);
166 | }
167 |
168 | private void startActivity(Class> cls) {
169 | final Intent intent = new Intent(this, cls);
170 | startActivity(intent);
171 | }
172 |
173 |
174 | }
175 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/AISampleAppWidget.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.app.PendingIntent;
20 | import android.appwidget.AppWidgetManager;
21 | import android.appwidget.AppWidgetProvider;
22 | import android.content.Context;
23 | import android.content.Intent;
24 | import android.widget.RemoteViews;
25 | import android.widget.Toast;
26 |
27 |
28 | /**
29 | * Implementation of App Widget functionality.
30 | */
31 | public class AISampleAppWidget extends AppWidgetProvider {
32 | private static final String ACTION_KEY = "tap_on_icon";
33 | @Override
34 | public void onReceive(final Context context, final Intent intent) {
35 | super.onReceive(context, intent);
36 | if (intent.getAction().equals(ACTION_KEY)) {
37 |
38 | final Intent popUpIntent = new Intent(context, AIWidgetActivity.class);
39 |
40 | popUpIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
41 |
42 | context.startActivity(popUpIntent);
43 | Toast.makeText(context.getApplicationContext(), "API.AI Dialog shown",Toast.LENGTH_SHORT).show();
44 |
45 | }
46 | }
47 |
48 | @Override
49 | public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) {
50 | // There may be multiple widgets active, so update all of them
51 | final int N = appWidgetIds.length;
52 | for (int i = 0; i < N; i++) {
53 | updateAppWidget(context, appWidgetManager, appWidgetIds[i]);
54 | }
55 | }
56 |
57 |
58 | @Override
59 | public void onEnabled(final Context context) {
60 | // Enter relevant functionality for when the first widget is created
61 | }
62 |
63 | @Override
64 | public void onDisabled(final Context context) {
65 | // Enter relevant functionality for when the last widget is disabled
66 | }
67 |
68 | static void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager,
69 | final int appWidgetId) {
70 | final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.ai_app_widget);
71 | //views.setTextViewText(R.id.appwidget_text, widgetText);
72 | final Intent intent = new Intent(context, AISampleAppWidget.class);
73 | intent.setAction(ACTION_KEY);
74 | final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
75 | views.setOnClickPendingIntent(R.id.appwidget_new_app_widget, pendingIntent);
76 | // Instruct the widget manager to update the widget
77 | appWidgetManager.updateAppWidget(appWidgetId, views);
78 | }
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/AIServiceSampleActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.content.Intent;
20 | import android.os.Bundle;
21 | import android.text.TextUtils;
22 | import android.util.Log;
23 | import android.view.Menu;
24 | import android.view.MenuItem;
25 | import android.view.View;
26 | import android.widget.AdapterView;
27 | import android.widget.ArrayAdapter;
28 | import android.widget.EditText;
29 | import android.widget.ImageView;
30 | import android.widget.ProgressBar;
31 | import android.widget.Spinner;
32 | import android.widget.TextView;
33 |
34 | import com.google.gson.Gson;
35 | import com.google.gson.JsonElement;
36 |
37 | import java.util.Collections;
38 | import java.util.HashMap;
39 | import java.util.List;
40 | import java.util.Map;
41 |
42 | import ai.api.android.AIConfiguration;
43 | import ai.api.AIListener;
44 | import ai.api.android.AIService;
45 | import ai.api.android.GsonFactory;
46 | import ai.api.RequestExtras;
47 | import ai.api.model.AIContext;
48 | import ai.api.model.AIError;
49 | import ai.api.model.AIResponse;
50 | import ai.api.model.Metadata;
51 | import ai.api.model.Result;
52 | import ai.api.model.Status;
53 |
54 | public class AIServiceSampleActivity extends BaseActivity
55 | implements AIListener, AdapterView.OnItemSelectedListener {
56 |
57 | public static final String TAG = AIServiceSampleActivity.class.getName();
58 |
59 |
60 | private AIService aiService;
61 | private ProgressBar progressBar;
62 | private ImageView recIndicator;
63 | private TextView resultTextView;
64 | private EditText contextEditText;
65 |
66 | private Gson gson = GsonFactory.getGson();
67 |
68 | @Override
69 | protected void onCreate(final Bundle savedInstanceState) {
70 | super.onCreate(savedInstanceState);
71 | setContentView(R.layout.activity_aiservice_sample);
72 |
73 | progressBar = (ProgressBar) findViewById(R.id.progressBar);
74 | recIndicator = (ImageView) findViewById(R.id.recIndicator);
75 | resultTextView = (TextView) findViewById(R.id.resultTextView);
76 | contextEditText = (EditText) findViewById(R.id.contextEditText);
77 |
78 | Spinner spinner = (Spinner) findViewById(R.id.selectLanguageSpinner);
79 | final ArrayAdapter languagesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, Config.languages);
80 | spinner.setAdapter(languagesAdapter);
81 | spinner.setOnItemSelectedListener(this);
82 | }
83 |
84 | private void initService(final LanguageConfig selectedLanguage) {
85 | final AIConfiguration.SupportedLanguages lang = AIConfiguration.SupportedLanguages.fromLanguageTag(selectedLanguage.getLanguageCode());
86 | final AIConfiguration config = new AIConfiguration(selectedLanguage.getAccessToken(),
87 | lang,
88 | AIConfiguration.RecognitionEngine.System);
89 |
90 | if (aiService != null) {
91 | aiService.pause();
92 | }
93 |
94 | aiService = AIService.getService(this, config);
95 | aiService.setListener(this);
96 | }
97 |
98 |
99 | @Override
100 | public boolean onCreateOptionsMenu(final Menu menu) {
101 | getMenuInflater().inflate(R.menu.menu_aiservice_sample, menu);
102 | return true;
103 | }
104 |
105 | @Override
106 | public boolean onOptionsItemSelected(final MenuItem item) {
107 | final int id = item.getItemId();
108 |
109 | //noinspection SimplifiableIfStatement
110 | if (id == R.id.action_settings) {
111 | startActivity(AISettingsActivity.class);
112 | return true;
113 | }
114 | return super.onOptionsItemSelected(item);
115 | }
116 |
117 | @Override
118 | protected void onPause() {
119 | super.onPause();
120 |
121 | // use this method to disconnect from speech recognition service
122 | // Not destroying the SpeechRecognition object in onPause method would block other apps from using SpeechRecognition service
123 | if (aiService != null) {
124 | aiService.pause();
125 | }
126 | }
127 |
128 | @Override
129 | protected void onResume() {
130 | super.onResume();
131 |
132 | // use this method to reinit connection to recognition service
133 | if (aiService != null) {
134 | aiService.resume();
135 | }
136 | }
137 |
138 | public void startRecognition(final View view) {
139 | final String contextString = String.valueOf(contextEditText.getText());
140 | if (TextUtils.isEmpty(contextString)) {
141 | aiService.startListening();
142 | } else {
143 | final List contexts = Collections.singletonList(new AIContext(contextString));
144 | final RequestExtras requestExtras = new RequestExtras(contexts, null);
145 | aiService.startListening(requestExtras);
146 | }
147 |
148 | }
149 |
150 | public void stopRecognition(final View view) {
151 | aiService.stopListening();
152 | }
153 |
154 | public void cancelRecognition(final View view) {
155 | aiService.cancel();
156 | }
157 |
158 | @Override
159 | public void onResult(final AIResponse response) {
160 | runOnUiThread(new Runnable() {
161 | @Override
162 | public void run() {
163 | Log.d(TAG, "onResult");
164 |
165 | resultTextView.setText(gson.toJson(response));
166 |
167 | Log.i(TAG, "Received success response");
168 |
169 | // this is example how to get different parts of result object
170 | final Status status = response.getStatus();
171 | Log.i(TAG, "Status code: " + status.getCode());
172 | Log.i(TAG, "Status type: " + status.getErrorType());
173 |
174 | final Result result = response.getResult();
175 | Log.i(TAG, "Resolved query: " + result.getResolvedQuery());
176 |
177 | Log.i(TAG, "Action: " + result.getAction());
178 |
179 | final String speech = result.getFulfillment().getSpeech();
180 | Log.i(TAG, "Speech: " + speech);
181 | TTS.speak(speech);
182 |
183 | final Metadata metadata = result.getMetadata();
184 | if (metadata != null) {
185 | Log.i(TAG, "Intent id: " + metadata.getIntentId());
186 | Log.i(TAG, "Intent name: " + metadata.getIntentName());
187 | }
188 |
189 | final HashMap params = result.getParameters();
190 | if (params != null && !params.isEmpty()) {
191 | Log.i(TAG, "Parameters: ");
192 | for (final Map.Entry entry : params.entrySet()) {
193 | Log.i(TAG, String.format("%s: %s", entry.getKey(), entry.getValue().toString()));
194 | }
195 | }
196 | }
197 |
198 | });
199 | }
200 |
201 | @Override
202 | public void onError(final AIError error) {
203 | runOnUiThread(new Runnable() {
204 | @Override
205 | public void run() {
206 | resultTextView.setText(error.toString());
207 | }
208 | });
209 | }
210 |
211 | @Override
212 | public void onAudioLevel(final float level) {
213 | runOnUiThread(new Runnable() {
214 | @Override
215 | public void run() {
216 | float positiveLevel = Math.abs(level);
217 |
218 | if (positiveLevel > 100) {
219 | positiveLevel = 100;
220 | }
221 | progressBar.setProgress((int) positiveLevel);
222 | }
223 | });
224 | }
225 |
226 | @Override
227 | public void onListeningStarted() {
228 | runOnUiThread(new Runnable() {
229 | @Override
230 | public void run() {
231 | recIndicator.setVisibility(View.VISIBLE);
232 | }
233 | });
234 | }
235 |
236 | @Override
237 | public void onListeningCanceled() {
238 | runOnUiThread(new Runnable() {
239 | @Override
240 | public void run() {
241 | recIndicator.setVisibility(View.INVISIBLE);
242 | resultTextView.setText("");
243 | }
244 | });
245 | }
246 |
247 | @Override
248 | public void onListeningFinished() {
249 | runOnUiThread(new Runnable() {
250 | @Override
251 | public void run() {
252 | recIndicator.setVisibility(View.INVISIBLE);
253 | }
254 | });
255 | }
256 |
257 | @Override
258 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
259 | final LanguageConfig selectedLanguage = (LanguageConfig) parent.getItemAtPosition(position);
260 | initService(selectedLanguage);
261 | }
262 |
263 | @Override
264 | public void onNothingSelected(AdapterView> parent) {
265 |
266 | }
267 |
268 | private void startActivity(Class> cls) {
269 | final Intent intent = new Intent(this, cls);
270 | startActivity(intent);
271 | }
272 | }
273 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/AISettingsActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.os.Bundle;
20 | import android.view.View;
21 | import android.view.ViewGroup;
22 | import android.widget.CheckBox;
23 | import android.widget.CompoundButton;
24 |
25 | public class AISettingsActivity extends BaseActivity implements
26 | View.OnClickListener,
27 | CompoundButton.OnCheckedChangeListener {
28 |
29 | private CheckBox bluetoothSwitch;
30 |
31 | private SettingsManager settingsManager;
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.activity_settings);
37 |
38 | settingsManager = ((AIApplication) getApplication()).getSettingsManager();
39 |
40 | ViewGroup bluetoothSection = (ViewGroup) findViewById(R.id.activity_settings_bluetooth_section);
41 | bluetoothSection.setOnClickListener(this);
42 |
43 | bluetoothSwitch = (CheckBox) findViewById(R.id.activity_settings_bluetooth_swith);
44 | bluetoothSwitch.setChecked(settingsManager.isUseBluetooth());
45 | bluetoothSwitch.setOnCheckedChangeListener(this);
46 |
47 | }
48 |
49 | @Override
50 | public void onClick(View v) {
51 | switch (v.getId()) {
52 | case R.id.activity_settings_bluetooth_section:
53 | bluetoothSwitch.performClick();
54 | break;
55 | }
56 | }
57 |
58 | @Override
59 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
60 | switch (buttonView.getId()) {
61 | case R.id.activity_settings_bluetooth_swith:
62 | settingsManager.setUseBluetooth(isChecked);
63 | break;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/AIWidgetActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 | import android.content.DialogInterface;
19 | import android.os.Bundle;
20 | import android.support.v7.app.ActionBarActivity;
21 | import android.view.Menu;
22 | import android.view.MenuItem;
23 | import android.view.Window;
24 | import android.widget.Toast;
25 |
26 | import ai.api.android.AIConfiguration;
27 | import ai.api.model.AIError;
28 | import ai.api.model.AIResponse;
29 | import ai.api.ui.AIDialog;
30 |
31 |
32 | public class AIWidgetActivity extends ActionBarActivity {
33 |
34 | private AIDialog aiDialog;
35 |
36 | @Override
37 | protected void onCreate(final Bundle savedInstanceState) {
38 | supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
39 | super.onCreate(savedInstanceState);
40 | setContentView(R.layout.activity_widget_sample);
41 | final AIConfiguration config = new AIConfiguration(Config.ACCESS_TOKEN,
42 | AIConfiguration.SupportedLanguages.English,
43 | AIConfiguration.RecognitionEngine.System);
44 |
45 | aiDialog = new AIDialog(this, config);
46 | aiDialog.setResultsListener(new AIDialog.AIDialogListener() {
47 | @Override
48 | public void onResult(final AIResponse aiResponse) {
49 | // TODO Process aiResponse
50 | aiDialog.close();
51 | Toast.makeText(getApplicationContext(), String.format("%s %s","Successful response: ",
52 | aiResponse.getResult().getResolvedQuery()), Toast.LENGTH_SHORT).show();
53 | AIWidgetActivity.this.finish();
54 | }
55 |
56 | @Override
57 | public void onError(final AIError aiError) {
58 | // TODO show error message
59 | aiDialog.close();
60 | Toast.makeText(getApplicationContext(), aiError.getMessage(), Toast.LENGTH_SHORT).show();
61 | AIWidgetActivity.this.finish();
62 | }
63 |
64 | @Override
65 | public void onCancelled() {
66 | aiDialog.close();
67 | Toast.makeText(getApplicationContext(), "Process cancelled", Toast.LENGTH_SHORT).show();
68 | AIWidgetActivity.this.finish();
69 | }
70 |
71 | });
72 |
73 | aiDialog.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
74 | @Override
75 | public void onDismiss(final DialogInterface dialog) {
76 | Toast.makeText(getApplicationContext(), "Dialog dismissed by user", Toast.LENGTH_SHORT).show();
77 | AIWidgetActivity.this.finish();
78 | }
79 | });
80 |
81 |
82 | }
83 |
84 | @Override
85 | protected void onResume() {
86 | super.onResume();
87 | aiDialog.showAndListen();
88 | }
89 |
90 | @Override
91 | public boolean onCreateOptionsMenu(final Menu menu) {
92 | return true;
93 | }
94 |
95 | @Override
96 | public boolean onOptionsItemSelected(final MenuItem item) {
97 | final int id = item.getItemId();
98 | return super.onOptionsItemSelected(item);
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/BaseActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.Manifest;
20 | import android.content.pm.PackageManager;
21 | import android.os.Bundle;
22 | import android.os.Handler;
23 | import android.support.annotation.NonNull;
24 | import android.support.v4.app.ActivityCompat;
25 | import android.support.v4.content.ContextCompat;
26 | import android.support.v7.app.AppCompatActivity;
27 |
28 | public class BaseActivity extends AppCompatActivity {
29 |
30 | private AIApplication app;
31 |
32 | private static final long PAUSE_CALLBACK_DELAY = 500;
33 | private static final int REQUEST_AUDIO_PERMISSIONS_ID = 33;
34 |
35 | private final Handler handler = new Handler();
36 | private Runnable pauseCallback = new Runnable() {
37 | @Override
38 | public void run() {
39 | app.onActivityPaused();
40 | }
41 | };
42 |
43 | @Override
44 | protected void onCreate(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 | app = (AIApplication) getApplication();
47 | }
48 |
49 | @Override
50 | protected void onResume() {
51 | super.onResume();
52 | app.onActivityResume();
53 | }
54 |
55 | @Override
56 | protected void onPause() {
57 | super.onPause();
58 | handler.postDelayed(pauseCallback, PAUSE_CALLBACK_DELAY);
59 | }
60 |
61 | protected void checkAudioRecordPermission() {
62 | if (ContextCompat.checkSelfPermission(this,
63 | Manifest.permission.RECORD_AUDIO)
64 | != PackageManager.PERMISSION_GRANTED) {
65 |
66 | // Should we show an explanation?
67 | if (ActivityCompat.shouldShowRequestPermissionRationale(this,
68 | Manifest.permission.RECORD_AUDIO)) {
69 |
70 | // Show an explanation to the user *asynchronously* -- don't block
71 | // this thread waiting for the user's response! After the user
72 | // sees the explanation, try again to request the permission.
73 |
74 | } else {
75 |
76 | // No explanation needed, we can request the permission.
77 |
78 | ActivityCompat.requestPermissions(this,
79 | new String[]{Manifest.permission.RECORD_AUDIO},
80 | REQUEST_AUDIO_PERMISSIONS_ID);
81 |
82 | }
83 | }
84 | }
85 |
86 | @Override
87 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
88 | switch (requestCode) {
89 | case REQUEST_AUDIO_PERMISSIONS_ID: {
90 | // If request is cancelled, the result arrays are empty.
91 | if (grantResults.length > 0
92 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
93 |
94 | // permission was granted, yay! Do the
95 | // contacts-related task you need to do.
96 |
97 | } else {
98 |
99 | // permission denied, boo! Disable the
100 | // functionality that depends on this permission.
101 | }
102 | return;
103 | }
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/Config.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | public abstract class Config {
20 | // copy this keys from your developer dashboard
21 | public static final String ACCESS_TOKEN = "3485a96fb27744db83e78b8c4bc9e7b7";
22 |
23 | public static final LanguageConfig[] languages = new LanguageConfig[]{
24 | new LanguageConfig("en", "a11ea1d839e3446d84e402cb97cdadfb"),
25 | new LanguageConfig("ru", "c8acebfbeeaa42ccb986e30573509055"),
26 | new LanguageConfig("de", "ae2afb2dfd3f4a02bb0da9dd32b78ff6"),
27 | new LanguageConfig("pt", "b27372e24ee44db48df4dccbd57ea021"),
28 | new LanguageConfig("pt-BR", "a4e08b5bc87a41098237e3f23a5e1351"),
29 | new LanguageConfig("es", "49be4c10b6a543dfb41d49d88731bd49"),
30 | new LanguageConfig("fr", "62161233bc094a75b3acfe16aeeed203"),
31 | new LanguageConfig("it", "57f80c9c9a2b4e0eae1739349a46e342"),
32 | new LanguageConfig("ja", "b92617a3f82e4b52b3db44436d2d4b8b"),
33 | new LanguageConfig("ko", "447a595234d74561a76b669a88ab3d99"),
34 | new LanguageConfig("zh-CN", "52d2b2bd992749409fc3a7d0605c3db4"),
35 | new LanguageConfig("zh-HK", "760c7a5efe5d43b9a90d62f73251de6a"),
36 | new LanguageConfig("zh-TW", "9cadea114425436cbaeaa504ea56555b"),
37 | };
38 |
39 | public static final String[] events = new String[]{
40 | "hello_event",
41 | "goodbye_event",
42 | "how_are_you_event"
43 | };
44 | }
45 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/LanguageConfig.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import java.lang.String;
20 |
21 | public class LanguageConfig {
22 | private final String languageCode;
23 | private final String accessToken;
24 |
25 | public LanguageConfig(final String languageCode, final String accessToken) {
26 | this.languageCode = languageCode;
27 | this.accessToken = accessToken;
28 | }
29 |
30 | public String getLanguageCode() {
31 | return languageCode;
32 | }
33 |
34 | public String getAccessToken() {
35 | return accessToken;
36 | }
37 |
38 | @Override
39 | public String toString() {
40 | return languageCode;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.content.Intent;
20 | import android.os.Bundle;
21 | import android.view.Menu;
22 | import android.view.MenuItem;
23 | import android.view.View;
24 |
25 | public class MainActivity extends BaseActivity {
26 |
27 | public static final String TAG = MainActivity.class.getName();
28 |
29 | @Override
30 | protected void onCreate(final Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_main);
33 |
34 | TTS.init(getApplicationContext());
35 | }
36 |
37 | @Override
38 | protected void onStart() {
39 | super.onStart();
40 |
41 | checkAudioRecordPermission();
42 | }
43 |
44 | @Override
45 | public boolean onCreateOptionsMenu(final Menu menu) {
46 | // Inflate the menu; this adds items to the action bar if it is present.
47 | getMenuInflater().inflate(R.menu.main, menu);
48 | return true;
49 | }
50 |
51 | @Override
52 | public boolean onOptionsItemSelected(final MenuItem item) {
53 | // Handle action bar item clicks here. The action bar will
54 | // automatically handle clicks on the Home/Up button, so long
55 | // as you specify a parent activity in AndroidManifest.xml.
56 | final int id = item.getItemId();
57 | if (id == R.id.action_settings) {
58 | startActivity(AISettingsActivity.class);
59 | return true;
60 | }
61 | return super.onOptionsItemSelected(item);
62 | }
63 |
64 | public void serviceSampleClick(final View view) {
65 | startActivity(AIServiceSampleActivity.class);
66 | }
67 |
68 | public void buttonSampleClick(final View view) {
69 | startActivity(AIButtonSampleActivity.class);
70 | }
71 |
72 | public void dialogSampleClick(final View view) {
73 | startActivity(AIDialogSampleActivity.class);
74 | }
75 |
76 | public void textSampleClick(final View view) {
77 | startActivity(AITextSampleActivity.class);
78 | }
79 |
80 | private void startActivity(Class> cls) {
81 | final Intent intent = new Intent(this, cls);
82 | startActivity(intent);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/SettingsManager.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.content.Context;
20 | import android.content.SharedPreferences;
21 |
22 | import ai.api.util.BluetoothController;
23 |
24 | public class SettingsManager {
25 |
26 | private static final String SETTINGS_PREFS_NAME = "ai.api.APP_SETTINGS";
27 | private static final String PREF_USE_BLUETOOTH = "USE_BLUETOOTH";
28 |
29 | private final Context context;
30 | private SharedPreferences prefs;
31 |
32 | private boolean useBluetooth;
33 |
34 | public SettingsManager(final Context context) {
35 | this.context = context;
36 | prefs = context.getSharedPreferences(SETTINGS_PREFS_NAME, Context.MODE_PRIVATE);
37 |
38 | useBluetooth = prefs.getBoolean(PREF_USE_BLUETOOTH, true);
39 | }
40 |
41 | public void setUseBluetooth(final boolean useBluetooth) {
42 | this.useBluetooth = useBluetooth;
43 |
44 | prefs.edit().putBoolean(PREF_USE_BLUETOOTH, useBluetooth).commit();
45 | final BluetoothController controller = ((AIApplication) context.getApplicationContext()).getBluetoothController();
46 | if (useBluetooth) {
47 | controller.start();
48 | } else {
49 | controller.stop();
50 | }
51 | }
52 |
53 | public boolean isUseBluetooth() {
54 | return useBluetooth;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/java/ai/api/sample/TTS.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ai.api.sample;
18 |
19 | import android.content.Context;
20 | import android.speech.tts.TextToSpeech;
21 |
22 | public class TTS {
23 |
24 | private static TextToSpeech textToSpeech;
25 |
26 | public static void init(final Context context) {
27 | if (textToSpeech == null) {
28 | textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
29 | @Override
30 | public void onInit(int i) {
31 |
32 | }
33 | });
34 | }
35 | }
36 |
37 | public static void speak(final String text) {
38 | textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/apiAISampleApp/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/drawable-hdpi/recording_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/apiAISampleApp/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/apiAISampleApp/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/apiAISampleApp/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/drawable/view_alpha_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/layout/activity_aibutton_sample.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
16 |
17 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/layout/activity_aidialog_sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
11 |
19 |
20 |
21 |
22 |
29 |
30 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/layout/activity_aiservice_sample.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
19 |
20 |
24 |
25 |
29 |
30 |
36 |
37 |
43 |
44 |
50 |
51 |
58 |
59 |
60 |
61 |
68 |
69 |
72 |
73 |
77 |
78 |
83 |
84 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/layout/activity_aitext_sample.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
13 |
14 |
18 |
19 |
22 |
23 |
27 |
28 |
32 |
33 |
34 |
39 |
40 |
44 |
45 |
51 |
52 |
58 |
59 |
60 |
61 |
65 |
66 |
71 |
72 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
16 |
17 |
22 |
23 |
29 |
30 |
36 |
37 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/layout/activity_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
18 |
19 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/layout/activity_widget_sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/layout/ai_app_widget.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/menu/menu_aibutton_sample.xml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/menu/menu_aiservice_sample.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/raw/test_cancel.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/apiAISampleApp/src/main/res/raw/test_cancel.wav
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/raw/test_start.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/apiAISampleApp/src/main/res/raw/test_start.wav
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/raw/test_stop.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/apiAISampleApp/src/main/res/raw/test_stop.mp3
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #4Db4b4b4
4 | #cfcfcf
5 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | API.AI Sample
5 | Settings
6 |
7 | AIButtonSampleActivity
8 | AIServiceSample
9 | AIDialogSample
10 | AITextSample
11 | Service sample
12 | Button sample
13 | Dialog sample
14 | Text sample
15 | Voice command
16 | Query should not be empty
17 |
18 | Use Bluetooth headset
19 |
20 |
21 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
17 |
18 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/apiAISampleApp/src/main/res/xml/ai_app_widget_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | mavenLocal()
6 | mavenCentral()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:2.3.3'
11 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | mavenCentral()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/docs/images/AppScreenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/AppScreenshot.png
--------------------------------------------------------------------------------
/docs/images/BuildTools19.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/BuildTools19.1.png
--------------------------------------------------------------------------------
/docs/images/DebugButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/DebugButton.png
--------------------------------------------------------------------------------
/docs/images/Dependencies.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/Dependencies.png
--------------------------------------------------------------------------------
/docs/images/Dependencies2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/Dependencies2.png
--------------------------------------------------------------------------------
/docs/images/LayoutDesigner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/LayoutDesigner.png
--------------------------------------------------------------------------------
/docs/images/ListenButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/ListenButton.png
--------------------------------------------------------------------------------
/docs/images/MinSDK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/MinSDK.png
--------------------------------------------------------------------------------
/docs/images/NewModule.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/NewModule.png
--------------------------------------------------------------------------------
/docs/images/NewModuleDlg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/NewModuleDlg.png
--------------------------------------------------------------------------------
/docs/images/NewProject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/NewProject.png
--------------------------------------------------------------------------------
/docs/images/NewProjectDialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/NewProjectDialog.png
--------------------------------------------------------------------------------
/docs/images/PlainText.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/PlainText.png
--------------------------------------------------------------------------------
/docs/images/ResultViewText.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/ResultViewText.png
--------------------------------------------------------------------------------
/docs/images/SDKManager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/SDKManager.png
--------------------------------------------------------------------------------
/docs/images/apiKeys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/docs/images/apiKeys.png
--------------------------------------------------------------------------------
/docs/integration.md:
--------------------------------------------------------------------------------
1 | Integration
2 | ==================
3 |
4 | This instruction describes two different ways of integration [API.AI](http://www.api.ai) Android SDK with your app.
5 |
6 | Before integration make sure your app have these permissions:
7 |
8 | * **android.permission.INTERNET** for internet access
9 | * **android.permission.RECORD_AUDIO** for microphone access
10 |
11 | Also SDK library must be in your app dependencies (see **build.gradle**)
12 | ```
13 | dependencies {
14 | // some another dependencies...
15 | compile 'ai.api:libai:1.4.8'
16 | compile 'ai.api:sdk:2.0.5@aar'
17 | // api.ai SDK dependencies
18 | compile 'com.android.support:appcompat-v7:21.0.3'
19 | compile 'com.google.code.gson:gson:2.3'
20 | compile 'commons-io:commons-io:2.4'
21 | }
22 | ```
23 |
24 | * [Integration with AIButton](#integration-with-aibutton)
25 | * [Integration with AIService](#integration-with-aiservice)
26 | * [Integration with AIDialog](#integration-with-aidialog)
27 |
28 | # Integration with AIButton
29 |
30 | Use this type of integration if you want quickly integrate natural language processing functionality into your application. The idea is to add ready button control from the SDK. Use the following steps.
31 |
32 | 1. Add the following code snippet to your activity
33 |
34 | ```xml
35 |
40 | ```
41 |
42 | 2. Add the following code to your activity's `onCreate` function
43 |
44 | ```java
45 | final AIConfiguration config = new AIConfiguration("YOUR_ACCESS_TOKEN",
46 | AIConfiguration.SupportedLanguages.English,
47 | AIConfiguration.RecognitionEngine.System);
48 |
49 | aiButton = (AIButton) findViewById(R.id.micButton);
50 |
51 | aiButton.initialize(config);
52 | aiButton.setResultsListener(new AIButton.AIButtonListener() {
53 | @Override
54 | public void onResult(final AIResponse result) {
55 | runOnUiThread(new Runnable() {
56 | @Override
57 | public void run() {
58 | Log.d("ApiAi", "onResult");
59 | // TODO process response here
60 | }
61 | });
62 | }de
63 |
64 | @Override
65 | public void onError(final AIError error) {
66 | runOnUiThread(new Runnable() {
67 | @Override
68 | public void run() {
69 | Log.d("ApiAi", "onError");
70 | // TODO process error here
71 | }
72 | });
73 | }
74 | });
75 | ```
76 |
77 | 3. Replace "YOUR_ACCESS_TOKEN" with key from your development console on the [API.AI](http://www.api.ai) site.
78 | 4. Write your custom code instead of `// process response here` and `//process error here` to process success and error responses from the api.ai.
79 |
80 | # Integration with AIService
81 |
82 | Use this type of integration if you want integrate natural language processing functionality from the [API.AI](http://www.api.ai) in more customizable way. In this way you will be need to create your own controls for start listening, show sound level, cancel request etc.
83 | Use the following steps:
84 |
85 | 1. Use one of your application's Activity as the class that will be called when events occur by having it implement the AIListener class. Replace the class declaration with this:
86 |
87 | ```java
88 | public class MainActivity extends ActionBarActivity implements AIListener {
89 | ```
90 |
91 | 2. In the Activity class, create a private member for the **AIService** class named `aiService`.
92 |
93 | ```java
94 | private AIService aiService;
95 | ```
96 |
97 | 3. In the OnCreate method, add the following line to set up the configuration to use Google speech recognition. Replace CLIENT_ACCESS_TOKEN with your client access token.
98 |
99 | ```java
100 | final AIConfiguration config = new AIConfiguration("CLIENT_ACCESS_TOKEN",
101 | AIConfiguration.SupportedLanguages.English,
102 | AIConfiguration.RecognitionEngine.System);
103 | ```
104 |
105 | 
106 |
107 | 4. Below this line, initialize the AI service and add this instance as the listener to handle events.
108 |
109 | ```java
110 | aiService = AIService.getService(this, config);
111 | aiService.setListener(this);
112 | ```
113 |
114 | 5. Add button to your activity and add method to start listening on the button click:
115 | ```java
116 | public void listenButtonOnClick(final View view) {
117 | aiService.startListening();
118 | }
119 | ```
120 |
121 | 6. Add the following method to show the results when the listening is complete. *Make sure you interact with UI in the UI thread.*
122 |
123 | ```java
124 | public void onResult(final AIResponse response) {
125 | runOnUiThread(new Runnable() {
126 | @Override
127 | public void run() {
128 | Result result = response.getResult();
129 |
130 | // Get parameters
131 | String parameterString = "";
132 | if (result.getParameters() != null && !result.getParameters().isEmpty()) {
133 | for (final Map.Entry entry : result.getParameters().entrySet()) {
134 | parameterString += "(" + entry.getKey() + ", " + entry.getValue() + ") ";
135 | }
136 | }
137 |
138 | // Show results in TextView.
139 | resultTextView.setText("Query:" + result.getResolvedQuery() +
140 | "\nAction: " + result.getAction() +
141 | "\nParameters: " + parameterString);
142 | }
143 | });
144 | }
145 | ```
146 |
147 | 7. Add the following method to handle errors. *Make sure you interact with UI in the UI thread.*
148 |
149 | ```java
150 | @Override
151 | public void onError(final AIError error) {
152 | runOnUiThread(new Runnable() {
153 | @Override
154 | public void run() {
155 | resultTextView.setText(error.toString());
156 | }
157 | });
158 | }
159 | ```
160 |
161 | 8. Use the following methods to implement the AIListener interface and process ListeningStarted, ListeningFinished, SoundLevelChanged events:
162 |
163 | ```java
164 | @Override
165 | public void onListeningStarted() {
166 | // show recording indicator
167 | }
168 |
169 | @Override
170 | public void onListeningFinished() {
171 | // hide recording indicator
172 | }
173 |
174 | @Override
175 | public void onAudioLevel(final float level) {
176 | // show sound level
177 | }
178 | ```
179 |
180 | # Integration with AIDialog
181 |
182 | AIDialog is simple and ready to use dialog for making voice requests. All you need is create `AIConfiguration`:
183 |
184 | ```java
185 | final AIConfiguration config = new AIConfiguration("CLIENT_ACCESS_TOKEN",
186 | AIConfiguration.SupportedLanguages.English,
187 | AIConfiguration.RecognitionEngine.System);
188 | ```
189 |
190 | And implement `AIDialog.AIDialogListener` interface methods:
191 |
192 | ```java
193 | void onResult(final AIResponse result);
194 | void onError(final AIError error);
195 | void onCancelled();
196 | ```
197 |
198 | Then create `AIDialog` instance and show it:
199 |
200 | ```java
201 | AIDialog aiDialog = new AIDialog(this, config);
202 | aiDialog.setResultsListener(yourListenerImplementation);
203 | aiDialog.showAndListen();
204 | ```
205 |
206 | AIDialog instance can be used multiple times.
--------------------------------------------------------------------------------
/gradle-mvn-push.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Chris Banes
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: 'maven'
18 | apply plugin: 'signing'
19 |
20 | def isReleaseBuild() {
21 | return VERSION_NAME.contains("SNAPSHOT") == false
22 | }
23 |
24 | def getReleaseRepositoryUrl() {
25 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
26 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
27 | }
28 |
29 | def getSnapshotRepositoryUrl() {
30 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
31 | : "https://oss.sonatype.org/content/repositories/snapshots/"
32 | }
33 |
34 | def getRepositoryUsername() {
35 | return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
36 | }
37 |
38 | def getRepositoryPassword() {
39 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
40 | }
41 |
42 | afterEvaluate { project ->
43 | uploadArchives {
44 | repositories {
45 | mavenDeployer {
46 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
47 |
48 | pom.groupId = GROUP
49 | pom.artifactId = POM_ARTIFACT_ID
50 | pom.version = VERSION_NAME
51 |
52 | repository(url: getReleaseRepositoryUrl()) {
53 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
54 | }
55 | snapshotRepository(url: getSnapshotRepositoryUrl()) {
56 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
57 | }
58 |
59 | pom.project {
60 | name POM_NAME
61 | packaging POM_PACKAGING
62 | description POM_DESCRIPTION
63 | url POM_URL
64 |
65 | scm {
66 | url POM_SCM_URL
67 | connection POM_SCM_CONNECTION
68 | developerConnection POM_SCM_DEV_CONNECTION
69 | }
70 |
71 | licenses {
72 | license {
73 | name POM_LICENCE_NAME
74 | url POM_LICENCE_URL
75 | distribution POM_LICENCE_DIST
76 | }
77 | }
78 |
79 | developers {
80 | developer {
81 | id POM_DEVELOPER_ID
82 | name POM_DEVELOPER_NAME
83 | }
84 | }
85 | }
86 | }
87 | }
88 | }
89 |
90 | signing {
91 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
92 | sign configurations.archives
93 | }
94 |
95 | task androidJavadocs(type: Javadoc) {
96 | source = android.sourceSets.main.java.srcDirs
97 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
98 | classpath += project.android.libraryVariants.toList().first().javaCompile.classpath
99 | failOnError = false
100 | }
101 |
102 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
103 | classifier = 'javadoc'
104 | from androidJavadocs.destinationDir
105 | }
106 |
107 | task androidSourcesJar(type: Jar) {
108 | classifier = 'sources'
109 | from android.sourceSets.main.java.sourceFiles
110 | }
111 |
112 | artifacts {
113 | archives androidSourcesJar
114 | archives androidJavadocsJar
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | VERSION_NAME=2.0.7
21 | VERSION_CODE=58
22 | GROUP=ai.api
23 |
24 | POM_DESCRIPTION=API.AI Android SDK allows using voice commands and integration with dialog scenarios defined for a particular agent in API.AI.
25 | POM_URL=https://github.com/speaktoit/api-ai-android-sdk
26 | POM_SCM_URL=https://github.com/speaktoit/api-ai-android-sdk
27 | POM_SCM_CONNECTION=scm:git@github.com:speaktoit/api-ai-android-sdk.git
28 | POM_SCM_DEV_CONNECTION=scm:git@github.com:speaktoit/api-ai-android-sdk.git
29 | POM_LICENCE_NAME=The Apache Software License, Version 2.0
30 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
31 |
32 | POM_LICENCE_DIST=repo
33 | POM_DEVELOPER_ID=speaktoit
34 | POM_DEVELOPER_NAME=Speaktoit
35 |
36 | ANDROID_BUILD_TARGET_SDK_VERSION=24
37 | ANDROID_BUILD_TOOLS_VERSION=25.0.1
38 | ANDROID_BUILD_SDK_VERSION=24
39 | ANDROID_BUILD_MIN_SDK_VERSION=8
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dialogflow/dialogflow-android-client/331f3ae8f2e404e245cc6024fdf44ec99feba7ee/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jul 07 09:45:50 NOVT 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':ailib', ':apiAISampleApp'
2 |
--------------------------------------------------------------------------------