ソースを参照

fix

tags/A.2.0.0.1_20231007_base
tangmingjie 2年前
コミット
640a10b2f4
35個のファイルの変更1632行の追加651行の削除
  1. +5
    -1
      .idea/misc.xml
  2. +11
    -0
      app/build.gradle
  3. バイナリ
      app/libs/arm64-v8a/libmsc.so
  4. バイナリ
      app/libs/armeabi-v7a/libmsc.so
  5. +37
    -0
      app/src/ltLandscape/AndroidManifest.xml
  6. +167
    -0
      app/src/ltLandscape/res/layout/activity_main.xml
  7. +6
    -1
      app/src/main/AndroidManifest.xml
  8. +119
    -23
      app/src/main/java/com/aispeech/nativedemo/DDSService.java
  9. +2
    -1
      app/src/main/java/com/aispeech/nativedemo/DuiApplication.java
  10. +9
    -2
      app/src/main/java/com/aispeech/nativedemo/MainActivity.java
  11. +0
    -71
      app/src/main/java/com/aispeech/nativedemo/asr/observer/DuiCommandObserver.java
  12. +38
    -7
      app/src/main/java/com/aispeech/nativedemo/asr/observer/DuiMessageObserver.java
  13. +0
    -96
      app/src/main/java/com/aispeech/nativedemo/asr/observer/DuiUpdateObserver.java
  14. +1
    -0
      app/src/main/java/com/aispeech/nativedemo/config/ConfigManager.java
  15. +70
    -18
      app/src/main/java/com/aispeech/nativedemo/entity/PersonInfo.java
  16. +6
    -7
      app/src/main/java/com/aispeech/nativedemo/face/FaceChatGreetingQueueMode.java
  17. +1
    -1
      app/src/main/java/com/aispeech/nativedemo/face/FaceManager.java
  18. +11
    -0
      app/src/main/java/com/aispeech/nativedemo/iat/AsrMessageItem.java
  19. +7
    -0
      app/src/main/java/com/aispeech/nativedemo/iat/AsrResult.java
  20. +215
    -19
      app/src/main/java/com/aispeech/nativedemo/iat/IatManager.java
  21. +5
    -0
      app/src/main/java/com/aispeech/nativedemo/log/LogFile.java
  22. +2
    -0
      app/src/main/java/com/aispeech/nativedemo/log/LoggerPrinter.java
  23. +4
    -3
      app/src/main/java/com/aispeech/nativedemo/music/PlayerActivity.java
  24. +72
    -8
      app/src/main/java/com/aispeech/nativedemo/network/ws/MessageUtils.java
  25. +0
    -388
      app/src/main/java/com/aispeech/nativedemo/observer/DuiMessageObserver.java
  26. +31
    -0
      app/src/main/java/com/aispeech/nativedemo/rtasr/DraftWithOrigin.java
  27. +340
    -0
      app/src/main/java/com/aispeech/nativedemo/rtasr/RTASRTestJSON.java
  28. +344
    -0
      app/src/main/java/com/aispeech/nativedemo/rtasr/RTASRZXManager.java
  29. +21
    -0
      app/src/main/java/com/aispeech/nativedemo/rtasr/RecognizerExtendResult.java
  30. +66
    -0
      app/src/main/java/com/aispeech/nativedemo/rtasr/util/EncryptUtil.java
  31. バイナリ
      app/src/main/res/drawable-xxhdpi/pic_bg_sp.jpg
  32. +37
    -0
      app/src/main/res/drawable/launcher_drawable.xml
  33. +1
    -0
      app/src/main/res/layout/activity_launcher.xml
  34. +3
    -4
      app/src/main/res/layout/view_init.xml
  35. +1
    -1
      app/src/main/res/values/styles.xml

+ 5
- 1
.idea/misc.xml ファイルの表示

@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17_PREVIEW" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<component name="ASMIdeaPluginConfiguration">
<asm skipDebug="true" skipFrames="true" skipCode="false" expandFrames="false" />
<groovy codeStyle="LEGACY" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">


+ 11
- 0
app/build.gradle ファイルの表示

@@ -23,6 +23,7 @@ android {
}
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
flavorDimensions "channel"
}

signingConfigs {
@@ -54,6 +55,16 @@ android {
}
}

productFlavors {
ltLandscape {

}

portraitH5 {

}
}

externalNativeBuild {
ndkBuild {
path file('src/main/jni/Android.mk')


バイナリ
app/libs/arm64-v8a/libmsc.so ファイルの表示


バイナリ
app/libs/armeabi-v7a/libmsc.so ファイルの表示


+ 37
- 0
app/src/ltLandscape/AndroidManifest.xml ファイルの表示

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.aispeech.nativedemo">

<application
android:name=".DuiApplication"
android:allowBackup="true"
android:icon="@drawable/lt_logo"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
android:hardwareAccelerated="true"
android:requestLegacyExternalStorage="true"
>
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
tools:node="replace"
android:screenOrientation="landscape">
</activity>

<activity
android:name=".ui.LauncherActivity"
android:screenOrientation="landscape"
tools:node="replace"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

+ 167
- 0
app/src/ltLandscape/res/layout/activity_main.xml ファイルの表示

@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/rootView">

<TextureView
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:rotation="90"
android:rotationY="180"
android:id="@+id/texture_hdmi"
android:layout_width="2000dp"
android:layout_height="1125dp"
android:visibility="gone"/>

<com.tencent.smtt.sdk.WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>

<com.tencent.smtt.sdk.WebView
android:id="@+id/webview2"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent" />

<com.aispeech.nativedemo.widget.CameraTextureView
android:id="@+id/texture"
android:layout_width="2048px"
android:layout_height="1536px"
app:layout_constraintTop_toBottomOf="@id/webview2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />

<com.aispeech.nativedemo.widget.CameraTextureView
android:id="@+id/web_camera"
android:layout_width="640px"
android:layout_height="480px"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<TextView
android:id="@+id/face_focus_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/white"
android:textSize="40sp"
app:layout_constraintBottom_toBottomOf="@id/texture"
app:layout_constraintLeft_toLeftOf="@id/texture"
app:layout_constraintRight_toRightOf="@id/texture"
app:layout_constraintTop_toTopOf="@id/texture"/>

<TextView
android:id="@+id/my_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/white"
android:textSize="40sp"
app:layout_constraintBottom_toBottomOf="@id/texture"
app:layout_constraintLeft_toLeftOf="@id/texture"
app:layout_constraintRight_toRightOf="@id/texture"
app:layout_constraintTop_toTopOf="@id/texture" />

<TextView
android:id="@+id/my_face_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/white"
android:textSize="40sp"
app:layout_constraintBottom_toBottomOf="@id/texture"
app:layout_constraintLeft_toLeftOf="@id/texture"
app:layout_constraintRight_toRightOf="@id/texture"
app:layout_constraintTop_toTopOf="@id/texture" />

<Button
android:id="@+id/close_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="关闭会话"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone"/>

<Button
android:id="@+id/open_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选择GLM-6B"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone"/>

<Button
android:id="@+id/reboot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="reload"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone"/>

<Button
android:id="@+id/stop_web_socket"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查询员工"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:visibility="gone"/>

<Button
android:id="@+id/start_web_socket"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start server"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginEnd="150px"
android:visibility="gone"/>

<Button
android:id="@+id/kill_app"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="kill app"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />

<Button
android:id="@+id/stop_client"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop client"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="@id/stop_web_socket"
app:layout_constraintRight_toRightOf="@id/kill_app"
android:visibility="gone"/>

<Button
android:id="@+id/start_client"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start client"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="@id/kill_app"
app:layout_constraintRight_toRightOf="@id/start_web_socket"
android:visibility="gone"/>

<com.aispeech.nativedemo.ui.InitView
android:id="@+id/initView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>

</androidx.constraintlayout.widget.ConstraintLayout>

+ 6
- 1
app/src/main/AndroidManifest.xml ファイルの表示

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.aispeech.nativedemo">

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
@@ -41,10 +42,14 @@
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
tools:node="replace"
android:screenOrientation="portrait">
</activity>

<activity android:name=".ui.LauncherActivity" android:exported="true">
<activity
android:name=".ui.LauncherActivity"
android:screenOrientation="portrait"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />



+ 119
- 23
app/src/main/java/com/aispeech/nativedemo/DDSService.java ファイルの表示

@@ -4,7 +4,6 @@ import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioFormat;
@@ -23,9 +22,11 @@ import com.aispeech.dui.dds.DDSAuthListener;
import com.aispeech.dui.dds.DDSConfig;
import com.aispeech.dui.dds.DDSInitListener;
import com.aispeech.dui.dds.agent.AsrListener;
import com.aispeech.dui.dds.agent.MessageObserver;
import com.aispeech.dui.dds.agent.tts.TTSEngine;
import com.aispeech.dui.dds.agent.wakeup.cb.BfListener;
import com.aispeech.dui.dds.exceptions.DDSNotInitCompleteException;
import com.aispeech.nativedemo.face.FaceManager;
import com.aispeech.nativedemo.asr.observer.DuiMessageObserver;
import com.aispeech.nativedemo.iat.IatManager;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.mqtt.MqttManager;
@@ -36,6 +37,8 @@ import com.aispeech.nativedemo.utils.StatusUtils;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
@@ -114,6 +117,7 @@ public class DDSService extends Service {
private void init() {
// DDS.getInstance().setDebugMode(2); //在调试时可以打开sdk调试日志,在发布版本时,请关闭
DDS.getInstance().init(getApplicationContext(), createConfig(), mInitListener, mAuthListener);

}

// dds初始状态监听器,监听init是否成功
@@ -133,7 +137,7 @@ public class DDSService extends Service {
// DDS.getInstance().getAgent().getTTSEngine().setMode(DDSMode.TTS_SILENCE);
// DDS.getInstance().getAgent().getTTSEngine().setSpeaker("zhilingfp");
DDS.getInstance().getAgent().getTTSEngine().setSpeaker("hqqiaf","hqqiaf_lstm_210909.bin");
// startAsrListening();
startAsrListening();
} catch (DDSNotInitCompleteException e) {
throw new RuntimeException(e);
}
@@ -141,7 +145,8 @@ public class DDSService extends Service {
} else{
Logger.e("思必驰++++++++++++++++++++");
}
if(!Config.CURRENT_URL.equals(Config.PROD_BASE_URL)){
//if(!Config.CURRENT_URL.equals(Config.PROD_BASE_URL))
{
DDS.getInstance().setAudioDebug(true);
}
}
@@ -188,6 +193,8 @@ public class DDSService extends Service {
super.onDestroy();
// 在退出app时将dds组件注销
isStarted = false;
// 注销
DDS.getInstance().getAgent().unSubscribe(messageObserver);
DDS.getInstance().releaseSync();
}

@@ -345,31 +352,120 @@ public class DDSService extends Service {
private long mAsrTime = 0;
private String mFileName = "";

public void startKDXFListening() throws DDSNotInitCompleteException {
DDS.getInstance().getAgent().getWakeupEngine().setBfListener(new BfListener() {
@Override
public void onBeamforming(byte[] bytes) {
// Log.e(TAG, "onBeamforming" + bytes.length);
}
});
}

private List<byte[]> byteList = new LinkedList<>();
private long maxDuration = 0;
private static int WIRITE_DURATION = 300;
public void startAsrListening() {
DDS.getInstance().getAgent().getASREngine().setAsrListener(new AsrListener() {
@Override
public void onAsr(byte[] bytes) {
startTimer();
if(mTime == 0){
mTime = System.currentTimeMillis();
mAsrTime = System.currentTimeMillis();
}
if(System.currentTimeMillis() - mAsrTime > 1000){
mTime = System.currentTimeMillis();
//writeByFile(bytes);
writeNewMessage(bytes);
Log.e("testkd", "dds thread " + Thread.currentThread() + "bytes " + bytes.length);
}
});
startListenMessage();
}

private void startListenMessage() {
// 注册
DDS.getInstance().getAgent().subscribe(new String[]{"local_vad.timeout", "sys.vad.begin", "sys.vad.end"}, messageObserver);


}

private MessageObserver messageObserver = new MessageObserver() {
@Override
public void onMessage(final String message, final String data) {
if (message.equals("sys.vad.begin")){
mTime = System.currentTimeMillis();
byteList = new LinkedList<>();
Log.e("testkd", "mtime " + mTime + " vad.begin ");
}else if(message.equals("sys.vad.end")){
if(!byteList.isEmpty()){
IatManager.getInstance().executeStreamZXByte(DuiMessageObserver.mTime, byteList);
byteList = new LinkedList<>();
}
mAsrTime = System.currentTimeMillis();
File file = createFile("asr-" + mTime + ".pcm");
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(file, "rw");
raf.seek(file.length());
raf.write(bytes);
raf.close();
} catch (IOException e) {
throw new RuntimeException(e);
Log.e("testkd", "mtime " + mTime + " vad.end " + " thread " + Thread.currentThread());
} else {

}
}
};

private void writeNewMessage(byte[] bytes) {
byteList.add(bytes);
}

private void writeNew(byte[] bytes) {
startByteTimer();
if(mTime == 0){
mTime = System.currentTimeMillis();
mAsrTime = System.currentTimeMillis();
}

long duration = System.currentTimeMillis() - mAsrTime;
if(duration > WIRITE_DURATION){
Log.e("testtest", "max duration " + maxDuration);
} else if (duration > maxDuration){
maxDuration = duration;
}
if(System.currentTimeMillis() - mAsrTime > WIRITE_DURATION){
mTime = System.currentTimeMillis();
byteList = new LinkedList<>();
Log.e("testtest", "mtime " + mTime);
}
byteList.add(bytes);
mAsrTime = System.currentTimeMillis();
}

private void writeByFile(byte[] bytes) {
startTimer();
if(mTime == 0){
mTime = System.currentTimeMillis();
mAsrTime = System.currentTimeMillis();
}
if(System.currentTimeMillis() - mAsrTime > WIRITE_DURATION){
mTime = System.currentTimeMillis();
}
mAsrTime = System.currentTimeMillis();
File file = createFile("asr-" + mTime + ".pcm");
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(file, "rw");
raf.seek(file.length());
raf.write(bytes);
raf.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private Timer mByteTimer;
public void startByteTimer(){
if(mByteTimer != null){
mByteTimer.cancel();
mByteTimer = null;
}
mByteTimer = new Timer();
mByteTimer.schedule(new TimerTask() {
@Override
public void run() {
if(!byteList.isEmpty()){
IatManager.getInstance().executeStreamByte(String.valueOf(mTime), byteList);
byteList = new LinkedList<>();
}
}
});
}, WIRITE_DURATION);
}

private Timer mTimer;
@@ -392,7 +488,7 @@ public class DDSService extends Service {
mFileName = dirPath;
}
}
}, 1000);
}, WIRITE_DURATION);
}

