Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os-example-mbed5-blinky by
Revision 45:2aa9f933c8d2, committed 2017-07-18
- Comitter:
- TMBOY
- Date:
- Tue Jul 18 16:34:48 2017 +0800
- Parent:
- 44:c1d8923072ba
- Child:
- 46:183cfc59d4e4
- Commit message:
- ?
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/.gitignore Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,55 @@ +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# Intellij +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/dictionaries +.idea/libraries + +# Keystore files +*.jks + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/LICENSE.txt Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/README.md Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,71 @@ +# DCS SDK(Java)开发者指南 + +## DCS协议 + +DCS协议是DuerOS服务端与设备端之间的通讯协议,是一套把DuerOS的智能语音交互能力向所有设备开放的API,了解详情请看[DCS协议文档](http://developer.dueros.baidu.com/doc/dueros-conversational-service/introduction_markdown)。 + +## 摘要 + +DCS SDK提供DCS协议在设备端的实现,旨在降低设备接入DuerOS的开发成本。DCS SDK是完整的Sample App,可以直接在目标设备运行,并且源代码全部开源,开发者可以基于源码进行二次开发。 + +本文档介绍的DCS SDK(Java)是Java版本的实现,该版本目前支持Android系统。 + +## 1-前置条件 + +a.完成注册百度账号、开发者认证和产品创建(选择手机场景和Android平台)后,请保存client_id和client_secret + + + +具体参考[控制台接入流程](http://developer.dueros.baidu.com/doc/overall/console-guide_markdown)。 + +b.在百度开发者中心配置OAuth的授权回调页 + 1. 到DuerOS开放平台控制台: http://developer.dueros.baidu.com/openduer/product/getproduct + 2. 点击所创建产品的“编辑”按钮,按钮在右侧 + 3. 点击OAUTH CONFIG URL,到百度开发者平台控制台 + 4. 在开发者平台控制台,点击左侧“安全设置” + 5. 在“授权回调页”输入框中输入"bdconnect://cancel,bdconnect://success"(不带双引号) + 6. 点击页面下方“确定”按钮 + +c.开发环境 + - Android Studio 2.2+ + - Gradle 2.2+ + - Android SDK 5.0+ (支持http/2) + - JDK 1.6+ + +## 2-克隆项目 + +```shell +git clone https://github.com/dueros/dcs-sdk-java.git +``` + +## 3-运行 + +a.通过Android Studio找到DcsSampleOAuthActivity.java,利用上述client_id进行替换 + + + +b.运行(Android真机) + + + +c.百度账号登录 + + + +## 4-唤醒 + +说“小度小度”,成功唤醒后进入“录音中”状态,如下图: + + + +## 5-和小度对话 + +a.通过唤醒或者单击“点击说话”进入录音状态, 问“北京天气怎么样”,DuerOS后端将发送stopListen指令,同时返回speak指令,播报北京天气。 + +b.问“播放刘若英的歌”, 返回play指令播放歌,可以从界面上进行“播放”、“暂停”、“上一首”和“下一首”操作。 + +## 6 SDK结构 + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/.gitignore Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,44 @@ +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# Intellij +*.iml +.idea/* + +# Keystore files +*.jks + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.idea/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/CMakeLists.txt Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,30 @@
+#指定CMake的最小版本
+cmake_minimum_required(VERSION 3.4.1)
+
+set(libs_DIR src/main/jniLibs/${ANDROID_ABI})
+
+set(libs_include_DIR src/main/cpp)
+
+#确保 CMake 可以在编译时定位您的标头文件以及源文件
+include_directories(${lib_include_DIR})
+
+link_directories(${libs_DIR})
+
+#添加我们自己的模块,名字是wakeup,SHARED可分享的,以及配置源文件或者头文件的路径
+add_library( wakeup
+ SHARED
+ src/main/cpp/wakeup.cpp
+ src/main/cpp/Interface.h
+ )
+#找到log这个模块
+find_library(log-lib
+ log
+ )
+#把我们自己的模块和动态库bdEASRAndroid模块,找到log这个模块,关联起来
+target_link_libraries(wakeup
+ bdEASRAndroid
+ ${log-lib}
+ )
+
+# 注意:bdEASRAndroid so库不要带版本号 比如:bdEASRAndroid.v1.10.10
+# jniLibs 里面也不要带版本号
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/build.gradle Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,73 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion "25.0.2"
+ defaultConfig {
+ applicationId "com.baidu.duer.dcs"
+ minSdkVersion 21
+ targetSdkVersion 22
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ externalNativeBuild {
+ cmake {
+ cppFlags "-std=c++11 -frtti -fexceptions -I/src/main/cpp"
+ }
+ }
+ ndk {
+ // 平台
+ abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a'
+ }
+ }
+ externalNativeBuild {
+ cmake {
+ path "CMakeLists.txt"
+ }
+ }
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['src/main/jniLibs']
+ }
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ packagingOptions {
+ exclude 'META-INF/DEPENDENCIES.txt'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/DEPENDENCIES'
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/dependencies.txt'
+ exclude 'META-INF/LGPL2.1'
+ exclude 'META-INF/ASL2.0'
+ }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ exclude group: 'com.android.support', module: 'support-annotations'
+ })
+ compile 'com.android.support:appcompat-v7:25.3.0'
+ compile 'com.android.support:design:25.3.0'
+ testCompile 'junit:junit:4.12'
+ compile files('libs/jackson-core-asl-1.9.13.jar')
+ compile files('libs/jackson-mapper-asl-1.9.13.jar')
+ compile files('libs/commons-fileupload-1.3.2.jar')
+ compile files('libs/commons-lang3-3.4.jar')
+ compile files('libs/commons-io-2.5.jar')
+ def okHttp3Version = '3.8.1'
+ compile('com.squareup.okhttp3:okhttp:' + okHttp3Version)
+ compile('com.squareup.okhttp3:logging-interceptor:' + okHttp3Version)
+
+ // debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
+}
Binary file dcs-sdk-java-master/app/libs/commons-fileupload-1.3.2.jar has changed
Binary file dcs-sdk-java-master/app/libs/commons-io-2.5.jar has changed
Binary file dcs-sdk-java-master/app/libs/commons-lang3-3.4.jar has changed
Binary file dcs-sdk-java-master/app/libs/jackson-core-asl-1.9.13.jar has changed
Binary file dcs-sdk-java-master/app/libs/jackson-mapper-asl-1.9.13.jar has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/proguard-rules.pro Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in D:\AppData\android-sdk-windows/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/AndroidManifest.xml Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,45 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.baidu.duer.dcs"> + + <uses-permission android:name="android.permission.RECORD_AUDIO" /> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.READ_PHONE_STATE"/> + + <application + android:name="com.baidu.duer.dcs.androidapp.DcsSampleApplication" + android:allowBackup="true" + android:icon="@mipmap/ic_launcher" + android:label="@string/app_name" + android:supportsRtl="true" + android:theme="@style/AppTheme"> + + <activity + android:name="com.baidu.duer.dcs.androidapp.DcsSampleOAuthActivity" + android:label="@string/app_name" + android:screenOrientation="portrait" + android:theme="@style/AppTheme.NoActionBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <activity + android:name="com.baidu.duer.dcs.androidapp.DcsSampleMainActivity" + android:label="@string/app_name" + android:screenOrientation="portrait" + android:theme="@style/AppTheme.NoActionBar" /> + <activity + android:name="com.baidu.duer.dcs.androidapp.DcsSampleScreenHtmlActivity" + android:label="@string/app_name" + android:screenOrientation="portrait" + android:theme="@style/AppTheme.NoActionBar" /> + </application> + +</manifest>
Binary file dcs-sdk-java-master/app/src/main/assets/alarm.mp3 has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/cpp/Interface.h Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,107 @@ + +#ifndef _EASR_INTERFACE_ +#define _EASR_INTERFACE_ + +int GetEngineVersion(); +int SetLogLevel(int level); +int SetTimeLogFile(const char* fn); +int SetSampleRateMode(int mode); +bool ExistFile(const char* file); +int GetDataDate(const char* fn); +int GetResLine(const char* fn); +int GetResVersion(const char* fn); +bool CheckDataMD5(const char* fn); +int DisableSSE4(); + +int ClearRes(); +int Free(); +int Initial(); +int Initial(const char* dictFile, const char* userFile, const char* mmfFile, const char* hmmMapFile, + short acoustic_model_mode=1,bool fastMode=false); +int BuildNet(int netTreeID,const char* synFile); +int WriteWdNonPron(const char* outFile); + +int BuildSlot(char* buffer,long len); +int ReadSlot(const char* slotFile); +int ReadSlotLink(const char* slotLinkFile); +int ReadLM(const char* lmFn,const char* slotName,bool needBuildSlot); +int LoadRes(const char* lmFn,const char* lmSlotName,const char* slotFile,const char* slotLinkFile); + +int SetVADEndCut(int id,bool vadEdForCut); +int InitialDecoder(int id,int vadID,int nBeam,double prunThres); +int ResetDecoder(int id); +int SetCurrNetTreeID(int id,int treeID,int mode=0); +int Fep(int id,short* data, int dataLen, bool bEd); +int Rec(int id, char** senArr, int expectNum); +char* GetImmeSentence(int id,int& frame); + +char* DecodeAlways(int id,short* data, int dataLen, bool bEd); + +int InitialMem(); +int InitialVAD(int id,float max_speech_len,float max_speech_pause_len); +int ResetVAD(int id); +int VADDetect(int id,short* data, int dataLen, bool bEd); +int GetVadSt(int id); +int GetVadEd(int id); +long int get_dect_end_point_time(int id); + +int KWSSetParam(int type,float value); +int KWSInitial(const char* kwdSynStr,const char* sFile,const char* resDir,int mode = 0); +int KWSReset(int* sceneArr,int n); +int KWSDecode(short* data, int dataLen, char** kwdArr, int expectNum, bool bEd); +int KWSDecode(short* data, int dataLen, char* outJsonStr, bool bEd); +int KWSFree(); + +int AudioSegReset(); +int AudioSegFree(); +int AudioSegInitial(const char* sFile,int mode=0); +int AudioSegDetect(short* data, int dataLen, bool bEd, int& spSt, int& spEd); +int AudioSegDetect(short* data, int dataLen, bool bEd, int& spSt, int& spEd, int *pauseEd); +float AudioSeggetSilConfidence(int contextLen); +int setParam(int function, int type, float value); //function: 1 = audioSeg +int AudioSegGetDelayFrameNum(); + +int WakeUpInitial(const char* wakeUpWd,const char* sFile,int mode=0); +int WakeUpReset(); +int WakeUpDecode(short* data, int dataLen, char** senArr, int expectNum, bool bEd); +int WakeUpDecode(short* data, int dataLen, char** senArr, int expectNum, int &wakeword_frame_len, bool bEd); +int WakeUpDecode(short* data, int dataLen, char** senArr, int expectNum, int &wakeword_frame_len, + bool &is_confidence, int &voice_offset, bool bEd); +int WakeUpFree(); +int WakeUpSetEnvironment(int status);//0 is quiet,else is noise + +int AECInit(); +int AECReset(); +short* AECProcess(short* data_in,short* wav_ref,long len_in); +int AECExit(); + +int GetPyED(const char* str1,const char* str2); +int GetStateED(const char* str1,const char* str2); + +extern char* ChnNameSegPreProcess(const char* aNameArr,const char* aResFileName); +extern char* EngNamePronPreProcess(const char* aNameArr); + +int SetLicenseFlag(bool lic_flag); +bool GetLicenseFlag(); + +#ifdef _ANDROID_ +#include <jni.h> +int GetLicense(JNIEnv *env, jclass obj,jobject context,jstring appCode,jstring cuid,jstring stat,jstring license_file); +int VerifyLicense(JNIEnv *env,jobject context,jstring appCode,jstring cuid,jbyteArray license,jint len,jbyteArray appIDSeq,jstring logDir); +#else +#ifdef _IOS_ +int GetLicense(const char* appCode,const char* stat,const char* license_file); +int VerifyLicense(const char* appCode,const char* license,int len,unsigned int& appID,const char* logDir); +#else //x86 +int GetLicense(const char* appName,const char* appCode,const char* stat,const char* license_file); +int VerifyLicense(const char* appName,const char* appCode,const char* license,int len,unsigned int& appID,const char* logDir); +#endif +#endif +int OpenPVUpload(); +int ClosePVUpload(); +int GetTestAuthorize(); +int GetLongAuthorize(); +bool GetAuthorize(); + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/cpp/wakeup.cpp Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * 唤醒调用底层so库实现-jni
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/22.
+ */
+#include <jni.h>
+#include "Interface.h"
+#include <android/log.h>
+
+#define LOG_TAG "wakeup"
+#define LOG_D(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+
+
+extern "C"
+JNIEXPORT jint JNICALL
+Java_com_baidu_duer_dcs_androidsystemimpl_wakeup_WakeUpNative_wakeUpInitial(JNIEnv *env,
+ jobject instance,
+ jstring wakeUpWd_,
+ jstring sFile_,
+ jint mode) {
+ const char *wakeUpWd = env->GetStringUTFChars(wakeUpWd_, 0);
+ const char *sFile = env->GetStringUTFChars(sFile_, 0);
+
+ int _mode = mode;
+ // 打开log
+ // SetLogLevel(5);
+ LOG_D("WakeUpInitial wakeUpWd=%s", wakeUpWd);
+ LOG_D("WakeUpInitial sFile_=%s", sFile);
+ int ret = WakeUpInitial(wakeUpWd, sFile, _mode);
+ LOG_D("WakeUpInitial ret=%d", ret);
+
+ env->ReleaseStringUTFChars(wakeUpWd_, wakeUpWd);
+ env->ReleaseStringUTFChars(sFile_, sFile);
+
+ return ret;
+}
+
+extern "C"
+JNIEXPORT jint JNICALL
+Java_com_baidu_duer_dcs_androidsystemimpl_wakeup_WakeUpNative_wakeUpReset(JNIEnv *env,
+ jobject instance) {
+ return WakeUpReset();
+}
+
+extern "C"
+JNIEXPORT jint JNICALL
+Java_com_baidu_duer_dcs_androidsystemimpl_wakeup_WakeUpNative_wakeUpDecode(JNIEnv *env,
+ jobject instance,
+ jshortArray data_,
+ jint dataLen,
+ jstring senArr_,
+ jint expectNum,
+ jint wakeWord_frame_len,
+ jboolean is_confidence,
+ jint voice_offset,
+ jboolean bEd) {
+
+
+ jboolean isCopy = 0;
+ short *data_invoke = env->GetShortArrayElements(data_, &isCopy);
+
+ // 写入文件
+ // FILE *file = fopen("/storage/emulated/0/222.pcm", "ab+");
+ // fwrite(data_invoke, sizeof(short) * dataLen, 1, file);
+ // fclose(file);
+
+ LOG_D("WakeUpDecode data_ GetArrayLength=%d", env->GetArrayLength(data_));
+
+ int dataLen_invoke = dataLen;
+ // 因为so库里面最大为2560
+ char *senArr = new char[2560];
+ int expectNum_invoke = expectNum;
+ int wakeWord_frame_len_invoke = wakeWord_frame_len;
+ bool is_confidence_invoke = is_confidence;
+ int voice_offset_invoke = voice_offset;
+ bool bEd_invoke = bEd;
+
+ LOG_D("WakeUpDecode dataLen_invoke=%d", dataLen_invoke);
+ LOG_D("WakeUpDecode expectNum_invoke=%d", expectNum_invoke);
+ LOG_D("WakeUpDecode wakeWord_frame_len_invoke=%d", wakeWord_frame_len_invoke);
+ LOG_D("WakeUpDecode is_confidence_invoke=%d", is_confidence_invoke);
+ LOG_D("WakeUpDecode bEd_invoke=%d", bEd_invoke);
+
+
+ int ret = WakeUpDecode(data_invoke,
+ dataLen_invoke,
+ &senArr,
+ expectNum_invoke,
+ wakeWord_frame_len_invoke,
+ is_confidence_invoke,
+ voice_offset_invoke,
+ bEd_invoke
+ );
+
+ LOG_D("WakeUpDecode ret=%d", ret);
+ LOG_D("WakeUpDecode senArr=%s", senArr);
+ LOG_D("WakeUpDecode wakeWord_frame_len_invoke=%d", wakeWord_frame_len_invoke);
+ LOG_D("WakeUpDecode is_confidence_invoke=%d", is_confidence_invoke);
+ LOG_D("WakeUpDecode voice_offset_invoke=%d", voice_offset_invoke);
+
+ // 释放内存资源
+ env->ReleaseShortArrayElements(data_, data_invoke, 0);
+ env->ReleaseStringUTFChars(senArr_, senArr);
+ return ret;
+}
+
+extern "C"
+JNIEXPORT jint JNICALL
+Java_com_baidu_duer_dcs_androidsystemimpl_wakeup_WakeUpNative_wakeUpFree(JNIEnv *env,
+ jobject instance) {
+ LOG_D("WakeUpFree");
+ return WakeUpFree();
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleApplication.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidapp;
+
+import android.app.Application;
+
+/**
+ * DcsSample application
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/11.
+ */
+public class DcsSampleApplication extends Application {
+ private static volatile DcsSampleApplication instance = null;
+
+ public void onCreate() {
+ super.onCreate();
+ instance = this;
+ // LeakCanary.install(this);
+ }
+
+ public static DcsSampleApplication getInstance() {
+ return instance;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleBaseActivity.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidapp;
+
+import android.app.Activity;
+
+/**
+ * 基础base activity
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/18.
+ */
+public class DcsSampleBaseActivity extends Activity {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleMainActivity.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidapp;
+
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.webkit.WebView;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.baidu.duer.dcs.R;
+import com.baidu.duer.dcs.androidsystemimpl.PlatformFactoryImpl;
+import com.baidu.duer.dcs.androidsystemimpl.webview.BaseWebView;
+import com.baidu.duer.dcs.devicemodule.voiceinput.VoiceInputDeviceModule;
+import com.baidu.duer.dcs.framework.DcsFramework;
+import com.baidu.duer.dcs.framework.DeviceModuleFactory;
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.http.HttpConfig;
+import com.baidu.duer.dcs.oauth.api.IOauth;
+import com.baidu.duer.dcs.oauth.api.OauthImpl;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.systeminterface.IWakeUp;
+import com.baidu.duer.dcs.util.CommonUtil;
+import com.baidu.duer.dcs.util.FileUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+import com.baidu.duer.dcs.util.NetWorkUtil;
+import com.baidu.duer.dcs.wakeup.WakeUp;
+
+import java.io.File;
+
+/**
+ * 主界面 activity
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/18.
+ */
+public class DcsSampleMainActivity extends DcsSampleBaseActivity implements View.OnClickListener {
+ public static final String TAG = "DcsDemoActivity";
+ private Button voiceButton;
+ private TextView textViewTimeStopListen;
+ private Button pauseOrPlayButton;
+ private BaseWebView webView;
+ private LinearLayout mTopLinearLayout;
+ private DcsFramework dcsFramework;
+ private DeviceModuleFactory deviceModuleFactory;
+ private IPlatformFactory platformFactory;
+ private boolean isPause = true;
+ private long startTimeStopListen;
+ private boolean isStopListenReceiving;
+ private String mHtmlUrl;
+ // 唤醒
+ private WakeUp wakeUp;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.dcs_sample_activity_main);
+ initView();
+ initOauth();
+ initFramework();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ initOauth();
+ }
+
+ private void initView() {
+ Button openLogBtn = (Button) findViewById(R.id.openLogBtn);
+ openLogBtn.setOnClickListener(this);
+ voiceButton = (Button) findViewById(R.id.voiceBtn);
+ voiceButton.setOnClickListener(this);
+
+ textViewTimeStopListen = (TextView) findViewById(R.id.id_tv_time_0);
+ mTopLinearLayout = (LinearLayout) findViewById(R.id.topLinearLayout);
+
+ webView = new BaseWebView(DcsSampleMainActivity.this.getApplicationContext());
+ webView.setWebViewClientListen(new BaseWebView.WebViewClientListener() {
+ @Override
+ public BaseWebView.LoadingWebStatus shouldOverrideUrlLoading(WebView view, String url) {
+ // 拦截处理不让其点击
+ return BaseWebView.LoadingWebStatus.STATUS_TRUE;
+ }
+
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ if (!url.equals(mHtmlUrl) && !"about:blank".equals(mHtmlUrl)) {
+ platformFactory.getWebView().linkClicked(url);
+ }
+
+ mHtmlUrl = url;
+ }
+
+ @Override
+ public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+
+ }
+ });
+ mTopLinearLayout.addView(webView);
+ webView.loadUrl("about:blank");
+
+ Button mPreviousSongBtn = (Button) findViewById(R.id.previousSongBtn);
+ pauseOrPlayButton = (Button) findViewById(R.id.pauseOrPlayBtn);
+ Button mNextSongBtn = (Button) findViewById(R.id.nextSongBtn);
+ mPreviousSongBtn.setOnClickListener(this);
+ pauseOrPlayButton.setOnClickListener(this);
+ mNextSongBtn.setOnClickListener(this);
+ }
+
+ private void initFramework() {
+ platformFactory = new PlatformFactoryImpl(this);
+ platformFactory.setWebView(webView);
+ dcsFramework = new DcsFramework(platformFactory);
+ deviceModuleFactory = dcsFramework.getDeviceModuleFactory();
+
+ deviceModuleFactory.createVoiceOutputDeviceModule();
+ deviceModuleFactory.createVoiceInputDeviceModule();
+ deviceModuleFactory.getVoiceInputDeviceModule().addVoiceInputListener(
+ new VoiceInputDeviceModule.IVoiceInputListener() {
+ @Override
+ public void onStartRecord() {
+ LogUtil.d(TAG, "onStartRecord");
+ startRecording();
+ }
+
+ @Override
+ public void onFinishRecord() {
+ LogUtil.d(TAG, "onFinishRecord");
+ stopRecording();
+ }
+
+ public void onSucceed(int statusCode) {
+ LogUtil.d(TAG, "onSucceed-statusCode:" + statusCode);
+ if (statusCode != 200) {
+ stopRecording();
+ Toast.makeText(DcsSampleMainActivity.this,
+ getResources().getString(R.string.voice_err_msg),
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
+
+ @Override
+ public void onFailed(String errorMessage) {
+ LogUtil.d(TAG, "onFailed-errorMessage:" + errorMessage);
+ stopRecording();
+ Toast.makeText(DcsSampleMainActivity.this,
+ getResources().getString(R.string.voice_err_msg),
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ });
+
+ deviceModuleFactory.createAlertsDeviceModule();
+
+ deviceModuleFactory.createAudioPlayerDeviceModule();
+ deviceModuleFactory.getAudioPlayerDeviceModule().addAudioPlayListener(
+ new IMediaPlayer.SimpleMediaPlayerListener() {
+ @Override
+ public void onPaused() {
+ super.onPaused();
+ pauseOrPlayButton.setText(getResources().getString(R.string.audio_paused));
+ isPause = true;
+ }
+
+ @Override
+ public void onPlaying() {
+ super.onPlaying();
+ pauseOrPlayButton.setText(getResources().getString(R.string.audio_playing));
+ isPause = false;
+ }
+
+ @Override
+ public void onCompletion() {
+ super.onCompletion();
+ pauseOrPlayButton.setText(getResources().getString(R.string.audio_default));
+ isPause = false;
+ }
+
+ @Override
+ public void onStopped() {
+ super.onStopped();
+ pauseOrPlayButton.setText(getResources().getString(R.string.audio_default));
+ isPause = true;
+ }
+ });
+
+ deviceModuleFactory.createSystemDeviceModule();
+ deviceModuleFactory.createSpeakControllerDeviceModule();
+ deviceModuleFactory.createPlaybackControllerDeviceModule();
+ deviceModuleFactory.createScreenDeviceModule();
+
+ // init唤醒
+ wakeUp = new WakeUp(platformFactory.getWakeUp(),
+ platformFactory.getAudioRecord());
+ wakeUp.addWakeUpListener(wakeUpListener);
+ // 开始录音,监听是否说了唤醒词
+ wakeUp.startWakeUp();
+ }
+
+ private IWakeUp.IWakeUpListener wakeUpListener = new IWakeUp.IWakeUpListener() {
+ @Override
+ public void onWakeUpSucceed() {
+ Toast.makeText(DcsSampleMainActivity.this,
+ getResources().getString(R.string.wakeup_succeed),
+ Toast.LENGTH_SHORT)
+ .show();
+ voiceButton.performClick();
+ }
+ };
+
+ private void doUserActivity() {
+ deviceModuleFactory.getSystemProvider().userActivity();
+ }
+
+ private void initOauth() {
+ IOauth baiduOauth = new OauthImpl();
+ if (baiduOauth.isSessionValid()) {
+ HttpConfig.setAccessToken(baiduOauth.getAccessToken());
+ } else {
+ baiduOauth.authorize();
+ }
+ }
+
+ private void stopRecording() {
+ wakeUp.startWakeUp();
+ isStopListenReceiving = false;
+ voiceButton.setText(getResources().getString(R.string.stop_record));
+ long t = System.currentTimeMillis() - startTimeStopListen;
+ textViewTimeStopListen.setText(getResources().getString(R.string.time_record, t));
+ }
+
+ private void startRecording() {
+ wakeUp.stopWakeUp();
+ isStopListenReceiving = true;
+ deviceModuleFactory.getSystemProvider().userActivity();
+ voiceButton.setText(getResources().getString(R.string.start_record));
+ textViewTimeStopListen.setText("");
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.voiceBtn:
+ if (!NetWorkUtil.isNetworkConnected(this)) {
+ Toast.makeText(this,
+ getResources().getString(R.string.err_net_msg),
+ Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (CommonUtil.isFastDoubleClick()) {
+ return;
+ }
+ if (isStopListenReceiving) {
+ platformFactory.getVoiceInput().stopRecord();
+ isStopListenReceiving = false;
+ return;
+ }
+ isStopListenReceiving = true;
+ startTimeStopListen = System.currentTimeMillis();
+ platformFactory.getVoiceInput().startRecord();
+ doUserActivity();
+ break;
+ case R.id.openLogBtn:
+ openAssignFolder(FileUtil.getLogFilePath());
+ break;
+ case R.id.previousSongBtn:
+ platformFactory.getPlayback().previous(nextPreResponseListener);
+ doUserActivity();
+ break;
+ case R.id.nextSongBtn:
+ platformFactory.getPlayback().next(nextPreResponseListener);
+ doUserActivity();
+ break;
+ case R.id.pauseOrPlayBtn:
+ if (isPause) {
+ platformFactory.getPlayback().play(playPauseResponseListener);
+ } else {
+ platformFactory.getPlayback().pause(playPauseResponseListener);
+ }
+ doUserActivity();
+ break;
+ default:
+ break;
+ }
+ }
+
+ private IResponseListener playPauseResponseListener = new IResponseListener() {
+ @Override
+ public void onSucceed(int statusCode) {
+ if (statusCode == 204) {
+ Toast.makeText(DcsSampleMainActivity.this,
+ getResources().getString(R.string.no_directive),
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
+
+ @Override
+ public void onFailed(String errorMessage) {
+ Toast.makeText(DcsSampleMainActivity.this,
+ getResources().getString(R.string.request_error),
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ };
+
+ private IResponseListener nextPreResponseListener = new IResponseListener() {
+ @Override
+ public void onSucceed(int statusCode) {
+ if (statusCode == 204) {
+ Toast.makeText(DcsSampleMainActivity.this,
+ getResources().getString(R.string.no_audio),
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
+
+ @Override
+ public void onFailed(String errorMessage) {
+ Toast.makeText(DcsSampleMainActivity.this,
+ getResources().getString(R.string.request_error),
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+ };
+
+ /**
+ * 打开日志
+ *
+ * @param path 文件的绝对路径
+ */
+ private void openAssignFolder(String path) {
+ File file = new File(path);
+ if (!file.exists()) {
+ Toast.makeText(DcsSampleMainActivity.this,
+ getResources().getString(R.string.no_log),
+ Toast.LENGTH_SHORT)
+ .show();
+ return;
+ }
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setDataAndType(Uri.fromFile(file), "text/plain");
+ try {
+ startActivity(Intent.createChooser(intent,
+ getResources().getString(R.string.open_file_title)));
+ } catch (ActivityNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ // 先remove listener 停止唤醒,释放资源
+ wakeUp.removeWakeUpListener(wakeUpListener);
+ wakeUp.stopWakeUp();
+ wakeUp.releaseWakeUp();
+
+ if (dcsFramework != null) {
+ dcsFramework.release();
+ }
+ webView.setWebViewClientListen(null);
+ mTopLinearLayout.removeView(webView);
+ webView.removeAllViews();
+ webView.destroy();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleOAuthActivity.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidapp;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.baidu.duer.dcs.R;
+import com.baidu.duer.dcs.oauth.api.BaiduDialog;
+import com.baidu.duer.dcs.oauth.api.BaiduDialogError;
+import com.baidu.duer.dcs.oauth.api.BaiduException;
+import com.baidu.duer.dcs.oauth.api.BaiduOauthImplicitGrant;
+import com.baidu.duer.dcs.util.LogUtil;
+
+/**
+ * 用户认证界面
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/18.
+ */
+public class DcsSampleOAuthActivity extends DcsSampleBaseActivity implements View.OnClickListener {
+ // 需要开发者自己申请client_id
+ // client_id,就是oauth的client_id
+ private static final String CLIENT_ID = "{{nc72pRBp2VbSBZk0LSvqHGjFrbjOvQNH}}";
+ // 是否每次授权都强制登陆
+ private boolean isForceLogin = false;
+ // 是否每次都确认登陆
+ private boolean isConfirmLogin = true;
+ private EditText editTextClientId;
+ private Button oauthLoginButton;
+ private BaiduOauthImplicitGrant baiduOauthImplicitGrant;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.dcs_sample_activity_oauth);
+ initView();
+ setOnClickListener();
+ }
+
+ private void setOnClickListener() {
+ oauthLoginButton.setOnClickListener(this);
+ }
+
+ private void initView() {
+ editTextClientId = (EditText) findViewById(R.id.edit_client_id);
+ oauthLoginButton = (Button) findViewById(R.id.btn_login);
+
+ editTextClientId.setText(CLIENT_ID);
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.btn_login:
+ String clientId = editTextClientId.getText().toString();
+ if (!TextUtils.isEmpty(clientId) && !TextUtils.isEmpty(clientId)) {
+ baiduOauthImplicitGrant = new BaiduOauthImplicitGrant(clientId, DcsSampleOAuthActivity.this.getApplication());
+ baiduOauthImplicitGrant.authorize(DcsSampleOAuthActivity.this, isForceLogin, isConfirmLogin, new BaiduDialog
+ .BaiduDialogListener() {
+ @Override
+ public void onComplete(Bundle values) {
+ Toast.makeText(DcsSampleOAuthActivity.this.getApplicationContext(),
+ getResources().getString(R.string.login_succeed),
+ Toast.LENGTH_SHORT).show();
+ startMainActivity();
+ }
+
+ @Override
+ public void onBaiduException(BaiduException e) {
+
+ }
+
+ @Override
+ public void onError(BaiduDialogError e) {
+ if (null != e) {
+ String toastString = TextUtils.isEmpty(e.getMessage())
+ ? DcsSampleOAuthActivity.this.getResources()
+ .getString(R.string.err_net_msg) : e.getMessage();
+ Toast.makeText(DcsSampleOAuthActivity.this.getApplicationContext(), toastString,
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onCancel() {
+ LogUtil.d("cancle", "I am back");
+ }
+ });
+ } else {
+ Toast.makeText(DcsSampleOAuthActivity.this.getApplicationContext(),
+ getResources().getString(R.string.client_id_empty),
+ Toast.LENGTH_SHORT).show();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void startMainActivity() {
+ Intent intent = new Intent(DcsSampleOAuthActivity.this, DcsSampleMainActivity.class);
+ intent.putExtra("baidu", baiduOauthImplicitGrant);
+ startActivity(intent);
+ finish();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleScreenHtmlActivity.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidapp;
+
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.webkit.WebView;
+import android.widget.RelativeLayout;
+
+import com.baidu.duer.dcs.R;
+import com.baidu.duer.dcs.androidsystemimpl.webview.BaseWebView;
+import com.baidu.duer.dcs.devicemodule.screen.message.HtmlPayload;
+
+/**
+ * show html UI.
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/31.
+ */
+public class DcsSampleScreenHtmlActivity extends DcsSampleBaseActivity {
+ private HtmlPayload htmlPayLoad;
+ private RelativeLayout relativeLayout;
+ private BaseWebView webView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.dcs_sample_activity_screen_html);
+ htmlPayLoad = (HtmlPayload) this.getIntent().getSerializableExtra("HTML_PLAY_LOAD");
+ initView();
+ addView();
+ }
+
+ private void initView() {
+ relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
+ }
+
+ private void addView() {
+ webView = new BaseWebView(DcsSampleScreenHtmlActivity.this.getApplicationContext());
+ webView.setWebViewClientListen(new BaseWebView.WebViewClientListener() {
+ @Override
+ public BaseWebView.LoadingWebStatus shouldOverrideUrlLoading(WebView view, String url) {
+ return BaseWebView.LoadingWebStatus.STATUS_UNKNOW;
+ }
+
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+
+ }
+
+ @Override
+ public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+
+ }
+ });
+ relativeLayout.addView(webView);
+ if (null != htmlPayLoad) {
+ webView.loadUrl(htmlPayLoad.getUrl());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/AudioRecordThread.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,84 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl;
+
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+
+import com.baidu.duer.dcs.systeminterface.IAudioRecord;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * 录音采集线程-音频数据生产者
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/26.
+ */
+public class AudioRecordThread extends Thread implements IAudioRecord {
+ private static final String TAG = AudioRecordThread.class.getSimpleName();
+ // 采样率
+ private static final int SAMPLE_RATE_HZ = 16000;
+ private int bufferSize;
+ private AudioRecord audioRecord;
+ private volatile boolean isStartRecord = false;
+ private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+
+ public AudioRecordThread(LinkedBlockingDeque<byte[]> linkedBlockingDeque) {
+ this.linkedBlockingDeque = linkedBlockingDeque;
+ bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE_HZ, AudioFormat.CHANNEL_IN_MONO,
+ AudioFormat.ENCODING_PCM_16BIT);
+ audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE_HZ, AudioFormat.CHANNEL_IN_MONO,
+ AudioFormat.ENCODING_PCM_16BIT, bufferSize);
+ }
+
+ @Override
+ public void startRecord() {
+ if (isStartRecord) {
+ return;
+ }
+ isStartRecord = true;
+ this.start();
+ }
+
+ @Override
+ public void stopRecord() {
+ isStartRecord = false;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ LogUtil.i(TAG, "audioRecord startRecording ");
+ audioRecord.startRecording();
+ byte[] buffer = new byte[bufferSize];
+ while (isStartRecord) {
+ int readBytes = audioRecord.read(buffer, 0, bufferSize);
+ if (readBytes > 0) {
+ linkedBlockingDeque.add(buffer);
+ }
+ }
+ // 清空数据
+ linkedBlockingDeque.clear();
+ // 释放资源
+ audioRecord.stop();
+ audioRecord.release();
+ audioRecord = null;
+ LogUtil.i(TAG, "audioRecord release ");
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/HandlerImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import com.baidu.duer.dcs.systeminterface.IHandler;
+
+/**
+ * Created by wuruisheng on 2017/6/7.
+ */
+public class HandlerImpl implements IHandler {
+ private final Handler handler;
+
+ public HandlerImpl() {
+ handler = new Handler();
+ }
+
+ public HandlerImpl(Looper looper) {
+ handler = new Handler(looper);
+ }
+
+ @Override
+ public boolean post(Runnable runnable) {
+ return handler.post(runnable);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/PlatformFactoryImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl;
+
+import android.content.Context;
+import android.os.Looper;
+
+import com.baidu.duer.dcs.androidsystemimpl.alert.AlertsFileDataStoreImpl;
+import com.baidu.duer.dcs.androidsystemimpl.audioinput.AudioVoiceInputImpl;
+import com.baidu.duer.dcs.androidsystemimpl.playbackcontroller.IPlaybackControllerImpl;
+import com.baidu.duer.dcs.androidsystemimpl.player.MediaPlayerImpl;
+import com.baidu.duer.dcs.androidsystemimpl.wakeup.WakeUpImpl;
+import com.baidu.duer.dcs.systeminterface.IAlertsDataStore;
+import com.baidu.duer.dcs.systeminterface.IAudioInput;
+import com.baidu.duer.dcs.systeminterface.IAudioRecord;
+import com.baidu.duer.dcs.systeminterface.IHandler;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.systeminterface.IPlaybackController;
+import com.baidu.duer.dcs.systeminterface.IWakeUp;
+import com.baidu.duer.dcs.systeminterface.IWebView;
+
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * Created by wuruisheng on 2017/6/7.
+ */
+public class PlatformFactoryImpl implements IPlatformFactory {
+ private IHandler mainHandler;
+ private IAudioInput voiceInput;
+ private IWebView webView;
+ private IPlaybackController playback;
+ private Context context;
+ private IAudioRecord audioRecord;
+ private LinkedBlockingDeque<byte[]> linkedBlockingDeque = new LinkedBlockingDeque<>();
+
+ public PlatformFactoryImpl(Context context) {
+ this.context = context.getApplicationContext();
+ }
+
+ @Override
+ public IHandler createHandler() {
+ return new HandlerImpl();
+ }
+
+ @Override
+ public IHandler getMainHandler() {
+ if (mainHandler == null) {
+ mainHandler = new HandlerImpl(Looper.getMainLooper());
+ }
+
+ return mainHandler;
+ }
+
+ @Override
+ public IAudioRecord getAudioRecord() {
+ if (audioRecord == null) {
+ audioRecord = new AudioRecordThread(linkedBlockingDeque);
+ }
+ return audioRecord;
+ }
+
+ @Override
+ public IWakeUp getWakeUp() {
+ return new WakeUpImpl(context, linkedBlockingDeque);
+ }
+
+ @Override
+ public IAudioInput getVoiceInput() {
+ if (voiceInput == null) {
+ voiceInput = new AudioVoiceInputImpl(linkedBlockingDeque);
+ }
+
+ return voiceInput;
+ }
+
+ @Override
+ public IMediaPlayer createMediaPlayer() {
+ return new MediaPlayerImpl();
+ }
+
+ public IAlertsDataStore createAlertsDataStore() {
+ return new AlertsFileDataStoreImpl();
+ }
+
+ @Override
+ public IWebView getWebView() {
+ return webView;
+ }
+
+ @Override
+ public IPlaybackController getPlayback() {
+ if (playback == null) {
+ playback = new IPlaybackControllerImpl();
+ }
+
+ return playback;
+ }
+
+ public void setWebView(IWebView webView) {
+ this.webView = webView;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/alert/AlertsFileDataStoreImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.alert;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.Alert;
+import com.baidu.duer.dcs.systeminterface.IAlertsDataStore;
+import com.baidu.duer.dcs.util.CommonUtil;
+import com.baidu.duer.dcs.util.FileUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+import com.baidu.duer.dcs.util.ObjectMapperUtil;
+
+import org.codehaus.jackson.map.ObjectReader;
+import org.codehaus.jackson.map.ObjectWriter;
+import org.codehaus.jackson.type.TypeReference;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * 持久化alert数据到文件-android中实现
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/18.
+ */
+public class AlertsFileDataStoreImpl implements IAlertsDataStore {
+ private static final String TAG = AlertsFileDataStoreImpl.class.getSimpleName();
+ private static final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+ private Handler mHandler = new Handler();
+
+ public AlertsFileDataStoreImpl() {
+ }
+
+ @Override
+ public void readFromDisk(final IAlertsDataStore.ReadResultListener listener) {
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ FileReader fis;
+ BufferedReader br = null;
+ ObjectReader reader = ObjectMapperUtil.instance()
+ .getObjectReader()
+ .withType(new TypeReference<List<Alert>>() {
+ });
+ try {
+ File file = FileUtil.getAlarmFile();
+ if (file == null) {
+ postReadFailed(listener, "create file failed file is null");
+ return;
+ }
+ fis = new FileReader(file);
+ br = new BufferedReader(fis);
+ List<Alert> alerts = reader.readValue(br);
+ postReadSucceed(listener, alerts);
+ } catch (final FileNotFoundException e) {
+ postReadFailed(listener, "Failed to load alerts from disk.");
+ } catch (IOException e) {
+ postReadFailed(listener, e.getMessage());
+ } finally {
+ CommonUtil.closeQuietly(br);
+ }
+ }
+ });
+ }
+
+ private void postReadFailed(final IAlertsDataStore.ReadResultListener listener, final String errorMessage) {
+ if (listener != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onFailed(errorMessage);
+ }
+ });
+ }
+ }
+
+ private void postReadSucceed(final IAlertsDataStore.ReadResultListener listener, final List<Alert> alerts) {
+ if (listener != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onSucceed(alerts);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void writeToDisk(final List<Alert> alerts, final IAlertsDataStore.WriteResultListener listener) {
+ mExecutor.execute(new Runnable() {
+
+ @Override
+ public void run() {
+ ObjectWriter writer = ObjectMapperUtil.instance().getObjectWriter();
+ PrintWriter out = null;
+ try {
+ File file = FileUtil.getAlarmFile();
+ if (file == null) {
+ postWriteFailed(listener, "create file failed file is null ");
+ return;
+ }
+ out = new PrintWriter(file);
+ out.print(writer.writeValueAsString(alerts));
+ out.flush();
+ LogUtil.e(TAG, "start postWriteSucceed");
+ postWriteSucceed(listener);
+ } catch (IOException e) {
+ LogUtil.e(TAG, "Failed to write to disk", e);
+ postWriteFailed(listener, "Failed to write to disk,error:" + e.getMessage());
+ } finally {
+ CommonUtil.closeQuietly(out);
+ }
+ }
+ });
+ }
+
+ private void postWriteFailed(final IAlertsDataStore.WriteResultListener listener, final String errorMessage) {
+ if (listener != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onFailed(errorMessage);
+ }
+ });
+ }
+ }
+
+ private void postWriteSucceed(final IAlertsDataStore.WriteResultListener listener) {
+ if (listener != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onSucceed();
+ }
+ });
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/audioinput/AudioVoiceInputImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,71 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.audioinput;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.systeminterface.IAudioInput;
+
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * AudioInput实现,控制麦克风获取语音数据流
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/26.
+ */
+public class AudioVoiceInputImpl implements IAudioInput {
+ // 消费线程
+ private AudioVoiceInputThread audioVoiceInputThread;
+ // 音频数据
+ private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+ private IAudioInputListener audioInputListener;
+ private Handler handler = new Handler();
+
+ public AudioVoiceInputImpl(LinkedBlockingDeque<byte[]> linkedBlockingDeque) {
+ this.linkedBlockingDeque = linkedBlockingDeque;
+ }
+
+ @Override
+ public void startRecord() {
+ DcsStreamRequestBody dcsStreamRequestBody = new DcsStreamRequestBody();
+ audioInputListener.onStartRecord(dcsStreamRequestBody);
+ audioVoiceInputThread = new AudioVoiceInputThread(
+ linkedBlockingDeque,
+ dcsStreamRequestBody.sink(),
+ handler);
+ audioVoiceInputThread.setAudioInputListener(new AudioVoiceInputThread.IAudioInputListener() {
+ @Override
+ public void onWriteFinished() {
+ if (audioInputListener != null) {
+ audioInputListener.onStopRecord();
+ }
+ }
+ });
+ audioVoiceInputThread.startWriteStream();
+ }
+
+ @Override
+ public void stopRecord() {
+ audioVoiceInputThread.stopWriteStream();
+ }
+
+ @Override
+ public void registerAudioInputListener(IAudioInputListener audioInputListener) {
+ this.audioInputListener = audioInputListener;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/audioinput/AudioVoiceInputThread.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,131 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.audioinput;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.IOException;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import okio.BufferedSink;
+
+/**
+ * 将语音发送到服务器的线程-发送消费者
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/26.
+ */
+public class AudioVoiceInputThread extends Thread {
+ private static final String TAG = AudioVoiceInputThread.class.getSimpleName();
+ private volatile boolean isStart = false;
+ private BufferedSink bufferedSink;
+ // 音频数据
+ private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+ private Handler handler;
+
+ public AudioVoiceInputThread(LinkedBlockingDeque<byte[]> linkedBlockingDeque,
+ BufferedSink bufferedSink,
+ Handler handler) {
+ this.linkedBlockingDeque = linkedBlockingDeque;
+ this.bufferedSink = bufferedSink;
+ this.handler = handler;
+ }
+
+ /**
+ * 开始写入数据
+ */
+ public void startWriteStream() {
+ if (isStart) {
+ return;
+ }
+ isStart = true;
+ this.start();
+ }
+
+ /**
+ * 停止写入数据
+ */
+ public void stopWriteStream() {
+ isStart = false;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ while (isStart) {
+ try {
+ byte[] recordAudioData = linkedBlockingDeque.pollFirst();
+ if (null != recordAudioData) {
+ bufferedSink.write(recordAudioData);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ LogUtil.d(TAG, "writeTo IOException", e);
+ } catch (Exception e) {
+ e.printStackTrace();
+ LogUtil.d(TAG, "writeTo Exception", e);
+ }
+ }
+ if (linkedBlockingDeque.size() > 0) {
+ byte[] recordAudioData = linkedBlockingDeque.pollFirst();
+ if (null != recordAudioData) {
+ LogUtil.d(TAG, "finally writeTo size:" + recordAudioData.length);
+ try {
+ bufferedSink.write(recordAudioData);
+ } catch (IOException e) {
+ e.printStackTrace();
+ LogUtil.d(TAG, " >0 writeTo IOException", e);
+ }
+ }
+ }
+ try {
+ bufferedSink.flush();
+ bufferedSink.close();
+ LogUtil.d(TAG, "closed");
+ } catch (IOException e) {
+ e.printStackTrace();
+ LogUtil.d(TAG, "IOException ", e);
+ }
+ LogUtil.d(TAG, "onWriteFinished ");
+ // 写入完成
+ if (listener != null) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onWriteFinished();
+ }
+ });
+ }
+ }
+
+ private IAudioInputListener listener;
+
+ public void setAudioInputListener(IAudioInputListener listener) {
+ this.listener = listener;
+ }
+
+ /**
+ * 写入完成的回调接口,比如当接收到StopListen指令后回触发
+ */
+ public interface IAudioInputListener {
+ /**
+ * 写入完成后回调此方法
+ */
+ void onWriteFinished();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/playbackcontroller/IPlaybackControllerImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.playbackcontroller;
+
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.systeminterface.IPlaybackController;
+
+/**
+ * 播放控制
+ * <p>
+ * Created by zhoujianliang01@baidu.com on 2017/6/17.
+ */
+public class IPlaybackControllerImpl implements IPlaybackController {
+ private IPlaybackListener playbackListener;
+
+ @Override
+ public void play(IResponseListener responseListener) {
+ if (playbackListener == null) {
+ return;
+ }
+ playbackListener.onPlay(responseListener);
+ }
+
+ @Override
+ public void pause(IResponseListener responseListener) {
+ if (playbackListener == null) {
+ return;
+ }
+ playbackListener.onPause(responseListener);
+ }
+
+ @Override
+ public void previous(IResponseListener responseListener) {
+ if (playbackListener == null) {
+ return;
+ }
+ playbackListener.onPrevious(responseListener);
+ }
+
+ @Override
+ public void next(IResponseListener responseListener) {
+ if (playbackListener == null) {
+ return;
+ }
+ playbackListener.onNext(responseListener);
+ }
+
+ @Override
+ public void registerPlaybackListener(IPlaybackListener listener) {
+ this.playbackListener = listener;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/AudioStoreThread.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.player;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.util.FileUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 将stream的mp3流保存到文件中
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/17.
+ */
+public class AudioStoreThread extends Thread {
+ private static final String TAG = AudioStoreThread.class.getSimpleName();
+ private static final int BUFFER_SIZE = 8192;
+ private volatile boolean mThreadExitFlag;
+ private InputStream mInputStream;
+ private Handler mHandler = new Handler();
+
+ private File file;
+ private File completedFile;
+ private FileOutputStream mOutputStream;
+
+ public AudioStoreThread(InputStream is) {
+ this.mInputStream = is;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ try {
+ file = FileUtil.getSpeakFile();
+ if (file != null) {
+ LogUtil.d(TAG, "AudioStoreThread file: " + file.getAbsolutePath());
+ this.mOutputStream = new FileOutputStream(file);
+ } else {
+ if (mOnDownListener != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mOnDownListener.onDownError(
+ new JSONObject("AudioStoreThread create temp file failed!"));
+ } catch (JSONException e1) {
+ e1.printStackTrace();
+ }
+ }
+ });
+ }
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ LogUtil.d(TAG, "AudioStoreThread FileNotFoundException ");
+ }
+ if (mOnDownListener != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mOnDownListener.onDownStart();
+ }
+ });
+ }
+ byte[] audioData = new byte[BUFFER_SIZE];
+ int readBytes;
+ try {
+ while (!mThreadExitFlag && (readBytes = mInputStream.read(audioData)) != -1) {
+ LogUtil.d(TAG, "readBytes=" + readBytes);
+ mOutputStream.write(audioData, 0, readBytes);
+ }
+ mOutputStream.flush();
+ LogUtil.d(TAG, "AudioStoreThread ok ");
+ } catch (final IOException e) {
+ e.printStackTrace();
+ LogUtil.d(TAG, "AudioStoreThread write error ", e);
+ if (mOnDownListener != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mOnDownListener.onDownError(new JSONObject("AudioStoreThread write error :"
+ + e.getMessage()));
+ } catch (JSONException e1) {
+ e1.printStackTrace();
+ }
+ }
+ });
+ }
+ } finally {
+ try {
+ String fileName = file.getName().substring(0, file.getName().length()
+ - FileUtil.TEMP_POSTFIX.length());
+ LogUtil.d(TAG, "AudioStoreThread fileName : " + fileName);
+ completedFile = new File(file.getParentFile(), fileName);
+ boolean renamed = file.renameTo(completedFile);
+ if (!renamed) {
+ if (mOnDownListener != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mOnDownListener.onDownError(new JSONObject("Error renaming file "
+ + file
+ + "to"
+ + completedFile
+ + " for completion!"));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+ }
+ mOutputStream.close();
+ mInputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ if (mOnDownListener != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ LogUtil.d(TAG, "completedFile path: " + completedFile.getAbsolutePath());
+ mOnDownListener.onDownComplete(completedFile.getAbsolutePath());
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * 停止保存/下载
+ */
+ public void stopDown() {
+ LogUtil.d(TAG, "stopDown");
+ mThreadExitFlag = true;
+ mHandler.removeCallbacksAndMessages(null);
+ }
+
+ /**
+ * 删除文件
+ *
+ * @return 是否删除成功
+ */
+ public boolean delDownFile() {
+ LogUtil.d(TAG, "delDownFile");
+ if (completedFile != null && completedFile.exists()) {
+ return completedFile.delete();
+ }
+ return false;
+ }
+
+ public static class SimpleOnDownListener implements OnDownListener {
+ @Override
+ public void onDownStart() {
+ }
+
+ @Override
+ public void onDownComplete(String path) {
+ }
+
+ @Override
+ public void onDownError(JSONObject jsonObject) {
+ }
+ }
+
+ public OnDownListener mOnDownListener;
+
+ public void setOnDownListener(OnDownListener listener) {
+ this.mOnDownListener = listener;
+ }
+
+ /**
+ * 流保存回调接口
+ */
+ public interface OnDownListener {
+ void onDownStart();
+
+ void onDownComplete(String path);
+
+ void onDownError(JSONObject jsonObject);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/AudioStreamStoreImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.player;
+
+import org.json.JSONObject;
+
+import java.io.InputStream;
+
+/**
+ * 保存音频mp3流到文件中-android中实现
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class AudioStreamStoreImpl implements IAudioStreamStore {
+ private AudioStoreThread mAudioStoreThread;
+ private OnStoreListener onStoreListener;
+
+ @Override
+ public void save(InputStream inputStream) {
+ mAudioStoreThread = new AudioStoreThread(inputStream);
+ mAudioStoreThread.setOnDownListener(simpleOnDownListener);
+ mAudioStoreThread.start();
+ }
+
+ @Override
+ public void cancel() {
+ if (mAudioStoreThread != null) {
+ mAudioStoreThread.stopDown();
+ }
+ }
+
+ @Override
+ public void speakAfter() {
+ if (mAudioStoreThread != null) {
+ mAudioStoreThread.delDownFile();
+ }
+ }
+
+ @Override
+ public void setOnStoreListener(OnStoreListener listener) {
+ onStoreListener = listener;
+ }
+
+ private AudioStoreThread.SimpleOnDownListener simpleOnDownListener = new AudioStoreThread.SimpleOnDownListener() {
+ @Override
+ public void onDownComplete(String path) {
+ super.onDownComplete(path);
+ if (onStoreListener != null) {
+ onStoreListener.onComplete(path);
+ }
+ }
+
+ @Override
+ public void onDownError(JSONObject jsonObject) {
+ super.onDownError(jsonObject);
+ if (onStoreListener != null) {
+ onStoreListener.onError(jsonObject.toString());
+ }
+ }
+ };
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/IAudioStreamStore.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.player;
+
+import java.io.InputStream;
+
+/**
+ * mp3流保存接口
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public interface IAudioStreamStore {
+ /**
+ * 保存mp3流到文件中(存储设备中)
+ */
+ void save(InputStream inputStream);
+
+ /**
+ * 取消保存
+ */
+ void cancel();
+
+ /**
+ * 播报完成后处理的操作,比如删除保存的文件
+ */
+ void speakAfter();
+
+ /**
+ * 保存回调监听
+ *
+ * @param listener listener
+ */
+ void setOnStoreListener(OnStoreListener listener);
+
+ /**
+ * 保存回调接口
+ */
+ interface OnStoreListener {
+ void onStart();
+
+ void onComplete(String path);
+
+ void onError(String errorMessage);
+ }
+
+ class SimpleOnStoreListener implements OnStoreListener {
+ @Override
+ public void onStart() {
+ }
+
+ @Override
+ public void onComplete(String path) {
+ }
+
+ @Override
+ public void onError(String errorMessage) {
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/MediaPlayerImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.player;
+
+import android.app.Service;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.baidu.duer.dcs.androidapp.DcsSampleApplication;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * android MediaPlayer -android平台中实现音频的播放逻辑
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class MediaPlayerImpl implements IMediaPlayer {
+ private static final String TAG = MediaPlayerImpl.class.getSimpleName();
+ public static final String ASSERT_PREFIX = "assets://";
+ private static final String KEY_SP_VOLUME = "currentVolume";
+ private static final String KEY_SP_MUTE = "isMute";
+ private IMediaPlayer.PlayState mCurrentState = IMediaPlayer.PlayState.IDLE;
+ private MediaPlayer mMediaPlayer;
+ private float currentVolume = 0.8f; // 默认音量80%
+ private boolean isMute;
+ private boolean isError38;
+ private float currentPercent;
+ private int currentSeekMilliseconds;
+ private IAudioStreamStore audioStreamStore; // stream流数据保存
+ private List<IMediaPlayer.IMediaPlayerListener> mediaPlayerListeners;
+ private boolean isActive;
+ private TelephonyManager telephonyManager;
+
+ public MediaPlayerImpl() {
+ mMediaPlayer = new MediaPlayer();
+ // set audio stream type
+ mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ mMediaPlayer.setOnBufferingUpdateListener(bufferingUpdateListener);
+ mMediaPlayer.setOnErrorListener(errorListener);
+ mMediaPlayer.setOnPreparedListener(preparedListener);
+ mMediaPlayer.setOnCompletionListener(completionListener);
+ mMediaPlayer.setOnSeekCompleteListener(seekCompleteListener);
+ // 不同的音频源,此回调有的不回调!!!
+ // mMediaPlayer.setOnInfoListener(infoListener);
+
+ // 读取音量和静音的数据
+ currentVolume = (float) MediaPlayerPreferenceUtil.get(DcsSampleApplication.getInstance(),
+ KEY_SP_VOLUME, 0.8f);
+ isMute = (boolean) MediaPlayerPreferenceUtil.get(DcsSampleApplication.getInstance(),
+ KEY_SP_MUTE, false);
+ // LinkedList
+ mediaPlayerListeners = Collections.synchronizedList(new LinkedList<IMediaPlayer.IMediaPlayerListener>());
+
+ // 来电监听
+ telephonyManager = (TelephonyManager)
+ DcsSampleApplication.getInstance().getSystemService(Service.TELEPHONY_SERVICE);
+ telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+ }
+
+ private PhoneStateListener phoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ super.onCallStateChanged(state, incomingNumber);
+ switch (state) {
+ // 电话挂断
+ case TelephonyManager.CALL_STATE_IDLE:
+ resume();
+ break;
+ // 等待接电话
+ case TelephonyManager.CALL_STATE_RINGING:
+ pause();
+ break;
+ // 通话中
+ case TelephonyManager.CALL_STATE_OFFHOOK:
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ private IAudioStreamStore.OnStoreListener onStoreListener = new IAudioStreamStore.SimpleOnStoreListener() {
+ @Override
+ public void onComplete(String path) {
+ LogUtil.e(TAG, "onStoreListener,path:" + path);
+ // after down star play
+ File file = new File(path);
+ if (file.exists() && file.length() > 0) {
+ play(path);
+ } else {
+ mCurrentState = IMediaPlayer.PlayState.ERROR;
+ fireOnError("play path not exists or length<0 ",
+ IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
+ }
+ }
+ };
+
+ @Override
+ public void play(MediaResource mediaResource) {
+ if (mediaResource.isStream) {
+ play(mediaResource.stream);
+ } else {
+ play(mediaResource.url);
+ }
+ }
+
+ private void play(InputStream stream) {
+ LogUtil.e(TAG, "play stream");
+ if (audioStreamStore == null) {
+ audioStreamStore = new AudioStreamStoreImpl();
+ }
+ audioStreamStore.setOnStoreListener(onStoreListener);
+ audioStreamStore.save(stream);
+ }
+
+ private void play(String url) {
+ if (TextUtils.isEmpty(url)) {
+ LogUtil.d(TAG, "play-url is empty");
+ fireOnError("play-url is empty.",
+ IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
+ mCurrentState = IMediaPlayer.PlayState.ERROR;
+ return;
+ }
+ fireOnInit();
+ LogUtil.d(TAG, "play-url:" + url);
+ if (url.startsWith(ASSERT_PREFIX) && url.length() > ASSERT_PREFIX.length()) {
+ playAsset(url.substring(ASSERT_PREFIX.length()));
+ } else {
+ try {
+ mMediaPlayer.reset();
+ mMediaPlayer.setDataSource(url);
+ // Async
+ mMediaPlayer.prepareAsync();
+ mCurrentState = IMediaPlayer.PlayState.PREPARING;
+ } catch (IOException e) {
+ e.printStackTrace();
+ LogUtil.d(TAG, "playPath", e);
+ mCurrentState = IMediaPlayer.PlayState.ERROR;
+ fireOnError("IOException play url :"
+ + url, IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
+ }
+ }
+ }
+
+ private void playAsset(String resName) {
+ LogUtil.d(TAG, "playAsset:" + resName);
+ try {
+ AssetManager am = DcsSampleApplication.getInstance().getAssets();
+ AssetFileDescriptor afd = am.openFd(resName);
+ mMediaPlayer.reset();
+ mMediaPlayer.setDataSource(afd.getFileDescriptor(),
+ afd.getStartOffset(), afd.getLength());
+ mMediaPlayer.prepareAsync();
+ mCurrentState = IMediaPlayer.PlayState.PREPARING;
+ } catch (IOException e) {
+ e.printStackTrace();
+ LogUtil.d(TAG, "playAsset", e);
+ mCurrentState = IMediaPlayer.PlayState.ERROR;
+ fireOnError("IOException play playAsset",
+ IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
+ }
+ }
+
+ @Override
+ public void pause() {
+ if (mCurrentState == IMediaPlayer.PlayState.PLAYING
+ || mCurrentState == IMediaPlayer.PlayState.PREPARED
+ || mCurrentState == IMediaPlayer.PlayState.PREPARING) {
+ mMediaPlayer.pause();
+ mCurrentState = IMediaPlayer.PlayState.PAUSED;
+ fireOnPaused();
+ }
+ }
+
+ @Override
+ public void stop() {
+ if (mMediaPlayer != null) {
+ mMediaPlayer.stop();
+ mCurrentState = IMediaPlayer.PlayState.STOPPED;
+ // delete audio file
+ if (audioStreamStore != null) {
+ audioStreamStore.cancel();
+ audioStreamStore.speakAfter();
+ }
+ fireStopped();
+ }
+ }
+
+
+ @Override
+ public void resume() {
+ if (mCurrentState == IMediaPlayer.PlayState.PAUSED) {
+ mMediaPlayer.start();
+ mCurrentState = IMediaPlayer.PlayState.PLAYING;
+ firePlaying();
+ }
+ }
+
+ @Override
+ public void release() {
+ if (mMediaPlayer != null) {
+ mMediaPlayer.stop();
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ mCurrentState = IMediaPlayer.PlayState.IDLE;
+ fireOnRelease();
+ }
+ if (audioStreamStore != null) {
+ audioStreamStore.cancel();
+ audioStreamStore.speakAfter();
+ }
+ mediaPlayerListeners.clear();
+ }
+
+ @Override
+ public PlayState getPlayState() {
+ return mCurrentState;
+ }
+
+ @Override
+ public void seekTo(int pos) {
+ currentSeekMilliseconds = pos;
+ LogUtil.d(TAG, "seekTo,currentSeekMilliseconds:" + currentSeekMilliseconds);
+ if (mMediaPlayer != null && mCurrentState == IMediaPlayer.PlayState.PREPARED) {
+ mMediaPlayer.seekTo(pos);
+ }
+ }
+
+ /**
+ * 设置音量
+ *
+ * @param volume 0.0 -1.0
+ */
+ @Override
+ public void setVolume(float volume) {
+ // 设置音量就不再静音了,比如:说了调衡音量等操作
+ isMute = false;
+ currentVolume = volume;
+ if (mMediaPlayer != null) {
+ mMediaPlayer.setVolume(volume, volume);
+ }
+ // 保存数据
+ MediaPlayerPreferenceUtil.put(DcsSampleApplication.getInstance(),
+ KEY_SP_VOLUME, currentVolume);
+ MediaPlayerPreferenceUtil.put(DcsSampleApplication.getInstance(),
+ KEY_SP_MUTE, isMute);
+ }
+
+ @Override
+ public float getVolume() {
+ return currentVolume;
+ }
+
+ @Override
+ public void setMute(boolean mute) {
+ isMute = mute;
+ if (mMediaPlayer != null) {
+ if (mute) {
+ mMediaPlayer.setVolume(0, 0);
+ } else {
+ mMediaPlayer.setVolume(currentVolume, currentVolume);
+ }
+ }
+ // 保存数据
+ MediaPlayerPreferenceUtil.put(DcsSampleApplication.getInstance(),
+ KEY_SP_MUTE, isMute);
+ }
+
+ @Override
+ public boolean getMute() {
+ return isMute;
+ }
+
+ @Override
+ public long getCurrentPosition() {
+ if (mMediaPlayer == null) {
+ return 0;
+ }
+ if (mCurrentState == IMediaPlayer.PlayState.IDLE || mCurrentState == IMediaPlayer.PlayState.ERROR) {
+ return 0;
+ }
+ return mMediaPlayer.getCurrentPosition();
+ }
+
+ @Override
+ public long getDuration() {
+ if (mMediaPlayer == null) {
+ return 0;
+ }
+ if (mCurrentState == IMediaPlayer.PlayState.IDLE || mCurrentState == IMediaPlayer.PlayState.ERROR) {
+ return 0;
+ }
+ return mMediaPlayer.getDuration();
+ }
+
+ @Override
+ public float getBufferPercentage() {
+ return currentPercent;
+ }
+
+
+ @Override
+ public void addMediaPlayerListener(IMediaPlayerListener listener) {
+ if (!mediaPlayerListeners.contains(listener)) {
+ mediaPlayerListeners.add(listener);
+ }
+ }
+
+ @Override
+ public void removeMediaPlayerListener(IMediaPlayerListener listener) {
+ if (mediaPlayerListeners.contains(listener)) {
+ mediaPlayerListeners.remove(listener);
+ }
+ }
+
+ @Override
+ public void setActive(boolean isActive) {
+ this.isActive = isActive;
+ }
+
+ @Override
+ public boolean isActive() {
+ return isActive;
+ }
+
+ private void fireOnError(String error, ErrorType errorType) {
+ for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+ if (listener != null) {
+ listener.onError(error, errorType);
+ }
+ }
+ }
+
+ private void fireOnInit() {
+ for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+ if (listener != null) {
+ listener.onInit();
+ }
+ }
+ }
+
+ private void fireOnPaused() {
+ for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+ if (listener != null) {
+ listener.onPaused();
+ }
+ }
+ }
+
+ private void fireStopped() {
+ for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+ if (listener != null) {
+ listener.onStopped();
+ }
+ }
+ }
+
+ private void firePlaying() {
+ for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+ if (listener != null) {
+ listener.onPlaying();
+ }
+ }
+ }
+
+ private void fireOnRelease() {
+ for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+ if (listener != null) {
+ listener.onRelease();
+ }
+ }
+ }
+
+ private void fireOnPrepared() {
+ for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+ if (listener != null) {
+ listener.onPrepared();
+ }
+ }
+ }
+
+ private void fireOonBufferingUpdate(int percent) {
+ for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+ if (listener != null) {
+ listener.onBufferingUpdate(percent);
+ }
+ }
+ }
+
+ private void fireOnCompletion() {
+ for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+ if (listener != null) {
+ listener.onCompletion();
+ }
+ }
+ }
+
+ private MediaPlayer.OnPreparedListener preparedListener = new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ LogUtil.d(TAG, "onPrepared");
+ mCurrentState = IMediaPlayer.PlayState.PREPARED;
+ isError38 = false;
+ fireOnPrepared();
+ // must be called after prepareAsync or prepare
+ LogUtil.d(TAG, "currentVolume:" + currentVolume);
+ LogUtil.d(TAG, "currentSeekMilliseconds:" + currentSeekMilliseconds);
+ // 一开始就说话让它静音了
+ if (isMute) {
+ mMediaPlayer.setVolume(0, 0);
+ } else {
+ setVolume(currentVolume);
+ }
+ seekTo(currentSeekMilliseconds);
+ }
+ };
+
+ private MediaPlayer.OnBufferingUpdateListener bufferingUpdateListener =
+ new MediaPlayer.OnBufferingUpdateListener() {
+ @Override
+ public void onBufferingUpdate(MediaPlayer mp, int percent) {
+ currentPercent = percent * 1.0f;
+ fireOonBufferingUpdate(percent);
+ }
+ };
+ private MediaPlayer.OnErrorListener errorListener = new MediaPlayer.OnErrorListener() {
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ LogUtil.d(TAG, "onError:" + what + ", extra:" + extra);
+ if (what == -38) {
+ isError38 = true;
+ return false;
+ }
+ isError38 = false;
+ mCurrentState = IMediaPlayer.PlayState.ERROR;
+ JSONObject jsonObject = new JSONObject();
+ try {
+ jsonObject.put("msg", "what: " + what + "; extra:" + extra);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ IMediaPlayer.ErrorType errorType;
+ switch (what) {
+ case MediaPlayer.MEDIA_ERROR_IO:
+ // Stream服务端返回错误 (bad request, unauthorized, forbidden, not found etc)
+ errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_INVALID_REQUEST;
+ break;
+ case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
+ // 端无法连接stream服务端
+ errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_SERVICE_UNAVAILABLE;
+ break;
+ case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
+ // 端内部错误
+ errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR;
+ break;
+ case MediaPlayer.MEDIA_ERROR_MALFORMED:
+ // stream服务端接受请求,但未能正确处理 ?????
+ errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_SERVER_ERROR;
+ break;
+ default:
+ // 未知错误
+ errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_UNKNOWN;
+ break;
+ }
+ fireOnError(jsonObject.toString(), errorType);
+ return false;
+ }
+ };
+
+ private MediaPlayer.OnSeekCompleteListener seekCompleteListener = new MediaPlayer.OnSeekCompleteListener() {
+ @Override
+ public void onSeekComplete(MediaPlayer mp) {
+ LogUtil.d(TAG, "onSeekComplete");
+ if (mCurrentState == IMediaPlayer.PlayState.PREPARED) {
+ mp.start();
+ mCurrentState = IMediaPlayer.PlayState.PLAYING;
+ firePlaying();
+ }
+ }
+ };
+
+ private MediaPlayer.OnCompletionListener completionListener = new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ if (isError38) {
+ return;
+ }
+ LogUtil.d(TAG, "onCompletion");
+ // delete audio file
+ if (audioStreamStore != null) {
+ audioStreamStore.cancel();
+ audioStreamStore.speakAfter();
+ }
+ mCurrentState = IMediaPlayer.PlayState.COMPLETED;
+ fireOnCompletion();
+ }
+ };
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/MediaPlayerPreferenceUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.player;
+
+import android.content.Context;
+
+import com.baidu.duer.dcs.util.PreferenceUtil;
+
+/**
+ * Media Player 保存音量和静音的状态
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/17.
+ */
+public class MediaPlayerPreferenceUtil extends PreferenceUtil {
+ // 保存到的文件名字
+ private static final String BAIDU_MEDIA_CONFIG = "baidu_media_config";
+
+ /**
+ * 保存音量或者静音的数据状态
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param object 值
+ */
+ public static void put(Context context, String key, Object object) {
+ put(context, BAIDU_MEDIA_CONFIG, key, object);
+ }
+
+ /**
+ * 读取音量或者静音的数据状态
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param defaultObject 默认值
+ */
+ public static Object get(Context context, String key, Object defaultObject) {
+ return get(context, BAIDU_MEDIA_CONFIG, key, defaultObject);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpDecodeThread.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,225 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.wakeup;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * 唤醒声音处理-唤醒消费者
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/22.
+ */
+public class WakeUpDecodeThread extends Thread {
+ private static final String TAG = WakeUpDecodeThread.class.getSimpleName();
+ // 唤醒成功
+ private static final int WAKEUP_SUCCEED = 1;
+ // 唤醒词位置
+ private int voiceOffset;
+ private boolean isWakeUp;
+ private WakeUpNative wakeUpNative;
+ private Handler handler;
+ private volatile boolean isStart = false;
+ private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+
+ public WakeUpDecodeThread(LinkedBlockingDeque<byte[]> linkedBlockingDeque,
+ WakeUpNative wakeUpNative,
+ Handler handler) {
+ this.linkedBlockingDeque = linkedBlockingDeque;
+ this.wakeUpNative = wakeUpNative;
+ this.handler = handler;
+ }
+
+ /**
+ * 开始唤醒
+ */
+ public void startWakeUp() {
+ if (isStart) {
+ return;
+ }
+ isStart = true;
+ this.start();
+ }
+
+ public boolean isStart() {
+ return isStart;
+ }
+
+ /**
+ * 停止唤醒
+ */
+ public void stopWakeUp() {
+ isStart = false;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ LogUtil.i(TAG, "wakeup wakeUpDecode start" );
+ while (isStart) {
+ try {
+ byte[] data = linkedBlockingDeque.take();
+
+ // 暂时不检测vad
+ // int volume = calculateVolume(data, 16);
+ // LogUtil.i(TAG, "wakeup audioRecord Volume:" + volume);
+ // if (volume <= 0) {
+ // continue;
+ // }
+
+ if (data.length > 0) {
+ // 是否为最后一帧数据
+ boolean isEnd = false;
+ short[] arr = byteArray2ShortArray(data, data.length / 2);
+ int ret = wakeUpNative.wakeUpDecode(
+ arr,
+ arr.length,
+ "",
+ 1,
+ -1,
+ true,
+ voiceOffset++,
+ isEnd
+ );
+ // 唤醒成功
+ if (ret == WAKEUP_SUCCEED) {
+ LogUtil.i(TAG, "wakeup wakeUpDecode ret:" + ret);
+ isWakeUp = true;
+ stopWakeUp();
+ LogUtil.i(TAG, "wakeup wakeUpDecode succeed !!");
+ break;
+ }
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ LogUtil.i(TAG, "wakeup after wakeUpDecode over !!");
+ LogUtil.i(TAG, "wakeup after linkedBlockingDeque size:" + linkedBlockingDeque.size());
+
+ if (isWakeUp) {
+ if (listener != null) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onWakeUpSucceed();
+ }
+ });
+ }
+ }
+ // 重置
+ voiceOffset = 0;
+ isWakeUp = false;
+ }
+
+ /**
+ * 将byte数组转为short数组
+ *
+ * @param data byte数组的音频数据
+ * @param items short数组的大小
+ * @return 转换后的short数组
+ */
+ private short[] byteArray2ShortArray(byte[] data, int items) {
+ short[] retVal = new short[items];
+ for (int i = 0; i < retVal.length; i++) {
+ retVal[i] = (short) ((data[i * 2] & 0xff) | (data[i * 2 + 1] & 0xff) << 8);
+ }
+ return retVal;
+ }
+
+ /**
+ * 根据输入的音量大小来判断用户是否有语音输入
+ *
+ * @param var0 原始音频数据
+ * @param var1 音频数据格式位PCM,16位每个样本,比如如果音频数据格式设为AudioFormat.ENCODING_PCM_16BIT,则参数传16
+ * @return >0 代表有音频输入
+ */
+ private int calculateVolume(byte[] var0, int var1) {
+ int[] var3 = null;
+ int var4 = var0.length;
+ int var2;
+ if (var1 == 8) {
+ var3 = new int[var4];
+ for (var2 = 0; var2 < var4; ++var2) {
+ var3[var2] = var0[var2];
+ }
+ } else if (var1 == 16) {
+ var3 = new int[var4 / 2];
+ for (var2 = 0; var2 < var4 / 2; ++var2) {
+ byte var5 = var0[var2 * 2];
+ byte var6 = var0[var2 * 2 + 1];
+ int var13;
+ if (var5 < 0) {
+ var13 = var5 + 256;
+ } else {
+ var13 = var5;
+ }
+ short var7 = (short) (var13 + 0);
+ if (var6 < 0) {
+ var13 = var6 + 256;
+ } else {
+ var13 = var6;
+ }
+ var3[var2] = (short) (var7 + (var13 << 8));
+ }
+ }
+ int[] var8 = var3;
+ if (var3 != null && var3.length != 0) {
+ float var10 = 0.0F;
+ for (int var11 = 0; var11 < var8.length; ++var11) {
+ var10 += (float) (var8[var11] * var8[var11]);
+ }
+ var10 /= (float) var8.length;
+ float var12 = 0.0F;
+ for (var4 = 0; var4 < var8.length; ++var4) {
+ var12 += (float) var8[var4];
+ }
+ var12 /= (float) var8.length;
+ var4 = (int) (Math.pow(2.0D, (double) (var1 - 1)) - 1.0D);
+ double var14 = Math.sqrt((double) (var10 - var12 * var12));
+ int var9;
+ if ((var9 = (int) (10.0D * Math.log10(var14 * 10.0D * Math.sqrt(2.0D) / (double) var4 + 1.0D))) < 0) {
+ var9 = 0;
+ }
+ if (var9 > 10) {
+ var9 = 10;
+ }
+ return var9;
+ } else {
+ return 0;
+ }
+ }
+
+ private IWakeUpListener listener;
+
+ public void setWakeUpListener(IWakeUpListener listener) {
+ this.listener = listener;
+ }
+
+ /**
+ * 唤醒成功回调接口
+ */
+ public interface IWakeUpListener {
+ /**
+ * 唤醒成功后回调
+ */
+ void onWakeUpSucceed();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,132 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.wakeup;
+
+import android.content.Context;
+import android.os.Handler;
+
+import com.baidu.duer.dcs.systeminterface.IWakeUp;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * 唤醒模块-android中实现
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/25.
+ */
+public class WakeUpImpl implements IWakeUp {
+ private static final String TAG = WakeUpImpl.class.getSimpleName();
+ // 初始化唤醒词成功
+ private static final int WAKEUP_INIT_SUCCEED = 0;
+ // 唤醒词
+ private static final String WAKEUP_WORD = "小度小度";
+ // 唤醒词声学模型模型文件
+ private static final String WAKEUP_FILENAME = "libbdEasrS1MergeNormal.so";
+ // jni
+ private WakeUpNative wakeUpNative;
+ // Decode消费线程
+ private WakeUpDecodeThread wakeUpDecodeThread;
+ // callback
+ private List<IWakeUpListener> wakeUpListeners;
+ private Handler handler = new Handler();
+ // 音频数据
+ private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+ // 初始化唤醒词的返回值
+ private int wakeUpInitialRet;
+ private Context context;
+
+ public WakeUpImpl(Context context, LinkedBlockingDeque<byte[]> linkedBlockingDeque) {
+ this.linkedBlockingDeque = linkedBlockingDeque;
+ this.context = context.getApplicationContext();
+ this.wakeUpNative = new WakeUpNative();
+ this.wakeUpListeners = Collections.synchronizedList(new LinkedList<IWakeUpListener>());
+ this.initWakeUp();
+ }
+
+ private void initWakeUp() {
+ // 方法1:加载声学模型文件,当作so库进行加载到nativeLibraryDir目录中
+ // 方法2:当然你也可以放到assets目录或者raw下,然后进行拷贝到应用的私有目录或者sd卡
+ // 方法2需要处理声学模型文件覆盖安装问题,以及不可预料的拷贝失败问题!
+ String path = this.context.getApplicationInfo().nativeLibraryDir
+ + File.separatorChar + WAKEUP_FILENAME;
+ LogUtil.d(TAG, "wakeup path:" + path);
+ LogUtil.d(TAG, "wakeup exists:" + new File(path).exists());
+ // 1.初始化唤醒词,0 是初始化成功
+ wakeUpInitialRet = wakeUpNative.wakeUpInitial(WAKEUP_WORD, path, 0);
+ LogUtil.d(TAG, "wakeUpInitialRet:" + wakeUpInitialRet);
+ }
+
+ @Override
+ public void startWakeUp() {
+ if (wakeUpDecodeThread != null && wakeUpDecodeThread.isStart()) {
+ LogUtil.d(TAG, "wakeup wakeUpDecodeThread is Started !");
+ return;
+ }
+ // 2.开始唤醒
+ if (wakeUpInitialRet == WAKEUP_INIT_SUCCEED) {
+ wakeUp();
+ } else {
+ LogUtil.d(TAG, "wakeup wakeUpInitialRet failed, not startWakeUp ");
+ }
+ }
+
+ @Override
+ public void stopWakeUp() {
+ if (wakeUpDecodeThread != null) {
+ wakeUpDecodeThread.stopWakeUp();
+ }
+ handler.removeCallbacksAndMessages(null);
+ }
+
+ @Override
+ public void releaseWakeUp() {
+ // 3.释放资源
+ int ret = wakeUpNative.wakeUpFree();
+ LogUtil.d(TAG, "wakeUpFree-ret:" + ret);
+ }
+
+ @Override
+ public void addWakeUpListener(IWakeUpListener listener) {
+ wakeUpListeners.add(listener);
+ }
+
+ /**
+ * 开始音频解码进行唤醒操作
+ */
+ private void wakeUp() {
+ wakeUpDecodeThread = new WakeUpDecodeThread(linkedBlockingDeque, wakeUpNative, handler);
+ wakeUpDecodeThread.setWakeUpListener(new WakeUpDecodeThread.IWakeUpListener() {
+ @Override
+ public void onWakeUpSucceed() {
+ // 唤醒成功
+ fireOnWakeUpSucceed();
+ }
+ });
+ wakeUpDecodeThread.startWakeUp();
+ }
+
+ private void fireOnWakeUpSucceed() {
+ for (IWakeUpListener listener : wakeUpListeners) {
+ listener.onWakeUpSucceed();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpNative.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,79 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.wakeup;
+
+/**
+ * 唤醒服务-native-声明
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/21.
+ */
+public class WakeUpNative {
+
+ // 加载动态库.so文件
+ static {
+ System.loadLibrary("wakeup");
+ // 唤醒词解码so库
+ System.loadLibrary("bdEASRAndroid");
+ }
+
+ /**
+ * 初始化唤醒词成功
+ *
+ * @param wakeUpWd 唤醒词,例如“小度小度”
+ * @param sFile 附件中的资源文件, 唤醒词模型数据的文件绝对路径
+ * @param mode 缺省0即可
+ * @return 返回0表示初始化唤醒词成功
+ */
+ public native int wakeUpInitial(String wakeUpWd, String sFile, int mode);
+
+ /**
+ * 重制唤醒词
+ *
+ * @return 返回0表示成功
+ */
+ public native int wakeUpReset();
+
+ /**
+ * 唤醒解码
+ *
+ * @param data 音频数据
+ * @param dataLen 数据长度
+ * @param senArr 返回结果,如果唤醒词是小度小度”,唤醒成功后会赋值
+ * @param expectNum 传1
+ * @param wakeWord_frame_len 唤醒成功返回唤醒词长度
+ * @param is_confidence true表示置信,false表示疑似唤醒
+ * @param voice_offset 唤醒词位置,需要用户传入,同时内部处理后传出
+ * @param bEd 是否为最后一帧数据
+ * @return 返回1表示唤醒,其他表示未唤醒
+ */
+ public native int wakeUpDecode(short[] data,
+ int dataLen,
+ String senArr,
+ int expectNum,
+ int wakeWord_frame_len,
+ boolean is_confidence,
+ int voice_offset,
+ boolean bEd
+ );
+
+ /**
+ * 释放资源
+ *
+ * @return 返回0表示成功
+ */
+ public native int wakeUpFree();
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/webview/BaseWebView.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.androidsystemimpl.webview;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.net.http.SslError;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.webkit.CookieManager;
+import android.webkit.CookieSyncManager;
+import android.webkit.DownloadListener;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebSettings;
+import android.webkit.WebSettings.PluginState;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import com.baidu.duer.dcs.systeminterface.IWebView;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * common webView
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/19.
+ */
+@SuppressLint("SetJavaScriptEnabled")
+public class BaseWebView extends WebView implements IWebView {
+ private final List<IWebViewListener> webViewListeners =
+ Collections.synchronizedList(new ArrayList<IWebViewListener>());
+
+ public BaseWebView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public BaseWebView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ public BaseWebView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ @SuppressWarnings("deprecation")
+ @SuppressLint("NewApi")
+ private void init(Context context) {
+ this.setVerticalScrollBarEnabled(false);
+ this.setHorizontalScrollBarEnabled(false);
+ if (Build.VERSION.SDK_INT < 19) {
+ removeJavascriptInterface("searchBoxJavaBridge_");
+ }
+
+ WebSettings localWebSettings = this.getSettings();
+ try {
+ // 禁用file协议,http://www.tuicool.com/articles/Q36ZfuF, 防止Android WebView File域攻击
+ localWebSettings.setAllowFileAccess(false);
+ localWebSettings.setSupportZoom(false);
+ localWebSettings.setBuiltInZoomControls(false);
+ localWebSettings.setUseWideViewPort(true);
+ localWebSettings.setDomStorageEnabled(true);
+ localWebSettings.setLoadWithOverviewMode(true);
+ localWebSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
+ localWebSettings.setPluginState(PluginState.ON);
+ // 启用数据库
+ localWebSettings.setDatabaseEnabled(true);
+ // 设置定位的数据库路径
+ String dir = context.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
+ localWebSettings.setGeolocationDatabasePath(dir);
+ localWebSettings.setGeolocationEnabled(true);
+ localWebSettings.setJavaScriptEnabled(true);
+ localWebSettings.setSavePassword(false);
+ String agent = localWebSettings.getUserAgentString();
+
+ localWebSettings.setUserAgentString(agent);
+ // setCookie(context, ".baidu.com", bdussCookie);
+
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ this.setWebViewClient(new BridgeWebViewClient());
+ }
+
+ private void setCookie(Context context, String domain, String sessionCookie) {
+ CookieSyncManager.createInstance(context);
+ CookieManager cookieManager = CookieManager.getInstance();
+ cookieManager.setAcceptCookie(true);
+ if (sessionCookie != null) {
+ // delete old cookies
+ cookieManager.removeSessionCookie();
+ }
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ cookieManager.setCookie(domain, sessionCookie);
+
+ CookieSyncManager.createInstance(context);
+ CookieSyncManager.getInstance().sync();
+ }
+
+ public void setDownloadListener(DownloadListener listener) {
+ super.setDownloadListener(listener);
+ }
+
+ private WebViewClientListener webViewClientListen;
+
+ public void setWebViewClientListen(WebViewClientListener webViewClientListen) {
+ this.webViewClientListen = webViewClientListen;
+ }
+
+ /**
+ * 枚举网络加载返回状态 STATUS_FALSE:false
+ * STATUS_TRUE:true
+ * STATUS_UNKNOW:不知道
+ * NET_UNKNOWN:未知网络
+ */
+ public enum LoadingWebStatus {
+ STATUS_FALSE, STATUS_TRUE, STATUS_UNKNOW
+ }
+
+ @Override
+ public void linkClicked(String url) {
+ fireLinkClicked(url);
+ }
+
+ @Override
+ public void addWebViewListener(IWebViewListener listener) {
+ this.webViewListeners.add(listener);
+ }
+
+ void fireLinkClicked(String url) {
+ for (IWebViewListener listener : webViewListeners) {
+ listener.onLinkClicked(url);
+ }
+ }
+
+ public interface WebViewClientListener {
+ LoadingWebStatus shouldOverrideUrlLoading(WebView view, String url);
+
+ void onPageStarted(WebView view, String url, Bitmap favicon);
+
+ void onPageFinished(WebView view, String url);
+
+ void onReceivedError(WebView view, int errorCode, String description, String failingUrl);
+ }
+
+ public class BridgeWebViewClient extends WebViewClient {
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ LoadingWebStatus loadWebStatus = LoadingWebStatus.STATUS_UNKNOW;
+ String mUrl = url;
+ try {
+ mUrl = URLDecoder.decode(url, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ }
+ if (null != webViewClientListen) {
+ loadWebStatus = webViewClientListen.shouldOverrideUrlLoading(view, url);
+ }
+ if (LoadingWebStatus.STATUS_FALSE == loadWebStatus) {
+ return false;
+ } else if (LoadingWebStatus.STATUS_TRUE == loadWebStatus) {
+ return true;
+ } else {
+ return super.shouldOverrideUrlLoading(view, url);
+ }
+ }
+
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ super.onPageStarted(view, url, favicon);
+ if (null != webViewClientListen) {
+ webViewClientListen.onPageStarted(view, url, favicon);
+ }
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ super.onPageFinished(view, url);
+ if (null != webViewClientListen) {
+ webViewClientListen.onPageFinished(view, url);
+ }
+ }
+
+ @Override
+ public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+ super.onReceivedError(view, errorCode, description, failingUrl);
+ if (null != webViewClientListen) {
+ webViewClientListen.onReceivedError(view, errorCode, description, failingUrl);
+ }
+ }
+
+ @Override
+ public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+ // 当发生证书认证错误时,采用默认的处理方法handler.cancel(),停止加载问题页面
+ handler.cancel();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/AlertHandler.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.alerts;
+
+/**
+ * 定义Alerts模块的基础能力接口:开启与停止闹钟
+ * <p>
+ * Created by zhoujianliang01@baidu.com on 2017/6/5.
+ */
+public interface AlertHandler {
+ void startAlert(String alertToken);
+
+ void stopAlert(String alertToken);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/AlertScheduler.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.alerts;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.Alert;
+import com.baidu.duer.dcs.util.DateFormatterUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * 单个的闹铃/提醒计时器
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/5.
+ */
+public class AlertScheduler extends Timer {
+ private static final String TAG = "AlertScheduler";
+ private final Alert alert;
+ private final AlertHandler handler;
+ private boolean active = false;
+
+ public AlertScheduler(final Alert alert, final AlertHandler handler) {
+ super();
+ String scheduledTimeStr = alert.getScheduledTime();
+ if (scheduledTimeStr != null && scheduledTimeStr.length() > 0) {
+ try {
+ Date date = DateFormatterUtil.toDate(alert.getScheduledTime());
+ long scheduledTime = date.getTime();
+ long delay = scheduledTime - System.currentTimeMillis();
+ LogUtil.d(TAG, "alert-delay start:" + delay);
+ if (delay > 0) {
+ this.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ // 时间到了,开始闹铃
+ setActive(true);
+ handler.startAlert(alert.getToken());
+ }
+ }, delay);
+ }
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ }
+ this.alert = alert;
+ this.handler = handler;
+ }
+
+ public synchronized boolean isActive() {
+ return active;
+ }
+
+ public synchronized void setActive(boolean active) {
+ this.active = active;
+ }
+
+ @Override
+ public void cancel() {
+ super.cancel();
+ if (isActive()) {
+ handler.stopAlert(alert.getToken());
+ setActive(false);
+ }
+ }
+
+ public Alert getAlert() {
+ return alert;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/AlertsDeviceModule.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.alerts;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.Alert;
+import com.baidu.duer.dcs.devicemodule.alerts.message.AlertPayload;
+import com.baidu.duer.dcs.devicemodule.alerts.message.AlertsStatePayload;
+import com.baidu.duer.dcs.devicemodule.alerts.message.DeleteAlertPayload;
+import com.baidu.duer.dcs.devicemodule.alerts.message.SetAlertPayload;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IAlertsDataStore;
+import com.baidu.duer.dcs.systeminterface.IHandler;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.CommonUtil;
+import com.baidu.duer.dcs.util.DateFormatterUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Alerts模块的核心处理逻辑,如执行SetAlert、DeleteAlert指令,上传SetAlertSucceeded、DeleteAlertSucceeded等事件,
+ * 以及维护自身的端状态
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class AlertsDeviceModule extends BaseDeviceModule implements AlertHandler {
+ private static final String TAG = AlertsDeviceModule.class.getSimpleName();
+ // 闹铃开始是播放的音频文件
+ private static final String ALARM_NAME = "assets://alarm.mp3";
+ // 已经离alert时间点超过30分钟了
+ private static final int MINUTES_AFTER_PAST_ALERT_EXPIRES = 30;
+ // 当前的闹钟/提醒
+ private final Map<String, AlertScheduler> schedulers;
+ // 当前处于播放的
+ private final Set<String> activeAlerts;
+ private final IAlertsDataStore dataStore;
+ // 播放闹铃/提醒的mediaPlayer
+ private IMediaPlayer mediaPlayer;
+ private IHandler handler;
+ private List<IAlertListener> alertListeners;
+
+ // 提醒的状态
+ private enum AlertState {
+ PLAYING,
+ INTERRUPTED,
+ FINISHED
+ }
+
+ private AlertState alertState = AlertState.FINISHED;
+
+ public AlertsDeviceModule(IMediaPlayer mediaPlayer, IAlertsDataStore dataStore,
+ IMessageSender messageSender, IHandler handler) {
+ super(ApiConstants.NAMESPACE, messageSender);
+ this.schedulers = new ConcurrentHashMap<>();
+ this.activeAlerts = new HashSet<>();
+ this.mediaPlayer = mediaPlayer;
+ this.dataStore = dataStore;
+ this.handler = handler;
+ this.mediaPlayer.addMediaPlayerListener(mediaPlayerListener);
+ this.alertListeners = Collections.synchronizedList(new ArrayList<IAlertListener>());
+ // 先读取历史保存到文件中的提醒
+ this.loadFromDisk();
+ }
+
+ @Override
+ public ClientContext clientContext() {
+ String namespace = ApiConstants.NAMESPACE;
+ String name = ApiConstants.Events.AlertsState.NAME;
+ Header header = new Header(namespace, name);
+ Payload payload = getState();
+ return new ClientContext(header, payload);
+ }
+
+ @Override
+ public void handleDirective(Directive directive) throws HandleDirectiveException {
+ String directiveName = directive.getName();
+ if (directiveName.equals(ApiConstants.Directives.SetAlert.NAME)) {
+ // 设置一个闹铃/提醒的指令处理逻辑
+ LogUtil.d(TAG, "alert-SetAlertPayload");
+ SetAlertPayload payload = (SetAlertPayload) directive.payload;
+
+ String alertToken = payload.getToken();
+ String scheduledTime = payload.getScheduledTime();
+ LogUtil.d(TAG, "alert-scheduledTime:" + scheduledTime);
+
+ // scheduledTime 时间为ISO8601格式转换为Date
+ try {
+ Date date = DateFormatterUtil.toDate(scheduledTime);
+ LogUtil.d(TAG, "alert-ms:" + date.getTime());
+ LogUtil.d(TAG, "alert-format:" + CommonUtil.formatToDataTime(date.getTime()));
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ SetAlertPayload.AlertType type = payload.getType();
+ // 如果存在一样的闹铃/提醒 就cancel掉
+ if (hasAlert(alertToken)) {
+ AlertScheduler scheduler = getScheduler(alertToken);
+ if (scheduler.getAlert().getScheduledTime().equals(scheduledTime)) {
+ return;
+ } else {
+ scheduler.cancel();
+ }
+ }
+ // 设置一个闹铃/提醒
+ Alert alert = new Alert(alertToken, type, scheduledTime);
+ add(alert, false);
+ } else if (ApiConstants.Directives.DeleteAlert.NAME.equals(directiveName)) {
+ // 删除一个闹铃/提醒的指令处理
+ LogUtil.d(TAG, "alert-DeleteAlertPayload");
+ DeleteAlertPayload payload = (DeleteAlertPayload) directive.getPayload();
+ delete(payload.getToken());
+ } else {
+ String message = "Alert cannot handle the directive";
+ throw (new HandleDirectiveException(
+ HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
+ }
+ }
+
+ @Override
+ public void startAlert(final String alertToken) {
+ LogUtil.d(TAG, "alert-startAlert");
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ activeAlerts.add(alertToken);
+ sendAlertsRequest(ApiConstants.Events.AlertStarted.NAME, alertToken);
+ fireOnAlertStarted(alertToken);
+ if (!isAlarming()) {
+ alertState = AlertState.PLAYING;
+ if (mediaPlayer != null) {
+ mediaPlayer.play(new IMediaPlayer.MediaResource(ALARM_NAME));
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public void stopAlert(final String alertToken) {
+ LogUtil.d(TAG, "alert-stopAlert");
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ activeAlerts.remove(alertToken);
+ schedulers.remove(alertToken);
+ alertStopped(alertToken);
+ if (!hasActiveAlerts()) {
+ alertState = AlertState.FINISHED;
+ if (mediaPlayer != null) {
+ mediaPlayer.pause();
+ }
+ }
+ }
+ });
+ }
+
+ private void sendAlertEnteredBackgroundEvent(String alertToken) {
+ sendAlertsRequest(ApiConstants.Events.AlertEnteredBackground.NAME, alertToken);
+ }
+
+ private void sendAlertEnteredBackgroundEvent() {
+ if (hasActiveAlerts()) {
+ for (String alertToken : getActiveAlerts()) {
+ sendAlertsRequest(ApiConstants.Events.AlertEnteredBackground.NAME, alertToken);
+ }
+ }
+ }
+
+ private void sendAlertEnteredForegroundEvent(String alertToken) {
+ sendAlertsRequest(ApiConstants.Events.AlertEnteredForeground.NAME, alertToken);
+ }
+
+ public void sendAlertEnteredForegroundEvent() {
+ if (hasActiveAlerts()) {
+ for (String alertToken : getActiveAlerts()) {
+ sendAlertsRequest(ApiConstants.Events.AlertEnteredForeground.NAME, alertToken);
+ }
+ }
+ }
+
+ public void sendAlertStartedEvent(boolean isSpeaking, String alertToken) {
+ if (isSpeaking) {
+ sendAlertEnteredBackgroundEvent(alertToken);
+ } else {
+ sendAlertEnteredForegroundEvent(alertToken);
+ }
+ }
+
+ private void sendAlertsRequest(String eventName, String alertToken) {
+ Header header = new MessageIdHeader(ApiConstants.NAMESPACE, eventName);
+ Payload payload = new AlertPayload(alertToken);
+ Event event = new Event(header, payload);
+ messageSender.sendEvent(event);
+ }
+
+ /**
+ * 设置提醒/闹钟成功或者失败的上报
+ *
+ * @param alertToken alertToken
+ * @param success success
+ */
+ private void setAlert(String alertToken, boolean success) {
+ String eventName = success ? ApiConstants.Events.SetAlertSucceeded.NAME :
+ ApiConstants.Events.SetAlertFailed.NAME;
+ sendAlertsRequest(eventName, alertToken);
+ }
+
+ /**
+ * 删除提醒/闹钟成功或者失败的上报
+ *
+ * @param alertToken alertToken
+ * @param success success
+ */
+ private void deleteAlert(String alertToken, boolean success) {
+ String eventName = success ? ApiConstants.Events.DeleteAlertSucceeded.NAME :
+ ApiConstants.Events.DeleteAlertFailed.NAME;
+ sendAlertsRequest(eventName, alertToken);
+ }
+
+ /**
+ * 到了定点时间,触发了提醒/闹钟 时上报
+ *
+ * @param alertToken alertToken
+ */
+ private void fireOnAlertStarted(String alertToken) {
+ for (IAlertListener listener : alertListeners) {
+ listener.onAlertStarted(alertToken);
+ }
+ }
+
+ /**
+ * 上报AlertStopped事件
+ *
+ * @param alertToken alertToken 闹钟/提醒 唯一的标识
+ */
+ private void alertStopped(String alertToken) {
+ sendAlertsRequest(ApiConstants.Events.AlertStopped.NAME, alertToken);
+ }
+
+ /**
+ * 从文件里读取之前设置的闹铃/提醒
+ */
+ private void loadFromDisk() {
+ dataStore.readFromDisk(new IAlertsDataStore.ReadResultListener() {
+
+ @Override
+ public void onSucceed(List<Alert> alerts) {
+ if (alerts == null || alerts.size() <= 0) {
+ return;
+ }
+ List<Alert> droppedAlerts = new LinkedList<>();
+ for (final Alert alert : alerts) {
+ String scheduledTime = alert.getScheduledTime();
+ if (scheduledTime != null && scheduledTime.length() > 0) {
+ try {
+ Date date = DateFormatterUtil.toDate(alert.getScheduledTime());
+ long scheduledTimeLong = date.getTime();
+ // 已经离alert时间点超过30分钟了
+ long cur = System.currentTimeMillis();
+ if (scheduledTimeLong + MINUTES_AFTER_PAST_ALERT_EXPIRES * 60 * 1000 < cur) {
+ droppedAlerts.add(alert);
+ } else {
+ add(alert, true);
+ }
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ for (Alert alert : droppedAlerts) {
+ drop(alert);
+ }
+ }
+
+ @Override
+ public void onFailed(String errMsg) {
+
+ }
+ });
+ }
+
+ public boolean isAlarming() {
+ return alertState == AlertState.PLAYING;
+ }
+
+ private synchronized boolean hasAlert(String alertToken) {
+ return schedulers.containsKey(alertToken);
+ }
+
+ public synchronized boolean hasActiveAlerts() {
+ return activeAlerts != null && activeAlerts.size() > 0;
+ }
+
+ private synchronized Set<String> getActiveAlerts() {
+ return activeAlerts;
+ }
+
+ private synchronized AlertScheduler getScheduler(String alertToken) {
+ return schedulers.get(alertToken);
+ }
+
+ /**
+ * 设置一个闹钟/提醒
+ *
+ * @param alert alert
+ * @param suppressEvent suppressEvent 是否需要上报事件
+ */
+ private synchronized void add(final Alert alert, final boolean suppressEvent) {
+ LogUtil.d(TAG, "add alertToken: " + alert.getToken());
+ final AlertScheduler scheduler = new AlertScheduler(alert, this);
+ schedulers.put(alert.getToken(), scheduler);
+ dataStore.writeToDisk(getAllAlerts(), new IAlertsDataStore.WriteResultListener() {
+
+ @Override
+ public void onSucceed() {
+ if (!suppressEvent) {
+ setAlert(alert.getToken(), true);
+ }
+ }
+
+ @Override
+ public void onFailed(String errMsg) {
+ if (!suppressEvent) {
+ setAlert(alert.getToken(), false);
+ }
+ schedulers.remove(alert.getToken());
+ scheduler.cancel();
+ }
+ });
+ }
+
+ /**
+ * 删除一个闹钟
+ *
+ * @param alertToken alertToken
+ */
+ private synchronized void delete(final String alertToken) {
+ LogUtil.d(TAG, "delete alertToken: " + alertToken);
+ final AlertScheduler scheduler = schedulers.remove(alertToken);
+ if (scheduler != null) {
+ final Alert alert = scheduler.getAlert();
+ dataStore.writeToDisk(getAllAlerts(), new IAlertsDataStore.WriteResultListener() {
+ @Override
+ public void onSucceed() {
+ LogUtil.d(TAG, "delete onSucceed");
+ scheduler.cancel();
+ deleteAlert(alert.getToken(), true);
+ }
+
+ @Override
+ public void onFailed(String errMsg) {
+ LogUtil.d(TAG, "delete onFailed");
+ deleteAlert(alert.getToken(), false);
+ }
+ });
+ } else {
+ // 本地没有查询到就上报删除失败的事件
+ LogUtil.d(TAG, "delete scheduler is null");
+ deleteAlert(alertToken, false);
+ }
+ }
+
+ private synchronized List<Alert> getAllAlerts() {
+ List<Alert> list = new ArrayList<>(schedulers.size());
+ for (AlertScheduler scheduler : schedulers.values()) {
+ list.add(scheduler.getAlert());
+ }
+ return list;
+ }
+
+ /**
+ * 如果有正在播放的闹铃/提醒,就停止播放并删除该闹铃/提醒
+ */
+ public synchronized void stopActiveAlert() {
+ for (String alertToken : activeAlerts) {
+ stopAlert(alertToken);
+ return;
+ }
+ }
+
+ private void drop(final Alert alert) {
+ alertStopped(alert.getToken());
+ }
+
+ private synchronized AlertsStatePayload getState() {
+ List<Alert> all = new ArrayList<>(schedulers.size());
+ List<Alert> active = new ArrayList<>(activeAlerts.size());
+ for (AlertScheduler scheduler : schedulers.values()) {
+ Alert alert = scheduler.getAlert();
+ all.add(alert);
+
+ if (activeAlerts.contains(alert.getToken())) {
+ active.add(alert);
+ }
+ }
+ return new AlertsStatePayload(all, active);
+ }
+
+ @Override
+ public void release() {
+ if (mediaPlayer != null) {
+ mediaPlayer.release();
+ mediaPlayer.removeMediaPlayerListener(mediaPlayerListener);
+ mediaPlayer = null;
+ }
+ for (AlertScheduler scheduler : schedulers.values()) {
+ scheduler.cancel();
+ }
+ alertListeners.clear();
+ }
+
+ private IMediaPlayer.IMediaPlayerListener mediaPlayerListener = new IMediaPlayer.SimpleMediaPlayerListener() {
+ @Override
+ public void onPrepared() {
+ super.onPrepared();
+ mediaPlayer.setActive(true);
+ }
+
+ @Override
+ public void onCompletion() {
+ alertState = AlertState.FINISHED;
+ mediaPlayer.setActive(false);
+ }
+
+ @Override
+ public void onError(String error, IMediaPlayer.ErrorType errorType) {
+ super.onError(error, errorType);
+ alertState = AlertState.FINISHED;
+ mediaPlayer.setActive(false);
+ }
+ };
+
+
+ /**
+ * 闹铃/提醒回调
+ */
+ public interface IAlertListener {
+ /**
+ * 到了定点时间,触发了提醒/闹钟 时上报
+ *
+ * @param alertToken alertToken
+ */
+ void onAlertStarted(String alertToken);
+ }
+
+ public void addAlertListener(IAlertListener listener) {
+ this.alertListeners.add(listener);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/ApiConstants.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.alerts;
+
+/**
+ * 定义了表示Alerts模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+ public static final String NAMESPACE = "ai.dueros.device_interface.alerts";
+ public static final String NAME = "AlertsInterface";
+
+ public static final class Events {
+ public static final class SetAlertSucceeded {
+ public static final String NAME = SetAlertSucceeded.class.getSimpleName();
+ }
+
+ public static final class SetAlertFailed {
+ public static final String NAME = SetAlertFailed.class.getSimpleName();
+ }
+
+ public static final class DeleteAlertSucceeded {
+ public static final String NAME = DeleteAlertSucceeded.class.getSimpleName();
+ }
+
+ public static final class DeleteAlertFailed {
+ public static final String NAME = DeleteAlertFailed.class.getSimpleName();
+ }
+
+ public static final class AlertStarted {
+ public static final String NAME = AlertStarted.class.getSimpleName();
+ }
+
+ public static final class AlertStopped {
+ public static final String NAME = AlertStopped.class.getSimpleName();
+ }
+
+ public static final class AlertsState {
+ public static final String NAME = AlertsState.class.getSimpleName();
+ }
+
+ public static final class AlertEnteredForeground {
+ public static final String NAME = AlertEnteredForeground.class.getSimpleName();
+ }
+
+ public static final class AlertEnteredBackground {
+ public static final String NAME = AlertEnteredBackground.class.getSimpleName();
+ }
+ }
+
+ public static final class Directives {
+ public static final class SetAlert {
+ public static final String NAME = SetAlert.class.getSimpleName();
+ }
+
+ public static final class DeleteAlert {
+ public static final String NAME = DeleteAlert.class.getSimpleName();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/Alert.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Alert 数据对象(model)
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/18.
+ */
+public class Alert {
+ private final String token;
+ private final SetAlertPayload.AlertType type;
+ // 触发时间,ISO 8601格式
+ private final String scheduledTime;
+
+ @JsonCreator
+ public Alert(@JsonProperty("token") String token, @JsonProperty("type") SetAlertPayload.AlertType type,
+ @JsonProperty("scheduledTime") String scheduledTime) {
+ this.token = token;
+ this.type = type;
+ this.scheduledTime = scheduledTime;
+ }
+
+ public String getToken() {
+ return this.token;
+ }
+
+ public SetAlertPayload.AlertType getType() {
+ return this.type;
+ }
+
+ public String getScheduledTime() {
+ return scheduledTime;
+ }
+
+ @Override
+ public int hashCode() {
+ return ((token == null) ? 0 : token.hashCode());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Alert other = (Alert) obj;
+ if (token == null) {
+ if (other.token != null) {
+ return false;
+ }
+ } else if (!token.equals(other.token)) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/AlertPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Alerts模块上报各种事件的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/16.
+ */
+public class AlertPayload extends Payload {
+ // 本闹钟的唯一token
+ public String token;
+
+ public AlertPayload(String token) {
+ this.token = token;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/AlertsStatePayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import java.util.List;
+
+/**
+ * Alerts模块端状态对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/18.
+ */
+public class AlertsStatePayload extends Payload {
+ public List<Alert> allAlerts;
+ public List<Alert> activeAlerts;
+
+ public AlertsStatePayload(List<Alert> all, List<Alert> active) {
+ this.allAlerts = all;
+ this.activeAlerts = active;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/DeleteAlertPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import java.io.Serializable;
+
+/**
+ * DeleteAlert指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/17.
+ */
+public class DeleteAlertPayload extends Payload implements Serializable {
+ public String token;
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public String getToken() {
+ return token;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/SetAlertPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.io.Serializable;
+
+/**
+ * SetAlert指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/17.
+ */
+public class SetAlertPayload extends Payload implements Serializable {
+ public enum AlertType {
+ ALARM,
+ TIMER
+ }
+
+ // alert唯一token
+ private String token;
+ private AlertType type;
+ // 格式:2017-05-17T03:00:00+0000
+ private String scheduledTime;
+ private String content;
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setType(String type) {
+ this.type = AlertType.valueOf(type.toUpperCase());
+ }
+
+ public AlertType getType() {
+ return type;
+ }
+
+ @JsonProperty("scheduledTime")
+ public void setScheduledTime(String dateTime) {
+ scheduledTime = dateTime;
+ }
+
+ public String getScheduledTime() {
+ return scheduledTime;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ @Override
+ public String toString() {
+ return "SetAlertPayload{"
+ + "token='"
+ + token
+ + '\''
+ + ", type="
+ + type
+ + ", scheduledTime='"
+ + scheduledTime
+ + '\''
+ + '}';
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/ApiConstants.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer;
+
+/**
+ * 定义了表示Audio Player模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class ApiConstants {
+ public static final String NAMESPACE = "ai.dueros.device_interface.audio_player";
+ public static final String NAME = "AudioPlayerInterface";
+
+ public static final class Events {
+ public static final class PlaybackStarted {
+ public static final String NAME = PlaybackStarted.class.getSimpleName();
+ }
+
+ public static final class PlaybackNearlyFinished {
+ public static final String NAME = PlaybackNearlyFinished.class.getSimpleName();
+ }
+
+ public static final class PlaybackStutterStarted {
+ public static final String NAME = PlaybackStutterStarted.class.getSimpleName();
+ }
+
+ public static final class PlaybackStutterFinished {
+ public static final String NAME = PlaybackStutterFinished.class.getSimpleName();
+ }
+
+ public static final class PlaybackFinished {
+ public static final String NAME = PlaybackFinished.class.getSimpleName();
+ }
+
+ public static final class PlaybackFailed {
+ public static final String NAME = PlaybackFailed.class.getSimpleName();
+ }
+
+ public static final class PlaybackStopped {
+ public static final String NAME = PlaybackStopped.class.getSimpleName();
+ }
+
+ public static final class PlaybackPaused {
+ public static final String NAME = PlaybackPaused.class.getSimpleName();
+ }
+
+ public static final class PlaybackResumed {
+ public static final String NAME = PlaybackResumed.class.getSimpleName();
+ }
+
+ public static final class PlaybackQueueCleared {
+ public static final String NAME = PlaybackQueueCleared.class.getSimpleName();
+ }
+
+ public static final class ProgressReportDelayElapsed {
+ public static final String NAME = ProgressReportDelayElapsed.class.getSimpleName();
+ }
+
+ public static final class ProgressReportIntervalElapsed {
+ public static final String NAME = ProgressReportIntervalElapsed.class
+ .getSimpleName();
+ }
+
+ public static final class PlaybackState {
+ public static final String NAME = PlaybackState.class.getSimpleName();
+ }
+ }
+
+ public static final class Directives {
+ public static final class Play {
+ public static final String NAME = Play.class.getSimpleName();
+ }
+
+ public static final class Stop {
+ public static final String NAME = Stop.class.getSimpleName();
+ }
+
+ public static final class ClearQueue {
+ public static final String NAME = ClearQueue.class.getSimpleName();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/AudioPlayerDeviceModule.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer;
+
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.ClearQueuePayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlayPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlaybackStatePayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.StopPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.report.AudioPlayStateReport;
+import com.baidu.duer.dcs.devicemodule.audioplayer.report.AudioPlayerProgressReporter;
+import com.baidu.duer.dcs.devicemodule.audioplayer.report.AudioPlayerTimer;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 音乐播放的端能力实现,处理指令:Play,Stop,ClearQueue
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class AudioPlayerDeviceModule extends BaseDeviceModule {
+ private static final String TAG = AudioPlayerDeviceModule.class.getSimpleName();
+ // 播放列表,先进先出
+ private LinkedList<PlayPayload.Stream> playQueue = new LinkedList<>();
+ // 当前stream的token
+ private String latestStreamToken = "";
+ // 当前manager的播放器
+ private IMediaPlayer mediaPlayer;
+ // 播放上报
+ private AudioPlayStateReport audioPlayStateReport;
+ // 开始时的缓冲时间
+ private long bufferingStartMilliseconds;
+ // 结束时的缓冲时间
+ private long bufferingEndMilliseconds;
+ // 用来统计状态的时间间隔offsetInMilliseconds
+ private AudioPlayerTimer timer;
+ // 播放状态的上报eg:暂停,完成等
+ private AudioPlayerProgressReporter progressReporter;
+ // 回调接口
+ private List<IMediaPlayer.IMediaPlayerListener> audioPlayerListeners;
+
+ public AudioPlayerDeviceModule(IMediaPlayer mediaPlayer,
+ IMessageSender messageSender) {
+ super(ApiConstants.NAMESPACE, messageSender);
+ this.mediaPlayer = mediaPlayer;
+ this.mediaPlayer.addMediaPlayerListener(mediaPlayerListener);
+ this.audioPlayStateReport = new AudioPlayStateReport(getNameSpace(),
+ messageSender,
+ audioPlayStateReportListener);
+ this.timer = new AudioPlayerTimer();
+ this.progressReporter = new AudioPlayerProgressReporter(
+ new ProgressReportDelayEventRunnable(audioPlayStateReport),
+ new ProgressReportIntervalEventRunnable(audioPlayStateReport), timer);
+ this.audioPlayerListeners = Collections.synchronizedList(
+ new ArrayList<IMediaPlayer.IMediaPlayerListener>());
+ }
+
+ @Override
+ public ClientContext clientContext() {
+ String namespace = ApiConstants.NAMESPACE;
+ String name = ApiConstants.Events.PlaybackState.NAME;
+ Header header = new Header(namespace, name);
+ PlaybackStatePayload payload = new PlaybackStatePayload(latestStreamToken,
+ mediaPlayer.getCurrentPosition(),
+ audioPlayStateReport.getState().name());
+ return new ClientContext(header, payload);
+ }
+
+ @Override
+ public void handleDirective(Directive directive) throws HandleDirectiveException {
+ LogUtil.d(TAG, "dcs-play-directive:" + directive.rawMessage);
+ String directiveName = directive.getName();
+ LogUtil.d(TAG, "dcs-play-directiveName:" + directiveName);
+ if (ApiConstants.Directives.Play.NAME.equals(directiveName)) {
+ handlePlay((PlayPayload) directive.getPayload());
+ } else if (ApiConstants.Directives.Stop.NAME.equals(directiveName)) {
+ handleStop((StopPayload) directive.getPayload());
+ } else if (ApiConstants.Directives.ClearQueue.NAME.equals(directiveName)) {
+ handleClearQueue((ClearQueuePayload) directive.getPayload());
+ } else {
+ String message = "audioPlayer cannot handle the directive";
+ throw (new HandleDirectiveException(
+ HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
+ }
+ }
+
+ /**
+ * 处理播放指令(Play)
+ *
+ * @param payload payload
+ */
+ private void handlePlay(PlayPayload payload) {
+ PlayPayload.AudioItem item = payload.audioItem;
+ if (payload.playBehavior == PlayPayload.PlayBehavior.REPLACE_ALL) {
+ clearAll();
+ } else if (payload.playBehavior == PlayPayload.PlayBehavior.REPLACE_ENQUEUED) {
+ clearEnqueued();
+ }
+ final PlayPayload.Stream stream = item.stream;
+ String streamUrl = stream.url;
+ String streamId = stream.token;
+ long offset = stream.offsetInMilliseconds;
+ LogUtil.i(TAG, "URL:" + streamUrl);
+ LogUtil.i(TAG, "StreamId:" + streamId);
+ LogUtil.i(TAG, "Offset:" + offset);
+ add(stream);
+ }
+
+ /**
+ * 处理停止指令(Stop)
+ *
+ * @param payload payload
+ */
+ private void handleStop(StopPayload payload) {
+ stop();
+ }
+
+ /**
+ * 处理清空队列指令(Stop)
+ *
+ * @param clearQueuePayload clearQueuePayload
+ */
+ private void handleClearQueue(ClearQueuePayload clearQueuePayload) {
+ // 清除播放列表,并停止当前播放的音频(如果有)
+ if (clearQueuePayload.clearBehavior == ClearQueuePayload.ClearBehavior.CLEAR_ALL) {
+ audioPlayStateReport.clearQueueAll();
+ clearAll();
+ } else if (clearQueuePayload.clearBehavior == ClearQueuePayload.ClearBehavior.CLEAR_ENQUEUED) {
+ // 清除播放列表,但不影响当前播放
+ audioPlayStateReport.clearQueueEnqueued();
+ clearEnqueued();
+ }
+ }
+
+ private void add(PlayPayload.Stream stream) {
+ String expectedPreviousToken = stream.expectedPreviousToken;
+ boolean startPlaying = playQueue.isEmpty();
+ if (expectedPreviousToken == null || latestStreamToken.isEmpty()
+ || latestStreamToken.equals(expectedPreviousToken)) {
+ playQueue.add(stream);
+ }
+ LogUtil.d(TAG, " coming playQueue size :" + playQueue.size());
+ if (startPlaying) {
+ startPlay();
+ }
+ }
+
+ /**
+ * 开始播放音乐
+ */
+ private void startPlay() {
+ if (playQueue.isEmpty()) {
+ LogUtil.d(TAG, "startPlay-playQueue isEmpty !!");
+ return;
+ }
+ PlayPayload.Stream currentStream = playQueue.peek();
+ if (currentStream == null) {
+ return;
+ }
+ latestStreamToken = currentStream.token;
+ String url = currentStream.url;
+ // 从哪个位置开始播放
+ long offset = currentStream.offsetInMilliseconds;
+ // 判断是否是流类型还是URL类型
+ if (currentStream.hasAttachedContent()) {
+ mediaPlayer.play(new IMediaPlayer.MediaResource(currentStream.getAttachedContent()));
+ } else {
+ mediaPlayer.play(new IMediaPlayer.MediaResource(url));
+ }
+ mediaPlayer.seekTo((int) offset);
+ }
+
+ private IMediaPlayer.IMediaPlayerListener mediaPlayerListener = new IMediaPlayer.SimpleMediaPlayerListener() {
+ // 是否处于暂停
+ private boolean isPause;
+ // 是否第一次到达了100
+ private boolean stutterFinished;
+ // 是否处于上报ProgressReport事件中
+ private boolean progressReporting;
+ // 是否处于缓冲中
+ private boolean bufferUnderRunInProgress;
+
+ @Override
+ public void onInit() {
+ super.onInit();
+ LogUtil.d(TAG, "onInit");
+ isPause = false;
+ stutterFinished = false;
+ progressReporting = false;
+ bufferUnderRunInProgress = false;
+ }
+
+ @Override
+ public void onPrepared() {
+ super.onPrepared();
+ LogUtil.d(TAG, "onPrepared");
+ fireOnPrepared();
+ }
+
+ @Override
+ public void onPlaying() {
+ super.onPlaying();
+ LogUtil.d(TAG, "onPlaying");
+ // 暂停后继续播放
+ if (isPause) {
+ isPause = false;
+ audioPlayStateReport.playbackResumed();
+ } else {
+ // 第一次播放
+ PlayPayload.Stream stream = playQueue.peek();
+ if (stream == null) {
+ return;
+ }
+ long offset = stream.offsetInMilliseconds;
+ LogUtil.d(TAG, "onPlaying---Duration----:" + mediaPlayer.getDuration());
+ timer.reset(offset, mediaPlayer.getDuration());
+
+ // 上报PlaybackStarted事件
+ audioPlayStateReport.playbackStarted();
+ }
+ startTimerAndProgressReporter();
+ fireOnPlaying();
+ }
+
+ @Override
+ public void onPaused() {
+ LogUtil.d(TAG, "onPaused");
+ stopTimerAndProgressReporter();
+ isPause = true;
+ audioPlayStateReport.playbackPaused();
+ fireOnPaused();
+ }
+
+ @Override
+ public void onStopped() {
+ super.onStopped();
+ stopTimerAndProgressReporter();
+ audioPlayStateReport.playbackStopped();
+ fireOnStopped();
+ }
+
+ @Override
+ public void onCompletion() {
+ LogUtil.d(TAG, "onCompletion");
+ stopTimerAndProgressReporter();
+ playQueue.poll();
+ audioPlayStateReport.playbackFinished();
+ audioPlayStateReport.playbackNearlyFinished();
+ if (!playQueue.isEmpty()) {
+ startPlay();
+ }
+ fireOnCompletion();
+ }
+
+ @Override
+ public void onRelease() {
+ LogUtil.d(TAG, "onError");
+ stopTimerAndProgressReporter();
+ fireOnRelease();
+ }
+
+ @Override
+ public void onError(String error, IMediaPlayer.ErrorType errorType) {
+ LogUtil.d(TAG, "onError");
+ playQueue.clear();
+ audioPlayStateReport.playbackFailed(errorType);
+ stopTimerAndProgressReporter();
+ fireOnError(error, errorType);
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+ LogUtil.d(TAG, "onBufferingUpdate:" + percent);
+ fireOnBufferingUpdate(percent);
+ PlayPayload.Stream stream = playQueue.peek();
+ if (stream == null) {
+ return;
+ }
+ // Play指令有progressReportDelayInMilliseconds
+ if (!progressReporting && stream.getProgressReportRequired()) {
+ LogUtil.d(TAG, "onBufferingUpdate:" + percent);
+ progressReporting = true;
+ progressReporter.disable();
+ progressReporter.setup(stream.progressReport);
+ long offset = stream.offsetInMilliseconds;
+ timer.reset(offset, mediaPlayer.getDuration());
+ startTimerAndProgressReporter();
+ }
+
+ // 已经缓冲完成了
+ if (stutterFinished) {
+ return;
+ }
+ // 开始缓冲
+ if (!bufferUnderRunInProgress) {
+ LogUtil.d(TAG, "==playbackStutterStarted");
+ bufferUnderRunInProgress = true;
+ bufferingStartMilliseconds = System.currentTimeMillis();
+ audioPlayStateReport.playbackStutterStarted();
+ }
+ // 缓冲完毕后上报playbackStutterFinished
+ if (percent >= 100) {
+ stutterFinished = true;
+ bufferingEndMilliseconds = System.currentTimeMillis();
+ audioPlayStateReport.playbackStutterFinished();
+ }
+ }
+ };
+
+ private void startTimerAndProgressReporter() {
+ timer.start();
+ if (progressReporter.isSetup()) {
+ progressReporter.start();
+ }
+ }
+
+ private void stopTimerAndProgressReporter() {
+ timer.stop();
+ progressReporter.stop();
+ }
+
+ private void clearAll() {
+ stop();
+ playQueue.clear();
+ }
+
+ private void clearEnqueued() {
+ PlayPayload.Stream top = playQueue.poll();
+ playQueue.clear();
+ if (top != null) {
+ playQueue.add(top);
+ }
+ }
+
+ private void stop() {
+ if (!playQueue.isEmpty() && isPlayingOrPaused()) {
+ stopTimerAndProgressReporter();
+ // 要把播放策略中的对应的那一条删除了
+ mediaPlayer.stop();
+ }
+ }
+
+ private boolean isPlaying() {
+ return (audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.PLAYING
+ || audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.PAUSED
+ || audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.BUFFER_UNDERRUN);
+ }
+
+ private boolean isPlayingOrPaused() {
+ return isPlaying() || audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.PAUSED;
+ }
+
+ @Override
+ public void release() {
+ if (mediaPlayer != null) {
+ mediaPlayer.release();
+ mediaPlayer.removeMediaPlayerListener(mediaPlayerListener);
+ }
+ stopTimerAndProgressReporter();
+ audioPlayerListeners.clear();
+ }
+
+ /**
+ * 播放上报时需要的信息
+ */
+ private AudioPlayStateReport.AudioPlayStateReportListener audioPlayStateReportListener =
+ new AudioPlayStateReport.AudioPlayStateReportListener() {
+ @Override
+ public String getCurrentStreamToken() {
+ return latestStreamToken;
+ }
+
+ @Override
+ public long getCurrentOffsetInMilliseconds() {
+ return getCurrentOffsetInMillisecondsByTime();
+ }
+
+ @Override
+ public long getStutterDurationInMilliseconds() {
+ // 缓冲时间ms
+ return bufferingEndMilliseconds - bufferingStartMilliseconds;
+ }
+ };
+
+ private long getCurrentOffsetInMillisecondsByTime() {
+ AudioPlayStateReport.AudioPlayerState playerActivity = audioPlayStateReport.getState();
+ long offset;
+ switch (playerActivity) {
+ case PLAYING:
+ case PAUSED:
+ case BUFFER_UNDERRUN:
+ case STOPPED:
+ case FINISHED:
+ offset = timer.getOffsetInMilliseconds();
+ break;
+ case IDLE:
+ default:
+ offset = 0;
+ }
+ LogUtil.d(TAG, "getCurrentOffsetInMilliseconds offset:" + offset);
+ return offset;
+ }
+
+ private static class ProgressReportDelayEventRunnable implements Runnable {
+ private final AudioPlayStateReport audioPlayStateReport;
+
+ ProgressReportDelayEventRunnable(AudioPlayStateReport audioPlayStateReport) {
+ this.audioPlayStateReport = audioPlayStateReport;
+ }
+
+ @Override
+ public void run() {
+ audioPlayStateReport.reportProgressDelay();
+ }
+ }
+
+ private static class ProgressReportIntervalEventRunnable implements Runnable {
+ private final AudioPlayStateReport audioPlayStateReport;
+
+ ProgressReportIntervalEventRunnable(AudioPlayStateReport audioPlayStateReport) {
+ this.audioPlayStateReport = audioPlayStateReport;
+ }
+
+ @Override
+ public void run() {
+ audioPlayStateReport.reportProgressInterval();
+ }
+ }
+
+ private void fireOnPrepared() {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onPrepared();
+ }
+ }
+
+ private void fireOnRelease() {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onRelease();
+ }
+ }
+
+ private void fireOnPlaying() {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onPlaying();
+ }
+ }
+
+ private void fireOnPaused() {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onPaused();
+ }
+ }
+
+ private void fireOnStopped() {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onStopped();
+ }
+ }
+
+ private void fireOnCompletion() {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onCompletion();
+ }
+ }
+
+ private void fireOnError(String error, IMediaPlayer.ErrorType errorType) {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onError(error, errorType);
+ }
+ }
+
+ private void fireOnBufferingUpdate(int percent) {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onBufferingUpdate(percent);
+ }
+ }
+
+ private void fireBufferingStart() {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onBufferingStart();
+ }
+ }
+
+ private void fireBufferingEnd() {
+ for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+ listener.onBufferingEnd();
+ }
+ }
+
+ public void addAudioPlayListener(IMediaPlayer.IMediaPlayerListener listener) {
+ audioPlayerListeners.add(listener);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/AudioPlayerPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Audio Player模块上报各种事件的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/4.
+ */
+public class AudioPlayerPayload extends Payload {
+ public String token;
+ public long offsetInMilliseconds;
+
+ public AudioPlayerPayload(String token, long offsetInMilliseconds) {
+ this.token = token;
+ this.offsetInMilliseconds = offsetInMilliseconds;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/ClearQueuePayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * ClearQueue指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class ClearQueuePayload extends Payload {
+ public enum ClearBehavior {
+ CLEAR_ENQUEUED,
+ CLEAR_ALL
+ }
+
+ public ClearBehavior clearBehavior;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlayPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+import java.io.InputStream;
+import java.io.Serializable;
+
+/**
+ * Audio Player模块Play指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class PlayPayload extends Payload {
+ public PlayBehavior playBehavior;
+ public AudioItem audioItem;
+
+ public enum PlayBehavior {
+ REPLACE_ALL,
+ ENQUEUE,
+ REPLACE_ENQUEUED
+ }
+
+ public static class AudioItem implements Serializable {
+ public String audioItemId;
+ public Stream stream;
+ }
+
+ public static class Stream implements Serializable {
+ public String url;
+ public String token;
+ public String expiryTime;
+ public long offsetInMilliseconds;
+ public String expectedPreviousToken;
+ public String streamFormat;
+ public boolean urlIsAContentId;
+ public ProgressReport progressReport;
+ @JsonIgnore
+ public InputStream attachedContent;
+
+ public boolean getProgressReportRequired() {
+ return progressReport != null && progressReport.isRequired();
+ }
+
+ public void setUrl(String url) {
+ urlIsAContentId = url.startsWith("cid");
+ if (urlIsAContentId) {
+ this.url = url.substring(4);
+ } else {
+ this.url = url;
+ }
+ }
+
+ public boolean requiresAttachedContent() {
+ return urlIsAContentId && !hasAttachedContent();
+ }
+
+ public boolean hasAttachedContent() {
+ return attachedContent != null;
+ }
+
+ @JsonIgnore
+ public InputStream getAttachedContent() {
+ return attachedContent;
+ }
+ }
+
+ public static class ProgressReport implements Serializable {
+ public long progressReportDelayInMilliseconds;
+ public long progressReportIntervalInMilliseconds;
+
+ public boolean isRequired() {
+ return progressReportDelayInMilliseconds > 0 || progressReportIntervalInMilliseconds > 0;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlaybackFailedPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+
+/**
+ * Audio Player模块上报PlaybackFailed事件对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/8.
+ */
+public class PlaybackFailedPayload extends Payload {
+ private String token;
+ private PlaybackStatePayload currentPlaybackState;
+ private ErrorStructure error;
+
+ public PlaybackFailedPayload(String token, PlaybackStatePayload playbackState,
+ IMediaPlayer.ErrorType errorType) {
+ this.token = token;
+ this.currentPlaybackState = playbackState;
+ error = new ErrorStructure(errorType);
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public PlaybackStatePayload getCurrentPlaybackState() {
+ return currentPlaybackState;
+ }
+
+ public ErrorStructure getError() {
+ return error;
+ }
+
+ private static final class ErrorStructure {
+ private IMediaPlayer.ErrorType type;
+ private String message;
+
+ public ErrorStructure(IMediaPlayer.ErrorType type) {
+ this.type = type;
+ this.message = type.getMessage();
+ }
+
+ public IMediaPlayer.ErrorType getType() {
+ return type;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlaybackStatePayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Audio Player模块端状态对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class PlaybackStatePayload extends Payload {
+ public String token;
+ public long offsetInMilliseconds;
+ public String playerActivity;
+
+ public PlaybackStatePayload(String token, long offsetInMilliseconds, String playerActivity) {
+ this.token = token;
+ this.offsetInMilliseconds = offsetInMilliseconds;
+ this.playerActivity = playerActivity;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlaybackStutterFinishedPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+/**
+ * Audio Player模块上报PlaybackStutterFinished事件对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/4.
+ */
+public class PlaybackStutterFinishedPayload extends AudioPlayerPayload {
+ public long stutterDurationInMilliseconds;
+
+ public PlaybackStutterFinishedPayload(String token, long offsetInMilliseconds,
+ long stutterDurationInMilliseconds) {
+ super(token, offsetInMilliseconds);
+ this.stutterDurationInMilliseconds = stutterDurationInMilliseconds;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/StopPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Audio Player模块Stop指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/6.
+ */
+public class StopPayload extends Payload {
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/report/AudioPlayStateReport.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.report;
+
+import com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.AudioPlayerPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlaybackFailedPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlaybackStatePayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlaybackStutterFinishedPayload;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+
+/**
+ * Audio Player模块各种事件上报的处理,同时维护当前的端状态
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class AudioPlayStateReport {
+ public enum AudioPlayerState {
+ IDLE,
+ PLAYING,
+ PAUSED,
+ FINISHED,
+ STOPPED,
+ BUFFER_UNDERRUN
+ }
+
+ private AudioPlayerState currentState = AudioPlayerState.FINISHED;
+ private IMessageSender messageSender;
+ private String namespace;
+ private AudioPlayStateReportListener audioPlayStateReportListener;
+
+ public AudioPlayStateReport(String namespace, IMessageSender messageSender,
+ AudioPlayStateReportListener audioPlayStateReportListener) {
+ this.namespace = namespace;
+ this.messageSender = messageSender;
+ this.audioPlayStateReportListener = audioPlayStateReportListener;
+
+ }
+
+ public AudioPlayerState getState() {
+ return currentState;
+ }
+
+ public void playbackResumed() {
+ currentState = AudioPlayerState.PLAYING;
+ Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackResumed.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(event);
+ }
+
+ public void playbackFinished() {
+ currentState = AudioPlayerState.FINISHED;
+ Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackFinished.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(event);
+ }
+
+ public void playbackStarted() {
+ currentState = AudioPlayerState.PLAYING;
+ Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackStarted.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(event);
+ }
+
+ public void playbackFailed(IMediaPlayer.ErrorType errorType) {
+ currentState = AudioPlayerState.STOPPED;
+ long offset = audioPlayStateReportListener.getCurrentOffsetInMilliseconds();
+ PlaybackStatePayload playbackStatePayload =
+ new PlaybackStatePayload(audioPlayStateReportListener.getCurrentStreamToken(),
+ offset, currentState.toString());
+
+ Header header = new MessageIdHeader(namespace,
+ ApiConstants.Events.PlaybackFailed.NAME);
+ Event event = new Event(header,
+ new PlaybackFailedPayload(audioPlayStateReportListener.getCurrentStreamToken(),
+ playbackStatePayload, errorType));
+
+ messageSender.sendEvent(event);
+ }
+
+ public void playbackPaused() {
+ currentState = AudioPlayerState.PAUSED;
+ Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackPaused.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(event);
+ }
+
+ public void playbackNearlyFinished() {
+ currentState = AudioPlayerState.FINISHED;
+ Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackNearlyFinished.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(event);
+ }
+
+ public void playbackStutterStarted() {
+ currentState = AudioPlayerState.BUFFER_UNDERRUN;
+ Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackStutterStarted.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(event);
+ }
+
+ public void playbackStutterFinished() {
+ currentState = AudioPlayerState.PLAYING;
+ Event event = createAudioPlayerPlaybackStutterFinishedEvent(
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds(),
+ audioPlayStateReportListener.getStutterDurationInMilliseconds()
+ );
+ messageSender.sendEvent(event);
+ }
+
+ public void playbackStopped() {
+ currentState = AudioPlayerState.STOPPED;
+ Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackStopped.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(event);
+ }
+
+ public void clearQueueAll() {
+ Event event = createAudioPlayerPlaybackQueueClearedEvent();
+ messageSender.sendEvent(event);
+ if (currentState == AudioPlayerState.PLAYING || currentState == AudioPlayerState.PAUSED
+ || currentState == AudioPlayerState.BUFFER_UNDERRUN) {
+ currentState = AudioPlayerState.STOPPED;
+ Event eventStopped = createAudioPlayerEvent(ApiConstants.Events.PlaybackStopped.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(eventStopped);
+ }
+ }
+
+ public void clearQueueEnqueued() {
+ Event event = createAudioPlayerPlaybackQueueClearedEvent();
+ messageSender.sendEvent(event);
+ }
+
+ private Event createAudioPlayerEvent(String name, String streamToken,
+ long offsetInMilliseconds) {
+ Header header = new MessageIdHeader(namespace, name);
+ Payload payload = new AudioPlayerPayload(streamToken, offsetInMilliseconds);
+ return new Event(header, payload);
+ }
+
+ private Event createAudioPlayerPlaybackQueueClearedEvent() {
+ Header header = new MessageIdHeader(ApiConstants.NAMESPACE,
+ ApiConstants.Events.PlaybackQueueCleared.NAME);
+ return new Event(header, new Payload());
+ }
+
+ private Event createAudioPlayerPlaybackStutterFinishedEvent(String streamToken,
+ long offsetInMilliseconds,
+ long stutterDurationInMilliseconds) {
+ Header header = new MessageIdHeader(ApiConstants.NAMESPACE,
+ ApiConstants.Events.PlaybackStutterFinished.NAME);
+ return new Event(header, new PlaybackStutterFinishedPayload(streamToken,
+ offsetInMilliseconds, stutterDurationInMilliseconds));
+ }
+
+ public void reportProgressDelay() {
+ currentState = AudioPlayerState.PLAYING;
+ Event event = createAudioPlayerEvent(ApiConstants.Events.ProgressReportDelayElapsed.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(event);
+ }
+
+ public void reportProgressInterval() {
+ currentState = AudioPlayerState.PLAYING;
+ Event event = createAudioPlayerEvent(ApiConstants.Events.ProgressReportIntervalElapsed.NAME,
+ audioPlayStateReportListener.getCurrentStreamToken(),
+ audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+ messageSender.sendEvent(event);
+ }
+
+ public interface AudioPlayStateReportListener {
+ String getCurrentStreamToken();
+
+ long getCurrentOffsetInMilliseconds();
+
+ long getStutterDurationInMilliseconds();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/report/AudioPlayerProgressReporter.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.report;
+
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlayPayload;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 当服务器返回Play指令有progressReportDelayInMilliseconds,
+ * <p>
+ * ProgressReportDelayElapsed和ProgressReportIntervalElapsed事件的上报
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/22.
+ */
+public class AudioPlayerProgressReporter {
+ private final ScheduledExecutorService eventScheduler = Executors.newScheduledThreadPool(1);
+ private ScheduledFuture<?> progressReportDelayFuture;
+ private ScheduledFuture<?> progressReportIntervalFuture;
+ private final Runnable progressReportDelayRunnable;
+ private final Runnable progressReportIntervalRunnable;
+ private final AudioPlayerTimer audioPlayerTimer;
+ private long progressReportDelay;
+ private long progressReportInterval;
+ private boolean isSetup;
+
+ public AudioPlayerProgressReporter(Runnable progressReportDelayRunnable,
+ Runnable progressReportIntervalRunnable,
+ AudioPlayerTimer audioPlayerTimer) {
+ if (progressReportDelayRunnable == null
+ || progressReportIntervalRunnable == null
+ || audioPlayerTimer == null) {
+ throw new IllegalArgumentException("All arguments must be provided.");
+ }
+ this.progressReportDelayRunnable = progressReportDelayRunnable;
+ this.progressReportIntervalRunnable = progressReportIntervalRunnable;
+ this.audioPlayerTimer = audioPlayerTimer;
+ this.isSetup = false;
+ }
+
+ public synchronized void setup(PlayPayload.ProgressReport progressReport) {
+ if (progressReport == null) {
+ String errorMessage = "ProgressReport must not be null.";
+ throw new IllegalArgumentException(errorMessage);
+ }
+ if (isSetup) {
+ String errorMessage = "AudioPlayerProgressReporter has already been setup. "
+ + "Please disable it before setting it up again.";
+ throw new IllegalStateException(errorMessage);
+ }
+
+ cancelEvents();
+ progressReportDelay = progressReport.progressReportDelayInMilliseconds;
+ progressReportInterval = progressReport.progressReportIntervalInMilliseconds;
+ isSetup = true;
+ }
+
+ public synchronized void disable() {
+ isSetup = false;
+ cancelEvents();
+ progressReportDelay = 0;
+ progressReportInterval = 0;
+ }
+
+ public synchronized void start() {
+ cancelEvents();
+
+ if (!isSetup) {
+ String errorMessage = "AudioPlayerProgressReporter cannot be started "
+ + "because it has not been setup yet.";
+ throw new IllegalStateException(errorMessage);
+ }
+
+ long currentOffsetIntoTrack = audioPlayerTimer.getOffsetInMilliseconds();
+
+ long timeUntilDelayReport = progressReportDelay - currentOffsetIntoTrack;
+ if (timeUntilDelayReport > 0) {
+ scheduleDelayEvent(timeUntilDelayReport);
+ }
+
+ long timeUntilIntervalReport = progressReportInterval == 0 ? 0 :
+ progressReportInterval - (currentOffsetIntoTrack % progressReportInterval);
+ if (timeUntilIntervalReport > 0) {
+ scheduleIntervalEvent(timeUntilIntervalReport, progressReportInterval);
+ }
+ }
+
+ public synchronized void stop() {
+ cancelEvents();
+ }
+
+ public synchronized boolean isSetup() {
+ return isSetup;
+ }
+
+ private void scheduleDelayEvent(long delay) {
+ progressReportDelayFuture = eventScheduler.schedule(progressReportDelayRunnable, delay,
+ TimeUnit.MILLISECONDS);
+ }
+
+ private void scheduleIntervalEvent(long delay, long interval) {
+ progressReportIntervalFuture = eventScheduler.scheduleAtFixedRate(
+ progressReportIntervalRunnable, delay, interval, TimeUnit.MILLISECONDS);
+ }
+
+ private void cancelEvents() {
+ if (progressReportDelayFuture != null && !progressReportDelayFuture.isDone()) {
+ progressReportDelayFuture.cancel(false);
+ }
+ if (progressReportIntervalFuture != null && !progressReportIntervalFuture.isDone()) {
+ progressReportIntervalFuture.cancel(false);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/report/AudioPlayerTimer.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.audioplayer.report;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * audio 播放统计OffsetInMilliseconds
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/22.
+ */
+public class AudioPlayerTimer {
+ private long startNano;
+ private long elapsedTimeMs;
+ private long totalStreamLength;
+ private boolean isPlaying = false;
+
+ public synchronized void start() {
+ startNano = System.nanoTime();
+ isPlaying = true;
+ }
+
+ public synchronized void stop() {
+ if (isPlaying) {
+ elapsedTimeMs += getCurrentOffsetInMilliseconds();
+ isPlaying = false;
+ }
+ }
+
+ public synchronized long getOffsetInMilliseconds() {
+ long offset = elapsedTimeMs + (isPlaying ? getCurrentOffsetInMilliseconds() : 0);
+ if (totalStreamLength > 0) {
+ offset = Math.min(totalStreamLength, offset);
+ }
+ return offset;
+ }
+
+ public void reset() {
+ reset(0);
+ }
+
+ public void reset(long startPosition) {
+ reset(startPosition, -1);
+ }
+
+ public synchronized void reset(long startPosition, long maxPosition) {
+ elapsedTimeMs = startPosition;
+ isPlaying = false;
+ startNano = System.nanoTime();
+ totalStreamLength = maxPosition;
+ }
+
+ private long getCurrentOffsetInMilliseconds() {
+ return TimeUnit.MILLISECONDS.convert(System.nanoTime() - startNano, TimeUnit.NANOSECONDS);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/playbackcontroller/ApiConstants.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.playbackcontroller;
+
+/**
+ * 定义了表示PlaybackController模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+ public static final String NAMESPACE = "ai.dueros.device_interface.playback_controller";
+ public static final String NAME = "PlaybackControllerInterface";
+
+ public static final class Events {
+ public static final class NextCommandIssued {
+ public static final String NAME = NextCommandIssued.class.getSimpleName();
+ }
+
+ public static final class PreviousCommandIssued {
+ public static final String NAME = PreviousCommandIssued.class.getSimpleName();
+ }
+
+ public static final class PlayCommandIssued {
+ public static final String NAME = PlayCommandIssued.class.getSimpleName();
+ }
+
+ public static final class PauseCommandIssued {
+ public static final String NAME = PauseCommandIssued.class.getSimpleName();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/playbackcontroller/PlaybackControllerDeviceModule.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.playbackcontroller;
+
+import com.baidu.duer.dcs.devicemodule.alerts.AlertsDeviceModule;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IPlaybackController;
+
+/**
+ * 音频播放控制
+ * <p>
+ * 用户按了端上的播放/暂停等控制按钮,或者通过端上的GUI进行了此类操作时,上报PlayCommandIssued、PauseCommandIssued等事件
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class PlaybackControllerDeviceModule extends BaseDeviceModule {
+ private AlertsDeviceModule mAlertsDeviceModule;
+
+ public enum PlaybackAction {
+ PLAY,
+ PAUSE,
+ PREVIOUS,
+ NEXT
+ }
+
+ public PlaybackControllerDeviceModule(IPlaybackController playback, IMessageSender messageSender,
+ AlertsDeviceModule alertsDeviceModule) {
+ super(ApiConstants.NAMESPACE, messageSender);
+ this.mAlertsDeviceModule = alertsDeviceModule;
+ playback.registerPlaybackListener(new IPlaybackController.IPlaybackListener() {
+ @Override
+ public void onPlay(IResponseListener responseListener) {
+ handlePlaybackAction(PlaybackAction.PLAY, responseListener);
+ }
+
+ @Override
+ public void onPause(IResponseListener responseListener) {
+ handlePlaybackAction(PlaybackAction.PAUSE, responseListener);
+ }
+
+ @Override
+ public void onPrevious(IResponseListener responseListener) {
+ handlePlaybackAction(PlaybackAction.PREVIOUS, responseListener);
+ }
+
+ @Override
+ public void onNext(IResponseListener responseListener) {
+ handlePlaybackAction(PlaybackAction.NEXT, responseListener);
+ }
+ });
+ }
+
+ @Override
+ public ClientContext clientContext() {
+ return null;
+ }
+
+ @Override
+ public void handleDirective(Directive directive) throws HandleDirectiveException {
+ }
+
+ @Override
+ public void release() {
+ }
+
+ private void handlePlaybackAction(PlaybackAction action, IResponseListener responseListener) {
+ switch (action) {
+ case PLAY:
+ if (mAlertsDeviceModule.hasActiveAlerts()) {
+ mAlertsDeviceModule.stopActiveAlert();
+ } else {
+ Event event = createPlaybackControllerEvent(ApiConstants.Events.PlayCommandIssued.NAME);
+ messageSender.sentEventWithClientContext(event, responseListener);
+ }
+ break;
+ case PAUSE:
+ if (mAlertsDeviceModule.hasActiveAlerts()) {
+ mAlertsDeviceModule.stopActiveAlert();
+ } else {
+ Event event = createPlaybackControllerEvent(ApiConstants.Events.PauseCommandIssued.NAME);
+ messageSender.sentEventWithClientContext(event, responseListener);
+ }
+ break;
+ case PREVIOUS:
+ Event event = createPlaybackControllerEvent(ApiConstants.Events.PreviousCommandIssued.NAME);
+ messageSender.sentEventWithClientContext(event, responseListener);
+ break;
+ case NEXT:
+ Event eventNext = createPlaybackControllerEvent(ApiConstants.Events.NextCommandIssued.NAME);
+ messageSender.sentEventWithClientContext(eventNext, responseListener);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private Event createPlaybackControllerEvent(String name) {
+ Header header = new MessageIdHeader(ApiConstants.NAMESPACE, name);
+ return new Event(header, new Payload());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/ApiConstants.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.screen;
+
+/**
+ * 定义了表示Screen模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+ public static final String NAMESPACE = "ai.dueros.device_interface.screen";
+ public static final String NAME = "ScreenInterface";
+
+ public static final class Events {
+ public static final class LinkClicked {
+ public static final String NAME = LinkClicked.class.getSimpleName();
+ }
+ }
+
+ public static final class Directives {
+ public static final class HtmlView {
+ public static final String NAME = HtmlView.class.getSimpleName();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/ScreenDeviceModule.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.screen;
+
+import com.baidu.duer.dcs.devicemodule.screen.message.HtmlPayload;
+import com.baidu.duer.dcs.devicemodule.screen.message.LinkClickedPayload;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IWebView;
+
+/**
+ * Screen模块处理并执行服务下发的指令,如HtmlView指令,以及发送事件,如LinkClicked事件
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class ScreenDeviceModule extends BaseDeviceModule {
+ private final IWebView webView;
+
+ public ScreenDeviceModule(IWebView webView, IMessageSender messageSender) {
+ super(ApiConstants.NAMESPACE, messageSender);
+ this.webView = webView;
+ webView.addWebViewListener(new IWebView.IWebViewListener() {
+ @Override
+ public void onLinkClicked(String url) {
+ sendLinkClickedEvent(url);
+ }
+ });
+ }
+
+ @Override
+ public ClientContext clientContext() {
+ return null;
+ }
+
+ @Override
+ public void handleDirective(Directive directive) {
+ String name = directive.header.getName();
+ if (name.equals(ApiConstants.Directives.HtmlView.NAME)) {
+ handleHtmlPayload(directive.getPayload());
+ }
+ }
+
+ @Override
+ public void release() {
+ }
+
+ private void handleHtmlPayload(Payload payload) {
+ if (payload instanceof HtmlPayload) {
+ HtmlPayload htmlPayload = (HtmlPayload) payload;
+ webView.loadUrl(htmlPayload.getUrl());
+ }
+ }
+
+ private void sendLinkClickedEvent(String url) {
+ String name = ApiConstants.Events.LinkClicked.NAME;
+ Header header = new MessageIdHeader(getNameSpace(), name);
+
+ LinkClickedPayload linkClickedPayload = new LinkClickedPayload(url);
+ Event event = new Event(header, linkClickedPayload);
+ if (messageSender != null) {
+ messageSender.sendEvent(event);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/message/HtmlPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.screen.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import java.io.Serializable;
+
+/**
+ * HtmlView指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class HtmlPayload extends Payload implements Serializable {
+ private String url;
+ private String token;
+
+ public HtmlPayload() {
+ }
+
+ public HtmlPayload(String url, String token) {
+ this.url = url;
+ this.token = token;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public String getToken() {
+ return token;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/message/LinkClickedPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.screen.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * LinkClicked事件对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class LinkClickedPayload extends Payload {
+ private String url;
+
+ public LinkClickedPayload(String url) {
+ this.url = url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/ApiConstants.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.speakcontroller;
+
+/**
+ * 定义了表示SpeakController模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+ public static final String NAMESPACE = "ai.dueros.device_interface.speaker_controller";
+ public static final String NAME = "SpeakerControllerInterface";
+
+ public static final class Events {
+ public static final class VolumeChanged {
+ public static final String NAME = VolumeChanged.class.getSimpleName();
+ }
+
+ public static final class MuteChanged {
+ public static final String NAME = MuteChanged.class.getSimpleName();
+ }
+
+ public static final class VolumeState {
+ public static final String NAME = VolumeState.class.getSimpleName();
+ }
+ }
+
+ public static final class Directives {
+ public static final class SetVolume {
+ public static final String NAME = SetVolume.class.getSimpleName();
+ }
+
+ public static final class AdjustVolume {
+ public static final String NAME = AdjustVolume.class.getSimpleName();
+ }
+
+ public static final class SetMute {
+ public static final String NAME = SetMute.class.getSimpleName();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/SpeakerControllerDeviceModule.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.speakcontroller;
+
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.AdjustVolumePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.MuteChangedPayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.SetMutePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.SetVolumePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.VolumeStatePayload;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException.ExceptionType;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.BaseMultiChannelMediaPlayer;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * SpeakerController模块处理服务下发的SetVolume、AdjustVolume、SetMute指令,发送VolumeChanged、MuteChanged事件,
+ * 以及维护自身的端状态
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class SpeakerControllerDeviceModule extends BaseDeviceModule {
+ private final BaseMultiChannelMediaPlayer.ISpeakerController speakerController;
+
+ public SpeakerControllerDeviceModule(BaseMultiChannelMediaPlayer.ISpeakerController speakerController,
+ IMessageSender messageSender) {
+ super(ApiConstants.NAMESPACE, messageSender);
+ this.speakerController = speakerController;
+ }
+
+ @Override
+ public ClientContext clientContext() {
+ String namespace = getNameSpace();
+ String name = ApiConstants.Events.VolumeState.NAME;
+ Header header = new Header(namespace, name);
+ long volume = (long) (speakerController.getVolume() * 100.0F);
+ boolean mute = speakerController.getMute();
+ VolumeStatePayload payload = new VolumeStatePayload(volume, mute);
+ return new ClientContext(header, payload);
+ }
+
+ @Override
+ public void handleDirective(Directive directive) throws HandleDirectiveException {
+ Header header = directive.header;
+ String name = header.getName();
+ Payload payload = directive.getPayload();
+ if (name.equals(ApiConstants.Directives.AdjustVolume.NAME)) {
+ if (payload instanceof AdjustVolumePayload) {
+ AdjustVolumePayload adjustVolumePayload = (AdjustVolumePayload) directive.getPayload();
+ float increment = (float) adjustVolumePayload.getVolume() / 100.0F;
+ float volume = speakerController.getVolume() + increment;
+ volume = Math.min(1.0F, Math.max(volume, -1.0F));
+ setVolume(volume);
+ }
+ } else if (name.equals(ApiConstants.Directives.SetVolume.NAME)) {
+ if (payload instanceof SetVolumePayload) {
+ SetVolumePayload setVolumePayload = (SetVolumePayload) payload;
+ float volume = (float) setVolumePayload.getVolume() / 100.0F;
+ this.setVolume(volume);
+ }
+ } else if (name.equals(ApiConstants.Directives.SetMute.NAME)) {
+ if (payload instanceof SetMutePayload) {
+ SetMutePayload setMutePayload = (SetMutePayload) payload;
+ setMute(setMutePayload.getMute());
+ }
+ } else {
+ String message = "SpeakerController cannot handle the directive";
+ throw new HandleDirectiveException(ExceptionType.UNSUPPORTED_OPERATION, message);
+ }
+ }
+
+ @Override
+ public void release() {
+
+ }
+
+ private void setVolume(float volume) {
+ speakerController.setVolume(volume);
+ messageSender.sendEvent(volumeChangedEvent());
+ }
+
+ private void setMute(boolean mute) {
+ speakerController.setMute(mute);
+ messageSender.sendEvent(muteChangedEvent());
+ }
+
+ private Event volumeChangedEvent() {
+ String nameSpace = getNameSpace();
+ String name = ApiConstants.Events.VolumeChanged.NAME;
+ MessageIdHeader header = new MessageIdHeader(nameSpace, name);
+ VolumeStatePayload payload = new VolumeStatePayload(getVolume(), isMuted());
+ return new Event(header, payload);
+ }
+
+ private Event muteChangedEvent() {
+ String nameSpace = getNameSpace();
+ String name = ApiConstants.Events.MuteChanged.NAME;
+ MessageIdHeader header = new MessageIdHeader(nameSpace, name);
+ MuteChangedPayload payload = new MuteChangedPayload(getVolume(), isMuted());
+ return new Event(header, payload);
+ }
+
+ private long getVolume() {
+ return (long) (speakerController.getVolume() * 100.0F);
+ }
+
+ private boolean isMuted() {
+ return speakerController.getMute();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/AdjustVolumePayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * adjustVolume指令对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class AdjustVolumePayload extends Payload {
+ private long volume;
+
+ public AdjustVolumePayload() {
+ }
+
+ public AdjustVolumePayload(long volume) {
+ this.volume = volume;
+ }
+
+ public void setVolume(long volume) {
+ this.volume = volume;
+ }
+
+ public long getVolume() {
+ return volume;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/MuteChangedPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * 上报MuteChanged事件对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class MuteChangedPayload extends Payload {
+ private long volume;
+ private boolean muted;
+
+ public MuteChangedPayload(long volume, boolean muted) {
+ this.volume = volume;
+ this.muted = muted;
+ }
+
+ public void setVolume(long volume) {
+ this.volume = volume;
+ }
+
+ public long getVolume() {
+ return this.volume;
+ }
+
+ public void setMuted(boolean muted) {
+ this.muted = muted;
+ }
+
+ public boolean getMuted() {
+ return muted;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/SetMutePayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * setMuted指令对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class SetMutePayload extends Payload {
+ private boolean mute;
+
+ public SetMutePayload() {
+ }
+
+ public SetMutePayload(boolean mute) {
+ this.mute = mute;
+ }
+
+ public void setMute(boolean mute) {
+ this.mute = mute;
+ }
+
+ public boolean getMute() {
+ return this.mute;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/SetVolumePayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * setVolume指令对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class SetVolumePayload extends Payload {
+ private long volume;
+
+ public SetVolumePayload() {
+ }
+
+ public SetVolumePayload(long volume) {
+ this.volume = volume;
+ }
+
+ public void setVolume(long volume) {
+ this.volume = volume;
+ }
+
+ public long getVolume() {
+ return volume;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/VolumeStatePayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * 本模块端状态对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class VolumeStatePayload extends Payload {
+ private long volume;
+ private boolean muted;
+
+ public VolumeStatePayload() {
+ }
+
+ public VolumeStatePayload(long volume, boolean muted) {
+ this.volume = volume;
+ this.muted = muted;
+ }
+
+ public void setVolume(long volume) {
+ this.volume = volume;
+ }
+
+ public long getVolume() {
+ return this.volume;
+ }
+
+ public void setMuted(boolean muted) {
+ this.muted = muted;
+ }
+
+ public boolean getMuted() {
+ return muted;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/ApiConstants.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.system;
+
+/**
+ * 定义了表示System模块的namespace、name,以及其事件、指令、异常的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+ public static final String NAMESPACE = "ai.dueros.device_interface.system";
+ public static final String NAME = "SystemInterface";
+
+ public static final class Events {
+ public static final class SynchronizeState {
+ public static final String NAME = SynchronizeState.class.getSimpleName();
+ }
+
+ public static final class ExceptionEncountered {
+ public static final String NAME = ExceptionEncountered.class.getSimpleName();
+ }
+
+ public static final class UserInactivityReport {
+ public static final String NAME = UserInactivityReport.class.getSimpleName();
+ }
+ }
+
+ public static final class Directives {
+ public static final class ResetUserInactivity {
+ public static final String NAME = ResetUserInactivity.class.getSimpleName();
+ }
+
+ public static final class SetEndpoint {
+ public static final String NAME = SetEndpoint.class.getSimpleName();
+ }
+
+ public static final class ThrowException {
+ public static final String NAME = ThrowException.class.getSimpleName();
+ }
+ }
+
+ public static final class Exception {
+ public static final String NAME = Exception.class.getSimpleName();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/HandleDirectiveException.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.system;
+
+/**
+ * 指令没有处理异常
+ * <p>
+ * Created by wuruisheng on 2017/6/3.
+ */
+public class HandleDirectiveException extends Exception {
+ private ExceptionType exceptionType;
+
+ public HandleDirectiveException(ExceptionType exceptionType, String message) {
+ super(message);
+ this.exceptionType = exceptionType;
+ }
+
+ public ExceptionType getExceptionType() {
+ return exceptionType;
+ }
+
+ public enum ExceptionType {
+ UNEXPECTED_INFORMATION_RECEIVED,
+ UNSUPPORTED_OPERATION,
+ INTERNAL_ERROR
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/SystemDeviceModule.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.system;
+
+import com.baidu.duer.dcs.devicemodule.system.message.ExceptionEncounteredPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.SetEndPointPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.ThrowExceptionPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.UserInactivityReportPayload;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * System模块处理ResetUserInactivity、SetEndpoint、ThrowException指令,发送SynchronizeState、UserInactivityReport等事件
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class SystemDeviceModule extends BaseDeviceModule {
+ private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(1);
+ private static final long MILLISECONDS_PER_SECOND = 1000;
+ private static final long USER_INACTIVITY_REPORT_PERIOD_HOURS = 1;
+ private final List<IDeviceModuleListener> deviceModuleListeners;
+ private AtomicLong lastUserInteractionInSeconds;
+ private Provider provider;
+
+ public SystemDeviceModule(final IMessageSender messageSender) {
+ super(ApiConstants.NAMESPACE, messageSender);
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ long inactiveTimeInSeconds = currentTimeSeconds() - lastUserInteractionInSeconds.get();
+ Event event = userInactivityReportEvent(inactiveTimeInSeconds);
+ messageSender.sendEvent(event);
+ }
+ };
+
+ lastUserInteractionInSeconds = new AtomicLong(currentTimeSeconds());
+ scheduledExecutor.scheduleAtFixedRate(runnable, USER_INACTIVITY_REPORT_PERIOD_HOURS,
+ USER_INACTIVITY_REPORT_PERIOD_HOURS, TimeUnit.HOURS);
+
+ deviceModuleListeners = Collections.synchronizedList(new ArrayList<IDeviceModuleListener>());
+ }
+
+
+ @Override
+ public ClientContext clientContext() {
+ return null;
+ }
+
+ @Override
+ public void handleDirective(Directive directive) throws HandleDirectiveException {
+ String name = directive.header.getName();
+ if (ApiConstants.Directives.ResetUserInactivity.NAME.equals(name)) {
+ userActivity();
+ } else if (ApiConstants.Directives.SetEndpoint.NAME.equals(name)) {
+ handleSetEndpointDirective(directive);
+ } else if (ApiConstants.Directives.ThrowException.NAME.equals(name)) {
+ handleThrowException(directive);
+ } else {
+ String message = "system cannot handle this directive";
+ throw (new HandleDirectiveException(
+ HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
+ }
+ }
+
+ @Override
+ public void release() {
+ if (!scheduledExecutor.isShutdown()) {
+ scheduledExecutor.shutdownNow();
+ }
+ deviceModuleListeners.clear();
+ }
+
+ private void handleSetEndpointDirective(Directive directive) {
+ Payload payload = directive.getPayload();
+ if (payload instanceof SetEndPointPayload) {
+ SetEndPointPayload setEndPointPayload = (SetEndPointPayload) payload;
+ fireSetEndpoint(setEndPointPayload);
+ }
+ }
+
+ private void handleThrowException(Directive directive) {
+ Payload payload = directive.getPayload();
+ if (payload instanceof ThrowExceptionPayload) {
+ ThrowExceptionPayload throwExceptionPayload = (ThrowExceptionPayload) payload;
+ fireThrowException(throwExceptionPayload);
+ }
+ }
+
+ public void sendSynchronizeStateEvent() {
+ String name = ApiConstants.Events.SynchronizeState.NAME;
+ Header header = new MessageIdHeader(getNameSpace(), name);
+ Payload payload = new Payload();
+ Event event = new Event(header, payload);
+
+ if (messageSender != null) {
+ messageSender.sentEventWithClientContext(event, null);
+ }
+ }
+
+ private Event userInactivityReportEvent(long inactiveTimeInSeconds) {
+ final String name = ApiConstants.Events.UserInactivityReport.NAME;
+ Header header = new MessageIdHeader(getNameSpace(), name);
+ Payload payload = new UserInactivityReportPayload(inactiveTimeInSeconds);
+ Event event = new Event(header, payload);
+ return event;
+ }
+
+ public void sendExceptionEncounteredEvent(String directiveJson,
+ HandleDirectiveException.ExceptionType type,
+ String message) {
+ final String name = ApiConstants.Events.ExceptionEncountered.NAME;
+ Header header = new MessageIdHeader(getNameSpace(), name);
+
+ ExceptionEncounteredPayload exceptionEncounteredPayLoad = new ExceptionEncounteredPayload(
+ directiveJson, type, message);
+ Event event = new Event(header, exceptionEncounteredPayLoad);
+ messageSender.sentEventWithClientContext(event, null);
+ }
+
+ private void userActivity() {
+ lastUserInteractionInSeconds.set(currentTimeSeconds());
+ }
+
+ private long currentTimeSeconds() {
+ return System.currentTimeMillis() / MILLISECONDS_PER_SECOND;
+ }
+
+ public Provider getProvider() {
+ if (provider == null) {
+ provider = new Provider();
+ }
+
+ return provider;
+ }
+
+ public class Provider {
+ public void userActivity() {
+ SystemDeviceModule.this.userActivity();
+ }
+ }
+
+ private void fireSetEndpoint(SetEndPointPayload setEndPointPayload) {
+ for (IDeviceModuleListener listener : deviceModuleListeners) {
+ listener.onSetEndpoint(setEndPointPayload);
+ }
+ }
+
+ private void fireThrowException(ThrowExceptionPayload throwExceptionPayload) {
+ for (IDeviceModuleListener listener : deviceModuleListeners) {
+ listener.onThrowException(throwExceptionPayload);
+ }
+ }
+
+ public void addModuleListener(IDeviceModuleListener listener) {
+ deviceModuleListeners.add(listener);
+ }
+
+ public interface IDeviceModuleListener {
+ void onSetEndpoint(SetEndPointPayload endPointPayload);
+
+ void onThrowException(ThrowExceptionPayload throwExceptionPayload);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/ExceptionEncounteredPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.system.message;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException.ExceptionType;
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * ExceptionEncountered事件对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/3.
+ */
+public class ExceptionEncounteredPayload extends Payload {
+ private String unparsedDirective;
+ private Error error;
+
+ public ExceptionEncounteredPayload(String unparsedDirective, ExceptionType type, String message) {
+ this.unparsedDirective = unparsedDirective;
+ Error error = new Error(type, message);
+ this.error = error;
+ }
+
+ public void setUnparsedDirective(String unparsedDirective) {
+ this.unparsedDirective = unparsedDirective;
+ }
+
+ public String getUnparsedDirective() {
+ return unparsedDirective;
+ }
+
+ public void setError(Error error) {
+ this.error = error;
+ }
+
+ public Error getError() {
+ return error;
+ }
+
+ public static class Error {
+ public ExceptionType type;
+ public String message;
+
+ public Error(ExceptionType type, String message) {
+ this.type = type;
+ this.message = message;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/SetEndPointPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.system.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * setEndPoint指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/3.
+ */
+public class SetEndPointPayload extends Payload {
+ private String endpoint;
+
+ public SetEndPointPayload() {
+
+ }
+
+ public SetEndPointPayload(String endpoint) {
+ this.endpoint = endpoint;
+ }
+
+ public void setEndpoint(String endpoint) {
+ this.endpoint = endpoint;
+ }
+
+ public String getEndpoint() {
+ return endpoint;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/ThrowExceptionPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.system.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * ThrowException指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/8.
+ */
+public class ThrowExceptionPayload extends Payload {
+ private String code;
+ private String description;
+
+ public ThrowExceptionPayload() {
+ }
+
+ public ThrowExceptionPayload(String code, String description) {
+ this.code = code;
+ this.description = description;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return this.code;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String toString() {
+ return "code=" + code + " description=" + description;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/UserInactivityReportPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.system.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * UserInactivityReport事件对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/3.
+ */
+public class UserInactivityReportPayload extends Payload {
+ private long inactiveTimeInSeconds;
+
+ public UserInactivityReportPayload(long inactiveTimeInSeconds) {
+ this.inactiveTimeInSeconds = inactiveTimeInSeconds;
+ }
+
+ void setInactiveTimeInSeconds(long inactiveTimeInSeconds) {
+ this.inactiveTimeInSeconds = inactiveTimeInSeconds;
+ }
+
+ long getInactiveTimeInSeconds() {
+ return inactiveTimeInSeconds;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/ApiConstants.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.voiceinput;
+
+/**
+ * 定义了表示Voice Input模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+ public static final String NAMESPACE = "ai.dueros.device_interface.voice_input";
+ public static final String NAME = "VoiceInputInterface";
+
+ public static final class Events {
+ public static final class ListenStarted {
+ public static final String NAME = ListenStarted.class.getSimpleName();
+ }
+
+ public static final class ListenTimedOut {
+ public static final String NAME = ListenTimedOut.class.getSimpleName();
+ }
+ }
+
+ public static final class Directives {
+ public static final class Listen {
+ public static final String NAME = Listen.class.getSimpleName();
+ }
+
+ public static final class StopListen {
+ public static final String NAME = StopListen.class.getSimpleName();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/VoiceInputDeviceModule.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.voiceinput;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.devicemodule.voiceinput.message.ListenStartedPayload;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher;
+import com.baidu.duer.dcs.framework.DialogRequestIdHandler;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.framework.message.DialogRequestIdHeader;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IAudioInput;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Voice Input模块处理并执行服务下发的StopListen、Listen指令,上报ListenStarted、ListenTimedOut事件
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class VoiceInputDeviceModule extends BaseDeviceModule {
+ public static final String TAG = VoiceInputDeviceModule.class.getSimpleName();
+ private final IAudioInput audioInput;
+ private final List<IVoiceInputListener> voiceInputListeners;
+ private final IMediaPlayer mediaPlayer;
+ private final DialogRequestIdHandler dialogRequestIdHandler;
+ private final DcsResponseDispatcher dcsResponseDispatcher;
+
+ public VoiceInputDeviceModule(final IMediaPlayer mediaPlayer,
+ IMessageSender messageSender,
+ final IAudioInput audioInput,
+ DialogRequestIdHandler dialogRequestIdHandler,
+ DcsResponseDispatcher dcsResponseDispatcher) {
+ super(ApiConstants.NAMESPACE, messageSender);
+ this.audioInput = audioInput;
+ this.voiceInputListeners = Collections.synchronizedList(new ArrayList<IVoiceInputListener>());
+ this.mediaPlayer = mediaPlayer;
+ this.dialogRequestIdHandler = dialogRequestIdHandler;
+ this.dcsResponseDispatcher = dcsResponseDispatcher;
+
+ this.audioInput.registerAudioInputListener(new IAudioInput.IAudioInputListener() {
+ @Override
+ public void onStartRecord(DcsStreamRequestBody dcsStreamRequestBody) {
+ stopSpeaker();
+ // 发送网络请求
+ sendListenStartedEvent(dcsStreamRequestBody, new IResponseListener() {
+ @Override
+ public void onSucceed(int statusCode) {
+ fireOnSucceed(statusCode);
+ // 没有下发新的语音speak-stream
+ if (statusCode == 204) {
+ // 设置对话通道为非活跃状态
+ mediaPlayer.setActive(false);
+ } else {
+ mediaPlayer.setActive(true);
+ }
+ }
+
+ @Override
+ public void onFailed(String errorMessage) {
+ LogUtil.d(TAG, "onFailed,errorMessage:" + errorMessage);
+ fireOnFailed(errorMessage);
+ audioInput.stopRecord();
+ mediaPlayer.setActive(false);
+ }
+ });
+
+ fireOnStartRecord();
+ }
+
+ @Override
+ public void onStopRecord() {
+ fireFinishRecord();
+ }
+ });
+ }
+
+
+ @Override
+ public ClientContext clientContext() {
+ return null;
+ }
+
+ @Override
+ public void handleDirective(Directive directive) throws HandleDirectiveException {
+ String name = directive.getName();
+ if (name.equals(ApiConstants.Directives.StopListen.NAME)) {
+ audioInput.stopRecord();
+ } else if (name.equals(ApiConstants.Directives.Listen.NAME)) {
+ audioInput.startRecord();
+ } else {
+ String message = "No device to handle the directive";
+ throw new HandleDirectiveException(
+ HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION,
+ message);
+ }
+ }
+
+ @Override
+ public void release() {
+ voiceInputListeners.clear();
+ }
+
+ /**
+ * 停止speaker对话通道的语音播放
+ */
+ private void stopSpeaker() {
+ mediaPlayer.setActive(true);
+ mediaPlayer.stop();
+ dcsResponseDispatcher.interruptDispatch();
+ }
+
+ private void sendListenStartedEvent(DcsStreamRequestBody streamRequestBody, IResponseListener responseListener) {
+ String dialogRequestId = dialogRequestIdHandler.createActiveDialogRequestId();
+ String name = ApiConstants.Events.ListenStarted.NAME;
+ DialogRequestIdHeader header = new DialogRequestIdHeader(getNameSpace(), name, dialogRequestId);
+ Payload payload = new ListenStartedPayload(ListenStartedPayload.FORMAT);
+ Event event = new Event(header, payload);
+ messageSender.sendEvent(event, streamRequestBody, responseListener);
+ }
+
+ private void fireOnStartRecord() {
+ for (IVoiceInputListener listener : voiceInputListeners) {
+ listener.onStartRecord();
+ }
+ }
+
+ private void fireFinishRecord() {
+ for (IVoiceInputListener listener : voiceInputListeners) {
+ listener.onFinishRecord();
+ }
+ }
+
+ private void fireOnSucceed(int statusCode) {
+ for (IVoiceInputListener listener : voiceInputListeners) {
+ listener.onSucceed(statusCode);
+ }
+ }
+
+ private void fireOnFailed(String errorMessage) {
+ for (IVoiceInputListener listener : voiceInputListeners) {
+ listener.onFailed(errorMessage);
+ }
+ }
+
+ public void addVoiceInputListener(IVoiceInputListener listener) {
+ this.voiceInputListeners.add(listener);
+ }
+
+ public interface IVoiceInputListener {
+ /**
+ * 开始录音的回调
+ */
+ void onStartRecord();
+
+ /**
+ * 结束录音的回调
+ */
+ void onFinishRecord();
+
+ /**
+ * 录音-网络请求成功
+ *
+ * @param statusCode 网络返回状态码
+ */
+ void onSucceed(int statusCode);
+
+ /**
+ * 录音-网络请求失败
+ *
+ * @param errorMessage 错误信息
+ */
+ void onFailed(String errorMessage);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/message/ListenPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.voiceinput.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Listen指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ListenPayload extends Payload {
+ private long timeoutInMilliseconds;
+
+ public void setTimeoutInMilliseconds(long timeoutInMilliseconds) {
+ this.timeoutInMilliseconds = timeoutInMilliseconds;
+ }
+
+ public long getTimeoutInMilliseconds() {
+ return timeoutInMilliseconds;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/message/ListenStartedPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.voiceinput.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * ListenStarted事件对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ListenStartedPayload extends Payload {
+ public static final String FORMAT = "AUDIO_L16_RATE_16000_CHANNELS_1";
+ private String format;
+
+ public ListenStartedPayload(String format) {
+ this.format = format;
+ }
+
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ public String getFormat() {
+ return format;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/ApiConstants.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.voiceoutput;
+
+/**
+ * 定义了表示Voice Output模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class ApiConstants {
+ public static final String NAMESPACE = "ai.dueros.device_interface.voice_output";
+ public static final String NAME = "VoiceOutputInterface";
+
+ public static final class Events {
+ public static final class SpeechStarted {
+ public static final String NAME = SpeechStarted.class.getSimpleName();
+ }
+
+ public static final class SpeechFinished {
+ public static final String NAME = SpeechFinished.class.getSimpleName();
+ }
+
+ public static final class SpeechState {
+ public static final String NAME = SpeechState.class.getSimpleName();
+ }
+ }
+
+ public static final class Directives {
+ public static final class Speak {
+ public static final String NAME = Speak.class.getSimpleName();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/VoiceOutputDeviceModule.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.voiceoutput;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.message.SpeakPayload;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.message.SpeechLifecyclePayload;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.message.VoiceOutputStatePayload;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Voice Output模块处理并执行服务下发的Speak指令,上报SpeechStarted、SpeechFinished事件,以及维护自身的端状态
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class VoiceOutputDeviceModule extends BaseDeviceModule {
+ private static final String TAG = VoiceOutputDeviceModule.class.getSimpleName();
+ // 播放回调
+ private final List<IVoiceOutputListener> voiceOutputListeners;
+ // 播放队列
+ private final LinkedList<SpeakPayload> speakQueue = new LinkedList<>();
+ // 语音播放的播放器
+ private final IMediaPlayer mediaPlayer;
+ private SpeechState speechState = SpeechState.FINISHED;
+
+ // 上一次的token
+ private String lastSpeakToken = "";
+
+ // 当前播放状态
+ private enum SpeechState {
+ PLAYING,
+ FINISHED
+ }
+
+ public VoiceOutputDeviceModule(IMediaPlayer mediaPlayer,
+ IMessageSender messageSender) {
+ super(ApiConstants.NAMESPACE, messageSender);
+ this.mediaPlayer = mediaPlayer;
+ this.mediaPlayer.addMediaPlayerListener(mediaPlayerListener);
+ this.voiceOutputListeners = Collections.synchronizedList(new ArrayList<IVoiceOutputListener>());
+ }
+
+ @Override
+ public ClientContext clientContext() {
+ String namespace = ApiConstants.NAMESPACE;
+ String name = ApiConstants.Events.SpeechState.NAME;
+ Header header = new Header(namespace, name);
+ VoiceOutputStatePayload payload = new VoiceOutputStatePayload(lastSpeakToken,
+ mediaPlayer.getCurrentPosition(),
+ speechState.name());
+ return new ClientContext(header, payload);
+ }
+
+ @Override
+ public void handleDirective(Directive directive) throws HandleDirectiveException {
+ String directiveName = directive.getName();
+ LogUtil.d(TAG, "rawMessage:" + directive.rawMessage);
+ LogUtil.d(TAG, "directiveName:" + directiveName);
+ if (directiveName.equals(ApiConstants.Directives.Speak.NAME)) {
+ SpeakPayload speak = (SpeakPayload) directive.payload;
+ handleSpeak(speak);
+ } else {
+ String message = "VoiceOutput cannot handle the directive";
+ throw (new HandleDirectiveException(
+ HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
+ }
+ }
+
+ private void handleSpeak(SpeakPayload speak) {
+ speakQueue.add(speak);
+ // 如果已经有了,就只入队列,等待下一次的调度
+ if (speakQueue.size() == 1) {
+ startSpeech();
+ }
+ }
+
+ private void startSpeech() {
+ final SpeakPayload speak = speakQueue.getFirst();
+ if (null != speak) {
+ lastSpeakToken = speak.token;
+ InputStream inputStream = new ByteArrayInputStream(speak.attachedContent);
+ mediaPlayer.play(new IMediaPlayer.MediaResource(inputStream));
+ }
+ }
+
+ private IMediaPlayer.IMediaPlayerListener mediaPlayerListener = new IMediaPlayer.SimpleMediaPlayerListener() {
+ @Override
+ public void onPrepared() {
+ super.onPrepared();
+ speechState = SpeechState.PLAYING;
+ sendStartedEvent(lastSpeakToken);
+ fireOnVoiceOutputStarted();
+ }
+
+ @Override
+ public void onStopped() {
+ super.onStopped();
+ speakQueue.clear();
+ }
+
+ @Override
+ public void onError(String error, IMediaPlayer.ErrorType errorType) {
+ super.onError(error, errorType);
+ finishedSpeechItem();
+ }
+
+ @Override
+ public void onCompletion() {
+ LogUtil.d(TAG, " IMediaPlayer onCompletion");
+ finishedSpeechItem();
+ }
+ };
+
+ /**
+ * 播放完一条后开始下一条的处理
+ */
+ private void finishedSpeechItem() {
+ speakQueue.poll();
+ LogUtil.d(TAG, "finishedSpeechItem speakQueue size :" + speakQueue.size());
+ if (speakQueue.isEmpty()) {
+ speechState = SpeechState.FINISHED;
+ sendFinishedEvent(lastSpeakToken);
+ fireOnVoiceOutputFinished();
+ } else {
+ startSpeech();
+ }
+ }
+
+ @Override
+ public void release() {
+ if (mediaPlayer != null) {
+ mediaPlayer.release();
+ mediaPlayer.removeMediaPlayerListener(mediaPlayerListener);
+ }
+ if (isSpeaking()) {
+ speechState = SpeechState.FINISHED;
+ }
+ speakQueue.clear();
+ voiceOutputListeners.clear();
+ }
+
+ public boolean isSpeaking() {
+ return speechState == SpeechState.PLAYING;
+ }
+
+ /**
+ * 播放开始时上报的事件
+ *
+ * @param token token 一条speak的唯一标识
+ */
+ private void sendStartedEvent(String token) {
+ String namespace = ApiConstants.NAMESPACE;
+ String name = ApiConstants.Events.SpeechStarted.NAME;
+ MessageIdHeader header = new MessageIdHeader(namespace, name);
+ Event event = new Event(header, new SpeechLifecyclePayload(token));
+ messageSender.sendEvent(event);
+ }
+
+ /**
+ * 播放结束时上报的事件
+ *
+ * @param token token 一条speak的唯一标识
+ */
+ private void sendFinishedEvent(String token) {
+ String namespace = ApiConstants.NAMESPACE;
+ String name = ApiConstants.Events.SpeechFinished.NAME;
+ MessageIdHeader header = new MessageIdHeader(namespace, name);
+ Event event = new Event(header, new SpeechLifecyclePayload(token));
+ messageSender.sendEvent(event, new IResponseListener() {
+ @Override
+ public void onSucceed(int statusCode) {
+ // 没有新的语音speak-stream
+ if (statusCode == 204) {
+ mediaPlayer.setActive(false);
+ } else {
+ mediaPlayer.setActive(true);
+ }
+ }
+
+ @Override
+ public void onFailed(String errorMessage) {
+ mediaPlayer.setActive(false);
+ }
+ });
+ }
+
+ private void fireOnVoiceOutputStarted() {
+ for (IVoiceOutputListener listener : voiceOutputListeners) {
+ listener.onVoiceOutputStarted();
+ }
+ }
+
+ private void fireOnVoiceOutputFinished() {
+ for (IVoiceOutputListener listener : voiceOutputListeners) {
+ listener.onVoiceOutputFinished();
+ }
+ }
+
+ /**
+ * 添加播放监听
+ *
+ * @param listener listener
+ */
+ public void addVoiceOutputListener(IVoiceOutputListener listener) {
+ this.voiceOutputListeners.add(listener);
+ }
+
+ /**
+ * 播报监听器接口
+ */
+ public interface IVoiceOutputListener {
+ /**
+ * 开始播放时回调
+ */
+ void onVoiceOutputStarted();
+
+ /**
+ * 播放完成时回调
+ */
+ void onVoiceOutputFinished();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/message/SpeakPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.voiceoutput.message;
+
+import com.baidu.duer.dcs.framework.message.AttachedContentPayload;
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * Speak指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class SpeakPayload extends Payload implements AttachedContentPayload {
+ public String url;
+ public String format;
+ public String token;
+
+ @JsonIgnore
+ public byte[] attachedContent;
+
+ // start with cid:
+ public void setUrl(String url) {
+ this.url = url.substring(4);
+ }
+
+ @Override
+ public boolean requiresAttachedContent() {
+ return !hasAttachedContent();
+ }
+
+ @Override
+ public boolean hasAttachedContent() {
+ return attachedContent != null;
+ }
+
+ @Override
+ public String getAttachedContentId() {
+ return url;
+ }
+
+ @Override
+ public byte[] getAttachedContent() {
+ return attachedContent;
+ }
+
+ @Override
+ public void setAttachedContent(String cid, byte[] data) {
+ if (getAttachedContentId().equals(cid)) {
+ this.attachedContent = data;
+ } else {
+ throw new IllegalArgumentException(
+ "Tried to add the wrong audio content to a Speak directive. This cid: "
+ + getAttachedContentId() + " other cid: " + cid);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/message/SpeechLifecyclePayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.voiceoutput.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+/**
+ * SpeechStarted和SpeechFinished事件对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+public class SpeechLifecyclePayload extends Payload {
+ private String token;
+
+ public SpeechLifecyclePayload(String token) {
+ this.token = token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public String getToken() {
+ return token;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/message/VoiceOutputStatePayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.devicemodule.voiceoutput.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * 本模块端状态对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class VoiceOutputStatePayload extends Payload {
+ public String token;
+ public long offsetInMilliseconds;
+ public String playerActivity;
+
+ public VoiceOutputStatePayload(String token, long offsetInMilliseconds, String playerActivity) {
+ this.token = token;
+ this.offsetInMilliseconds = offsetInMilliseconds;
+ this.playerActivity = playerActivity;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/BaseDeviceModule.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+
+/**
+ * 定义deviceModule端状态和处理指令的接口
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public abstract class BaseDeviceModule {
+ private final String nameSpace;
+ protected final IMessageSender messageSender;
+
+ public BaseDeviceModule(String nameSpace) {
+ this(nameSpace, null);
+ }
+
+ public BaseDeviceModule(String nameSpace, IMessageSender messageSender) {
+ this.nameSpace = nameSpace;
+ this.messageSender = messageSender;
+ }
+
+ /**
+ * 端状态:服务端在处理某些事件时,需要了解在请求当时设备端各模块所处的状态。比如端上是否正在播放音乐,
+ * 是否有闹钟在响,是否正在播报等等
+ *
+ * @return 端状态
+ */
+ public abstract ClientContext clientContext();
+
+ /**
+ * 处理服务端下发的指令
+ *
+ * @param directive
+ * @throws HandleDirectiveException
+ */
+ public abstract void handleDirective(Directive directive) throws HandleDirectiveException;
+
+ public abstract void release();
+
+ public String getNameSpace() {
+ return nameSpace;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/BaseMultiChannelMediaPlayer.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 1.用途:控制各个DeviceModule的播放策略-基类,主要控制的是{@link com.baidu.duer.dcs.devicemodule.alerts.AlertsDeviceModule}
+ * and {@link com.baidu.duer.dcs.devicemodule.voiceoutput.VoiceOutputDeviceModule}
+ * and {@link com.baidu.duer.dcs.devicemodule.audioplayer.AudioPlayerDeviceModule}
+ * <p>
+ * 2.如果你需要实现自己的策略需要复写handlePlay方法,该sample中提供了一种暂停策略,即
+ * {@link com.baidu.duer.dcs.framework.PauseStrategyMultiChannelMediaPlayer}
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public abstract class BaseMultiChannelMediaPlayer {
+ // 注册的mediaPlayer
+ protected Map<String, ChannelMediaPlayerInfo> mediaPlayers = new ConcurrentHashMap<>();
+ private IPlatformFactory factory;
+
+ public BaseMultiChannelMediaPlayer(IPlatformFactory factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * 添加一个频道并创建一个mediaPlayer
+ *
+ * @param channelName 频道的名字
+ * @param priority 频道的优先级
+ * @return IMediaPlayer 用于处理端能力的播放
+ */
+ public IMediaPlayer addNewChannel(String channelName, int priority) {
+ IMediaPlayer mediaPlayer = factory.createMediaPlayer();
+
+ ChannelMediaPlayerInfo info = new ChannelMediaPlayerInfo();
+ info.channelName = channelName;
+ info.priority = priority;
+ info.mediaPlayer = mediaPlayer;
+ mediaPlayers.put(channelName, info);
+
+ return new ChannelMediaPlayer(info);
+ }
+
+ /**
+ * 处理对话频道(speak), 闹钟/提醒频道(alert),音乐频道(audio)的播放策略,
+ * 比如: 当播放一个低优先级的指令内容时,来了一个高优先级的播放指令是否需要暂停/降低 低优先级频道对应的mediaPlayer
+ *
+ * @param channelName 频道的名字(即通过addNewChannel方法指定的)
+ * @param mediaResource 媒体资源
+ */
+ protected abstract void handlePlay(String channelName, IMediaPlayer.MediaResource mediaResource);
+
+ protected int getPriorityByChannelName(String channelName) {
+ if (mediaPlayers.containsKey(channelName)) {
+ ChannelMediaPlayerInfo info = mediaPlayers.get(channelName);
+ return info.priority;
+ }
+ return UNKNOWN_PRIORITY;
+ }
+
+ /**
+ * 根据频道的名字获取对应的播放器
+ *
+ * @param channelName channelName 频道的名字
+ * @return IMediaPlayer
+ */
+ protected IMediaPlayer getMediaPlayer(String channelName) {
+ if (channelName != null && channelName.length() > 0) {
+ if (mediaPlayers.containsKey(channelName)) {
+ return mediaPlayers.get(channelName).mediaPlayer;
+ }
+ }
+ return null;
+ }
+
+ private static final String TAG = BaseMultiChannelMediaPlayer.class.getSimpleName();
+ protected static final int UNKNOWN_PRIORITY = -1;
+ // 按优先级保存的需要播放的数据
+ protected Map<Integer, ChannelMediaPlayerInfo> currentPlayMap = new TreeMap<>(
+ new Comparator<Integer>() {
+ public int compare(Integer obj1, Integer obj2) {
+ // 降序排序
+ return obj2 - obj1;
+ }
+ });
+
+ /**
+ * 播放信息
+ */
+ protected static class ChannelMediaPlayerInfo {
+ // 播放信息
+ IMediaPlayer.MediaResource mediaResource;
+ // 频道名字
+ String channelName;
+ // 频道优先级
+ int priority;
+ // 播放器
+ IMediaPlayer mediaPlayer;
+ }
+
+ /**
+ * 获取控制音量,静音等操作的实例
+ *
+ * @return ISpeakerController
+ */
+ public ISpeakerController getSpeakerController() {
+ return new SpeakerControllerImpl();
+ }
+
+ /**
+ * 暂停所有的mediaPlayer播放
+ */
+ private void pauseAll() {
+ // 需要暂停所有的播放,有可能没有requestDialogId的指令正在speaking
+ Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+ ChannelMediaPlayerInfo value = entry.getValue();
+ value.mediaPlayer.pause();
+ }
+ }
+
+ private void stop(String channelName) {
+ IMediaPlayer mediaPlayer = getMediaPlayer(channelName);
+ if (mediaPlayer != null) {
+ mediaPlayer.stop();
+ }
+ }
+
+ /**
+ * 设置所有频道的mediaPlayer的音量
+ *
+ * @param volume 音量 0-1
+ */
+ private void setVolumeAll(float volume) {
+ Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+ ChannelMediaPlayerInfo info = entry.getValue();
+ info.mediaPlayer.setVolume(volume);
+ }
+ }
+
+ /**
+ * 获取最高优先级的音量
+ *
+ * @return float 0-1
+ */
+ private float getVolumeTopPriority() {
+ Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+ if (it.hasNext()) {
+ Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+ ChannelMediaPlayerInfo info = entry.getValue();
+ return info.mediaPlayer.getVolume();
+ }
+ return 0;
+ }
+
+ /**
+ * 设置所有频道的mediaPlayer静音状态
+ *
+ * @param mute 静音状态
+ */
+ private void setMuteAll(boolean mute) {
+ Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+ ChannelMediaPlayerInfo info = entry.getValue();
+ info.mediaPlayer.setMute(mute);
+ }
+ }
+
+ /**
+ * 获取最高优先级的mediaPlayer静音状态
+ *
+ * @return true 静音,false 非静音
+ */
+ private boolean getMuteTopPriority() {
+ Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+ if (it.hasNext()) {
+ Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+ ChannelMediaPlayerInfo info = entry.getValue();
+ return info.mediaPlayer.getMute();
+ }
+ return false;
+ }
+
+ protected void findToPlay() {
+ LogUtil.d(TAG, "findToPlay");
+ // 找到最高优先级的重新播放
+ Iterator<Map.Entry<Integer, ChannelMediaPlayerInfo>> it = currentPlayMap.entrySet().iterator();
+ if (!it.hasNext()) {
+ return;
+ }
+ Map.Entry<Integer, ChannelMediaPlayerInfo> entry = it.next();
+ ChannelMediaPlayerInfo info = entry.getValue();
+ LogUtil.d(TAG, "findToPlay-channelName:" + info.channelName);
+ if (info.mediaPlayer.getPlayState() == IMediaPlayer.PlayState.PAUSED) {
+ LogUtil.d(TAG, "findToPlay-value-resume:" + info.priority);
+ info.mediaPlayer.resume();
+ } else {
+ LogUtil.d(TAG, "findToPlay-PlayState:" + info.mediaPlayer.getPlayState());
+ // 不是处于正在播放或者准备播放中或者准备完成,开始播放
+ if (info.mediaPlayer.getPlayState() != IMediaPlayer.PlayState.PLAYING
+ && info.mediaPlayer.getPlayState() != IMediaPlayer.PlayState.PREPARING
+ && info.mediaPlayer.getPlayState() != IMediaPlayer.PlayState.PREPARED) {
+ LogUtil.d(TAG, "findToPlay-value-play:" + info.priority);
+ info.mediaPlayer.play(info.mediaResource);
+ } else {
+ LogUtil.d(TAG, "findToPlay-value-isPlaying-false:" + info.priority);
+ }
+ }
+ }
+
+ private final class ListenerProxy extends IMediaPlayer.SimpleMediaPlayerListener {
+ private String channelName;
+
+ ListenerProxy(String channelName) {
+ this.channelName = channelName;
+ }
+
+ @Override
+ public void onStopped() {
+ super.onStopped();
+ // stop 后就删除不需要播放了
+ int priority = getPriorityByChannelName(channelName);
+ LogUtil.d(TAG, "ListenerProxy onStopped del:" + channelName);
+ if (priority != UNKNOWN_PRIORITY) {
+ currentPlayMap.remove(priority);
+ }
+ LogUtil.d(TAG, "ListenerProxy onStopped after del :" + currentPlayMap.size());
+ }
+
+ @Override
+ public void onCompletion() {
+ super.onCompletion();
+ LogUtil.d(TAG, "ListenerProxy onCompletion,channelName:" + channelName);
+ // 删除当前的
+ int priority = BaseMultiChannelMediaPlayer.this.getPriorityByChannelName(channelName);
+ if (priority != UNKNOWN_PRIORITY) {
+ currentPlayMap.remove(priority);
+ }
+ }
+ }
+
+ /**
+ * 带有优先级信息的IMediaPlayer
+ */
+ private final class ChannelMediaPlayer implements IMediaPlayer {
+ private ChannelMediaPlayerInfo mediaPlayerInfo;
+ private String channelName;
+ private IMediaPlayer mediaPlayer;
+
+ ChannelMediaPlayer(ChannelMediaPlayerInfo info) {
+ this.mediaPlayerInfo = info;
+ this.channelName = mediaPlayerInfo.channelName;
+ this.mediaPlayer = mediaPlayerInfo.mediaPlayer;
+ }
+
+ @Override
+ public void play(MediaResource mediaResource) {
+ LogUtil.d(TAG, "ChannelMediaPlayer-play,will handlePlay");
+ BaseMultiChannelMediaPlayer.this.handlePlay(channelName, mediaResource);
+ }
+
+ @Override
+ public void pause() {
+ mediaPlayer.pause();
+ }
+
+ @Override
+ public void stop() {
+ LogUtil.d(TAG, "ChannelMediaPlayer-stop-channelName:" + channelName);
+ BaseMultiChannelMediaPlayer.this.handleStop(channelName);
+ }
+
+ @Override
+ public void resume() {
+ mediaPlayer.resume();
+ }
+
+ @Override
+ public void seekTo(int milliseconds) {
+ mediaPlayer.seekTo(milliseconds);
+ }
+
+ @Override
+ public void release() {
+ mediaPlayer.release();
+ }
+
+ @Override
+ public PlayState getPlayState() {
+ return mediaPlayer.getPlayState();
+ }
+
+ @Override
+ public void setVolume(float volume) {
+ mediaPlayer.setVolume(volume);
+ }
+
+ @Override
+ public float getVolume() {
+ return mediaPlayer.getVolume();
+ }
+
+ @Override
+ public void setMute(boolean mute) {
+ mediaPlayer.setMute(mute);
+ }
+
+ @Override
+ public boolean getMute() {
+ return mediaPlayer.getMute();
+ }
+
+ @Override
+ public long getCurrentPosition() {
+ return mediaPlayer.getCurrentPosition();
+ }
+
+ @Override
+ public long getDuration() {
+ return mediaPlayer.getDuration();
+ }
+
+ @Override
+ public float getBufferPercentage() {
+ return mediaPlayer.getBufferPercentage();
+ }
+
+ @Override
+ public void addMediaPlayerListener(IMediaPlayerListener listener) {
+ // 注意add的顺序
+ // 先1后2的目的是播放完要先从等待播放map中删除对应改成播放完的那一条。
+ // 1.先add wrappedListener
+ IMediaPlayerListener wrappedListener =
+ new ListenerProxy(channelName);
+ mediaPlayer.addMediaPlayerListener(wrappedListener);
+
+ // 2.再addDeviceModule通知到DeviceModule
+ mediaPlayer.addMediaPlayerListener(listener);
+ }
+
+ @Override
+ public void removeMediaPlayerListener(IMediaPlayerListener listener) {
+ mediaPlayer.removeMediaPlayerListener(listener);
+ }
+
+ @Override
+ public void setActive(boolean isActive) {
+ LogUtil.d(TAG, "ChannelMediaPlayer-setActive-isActive:" + isActive);
+ mediaPlayer.setActive(isActive);
+ // 不是处于活跃频道
+ if (!isActive && mediaPlayer.getPlayState() != IMediaPlayer.PlayState.STOPPED) {
+ BaseMultiChannelMediaPlayer.this.handleActive();
+ }
+ }
+
+ @Override
+ public boolean isActive() {
+ return mediaPlayer.isActive();
+ }
+ }
+
+ /**
+ * 处理停止播放
+ */
+ private void handleStop(String channelName) {
+ stop(channelName);
+ pauseAll();
+ }
+
+ /**
+ * 设置对话通道不活跃后的处理逻辑
+ */
+ private void handleActive() {
+ // 找到最高优先级的开始播放
+ findToPlay();
+ }
+
+ /**
+ * 控制接口
+ */
+ public interface ISpeakerController {
+ /**
+ * 设置音量(0-1)
+ *
+ * @param volume 音量(0-1)
+ */
+ void setVolume(float volume);
+
+ /**
+ * 获取当前最高通道的音量
+ *
+ * @return 音量(0-1)
+ */
+ float getVolume();
+
+ /**
+ * 设置是否静音
+ *
+ * @param mute 是否静音
+ */
+ void setMute(boolean mute);
+
+ /**
+ * 获取当前最高通道的静音状态
+ *
+ * @return 静音状态,true 是静音
+ */
+ boolean getMute();
+ }
+
+ /**
+ * 给speak-controller 用的,控制一些音量等操作
+ */
+ private final class SpeakerControllerImpl implements ISpeakerController {
+
+ @Override
+ public void setVolume(float volume) {
+ BaseMultiChannelMediaPlayer.this.setVolumeAll(volume);
+ findToPlay();
+ }
+
+ @Override
+ public float getVolume() {
+ return BaseMultiChannelMediaPlayer.this.getVolumeTopPriority();
+ }
+
+ @Override
+ public void setMute(boolean mute) {
+ BaseMultiChannelMediaPlayer.this.setMuteAll(mute);
+ findToPlay();
+ }
+
+ @Override
+ public boolean getMute() {
+ return BaseMultiChannelMediaPlayer.this.getMuteTopPriority();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DcsClient.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.framework.dispatcher.AudioData;
+import com.baidu.duer.dcs.framework.dispatcher.MultipartParser;
+import com.baidu.duer.dcs.framework.heartbeat.HeartBeat;
+import com.baidu.duer.dcs.framework.message.DcsRequestBody;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.http.HttpConfig;
+import com.baidu.duer.dcs.http.HttpRequestInterface;
+import com.baidu.duer.dcs.http.OkHttpRequestImpl;
+import com.baidu.duer.dcs.http.callback.ResponseCallback;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.IOException;
+
+import okhttp3.Call;
+import okhttp3.Response;
+
+/**
+ * 和服务器端保持长连接、发送events和接收directives和维持心跳
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsClient {
+ public static final String TAG = DcsClient.class.getSimpleName();
+ private final DcsResponseDispatcher dcsResponseDispatcher;
+ private final HttpRequestInterface httpRequestImp;
+ private final HeartBeat heartBeat;
+ private IDcsClientListener dcsClientListener;
+
+ public DcsClient(DcsResponseDispatcher dcsResponseDispatcher, IDcsClientListener dcsClientListener) {
+ this.dcsResponseDispatcher = dcsResponseDispatcher;
+ this.dcsClientListener = dcsClientListener;
+ httpRequestImp = new OkHttpRequestImpl();
+ heartBeat = new HeartBeat(httpRequestImp);
+ heartBeat.setHeartbeatListener(new HeartBeat.IHeartbeatListener() {
+ @Override
+ public void onStartConnect() {
+ startConnect();
+ }
+ });
+ }
+
+ public void release() {
+ heartBeat.release();
+ httpRequestImp.cancelRequest(HttpConfig.HTTP_DIRECTIVES_TAG);
+ httpRequestImp.cancelRequest(HttpConfig.HTTP_EVENT_TAG);
+ }
+
+ /**
+ * 建立连接
+ */
+ public void startConnect() {
+ httpRequestImp.cancelRequest(HttpConfig.HTTP_DIRECTIVES_TAG);
+ getDirectives(new IResponseListener() {
+ @Override
+ public void onSucceed(int statusCode) {
+ LogUtil.d(TAG, "getDirectives onSucceed");
+ fireOnConnected();
+ heartBeat.startNormalPing();
+ }
+
+ @Override
+ public void onFailed(String errorMessage) {
+ LogUtil.d(TAG, "getDirectives onFailed");
+ fireOnUnconnected();
+ heartBeat.startExceptionalPing();
+ }
+ });
+ }
+
+ /**
+ * 发送带流式请求
+ *
+ * @param requestBody 消息体
+ * @param streamRequestBody stream式消息体
+ * @param listener 回调
+ */
+ public void sendRequest(DcsRequestBody requestBody,
+ DcsStreamRequestBody streamRequestBody, final IResponseListener listener) {
+ httpRequestImp.doPostEventMultipartAsync(requestBody,
+ streamRequestBody, getResponseCallback(dcsResponseDispatcher, new IResponseListener() {
+ @Override
+ public void onSucceed(int statusCode) {
+ if (listener != null) {
+ listener.onSucceed(statusCode);
+ }
+ }
+
+ @Override
+ public void onFailed(String errorMessage) {
+ if (listener != null) {
+ listener.onFailed(errorMessage);
+ }
+
+ heartBeat.startImmediatePing();
+ }
+ }));
+ }
+
+ /**
+ * 发送普通请求
+ *
+ * @param requestBody 消息体
+ * @param listener 回调
+ */
+ public void sendRequest(DcsRequestBody requestBody, IResponseListener listener) {
+ httpRequestImp.doPostEventStringAsync(requestBody,
+ getResponseCallback(dcsResponseDispatcher, listener));
+ }
+
+ private void getDirectives(IResponseListener listener) {
+ httpRequestImp.cancelRequest(HttpConfig.HTTP_DIRECTIVES_TAG);
+ httpRequestImp.doGetDirectivesAsync(null,
+ getResponseCallback(dcsResponseDispatcher, listener));
+ }
+
+ private void fireOnConnected() {
+ if (dcsClientListener != null) {
+ dcsClientListener.onConnected();
+ }
+ }
+
+ private void fireOnUnconnected() {
+ if (dcsClientListener != null) {
+ dcsClientListener.onUnconnected();
+ }
+ }
+
+ private ResponseCallback getResponseCallback(final DcsResponseDispatcher dcsResponseDispatcher,
+ final IResponseListener responseListener) {
+ ResponseCallback responseCallback = new ResponseCallback() {
+ @Override
+ public void onError(Call call, Exception e, int id) {
+ LogUtil.d(TAG, "onError,", e);
+ if (responseListener != null) {
+ responseListener.onFailed(e.getMessage());
+ }
+ }
+
+ @Override
+ public void onResponse(Response response, int id) {
+ super.onResponse(response, id);
+ LogUtil.d(TAG, "onResponse OK ," + response.request().url());
+ LogUtil.d(TAG, "onResponse code ," + response.code());
+ if (responseListener != null) {
+ responseListener.onSucceed(response.code());
+ }
+ }
+
+ @Override
+ public Response parseNetworkResponse(Response response, int id) throws Exception {
+ int statusCode = response.code();
+ if (statusCode == 200) {
+ MultipartParser multipartParser = new MultipartParser(
+ new MultipartParser.IMultipartParserListener() {
+ @Override
+ public void onResponseBody(DcsResponseBody responseBody) {
+ dcsResponseDispatcher.onResponseBody(responseBody);
+ }
+
+ @Override
+ public void onAudioData(AudioData audioData) {
+ dcsResponseDispatcher.onAudioData(audioData);
+ }
+
+ @Override
+ public void onParseFailed(String unParseMessage) {
+ dcsResponseDispatcher.onParseFailed(unParseMessage);
+ }
+ });
+
+ try {
+ multipartParser.parseResponse(response);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return response;
+ }
+ };
+
+ return responseCallback;
+ }
+
+ public interface IDcsClientListener {
+ void onConnected();
+
+ void onUnconnected();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DcsFramework.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.devicemodule.system.SystemDeviceModule;
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher.IDcsResponseHandler;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.DcsRequestBody;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * dcs业务处理框架,用于分发指令(directives)、发送事件(events)和创建deviceModule等
+ * <p>
+ * Created by shenguanghao、wuruisheng on 2017/5/31.
+ */
+public class DcsFramework {
+ private static final String TAG = DcsFramework.class.getSimpleName();
+ // 管理平台相关的对象
+ private final IPlatformFactory platformFactory;
+ // 管理deviceModules
+ private final HashMap<String, BaseDeviceModule> dispatchDeviceModules;
+ // 创建会话Id
+ private final DialogRequestIdHandler dialogRequestIdHandler;
+ // 基于通道活跃状态和优先级进行mediaPlayer调度
+ private final BaseMultiChannelMediaPlayer multiChannelMediaPlayer;
+ // 创建deviceModule工厂
+ private DeviceModuleFactory deviceModuleFactory;
+ // 和服务器端保持长连接、发送events和接收directives和维持心跳
+ private DcsClient dcsClient;
+ // 用于DeviceModules发送events
+ private IMessageSender messageSender;
+ // 服务器端返回response调度中心
+ private DcsResponseDispatcher dcsResponseDispatcher;
+
+ public DcsFramework(IPlatformFactory platformFactory) {
+ this.platformFactory = platformFactory;
+ dispatchDeviceModules = new HashMap<>();
+ dialogRequestIdHandler = new DialogRequestIdHandler();
+ multiChannelMediaPlayer = new PauseStrategyMultiChannelMediaPlayer(platformFactory);
+
+ createMessageSender();
+ createDcsClient();
+ createDeviceModuleFactory();
+ }
+
+ public void release() {
+ for (BaseDeviceModule deviceModule : dispatchDeviceModules.values()) {
+ deviceModule.release();
+ }
+ dcsClient.release();
+ dcsResponseDispatcher.release();
+ }
+
+ public DeviceModuleFactory getDeviceModuleFactory() {
+ return deviceModuleFactory;
+ }
+
+ private ArrayList<ClientContext> clientContexts() {
+ ArrayList<ClientContext> clientContexts = new ArrayList<>();
+ for (BaseDeviceModule deviceModule : dispatchDeviceModules.values()) {
+ ClientContext clientContext = deviceModule.clientContext();
+ if (clientContext != null) {
+ clientContexts.add(clientContext);
+ }
+ }
+
+ return clientContexts;
+ }
+
+ private void handleDirective(Directive directive) {
+ String namespace = directive.header.getNamespace();
+ try {
+ BaseDeviceModule deviceModule = dispatchDeviceModules.get(namespace);
+ if (deviceModule != null) {
+ deviceModule.handleDirective(directive);
+ } else {
+ String message = "No device to handle the directive";
+ throw new HandleDirectiveException(
+ HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message);
+ }
+ } catch (HandleDirectiveException exception) {
+ getSystemDeviceModule().sendExceptionEncounteredEvent(directive.rawMessage,
+ exception.getExceptionType(), exception.getMessage());
+ } catch (Exception exception) {
+ getSystemDeviceModule().sendExceptionEncounteredEvent(directive.rawMessage,
+ HandleDirectiveException.ExceptionType.INTERNAL_ERROR,
+ exception.getMessage()
+ );
+ }
+ }
+
+ private void createDcsClient() {
+ IDcsResponseHandler responseHandler = new IDcsResponseHandler() {
+ @Override
+ public void onResponse(final DcsResponseBody responseBody) {
+ platformFactory.getMainHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ LogUtil.d(TAG, "DcsResponseBodyEnqueue-handleDirective-MSG:"
+ + responseBody.getDirective().rawMessage);
+ handleDirective(responseBody.getDirective());
+ }
+ });
+ }
+
+ @Override
+ public void onParseFailed(String unParsedMessage) {
+ LogUtil.d(TAG, "DcsResponseBodyEnqueue-handleDirective-onParseFailed");
+ String message = "parse failed";
+ getSystemDeviceModule().sendExceptionEncounteredEvent(unParsedMessage,
+ HandleDirectiveException.ExceptionType.UNEXPECTED_INFORMATION_RECEIVED,
+ message);
+ }
+ };
+
+ dcsResponseDispatcher = new DcsResponseDispatcher(dialogRequestIdHandler, responseHandler);
+ dcsClient = new DcsClient(dcsResponseDispatcher, new DcsClient.IDcsClientListener() {
+ @Override
+ public void onConnected() {
+ LogUtil.d(TAG, "onConnected");
+ getSystemDeviceModule().sendSynchronizeStateEvent();
+ }
+
+ @Override
+ public void onUnconnected() {
+ LogUtil.d(TAG, "onUnconnected");
+ }
+ });
+ dcsClient.startConnect();
+ }
+
+ private void createMessageSender() {
+ messageSender = new IMessageSender() {
+ @Override
+ public void sendEvent(Event event, DcsStreamRequestBody streamRequestBody,
+ IResponseListener responseListener) {
+ DcsRequestBody requestBody = new DcsRequestBody(event);
+ requestBody.setClientContext(clientContexts());
+ dcsClient.sendRequest(requestBody, streamRequestBody, responseListener);
+ }
+
+ @Override
+ public void sendEvent(Event event, IResponseListener responseListener) {
+ sendEventRequest(event, null, responseListener);
+ }
+
+ @Override
+ public void sendEvent(Event event) {
+ sendEventRequest(event, null, null);
+ }
+
+ @Override
+ public void sentEventWithClientContext(Event event, IResponseListener responseListener) {
+ sendEventRequest(event, clientContexts(), responseListener);
+ }
+ };
+ }
+
+ private void sendEventRequest(Event event,
+ ArrayList<ClientContext> clientContexts,
+ IResponseListener responseListener) {
+ DcsRequestBody dcsRequestBody = new DcsRequestBody(event);
+ dcsRequestBody.setClientContext(clientContexts);
+ dcsClient.sendRequest(dcsRequestBody, responseListener);
+ }
+
+ private void createDeviceModuleFactory() {
+ deviceModuleFactory = new DeviceModuleFactory(new DeviceModuleFactory.IDeviceModuleHandler() {
+ @Override
+ public IPlatformFactory getPlatformFactory() {
+ return platformFactory;
+ }
+
+ @Override
+ public DialogRequestIdHandler getDialogRequestIdHandler() {
+ return dialogRequestIdHandler;
+ }
+
+ @Override
+ public IMessageSender getMessageSender() {
+ return messageSender;
+ }
+
+ @Override
+ public BaseMultiChannelMediaPlayer getMultiChannelMediaPlayer() {
+ return multiChannelMediaPlayer;
+ }
+
+ @Override
+ public void addDeviceModule(BaseDeviceModule deviceModule) {
+ DcsFramework.this.addDeviceModule(deviceModule);
+ }
+
+ @Override
+ public DcsResponseDispatcher getResponseDispatcher() {
+ return dcsResponseDispatcher;
+ }
+ });
+ }
+
+ private void addDeviceModule(BaseDeviceModule deviceModule) {
+ dispatchDeviceModules.put(deviceModule.getNameSpace(), deviceModule);
+ }
+
+ private SystemDeviceModule getSystemDeviceModule() {
+ return deviceModuleFactory.getSystemDeviceModule();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DcsResponseDispatcher.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.framework.dispatcher.AudioData;
+import com.baidu.duer.dcs.framework.dispatcher.DcsResponseBodyEnqueue;
+import com.baidu.duer.dcs.framework.dispatcher.WithDialogIdBlockThread;
+import com.baidu.duer.dcs.framework.dispatcher.WithoutDialogIdBlockThread;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * response调度中心,带有dialogRequestId directives按照顺序执行,对于speak指令播报完才执行下一个指令;
+ * 设备端收到不带dialogRequestId的directives立即执行
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsResponseDispatcher {
+ private final WithDialogIdBlockThread withDialogIdBlockThread;
+ private final WithoutDialogIdBlockThread withoutDialogIdBlockThread;
+ private final BlockingQueue<DcsResponseBody> dependentQueue;
+ private final BlockingQueue<DcsResponseBody> independentQueue;
+ private final DcsResponseBodyEnqueue dcsResponseBodyEnqueue;
+ private final IDcsResponseHandler responseHandler;
+
+ public DcsResponseDispatcher(final DialogRequestIdHandler dialogRequestIdHandler,
+ final IDcsResponseHandler responseHandler) {
+ this.responseHandler = responseHandler;
+ dependentQueue = new LinkedBlockingDeque<>();
+ independentQueue = new LinkedBlockingDeque<>();
+ dcsResponseBodyEnqueue = new DcsResponseBodyEnqueue(dialogRequestIdHandler, dependentQueue,
+ independentQueue);
+
+ withDialogIdBlockThread = new WithDialogIdBlockThread(dependentQueue, responseHandler,
+ "withDialogIdBlockThread");
+ withoutDialogIdBlockThread = new WithoutDialogIdBlockThread(independentQueue, responseHandler,
+ "withoutDialogIdBlockThread");
+ withDialogIdBlockThread.start();
+ withoutDialogIdBlockThread.start();
+ }
+
+ public void interruptDispatch() {
+ // 先清空队列,比如播放一首歌:speak+play指令组合的方式,在speak播报过程中进行打断,play就不需要执行了
+ withDialogIdBlockThread.clear();
+ // 让其处于等待新的指令处理
+ unBlockDependentQueue();
+ }
+
+ public void blockDependentQueue() {
+ withDialogIdBlockThread.block();
+ }
+
+ public void unBlockDependentQueue() {
+ withDialogIdBlockThread.unblock();
+ }
+
+ public void onResponseBody(DcsResponseBody responseBody) {
+ dcsResponseBodyEnqueue.handleResponseBody(responseBody);
+ }
+
+ public void onAudioData(AudioData audioData) {
+ dcsResponseBodyEnqueue.handleAudioData(audioData);
+ }
+
+ public void onParseFailed(String unParseMessage) {
+ if (responseHandler != null) {
+ responseHandler.onParseFailed(unParseMessage);
+ }
+ }
+
+ public void release() {
+ withDialogIdBlockThread.stopThread();
+ withoutDialogIdBlockThread.stopThread();
+ }
+
+ public interface IDcsResponseHandler {
+ void onResponse(DcsResponseBody responseBody);
+
+ void onParseFailed(String unParseMessage);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DeviceModuleFactory.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.devicemodule.alerts.AlertsDeviceModule;
+import com.baidu.duer.dcs.devicemodule.audioplayer.AudioPlayerDeviceModule;
+import com.baidu.duer.dcs.devicemodule.playbackcontroller.PlaybackControllerDeviceModule;
+import com.baidu.duer.dcs.devicemodule.screen.ScreenDeviceModule;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.SpeakerControllerDeviceModule;
+import com.baidu.duer.dcs.devicemodule.system.SystemDeviceModule;
+import com.baidu.duer.dcs.devicemodule.system.message.SetEndPointPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.ThrowExceptionPayload;
+import com.baidu.duer.dcs.devicemodule.voiceinput.VoiceInputDeviceModule;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.VoiceOutputDeviceModule;
+import com.baidu.duer.dcs.http.HttpConfig;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.systeminterface.IPlaybackController;
+import com.baidu.duer.dcs.systeminterface.IWebView;
+import com.baidu.duer.dcs.util.LogUtil;
+
+/**
+ * 创建语音输入、语音输出、扬声器、音频播放器、播放控制、闹钟、屏幕显示和系统等deviceModule
+ * <p>
+ * Created by wuruisheng on 2017/6/15.
+ */
+public class DeviceModuleFactory {
+ private static final String TAG = DeviceModuleFactory.class.getSimpleName();
+ private final IDeviceModuleHandler deviceModuleHandler;
+ private final IMediaPlayer dialogMediaPlayer;
+
+ private VoiceInputDeviceModule voiceInputDeviceModule;
+ private VoiceOutputDeviceModule voiceOutputDeviceModule;
+ private SpeakerControllerDeviceModule speakerControllerDeviceModule;
+ private AudioPlayerDeviceModule audioPlayerDeviceModule;
+ private AlertsDeviceModule alertsDeviceModule;
+ private SystemDeviceModule systemDeviceModule;
+ private PlaybackControllerDeviceModule playbackControllerDeviceModule;
+ private ScreenDeviceModule screenDeviceModule;
+
+ // 数字越大,优先级越高,播放优先级
+ private enum MediaChannel {
+ SPEAK("dialog", 3),
+ ALERT("alert", 2),
+ AUDIO("audio", 1);
+
+ private String channelName;
+ private int priority;
+
+ MediaChannel(String channelName, int priority) {
+ this.channelName = channelName;
+ this.priority = priority;
+ }
+ }
+
+ public DeviceModuleFactory(final IDeviceModuleHandler deviceModuleHandler) {
+ this.deviceModuleHandler = deviceModuleHandler;
+ dialogMediaPlayer = deviceModuleHandler.getMultiChannelMediaPlayer()
+ .addNewChannel(MediaChannel.SPEAK.channelName, MediaChannel.SPEAK.priority);
+ }
+
+
+ public void createVoiceInputDeviceModule() {
+ /*
+ * 传入VoiceOutput的MediaPlayer,因为根据dcs协议的规范
+ * 对话通道:
+ * 对应语音输入(Voice Input)和语音输出(Voice Output)端能力;
+ * 用户在语音请求时,或者设备在执行Speak指令进行播报时,对话通道进入活跃状态
+ */
+ voiceInputDeviceModule = new VoiceInputDeviceModule(
+ dialogMediaPlayer, deviceModuleHandler.getMessageSender(),
+ deviceModuleHandler.getPlatformFactory().getVoiceInput(),
+ deviceModuleHandler.getDialogRequestIdHandler(),
+ deviceModuleHandler.getResponseDispatcher());
+ deviceModuleHandler.addDeviceModule(voiceInputDeviceModule);
+ }
+
+ public VoiceInputDeviceModule getVoiceInputDeviceModule() {
+ return voiceInputDeviceModule;
+ }
+
+ public void createVoiceOutputDeviceModule() {
+ voiceOutputDeviceModule = new VoiceOutputDeviceModule(dialogMediaPlayer,
+ deviceModuleHandler.getMessageSender());
+ voiceOutputDeviceModule.addVoiceOutputListener(new VoiceOutputDeviceModule.IVoiceOutputListener() {
+ @Override
+ public void onVoiceOutputStarted() {
+ LogUtil.d(TAG, "DcsResponseBodyEnqueue-onVoiceOutputStarted ok ");
+ deviceModuleHandler.getResponseDispatcher().blockDependentQueue();
+ }
+
+ @Override
+ public void onVoiceOutputFinished() {
+ LogUtil.d(TAG, "DcsResponseBodyEnqueue-onVoiceOutputFinished ok ");
+ deviceModuleHandler.getResponseDispatcher().unBlockDependentQueue();
+ }
+ });
+
+ deviceModuleHandler.addDeviceModule(voiceOutputDeviceModule);
+ }
+
+ public void createSpeakControllerDeviceModule() {
+ BaseMultiChannelMediaPlayer.ISpeakerController speakerController =
+ deviceModuleHandler.getMultiChannelMediaPlayer().getSpeakerController();
+ speakerControllerDeviceModule =
+ new SpeakerControllerDeviceModule(speakerController,
+ deviceModuleHandler.getMessageSender());
+ deviceModuleHandler.addDeviceModule(speakerControllerDeviceModule);
+ }
+
+ public void createAudioPlayerDeviceModule() {
+ IMediaPlayer mediaPlayer = deviceModuleHandler.getMultiChannelMediaPlayer()
+ .addNewChannel(MediaChannel.AUDIO.channelName,
+ MediaChannel.AUDIO.priority);
+ audioPlayerDeviceModule = new AudioPlayerDeviceModule(mediaPlayer,
+ deviceModuleHandler.getMessageSender());
+ deviceModuleHandler.addDeviceModule(audioPlayerDeviceModule);
+ }
+
+ public AudioPlayerDeviceModule getAudioPlayerDeviceModule() {
+ return audioPlayerDeviceModule;
+ }
+
+ public void createAlertsDeviceModule() {
+ IMediaPlayer mediaPlayer = deviceModuleHandler.getMultiChannelMediaPlayer()
+ .addNewChannel(MediaChannel.ALERT.channelName,
+ MediaChannel.ALERT.priority);
+ alertsDeviceModule = new AlertsDeviceModule(mediaPlayer,
+ deviceModuleHandler.getPlatformFactory().createAlertsDataStore(),
+ deviceModuleHandler.getMessageSender(),
+ deviceModuleHandler.getPlatformFactory().getMainHandler());
+
+ alertsDeviceModule.addAlertListener(new AlertsDeviceModule.IAlertListener() {
+ @Override
+ public void onAlertStarted(String alertToken) {
+ }
+ });
+
+ deviceModuleHandler.addDeviceModule(alertsDeviceModule);
+ }
+
+ public void createSystemDeviceModule() {
+ systemDeviceModule = new SystemDeviceModule(deviceModuleHandler.getMessageSender());
+ systemDeviceModule.addModuleListener(new SystemDeviceModule.IDeviceModuleListener() {
+ @Override
+ public void onSetEndpoint(SetEndPointPayload endPointPayload) {
+ if (null != endPointPayload) {
+ String endpoint = endPointPayload.getEndpoint();
+ if (null != endpoint && endpoint.length() > 0) {
+ HttpConfig.setEndpoint(endpoint);
+ }
+ }
+ }
+
+ @Override
+ public void onThrowException(ThrowExceptionPayload throwExceptionPayload) {
+ LogUtil.v(TAG, throwExceptionPayload.toString());
+ }
+ });
+ deviceModuleHandler.addDeviceModule(systemDeviceModule);
+ }
+
+ public SystemDeviceModule getSystemDeviceModule() {
+ return systemDeviceModule;
+ }
+
+ public SystemDeviceModule.Provider getSystemProvider() {
+ return systemDeviceModule.getProvider();
+ }
+
+ public void createPlaybackControllerDeviceModule() {
+ IPlaybackController playback = deviceModuleHandler.getPlatformFactory().getPlayback();
+ playbackControllerDeviceModule = new PlaybackControllerDeviceModule(playback,
+ deviceModuleHandler.getMessageSender(), alertsDeviceModule);
+ deviceModuleHandler.addDeviceModule(playbackControllerDeviceModule);
+ }
+
+ public void createScreenDeviceModule() {
+ IWebView webView = deviceModuleHandler.getPlatformFactory().getWebView();
+ screenDeviceModule = new ScreenDeviceModule(webView, deviceModuleHandler.getMessageSender());
+ deviceModuleHandler.addDeviceModule(screenDeviceModule);
+ }
+
+ public interface IDeviceModuleHandler {
+ IPlatformFactory getPlatformFactory();
+
+ DialogRequestIdHandler getDialogRequestIdHandler();
+
+ IMessageSender getMessageSender();
+
+ BaseMultiChannelMediaPlayer getMultiChannelMediaPlayer();
+
+ void addDeviceModule(BaseDeviceModule deviceModule);
+
+ DcsResponseDispatcher getResponseDispatcher();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DialogRequestIdHandler.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+import java.util.UUID;
+
+/**
+ * 生成dialogRequestId
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class DialogRequestIdHandler {
+ private String activeDialogRequestId;
+
+ public DialogRequestIdHandler() {
+ }
+
+ public String createActiveDialogRequestId() {
+ activeDialogRequestId = UUID.randomUUID().toString();
+ return activeDialogRequestId;
+ }
+
+ /**
+ * 判断当前dialogRequestId是否活跃的
+ *
+ * @param dialogRequestId dialogRequestId
+ * @return dialogRequestId与activeDialogRequestId相等则返回true,否则返回false
+ */
+ public Boolean isActiveDialogRequestId(String dialogRequestId) {
+ return activeDialogRequestId != null && activeDialogRequestId.equals(dialogRequestId);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/IMessageSender.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.framework.message.Event;
+
+/**
+ * 发送event接口
+ * <p>
+ * Created by wuruisheng on 2017/6/15.
+ */
+public interface IMessageSender {
+ /**
+ * 发送event
+ *
+ * @param event
+ */
+ void sendEvent(Event event);
+
+ /**
+ * 发送event
+ *
+ * @param event
+ * @param responseListener 回调
+ */
+ void sendEvent(Event event, IResponseListener responseListener);
+
+ /**
+ * 发送event且带有stream
+ *
+ * @param event event对象
+ * @param streamRequestBody stream对象
+ * @param responseListener 回调
+ */
+ void sendEvent(Event event, DcsStreamRequestBody streamRequestBody, IResponseListener responseListener);
+
+ /**
+ * 发送event带上clientContext
+ *
+ * @param event event对象
+ * @param responseListener 回调
+ */
+ void sentEventWithClientContext(Event event, IResponseListener responseListener);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/IResponseListener.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+/**
+ * 网络请求回调
+ * <p>
+ * Created by wuruisheng on 2017/6/17.
+ */
+public interface IResponseListener {
+ /**
+ * 成功回调
+ *
+ * @param statusCode http返回statusCode
+ */
+ void onSucceed(int statusCode);
+
+ /**
+ * 失败回调
+ *
+ * @param errorMessage 出错的异常信息
+ */
+ void onFailed(String errorMessage);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/PauseStrategyMultiChannelMediaPlayer.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * 暂停模式的播放控制策略
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/6.
+ */
+public class PauseStrategyMultiChannelMediaPlayer extends BaseMultiChannelMediaPlayer {
+ private static final String TAG = BaseMultiChannelMediaPlayer.class.getSimpleName();
+
+ public PauseStrategyMultiChannelMediaPlayer(IPlatformFactory factory) {
+ super(factory);
+ }
+
+ @Override
+ protected void handlePlay(String channelName, IMediaPlayer.MediaResource mediaResource) {
+ int priority = getPriorityByChannelName(channelName);
+ LogUtil.d(TAG, "handlePlay-priority:" + priority);
+ if (priority == UNKNOWN_PRIORITY) {
+ return;
+ }
+ ChannelMediaPlayerInfo info = new ChannelMediaPlayerInfo();
+ info.mediaPlayer = getMediaPlayer(channelName);
+ info.priority = priority;
+ info.channelName = channelName;
+ info.mediaResource = mediaResource;
+ currentPlayMap.put(priority, info);
+
+ // 把比当前优先级低的播放器都暂停
+ Iterator<Map.Entry<Integer, ChannelMediaPlayerInfo>> it = currentPlayMap.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<Integer, ChannelMediaPlayerInfo> entry = it.next();
+ ChannelMediaPlayerInfo value = entry.getValue();
+ LogUtil.d(TAG, "handlePlay-value:" + value.priority);
+ if (priority > value.priority) {
+ LogUtil.d(TAG, "handlePlay-value-pause:" + value.priority);
+ value.mediaPlayer.pause();
+ }
+ }
+ findToPlay();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/AudioData.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.dispatcher;
+
+/**
+ * 存储音频数据
+ * <p>
+ * Created by wuruisheng on 2017/5/13.
+ */
+public class AudioData {
+ public String contentId;
+ public byte[] partBytes;
+
+ public AudioData(String contentId, byte[] partBytes) {
+ this.contentId = contentId;
+ this.partBytes = partBytes;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/BaseBlockResponseThread.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * 单独线程阻塞控制response回调处理
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public abstract class BaseBlockResponseThread extends Thread {
+ private static final String TAG = BaseBlockResponseThread.class.getSimpleName();
+ private BlockingQueue<DcsResponseBody> responseBodyDeque;
+ private DcsResponseDispatcher.IDcsResponseHandler responseHandler;
+ private volatile boolean block;
+ private volatile boolean isStop;
+
+ public BaseBlockResponseThread(BlockingQueue<DcsResponseBody> responseBodyDeque,
+ DcsResponseDispatcher.IDcsResponseHandler responseHandler, String threadName) {
+ this.responseBodyDeque = responseBodyDeque;
+ this.responseHandler = responseHandler;
+ setName(threadName);
+ }
+
+ public synchronized void block() {
+ block = true;
+ }
+
+ public synchronized void unblock() {
+ block = false;
+ notify();
+ }
+
+ public synchronized void clear() {
+ responseBodyDeque.clear();
+ }
+
+ public synchronized void stopThread() {
+ clear();
+ isStop = true;
+ this.interrupt();
+ }
+
+ @Override
+ public void run() {
+ while (!isStop) {
+ try {
+ synchronized (this) {
+ if (block) {
+ wait();
+ }
+ }
+
+ if (responseHandler != null) {
+ DcsResponseBody responseBody = responseBodyDeque.take();
+ responseHandler.onResponse(responseBody);
+
+ if (shouldBlock(responseBody)) {
+ block = true;
+ }
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ abstract boolean shouldBlock(DcsResponseBody responseBody);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/DcsJsonProcessingException.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.dispatcher;
+
+import org.codehaus.jackson.JsonProcessingException;
+
+/**
+ * json序列化成异常对象
+ * <p>
+ * Created by wuruisheng on 2017/6/8.
+ */
+public class DcsJsonProcessingException extends JsonProcessingException {
+ private String unparsedCotent;
+
+ public DcsJsonProcessingException(String message, JsonProcessingException exception, String unparsedCotent) {
+ super(message, exception);
+ this.unparsedCotent = unparsedCotent;
+ }
+
+ public String getUnparsedCotent() {
+ return unparsedCotent;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/DcsResponseBodyEnqueue.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.framework.message.AttachedContentPayload;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+import com.baidu.duer.dcs.framework.DialogRequestIdHandler;
+import com.baidu.duer.dcs.framework.message.DialogRequestIdHeader;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+
+/**
+ * 带有dialogRequestId response进入dependentQueue队列,否则进入independentQueue
+ * 带有attached的directive需要知道找到对应的二进制数据才放到上述队列中
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsResponseBodyEnqueue {
+ private static final String TAG = DcsResponseBodyEnqueue.class.getSimpleName();
+ private final DialogRequestIdHandler dialogRequestIdHandler;
+ private final Queue<DcsResponseBody> dependentQueue;
+ private final Queue<DcsResponseBody> independentQueue;
+ private final Queue<DcsResponseBody> incompleteResponseQueue;
+ private final Map<String, AudioData> audioDataMap;
+
+ public DcsResponseBodyEnqueue(DialogRequestIdHandler dialogRequestIdHandler,
+ Queue<DcsResponseBody> dependentQueue,
+ Queue<DcsResponseBody> independentQueue) {
+ this.dialogRequestIdHandler = dialogRequestIdHandler;
+ this.dependentQueue = dependentQueue;
+ this.independentQueue = independentQueue;
+ incompleteResponseQueue = new LinkedList<>();
+ audioDataMap = new HashMap<>();
+ }
+
+ public synchronized void handleResponseBody(DcsResponseBody responseBody) {
+ incompleteResponseQueue.add(responseBody);
+ matchAudioDataWithResponseBody();
+ }
+
+ public synchronized void handleAudioData(AudioData audioData) {
+ audioDataMap.put(audioData.contentId, audioData);
+ matchAudioDataWithResponseBody();
+ }
+
+ private void matchAudioDataWithResponseBody() {
+ for (DcsResponseBody responseBody : incompleteResponseQueue) {
+ Directive directive = responseBody.getDirective();
+ if (directive == null) {
+ return;
+ }
+
+ Payload payload = responseBody.getDirective().payload;
+ if (payload instanceof AttachedContentPayload) {
+ AttachedContentPayload attachedContentPayload = (AttachedContentPayload) payload;
+ String contentId = attachedContentPayload.getAttachedContentId();
+ AudioData audioData = audioDataMap.remove(contentId);
+ if (audioData != null) {
+ attachedContentPayload.setAttachedContent(contentId, audioData.partBytes);
+ }
+ }
+ }
+
+ findCompleteResponseBody();
+ }
+
+ private void findCompleteResponseBody() {
+ Iterator<DcsResponseBody> iterator = incompleteResponseQueue.iterator();
+ while (iterator.hasNext()) {
+ DcsResponseBody responseBody = iterator.next();
+ Payload payload = responseBody.getDirective().payload;
+ if (payload instanceof AttachedContentPayload) {
+ AttachedContentPayload attachedContentPayload = (AttachedContentPayload) payload;
+
+ if (!attachedContentPayload.requiresAttachedContent()) {
+ // The front most directive IS complete.
+ enqueueResponseBody(responseBody);
+ iterator.remove();
+ } else {
+ break;
+ }
+ } else {
+ // Immediately enqueue any directive which does not contain audio content
+ enqueueResponseBody(responseBody);
+ iterator.remove();
+ }
+ }
+ }
+
+ private void enqueueResponseBody(DcsResponseBody responseBody) {
+ LogUtil.d(TAG, "DcsResponseBodyEnqueue-RecordThread:" + responseBody.getDirective().rawMessage);
+ Header header = responseBody.getDirective().header;
+ DialogRequestIdHeader dialogRequestIdHeader = (DialogRequestIdHeader) header;
+ if (dialogRequestIdHeader.getDialogRequestId() == null) {
+ LogUtil.d(TAG, "DcsResponseBodyEnqueue-DialogRequestId is null ,add to independentQueue");
+ independentQueue.add(responseBody);
+ } else if (dialogRequestIdHandler.isActiveDialogRequestId(dialogRequestIdHeader.getDialogRequestId())) {
+ LogUtil.d(TAG, "DcsResponseBodyEnqueue-DialogRequestId not null,add to dependentQueue");
+ dependentQueue.add(responseBody);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/MultipartParser.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+import com.baidu.duer.dcs.http.HttpConfig;
+
+import org.apache.commons.fileupload.MultipartStream;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import okhttp3.Response;
+
+/**
+ * 把从服务器返回multipart中json对象和二进制解析成directive对象
+ * <p>
+ * Created by wuruisheng on 2017/5/12.
+ */
+public class MultipartParser extends Parser {
+ private static final int BUFFER_SIZE = 512;
+ private final IMultipartParserListener multipartParserListener;
+
+ public MultipartParser(IMultipartParserListener listener) {
+ this.multipartParserListener = listener;
+ }
+
+ public void parseResponse(Response response) throws IOException {
+ String boundary = getBoundary(response);
+ if (boundary != null) {
+ parseStream(response.body().byteStream(), boundary);
+ }
+ }
+
+ private void parseStream(InputStream inputStream, String boundary) throws IOException {
+ MultipartStream multipartStream = new MultipartStream(inputStream, boundary.getBytes(), BUFFER_SIZE, null);
+ parseMultipartStream(multipartStream);
+ }
+
+ private void parseMultipartStream(MultipartStream multipartStream) throws IOException {
+ try {
+ Boolean hasNextPart = multipartStream.skipPreamble();
+ while (hasNextPart) {
+ handlePart(multipartStream);
+ hasNextPart = multipartStream.readBoundary();
+ }
+ } catch (DcsJsonProcessingException exception) {
+ if (multipartParserListener != null) {
+ multipartParserListener.onParseFailed(exception.getUnparsedCotent());
+ }
+ } catch (MultipartStream.MalformedStreamException exception) {
+ // 用于处理 empty part
+ }
+ }
+
+ private void handlePart(MultipartStream multipartStream) throws IOException {
+ Map<String, String> headers = getPartHeaders(multipartStream);
+ if (headers != null) {
+ byte[] partBytes = getPartBytes(multipartStream);
+ Boolean isJsonData = isPartJSON(headers);
+ if (isJsonData) {
+ handleJsonData(partBytes);
+ } else {
+ handleAudio(headers, partBytes);
+ }
+ }
+ }
+
+ private void handleJsonData(byte[] partBytes) throws IOException {
+ final DcsResponseBody responseBody = parse(partBytes, DcsResponseBody.class);
+ if (multipartParserListener != null) {
+ multipartParserListener.onResponseBody(responseBody);
+ }
+ }
+
+ private void handleAudio(Map<String, String> headers, byte[] partBytes) {
+ String contentId = getMultipartContentId(headers);
+ final AudioData audioData = new AudioData(contentId, partBytes);
+ if (multipartParserListener != null) {
+ multipartParserListener.onAudioData(audioData);
+ }
+ }
+
+ private byte[] getPartBytes(MultipartStream multipartStream) throws IOException {
+ ByteArrayOutputStream data = new ByteArrayOutputStream();
+ multipartStream.readBodyData(data);
+ return data.toByteArray();
+ }
+
+ private Map<String, String> getPartHeaders(MultipartStream multipartStream) throws IOException {
+ String headers = multipartStream.readHeaders();
+ BufferedReader reader = new BufferedReader(new StringReader(headers));
+ Map<String, String> headerMap = new HashMap<>();
+ try {
+ for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+ line = line.trim();
+ if (!StringUtils.isBlank(line) && line.contains(":")) {
+ int colon = line.indexOf(":");
+ String headerName = line.substring(0, colon).trim();
+ String headerValue = line.substring(colon + 1).trim();
+ headerMap.put(headerName.toLowerCase(), headerValue);
+ }
+ }
+ } catch (Exception e) {
+ throw e;
+ }
+
+ return headerMap;
+ }
+
+ private String getMultipartHeaderValue(Map<String, String> headers, String searchHeader) {
+ return headers.get(searchHeader.toLowerCase());
+ }
+
+ private String getMultipartContentId(Map<String, String> headers) {
+ String contentId = getMultipartHeaderValue(headers, HttpConfig.HttpHeaders.CONTENT_ID);
+ contentId = contentId.substring(1, contentId.length() - 1);
+ return contentId;
+ }
+
+ private boolean isPartJSON(Map<String, String> headers) {
+ String contentType = getMultipartHeaderValue(headers, HttpConfig.HttpHeaders.CONTENT_TYPE);
+ return StringUtils.contains(contentType, HttpConfig.ContentTypes.JSON);
+ }
+
+ private static String getBoundary(Response response) {
+ String headerValue = response.header(HttpConfig.HttpHeaders.CONTENT_TYPE);
+ String boundary = getHeaderParameter(headerValue, HttpConfig.Parameters.BOUNDARY);
+ return boundary;
+ }
+
+ private static String getHeaderParameter(final String headerValue, final String key) {
+ if ((headerValue == null) || (key == null)) {
+ return null;
+ }
+
+ String[] parts = headerValue.split(";");
+ for (String part : parts) {
+ part = part.trim();
+ if (part.startsWith(key)) {
+ return part.substring(key.length() + 1).replaceAll("(^\")|(\"$)", "").trim();
+ }
+ }
+
+ return null;
+ }
+
+ public interface IMultipartParserListener {
+ void onResponseBody(DcsResponseBody responseBody);
+
+ void onAudioData(AudioData audioData);
+
+ void onParseFailed(String unParseMessage);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/Parser.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.util.ObjectMapperUtil;
+
+import org.codehaus.jackson.JsonProcessingException;
+
+import java.io.IOException;
+
+/**
+ * 字节数据转换成对象
+ * <p>
+ * Created by wuruisheng on 2017/5/12.
+ */
+public class Parser {
+ protected <T> T parse(byte[] bytes, Class<T> clazz) throws IOException {
+ try {
+ return ObjectMapperUtil.instance().getObjectReader().withType(clazz).readValue(bytes);
+ } catch (JsonProcessingException e) {
+ String unparsedContent = new String(bytes, "UTF-8");
+ String message = String.format("failed to parse %1$s", clazz.getSimpleName());
+ throw new DcsJsonProcessingException(message, e, unparsedContent);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/WithDialogIdBlockThread.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.devicemodule.voiceoutput.ApiConstants;
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * 服务器返回的指令header中有dialogRequestId调度线程
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/12.
+ */
+public class WithDialogIdBlockThread extends BaseBlockResponseThread {
+
+ public WithDialogIdBlockThread(BlockingQueue<DcsResponseBody> responseBodyDeque,
+ DcsResponseDispatcher.IDcsResponseHandler responseHandler,
+ String threadName) {
+ super(responseBodyDeque, responseHandler, threadName);
+ }
+
+ @Override
+ boolean shouldBlock(DcsResponseBody responseBody) {
+ // 如果是speak指令就立马阻塞
+ String directiveName = responseBody.getDirective().getName();
+ return directiveName != null && directiveName.length() > 0
+ && directiveName.equals(ApiConstants.Directives.Speak.NAME);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/WithoutDialogIdBlockThread.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * 服务器返回的指令header中没有dialogRequestId调度线程
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/12.
+ */
+public class WithoutDialogIdBlockThread extends BaseBlockResponseThread {
+ public WithoutDialogIdBlockThread(BlockingQueue<DcsResponseBody> responseBodyDeque,
+ DcsResponseDispatcher.IDcsResponseHandler responseHandler,
+ String threadName) {
+ super(responseBodyDeque, responseHandler, threadName);
+ }
+
+ @Override
+ boolean shouldBlock(DcsResponseBody responseBody) {
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/heartbeat/HeartBeat.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.heartbeat;
+
+import com.baidu.duer.dcs.http.HttpConfig;
+import com.baidu.duer.dcs.http.HttpRequestInterface;
+import com.baidu.duer.dcs.http.callback.ResponseCallback;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import okhttp3.Call;
+import okhttp3.Response;
+
+/**
+ * 用于检测Directives 是否正常
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/17.
+ */
+public class HeartBeat {
+ private static final String TAG = HeartBeat.class.getSimpleName();
+ // 设置ping成功后的(ping成功即代表directive请求成功了)请求的时间间隔
+ // 修改成270s原因:国内网关保持一个连接时间一般都是300s
+ private static final long PING_TIME_SUCCEED = 30 * 1000;
+ // 设置ping失败后的(ping失败即代表directive请求失败了)请求的时间间隔
+ private static final long PING_TIME_FAILED = 5 * 1000;
+ private final HttpRequestInterface httpRequest;
+ private Timer timer;
+ private PingTask pingTask;
+ private IHeartbeatListener listener;
+ // 连接状态
+ private ConnectState connectState;
+
+ private enum ConnectState {
+ CONNECTED,
+ UNCONNECTED
+ }
+
+ public HeartBeat(HttpRequestInterface httpRequest) {
+ this.httpRequest = httpRequest;
+ timer = new Timer();
+ }
+
+ /**
+ * 如果Directives连接成功了,调用此方法进行探测
+ */
+ public void startNormalPing() {
+ connectState = ConnectState.CONNECTED;
+ startPing(PING_TIME_SUCCEED, PING_TIME_SUCCEED);
+ }
+
+ /**
+ * 如果Directives连接异常了,调用此方法进行探测
+ */
+ public void startExceptionalPing() {
+ connectState = ConnectState.UNCONNECTED;
+ startPing(PING_TIME_FAILED, PING_TIME_FAILED);
+ }
+
+ /**
+ * 如果Events连接异常了,调用此方法进行探测
+ */
+ public void startImmediatePing() {
+ connectState = ConnectState.UNCONNECTED;
+ startPing(0, PING_TIME_FAILED);
+ }
+
+ private void fireOnConnect() {
+ if (listener != null) {
+ listener.onStartConnect();
+ }
+ }
+
+ private void startPing(long delay, long timeInterval) {
+ if (pingTask != null) {
+ pingTask.cancel();
+ }
+ pingTask = new PingTask();
+ if (timer != null) {
+ timer.schedule(pingTask, delay, timeInterval);
+ }
+ }
+
+ /**
+ * 停止ping探测,释放资源
+ */
+ public void release() {
+ if (pingTask != null) {
+ pingTask.cancel();
+ pingTask = null;
+ }
+
+ timer.cancel();
+ timer = null;
+ httpRequest.cancelRequest(HttpConfig.HTTP_PING_TAG);
+ }
+
+ private void ping() {
+ httpRequest.cancelRequest(HttpConfig.HTTP_PING_TAG);
+ httpRequest.doGetPingAsync(null, new ResponseCallback() {
+ @Override
+ public void onError(Call call, Exception e, int id) {
+ super.onError(call, e, id);
+ LogUtil.d(TAG, "ping onError");
+ connectState = ConnectState.UNCONNECTED;
+ fireOnConnect();
+ }
+
+ @Override
+ public void onResponse(Response response, int id) {
+ super.onResponse(response, id);
+ LogUtil.d(TAG, "ping onResponse, code :" + response.code());
+ if (response.code() == 200 || response.code() == 204) {
+ if (connectState == ConnectState.UNCONNECTED) {
+ fireOnConnect();
+ }
+ } else {
+ connectState = ConnectState.UNCONNECTED;
+ fireOnConnect();
+ }
+ }
+ });
+ }
+
+ public void setHeartbeatListener(IHeartbeatListener listener) {
+ this.listener = listener;
+ }
+
+ /**
+ * ping 回调接口
+ */
+ public interface IHeartbeatListener {
+ /**
+ * 需要建立长连接时回调
+ */
+ void onStartConnect();
+ }
+
+ private final class PingTask extends TimerTask {
+ @Override
+ public void run() {
+ ping();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/AttachedContentPayload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+/**
+ * 语音输出speak指令附加内容
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public interface AttachedContentPayload {
+ boolean requiresAttachedContent();
+ boolean hasAttachedContent();
+ String getAttachedContentId();
+ byte[] getAttachedContent();
+ void setAttachedContent(String contentId, byte[] attachmentContent);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/BaseMessage.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+/**
+ * 带有header和payload的消息体基类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class BaseMessage {
+ private Header header;
+ private Payload payload;
+
+ public BaseMessage(Header header, Payload payload) {
+ this.header = header;
+ this.payload = payload;
+ }
+
+ public void setHeader(Header header) {
+ this.header = header;
+ }
+
+ public Header getHeader() {
+ return header;
+ }
+
+ public void setPayload(Payload payload) {
+ this.payload = payload;
+ }
+
+ public Payload getPayload() {
+ return payload;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/ClientContext.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+/**
+ * 端状态:服务端在处理某些事件时,需要了解在请求当时设备端各模块所处的状态。比如端上是否正在播放音乐,
+ * 是否有闹钟在响,是否正在播报等等
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class ClientContext extends BaseMessage {
+ public ClientContext(Header header, Payload payload) {
+ super(header, payload);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DcsRequestBody.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import java.util.ArrayList;
+
+/**
+ * 网络请求的消息体
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+public class DcsRequestBody {
+ private ArrayList<ClientContext> clientContext;
+ private Event event;
+
+ public DcsRequestBody(Event event) {
+ this.event = event;
+ }
+
+ public void setClientContext(ArrayList<ClientContext> clientContexts) {
+ this.clientContext = clientContexts;
+ }
+
+ public ArrayList<ClientContext> getClientContext() {
+ return clientContext;
+ }
+
+ public void setEvent(Event event) {
+ this.event = event;
+ }
+
+ public Event getEvent() {
+ return event;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DcsResponseBody.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+/**
+ * 服务器端返回应答
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsResponseBody {
+ // 指令
+ private Directive directive;
+
+ public Directive getDirective() {
+ return directive;
+ }
+
+ public void setDirective(Directive directive) {
+ this.directive = directive;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DcsStreamRequestBody.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+import com.baidu.duer.dcs.http.OkHttpMediaType;
+
+import java.io.IOException;
+
+import okhttp3.MediaType;
+import okhttp3.RequestBody;
+import okio.BufferedSink;
+import okio.Okio;
+import okio.Pipe;
+
+/**
+ * 流请求消息体
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsStreamRequestBody extends RequestBody {
+ private final Pipe pipe = new Pipe(8192);
+ private final BufferedSink mSink = Okio.buffer(pipe.sink());
+
+ public BufferedSink sink() {
+ return mSink;
+ }
+
+ @Override
+ public MediaType contentType() {
+ return OkHttpMediaType.MEDIA_STREAM_TYPE;
+ }
+
+ @Override
+ public void writeTo(BufferedSink bufferedSink) throws IOException {
+ bufferedSink.writeAll(pipe.source());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DialogRequestIdHeader.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+/**
+ * 带请求会话Id头部
+ * <p>
+ * Created by wuruisheng@baidu.com on 2017/5/31.
+ */
+public class DialogRequestIdHeader extends MessageIdHeader {
+ // 请求会话id
+ private String dialogRequestId;
+
+ public DialogRequestIdHeader() {
+
+ }
+
+ public DialogRequestIdHeader(String nameSpace, String name, String dialogRequestId) {
+ super(nameSpace, name);
+ this.dialogRequestId = dialogRequestId;
+ }
+
+ public final String getDialogRequestId() {
+ return dialogRequestId;
+ }
+
+ public final void setDialogRequestId(String dialogRequestId) {
+ this.dialogRequestId = dialogRequestId;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%1$s dialogRequestId:%2$s", super.toString(), dialogRequestId);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Directive.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+import com.baidu.duer.dcs.util.ObjectMapperUtil;
+
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.map.DeserializationContext;
+import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectReader;
+import org.codehaus.jackson.map.annotate.JsonDeserialize;
+import org.codehaus.jackson.node.ObjectNode;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * 指令类:服务端下发给设备端去执行
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+@JsonDeserialize(using = Directive.DirectiveDeserializer.class)
+public class Directive {
+ public Header header;
+ public Payload payload;
+
+ @JsonIgnore
+ public String rawMessage;
+
+
+ public Directive(Header header, JsonNode payload, String rawMessage) throws IOException {
+ this.header = header;
+ String namespace = header.getNamespace();
+ String name = header.getName();
+ Class<?> payloadType = PayloadConfig.getInstance().findPayloadClass(namespace, name);
+ if (null != payloadType) {
+ this.payload = ObjectMapperUtil.instance().getObjectReader().withType(payloadType).readValue(payload);
+ } else {
+ this.payload = new Payload();
+ }
+
+ this.rawMessage = rawMessage;
+ }
+
+ /**
+ * jackson反序列化directive对象
+ */
+ public static class DirectiveDeserializer extends JsonDeserializer<Directive> {
+ @Override
+ public Directive deserialize(JsonParser jp, DeserializationContext ctx)
+ throws IOException {
+ ObjectReader reader = ObjectMapperUtil.instance().getObjectReader();
+ ObjectNode obj = (ObjectNode) reader.readTree(jp);
+ Iterator<Map.Entry<String, JsonNode>> elementsIterator = obj.getFields();
+
+ String rawMessage = obj.toString();
+ DialogRequestIdHeader header = null;
+ JsonNode payloadNode = null;
+ ObjectReader headerReader =
+ ObjectMapperUtil.instance().getObjectReader(DialogRequestIdHeader.class);
+ while (elementsIterator.hasNext()) {
+ Map.Entry<String, JsonNode> element = elementsIterator.next();
+ if (element.getKey().equals("header")) {
+ header = headerReader.readValue(element.getValue());
+ }
+ if (element.getKey().equals("payload")) {
+ payloadNode = element.getValue();
+ }
+ }
+ if (header == null) {
+ throw ctx.mappingException("Missing header");
+ }
+ if (payloadNode == null) {
+ throw ctx.mappingException("Missing payload");
+ }
+
+ return createDirective(header, payloadNode, rawMessage);
+ }
+
+ private Directive createDirective(Header header, JsonNode payload, String rawMessage)
+ throws JsonParseException, JsonMappingException, IOException {
+ return new Directive(header, payload, rawMessage);
+ }
+ }
+
+ @JsonIgnore
+ public String getName() {
+ return header.getName();
+ }
+
+ public Payload getPayload() {
+ return payload;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Event.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+/**
+ * 事件:设备端上发生任何事情,需要通过事件来通知服务端
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class Event extends BaseMessage {
+ public Event(Header header, Payload payload) {
+ super(header, payload);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Header.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+/**
+ * header类
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class Header {
+ private String namespace;
+ private String name;
+
+ public Header() {
+ }
+
+ public Header(String namespace, String name) {
+ setNamespace(namespace);
+ setName(name);
+ }
+
+ public final void setNamespace(String namespace) {
+ if (namespace == null) {
+ throw new IllegalArgumentException("Header namespace must not be null");
+ }
+ this.namespace = namespace;
+ }
+
+ public final void setName(String name) {
+ if (name == null) {
+ throw new IllegalArgumentException("Header name must not be null");
+ }
+ this.name = name;
+ }
+
+ public final String getNamespace() {
+ return namespace;
+ }
+
+ public final String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "Header{"
+ + "namespace='"
+ + namespace
+ + '\''
+ + ", name='"
+ + name
+ + '\''
+ + '}';
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/MessageIdHeader.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+import java.util.UUID;
+
+/**
+ * 带有MessageId的Header
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class MessageIdHeader extends Header {
+ private String messageId;
+
+ public MessageIdHeader() {
+ super();
+ }
+
+ public MessageIdHeader(String nameSpace, String name) {
+ super(nameSpace, name);
+
+ messageId = UUID.randomUUID().toString();
+ }
+
+ public final void setMessageId(String messageId) {
+ this.messageId = messageId;
+ }
+
+ public final String getMessageId() {
+ return messageId;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%1$s id:%2$s", super.toString(), messageId);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Payload.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+/**
+ * Payload基类
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class Payload {
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/PayloadConfig.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.framework.message;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.DeleteAlertPayload;
+import com.baidu.duer.dcs.devicemodule.alerts.message.SetAlertPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.ClearQueuePayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlayPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.StopPayload;
+import com.baidu.duer.dcs.devicemodule.screen.message.HtmlPayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.AdjustVolumePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.SetMutePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.SetVolumePayload;
+import com.baidu.duer.dcs.devicemodule.system.message.SetEndPointPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.ThrowExceptionPayload;
+import com.baidu.duer.dcs.devicemodule.voiceinput.message.ListenPayload;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.message.SpeakPayload;
+
+import java.util.HashMap;
+
+/**
+ * 利用namespace和name做为key存储不同payload子类class并且find
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class PayloadConfig {
+ private final HashMap<String, Class<?>> payloadClass;
+
+ private static class PayloadConfigHolder {
+ private static final PayloadConfig instance = new PayloadConfig();
+ }
+
+ public static PayloadConfig getInstance() {
+ return PayloadConfigHolder.instance;
+ }
+
+ private PayloadConfig() {
+ payloadClass = new HashMap<>();
+
+ // AudioInputImpl
+ String namespace = com.baidu.duer.dcs.devicemodule.voiceinput.ApiConstants.NAMESPACE;
+ String name = com.baidu.duer.dcs.devicemodule.voiceinput.ApiConstants.Directives.Listen.NAME;
+ insertPayload(namespace, name, ListenPayload.class);
+
+ // VoiceOutput
+ namespace = com.baidu.duer.dcs.devicemodule.voiceoutput.ApiConstants.NAMESPACE;
+ name = com.baidu.duer.dcs.devicemodule.voiceoutput.ApiConstants.Directives.Speak.NAME;
+ insertPayload(namespace, name, SpeakPayload.class);
+
+ // audio
+ namespace = com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants.NAMESPACE;
+ name = com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants.Directives.Play.NAME;
+ insertPayload(namespace, name, PlayPayload.class);
+
+ name = com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants.Directives.Stop.NAME;
+ insertPayload(namespace, name, StopPayload.class);
+
+ name = com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants.Directives.ClearQueue.NAME;
+ insertPayload(namespace, name, ClearQueuePayload.class);
+
+ // alert
+ namespace = com.baidu.duer.dcs.devicemodule.alerts.ApiConstants.NAMESPACE;
+ name = com.baidu.duer.dcs.devicemodule.alerts.ApiConstants.Directives.SetAlert.NAME;
+ insertPayload(namespace, name, SetAlertPayload.class);
+
+ name = com.baidu.duer.dcs.devicemodule.alerts.ApiConstants.Directives.DeleteAlert.NAME;
+ insertPayload(namespace, name, DeleteAlertPayload.class);
+
+ // SpeakController
+ namespace = com.baidu.duer.dcs.devicemodule.speakcontroller.ApiConstants.NAMESPACE;
+ name = com.baidu.duer.dcs.devicemodule.speakcontroller.ApiConstants.Directives.SetVolume.NAME;
+ insertPayload(namespace, name, SetVolumePayload.class);
+
+ name = com.baidu.duer.dcs.devicemodule.speakcontroller.ApiConstants.Directives.AdjustVolume.NAME;
+ insertPayload(namespace, name, AdjustVolumePayload.class);
+
+ name = com.baidu.duer.dcs.devicemodule.speakcontroller.ApiConstants.Directives.SetMute.NAME;
+ insertPayload(namespace, name, SetMutePayload.class);
+
+ // System
+ namespace = com.baidu.duer.dcs.devicemodule.system.ApiConstants.NAMESPACE;
+ name = com.baidu.duer.dcs.devicemodule.system.ApiConstants.Directives.SetEndpoint.NAME;
+ insertPayload(namespace, name, SetEndPointPayload.class);
+
+ name = com.baidu.duer.dcs.devicemodule.system.ApiConstants.Directives.ThrowException.NAME;
+ insertPayload(namespace, name, ThrowExceptionPayload.class);
+
+ // Screen
+ namespace = com.baidu.duer.dcs.devicemodule.screen.ApiConstants.NAMESPACE;
+ name = com.baidu.duer.dcs.devicemodule.screen.ApiConstants.Directives.HtmlView.NAME;
+ insertPayload(namespace, name, HtmlPayload.class);
+ }
+
+ void insertPayload(String namespace, String name, Class<?> type) {
+ final String key = namespace + name;
+ payloadClass.put(key, type);
+ }
+
+ Class<?> findPayloadClass(String namespace, String name) {
+ final String key = namespace + name;
+ return payloadClass.get(key);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/DcsHttpManager.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http;
+
+import com.baidu.duer.dcs.http.builder.GetBuilder;
+import com.baidu.duer.dcs.http.builder.PostMultipartBuilder;
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+import com.baidu.duer.dcs.http.intercepter.LoggingInterceptor;
+import com.baidu.duer.dcs.http.request.RequestCall;
+import com.baidu.duer.dcs.http.utils.Platform;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+import okhttp3.Response;
+
+/**
+ * 网络请求-单例
+ * <p>
+ * Created by zhangyan@baidu.com on 2017/5/15.
+ */
+public class DcsHttpManager {
+ // 默认时间,比如超时时间
+ public static final long DEFAULT_MILLISECONDS = 60 * 1000L;
+ private OkHttpClient mOkHttpClient;
+ private Platform mPlatform;
+
+ private static class DcsHttpManagerHolder {
+ private static final DcsHttpManager INSTANCE = new DcsHttpManager();
+ }
+
+ public static DcsHttpManager getInstance() {
+ return DcsHttpManagerHolder.INSTANCE;
+ }
+
+ private DcsHttpManager() {
+ if (mOkHttpClient == null) {
+ // http数据log,日志中打印出HTTP请求&响应数据
+ // HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
+ // 包含header、body数据
+ mOkHttpClient = new OkHttpClient.Builder()
+ .retryOnConnectionFailure(false)
+ .readTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
+ .writeTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
+ .connectTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
+ // .addInterceptor(new RetryInterceptor(3))
+ .addInterceptor(new LoggingInterceptor())
+ // .connectionPool(new ConnectionPool(0, 1, TimeUnit.NANOSECONDS))
+ .build();
+ }
+ mPlatform = Platform.get();
+ }
+
+ public OkHttpClient getOkHttpClient() {
+ return mOkHttpClient;
+ }
+
+ public static GetBuilder get() {
+ return new GetBuilder();
+ }
+
+ public static PostMultipartBuilder post() {
+ return new PostMultipartBuilder();
+ }
+
+ public void execute(final RequestCall requestCall, DcsCallback dcsCallback) {
+
+ if (dcsCallback == null) {
+ dcsCallback = DcsCallback.backDefaultCallBack;
+ }
+ final DcsCallback finalDCSCallback = dcsCallback;
+ final int id = requestCall.getOkHttpRequest().getId();
+
+ requestCall.getCall().enqueue(new okhttp3.Callback() {
+ @Override
+ public void onFailure(Call call, final IOException e) {
+ sendFailResultCallback(call, e, finalDCSCallback, id);
+ }
+
+ @Override
+ public void onResponse(final Call call, final Response response) {
+ try {
+ if (call.isCanceled()) {
+ sendFailResultCallback(call, new IOException("Canceled!"), finalDCSCallback, id);
+ return;
+ }
+ if (!finalDCSCallback.validateResponse(response, id)) {
+ IOException exception = new IOException("request failed , response's code is : "
+ + response.code());
+ sendFailResultCallback(call, exception, finalDCSCallback, id);
+ return;
+ }
+ sendSuccessResultCallback(response, finalDCSCallback, id);
+ Object o = finalDCSCallback.parseNetworkResponse(response, id);
+ } catch (Exception e) {
+ sendFailResultCallback(call, e, finalDCSCallback, id);
+ } finally {
+ if (response.body() != null) {
+ response.body().close();
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * 网络请求失败处理
+ *
+ * @param call okhttp的请求call
+ * @param e 异常信息
+ * @param dcsCallback 回调
+ * @param id 请求标识
+ */
+ private void sendFailResultCallback(final Call call,
+ final Exception e,
+ final DcsCallback dcsCallback,
+ final int id) {
+ if (dcsCallback == null) {
+ return;
+ }
+ mPlatform.execute(new Runnable() {
+ @Override
+ public void run() {
+ dcsCallback.onError(call, e, id);
+ dcsCallback.onAfter(id);
+ }
+ });
+ }
+
+ /**
+ * 网络请求成功处理
+ *
+ * @param object object 返回的对象
+ * @param dcsCallback dcsCallback 回调
+ * @param id id 请求标识
+ */
+ private void sendSuccessResultCallback(final Object object,
+ final DcsCallback dcsCallback,
+ final int id) {
+ if (dcsCallback == null) {
+ return;
+ }
+ mPlatform.execute(new Runnable() {
+ @Override
+ public void run() {
+ dcsCallback.onResponse(object, id);
+ dcsCallback.onAfter(id);
+ }
+ });
+ }
+
+ /**
+ * 取消请求
+ *
+ * @param tag 请求的时候设置的tag
+ */
+ public void cancelTag(Object tag) {
+ for (Call call : mOkHttpClient.dispatcher().queuedCalls()) {
+ if (tag.equals(call.request().tag())) {
+ call.cancel();
+ }
+ }
+ for (Call call : mOkHttpClient.dispatcher().runningCalls()) {
+ if (tag.equals(call.request().tag())) {
+ call.cancel();
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/HttpConfig.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http;
+
+import com.baidu.duer.dcs.util.CommonUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * HttpConfig
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/1.
+ */
+public class HttpConfig {
+ // 请求https
+ public static final String HTTP_PREFIX = "https://";
+ // 请求host
+ public static final String HOST = "dueros-h2.baidu.com";
+ public static String endpoint = null;
+ // 请求event事件
+ public static final String EVENTS = "/dcs/v1/events";
+ // 请求directives事件
+ public static final String DIRECTIVES = "/dcs/v1/directives";
+ // ping
+ public static final String PING = "/dcs/v1/ping";
+ // 请求event事件TAG
+ public static final String HTTP_EVENT_TAG = "event";
+ // 请求directives事件TAG
+ public static final String HTTP_DIRECTIVES_TAG = "directives";
+ // 请求ping的TAG
+ public static final String HTTP_PING_TAG = "ping";
+
+ public static String getEndpoint() {
+ if (null == endpoint || "".equals(endpoint)) {
+ endpoint = HTTP_PREFIX + HOST;
+ }
+ return endpoint;
+ }
+
+ public static void setEndpoint(String endpoint) {
+ HttpConfig.endpoint = endpoint;
+ }
+
+ public static String getEventsUrl() {
+ return getEndpoint() + EVENTS;
+ }
+
+ public static String getDirectivesUrl() {
+ return getEndpoint() + DIRECTIVES;
+ }
+
+ public static String getPingUrl() {
+ return getEndpoint() + PING;
+ }
+
+ public static class HttpHeaders {
+ public static final String CONTENT_TYPE = "Content-Type";
+ public static final String DUEROS_DEVICE_ID = "dueros-device-id";
+ public static final String AUTHORIZATION = "Authorization";
+ public static final String CONTENT_ID = "Content-ID";
+ public static final String BEARER = "Bearer ";
+ public static final String DEBUG = "debug";
+ public static final String DEBUG_PARAM = "0";
+ }
+
+ public static class ContentTypes {
+ public static final String JSON = "application/json";
+ public static final String FORM_MULTIPART = "multipart/form-data boundary=dumi-boundory";
+ public static final String APPLICATION_JSON = JSON + ";" + " charset=UTF-8";
+ public static final String APPLICATION_AUDIO = "application/octet-stream";
+ }
+
+ public static class Parameters {
+ public static final String BOUNDARY = "boundary";
+ public static final String DATA_METADATA = "metadata";
+ public static final String DATA_AUDIO = "audio";
+ }
+
+ public static String accessToken = "";
+
+ public static String getAccessToken() {
+ return accessToken;
+ }
+
+ public static void setAccessToken(String accessToken) {
+ HttpConfig.accessToken = accessToken;
+ }
+
+ /**
+ * 获取dcs的headers
+ *
+ * @return header集合
+ */
+ public static Map<String, String> getDCSHeaders() {
+ Map<String, String> headers = new HashMap<>();
+ headers.put(HttpConfig.HttpHeaders.AUTHORIZATION,
+ HttpConfig.HttpHeaders.BEARER + getAccessToken());
+ headers.put(HttpConfig.HttpHeaders.CONTENT_TYPE,
+ HttpConfig.ContentTypes.FORM_MULTIPART);
+ headers.put(HttpConfig.HttpHeaders.DUEROS_DEVICE_ID,
+ CommonUtil.getDeviceUniqueID());
+ headers.put(HttpConfig.HttpHeaders.DEBUG,
+ HttpConfig.HttpHeaders.DEBUG_PARAM);
+ return headers;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/HttpRequestInterface.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http;
+
+import com.baidu.duer.dcs.framework.message.DcsRequestBody;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+
+/**
+ * 网络请求工具接口
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/1.
+ */
+public interface HttpRequestInterface {
+ /**
+ * 异步Post EventString请求
+ *
+ * @param requestBody 请求信息体
+ * @param dcsCallback 结果回调接口
+ */
+ void doPostEventStringAsync(DcsRequestBody requestBody, DcsCallback dcsCallback);
+
+ /**
+ * 异步PostMultipart请求
+ *
+ * @param requestBody 请求信息体
+ * @param streamRequestBody 请求信息体stream
+ * @param dcsCallback 结果回调接口
+ */
+ void doPostEventMultipartAsync(DcsRequestBody requestBody,
+ DcsStreamRequestBody streamRequestBody,
+ DcsCallback dcsCallback);
+
+ /**
+ * 异步Get Directives请求
+ *
+ * @param requestBody 请求信息体
+ * @param dcsCallback 结果回调接口
+ */
+ void doGetDirectivesAsync(DcsRequestBody requestBody, DcsCallback dcsCallback);
+
+ /**
+ * 异步Get Ping请求
+ *
+ * @param requestBody 请求信息体
+ * @param dcsCallback 结果回调接口
+ */
+ void doGetPingAsync(DcsRequestBody requestBody, DcsCallback dcsCallback);
+
+ /**
+ * 取消请求
+ *
+ * @param requestTag 请求标识
+ */
+ void cancelRequest(Object requestTag);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/OkHttpMediaType.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http;
+
+import okhttp3.MediaType;
+
+import static com.baidu.duer.dcs.http.HttpConfig.ContentTypes.APPLICATION_AUDIO;
+import static com.baidu.duer.dcs.http.HttpConfig.ContentTypes.APPLICATION_JSON;
+
+/**
+ * okhttp media_type
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/1.
+ */
+public class OkHttpMediaType {
+ // json类型
+ public static final MediaType MEDIA_JSON_TYPE = MediaType.parse(APPLICATION_JSON);
+ // 数据流类型
+ public static final MediaType MEDIA_STREAM_TYPE = MediaType.parse(APPLICATION_AUDIO);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/OkHttpRequestImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http;
+
+import com.baidu.duer.dcs.framework.message.DcsRequestBody;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+import com.baidu.duer.dcs.util.LogUtil;
+import com.baidu.duer.dcs.util.ObjectMapperUtil;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import okhttp3.RequestBody;
+
+/**
+ * 请求实现
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public class OkHttpRequestImpl implements HttpRequestInterface {
+ private static final String TAG = "OkHttpRequestImpl";
+ private final DcsHttpManager dcsHttpManager;
+
+ public OkHttpRequestImpl() {
+ dcsHttpManager = DcsHttpManager.getInstance();
+ }
+
+ @Override
+ public void doPostEventStringAsync(DcsRequestBody requestBody, DcsCallback dcsCallback) {
+ String bodyJson = ObjectMapperUtil.instance().objectToJson(requestBody);
+ LogUtil.d(TAG, "doPostEventStringAsync-bodyJson:" + bodyJson);
+ Map<String, RequestBody> multiParts = new LinkedHashMap<>();
+ multiParts.put(HttpConfig.Parameters.DATA_METADATA,
+ RequestBody.create(OkHttpMediaType.MEDIA_JSON_TYPE, bodyJson));
+ DcsHttpManager.post()
+ .url(HttpConfig.getEventsUrl())
+ .headers(HttpConfig.getDCSHeaders())
+ .multiParts(multiParts)
+ .tag(HttpConfig.HTTP_EVENT_TAG)
+ .build()
+ .execute(dcsCallback);
+ }
+
+ @Override
+ public void doPostEventMultipartAsync(DcsRequestBody requestBody,
+ DcsStreamRequestBody streamRequestBody,
+ DcsCallback dcsCallback) {
+ String bodyJson = ObjectMapperUtil.instance().objectToJson(requestBody);
+ LogUtil.d(TAG, "doPostEventMultipartAsync-bodyJson:" + bodyJson);
+ Map<String, RequestBody> multiParts = new LinkedHashMap<>();
+ multiParts.put(HttpConfig.Parameters.DATA_METADATA,
+ RequestBody.create(OkHttpMediaType.MEDIA_JSON_TYPE, bodyJson));
+ multiParts.put(HttpConfig.Parameters.DATA_AUDIO, streamRequestBody);
+ DcsHttpManager.post()
+ .url(HttpConfig.getEventsUrl())
+ .headers(HttpConfig.getDCSHeaders())
+ .multiParts(multiParts)
+ .tag(HttpConfig.HTTP_EVENT_TAG)
+ .build()
+ .execute(dcsCallback);
+ }
+
+ @Override
+ public void doGetDirectivesAsync(DcsRequestBody requestBody, DcsCallback dcsCallback) {
+ LogUtil.d(TAG, "doGetDirectivesAsync");
+ final long time = 60 * 60 * 1000L;
+ DcsHttpManager.get()
+ .url(HttpConfig.getDirectivesUrl())
+ .headers(HttpConfig.getDCSHeaders())
+ .tag(HttpConfig.HTTP_DIRECTIVES_TAG)
+ .build()
+ .connTimeOut(time)
+ .readTimeOut(time)
+ .writeTimeOut(time)
+ .execute(dcsCallback);
+ }
+
+ @Override
+ public void doGetPingAsync(DcsRequestBody requestBody, DcsCallback dcsCallback) {
+ LogUtil.d(TAG, "doGetPingAsync");
+ DcsHttpManager.get()
+ .url(HttpConfig.getPingUrl())
+ .headers(HttpConfig.getDCSHeaders())
+ .tag(HttpConfig.HTTP_PING_TAG)
+ .build()
+ .execute(dcsCallback);
+ }
+
+ @Override
+ public void cancelRequest(Object requestTag) {
+ dcsHttpManager.cancelTag(requestTag);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/GetBuilder.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.builder;
+
+import android.net.Uri;
+
+import com.baidu.duer.dcs.http.request.GetRequest;
+import com.baidu.duer.dcs.http.request.RequestCall;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * get请求构建
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class GetBuilder extends OkHttpRequestBuilder<GetBuilder> implements HasParamInterface {
+ @Override
+ public RequestCall build() {
+ if (params != null) {
+ url = appendParams(url, params);
+ }
+ return new GetRequest(url, tag, params, headers, id).build();
+ }
+
+ /**
+ * 添加参数到url上
+ *
+ * @param url url 请求的url
+ * @param params params 参数集合
+ * @return url 拼接后的url
+ */
+ protected String appendParams(String url, Map<String, String> params) {
+ if (url == null || params == null || params.isEmpty()) {
+ return url;
+ }
+ Uri.Builder builder = Uri.parse(url).buildUpon();
+ Set<String> keys = params.keySet();
+ Iterator<String> iterator = keys.iterator();
+ while (iterator.hasNext()) {
+ String key = iterator.next();
+ builder.appendQueryParameter(key, params.get(key));
+ }
+ return builder.build().toString();
+ }
+
+
+ @Override
+ public GetBuilder params(Map<String, String> params) {
+ this.params = params;
+ return this;
+ }
+
+ @Override
+ public GetBuilder addParams(String key, String val) {
+ if (this.params == null) {
+ params = new LinkedHashMap<>();
+ }
+ params.put(key, val);
+ return this;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/HasParamInterface.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.builder;
+
+import java.util.Map;
+
+/**
+ * 请求是否包含参数
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public interface HasParamInterface {
+ /**
+ * 构建请求参数
+ *
+ * @param params 请求参数
+ * @return OkHttpRequestBuilder
+ */
+ OkHttpRequestBuilder params(Map<String, String> params);
+
+ /**
+ * @param key 请求参数的key
+ * @param val 请求参数的值
+ * @return OkHttpRequestBuilder
+ */
+ OkHttpRequestBuilder addParams(String key, String val);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/OkHttpRequestBuilder.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.builder;
+
+import com.baidu.duer.dcs.http.request.RequestCall;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * 请求构建基类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public abstract class OkHttpRequestBuilder<T extends OkHttpRequestBuilder> {
+ // 请求url
+ protected String url;
+ // 请求tag
+ protected Object tag;
+ // 请求的headers
+ protected Map<String, String> headers;
+ // 请求的参数集合
+ protected Map<String, String> params;
+ // 请求的表识id
+ protected int id;
+
+ public T id(int id) {
+ this.id = id;
+ return (T) this;
+ }
+
+ public T url(String url) {
+ this.url = url;
+ return (T) this;
+ }
+
+
+ public T tag(Object tag) {
+ this.tag = tag;
+ return (T) this;
+ }
+
+ public T headers(Map<String, String> headers) {
+ this.headers = headers;
+ return (T) this;
+ }
+
+ public T addHeader(String key, String val) {
+ if (this.headers == null) {
+ headers = new LinkedHashMap<>();
+ }
+ headers.put(key, val);
+ return (T) this;
+ }
+
+ /**
+ * 构建请求
+ *
+ * @return RequestCall
+ */
+ public abstract RequestCall build();
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/PostMultipartBuilder.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.builder;
+
+import com.baidu.duer.dcs.http.request.PostMultipartRequest;
+import com.baidu.duer.dcs.http.request.RequestCall;
+
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import okhttp3.RequestBody;
+
+/**
+ * post请求多part构建
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class PostMultipartBuilder extends OkHttpRequestBuilder<PostMultipartBuilder>
+ implements HasParamInterface {
+ private LinkedList<Multipart> multiParts = new LinkedList<>();
+
+ @Override
+ public RequestCall build() {
+ return new PostMultipartRequest(url, tag, params, headers, multiParts, id).build();
+ }
+
+ @Override
+ public PostMultipartBuilder params(Map<String, String> params) {
+ this.params = params;
+ return this;
+ }
+
+ @Override
+ public PostMultipartBuilder addParams(String key, String val) {
+ if (this.params == null) {
+ params = new LinkedHashMap<>();
+ }
+ params.put(key, val);
+ return this;
+ }
+
+ /**
+ * 添加多个Multipart
+ *
+ * @param map map集合
+ * @return 当前对象
+ */
+ public PostMultipartBuilder multiParts(Map<String, RequestBody> map) {
+ if (map != null) {
+ multiParts = new LinkedList<>();
+ }
+ for (String k : map.keySet()) {
+ this.multiParts.add(new Multipart(k, map.get(k)));
+ }
+ return this;
+ }
+
+ /**
+ * 添加一个Multipart
+ *
+ * @param name name
+ * @param body body
+ * @return 当前对象
+ */
+ public PostMultipartBuilder addMultiPart(String name, RequestBody body) {
+ multiParts.add(new Multipart(name, body));
+ return this;
+ }
+
+ /**
+ * 请求体body-Multipart
+ */
+ public static final class Multipart implements Serializable {
+ // body的key
+ public String key;
+ // body的内容
+ public RequestBody requestBody;
+
+ public Multipart(String name, RequestBody requestBody) {
+ this.key = name;
+ this.requestBody = requestBody;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/PostStringBuilder.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.builder;
+
+import com.baidu.duer.dcs.http.request.PostStringRequest;
+import com.baidu.duer.dcs.http.request.RequestCall;
+
+import okhttp3.MediaType;
+
+/**
+ * post请求的构建类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/16.
+ */
+public class PostStringBuilder extends OkHttpRequestBuilder<PostStringBuilder> {
+ // 内容
+ private String content;
+ // 类型
+ private MediaType mediaType;
+
+ public PostStringBuilder content(String content) {
+ this.content = content;
+ return this;
+ }
+
+ public PostStringBuilder mediaType(MediaType mediaType) {
+ this.mediaType = mediaType;
+ return this;
+ }
+
+ @Override
+ public RequestCall build() {
+ return new PostStringRequest(url, tag, params, headers, content, mediaType, id).build();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/DcsCallback.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.callback;
+
+import okhttp3.Call;
+import okhttp3.Request;
+import okhttp3.Response;
+
+/**
+ * 网络回调基类
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public abstract class DcsCallback<T> {
+ /**
+ * UI线程
+ *
+ * @param request 请求
+ * @param id 请求id
+ */
+ public void onBefore(Request request, int id) {
+ }
+
+ /**
+ * UI线程
+ *
+ * @param id 请求id
+ */
+ public void onAfter(int id) {
+ }
+
+ public static DcsCallback backDefaultCallBack = new DcsCallback() {
+
+ @Override
+ public Object parseNetworkResponse(Response response, int id) throws Exception {
+ return null;
+ }
+
+ @Override
+ public void onError(Call call, Exception e, int id) {
+
+ }
+
+ @Override
+ public void onResponse(Object response, int id) {
+
+ }
+ };
+
+ public boolean validateResponse(Response response, int id) {
+ return response.isSuccessful();
+ }
+
+ /**
+ * 非UI线程
+ *
+ * @param response response
+ */
+ public abstract T parseNetworkResponse(Response response, int id) throws Exception;
+
+ /**
+ * 错误处理,UI线程
+ *
+ * @param call call
+ * @param e e 错误异常信息
+ * @param id id 请求id
+ */
+ public abstract void onError(Call call, Exception e, int id);
+
+ /**
+ * 数据回调,UI线程
+ *
+ * @param response response
+ * @param id id
+ */
+ public abstract void onResponse(T response, int id);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/ResponseCallback.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.callback;
+
+import com.baidu.duer.dcs.util.LogUtil;
+
+import okhttp3.Call;
+import okhttp3.Response;
+
+/**
+ * framework 返回数据类
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public class ResponseCallback extends DcsCallback<Response> {
+ private static final String TAG = "ResponseCallback";
+
+ @Override
+ public Response parseNetworkResponse(Response response, int id) throws Exception {
+ return response;
+ }
+
+ @Override
+ public void onError(Call call, Exception e, int id) {
+ LogUtil.d(TAG, "onError:" + e.getMessage());
+ }
+
+ @Override
+ public void onResponse(Response response, int id) {
+ LogUtil.d(TAG, "onResponse:" + response.code());
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/StreamDcsCallback.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.callback;
+
+import java.io.InputStream;
+
+import okhttp3.Response;
+
+/**
+ * 数据流回调
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public abstract class StreamDcsCallback extends DcsCallback<InputStream> {
+ @Override
+ public InputStream parseNetworkResponse(Response response, int id) throws Exception {
+ return response.body().byteStream();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/StringDcsCallback.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.callback;
+
+import okhttp3.Response;
+
+/**
+ * String类型回调
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public abstract class StringDcsCallback extends DcsCallback<String> {
+ @Override
+ public String parseNetworkResponse(Response response, int id) throws Exception {
+ return response.body().string();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/exceptions/Exceptions.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.exceptions;
+
+/**
+ * 网络模块的异常处理,比如参数检查
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class Exceptions {
+ public static void illegalArgument(String msg, Object... params) {
+ throw new IllegalArgumentException(String.format(msg, params));
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/intercepter/LoggingInterceptor.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.intercepter;
+
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+/**
+ * http Interceptor 拦截打印http-log
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/25.
+ */
+public class LoggingInterceptor implements Interceptor {
+ private static final String TAG = "HttpLog";
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ Request request = chain.request();
+ long t1 = System.nanoTime();
+ LogUtil.d(TAG, String.format("request: %s [%s] %s%n%s",
+ request.method(), request.url(), chain.connection(), request.headers()));
+
+ Response response = chain.proceed(request);
+ long t2 = System.nanoTime();
+ LogUtil.d(TAG, String.format(Locale.CANADA, "response: %d [%s] %.1fms%n%s",
+ response.code(), response.request().url(), (t2 - t1) / 1e6d, response.headers()));
+ return response;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/intercepter/RetryInterceptor.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.intercepter;
+
+import java.io.IOException;
+
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+/**
+ * 重试拦截器
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/20.
+ */
+public class RetryInterceptor implements Interceptor {
+ // 最大重试次数,假如设置为3次重试的话,则最大可能请求4次(默认1次+3次重试)
+ private int maxRetry;
+ private int retryNum = 0;
+
+ public RetryInterceptor(int maxRetry) {
+ this.maxRetry = maxRetry;
+ }
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ Request request = chain.request();
+ Response response = chain.proceed(request);
+ while (!response.isSuccessful() && retryNum < maxRetry) {
+ retryNum++;
+ response = chain.proceed(request);
+ }
+ return response;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/GetRequest.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.request;
+
+import java.util.Map;
+
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * 普通GetRequest
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class GetRequest extends OkHttpRequest {
+ public GetRequest(String url,
+ Object tag,
+ Map<String, String> params,
+ Map<String, String> headers,
+ int id) {
+ super(url, tag, params, headers, id);
+ }
+
+ @Override
+ protected RequestBody buildRequestBody() {
+ return null;
+ }
+
+ @Override
+ protected Request buildRequest(RequestBody requestBody) {
+ return builder.get().build();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/OkHttpRequest.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.request;
+
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+import com.baidu.duer.dcs.http.exceptions.Exceptions;
+
+import java.util.Map;
+
+import okhttp3.Headers;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * 请求基类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public abstract class OkHttpRequest {
+ // url
+ protected String url;
+ // 用于取消请求的tag
+ protected Object tag;
+ // 请求参数
+ protected Map<String, String> params;
+ // 请求header
+ protected Map<String, String> headers;
+ // 请求的标识id
+ protected int id;
+ // okhttp的请求构建类
+ protected Request.Builder builder = new Request.Builder();
+
+ protected OkHttpRequest(String url, Object tag,
+ Map<String, String> params,
+ Map<String, String> headers,
+ int id) {
+ this.url = url;
+ this.tag = tag;
+ this.params = params;
+ this.headers = headers;
+ this.id = id;
+ if (url == null) {
+ Exceptions.illegalArgument("url can not be null.");
+ }
+ initBuilder();
+ }
+
+ /**
+ * 初始化okhttp的请求builder
+ */
+ private void initBuilder() {
+ builder.url(url).tag(tag);
+ appendHeaders();
+ }
+
+ /**
+ * 拼接请求的Header
+ */
+ protected void appendHeaders() {
+ Headers.Builder headerBuilder = new Headers.Builder();
+ if (headers == null || headers.isEmpty()) {
+ return;
+ }
+ for (String key : headers.keySet()) {
+ headerBuilder.add(key, headers.get(key));
+ }
+ builder.headers(headerBuilder.build());
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public RequestCall build() {
+ return new RequestCall(this);
+ }
+
+ public Request generateRequest(DcsCallback dcsCallback) {
+ RequestBody requestBody = buildRequestBody();
+ RequestBody wrappedRequestBody = wrapRequestBody(requestBody, dcsCallback);
+ Request request = buildRequest(wrappedRequestBody);
+ return request;
+ }
+
+ protected RequestBody wrapRequestBody(RequestBody requestBody, final DcsCallback dcsCallback) {
+ return requestBody;
+ }
+
+ protected abstract RequestBody buildRequestBody();
+
+ protected abstract Request buildRequest(RequestBody requestBody);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/PostMultipartRequest.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.request;
+
+import com.baidu.duer.dcs.http.builder.PostMultipartBuilder;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import okhttp3.Headers;
+import okhttp3.MultipartBody;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * 用于post multipart请求
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class PostMultipartRequest extends OkHttpRequest {
+ private List<PostMultipartBuilder.Multipart> multiParts;
+
+ public PostMultipartRequest(String url,
+ Object tag,
+ Map<String, String> params,
+ Map<String, String> headers,
+ LinkedList<PostMultipartBuilder.Multipart> multiParts,
+ int id) {
+ super(url, tag, params, headers, id);
+ this.multiParts = multiParts;
+ }
+
+ @Override
+ protected RequestBody buildRequestBody() {
+ MultipartBody.Builder builder = new MultipartBody.Builder()
+ .setType(MultipartBody.FORM);
+ addParams(builder);
+ return builder.build();
+ }
+
+ @Override
+ protected Request buildRequest(RequestBody requestBody) {
+ return builder.post(requestBody).build();
+ }
+
+ private void addParams(MultipartBody.Builder builder) {
+ if (multiParts != null && !multiParts.isEmpty()) {
+ for (int i = 0; i < multiParts.size(); i++) {
+ PostMultipartBuilder.Multipart part = multiParts.get(i);
+ builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + part.key + "\""),
+ part.requestBody);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/PostStringRequest.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.request;
+
+import com.baidu.duer.dcs.http.exceptions.Exceptions;
+
+import java.util.Map;
+
+import okhttp3.MediaType;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * 用于发送字符串请求
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/16.
+ */
+public class PostStringRequest extends OkHttpRequest {
+ private static MediaType MEDIA_TYPE_PLAIN = MediaType.parse("text/plain;charset=utf-8");
+ private String content;
+ private MediaType mediaType;
+
+ public PostStringRequest(String url,
+ Object tag,
+ Map<String, String> params,
+ Map<String, String> headers,
+ String content,
+ MediaType mediaType,
+ int id) {
+ super(url, tag, params, headers, id);
+ this.content = content;
+ this.mediaType = mediaType;
+ if (this.content == null) {
+ Exceptions.illegalArgument("the content can not be null !");
+ }
+ if (this.mediaType == null) {
+ this.mediaType = MEDIA_TYPE_PLAIN;
+ }
+ }
+
+ @Override
+ protected RequestBody buildRequestBody() {
+ return RequestBody.create(mediaType, content);
+ }
+
+ @Override
+ protected Request buildRequest(RequestBody requestBody) {
+ return builder.post(requestBody).build();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/RequestCall.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.request;
+
+import com.baidu.duer.dcs.http.DcsHttpManager;
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+
+/**
+ * 请求设置
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class RequestCall {
+ private OkHttpRequest okHttpRequest;
+ private Request request;
+ private Call call;
+ private OkHttpClient clone;
+ // 读取超时时间
+ private long readTimeOut;
+ // 写入数据超时时间
+ private long writeTimeOut;
+ // 连接超时时间
+ private long connTimeOut;
+
+ public RequestCall(OkHttpRequest request) {
+ this.okHttpRequest = request;
+ }
+
+ public RequestCall readTimeOut(long readTimeOut) {
+ this.readTimeOut = readTimeOut;
+ return this;
+ }
+
+ public RequestCall writeTimeOut(long writeTimeOut) {
+ this.writeTimeOut = writeTimeOut;
+ return this;
+ }
+
+ public RequestCall connTimeOut(long connTimeOut) {
+ this.connTimeOut = connTimeOut;
+ return this;
+ }
+
+ /**
+ * 构建请求
+ *
+ * @param dcsCallback 回调
+ * @return Call
+ */
+ public Call buildCall(DcsCallback dcsCallback) {
+ request = generateRequest(dcsCallback);
+ if (readTimeOut > 0 || writeTimeOut > 0 || connTimeOut > 0) {
+ readTimeOut = readTimeOut > 0 ? readTimeOut : DcsHttpManager.DEFAULT_MILLISECONDS;
+ writeTimeOut = writeTimeOut > 0 ? writeTimeOut : DcsHttpManager.DEFAULT_MILLISECONDS;
+ connTimeOut = connTimeOut > 0 ? connTimeOut : DcsHttpManager.DEFAULT_MILLISECONDS;
+ clone = DcsHttpManager.getInstance().getOkHttpClient().newBuilder()
+ .readTimeout(readTimeOut, TimeUnit.MILLISECONDS)
+ .writeTimeout(writeTimeOut, TimeUnit.MILLISECONDS)
+ .connectTimeout(connTimeOut, TimeUnit.MILLISECONDS)
+ .build();
+
+ call = clone.newCall(request);
+ } else {
+ call = DcsHttpManager.getInstance().getOkHttpClient().newCall(request);
+ }
+ return call;
+ }
+
+ private Request generateRequest(DcsCallback dcsCallback) {
+ return okHttpRequest.generateRequest(dcsCallback);
+ }
+
+ public void execute(DcsCallback dcsCallback) {
+ buildCall(dcsCallback);
+ if (dcsCallback != null) {
+ dcsCallback.onBefore(request, getOkHttpRequest().getId());
+ }
+ DcsHttpManager.getInstance().execute(this, dcsCallback);
+ }
+
+ public OkHttpRequest getOkHttpRequest() {
+ return okHttpRequest;
+ }
+
+ public Call getCall() {
+ return call;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/utils/Platform.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.http.utils;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * 请求回调处理类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class Platform {
+ private static final Platform PLATFORM = findPlatform();
+
+ public static Platform get() {
+ return PLATFORM;
+ }
+
+ private static Platform findPlatform() {
+ return new Android();
+ }
+
+ public Executor defaultCallbackExecutor() {
+ return Executors.newCachedThreadPool();
+ }
+
+ public void execute(Runnable runnable) {
+ defaultCallbackExecutor().execute(runnable);
+ }
+
+ /**
+ * android 平台下用于回调到UI线程的辅助类
+ */
+ private static final class Android extends Platform {
+ @Override
+ public Executor defaultCallbackExecutor() {
+ return new MainThreadExecutor();
+ }
+
+ static class MainThreadExecutor implements Executor {
+ private final Handler handler = new Handler(Looper.getMainLooper());
+
+ @Override
+ public void execute(Runnable r) {
+ handler.post(r);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/AccessTokenManager.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import static com.baidu.duer.dcs.oauth.api.OauthPreferenceUtil.BAIDU_OAUTH_CONFIG;
+
+/**
+ * 对Token相关信息的管理类,包括初始化、存储、清除相应的token信息
+ * 由于AccessTokenManager涉及到在多个Activity中传递的,所以实现了Parcelable接口
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class AccessTokenManager implements Parcelable {
+ // accessToken信息
+ private String accessToken;
+ // token过期时间
+ private long expireTime = 0;
+ // 当前的上下文环境
+ private Context context;
+
+ /**
+ * 构建AccessTokenManager类
+ *
+ * @param context 当前的上下文环境,通常为××Activity.this等
+ */
+ public AccessTokenManager(Context context) {
+ this.context = context;
+ compareWithConfig();
+ }
+
+ /**
+ * 通过Parcel流构建AccessTokenManager,主要用在Parcelable.Creator中
+ *
+ * @param source Parcel 流信息
+ */
+ public AccessTokenManager(Parcel source) {
+ Bundle bundle = Bundle.CREATOR.createFromParcel(source);
+ if (bundle != null) {
+ this.accessToken = bundle.getString(OauthConfig.BundleKey.KEY_ACCESS_TOKEN);
+ this.expireTime = bundle.getLong(OauthConfig.BundleKey.KEY_EXPIRE_TIME);
+ }
+ compareWithConfig();
+ }
+
+ /**
+ * 检查当token信息与配置文件是否保持一致,若不一致则对当前的token信息进行初始化
+ */
+ private void compareWithConfig() {
+ if (this.context == null) {
+ return;
+ }
+
+ /**
+ * 对配置的权限信息进行监控,保持多个AccessTokenManager对象之间的,权限信息一致。
+ */
+ final SharedPreferences sp = this.context.getSharedPreferences(BAIDU_OAUTH_CONFIG, Context.MODE_PRIVATE);
+ sp.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ String acToken = sp.getString(OauthConfig.PrefenenceKey.SP_ACCESS_TOKEN, null);
+ if (accessToken != null && !accessToken.equals(acToken)) {
+ initToken();
+ }
+ }
+ });
+ }
+
+ /**
+ * 从SharedPreference中读取token数据,并初步判断数据的有效性
+ */
+ protected void initToken() {
+ this.accessToken = OauthPreferenceUtil.getAccessToken(context);
+ long expires = OauthPreferenceUtil.getExpires(context);
+ long createTime = OauthPreferenceUtil.getCreateTime(context);
+ long current = System.currentTimeMillis();
+ this.expireTime = createTime + expires;
+ if (expireTime != 0 && expireTime < current) {
+ clearToken();
+ }
+ }
+
+ /**
+ * 清楚SharedPreference中的所有数据
+ */
+ protected void clearToken() {
+ OauthPreferenceUtil.clearAllOauth(context);
+ this.accessToken = null;
+ this.expireTime = 0;
+ }
+
+ /**
+ * 将token信息存储到SharedPreference中
+ *
+ * @param values token信息的key-value形式
+ */
+ protected void storeToken(Bundle values) {
+ if (values == null || values.isEmpty()) {
+ return;
+ }
+ this.accessToken = values.getString("access_token");
+ // expires_in 返回值为秒
+ long expiresIn = Long.parseLong(values.getString("expires_in")) * 1000;
+ this.expireTime = System.currentTimeMillis() + expiresIn;
+ OauthPreferenceUtil.setAccessToken(context, this.accessToken);
+ OauthPreferenceUtil.setCreateTime(context, System.currentTimeMillis());
+ OauthPreferenceUtil.setExpires(context, expiresIn);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ Bundle bundle = new Bundle();
+ if (this.accessToken != null) {
+ bundle.putString(OauthConfig.BundleKey.KEY_ACCESS_TOKEN, this.accessToken);
+ }
+ if (this.expireTime != 0) {
+ bundle.putLong(OauthConfig.BundleKey.KEY_EXPIRE_TIME, this.expireTime);
+ }
+ bundle.writeToParcel(dest, flags);
+ }
+
+ public static final Creator<AccessTokenManager> CREATOR = new Creator<AccessTokenManager>() {
+ @Override
+ public AccessTokenManager createFromParcel(Parcel source) {
+ return new AccessTokenManager(source);
+ }
+
+ @Override
+ public AccessTokenManager[] newArray(int size) {
+ return new AccessTokenManager[size];
+ }
+
+ };
+
+ /**
+ * 判断当前的token信息是否有效
+ *
+ * @return true/false
+ */
+ protected boolean isSessionValid() {
+ if (this.accessToken == null || this.expireTime == 0) {
+ initToken();
+ }
+ return this.accessToken != null && this.expireTime != 0 && System.currentTimeMillis() < this.expireTime;
+ }
+
+ /**
+ * 获取AccessToken信息
+ *
+ * @return accessToken
+ */
+ public String getAccessToken() {
+ if (this.accessToken == null) {
+ initToken();
+ }
+ return this.accessToken;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduDialog.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.FrameLayout;
+import android.widget.RelativeLayout;
+
+import com.baidu.duer.dcs.androidsystemimpl.webview.BaseWebView;
+import com.baidu.duer.dcs.util.LogUtil;
+
+/**
+ * 自定义的Dialog UI类,用来展示WebView界面,即用户登录和授权的页面
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class BaiduDialog extends Dialog {
+ private static final FrameLayout.LayoutParams MATCH = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ private static final String LOG_TAG = "BaiduDialog";
+ private final String mUrl;
+ private final BaiduDialogListener mListener;
+ private ProgressDialog mSpinner;
+ private BaseWebView mWebView;
+ private FrameLayout mContent;
+ private RelativeLayout webViewContainer;
+
+ /**
+ * 构造BaiduDialog
+ *
+ * @param context 展示Dialog UI的上下文环境,通常是XXActivity.this
+ * @param url 用户请求的url地址
+ * @param listener 用于对请求回调的Listener对象
+ */
+ public BaiduDialog(Context context, String url, BaiduDialogListener listener) {
+ super(context, android.R.style.Theme_Translucent_NoTitleBar);
+ mUrl = url;
+ mListener = listener;
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ mListener.onCancel();
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // 设置ProgressDialog的样式
+ mSpinner = new ProgressDialog(getContext());
+ mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ mSpinner.setMessage("登录中...");
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ mContent = new FrameLayout(getContext());
+ setUpWebView();
+ addContentView(mContent, MATCH);
+ }
+
+ private void setUpWebView() {
+ webViewContainer = new RelativeLayout(getContext());
+ mWebView = new BaseWebView(getContext().getApplicationContext());
+ mWebView.setWebViewClient(new BdWebViewClient());
+ mWebView.loadUrl(mUrl);
+ mWebView.setLayoutParams(MATCH);
+ mWebView.setVisibility(View.INVISIBLE);
+ webViewContainer.addView(mWebView);
+ mContent.addView(webViewContainer, MATCH);
+ }
+
+ private class BdWebViewClient extends WebViewClient {
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ LogUtil.d(LOG_TAG, "Redirect URL: " + url);
+ /*
+ * 如果url的地址为bdconnect://success,即使用User-Agent方式获取用户授权的redirct
+ * url,则截取url中返回的各种token参数,
+ * 如果出错,则通过listener的相应处理方式回调
+ */
+ if (url.startsWith(BaiduOauthImplicitGrant.SUCCESS_URI)) {
+ Bundle values = OauthNetUtil.parseUrl(url);
+ if (values != null && !values.isEmpty()) {
+ String error = values.getString("error");
+ // 用户取消授权返回error=access_denied
+ if ("access_denied".equals(error)) {
+ mListener.onCancel();
+ BaiduDialog.this.dismiss();
+ return true;
+ }
+ // 请求出错时返回error=1100&errorDesp=error_desp
+ String errorDesp = values.getString("error_description");
+ if (error != null && errorDesp != null) {
+ mListener.onBaiduException(new BaiduException(error, errorDesp));
+ BaiduDialog.this.dismiss();
+ return true;
+ }
+ mListener.onComplete(values);
+ BaiduDialog.this.dismiss();
+ return true;
+ }
+ } else if (url.startsWith(BaiduOauthImplicitGrant.CANCEL_URI)) {
+ mListener.onCancel();
+ BaiduDialog.this.dismiss();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onReceivedError(WebView view, int errorCode, String description,
+ String failingUrl) {
+ super.onReceivedError(view, errorCode, description, failingUrl);
+ mListener.onError(new BaiduDialogError(description, errorCode, failingUrl));
+ BaiduDialog.this.dismiss();
+ }
+
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ LogUtil.d(LOG_TAG, "Webview loading URL: " + url);
+ super.onPageStarted(view, url, favicon);
+ mSpinner.show();
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ super.onPageFinished(view, url);
+ mSpinner.dismiss();
+ mContent.setBackgroundColor(Color.TRANSPARENT);
+ mWebView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void dismiss() {
+ super.dismiss();
+ webViewContainer.removeView(mWebView);
+ mWebView.removeAllViews();
+ mWebView.destroy();
+ }
+
+ /**
+ * 用于BaiduDialog回调接口
+ */
+ public interface BaiduDialogListener {
+ /**
+ * BaiduDailog请求成功时,执行该法方法,实现逻辑包括存储value信息,跳转activity的过程
+ *
+ * @param values token信息的key-value存储
+ */
+ void onComplete(Bundle values);
+
+ /**
+ * 当BaiduDialog执行发生BaiduException时执行的方法。
+ *
+ * @param e BaiduException信息
+ */
+ void onBaiduException(BaiduException e);
+
+ /**
+ * 发生DialogError时执行的方法
+ *
+ * @param e BaiduDialogError异常类
+ */
+ void onError(BaiduDialogError e);
+
+ /**
+ * 当BaiduDialog执行取消操作时,执行该方法
+ */
+ void onCancel();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduDialogError.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+/**
+ * 封装Dialog UI的错误异常信息类
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class BaiduDialogError extends Exception {
+ private static final long serialVersionUID = 1529106452635370329L;
+ private int errorCode;
+ private String failingUrl;
+
+ public BaiduDialogError(String message, int errorCode, String failingUrl) {
+ super(message);
+ this.errorCode = errorCode;
+ this.failingUrl = failingUrl;
+ }
+
+ public int getErrorCode() {
+ return errorCode;
+ }
+
+ public String getFailingUrl() {
+ return failingUrl;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduException.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+/**
+ * 封装了oauth授权和api请求的异常信息
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class BaiduException extends Exception {
+ private static final long serialVersionUID = -8309515227501598366L;
+ private String errorCode;
+ private String errorMsg;
+
+ public BaiduException() {
+ super();
+ }
+
+ public BaiduException(String detailMessage, Throwable throwable) {
+ super(detailMessage, throwable);
+ }
+
+ public BaiduException(String detailMessage) {
+ super(detailMessage);
+ }
+
+ public BaiduException(Throwable throwable) {
+ super(throwable);
+ }
+
+ public BaiduException(String errorCode, String errorDesp) {
+ this.errorCode = errorCode;
+ this.errorMsg = errorDesp;
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ public void setErrorCode(String errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ public String getErrorDesp() {
+ return errorMsg;
+ }
+
+ public void setErrorDesp(String errorDesp) {
+ this.errorMsg = errorDesp;
+ }
+
+ @Override
+ public String toString() {
+ return "BaiduException [errorCode=" + errorCode + ", errorDesp=" + errorMsg + "]";
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduOauthImplicitGrant.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+import android.webkit.CookieSyncManager;
+
+import com.baidu.duer.dcs.oauth.api.BaiduDialog.BaiduDialogListener;
+import com.baidu.duer.dcs.util.CommonUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+
+/**
+ * 封装了oauth2授权,我们采用的是百度Oauth的implicit grant的方式
+ * 该方式的地址:http://developer.baidu.com/wiki/index.php?title=docs/oauth/implicit
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ * TODO: 百度Oauth2授权方式完善
+ */
+public class BaiduOauthImplicitGrant implements Parcelable {
+ private static final String LOG_TAG = "BaiduOauth";
+ public static final String CANCEL_URI = "bdconnect://cancel";
+ // 百度Oauth授权回调需要在DUEROS开放平台的控制平台
+ // 应用编辑-->>OAUTH CONFIG URL的链接地址-->>授权回调页-->>安全设置-->>授权回调页
+ // 需要注意
+ public static final String SUCCESS_URI = "bdconnect://success";
+ private static final String OAUTHORIZE_URL = "https://openapi.baidu.com/oauth/2.0/authorize";
+ private static final String DISPLAY_STRING = "mobile";
+ private static final String[] DEFAULT_PERMISSIONS = {"basic"};
+ private static final String KEY_CLIENT_ID = "clientId";
+ // 应用注册的api key信息
+ private String cliendId;
+ private AccessTokenManager accessTokenManager;
+
+ /**
+ * 使用应用的基本信息构建Baidu对象
+ *
+ * @param clientId 应用注册的api key信息
+ * @param context 当前应用的上下文环境
+ */
+ public BaiduOauthImplicitGrant(String clientId, Context context) {
+ if (clientId == null) {
+ throw new IllegalArgumentException("apiKey信息必须提供!");
+ }
+ this.cliendId = clientId;
+ init(context);
+ }
+
+ /**
+ * 使用Parcel流构建Baidu对象
+ *
+ * @param in Parcel流信息
+ */
+ public BaiduOauthImplicitGrant(Parcel in) {
+ Bundle bundle = Bundle.CREATOR.createFromParcel(in);
+ this.cliendId = bundle.getString(KEY_CLIENT_ID);
+ this.accessTokenManager = AccessTokenManager.CREATOR.createFromParcel(in);
+ }
+
+ /**
+ * 初始化accesTokenManager等信息
+ *
+ * @param context 当前执行的上下文环境
+ */
+ public void init(Context context) {
+ if (context.checkCallingOrSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.w(LOG_TAG, "App miss permission android.permission.ACCESS_NETWORK_STATE! "
+ + "Some mobile's WebView don't display page!");
+ }
+ this.accessTokenManager = new AccessTokenManager(context);
+ this.accessTokenManager.initToken();
+ }
+
+ /**
+ * 完成登录并获取token信息(User-Agent Flow),该方法使用默认的用户权限
+ *
+ * @param activity 需要展示Dialog UI的Activity
+ * @param isForceLogin 是否强制登录,如果该参数为true的话,会强制用户进行登录。
+ * @param isConfirmLogin 是否确认登录,如果该参数为true的话,如果用户当前为登录状态,
+ * 则会显示用户的登录头像,点击头像后完成登录操作
+ * @param listener Dialog回调接口如Activity跳转
+ */
+ public void authorize(Activity activity,
+ boolean isForceLogin,
+ boolean isConfirmLogin,
+ final BaiduDialogListener listener) {
+ this.authorize(activity, null, isForceLogin, isConfirmLogin, listener);
+ }
+
+ /**
+ * 根据相应的permissions信息,完成登录并获取token信息(User-Agent Flow)
+ *
+ * @param activity 需要展示Dialog UI的Activity
+ * @param permissions 需要获得的授权权限信息
+ * @param isForceLogin 是否强制登录,如果该参数为true的话,会强制用户进行登录。
+ * @param listener 回调的listener接口,如Activity跳转等
+ */
+ private void authorize(Activity activity,
+ String[] permissions,
+ boolean isForceLogin,
+ boolean isConfirmLogin,
+ final BaiduDialogListener listener) {
+ if (this.isSessionValid()) {
+ listener.onComplete(new Bundle());
+ return;
+ }
+
+ // 使用匿名的BaiduDialogListener对listener进行了包装,并进行一些存储token信息和当前登录用户的逻辑,
+ // 外部传进来的listener信息不需要在进行存储相关的逻辑
+ this.authorize(activity,
+ permissions,
+ isForceLogin,
+ isConfirmLogin,
+ new BaiduDialogListener() {
+ @Override
+ public void onError(BaiduDialogError e) {
+ LogUtil.d(LOG_TAG, "DialogError " + e);
+ listener.onError(e);
+ }
+
+ @Override
+ public void onComplete(Bundle values) {
+ // 存储相应的token信息
+ getAccessTokenManager().storeToken(values);
+ // 完成授权操作,使用listener进行回调,eg。跳转到其他的activity
+ listener.onComplete(values);
+ }
+
+ @Override
+ public void onCancel() {
+ LogUtil.d(LOG_TAG, "login cancel");
+ listener.onCancel();
+ }
+
+ @Override
+ public void onBaiduException(BaiduException e) {
+ Log.d(LOG_TAG, "BaiduException : " + e);
+ listener.onBaiduException(e);
+ }
+ }, SUCCESS_URI, "token");
+ }
+
+ /**
+ * 通过Dialog UI展示用户登录、授权页
+ *
+ * @param activity 需要展示Dialog UI的Activity
+ * @param permissions 需要请求的环境
+ * @param listener 用于回调的listener接口方法
+ * @param redirectUrl 回调地址
+ * @param responseType 授权请求的类型
+ */
+ private void authorize(Activity activity,
+ String[] permissions,
+ boolean isForceLogin,
+ boolean isConfirmLogin,
+ final BaiduDialogListener listener,
+ String redirectUrl, String responseType) {
+ CookieSyncManager.createInstance(activity);
+ Bundle params = new Bundle();
+ params.putString("client_id", this.cliendId);
+ params.putString("redirect_uri", redirectUrl);
+ params.putString("response_type", responseType);
+ params.putString("display", DISPLAY_STRING);
+ if (isForceLogin) {
+ params.putString("force_login", "1");
+ }
+ if (isConfirmLogin) {
+ params.putString("confirm_login", "1");
+ }
+ if (permissions == null) {
+ permissions = DEFAULT_PERMISSIONS;
+ }
+ if (permissions != null && permissions.length > 0) {
+ String scope = TextUtils.join(" ", permissions);
+ params.putString("scope", scope);
+ }
+ String url = OAUTHORIZE_URL + "?" + CommonUtil.encodeUrl(params);
+ LogUtil.d(LOG_TAG, "url:" + url);
+ if (activity.checkCallingOrSelfPermission(Manifest.permission.INTERNET)
+ != PackageManager.PERMISSION_GRANTED) {
+ CommonUtil.showAlert(activity, "没有权限", "应用需要访问互联网的权限");
+ } else {
+ new BaiduDialog(activity, url, listener).show();
+ }
+ }
+
+ /**
+ * 将清除存储的token信息
+ */
+ public void clearAccessToken() {
+ if (this.accessTokenManager != null) {
+ this.accessTokenManager.clearToken();
+ this.accessTokenManager = null;
+ }
+ }
+
+ /**
+ * 判断token信息是否有效。
+ *
+ * @return boolean true/false
+ */
+ public boolean isSessionValid() {
+ return this.accessTokenManager.isSessionValid();
+ }
+
+ /**
+ * 获取AccessTokenManager对象
+ *
+ * @return accessTokenManager对象
+ */
+ public AccessTokenManager getAccessTokenManager() {
+ return this.accessTokenManager;
+ }
+
+ /**
+ * 获取AccessToken信息
+ *
+ * @return accessToken信息
+ */
+ public String getAccessToken() {
+ return this.accessTokenManager.getAccessToken();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.os.Parcelable#describeContents()
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ Bundle bundle = new Bundle();
+ bundle.putString(KEY_CLIENT_ID, this.cliendId);
+ bundle.writeToParcel(dest, flags);
+ this.accessTokenManager.writeToParcel(dest, flags);
+ }
+
+ public static final Creator<BaiduOauthImplicitGrant> CREATOR = new Creator<BaiduOauthImplicitGrant>() {
+ public BaiduOauthImplicitGrant createFromParcel(Parcel in) {
+ return new BaiduOauthImplicitGrant(in);
+ }
+
+ public BaiduOauthImplicitGrant[] newArray(int size) {
+ return new BaiduOauthImplicitGrant[size];
+ }
+ };
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/IOauth.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+/**
+ * 百度认证接口
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/8.
+ */
+public interface IOauth {
+ /**
+ * 获取accessToken
+ *
+ * @return String
+ */
+ String getAccessToken();
+
+ /**
+ * 用户认证
+ */
+ void authorize();
+
+ /**
+ * 判断当前的token信息是否有效
+ *
+ * @return true/false
+ */
+ boolean isSessionValid();
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthConfig.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+/**
+ * OauthConfig
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/3.
+ */
+public class OauthConfig {
+ public static class BundleKey {
+ // 在多个Activity中传递AccessTokenManager的键值
+ public static final String KEY_ACCESS_TOKEN = "baidu_token_manager_access_token";
+ public static final String KEY_EXPIRE_TIME = "baidu_token_manager_expire_time";
+ }
+
+ public static class PrefenenceKey {
+ // 持久化token信息的各种监制
+ public static final String SP_ACCESS_TOKEN = "baidu_oauth_config_prop_access_token";
+ public static final String SP_CREATE_TIME = "baidu_oauth_config_prop_create_time";
+ public static final String SP_EXPIRE_SECONDS = "baidu_oauth_config_prop_expire_secends";
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthImpl.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+import android.content.Intent;
+import android.text.TextUtils;
+
+import com.baidu.duer.dcs.androidapp.DcsSampleApplication;
+import com.baidu.duer.dcs.androidapp.DcsSampleOAuthActivity;
+
+/**
+ * 用户认证接口
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/8.
+ */
+public class OauthImpl implements IOauth {
+ @Override
+ public String getAccessToken() {
+ return OauthPreferenceUtil.getAccessToken(DcsSampleApplication.getInstance());
+ }
+
+ @Override
+ public void authorize() {
+ Intent intent = new Intent(DcsSampleApplication.getInstance(), DcsSampleOAuthActivity.class);
+ intent.putExtra("START_TAG", "RESTART");
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+ DcsSampleApplication.getInstance().startActivity(intent);
+ }
+
+ @Override
+ public boolean isSessionValid() {
+ String accessToken = getAccessToken();
+ long createTime = OauthPreferenceUtil.getCreateTime(DcsSampleApplication.getInstance());
+ long expires = OauthPreferenceUtil.getExpires(DcsSampleApplication.getInstance()) + createTime;
+ return !TextUtils.isEmpty(accessToken) && expires != 0 && System.currentTimeMillis() < expires;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthNetUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+import android.os.Bundle;
+
+import com.baidu.duer.dcs.util.CommonUtil;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Util类封装了一些基本的方法
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/19.
+ */
+public class OauthNetUtil {
+ /**
+ * 提取回调url中的token信息,用于User-Agent Flow中的授权操作
+ *
+ * @param url 回调的url,包括token信息
+ * @return 返回bundle类型的token信息
+ */
+ public static Bundle parseUrl(String url) {
+ Bundle ret;
+ url = url.replace("bdconnect", "http");
+ try {
+ URL urlParam = new URL(url);
+ ret = CommonUtil.decodeUrl(urlParam.getQuery());
+ ret.putAll(CommonUtil.decodeUrl(urlParam.getRef()));
+ return ret;
+ } catch (MalformedURLException e) {
+ return new Bundle();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthPreferenceUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.oauth.api;
+
+import android.content.Context;
+
+import com.baidu.duer.dcs.util.PreferenceUtil;
+
+/**
+ * 用户认证保存Preference工具类
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/3.
+ */
+public class OauthPreferenceUtil extends PreferenceUtil {
+ public static final String BAIDU_OAUTH_CONFIG = "baidu_oauth_config";
+
+ /**
+ * 保存数据的方法,拿到保存数据的具体类型,然后根据类型调用不同的保存方法
+ *
+ * @param context 上下文
+ * @param key key
+ * @param object value
+ */
+ public static void put(Context context, String key, Object object) {
+ put(context, BAIDU_OAUTH_CONFIG, key, object);
+ }
+
+ /**
+ * 得到保存数据的方法,
+ * 根据默认值得到保存的数据的具体类型,
+ * 然后调用相对于的方法获取值
+ *
+ * @param context 上下文
+ * @param key key
+ * @param defaultObject default-value
+ */
+ public static Object get(Context context, String key, Object defaultObject) {
+ return get(context, BAIDU_OAUTH_CONFIG, key, defaultObject);
+ }
+
+ public static void clear(Context context) {
+ clear(context, BAIDU_OAUTH_CONFIG);
+ }
+
+ public static void setAccessToken(Context context, String value) {
+ put(context, OauthConfig.PrefenenceKey.SP_ACCESS_TOKEN, value);
+ }
+
+ public static String getAccessToken(Context context) {
+ return (String) get(context, OauthConfig.PrefenenceKey.SP_ACCESS_TOKEN, "");
+ }
+
+ public static void setExpires(Context context, long value) {
+ put(context, OauthConfig.PrefenenceKey.SP_EXPIRE_SECONDS, value);
+ }
+
+ public static long getExpires(Context context) {
+ return (long) get(context, OauthConfig.PrefenenceKey.SP_EXPIRE_SECONDS, 0L);
+ }
+
+ public static void setCreateTime(Context context, long value) {
+ put(context, OauthConfig.PrefenenceKey.SP_CREATE_TIME, value);
+ }
+
+ public static long getCreateTime(Context context) {
+ return (long) get(context, OauthConfig.PrefenenceKey.SP_CREATE_TIME, 0L);
+ }
+
+ public static void clearAllOauth(Context context) {
+ clear(context);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IAlertsDataStore.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.systeminterface;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.Alert;
+
+import java.util.List;
+
+/**
+ * alert存储的回调接口
+ *
+ * Created by guxiuzhong@baidu.com on 2017/5/18.
+ */
+public interface IAlertsDataStore {
+
+ void readFromDisk(ReadResultListener listener);
+
+ void writeToDisk(List<Alert> alerts, WriteResultListener listener);
+
+ /**
+ * 读取回调
+ */
+ interface ReadResultListener {
+ void onSucceed(List<Alert> alerts);
+
+ void onFailed(String errMsg);
+ }
+
+ /**
+ * 写入回调
+ */
+ interface WriteResultListener {
+ void onSucceed();
+
+ void onFailed(String errMsg);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IAudioInput.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.systeminterface;
+
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+
+/**
+ * 语音输入接口
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public interface IAudioInput {
+ /**
+ * 处理开始录音的逻辑
+ */
+ void startRecord();
+
+ /**
+ * 处理停止录音的逻辑
+ */
+ void stopRecord();
+
+ void registerAudioInputListener(IAudioInputListener audioInputListener);
+
+ interface IAudioInputListener {
+ void onStartRecord(DcsStreamRequestBody dcsStreamRequestBody);
+ void onStopRecord();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IAudioRecord.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,34 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.systeminterface;
+
+/**
+ * 录音采集接口
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/26.
+ */
+public interface IAudioRecord {
+ /**
+ * 开始录音,采集音频数据
+ */
+ void startRecord();
+
+ /**
+ * 停止录音
+ */
+ void stopRecord();
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IHandler.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.systeminterface;
+
+/**
+ * handler接口
+ * <p>
+ * Created by wuruisheng on 2017/6/7.
+ */
+public interface IHandler {
+ boolean post(Runnable runnable);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IMediaPlayer.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.systeminterface;
+
+import java.io.InputStream;
+
+/**
+ * 播放器接口
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public interface IMediaPlayer {
+ /**
+ * 播放状态
+ */
+ enum PlayState {
+ ERROR(-1), // 播放错误
+ IDLE(0), // 播放未开始
+ PREPARING(1), // 播放准备中
+ PREPARED(2), // 播放准备就绪
+ PLAYING(3), // 正在播放
+ PAUSED(4), // 暂停播放
+ STOPPED(5), // 停止状态
+ COMPLETED(6); // 播放完成
+
+ private int state;
+
+ PlayState(int state) {
+ this.state = state;
+ }
+
+ public int getState() {
+ return state;
+ }
+ }
+
+ /**
+ * 获取当前的播放状态
+ *
+ * @return PlayState
+ */
+ PlayState getPlayState();
+
+ /**
+ * 播放
+ *
+ * @param mediaResource mediaResource
+ */
+ void play(MediaResource mediaResource);
+
+ /**
+ * 暂停
+ */
+ void pause();
+
+ /**
+ * 停止播放
+ */
+ void stop();
+
+ /**
+ * 调用pause暂停后重新播放
+ */
+ void resume();
+
+ /**
+ * 从milliseconds位置开始播放
+ *
+ * @param milliseconds 毫秒
+ */
+ void seekTo(int milliseconds);
+
+ /**
+ * 释放,销毁播放器
+ */
+ void release();
+
+ /**
+ * 设置音量 volume:0-1
+ *
+ * @param volume 音量(0-1之间的浮点数)
+ */
+ void setVolume(float volume);
+
+ float getVolume();
+
+ /**
+ * 设置静音
+ *
+ * @param mute 静音开关
+ */
+ void setMute(boolean mute);
+
+ boolean getMute();
+
+ /**
+ * 获取当前的播放位置
+ *
+ * @return 当前的播放位置
+ */
+ long getCurrentPosition();
+
+ /**
+ * 获取当前音频文件/流的总时长,单位:ms
+ *
+ * @return ms
+ */
+ long getDuration();
+
+ /**
+ * 获取当前缓冲到多少 0-100f
+ *
+ * @return 0-100f
+ */
+ float getBufferPercentage();
+
+ /**
+ * 添加播放器状态回调
+ *
+ * @param listener listener
+ */
+ void addMediaPlayerListener(IMediaPlayerListener listener);
+
+ void removeMediaPlayerListener(IMediaPlayerListener listener);
+
+ /**
+ * 设置播放通道是否处在活跃状态,比如:当用户在语音请求时,对话通道进入活跃状态
+ *
+ * @param isActive 是否处在活跃状态
+ */
+ void setActive(boolean isActive);
+
+ boolean isActive();
+
+ /**
+ * 播放器播放状态回调接口
+ */
+ interface IMediaPlayerListener {
+
+ /**
+ * 调用完play方法后回调此方法
+ */
+ void onInit();
+
+ /**
+ * 播放器准备完成后回调
+ */
+ void onPrepared();
+
+ /**
+ * 播放器销毁后回调
+ */
+ void onRelease();
+
+ /**
+ * 正在播放时回调
+ */
+ void onPlaying();
+
+ /**
+ * 暂停后回调
+ */
+ void onPaused();
+
+ void onStopped();
+
+ /**
+ * 播放完成后回调
+ */
+ void onCompletion();
+
+ /**
+ * 播放出错
+ */
+ void onError(String error, ErrorType errorType);
+
+ /**
+ * 播放器缓冲回调
+ *
+ * @param percent 缓冲的进度 0-100
+ */
+ void onBufferingUpdate(int percent);
+
+ /**
+ * 开始缓冲时回调
+ */
+ void onBufferingStart();
+
+ /**
+ * 结束缓冲时回调
+ */
+ void onBufferingEnd();
+
+ }
+
+ /**
+ * 播放错误类型信息
+ */
+ enum ErrorType {
+ MEDIA_ERROR_UNKNOWN("An unknown error occurred"),
+ MEDIA_ERROR_INVALID_REQUEST(
+ "The server recognized the request as being malformed "
+ + "(bad request, unauthorized, forbidden, not found, etc)"),
+ MEDIA_ERROR_SERVICE_UNAVAILABLE("The device was unavailable to reach the service"),
+ MEDIA_ERROR_INTERNAL_SERVER_ERROR(
+ "The server accepted the request, but was unable to process it as expected"),
+ MEDIA_ERROR_INTERNAL_DEVICE_ERROR("There was an internal error on the device");
+
+ private final String message;
+
+ ErrorType(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+ }
+
+ /**
+ * 内部空实现的IMediaPlayerListener,如果你只关心onCompletion,可以用这个
+ */
+ class SimpleMediaPlayerListener implements IMediaPlayerListener {
+ @Override
+ public void onInit() {
+
+ }
+
+ @Override
+ public void onPrepared() {
+
+ }
+
+ @Override
+ public void onRelease() {
+
+ }
+
+ @Override
+ public void onPlaying() {
+
+ }
+
+ @Override
+ public void onPaused() {
+
+ }
+
+ @Override
+ public void onStopped() {
+
+ }
+
+ @Override
+ public void onCompletion() {
+
+ }
+
+ @Override
+ public void onError(String error, ErrorType errorType) {
+
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+
+ }
+
+ @Override
+ public void onBufferingStart() {
+
+ }
+
+ @Override
+ public void onBufferingEnd() {
+
+ }
+ }
+
+ /**
+ * 需要播放的音频类型
+ */
+ final class MediaResource {
+ public InputStream stream; // 流类型
+ public String url; // url类型
+ public boolean isStream; // 是否值流类型
+
+ public MediaResource(InputStream stream) {
+ this.stream = stream;
+ this.isStream = true;
+ }
+
+ public MediaResource(String url) {
+ this.url = url;
+ this.isStream = false;
+ }
+
+ @Override
+ public String toString() {
+ if (isStream) {
+ return "stream";
+ } else {
+ return url;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IPlatformFactory.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.systeminterface;
+
+/**
+ * 定义平台相关工厂类
+ *
+ * Created by wuruisheng on 2017/6/7.
+ */
+public interface IPlatformFactory {
+ IHandler createHandler();
+ IHandler getMainHandler();
+ IAudioRecord getAudioRecord();
+ IWakeUp getWakeUp();
+ IAudioInput getVoiceInput();
+ IMediaPlayer createMediaPlayer();
+ IAlertsDataStore createAlertsDataStore();
+ IWebView getWebView();
+ void setWebView(IWebView webView);
+ IPlaybackController getPlayback();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IPlaybackController.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.systeminterface;
+
+import com.baidu.duer.dcs.framework.IResponseListener;
+
+/**
+ * PlaybackController接口
+ * <p>
+ * Created by zhoujianliang01 on 2017/6/17.
+ */
+public interface IPlaybackController {
+ void play(IResponseListener responseListener);
+
+ void pause(IResponseListener responseListener);
+
+ void previous(IResponseListener responseListener);
+
+ void next(IResponseListener responseListener);
+
+ void registerPlaybackListener(IPlaybackListener listener);
+
+ interface IPlaybackListener {
+ void onPlay(IResponseListener responseListener);
+
+ void onPause(IResponseListener responseListener);
+
+ void onPrevious(IResponseListener responseListener);
+
+ void onNext(IResponseListener responseListener);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IWakeUp.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,58 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.systeminterface;
+
+/**
+ * 唤醒接口
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/25.
+ */
+public interface IWakeUp {
+ /**
+ * 开始唤醒
+ * 1.初始化唤醒词
+ * 2.打开麦克风,并开始音频唤醒的解码
+ */
+ void startWakeUp();
+
+ /**
+ * 停止唤醒,调用停止录音
+ */
+ void stopWakeUp();
+
+ /**
+ * 释放资源,比如调用底层库释放资源等
+ */
+ void releaseWakeUp();
+
+ /**
+ * 唤醒结果的回调监听
+ *
+ * @param listener 监听实现
+ */
+ void addWakeUpListener(IWakeUpListener listener);
+
+ /**
+ * 唤醒结果的回调接口
+ */
+ interface IWakeUpListener {
+ /**
+ * 唤醒成功后回调
+ */
+ void onWakeUpSucceed();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IWebView.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.systeminterface;
+
+/**
+ * WebView接口
+ * <p>
+ * Created by zhoujianliang01 on 2017/6/17.
+ */
+public interface IWebView {
+ void loadUrl(String url);
+ void linkClicked(String url);
+
+ void addWebViewListener(IWebViewListener listener);
+
+ interface IWebViewListener {
+ void onLinkClicked(String url);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/CommonUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.util;
+
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.UUID;
+
+/**
+ * 辅助工具类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/17.
+ */
+public class CommonUtil {
+ private static final int JSON_INDENT = 4;
+
+ public static String getCurrentTime() {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
+ Locale.CHINESE);
+ return format.format(new Date());
+ }
+
+ /**
+ * 将毫秒格式转化为yyyy-MM-dd HH:mm:ss
+ *
+ * @param milliSeconds 毫秒
+ * @return 格式化后的字符串结果
+ */
+ public static String formatToDataTime(long milliSeconds) {
+ SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
+ return sd.format(milliSeconds);
+ }
+
+ /**
+ * 将key1=value1&key2=value2格式的query转换成key-value形式的参数串
+ *
+ * @param query key1=value1&key2=value2格式的query
+ * @return key-value形式的bundle
+ */
+ public static Bundle decodeUrl(String query) {
+ Bundle ret = new Bundle();
+ if (query != null) {
+ String[] pairs = query.split("&");
+ for (String pair : pairs) {
+ String[] keyAndValues = pair.split("=");
+ if (keyAndValues != null && keyAndValues.length == 2) {
+ String key = keyAndValues[0];
+ String value = keyAndValues[1];
+ if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
+ ret.putString(URLDecoder.decode(key), URLDecoder.decode(value));
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * 将key-value形式的参数串,转换成key1=value1&key2=value2格式的query
+ *
+ * @param params key-value参数
+ * @return key1=value1&key2=value2格式的query
+ */
+ public static String encodeUrl(Bundle params) {
+ if (params == null || params.isEmpty()) {
+ return null;
+ }
+ boolean first = true;
+ StringBuilder sb = new StringBuilder();
+ for (String key : params.keySet()) {
+ String paramValue = params.getString(key);
+ if (paramValue == null) {
+ continue;
+ }
+ if (first) {
+ first = false;
+ } else {
+ sb.append("&");
+ }
+ sb.append(URLEncoder.encode(key)).append("=").append(URLEncoder.encode(paramValue));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 展示一个通用的弹出框UI
+ *
+ * @param context 展示弹出框的上下文环境
+ * @param title 警告的title信息
+ * @param text 警告信息
+ */
+ public static void showAlert(Context context, String title, String text) {
+ AlertDialog alertDialog = new Builder(context).create();
+ alertDialog.setTitle(title);
+ alertDialog.setMessage(text);
+ alertDialog.setCanceledOnTouchOutside(true);
+ alertDialog.show();
+ }
+
+ private static long lastClickTime;
+
+ /**
+ * 是否是双击
+ *
+ * @return true 是,false 否
+ */
+ public static boolean isFastDoubleClick() {
+ long time = System.currentTimeMillis();
+ if (time - lastClickTime < 500) {
+ return true;
+ }
+ lastClickTime = time;
+ return false;
+ }
+
+ /**
+ * json 格式化输出
+ *
+ * @param json json字符串
+ * @return 用四个空格缩进后的json字符串结果
+ */
+ public static String formatJson(String json) {
+ String formatted = "";
+ if (json == null || json.length() == 0) {
+ return formatted;
+ }
+ try {
+ if (json.startsWith("{")) {
+ JSONObject jo = new JSONObject(json);
+ formatted = jo.toString(JSON_INDENT);
+ } else if (json.startsWith("[")) {
+ JSONArray ja = new JSONArray(json);
+ formatted = ja.toString(JSON_INDENT);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return formatted;
+ }
+
+ /**
+ * 关闭流
+ *
+ * @param closeables closeables
+ */
+ public static void closeQuietly(Closeable... closeables) {
+ for (Closeable c : closeables) {
+ try {
+ if (c != null) {
+ c.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Android设备物理唯一标识符
+ *
+ * @return String 设备唯一标识
+ */
+ public static String getDeviceUniqueID() {
+ String devIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ devIDShort += (Build.SUPPORTED_ABIS[0].length() % 10);
+ } else {
+ devIDShort += (Build.CPU_ABI.length() % 10);
+ }
+ devIDShort += (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10)
+ + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
+ String serial;
+ try {
+ serial = Build.class.getField("SERIAL").get(null).toString();
+ return new UUID(devIDShort.hashCode(), serial.hashCode()).toString();
+ } catch (Exception e) {
+ serial = "Dueros000";
+ }
+ return new UUID(devIDShort.hashCode(), serial.hashCode()).toString();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/DateFormatterUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.util;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * iso8601string 时间格式转换
+ * <p>
+ * Created by zhoujianliang01@baidu.com on 2017/6/5.
+ */
+public class DateFormatterUtil {
+ private static final String TAG = "ISO8601DateFormatter";
+ private static final DateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.CHINESE);
+ private static final DateFormat DATE_FORMAT_2 = new SimpleDateFormat("yyyy-MM-dd'T'HHmmssZ", Locale.CHINESE);
+ private static final String UTC_PLUS = "+";
+ private static final String UTC_MINUS = "-";
+
+ /**
+ * 将iso8601string格式字符串时间转为Date
+ *
+ * @param iso8601string iso8601格式的时间字符串
+ * @return Date Date类型表示的结果
+ * @throws ParseException ParseException
+ */
+ public static Date toDate(String iso8601string) throws ParseException {
+ iso8601string = iso8601string.trim();
+ if (iso8601string.toUpperCase().indexOf("Z") > 0) {
+ iso8601string = iso8601string.toUpperCase().replace("Z", "+0000");
+ } else if (((iso8601string.indexOf(UTC_PLUS)) > 0)) {
+ iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_PLUS));
+ iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_PLUS), UTC_PLUS);
+ } else if (((iso8601string.indexOf(UTC_MINUS)) > 0)) {
+ iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_MINUS));
+ iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_MINUS), UTC_MINUS);
+ }
+ LogUtil.d(TAG, "iso8601string:" + iso8601string);
+ Date date;
+ if (iso8601string.contains(":")) {
+ date = DATE_FORMAT_1.parse(iso8601string);
+ } else {
+ date = DATE_FORMAT_2.parse(iso8601string);
+ }
+ return date;
+ }
+
+ public static String toISO8601String(Date date) {
+ return DATE_FORMAT_1.format(date);
+ }
+
+ private static String replaceColon(String sourceStr, int offsetIndex) {
+ if (sourceStr.substring(offsetIndex).contains(":")) {
+ return sourceStr.substring(0, offsetIndex) + sourceStr.substring(offsetIndex).replace(":", "");
+ }
+ return sourceStr;
+ }
+
+ private static String appendZeros(String sourceStr, int offsetIndex, String offsetChar) {
+ if ((sourceStr.length() - 1) - sourceStr.indexOf(offsetChar, offsetIndex) <= 2) {
+ return sourceStr + "00";
+ }
+ return sourceStr;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/FileUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.util;
+
+import android.os.Environment;
+import android.text.TextUtils;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+/**
+ * FileUtil
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class FileUtil {
+ public static final String TEMP_POSTFIX = ".download";
+ private static final String LOG_FILE = "LogAll.txt";
+ private static final String APP_DIR = "/DCS";
+ private static final String SPEAK = APP_DIR + "/Speak";
+ private static final String ALERT = APP_DIR + "/Alert";
+ private static final String ALARM_FILE = "alarms.json";
+
+ private static String getSpeakDirPath() {
+ String dirPath = "";
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + SPEAK;
+ File dir = new File(dirPath);
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ }
+ return dirPath;
+ }
+
+ private static String getAlertDirPath() {
+ String dirPath = "";
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + ALERT;
+ File dir = new File(dirPath);
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ }
+ return dirPath;
+ }
+
+ public static File getSpeakFile() {
+ String dirPath = getSpeakDirPath();
+ if (TextUtils.isEmpty(dirPath)) {
+ return null;
+ }
+ return new File(dirPath,
+ "dcs_" + System.currentTimeMillis() + ".mp3" + TEMP_POSTFIX);
+ }
+
+ public static File getAlarmFile() {
+ String dirPath = getAlertDirPath();
+ if (TextUtils.isEmpty(dirPath)) {
+ return null;
+ }
+ return new File(dirPath, ALARM_FILE);
+ }
+
+ public static String getLogFilePath() {
+ return Environment.getExternalStorageDirectory().getAbsolutePath()
+ + APP_DIR + File.separator + LOG_FILE;
+ }
+
+ /**
+ * 日志追加文件
+ *
+ * @param content 追加的内容
+ */
+ public static void appendStrToFile(String content) {
+ File file = new File(getLogFilePath());
+ if (!file.isFile()) {
+ file.delete();
+ }
+ if (!file.exists()) {
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ BufferedWriter out = null;
+ try {
+ out = new BufferedWriter(new OutputStreamWriter(
+ new FileOutputStream(file, true)));
+ out.write(content);
+ out.flush();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ out.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/LogUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.util;
+
+import android.util.Log;
+
+/**
+ * Log日志输出信息
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class LogUtil {
+ // 是否开始debug模式,日志输出
+ public static boolean DEBUG = true;
+ private static final String APPNAME = "DCS-";
+ private static boolean LOGV_ON = DEBUG;
+ private static boolean LOGD_ON = DEBUG;
+ private static boolean LOGI_ON = DEBUG;
+ private static boolean LOGW_ON = DEBUG;
+ private static boolean LOGE_ON = DEBUG;
+ // 是否log写文件
+ private static boolean isWriteFile = true;
+
+ /**
+ * 设置debug 开关
+ *
+ * @param isDebug debug开关,true为开,false为关
+ */
+ public static void setDEBUG(boolean isDebug) {
+ DEBUG = isDebug;
+ LOGV_ON = true & DEBUG;
+ LOGD_ON = true & DEBUG;
+ LOGI_ON = true & DEBUG;
+ LOGW_ON = true & DEBUG;
+ LOGE_ON = true & DEBUG;
+ }
+
+ public static boolean getDEBUG() {
+ return DEBUG;
+ }
+
+ /**
+ * 记录相应的log信息v
+ *
+ * @param tag log tag 信息
+ * @param msg log msg 信息
+ */
+ public static void v(String tag, String msg) {
+ if (LOGV_ON) {
+ tag = APPNAME + tag;
+ Log.v(tag, msg);
+ writeLog("V", tag, msg, null);
+ }
+ }
+
+ public static void v(Class<?> c, String msg) {
+ if (LOGV_ON) {
+ String tag = APPNAME + c.getSimpleName();
+ Log.v(tag, msg);
+ writeLog("V", tag, msg, null);
+ }
+ }
+
+ public static void d(Class<?> c, String msg) {
+ if (LOGD_ON) {
+ String tag = APPNAME + c.getSimpleName();
+ Log.d(tag, msg);
+ writeLog("D", tag, msg, null);
+ }
+ }
+
+ /**
+ * 记录相应的log信息d
+ *
+ * @param tag log tag 信息
+ * @param msg log msg 信息
+ */
+ public static void d(String tag, String msg) {
+ if (LOGD_ON) {
+ tag = APPNAME + tag;
+ Log.d(tag, msg);
+ writeLog("D", tag, msg, null);
+ }
+ }
+
+ public static void d(String tag, String msg, Throwable tr) {
+ if (LOGE_ON) {
+ tag = APPNAME + tag;
+ Log.d(tag, msg, tr);
+ writeLog("D", tag, msg, tr);
+ }
+ }
+
+ /**
+ * 记录相应的log信息i
+ *
+ * @param tag log tag 信息
+ * @param msg log msg 信息
+ */
+ public static void i(String tag, String msg) {
+ if (LOGI_ON) {
+ tag = APPNAME + tag;
+ Log.i(tag, msg);
+ writeLog("I", tag, msg, null);
+ }
+ }
+
+ public static void i(Class<?> c, String msg) {
+ if (LOGI_ON) {
+ String tag = APPNAME + c.getSimpleName();
+ Log.i(tag, msg);
+ writeLog("I", tag, msg, null);
+ }
+ }
+
+ public static void w(Class<?> c, String msg) {
+ if (LOGW_ON) {
+ String tag = APPNAME + c.getSimpleName();
+ Log.w(tag, msg);
+ writeLog("W", tag, msg, null);
+ }
+ }
+
+ public static void w(Class<?> c, String msg, Throwable tr) {
+ if (LOGW_ON) {
+ String tag = APPNAME + c.getSimpleName();
+ Log.w(tag, msg, tr);
+ writeLog("W", tag, msg, tr);
+ }
+ }
+
+ /**
+ * 记录相应的log信息w
+ *
+ * @param tag log tag 信息
+ * @param msg log msg 信息
+ */
+ public static void w(String tag, String msg) {
+ if (LOGW_ON) {
+ tag = APPNAME + tag;
+ Log.w(tag, msg);
+ writeLog("W", tag, msg, null);
+ }
+ }
+
+ public static void w(String tag, String msg, Throwable tr) {
+ if (LOGW_ON) {
+ tag = APPNAME + tag;
+ Log.w(tag, msg, tr);
+ writeLog("W", tag, msg, tr);
+ }
+ }
+
+ /**
+ * 记录相应的log信息e
+ *
+ * @param tag log tag 信息
+ * @param msg log msg 信息
+ */
+ public static void e(String tag, String msg) {
+ if (LOGE_ON) {
+ tag = APPNAME + tag;
+ Log.e(tag, msg);
+ writeLog("E", tag, msg, null);
+ }
+ }
+
+ public static void e(Class<?> c, String msg) {
+ if (LOGE_ON) {
+ String tag = APPNAME + c.getSimpleName();
+ Log.e(tag, msg);
+ writeLog("E", tag, msg, null);
+ }
+ }
+
+ public static void e(String tag, String msg, Throwable tr) {
+ if (LOGE_ON) {
+ tag = APPNAME + tag;
+ Log.e(tag, msg, tr);
+ writeLog("E", tag, msg, tr);
+ }
+ }
+
+ public static void e(Class<?> c, String msg, Throwable tr) {
+ if (LOGE_ON) {
+ String tag = APPNAME + c.getSimpleName();
+ Log.e(tag, msg, tr);
+ writeLog("E", tag, msg, tr);
+ }
+ }
+
+ public static void setIsWriteFile(boolean isWriteFile) {
+ LogUtil.isWriteFile = isWriteFile;
+ }
+
+ private static void writeLog(String logLev, String tag, String msg, Throwable tr) {
+ if (isWriteFile) {
+ try {
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer
+ .append(CommonUtil.getCurrentTime())
+ .append("\n")
+ .append(tag)
+ .append("-")
+ .append(msg);
+ if (tr != null) {
+ stringBuffer.append(Log.getStackTraceString(tr));
+ }
+ stringBuffer.append("\n");
+ // 写文件
+ FileUtil.appendStrToFile(stringBuffer.toString());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/NetWorkUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.util;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+/**
+ * 网络检测工具类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/23.
+ */
+public class NetWorkUtil {
+ public static boolean isNetworkConnected(Context context) {
+ if (context != null) {
+ ConnectivityManager mConnectivityManager = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
+ if (mNetworkInfo != null) {
+ return mNetworkInfo.isAvailable();
+ }
+ }
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/ObjectMapperUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.util;
+
+import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.ObjectReader;
+import org.codehaus.jackson.map.ObjectWriter;
+import org.codehaus.jackson.map.SerializationConfig;
+
+import java.io.IOException;
+
+/**
+ * json序列化成对象和反序列化
+ *
+ * Created by wuruisheng on 2017/5/15.
+ */
+public class ObjectMapperUtil {
+ private static ObjectMapper objectMapper;
+
+ private static class ObjectMapperFactoryHolder {
+ private static final ObjectMapperUtil instance = new ObjectMapperUtil();
+ }
+
+ public static ObjectMapperUtil instance() {
+ return ObjectMapperFactoryHolder.instance;
+ }
+
+ private ObjectMapperUtil() {
+ objectMapper = new ObjectMapper();
+ objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
+ objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
+ }
+
+ public ObjectReader getObjectReader() {
+ return objectMapper.reader();
+ }
+
+ public ObjectReader getObjectReader(Class<?> clazz) {
+ return objectMapper.reader().withType(clazz);
+ }
+
+ public ObjectWriter getObjectWriter() {
+ return objectMapper.writer();
+ }
+
+
+ public String objectToJson(Object obj) {
+ String result = "";
+ try {
+ result = getObjectWriter().writeValueAsString(obj);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/PreferenceUtil.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.Build;
+
+import java.util.Map;
+
+/**
+ * 提供统一的Preference util方法
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class PreferenceUtil {
+ private static final String APP_SHARD = "com.baidu.duer.dcs";
+
+ /**
+ * 保存数据的方法,拿到保存数据的具体类型,然后根据类型调用不同的保存方法
+ *
+ * @param context 上下文
+ * @param key key
+ * @param object value
+ */
+ public static void put(Context context, String key, Object object) {
+ put(context, APP_SHARD, key, object);
+ }
+
+ public static void put(Context context, String spName, String key, Object object) {
+ SharedPreferences sp = context.getSharedPreferences(spName,
+ Context.MODE_PRIVATE);
+ Editor editor = sp.edit();
+
+ if (object instanceof String) {
+ editor.putString(key, (String) object);
+ } else if (object instanceof Integer) {
+ editor.putInt(key, (Integer) object);
+ } else if (object instanceof Boolean) {
+ editor.putBoolean(key, (Boolean) object);
+ } else if (object instanceof Float) {
+ editor.putFloat(key, (Float) object);
+ } else if (object instanceof Long) {
+ editor.putLong(key, (Long) object);
+ } else {
+ editor.putString(key, object.toString());
+ }
+ editSubmit(editor);
+ }
+
+ private static void editSubmit(Editor editor) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
+ editor.apply();
+ } else {
+ editor.commit();
+ }
+ }
+
+ /**
+ * 得到保存数据的方法,
+ * 根据默认值得到保存的数据的具体类型,
+ * 然后调用相对于的方法获取值
+ *
+ * @param context 上下文
+ * @param key key
+ * @param defaultObject default-value
+ */
+ public static Object get(Context context, String key, Object defaultObject) {
+ return get(context, APP_SHARD, key, defaultObject);
+ }
+
+ public static Object get(Context context, String spName, String key, Object defaultObject) {
+ SharedPreferences sp = context.getSharedPreferences(spName,
+ Context.MODE_PRIVATE);
+
+ if (defaultObject instanceof String) {
+ return sp.getString(key, (String) defaultObject);
+ } else if (defaultObject instanceof Integer) {
+ return sp.getInt(key, (Integer) defaultObject);
+ } else if (defaultObject instanceof Boolean) {
+ return sp.getBoolean(key, (Boolean) defaultObject);
+ } else if (defaultObject instanceof Float) {
+ return sp.getFloat(key, (Float) defaultObject);
+ } else if (defaultObject instanceof Long) {
+ return sp.getLong(key, (Long) defaultObject);
+ }
+ return null;
+ }
+
+ /**
+ * 移除某个key值已经对应的值
+ *
+ * @param context 上下文
+ * @param key key
+ */
+ public static void remove(Context context, String key) {
+ remove(context, APP_SHARD, key);
+ }
+
+ public static void remove(Context context, String spName, String key) {
+ SharedPreferences sp = context.getSharedPreferences(spName,
+ Context.MODE_PRIVATE);
+ Editor editor = sp.edit();
+ editor.remove(key);
+ editSubmit(editor);
+ }
+
+ /**
+ * 清除所有数据
+ *
+ * @param context 上下文
+ */
+ public static void clear(Context context) {
+ clear(context, APP_SHARD);
+ }
+
+ public static void clear(Context context, String spName) {
+ SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
+ Editor editor = sp.edit();
+ editor.clear();
+ editSubmit(editor);
+ }
+
+ /**
+ * 查询某个key是否已经存在
+ *
+ * @param context 上下文
+ * @param key key
+ */
+ public static boolean contains(Context context, String key) {
+ return contains(context, APP_SHARD, key);
+ }
+
+ public static boolean contains(Context context, String spName, String key) {
+ SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
+ return sp.contains(key);
+ }
+
+ /**
+ * 返回所有的键值对
+ *
+ * @param context 上下文
+ */
+ public static Map<String, ?> getAll(Context context) {
+ return getAll(context, APP_SHARD);
+ }
+
+ public static Map<String, ?> getAll(Context context, String spName) {
+ SharedPreferences sp = context.getSharedPreferences(spName,
+ Context.MODE_PRIVATE);
+ return sp.getAll();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/wakeup/WakeUp.java Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baidu.duer.dcs.wakeup;
+
+import com.baidu.duer.dcs.systeminterface.IAudioRecord;
+import com.baidu.duer.dcs.systeminterface.IWakeUp;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 本地唤醒服务
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/22.
+ */
+public class WakeUp {
+ private IWakeUp iWakeUp;
+ private List<IWakeUp.IWakeUpListener> wakeUpListeners;
+ private IAudioRecord iAudioRecord;
+
+ public WakeUp(IWakeUp iWakeUp, IAudioRecord iAudioRecord) {
+ this.iWakeUp = iWakeUp;
+ this.iAudioRecord = iAudioRecord;
+ this.wakeUpListeners = Collections.synchronizedList(new LinkedList<IWakeUp.IWakeUpListener>());
+ this.iWakeUp.addWakeUpListener(new IWakeUp.IWakeUpListener() {
+ @Override
+ public void onWakeUpSucceed() {
+ fireOnWakeUpSucceed();
+ }
+ });
+ // 启动音频采集
+ this.iAudioRecord.startRecord();
+ }
+
+ private void fireOnWakeUpSucceed() {
+ for (IWakeUp.IWakeUpListener listener : wakeUpListeners) {
+ listener.onWakeUpSucceed();
+ }
+ }
+
+ /**
+ * 开始唤醒,麦克风处于打开状态,一旦检测到有音频开始唤醒解码
+ */
+ public void startWakeUp() {
+ iWakeUp.startWakeUp();
+ }
+
+ /**
+ * 停止唤醒,关闭麦克风
+ */
+ public void stopWakeUp() {
+ iWakeUp.stopWakeUp();
+ }
+
+ /**
+ * 释放资源-解码so库资源
+ */
+ public void releaseWakeUp() {
+ iAudioRecord.stopRecord();
+ iWakeUp.releaseWakeUp();
+ }
+
+ /**
+ * 添加唤醒成功后的监听
+ */
+ public void addWakeUpListener(IWakeUp.IWakeUpListener listener) {
+ wakeUpListeners.add(listener);
+ }
+
+ public void removeWakeUpListener(IWakeUp.IWakeUpListener listener) {
+ if (wakeUpListeners.contains(listener)) {
+ wakeUpListeners.remove(listener);
+ }
+ }
+}
\ No newline at end of file
Binary file dcs-sdk-java-master/app/src/main/jniLibs/arm64-v8a/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/arm64-v8a/libbdEasrS1MergeNormal.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/armeabi-v7a/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/armeabi-v7a/libbdEasrS1MergeNormal.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/armeabi/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/armeabi/libbdEasrS1MergeNormal.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/x86/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/x86/libbdEasrS1MergeNormal.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/x86_64/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/x86_64/libbdEasrS1MergeNormal.so has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/res/drawable/btn_bg.xml Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_window_focused="false"> + <shape> + <solid android:color="@color/color_ff1247c2" /> + <corners android:radius="150dp" /> + + </shape> + </item> + <item android:state_focused="true"> + <shape> + <solid android:color="@color/color_aa1247c2" /> + <corners android:radius="150dp" /> + <stroke android:width="1dp" android:color="@color/color_aa1247c2" /> + </shape> + + </item> + <item android:state_pressed="true"> + <shape> + <solid android:color="@color/color_aa1247c2" /> + <corners android:radius="150dp" /> + <stroke android:width="1dp" android:color="@color/color_aa1247c2" /> + </shape> + + </item> +</selector> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_main.xml Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/color_f5f5f5" + android:orientation="vertical"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:text="@string/wakeup_word" + android:textColor="@android:color/black" + android:textSize="18dp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="vertical"> + + <ScrollView + android:id="@+id/id_sv_request" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <LinearLayout + android:id="@+id/topLinearLayout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" /> + </ScrollView> + </LinearLayout> + + + <LinearLayout + android:id="@+id/songLinearLayout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:orientation="horizontal"> + + <Button + android:id="@+id/previousSongBtn" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/previous_audio" /> + + <Button + android:id="@+id/pauseOrPlayBtn" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/audio_default" /> + + <Button + android:id="@+id/nextSongBtn" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/next_audio" /> + + </LinearLayout> + + <TextView + android:id="@+id/id_tv_time_0" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="@android:color/black" + android:textSize="16dp" /> + + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="10dp" + android:orientation="horizontal"> + + <Button + android:id="@+id/voiceBtn" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_margin="10dp" + android:layout_weight="1" + android:background="@drawable/btn_bg" + android:text="@string/stop_record" + android:textColor="@android:color/white" + android:textSize="16dp" /> + + <Button + android:id="@+id/openLogBtn" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_margin="10dp" + android:layout_weight="1" + android:background="@drawable/btn_bg" + android:text="@string/open_log" + android:textColor="@android:color/white" + android:textSize="16dp" /> + + </LinearLayout> + +</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_oauth.xml Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:text="@string/client_id" + android:textSize="16sp" /> + + <EditText + android:id="@+id/edit_client_id" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:enabled="false" /> + + <Button + android:id="@+id/btn_login" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:background="@drawable/btn_bg" + android:text="@string/login" + android:textColor="@android:color/white" /> + +</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_oauth_login.xml Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <RelativeLayout + android:id="@+id/containerLayout" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <WebView + android:id="@+id/oauthWeb" + android:layout_width="match_parent" + android:layout_height="match_parent" /> +</LinearLayout> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_screen_html.xml Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" android:layout_height="match_parent"> + + <RelativeLayout + android:id="@+id/relativeLayout" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + </RelativeLayout> +</RelativeLayout> \ No newline at end of file
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-hdpi/ic_launcher.png has changed
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-mdpi/ic_launcher.png has changed
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-xhdpi/ic_launcher.png has changed
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-xxhdpi/ic_launcher.png has changed
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/res/values/colors.xml Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="colorPrimary">#3F51B5</color> + <color name="colorPrimaryDark">#303F9F</color> + <color name="colorAccent">#FF4081</color> + + <color name="color_ff1247c2">#ff1247c2</color> + <color name="color_aa1247c2">#aa1247c2</color> + <color name="color_transparent">#00000000</color> + <color name="color_f5f5f5">#f5f5f5</color> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/res/values/strings.xml Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,25 @@ +<resources> + <string name="app_name">DcsSampleApp</string> + <string name="err_net_msg">当前网络连接失败,请稍后重试</string> + <string name="voice_err_msg">识别失败,请稍后再试</string> + <string name="audio_paused">暂停中…</string> + <string name="audio_playing">播放中…</string> + <string name="audio_default">等待音乐</string> + <string name="stop_record">点击说话</string> + <string name="start_record">录音中…</string> + <string name="time_record">耗时:click->StopListen:%1$dms</string> + <string name="request_error">出错了,请稍后再试</string> + <string name="no_log">暂时没有日志</string> + <string name="no_directive">对不起,暂时没有收到指令</string> + <string name="no_audio">暂时没有歌曲了,请稍后再试</string> + <string name="open_file_title">选择浏览工具</string> + <string name="previous_audio">上一首</string> + <string name="next_audio">下一首</string> + <string name="open_log">打开日志</string> + <string name="login">登陆</string> + <string name="client_id">您应用的client_id</string> + <string name="client_id_empty">请输入您申请的client_id</string> + <string name="login_succeed">登陆成功</string> + <string name="wakeup_succeed">唤醒成功,您问点什么呢?</string> + <string name="wakeup_word">您可以说【小度小度】进行唤醒</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/app/src/main/res/values/styles.xml Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,20 @@ +<resources> + + <!-- Base application theme. --> + <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> + <!-- Customize your theme here. --> + <item name="colorPrimary">@color/colorPrimary</item> + <item name="colorPrimaryDark">@color/colorPrimaryDark</item> + <item name="colorAccent">@color/colorAccent</item> + </style> + + <style name="AppTheme.NoActionBar"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + </style> + + <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> + + <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> + +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/build.gradle Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.2.3'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/gradle.properties Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,17 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true
Binary file dcs-sdk-java-master/gradle/wrapper/gradle-wrapper.jar has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/gradle/wrapper/gradle-wrapper.properties Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,6 @@ +#Mon Dec 28 10:00:20 PST 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/gradlew Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/gradlew.bat Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega
Binary file dcs-sdk-java-master/images/access-architecture.png has changed
Binary file dcs-sdk-java-master/images/client-id-secret.png has changed
Binary file dcs-sdk-java-master/images/login1.png has changed
Binary file dcs-sdk-java-master/images/login2.png has changed
Binary file dcs-sdk-java-master/images/modify-client-id.png has changed
Binary file dcs-sdk-java-master/images/project.png has changed
Binary file dcs-sdk-java-master/images/sdk-architecture.png has changed
Binary file dcs-sdk-java-master/images/wakeup.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcs-sdk-java-master/settings.gradle Tue Jul 18 16:34:48 2017 +0800 @@ -0,0 +1,1 @@ +include ':app'