public File createFile(String name) {


+ 2
- 1
app/src/main/java/com/aispeech/nativedemo/DuiApplication.java ファイルの表示

@@ -3,6 +3,7 @@ package com.aispeech.nativedemo;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.util.Log;

import com.aispeech.dui.dds.DDS;
@@ -35,7 +36,7 @@ public class DuiApplication extends Application {
mContext = this;
Logger.init();
CrashHandler.getInstance().init(this);
SpeechUtility.createUtility(this, "appid=e14469ab");
SpeechUtility.createUtility(this, "appid=" + "948cf4b6");// "tmj appid=" + "e14469ab" "ljc appid=" + "6917197f"
Fresco.initialize(this);
// Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
// FaceManager.getInstance(this).initEngine();


+ 9
- 2
app/src/main/java/com/aispeech/nativedemo/MainActivity.java ファイルの表示

@@ -425,7 +425,12 @@ public class MainActivity extends Activity implements DuiUpdateObserver.UpdateCa

public void onPageFinished(WebView var1, String var2) {
Log.e("testh", " onPageFinished " + Thread.currentThread());
mInitView.updateDigital(InitView.INIT_SUCCESS);
mInitView.postDelayed(new Runnable() {
@Override
public void run() {
mInitView.updateDigital(InitView.INIT_SUCCESS);
}
}, 4000);
}

@Override
@@ -467,7 +472,9 @@ public class MainActivity extends Activity implements DuiUpdateObserver.UpdateCa
String method = "setVideoPlaybackRequiresUserGesture";
Bundle bundle = new Bundle();
bundle.putBoolean("require", true);
webView.getX5WebViewExtension().invokeMiscMethod(method, bundle);
if (webView.getX5WebViewExtension() != null) {
webView.getX5WebViewExtension().invokeMiscMethod(method, bundle);
}
}

private WebSocketManager mWSManager;


+ 0
- 71
app/src/main/java/com/aispeech/nativedemo/asr/observer/DuiCommandObserver.java ファイルの表示

@@ -1,71 +0,0 @@
package com.aispeech.nativedemo.asr.observer;

import android.content.Intent;
import android.net.Uri;
import android.util.Log;

import com.aispeech.dui.dds.DDS;
import com.aispeech.dui.dsk.duiwidget.CommandObserver;

import org.json.JSONObject;

/**
* 客户端CommandObserver, 用于处理客户端动作的执行以及快捷唤醒中的命令响应.
* 例如在平台配置客户端动作: command://call?phone=$phone$&name=#name#,
* 那么在CommandObserver的onCall方法中会回调topic为"call", data为
*/
public class DuiCommandObserver implements CommandObserver {
private String TAG = "DuiCommandObserver";
private static final String COMMAND_CALL = "sys.action.call";
private static final String COMMAND_SELECT = "sys.action.call.select";
private String mSelectedPhone = null;

public DuiCommandObserver() {
}

// 注册当前更新消息
public void regist() {
DDS.getInstance().getAgent().subscribe(new String[]{COMMAND_CALL, COMMAND_SELECT},
this);
}

// 注销当前更新消息
public void unregist() {
DDS.getInstance().getAgent().unSubscribe(this);
}

@Override
public void onCall(String command, String data) {
Log.e(TAG, "command: " + command + " data: " + data);
try {
if (COMMAND_CALL.equals(command)) {
String number = new JSONObject(data).optString("phone");
if (number == null) {
phoneDial(mSelectedPhone);
mSelectedPhone = null;
} else {
phoneDial(number);
}
} else if (COMMAND_SELECT.equals(command)) {
mSelectedPhone = new JSONObject(data).optString("phone");
}
} catch (Exception e) {
e.printStackTrace();
}
}

// 拨打电话
private void phoneDial(String number) {
if (number == null) {
return;
}
Log.e(TAG, "phoneDial:" + number);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("tel:" + number));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
// DuiApplication.getContext().startActivity(intent);
}

}

+ 38
- 7
app/src/main/java/com/aispeech/nativedemo/asr/observer/DuiMessageObserver.java ファイルの表示

@@ -1,6 +1,7 @@
package com.aispeech.nativedemo.asr.observer;

import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import com.aispeech.dui.dds.DDS;
@@ -8,6 +9,7 @@ import com.aispeech.dui.dds.agent.DMTaskCallback;
import com.aispeech.dui.dds.agent.MessageObserver;
import com.aispeech.nativedemo.MainActivity;
import com.aispeech.nativedemo.config.Config;
import com.aispeech.nativedemo.iat.IatManager;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.mqtt.MqttManager;
import com.aispeech.nativedemo.network.ws.MessageUtils;
@@ -19,6 +21,7 @@ import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
* 客户端MessageObserver, 用于处理客户端动作的消息响应.
@@ -40,6 +43,9 @@ public class DuiMessageObserver implements MessageObserver {
private boolean mIsFirstVar = true;
private boolean mHasvar = false;
private Gson mGson;
public static volatile String mTime = "";

private ConcurrentHashMap<String, String> mRecordIdMap = new ConcurrentHashMap<>();
private String[] mSubscribeKeys = new String[]{
"sys.dialog.state",
"context.output.text",
@@ -67,11 +73,22 @@ public class DuiMessageObserver implements MessageObserver {
public JSONObject onDMTaskResult(JSONObject jsonObject, Type type) {
if(type == Type.DM_OUTPUT){
String sessionId = jsonObject.optString("sessionId");
String recordId = jsonObject.optString("recordId");
String display = jsonObject.optString("display");
String nlg = jsonObject.optString("nlg");
String dmInput = jsonObject.optString("dmInput");
Log.e(Tag, display);
Log.e(Tag, nlg);

Log.e("testtest", "thread "+ Thread.currentThread()+" onDMTResult " + jsonObject.toString());
Log.e("testtest", "thread "+ Thread.currentThread()+" md display " + display);
String time = "";
if (!TextUtils.isEmpty(dmInput) && !TextUtils.isEmpty(recordId)) {
time = mRecordIdMap.get(recordId);
String asrStr = IatManager.getInstance().getASRStr(time);
Logger.e("djASR-思必驰: " + dmInput);
Log.e("testtest", "djASR-思必驰: " + dmInput + " asrStr " + asrStr + " time " + time);
}
String readText = nlg;
// if (JSONUtils.isJson(display)) {
// readText = MessageUtils.sendSkill(sessionId, display, dmInput);
@@ -91,17 +108,21 @@ public class DuiMessageObserver implements MessageObserver {
// e.printStackTrace();
// }
// }
// onMessage 前置处理 nlp
if (JSONUtils.isJson(display)) {
MessageUtils.sendSkill(sessionId, display, dmInput);
MessageUtils.sendSkill(sessionId, display, dmInput, time);
} else {
MessageUtils.sendNlpResult(sessionId, display, dmInput);
MessageUtils.sendNlpResult(sessionId, display, dmInput, time);
}

try {
jsonObject.put("nlg", "");
jsonObject.put("display", "");
} catch (JSONException e) {
e.printStackTrace();
}
} else if (type == DMTaskCallback.Type.CDM_ERROR) {
Log.e("testtest", "CDM_ERROR ");
}
return jsonObject;
}
@@ -116,19 +137,26 @@ public class DuiMessageObserver implements MessageObserver {
public static boolean mIsSleep = false;
public static boolean mSpeakFinishStatus = true;
public static long mSpeakFinishTime = 0;
public static String mAsrWord = "";

@Override
public void onMessage(String message, String data) {
Log.d(Tag, "message : " + message + " data : " + data);
switch (message) {
case "context.output.text":
// nlp
MessageUtils.sendChatMessage(data);

Log.e("testtest", "message " + message + " data " + data.toString());
break;
case "context.input.text":
// 识别的文本
//判断有人的时候才发送给大模型
// if(FaceManager.getInstance(DuiApplication.getContext()).hasPerson()){
MessageUtils.sendAsr(data);
String recordId = MessageUtils.sendAsrAndGetRecordId(data, mTime);
if (!TextUtils.isEmpty(recordId)) {
mRecordIdMap.put(recordId, mTime);
}
Log.e("testtest", "message " + message + " data " + data.toString());
//Logger.e("djASR-asrWord " + mAsrWord);
// }
break;
case "context.widget.content":
@@ -185,6 +213,7 @@ public class DuiMessageObserver implements MessageObserver {

break;
case "local_vad.pcm":
//Log.e("testtest", "data = " + data.getBytes().length);
// Log.e(Tag, "data = " + data);
// byte[] buffer = data.getBytes();
// File file = createFile(mTime + ".pcm");
@@ -200,9 +229,12 @@ public class DuiMessageObserver implements MessageObserver {
// }
break;
case "sys.vad.begin":
// mTime = SystemClock.uptimeMillis();

Log.e("testtest", "mtime message " +" vad.begin ");
mTime = String.valueOf(System.currentTimeMillis());
break;
case "sys.vad.end":
Log.e("testtest", "message " +" vad.end " + Thread.currentThread());
break;
default:
}
@@ -228,6 +260,5 @@ public class DuiMessageObserver implements MessageObserver {
return objFile;
}

private long mTime = 0;

}

+ 0
- 96
app/src/main/java/com/aispeech/nativedemo/asr/observer/DuiUpdateObserver.java ファイルの表示

@@ -1,96 +0,0 @@
package com.aispeech.nativedemo.asr.observer;

import android.util.Log;

import com.aispeech.dui.dds.DDS;
import com.aispeech.dui.dds.agent.MessageObserver;
import com.aispeech.dui.dds.exceptions.DDSNotInitCompleteException;
import com.aispeech.dui.dds.update.DDSUpdateListener;

/**
* 更新Observer,用于更新当前dds组件
*/
public class DuiUpdateObserver implements MessageObserver {
private static final String Tag = "DuiUpdateObserver";
public static final int START = 0; // 开始更新
public static final int UPDATEING = 1; // 正在更新
public static final int FINISH = 2;// 更新完成
public static final int ERROR = 3;// 更新失败

private UpdateCallback mUpdateCallback;

// 更新回调
public interface UpdateCallback {
void onUpdate(int type, String result);
}

// 注册当前更新消息
public void regist(UpdateCallback updateCallback) {
mUpdateCallback = updateCallback;
DDS.getInstance().getAgent().subscribe("sys.resource.updated", this);
initUpdate();
}

// 注销当前更新消息
public void unregist() {
DDS.getInstance().getAgent().unSubscribe(this);
}

// 初始化更新
private void initUpdate() {
try {
DDS.getInstance().getUpdater().update(ddsUpdateListener);
} catch (DDSNotInitCompleteException e) {
e.printStackTrace();
}
}

@Override
public void onMessage(String s, String s1) {
initUpdate();
}

private DDSUpdateListener ddsUpdateListener = new DDSUpdateListener() {
@Override
public void onUpdateFound(String detail) {
try {
if (mUpdateCallback != null) {
mUpdateCallback.onUpdate(START, "发现新版本");
}
DDS.getInstance().getAgent().getTTSEngine().speak("发现新版本,正在为您更新", 1);
} catch (DDSNotInitCompleteException e) {
e.printStackTrace();
}
}

@Override
public void onUpdateFinish() {
if (mUpdateCallback != null) {
mUpdateCallback.onUpdate(FINISH, "更新成功");
}
// 更新成功后不要立即调用speak提示用户更新成功, 这个时间DDS正在初始化
}

@Override
public void onDownloadProgress(float progress) {
if (mUpdateCallback != null) {
mUpdateCallback.onUpdate(UPDATEING, "正在更新 -> " + progress + " / 100");
}
}

@Override
public void onError(int what, String error) {
if (mUpdateCallback != null) {
mUpdateCallback.onUpdate(ERROR, "更新失败,详情看Log");
}
Log.e(Tag, "what = " + what + ", error = " + error);
}

@Override
public void onUpgrade(String version) {
if (mUpdateCallback != null) {
mUpdateCallback.onUpdate(ERROR, "更新失败 -> 当前sdk版本过低,和dui平台上的dui内核不匹配,请更新sdk");
}
}
};
}

+ 1
- 0
app/src/main/java/com/aispeech/nativedemo/config/ConfigManager.java ファイルの表示

@@ -267,6 +267,7 @@ public class ConfigManager {
// MessageUtils.sendMessage("技能:" + success);
if (obj.has("data")) {
JSONArray array = obj.getJSONArray("data");
MessageUtils.sendSkills(array.toString());
for (int i = 0; i < array.length(); i++) {
JSONObject jsonObject = array.getJSONObject(i);
Skill skill = new Skill();


+ 70
- 18
app/src/main/java/com/aispeech/nativedemo/entity/PersonInfo.java ファイルの表示

@@ -1,5 +1,11 @@
package com.aispeech.nativedemo.entity;

import static com.aispeech.nativedemo.entity.PositionEnum.POSITION_LEFT_TO_LEFT;
import static com.aispeech.nativedemo.entity.PositionEnum.POSITION_LEFT_TO_RIGHT;
import static com.aispeech.nativedemo.entity.PositionEnum.POSITION_ONCE;
import static com.aispeech.nativedemo.entity.PositionEnum.POSITION_RIGHT_TO_LEFT;
import static com.aispeech.nativedemo.entity.PositionEnum.POSITION_RIGHT_TO_RIGHT;

import android.graphics.Bitmap;
import android.util.Log;

@@ -10,6 +16,10 @@ import org.json.JSONObject;

public class PersonInfo {
private static final long LEAVE_DURATION = 60 * 1000;
private static final int DELTA_X = 20;
private static final int RIGHT_MAX = 1700;
private static final int MAX_LENGTH = 800;
private static final int MAX_GREETING_DURATION = 1000;
public String id; // eid
public String name; //昵称
public String tag; //人物类别
@@ -41,7 +51,7 @@ public class PersonInfo {
* 初始值 0:从未出现
* 方向 1:从左到屏幕中静止 左右 (包含折现) 2:从右走到屏幕中(包含折现) 右左 3:左右左 4. 右左右
* 最终判定值配合是否在屏幕中 1.1:从左到右走出屏幕 2.1:从右到左走出屏幕 3.1:左右左后走出屏幕4.1右左右走出屏幕
* 5.只出现一次 6.出现并静止
* 5.只出现一次 6.出现并静止 最左 142 517 最右1959 1887
*/
public PositionEnum position_type; // directionType
public int face_x1;
@@ -82,7 +92,7 @@ public class PersonInfo {
this.last_in_time = startTime;
this.is_in_view = 1;
this.hasBeenGreeted = false;
this.position_type = PositionEnum.POSITION_ONCE;
this.position_type = POSITION_ONCE;
if (att.hd_bd > 0) {
this.startBodyPositionX = (result.bd_x1 + result.bd_x2) / 2;
}
@@ -126,8 +136,17 @@ public class PersonInfo {
obj.put("bd_x", (result.bd_x1 + result.bd_x2) / 2);
long time = System.currentTimeMillis();
obj.put("ts", time / 1000 + "." + time % 1000);
obj.put("lastInTime", last_in_time);
obj.put("lastInTime", last_in_time); // 进入屏幕的时间
obj.put("lastGreetTime", last_greet_time); // 打招呼的时间
obj.put("directionType", position_type.ordinal()); // 运动的方向
obj.put("currentBodyPositionX", currentBodyPositionX); // 运动的方向
obj.put("previewBodyPositionX", previewBodyPositionX); // 运动的方向
obj.put("startBodyPositionX", startBodyPositionX); // 运动的方向
obj.put("startFacePositionX", startFacePositionX); // 运动的方向
obj.put("previewFacePositionX", previewFacePositionX); // 运动的方向
obj.put("currentFacePositionX", currentFacePositionX); // 运动的方向
obj.put("hasBeenGreeted", hasBeenGreeted);
obj.put("isInView", is_in_view);
return obj.toString();
} catch (JSONException e) {
e.printStackTrace();
@@ -147,6 +166,7 @@ public class PersonInfo {
this.startBodyPositionX = -1;
this.previewBodyPositionX = -1;
this.currentBodyPositionX = -1;
this.position_type = POSITION_ONCE;
this.hasBeenGreeted = false;
} else {
this.previewFacePositionX = this.currentFacePositionX;
@@ -185,10 +205,14 @@ public class PersonInfo {
}
if (att.hd_fa > 0) {
this.currentFacePositionX = (face_x1 + face_x2) / 2;
if (!hasDirection && startFacePositionX >= 0 && previewFacePositionX >= 0) {
calculateDirection(startFacePositionX, previewFacePositionX, currentFacePositionX);
} else if (!hasDirection && startBodyPositionX >= 0) {
calculateDirection(currentFacePositionX, previewBodyPositionX, currentFacePositionX);
if (startFacePositionX >= 0 && previewFacePositionX >= 0) {
if (!hasDirection) {
calculateDirection(startFacePositionX, previewFacePositionX, currentFacePositionX);
}
} else if (startFacePositionX >= 0) {
if (!hasDirection) {
calculateDirection(startFacePositionX, currentFacePositionX);
}
} else {
startFacePositionX = currentFacePositionX;
}
@@ -199,32 +223,36 @@ public class PersonInfo {

private void calculateDirection(int startBodyPositionX, int currentBodyPositionX) {
int deltaX = currentBodyPositionX - startBodyPositionX;
if (deltaX > 0) {
if (deltaX >= DELTA_X) {
position_type = PositionEnum.POSITION_LEFT_TO_RIGHT;
} else if (deltaX == 0) {
position_type = PositionEnum.POSITION_WAITING;
} else {
} else if (deltaX <= -DELTA_X) {
position_type = PositionEnum.POSITION_RIGHT_TO_LEFT;
} else {
position_type = PositionEnum.POSITION_WAITING;
}
}

private void calculateDirection(int startBodyPositionX, int previewBodyPositionX, int currentBodyPositionX) {
int deltaCurrentX = currentBodyPositionX - previewBodyPositionX;
int deltaX = previewBodyPositionX - startBodyPositionX;
if (deltaCurrentX > 0) {
if (deltaX > 0) {
if (deltaCurrentX >= DELTA_X) {
if (deltaX >= DELTA_X) {
position_type = PositionEnum.POSITION_LEFT_TO_RIGHT;
} else {
} else if (deltaX <= -DELTA_X) {
position_type = PositionEnum.POSITION_RIGHT_TO_RIGHT;
} else {
position_type = PositionEnum.POSITION_LEFT_TO_RIGHT;
}
} else if (deltaX < 0) {
if (deltaX < 0) {
} else if (deltaX <= -DELTA_X) {
if (deltaX <= -DELTA_X) {
position_type = PositionEnum.POSITION_RIGHT_TO_LEFT;
} else {
} else if (deltaX >= DELTA_X){
position_type = PositionEnum.POSITION_LEFT_TO_LEFT;
} else {
position_type = PositionEnum.POSITION_RIGHT_TO_LEFT;
}
} else {
position_type = PositionEnum.POSITION_WAITING;
calculateDirection(startBodyPositionX, previewBodyPositionX);
}
}

@@ -243,4 +271,28 @@ public class PersonInfo {
return 1;
}

public boolean hasDirection() {
long time = System.currentTimeMillis();
if (position_type == POSITION_LEFT_TO_LEFT || position_type == POSITION_RIGHT_TO_LEFT) {
return true;
}
if (position_type == POSITION_LEFT_TO_RIGHT || position_type == POSITION_RIGHT_TO_RIGHT) {
if (startBodyPositionX > MAX_LENGTH && ((currentBodyPositionX - startBodyPositionX) > MAX_LENGTH)) {
return true;
} else if (startFacePositionX > MAX_LENGTH && ((currentFacePositionX - startFacePositionX) > MAX_LENGTH)) {
return true;
} else {
return false;
}
}
if (startBodyPositionX != -1 && currentBodyPositionX != -1
&& startBodyPositionX != currentBodyPositionX && ((time - last_in_time) > MAX_GREETING_DURATION)) {
return true;
}
if (startFacePositionX != -1 && currentFacePositionX != -1
&& startFacePositionX != currentFacePositionX && ((time - last_in_time) > MAX_GREETING_DURATION)) {
return true;
}
return false;
}
}

+ 6
- 7
app/src/main/java/com/aispeech/nativedemo/face/FaceChatGreetingQueueMode.java ファイルの表示

@@ -458,8 +458,7 @@ public class FaceChatGreetingQueueMode implements ChatMode {
// Log.e("testtest", "sendMsgAndLog mSelectedPerson is null ");
return;
}
// Log.e("testtest", "slected trackid " +mSelectPerson.trackId + "selectperson bd.x1 " + mSelectPerson.curResult.bd_x1+ " x2 " + mSelectPerson.curResult.bd_x2
// + " facex1 " + mSelectPerson.curResult.fa_x1 + " facex2 " + mSelectPerson.curResult.fa_x2 + " bitmap " + mSelectPerson.bitmap);
Log.e("testtrack", " select people " + mSelectPerson);
FaceManager.getInstance().updateRect(mSelectPerson.curResult);
sendMsg(mSelectPerson);

@@ -568,7 +567,7 @@ public class FaceChatGreetingQueueMode implements ChatMode {
for (PersonInfo value : mPersonsInScreen) {
// 是否有脸
long time = System.currentTimeMillis();
if (!value.hasBeenGreeted) {
if (!value.hasBeenGreeted && value.hasDirection()) {
value.last_greet_time = time;
value.hasBeenGreeted = true;
Log.e("testtrack", "greeting emp eid " + value);
@@ -579,17 +578,18 @@ public class FaceChatGreetingQueueMode implements ChatMode {
for (PersonInfo value : mUndeterminedPersonsInScreen) {
// 是否有脸
long time = System.currentTimeMillis();
if (!value.hasBeenGreeted && (time - value.last_in_time) >= UNKNOWN_GREETING_DURATION) {
if (!value.hasBeenGreeted && ((time - value.last_in_time) >= UNKNOWN_GREETING_DURATION)
&& value.hasDirection()) {
value.last_greet_time = time;
value.hasBeenGreeted = true;
Log.e("testtrack", "greeting trackId " + value.trackId + " old trackid" + value.oldTrackId + " fa.qulity " + value.face_quality + " greeting duration " + (System.currentTimeMillis() - value.last_greet_time));
Log.e("testtrack", "greeting trackId " + value.trackId + " old value " + value + " greeting duration " + (System.currentTimeMillis() - value.last_in_time));
sendGreeting(value);
break;
} else {
// 陌生人打招呼超过两秒才打
if (System.currentTimeMillis() - value.last_greet_time < 2500) {
//sendGreeting(value);
Log.e("testtrack", "< 2500 " + value.trackId + " old trackid" + value.oldTrackId + " fa.qulity " + value.face_quality + " greeting duration " + (System.currentTimeMillis() - value.last_greet_time));
//Log.e("testtrack", "< 2500 " + value.trackId + " old trackid" + value.oldTrackId + " fa.qulity " + value.face_quality + " greeting duration " + (System.currentTimeMillis() - value.last_greet_time));

return;
}
@@ -614,7 +614,6 @@ public class FaceChatGreetingQueueMode implements ChatMode {
person.put("lastGreetTime", message.last_greet_time); // 打招呼的时间
person.put("directionType", message.position_type.ordinal()); // 运动的方向
Skill skill = SkillDbHelper.getInstance().getByType(message.tag);
Log.e("testtrack", "skill " + skill);
if (skill != null) {
person.put("skillStatus", skill.status);
person.put("resp", skill.resp);


+ 1
- 1
app/src/main/java/com/aispeech/nativedemo/face/FaceManager.java ファイルの表示

@@ -206,7 +206,7 @@ public class FaceManager implements ChatMode {
long postDelay = 0;
if (IdentityMode.MODE_CURRENT.equals(IdentityMode.MODE_CHAT)) {
// 工作模式和闲聊模式
postDelay = mFaceChatMode.detectFace(textureBitmap);
postDelay = mFaceChatReasonMode.detectFace(textureBitmap);
} else {
// 接待模式
postDelay = mFaceReceptionMode.detectFace(textureBitmap);


+ 11
- 0
app/src/main/java/com/aispeech/nativedemo/iat/AsrMessageItem.java ファイルの表示

@@ -0,0 +1,11 @@
package com.aispeech.nativedemo.iat;

public class AsrMessageItem {
public String sessionId;
public String display;

public AsrMessageItem(String sessionId, String display) {
this.sessionId = sessionId;
this.display = display;
}
}

+ 7
- 0
app/src/main/java/com/aispeech/nativedemo/iat/AsrResult.java ファイルの表示

@@ -0,0 +1,7 @@
package com.aispeech.nativedemo.iat;

public class AsrResult {
public String asr = "";
public AsrMessageItem asrMessageItem;

}

+ 215
- 19
app/src/main/java/com/aispeech/nativedemo/iat/IatManager.java ファイルの表示

@@ -8,6 +8,8 @@ import android.util.Log;
import com.aispeech.nativedemo.DuiApplication;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.network.ws.MessageUtils;
import com.aispeech.nativedemo.rtasr.RTASRZXManager;
import com.aispeech.nativedemo.rtasr.RecognizerExtendResult;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
@@ -21,34 +23,34 @@ import org.json.JSONObject;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.TimeZone;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

public class IatManager {
public static final String ASR_ERROR = "ASR_ERROR";
private static String TAG = IatManager.class.getSimpleName();
private static IatManager mInstance;
private Context mContext;
private SpeechRecognizer mIat;
private StringBuffer buffer = new StringBuffer();
private HashMap<String, String> mIatResults = new LinkedHashMap<>();
private HashMap<String, String> mIatZXResults = new LinkedHashMap<>();
private String resultType = "json";
private String language = "zh_cn";
private String mEngineType = SpeechConstant.TYPE_CLOUD;

int ret = 0; // 函数调用返回值
String mTime;
private ConcurrentHashMap<String, AsrResult> mTimeStrMap = new ConcurrentHashMap<>();

private ConcurrentLinkedQueue<String> mTimeList = new ConcurrentLinkedQueue();
private volatile boolean mIsAsring;

private volatile RTASRZXManager mRTASR;

private IatManager(Context context) {
mContext = context;
initIat();
@@ -67,6 +69,8 @@ public class IatManager {

private void initIat(){
mIat = SpeechRecognizer.createRecognizer(mContext, mInitListener);
mRTASR = new RTASRZXManager();
mRTASR.startBackgroundThread();
}

private InitListener mInitListener = new InitListener() {
@@ -123,11 +127,10 @@ public class IatManager {
// mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, mContext.getExternalFilesDir("msc").getAbsolutePath() + "/iat.wav");
}

int ret = 0; // 函数调用返回值

public void executeStream(String filePath) {
buffer.setLength(0);
mIatResults.clear();
mIatZXResults.clear();
// 设置参数
setParam();
// 设置音频来源为外部文件
@@ -141,7 +144,7 @@ public class IatManager {
return;
}
try (FileInputStream open = new FileInputStream(filePath)) {
// InputStream open = getAssets().open("iattest.wav");
//InputStream open = getAssets().open("iattest.wav");
byte[] buff = new byte[1280];
while (open.available() > 0) {
int read = open.read(buff);
@@ -154,12 +157,67 @@ public class IatManager {
}
}


public boolean executeStreamByte(String time, List<byte[]> buffs) {
if (mIsAsring) {
Log.e("testkd", "asr vad listsize " + mTimeList.size() + " isArs " + mIsAsring);
return false;
}
// 也可以像以下这样直接设置音频文件路径识别(要求设置文件在sdcard上的全路径):
// mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-2");
// mIat.setParameter(SpeechConstant.ASR_SOURCE_PATH, "sdcard/XXX/XXX.pcm");
//if (!mIat.isListening())
{
Log.e("testkd", "start listen " + Thread.currentThread() + " buffer size " + buffs.size());
buffer.setLength(0);
mIatResults.clear();
mIatZXResults.clear();
// 设置参数
setParam();
// 设置音频来源为外部文件
mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");
ret = mIat.startListening(mRecognizerListener);
if (ret != ErrorCode.SUCCESS) {
Logger.e("djTtsTime-" + "识别失败,错误码:" + ret + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
return true;
}
}
for (byte[] buff: buffs) {
mIat.writeAudio(buff, 0, buff.length);
}
mIat.stopListening();
mTime = time;
mTimeList.offer(time);
mTimeStrMap.put(String.valueOf(mTime), new AsrResult());
if (mTimeList.size() > 1) {
Log.e("testtest", "asr vad listsize " + mTimeList.size());
}
return true;
}

public boolean executeStreamZXByte(String time, List<byte[]> buffs) {
if (mIsAsring) {
Log.e("testkd", "asr vad listsize " + mTimeList.size() + " isArs " + mIsAsring);
return false;
}
mIatZXResults.clear();
mRTASR.startAsr(buffs, mRecognizerZXListener);
mTime = time;
mTimeList.offer(time);
mTimeStrMap.put(String.valueOf(mTime), new AsrResult());
if (mTimeList.size() > 1) {
Log.e("testtest", "asr vad listsize " + mTimeList.size());
}
return true;
}

private RecognizerListener mRecognizerListener = new RecognizerListener() {

@Override
public void onBeginOfSpeech() {
// 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
Logger.e("djTtsTime-" + "开始说话");
Log.e("testkd", "listen begin ");
}

@Override
@@ -167,27 +225,41 @@ public class IatManager {
// Tips:
// 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
Logger.e("djTtsTime-" + "onError " + error.getPlainDescription(true));
mIsAsring = false;
onAsrResult(ASR_ERROR);
Log.e("testkd", "listen error " + error.getErrorCode());
}

@Override
public void onEndOfSpeech() {
// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
Logger.e("djTtsTime-" + "结束说话");
mIsAsring = true;

Log.e("testkd", "listen end");
}

@Override
public void onResult(RecognizerResult results, boolean isLast) {
mIsAsring = false;
Logger.e(results.getResultString());
if (resultType.equals("json")) {
printResult(results);
if (isLast) {
Logger.e("djTtsTime-" + "onResult 结束");
StringBuffer resultBuffer = new StringBuffer();
//resultBuffer.append("科大讯飞转写结果: ");
for (String key : mIatResults.keySet()) {
resultBuffer.append(mIatResults.get(key));
}
String res = resultBuffer.toString();
MessageUtils.sendAsrText(res);
//MessageUtils.sendAsrText(res);
if (TextUtils.isEmpty(res)) {
res = ASR_ERROR;
}
onAsrResult(res);
Log.e("testkd", "讯飞实时听写 last result " + res + " time " + mTime);
Logger.e( "djASR-讯飞实时听写: "+ res);
Logger.e("djTtsTime-" + "ASR转写结果: " + res);
}
return;
@@ -195,6 +267,7 @@ public class IatManager {
if (resultType.equals("plain")) {
buffer.append(results.getResultString());
Logger.e("djTtsTime-" + "听写结果: " + buffer.toString());
Log.e("testkd", "plain " + buffer.toString());
}
}

@@ -214,6 +287,96 @@ public class IatManager {
}
};

private RecognizerListener mRecognizerZXListener = new RecognizerListener() {

@Override
public void onBeginOfSpeech() {
// 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
Logger.e("djTtsTime-" + "开始说话");
Log.e("testkd", "listen begin ");
}

@Override
public void onError(SpeechError error) {
// Tips:
// 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
Logger.e("djTtsTime-" + "onError " + error.getPlainDescription(true));
mIsAsring = false;
onAsrResult(ASR_ERROR);
Log.e("testkd", "listen error " + error.getErrorCode());
}

@Override
public void onEndOfSpeech() {
// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
Logger.e("djTtsTime-" + "结束说话");
mIsAsring = true;

Log.e("testkd", "listen end");
}

@Override
public void onResult(RecognizerResult results, boolean isLast) {
mIsAsring = false;
Logger.e(results.getResultString());
printResultZX(results);
if (isLast) {
Logger.e("djTtsTime-" + "onResult 结束");
StringBuffer resultBuffer = new StringBuffer();
//resultBuffer.append("科大讯飞转写结果: ");
for (String key : mIatZXResults.keySet()) {
resultBuffer.append(mIatZXResults.get(key));
}
String res = resultBuffer.toString();
//MessageUtils.sendAsrText(res);
if (TextUtils.isEmpty(res)) {
res = ASR_ERROR;
}
onAsrResult(res);

Log.e("testkd", "讯飞实时语音转写 last result " + res + " time " + mTime);
Logger.e("djASR-讯飞实时语音转写: " + res);
}
}

@Override
public void onVolumeChanged(int volume, byte[] data) {
// Logger.e("djTtsTime-" + "当前正在说话,音量大小 = " + volume + " 返回音频数据 = " + data.length);
}

@Override
public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
// 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
// 若使用本地能力,会话id为null
// if (SpeechEvent.EVENT_SESSION_ID == eventType) {
// String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
// Log.d(TAG, "session id =" + sid);
// }
}
};

private void onAsrResult(String res) {
String time = mTimeList.poll();
if (time != null && time.equals(mTime)) {
Log.e("testtest", "time is equal ");
}
if (mTime == null) {
Log.e("testkd", "res " + res + " mtime is null");
}
AsrResult result = mTimeStrMap.get(mTime);
if (result != null) {
result.asr = res;
if (result.asrMessageItem != null) {
MessageUtils.sendXFASRResult(result.asrMessageItem.sessionId, res, mTime);
} else if (!TextUtils.isEmpty(res)){
MessageUtils.sendXFASRResult("", res, mTime);
}
removeAsr(mTime);
} else {
Log.e("testtest", "result is null ");
}
}

private void printResult(RecognizerResult results) {
// String text = JsonParser.parseIatResult(results.getResultString());
// String sn = null;
@@ -238,9 +401,11 @@ public class IatManager {
sn = resultJson.optString("sn");
pgs = resultJson.optString("pgs");
rg = resultJson.optString("rg");
Log.e("testkd", resultJson.toString());
} catch (JSONException e) {
e.printStackTrace();
}

//如果pgs是rpl就在已有的结果中删除掉要覆盖的sn部分
if (pgs.equals("rpl")) {
String[] strings = rg.replace("[", "").replace("]", "").split(",");
@@ -253,4 +418,35 @@ public class IatManager {

mIatResults.put(sn, text);
}

private void printResultZX(RecognizerResult results) {
if (results instanceof RecognizerExtendResult) {
String text = results.getResultString();
int segId = ((RecognizerExtendResult) results).seg_id;
mIatZXResults.put(String.valueOf(segId), text);
}

}

public String getASRStr(String mTime) {
AsrResult result = mTimeStrMap.get(mTime);
if (result == null) {
return null;
}
return result.asr;
}

public AsrResult getASRResult(String mTime) {
AsrResult result = mTimeStrMap.get(mTime);
return result;
}

public String pollASRStr() {
String time = mTimeList.poll();
return getASRStr(String.valueOf(time));
}

public void removeAsr(String key) {
mTimeStrMap.remove(key);
}
}

+ 5
- 0
app/src/main/java/com/aispeech/nativedemo/log/LogFile.java ファイルの表示

@@ -40,6 +40,11 @@ public class LogFile {
return saveFile(logMessage,"tts-total-time-");
}

public static String saveDjTtsASRFile(String logMessage) {
logMessage = logMessage.replace("djASR-", "");
return saveFile(logMessage,"asr-");
}

/**
* 保存日志文件
* @param logMessage 日志消息


+ 2
- 0
app/src/main/java/com/aispeech/nativedemo/log/LoggerPrinter.java ファイルの表示

@@ -381,6 +381,8 @@ final class LoggerPrinter implements Printer {
LogFile.saveDjLogMessageFile(chunk);
} else if(chunk.contains("djTtsTime")){
LogFile.saveDjTtsTimeFile(chunk);
} else if (chunk.contains("djASR")) {
LogFile.saveDjTtsASRFile(chunk);
} else{
LogFile.saveLogMessageFile(chunk);
}


+ 4
- 3
app/src/main/java/com/aispeech/nativedemo/music/PlayerActivity.java ファイルの表示

@@ -25,9 +25,10 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.aispeech.nativedemo.R;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.Target;
import com.google.android.material.navigation.NavigationView;
import com.google.gson.Gson;
import com.squareup.picasso.Picasso;

import org.json.JSONObject;

@@ -126,9 +127,9 @@ public class PlayerActivity extends AppCompatActivity {
Observable.just("")
.observeOn(Schedulers.io())
.subscribe(o -> {
Bitmap bitmap = Picasso.get().load(player.getCurrentMusic().getImageUrl()).get();
runOnUiThread(() -> playerAlbum.setImageBitmap(bitmap));

}, throwable -> Log.e(TAG, throwable.getLocalizedMessage(), throwable));
Glide.with(PlayerActivity.this).load(player.getCurrentMusic().getImageUrl()).into(playerAlbum);
} else {
playerAlbum.setImageResource(R.drawable.default_record_album);
}


+ 72
- 8
app/src/main/java/com/aispeech/nativedemo/network/ws/MessageUtils.java ファイルの表示

@@ -1,5 +1,7 @@
package com.aispeech.nativedemo.network.ws;

import static com.aispeech.nativedemo.iat.IatManager.ASR_ERROR;

import android.text.TextUtils;
import android.util.Log;

@@ -15,8 +17,10 @@ import com.aispeech.nativedemo.entity.Model;
import com.aispeech.nativedemo.entity.Skill;
import com.aispeech.nativedemo.face.FaceChatMode;
import com.aispeech.nativedemo.face.IdentityMode;
import com.aispeech.nativedemo.iat.AsrMessageItem;
import com.aispeech.nativedemo.iat.AsrResult;
import com.aispeech.nativedemo.iat.IatManager;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.shape.ShapeManager;
import com.aispeech.nativedemo.utils.StatusUtils;
import com.aispeech.nativedemo.utils.Utils;

@@ -140,7 +144,7 @@ public class MessageUtils {
}
}

public static String sendSkill(String sessionId, String display, String dmInput){
public static String sendSkill(String sessionId, String display, String dmInput, String time){
String readText = "";
try {
JSONObject jo = new JSONObject();
@@ -191,6 +195,7 @@ public class MessageUtils {
}
skillObj.put("sessionId", sessionId);
skillObj.put("dmInput", dmInput);
skillObj.put("time", time);
jo.put("data", skillObj.toString());
sendMessage(jo.toString());
} catch (JSONException e){
@@ -201,7 +206,7 @@ public class MessageUtils {
return readText;
}

public static void sendNlpResult(String sessionId, String display, String dmInput){
public static void sendNlpResult(String sessionId, String display, String dmInput, String time){
if(TextUtils.isEmpty(dmInput)){
return;
}
@@ -212,6 +217,25 @@ public class MessageUtils {
data.put("sessionId", sessionId);
data.put("display", display);
data.put("dmInput", dmInput);
data.put("time", time);
jo.put("data", data.toString());
sendMessage(jo.toString());
} catch (JSONException e){
e.printStackTrace();
}
}

public static void sendXFASRResult(String sessionId, String dmInput, String time){
if(TextUtils.isEmpty(dmInput)){
return;
}
try {
JSONObject jo = new JSONObject();
jo.put("type", "xfASRResult");
JSONObject data = new JSONObject();
data.put("sessionId", sessionId);
data.put("dmInput", dmInput);
data.put("time", time);
jo.put("data", data.toString());
sendMessage(jo.toString());
} catch (JSONException e){
@@ -219,21 +243,50 @@ public class MessageUtils {
}
}

public static void sendAsr(String data){
public static String sendAsrAndGetRecordId(String data, String time){
String recordId = "";
try {
JSONObject jo = new JSONObject(data);
String txt = jo.optString("text", "");
if(!TextUtils.isEmpty(txt)){
DuiMessageObserver.mAsrWord = txt;
if (!TextUtils.isEmpty(txt)) {
JSONObject person = new JSONObject();

JSONObject asrData = new JSONObject();
person.put("type", "asr");
person.put("data", txt);
asrData.put("text", txt);
asrData.put("time", time);
person.put("data", asrData.toString());
sendMessage(person.toString());
// ShapeManager.getInstance().nlpFromNewDevGpt(txt);
}
recordId = jo.optString("recordId", "");
//sendXfMsg(jo, time);
} catch (JSONException e) {
e.printStackTrace();
}
return recordId;
}

public static void sendXfMsg(JSONObject jo, String time) {
String sessionId = jo.optString("sessionId", "");
if (TextUtils.isEmpty(sessionId)) {
return ;
}
AsrResult result = IatManager.getInstance().getASRResult(time);
String asrStr = "";
if (result != null) {
asrStr = result.asr;
}
if (!TextUtils.isEmpty(asrStr)) {
if (ASR_ERROR.equals(asrStr)) {
return;
}
// 直接发送自己的后台获取nlp结果 增加mtime
MessageUtils.sendXFASRResult(sessionId, asrStr, time);
IatManager.getInstance().removeAsr(time);
} else if (result != null) {
String display = jo.optString("display", "");
result.asrMessageItem = new AsrMessageItem(sessionId, display);
}
}

public static void sendAsrText(String data){
@@ -394,4 +447,15 @@ public class MessageUtils {
throw new RuntimeException(e);
}
}

public static void sendSkills(String message){
try {
JSONObject jo = new JSONObject();
jo.put("type", "skillList");
jo.put("data", message);
sendMessage(jo.toString());
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
}

+ 0
- 388
app/src/main/java/com/aispeech/nativedemo/observer/DuiMessageObserver.java ファイルの表示

@@ -1,388 +0,0 @@
package com.aispeech.nativedemo.observer;

import android.content.Intent;
import android.util.Log;

import com.aispeech.dui.dds.DDS;
import com.aispeech.dui.dds.agent.DMTaskCallback;
import com.aispeech.dui.dds.agent.MessageObserver;
import com.aispeech.nativedemo.DuiApplication;
import com.aispeech.nativedemo.bean.MessageBean;
import com.aispeech.nativedemo.bean.WeatherBean;
import com.aispeech.nativedemo.music.PlayerActivity;
import com.aispeech.nativedemo.widget.pageview.utils.HttpUtil;
import com.google.gson.Gson;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;

import okhttp3.MediaType;
import okhttp3.RequestBody;

/**
* 客户端MessageObserver, 用于处理客户端动作的消息响应.
*/
public class DuiMessageObserver implements MessageObserver {
private final String Tag = "DuiMessageObserver";

public DuiMessageObserver() {
mGson = new Gson();
}

public interface MessageCallback {
void onMessage();

void onState(String state);
}

private MessageCallback mMessageCallback;
private LinkedList<MessageBean> mMessageList;
private boolean mIsFirstVar = true;
private boolean mHasvar = false;
private Gson mGson;
private String[] mSubscribeKeys = new String[]{
"sys.dialog.state",
"context.output.text",
"context.input.text",
"context.widget.content",
"context.widget.list",
"context.widget.web",
"context.widget.media",
"context.widget.custom"
};

// 注册当前更新消息
public void regist(MessageCallback messageCallback, LinkedList<MessageBean> msgList) {
mMessageCallback = messageCallback;
mMessageList = msgList;
DDS.getInstance().getAgent().subscribe(mSubscribeKeys, this);
DDS.getInstance().getAgent().setDMTaskCallback(new DMTaskCallback() {
@Override
public JSONObject onDMTaskResult(JSONObject jsonObject, Type type) {
if(type == Type.DM_OUTPUT){
String display = jsonObject.optString("display");
String nlg = jsonObject.optString("nlg");
Log.e(Tag, display);
Log.e(Tag, nlg);
// if(JSONUtils.isJson(display)){
// try {
// JSONObject object = new JSONObject(display);
// String url = object.optString("url");
// String newStr = getMsg(url);
// jsonObject.put("display", newStr);
// jsonObject.put("nlg", newStr);
//
// } catch (JSONException e) {
// throw new RuntimeException(e);
// }
// }
}
return jsonObject;
}
});
}

private String getMsg(String url){
HashMap<String, String> postParam = new HashMap<>();
postParam.put("knowledge", "卫生间");

RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), new JSONObject(postParam).toString());
String result = HttpUtil.post(url, requestBody, null, null);
try {
JSONObject obj = new JSONObject(result);
String extra = obj.optString("extra");
JSONObject resultObj = new JSONObject(extra);
String resultStr = resultObj.optString("result");
// DDS.getInstance().getAgent().getTTSEngine().speak(result, 1);
// DDS.getInstance().getAgent().getTTSEngine().speak(resultStr, 1, "10001", AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
return resultStr;
// clearVar();
// MessageBean bean = new MessageBean();
// bean.setText(resultStr);
// bean.setType(MessageBean.TYPE_OUTPUT);
// mMessageList.add(bean);
// if (mMessageCallback != null) {
// mMessageCallback.onMessage();
// }
// JSONTokener t = new JSONTokener(success);
// JSONObject obj = (JSONObject) t.nextValue();
// int status = -1001001;
// String errMsg = "";
//
// if (obj.has("status")) {
// status = obj.getInt("status");
// }
// if (obj.has("errMsg")) {
// errMsg = obj.getString("errMsg");
// }
//
// if (status == 0) {
//
// } else {
// onFail(errMsg);
// }
} catch (Exception e) {
e.printStackTrace();
}
// HttpUtil.post(url, requestBody, null, new HttpUtil.HttpCallback<String>() {
// @Override
// public void onSuccess(String success) {
// try {
// JSONObject obj = new JSONObject(success);
// String extra = obj.optString("extra");
// JSONObject resultObj = new JSONObject(extra);
// String result = resultObj.optString("result");
//// DDS.getInstance().getAgent().getTTSEngine().speak(result, 1);
// DDS.getInstance().getAgent().getTTSEngine().speak(result, 1, "10001", AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
//
// clearVar();
// MessageBean bean = new MessageBean();
// bean.setText(result);
// bean.setType(MessageBean.TYPE_OUTPUT);
// mMessageList.add(bean);
// if (mMessageCallback != null) {
// mMessageCallback.onMessage();
// }
//// JSONTokener t = new JSONTokener(success);
//// JSONObject obj = (JSONObject) t.nextValue();
//// int status = -1001001;
//// String errMsg = "";
////
//// if (obj.has("status")) {
//// status = obj.getInt("status");
//// }
//// if (obj.has("errMsg")) {
//// errMsg = obj.getString("errMsg");
//// }
////
//// if (status == 0) {
////
//// } else {
//// onFail(errMsg);
//// }
// } catch (Exception e) {
// e.printStackTrace();
// onFail(e.getMessage());
// }
// }
//
// @Override
// public void onFail(String error) {
//
// }
// });
return "";
}

// 注销当前更新消息
public void unregist() {
DDS.getInstance().getAgent().unSubscribe(this);
}

private void clearVar() {
if (mHasvar) {
mMessageList.pollLast();
}
}

@Override
public void onMessage(String message, String data) {
Log.d(Tag, "message : " + message + " data : " + data);
MessageBean bean = null;
switch (message) {
case "context.output.text":
// clearVar();
// bean = new MessageBean();
// String txt = "";
// try {
// JSONObject jo = new JSONObject(data);
// txt = jo.optString("text", "");
// } catch (JSONException e) {
// e.printStackTrace();
// }
// bean.setText(txt);
// bean.setType(MessageBean.TYPE_OUTPUT);
// mMessageList.add(bean);
// if (mMessageCallback != null) {
// mMessageCallback.onMessage();
// }

String txt = "";
try {
JSONObject jo = new JSONObject(data);
txt = jo.optString("text", "");
JSONObject person = new JSONObject();
person.put("type", "chatMessage");
person.put("content", txt);
String person_msg = person.toString();
long time = System.currentTimeMillis();
Date date = new Date(time);
SimpleDateFormat spTime = new SimpleDateFormat("yyyy-MM-dd/HH:mm:ss");//yyyy-MM-dd/HH:mm:ss HH24 hh12
String sT = spTime.format(date);
Log.e(Tag, "sendMsg: " + person_msg + "/" + sT);
// WebSocketManager.getInstance(DuiApplication.getContext()).sendMsg(person_msg);
} catch (JSONException e) {
e.printStackTrace();
}
break;
case "context.input.text":
bean = new MessageBean();
try {
JSONObject jo = new JSONObject(data);
if (jo.has("var")) {
String var = jo.optString("var", "");
if (mIsFirstVar) {
mIsFirstVar = false;
mHasvar = true;
bean.setText(var);
bean.setType(MessageBean.TYPE_INPUT);
mMessageList.add(bean);
if (mMessageCallback != null) {
mMessageCallback.onMessage();
}
} else {
mMessageList.pollLast();
bean.setText(var);
bean.setType(MessageBean.TYPE_INPUT);
mMessageList.add(bean);
if (mMessageCallback != null) {
mMessageCallback.onMessage();
}
}
}
if (jo.has("text")) {
if (mHasvar) {
mMessageList.pollLast();
mHasvar = false;
mIsFirstVar = true;
}
String text = jo.optString("text", "");
bean.setText(text);
bean.setType(MessageBean.TYPE_INPUT);
mMessageList.add(bean);
if (mMessageCallback != null) {
mMessageCallback.onMessage();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
break;
case "context.widget.content":
bean = new MessageBean();
try {
JSONObject jo = new JSONObject(data);
String title = jo.optString("title", "");
String subTitle = jo.optString("subTitle", "");
String imgUrl = jo.optString("imageUrl", "");
bean.setTitle(title);
bean.setSubTitle(subTitle);
bean.setImgUrl(imgUrl);
bean.setType(MessageBean.TYPE_WIDGET_CONTENT);
mMessageList.add(bean);
if (mMessageCallback != null) {
mMessageCallback.onMessage();
}
} catch (JSONException e) {
e.printStackTrace();
}
break;
case "context.widget.list":
bean = new MessageBean();
try {
JSONObject jo = new JSONObject(data);
JSONArray array = jo.optJSONArray("content");
if (array == null || array.length() == 0) {
return;
}
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.optJSONObject(i);
String title = object.optString("title", "");
String subTitle = object.optString("subTitle", "");
MessageBean b = new MessageBean();
b.setTitle(title);
b.setSubTitle(subTitle);
bean.addMessageBean(b);
}
int currentPage = jo.optInt("currentPage");
bean.setCurrentPage(currentPage);
bean.setType(MessageBean.TYPE_WIDGET_LIST);

int itemsPerPage = jo.optInt("itemsPerPage");
bean.setItemsPerPage(itemsPerPage);

mMessageList.add(bean);

if (mMessageCallback != null) {
mMessageCallback.onMessage();
}
} catch (JSONException e) {
e.printStackTrace();
}
break;
case "context.widget.web":
bean = new MessageBean();
try {
JSONObject jo = new JSONObject(data);
String url = jo.optString("url");
bean.setUrl(url);
bean.setType(MessageBean.TYPE_WIDGET_WEB);
mMessageList.add(bean);
if (mMessageCallback != null) {
mMessageCallback.onMessage();
}
} catch (JSONException e) {
e.printStackTrace();
}
break;
case "context.widget.custom":
bean = new MessageBean();
try {
JSONObject jo = new JSONObject(data);
String name = jo.optString("name");
if (name.equals("weather")) {
bean.setWeatherBean(mGson.fromJson(data, WeatherBean.class));
bean.setType(MessageBean.TYPE_WIDGET_WEATHER);
mMessageList.add(bean);
if (mMessageCallback != null) {
mMessageCallback.onMessage();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
break;
case "context.widget.media":
JSONObject jsonObject;
int count = 0;
String name = "";
try {
jsonObject = new JSONObject(data);
count = jsonObject.optInt("count");
name = jsonObject.optString("widgetName");
} catch (JSONException e) {
e.printStackTrace();
}
if (count > 0) {
Intent intent = new Intent(DuiApplication.getContext(), PlayerActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("data", data);
DuiApplication.getContext().startActivity(intent);
}
break;
case "sys.dialog.state":
if (mMessageCallback != null) {
mMessageCallback.onState(data);
}
break;
default:
}
}

}

+ 31
- 0
app/src/main/java/com/aispeech/nativedemo/rtasr/DraftWithOrigin.java ファイルの表示

@@ -0,0 +1,31 @@
package com.aispeech.nativedemo.rtasr;

import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ClientHandshakeBuilder;

import com.sun.istack.internal.NotNull;

@SuppressWarnings("deprecation")
public class DraftWithOrigin extends Draft_6455 {

private String originUrl;

public DraftWithOrigin(String originUrl) {
this.originUrl = originUrl;
}

@Override
public Draft copyInstance() {
System.out.println(originUrl);
return new DraftWithOrigin(originUrl);
}

@NotNull
@Override
public ClientHandshakeBuilder postProcessHandshakeRequestAsClient(@NotNull ClientHandshakeBuilder request) {
super.postProcessHandshakeRequestAsClient(request);
request.put("Origin", originUrl);
return request;
}
}

+ 340
- 0
app/src/main/java/com/aispeech/nativedemo/rtasr/RTASRTestJSON.java ファイルの表示

@@ -0,0 +1,340 @@
package com.aispeech.nativedemo.rtasr;

import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;

import com.aispeech.nativedemo.rtasr.util.EncryptUtil;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.SpeechError;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
* 实时转写调用demo
* 此demo只是一个简单的调用示例,不适合用到实际生产环境中
*
* @author white
*
*/
public class RTASRTestJSON {

// appid
private static final String APPID = "948cf4b6";

// appid对应的secret_key
private static final String SECRET_KEY = "fe5032b61525baa92d4d0baf1bb18713";

// 请求地址
private static final String HOST = "rtasr.xfyun.cn/v1/ws";

private static final String BASE_URL = "wss://" + HOST;

private static final String ORIGIN = "https://" + HOST;


private static final String BASE_HTTP_URL = "ws://" + HOST;

private static final String ORIGIN_HTTP = "http://" + HOST;

// 音频文件路径
private static final String AUDIO_PATH = "./resource/test_1.pcm";

// 每次发送的数据大小 1280 字节
private static final int CHUNCKED_SIZE = 1280;

private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS");
private static final String HANDLE_THREAD_NAME = "RTASR";
private static RecognizerListener mRecognizerListener;
private static List<byte[]> buffs;
private HandlerThread backgroundThread;
private Handler backgroundHandler;

private final Runnable asrRunnable = new Runnable() {
@Override
public void run() {
try {
testAsr();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};


public void startBackgroundThread() {
backgroundThread = new HandlerThread(HANDLE_THREAD_NAME);
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
}

public void startAsr(List<byte[]> buffs, RecognizerListener recognizerListener) {
mRecognizerListener = recognizerListener;
this.buffs = buffs;
backgroundHandler.post(asrRunnable);
}

public static void testAsr() throws Exception {
while (true) {
URI url = new URI(BASE_URL + getHandShakeParams(APPID, SECRET_KEY));
DraftWithOrigin draft = new DraftWithOrigin(ORIGIN);
CountDownLatch handshakeSuccess = new CountDownLatch(1);
CountDownLatch connectClose = new CountDownLatch(1);
MyWebSocketClient client = new MyWebSocketClient(url, draft, handshakeSuccess, connectClose);
client.connect();
while (!client.getReadyState().equals(ReadyState.OPEN)) {
System.out.println(getCurrentTimeStr() + "\t连接中");
Thread.sleep(1000);
}
// 等待握手成功
handshakeSuccess.await();
System.out.println(sdf.format(new Date()) + " 开始发送音频数据");
// 发送音频
//byte[] bytes = new byte[CHUNCKED_SIZE];
{
int len = -1;
long lastTs = 0;
for ( byte[] buff: buffs) {
if (len < CHUNCKED_SIZE) {
//bytes = Arrays.copyOfRange(bytes, 0, len)
//send(client, );
//break;
}

long curTs = System.currentTimeMillis();
if (lastTs == 0) {
lastTs = System.currentTimeMillis();
} else {
long s = curTs - lastTs;
if (s < 40) {
System.out.println("error time interval: " + s + " ms");
}
}
send(client, buff);
// 每隔40毫秒发送一次数据
Thread.sleep(40);
}
// 发送结束标识
send(client,"{\"end\": true}".getBytes());
System.out.println(getCurrentTimeStr() + "\t发送结束标识完成");
}

// 等待连接关闭
connectClose.await();
break;
}
}

// 生成握手参数
public static String getHandShakeParams(String appId, String secretKey) {
String ts = System.currentTimeMillis()/1000 + "";
String signa = "";
try {
signa = EncryptUtil.HmacSHA1Encrypt(EncryptUtil.MD5(appId + ts), secretKey);
return "?appid=" + appId + "&ts=" + ts + "&signa=" + URLEncoder.encode(signa, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}

return "";
}

public static void send(WebSocketClient client, byte[] bytes) {
if (client.isClosed()) {
throw new RuntimeException("client connect closed!");
}

client.send(bytes);
}

public static String getCurrentTimeStr() {
return sdf.format(new Date());
}

public static class MyWebSocketClient extends WebSocketClient {

private CountDownLatch handshakeSuccess;
private CountDownLatch connectClose;

public MyWebSocketClient(URI serverUri, Draft protocolDraft, CountDownLatch handshakeSuccess, CountDownLatch connectClose) {
super(serverUri, protocolDraft);
this.handshakeSuccess = handshakeSuccess;
this.connectClose = connectClose;
if(serverUri.toString().contains("wss")){
trustAllHosts(this);
}
}

@Override
public void onOpen(ServerHandshake handshake) {
System.out.println(getCurrentTimeStr() + "\t连接建立成功!");
}

@Override
public void onMessage(String msg) {
try {
JSONTokener tokener = new JSONTokener(msg);
JSONObject msgObj = new JSONObject(tokener);
String action = msgObj.getString("action");
if (Objects.equals("started", action)) {
// 握手成功
System.out.println(getCurrentTimeStr() + "\t握手成功!sid: " + msgObj.getString("sid"));
handshakeSuccess.countDown();
} else if (Objects.equals("result", action)) {
// 转写结果
String result = getContent(msgObj.getString("data"));
Log.e("testkd", "zx json" + msgObj);
Log.e("testkd", "zx " + result);
System.out.println(getCurrentTimeStr() + "\tresult: " + result);
if (mRecognizerListener != null) {
mRecognizerListener.onError(new SpeechError(100, msg));
}
} else if (Objects.equals("error", action)) {
// 连接发生错误
System.out.println("Error: " + msg);
//System.exit(0);
if (mRecognizerListener != null) {
mRecognizerListener.onError(new SpeechError(100, msg));
}
}
} catch (Exception e) {

}
}

@Override
public void onError(Exception e) {
System.out.println(getCurrentTimeStr() + "\t连接发生错误:" + e.getMessage() + ", " + new Date());
e.printStackTrace();
System.exit(0);
}

@Override
public void onClose(int arg0, String arg1, boolean arg2) {
System.out.println(getCurrentTimeStr() + "\t链接关闭");
connectClose.countDown();
}

@Override
public void onMessage(ByteBuffer bytes) {
try {
System.out.println(getCurrentTimeStr() + "\t服务端返回:" + new String(bytes.array(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}

public void trustAllHosts(MyWebSocketClient appClient) {
System.out.println("wss");
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}

@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub

}

@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub

}
}};

try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
appClient.setSocket(sc.getSocketFactory().createSocket());
} catch (Exception e) {
e.printStackTrace();
}
}
}

public static String getContent(String message) {
StringBuffer resultBuilder = new StringBuffer();
try {

JSONTokener tokener = new JSONTokener(message);
JSONObject messageObj = new JSONObject(tokener);
JSONObject cn = messageObj.getJSONObject("cn");
JSONObject st = cn.getJSONObject("st");
JSONArray rtArr = st.getJSONArray("rt");
for (int i = 0; i < rtArr.length(); i++) {
JSONObject rtArrObj = rtArr.getJSONObject(i);
JSONArray wsArr = rtArrObj.getJSONArray("ws");
for (int j = 0; j < wsArr.length(); j++) {
JSONObject wsArrObj = wsArr.getJSONObject(j);
JSONArray cwArr = wsArrObj.getJSONArray("cw");
for (int k = 0; k < cwArr.length(); k++) {
JSONObject cwArrObj = cwArr.getJSONObject(k);
String wStr = cwArrObj.getString("w");
resultBuilder.append(wStr);
}
}
}
} catch (Exception e) {
return message;
}

return resultBuilder.toString();
}

// 把转写结果解析为句子
// public static String getContent(String message) {
// StringBuffer resultBuilder = new StringBuffer();
// try {
// JSONObject messageObj = JSON.parseObject(message);
// JSONObject cn = messageObj.getJSONObject("cn");
// JSONObject st = cn.getJSONObject("st");
// JSONArray rtArr = st.getJSONArray("rt");
// for (int i = 0; i < rtArr.size(); i++) {
// JSONObject rtArrObj = rtArr.getJSONObject(i);
// JSONArray wsArr = rtArrObj.getJSONArray("ws");
// for (int j = 0; j < wsArr.size(); j++) {
// JSONObject wsArrObj = wsArr.getJSONObject(j);
// JSONArray cwArr = wsArrObj.getJSONArray("cw");
// for (int k = 0; k < cwArr.size(); k++) {
// JSONObject cwArrObj = cwArr.getJSONObject(k);
// String wStr = cwArrObj.getString("w");
// resultBuilder.append(wStr);
// }
// }
// }
// } catch (Exception e) {
// return message;
// }
//
// return resultBuilder.toString();
// }
}

+ 344
- 0
app/src/main/java/com/aispeech/nativedemo/rtasr/RTASRZXManager.java ファイルの表示

@@ -0,0 +1,344 @@
package com.aispeech.nativedemo.rtasr;

import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.handshake.ServerHandshake;

import com.aispeech.nativedemo.rtasr.util.EncryptUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.SpeechError;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
* 实时转写调用demo
* 此demo只是一个简单的调用示例,不适合用到实际生产环境中
*
* @author white
*/
public class RTASRZXManager {

// appid
private static final String APPID = "948cf4b6";

// appid对应的secret_key
private static final String SECRET_KEY = "fe5032b61525baa92d4d0baf1bb18713";

// 请求地址
private static final String HOST = "rtasr.xfyun.cn/v1/ws";

private static final String BASE_URL = "wss://" + HOST;

private static final String ORIGIN = "https://" + HOST;


private static final String BASE_HTTP_URL = "ws://" + HOST;

private static final String ORIGIN_HTTP = "http://" + HOST;

// 音频文件路径
private static final String AUDIO_PATH = "./resource/test_1.pcm";

// 每次发送的数据大小 1280 字节
private static final int CHUNCKED_SIZE = 1280;

private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS");
private static final String HANDLE_THREAD_NAME = "RTASR";
private static MyWebSocketClient mWebSocketClient;
private static URI url;
private static DraftWithOrigin draft;
private ConcurrentLinkedQueue<RecognizerListener> mRecognizerListenerList = new ConcurrentLinkedQueue<>();
private ConcurrentLinkedQueue<List<byte[]>> buffsList = new ConcurrentLinkedQueue<>();
private HandlerThread backgroundThread;
private Handler backgroundHandler;

private final Runnable asrRunnable = new Runnable() {
@Override
public void run() {
List<byte[]> bytesList = buffsList.poll();
RecognizerListener recognizerListener = mRecognizerListenerList.poll();
try {
if (bytesList != null && recognizerListener != null) {
testAsr(bytesList, recognizerListener);
}
} catch (Exception e) {
Log.e("testkd", "zx " + e.getMessage());
if (recognizerListener != null) {
recognizerListener.onError(new SpeechError(400, "socket is closed"));
}
}
}
};


public void startBackgroundThread() {
backgroundThread = new HandlerThread(HANDLE_THREAD_NAME);
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
}

public void startAsr(List<byte[]> buffs, RecognizerListener recognizerListener) {
mRecognizerListenerList.offer(recognizerListener);
buffsList.offer(buffs);
backgroundHandler.post(asrRunnable);
}

public static void testAsr(List<byte[]> buffs, RecognizerListener recognizerListener) throws Exception {
while (true) {
//if (mWebSocketClient == null || mWebSocketClient.isClosed() || mWebSocketClient.isClosing())

url = new URI(BASE_URL + getHandShakeParams(APPID, SECRET_KEY));
draft = new DraftWithOrigin(ORIGIN);
CountDownLatch handshakeSuccess = new CountDownLatch(1);
CountDownLatch connectClose = new CountDownLatch(1);
mWebSocketClient = new MyWebSocketClient(url, draft, handshakeSuccess, connectClose, recognizerListener);

mWebSocketClient.connect();

int count = 0;
while (!mWebSocketClient.getReadyState().equals(ReadyState.OPEN)) {
System.out.println(getCurrentTimeStr() + "\t连接中");

Log.e("testkd", "zx " + "连接中" + Thread.currentThread());
Thread.sleep(1000);
if (count > 20) {
throw new RuntimeException("client connect error");
}
count++;
}

// 等待握手成功
handshakeSuccess.await();

System.out.println(sdf.format(new Date()) + " 开始发送音频数据");
// 发送音频
//byte[] bytes = new byte[CHUNCKED_SIZE];
{
int len = -1;
long lastTs = 0;
for (byte[] buff : buffs) {
if (len < CHUNCKED_SIZE) {
//bytes = Arrays.copyOfRange(bytes, 0, len)
//send(client, );
//break;
}

long curTs = System.currentTimeMillis();
if (lastTs == 0) {
lastTs = System.currentTimeMillis();
} else {
long s = curTs - lastTs;
if (s < 40) {
System.out.println("error time interval: " + s + " ms");
}
}
send(mWebSocketClient, buff);
// 每隔40毫秒发送一次数据'
Thread.sleep(40);
}

// 发送结束标识
send(mWebSocketClient, "{\"end\": true}".getBytes());
System.out.println(getCurrentTimeStr() + "\t发送结束标识完成");
}

// 等待连接关闭
connectClose.await();
break;
}
}

// 生成握手参数
public static String getHandShakeParams(String appId, String secretKey) {
String ts = System.currentTimeMillis() / 1000 + "";
String signa = "";
try {
signa = EncryptUtil.HmacSHA1Encrypt(EncryptUtil.MD5(appId + ts), secretKey);
return "?appid=" + appId + "&ts=" + ts + "&signa=" + URLEncoder.encode(signa, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}

return "";
}

public static void send(WebSocketClient client, byte[] bytes) {
if (client.isClosed()) {
throw new RuntimeException("client connect closed!");
}

client.send(bytes);
}

public static String getCurrentTimeStr() {
return sdf.format(new Date());
}

public static class MyWebSocketClient extends WebSocketClient {

private CountDownLatch handshakeSuccess;
private CountDownLatch connectClose;

private RecognizerListener recognizerListener;

public MyWebSocketClient(URI serverUri, Draft protocolDraft, CountDownLatch handshakeSuccess, CountDownLatch connectClose, RecognizerListener recognizerListener) {
super(serverUri, protocolDraft);
this.handshakeSuccess = handshakeSuccess;
this.connectClose = connectClose;
this.recognizerListener = recognizerListener;
if (serverUri.toString().contains("wss")) {
trustAllHosts(this);
}
}

@Override
public void onOpen(ServerHandshake handshake) {
Log.e("testkd", "zx " + "连接建立成功!");
}

@Override
public void onMessage(String msg) {
JSONObject msgObj = JSON.parseObject(msg);
String action = msgObj.getString("action");
if (Objects.equals("started", action)) {
// 握手成功
System.out.println(getCurrentTimeStr() + "\t握手成功!sid: " + msgObj.getString("sid"));
handshakeSuccess.countDown();
} else if (Objects.equals("result", action)) {
// 转写结果
String result = getContent(msgObj.getString("data"), recognizerListener);
Log.e("testkd", "zx json" + msgObj);
Log.e("testkd", "zx " + result);
System.out.println(getCurrentTimeStr() + "\tresult: " + result);
} else if (Objects.equals("error", action)) {
// 连接发生错误
System.out.println("Error: " + msg);
//System.exit(0);
if (recognizerListener != null) {
recognizerListener.onError(new SpeechError(100, msg));
}
}
}

@Override
public void onError(Exception e) {
System.out.println(getCurrentTimeStr() + "\t连接发生错误:" + e.getMessage() + ", " + new Date());
Log.e("testkd", "zx " + "连接发生错误:" + e.getMessage() + ", " + new Date());
e.printStackTrace();
if (recognizerListener != null) {
recognizerListener.onError(new SpeechError(100, e.getMessage()));
}
}

@Override
public void onClose(int arg0, String arg1, boolean arg2) {
System.out.println(getCurrentTimeStr() + "\t链接关闭");
Log.e("testkd", "zx " + "链接关闭");

connectClose.countDown();
}

@Override
public void onMessage(ByteBuffer bytes) {
try {
System.out.println(getCurrentTimeStr() + "\t服务端返回:" + new String(bytes.array(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}

public void trustAllHosts(MyWebSocketClient appClient) {
System.out.println("wss");
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}

@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub

}

@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub

}
}};

try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
appClient.setSocket(sc.getSocketFactory().createSocket());
} catch (Exception e) {
e.printStackTrace();
}
}
}

// 把转写结果解析为句子
public static String getContent(String message, RecognizerListener recognizerListener) {
StringBuffer resultBuilder = new StringBuffer();
boolean isLast = false;
int segId = 0;
String type = "";
try {
JSONObject messageObj = JSON.parseObject(message);
isLast = messageObj.getBoolean("ls");
segId = messageObj.getIntValue("seg_id");
JSONObject cn = messageObj.getJSONObject("cn");
JSONObject st = cn.getJSONObject("st");
JSONArray rtArr = st.getJSONArray("rt");
type = st.getString("type");
for (int i = 0; i < rtArr.size(); i++) {
JSONObject rtArrObj = rtArr.getJSONObject(i);
JSONArray wsArr = rtArrObj.getJSONArray("ws");
for (int j = 0; j < wsArr.size(); j++) {
JSONObject wsArrObj = wsArr.getJSONObject(j);
JSONArray cwArr = wsArrObj.getJSONArray("cw");
for (int k = 0; k < cwArr.size(); k++) {
JSONObject cwArrObj = cwArr.getJSONObject(k);
String wStr = cwArrObj.getString("w");
resultBuilder.append(wStr);
}
}
}
} catch (Exception e) {
if (recognizerListener != null) {
recognizerListener.onError(new SpeechError(300, e.getMessage()));
}
return message;
}

String result = resultBuilder.toString();
if (recognizerListener != null && "0".equals(type)) {
recognizerListener.onResult(new RecognizerExtendResult(result, segId), isLast);
}
return result;
}
}

+ 21
- 0
app/src/main/java/com/aispeech/nativedemo/rtasr/RecognizerExtendResult.java ファイルの表示

@@ -0,0 +1,21 @@
package com.aispeech.nativedemo.rtasr;

import android.os.Parcel;

import com.iflytek.cloud.RecognizerResult;

public class RecognizerExtendResult extends RecognizerResult {
public int seg_id;
public RecognizerExtendResult(Parcel parcel) {
super(parcel);
}

public RecognizerExtendResult(String str) {
super(str);
}

public RecognizerExtendResult(String str, int segId) {
super(str);
seg_id = segId;
}
}

+ 66
- 0
app/src/main/java/com/aispeech/nativedemo/rtasr/util/EncryptUtil.java ファイルの表示

@@ -0,0 +1,66 @@
package com.aispeech.nativedemo.rtasr.util;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import cz.msebera.android.httpclient.extras.Base64;


public class EncryptUtil {

/**
* 加密数字签名(基于HMACSHA1算法)
*
* @param encryptText
* @param encryptKey
* @return
* @throws SignatureException
*/
public static String HmacSHA1Encrypt(String encryptText, String encryptKey) throws SignatureException {
byte[] rawHmac = null;
try {
byte[] data = encryptKey.getBytes("UTF-8");
SecretKeySpec secretKey = new SecretKeySpec(data, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(secretKey);
byte[] text = encryptText.getBytes("UTF-8");
rawHmac = mac.doFinal(text);
} catch (InvalidKeyException e) {
throw new SignatureException("InvalidKeyException:" + e.getMessage());
} catch (NoSuchAlgorithmException e) {
throw new SignatureException("NoSuchAlgorithmException:" + e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new SignatureException("UnsupportedEncodingException:" + e.getMessage());
}
String oauth = new String(Base64.encodeToString(rawHmac, Base64.DEFAULT));
return oauth;
}

public final static String MD5(String pstr) {
char md5String[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
try {
byte[] btInput = pstr.getBytes();
MessageDigest mdInst = MessageDigest.getInstance("MD5");
mdInst.update(btInput);
byte[] md = mdInst.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) { // i = 0
byte byte0 = md[i]; // 95
str[k++] = md5String[byte0 >>> 4 & 0xf]; // 5
str[k++] = md5String[byte0 & 0xf]; // F
}

return new String(str);
} catch (Exception e) {
return null;
}
}
}

バイナリ
app/src/main/res/drawable-xxhdpi/pic_bg_sp.jpg ファイルの表示

変更前 変更後
幅: 1125  |  高さ: 2985  |  サイズ: 22 KiB

+ 37
- 0
app/src/main/res/drawable/launcher_drawable.xml ファイルの表示

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<!--背景-->
<item>
<bitmap
android:gravity="top"
android:tileMode="clamp"
android:src="@drawable/pic_bg_sp" />
</item>

<!--文字-->
<!-- <item android:bottom="120dp">-->
<!-- <bitmap-->
<!-- android:gravity="center"-->
<!-- android:src="@drawable/pic_text_sp" />-->
<!-- </item>-->

<!--logo-->
<item
android:bottom="0dp">

<bitmap
android:gravity="center"
android:src="@drawable/lt_logo" />
</item>

<!-- <item-->
<!-- android:bottom="88dp"-->
<!-- android:gravity="bottom|center">-->

<!-- <bitmap-->
<!-- android:gravity="bottom|center"-->
<!-- android:src="@drawable/lt_logo" />-->
<!-- </item>-->

</layer-list>

+ 1
- 0
app/src/main/res/layout/activity_launcher.xml ファイルの表示

@@ -7,5 +7,6 @@
android:id="@+id/initView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
/>
</RelativeLayout>

+ 3
- 4
app/src/main/res/layout/view_init.xml ファイルの表示

@@ -7,12 +7,11 @@
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_guide" />
android:background="@drawable/pic_bg_sp" />

<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/lt_logo"
app:layout_constraintDimensionRatio="467:349"
app:layout_constraintBottom_toBottomOf="parent"


+ 1
- 1
app/src/main/res/values/styles.xml ファイルの表示

@@ -4,7 +4,7 @@
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/speed_normal_text_color</item>
<item name="android:windowBackground">@drawable/bg_guide</item>
<item name="android:windowBackground">@drawable/launcher_drawable</item>
</style>

<style name="Dialog" parent="android:style/Theme.Dialog">


読み込み中…
キャンセル
保存