commit 29af9af3998c0147adc6feca5a7ae9c4cf79cc0e Author: JOETION <1322874562@qq.com> Date: Mon Feb 8 10:34:29 2021 +0800 初始化框架,完成扫描回调,语音接口 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..8123d97 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +pda-web \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..f50231d --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..99f004f --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..f5a9999 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..f0934fc --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..d9ada76 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,57 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion 29 + buildToolsVersion "30.0.2" + + defaultConfig { + applicationId "chaoran.business.pda" + minSdkVersion 22 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + signingConfigs { + release { + storeFile file(RELEASE_STOREFILE); + storePassword RELEASE_STORE_PASSWORD; + keyAlias RELEASE_KEY_ALIAS + keyPassword RELEASE_KEY_PASSWORD + } + } + + buildTypes { + release { + minifyEnabled false //是否代码混淆 + multiDexEnabled true //防止方法数量超过65536导致错误 + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + //配置签名 + signingConfig signingConfigs.release + } + } + + //加载动态库 + sourceSets { + main { + jniLibs.srcDir(['libs']) + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + +} +dependencies { + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + //加载jar包 + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.preference:preference:1.1.1' +} \ No newline at end of file diff --git a/app/jni/Android.mk b/app/jni/Android.mk new file mode 100644 index 0000000..f4fb549 --- /dev/null +++ b/app/jni/Android.mk @@ -0,0 +1,26 @@ +# +# Copyright 2009 Cedric Priscal +# +# 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. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +TARGET_PLATFORM := android-3 +LOCAL_MODULE := rockchip +LOCAL_SRC_FILES := rockchip.c +LOCAL_LDLIBS := -llog + +include $(BUILD_SHARED_LIBRARY) diff --git a/app/jni/Application.mk b/app/jni/Application.mk new file mode 100644 index 0000000..850a82e --- /dev/null +++ b/app/jni/Application.mk @@ -0,0 +1 @@ +APP_ABI := armeabi-v7a diff --git a/app/jni/rockchip.c b/app/jni/rockchip.c new file mode 100644 index 0000000..d695bd6 --- /dev/null +++ b/app/jni/rockchip.c @@ -0,0 +1,163 @@ +/* + * Copyright 2009-2011 Cedric Priscal + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "rockchip.h" + +#include "android/log.h" +static const char *TAG="RockChip"; +#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args) +#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args) +#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args) + +static speed_t getBaudrate(jint baudrate) +{ + switch(baudrate) { + case 0: return B0; + case 50: return B50; + case 75: return B75; + case 110: return B110; + case 134: return B134; + case 150: return B150; + case 200: return B200; + case 300: return B300; + case 600: return B600; + case 1200: return B1200; + case 1800: return B1800; + case 2400: return B2400; + case 4800: return B4800; + case 9600: return B9600; + case 19200: return B19200; + case 38400: return B38400; + case 57600: return B57600; + case 115200: return B115200; + case 230400: return B230400; + case 460800: return B460800; + case 500000: return B500000; + case 576000: return B576000; + case 921600: return B921600; + case 1000000: return B1000000; + case 1152000: return B1152000; + case 1500000: return B1500000; + case 2000000: return B2000000; + case 2500000: return B2500000; + case 3000000: return B3000000; + case 3500000: return B3500000; + case 4000000: return B4000000; + default: return -1; + } +} + +/* + * Class: android_serialport_SerialPort + * Method: open + * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; + */ +JNIEXPORT jobject JNICALL Java_chaoran_business_adapter_RockChipAdapter_open + (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags) +{ + int fd; + speed_t speed; + jobject mFileDescriptor; + + /* Check arguments */ + { + speed = getBaudrate(baudrate); + if (speed == -1) { + LOGE("Invalid baudrate"); + return NULL; + } + } + + /* Opening device */ + { + jboolean iscopy; + const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy); + LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags); + fd = open(path_utf, O_RDWR | flags); + LOGD("open() fd = %d", fd); + (*env)->ReleaseStringUTFChars(env, path, path_utf); + if (fd == -1) + { + /* Throw an exception */ + LOGE("Cannot open port"); + return NULL; + } + } + + /* Configure device */ + { + struct termios cfg; + LOGD("Configuring serial port"); + if (tcgetattr(fd, &cfg)) + { + LOGE("tcgetattr() failed"); + close(fd); + return NULL; + } + + cfmakeraw(&cfg); + cfsetispeed(&cfg, speed); + cfsetospeed(&cfg, speed); + + if (tcsetattr(fd, TCSANOW, &cfg)) + { + LOGE("tcsetattr() failed"); + close(fd); + return NULL; + } + } + + /* Create a corresponding file descriptor */ + { + jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor"); + jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "", "()V"); + jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I"); + mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor); + (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd); + } + + return mFileDescriptor; +} + +/* + * Class: cedric_serial_SerialPort + * Method: close + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_chaoran_business_adapter_RockChipAdapter_close + (JNIEnv *env, jobject thiz) +{ + jclass SerialPortClass = (*env)->GetObjectClass(env, thiz); + jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor"); + + jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;"); + jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I"); + + jobject mFd = (*env)->GetObjectField(env, thiz, mFdID); + jint descriptor = (*env)->GetIntField(env, mFd, descriptorID); + + LOGD("close(fd = %d)", descriptor); + close(descriptor); +} + diff --git a/app/jni/rockchip.h b/app/jni/rockchip.h new file mode 100644 index 0000000..138876a --- /dev/null +++ b/app/jni/rockchip.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class chaoran_business_adapter_RockChipAdapter */ + +#ifndef _Included_chaoran_business_adapter_RockChipAdapter +#define _Included_chaoran_business_adapter_RockChipAdapter +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: chaoran_business_adapter_RockChipAdapter + * Method: open + * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; + */ +JNIEXPORT jobject JNICALL Java_chaoran_business_adapter_RockChipAdapter_open + (JNIEnv *, jclass, jstring, jint, jint); + +/* + * Class: chaoran_business_adapter_RockChipAdapter + * Method: close + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_chaoran_business_adapter_RockChipAdapter_close + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/app/libs/armeabi-v7a/libmsc.so b/app/libs/armeabi-v7a/libmsc.so new file mode 100644 index 0000000..e02fc91 Binary files /dev/null and b/app/libs/armeabi-v7a/libmsc.so differ diff --git a/app/libs/armeabi-v7a/librockchip.so b/app/libs/armeabi-v7a/librockchip.so new file mode 100644 index 0000000..fb73b4c Binary files /dev/null and b/app/libs/armeabi-v7a/librockchip.so differ diff --git a/app/libs/flytek.jar b/app/libs/flytek.jar new file mode 100644 index 0000000..e4ed582 Binary files /dev/null and b/app/libs/flytek.jar differ diff --git a/app/libs/idata.jar b/app/libs/idata.jar new file mode 100644 index 0000000..0f4bb38 Binary files /dev/null and b/app/libs/idata.jar differ diff --git a/app/libs/urobo.jar b/app/libs/urobo.jar new file mode 100644 index 0000000..eef7d29 Binary files /dev/null and b/app/libs/urobo.jar differ diff --git a/app/obj/local/armeabi-v7a/librockchip.so b/app/obj/local/armeabi-v7a/librockchip.so new file mode 100644 index 0000000..3bf3f32 Binary files /dev/null and b/app/obj/local/armeabi-v7a/librockchip.so differ diff --git a/app/obj/local/armeabi-v7a/objs/rockchip/rockchip.o b/app/obj/local/armeabi-v7a/objs/rockchip/rockchip.o new file mode 100644 index 0000000..1379d00 Binary files /dev/null and b/app/obj/local/armeabi-v7a/objs/rockchip/rockchip.o differ diff --git a/app/obj/local/armeabi-v7a/objs/rockchip/rockchip.o.d b/app/obj/local/armeabi-v7a/objs/rockchip/rockchip.o.d new file mode 100644 index 0000000..40a88dc --- /dev/null +++ b/app/obj/local/armeabi-v7a/objs/rockchip/rockchip.o.d @@ -0,0 +1,5 @@ +E:/AndroidStudioProject/pda-web/app/obj/local/armeabi-v7a/objs/rockchip/rockchip.o: \ + E:\AndroidStudioProject\pda-web\app\jni\rockchip.c \ + E:\AndroidStudioProject\pda-web\app\jni\rockchip.h + +E:\AndroidStudioProject\pda-web\app\jni\rockchip.h: diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..4ddcbc9 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/tts/common.jet b/app/src/main/assets/tts/common.jet new file mode 100644 index 0000000..a2fdf73 Binary files /dev/null and b/app/src/main/assets/tts/common.jet differ diff --git a/app/src/main/assets/tts/xiaofeng.jet b/app/src/main/assets/tts/xiaofeng.jet new file mode 100644 index 0000000..b3e2066 Binary files /dev/null and b/app/src/main/assets/tts/xiaofeng.jet differ diff --git a/app/src/main/assets/tts/xiaoyan.jet b/app/src/main/assets/tts/xiaoyan.jet new file mode 100644 index 0000000..2d266f5 Binary files /dev/null and b/app/src/main/assets/tts/xiaoyan.jet differ diff --git a/app/src/main/java/chaoran/business/BrandEnum.java b/app/src/main/java/chaoran/business/BrandEnum.java new file mode 100644 index 0000000..bf72553 --- /dev/null +++ b/app/src/main/java/chaoran/business/BrandEnum.java @@ -0,0 +1,46 @@ +package chaoran.business; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-01 FXY Created + ********************************************** + */ + + +public enum BrandEnum { + //枚举名即为valueOf() + UROBO("优博讯", "urobo"), + ROCKCHIP("瑞芯微电子", "rockchip"), + TEST("测试设备", "test"), + IDATA("匿名设备", "idata"), + ALPS("阿尔卑斯", "alps"); + + private String name; + private String code; + + BrandEnum(String name, String code) { + this.name = name; + this.code = code; + } + + /** + * 通过设备型号代码获取设备信息 + * + * @param code + * @return + */ + public static BrandEnum code(String code) { + if (null == code) { + code = new String(); + } + for (BrandEnum brandEnum : values()) { + if (brandEnum.code.equals(code.toLowerCase())) { + return brandEnum; + } + } + return TEST; + } + + +} diff --git a/app/src/main/java/chaoran/business/activity/AboutActivity.java b/app/src/main/java/chaoran/business/activity/AboutActivity.java new file mode 100644 index 0000000..1d8bda0 --- /dev/null +++ b/app/src/main/java/chaoran/business/activity/AboutActivity.java @@ -0,0 +1,27 @@ +package chaoran.business.activity; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-04 FXY Created + ********************************************** + */ + + +import android.os.Bundle; +import android.widget.TextView; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import chaoran.business.R; + +public class AboutActivity extends AppCompatActivity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_about); + setTitle(R.string.activity_about); + TextView textView = findViewById(R.id.about_content); + textView.setText(R.string.activity_about_content); + } +} diff --git a/app/src/main/java/chaoran/business/activity/MainActivity.java b/app/src/main/java/chaoran/business/activity/MainActivity.java new file mode 100644 index 0000000..17090ce --- /dev/null +++ b/app/src/main/java/chaoran/business/activity/MainActivity.java @@ -0,0 +1,128 @@ +package chaoran.business.activity; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import chaoran.business.BrandEnum; +import chaoran.business.R; +import chaoran.business.adapter.*; +import chaoran.business.vioce.TekVoiceEngine; +import chaoran.business.vioce.VoiceEngine; + +/** + * 流程:联网认证设备型号,验证通过,查找设备品牌进行调用驱动操作 + */ + +/** + * 提供文字转语音功能,实时播报PDA状态 + */ +public class MainActivity extends AppCompatActivity implements ResultListener { + + private WebView webView; + private Adapter adapter; + private VoiceEngine voiceEngine; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + initView(); + initData(); + } + + private void initData() { + BrandEnum brand = BrandEnum.code(Build.MANUFACTURER); + Toast.makeText(this, Build.MANUFACTURER, Toast.LENGTH_LONG).show(); + switch (brand) { + case UROBO: + adapter = new UroBoAdapter(this, this); + break; + case ROCKCHIP: + adapter = new RockChipAdapter(this, this); + break; + case IDATA: + adapter = new IDataAdapter(this, this); + break; + case ALPS: + adapter = new AlpsAdapter(this, this); + break; + } + if (null != adapter) { + adapter.start(); + } + } + + @SuppressLint("JavascriptInterface") + private void initView() { + setTitle(R.string.title_activity_main); + voiceEngine = new TekVoiceEngine(this); + webView = findViewById(R.id.webView); + WebSettings settings = webView.getSettings(); + settings.setJavaScriptEnabled(true); + webView.addJavascriptInterface(voiceEngine, "VoiceEngine"); + webView.loadUrl(url()); + } + + @Override + protected void onResume() { + //再次唤醒该页面时,重新加载页面和语音配置 + webView.loadUrl(url()); + voiceEngine.loadParam(); + super.onResume(); + } + + @Override + @SuppressLint("SetJavaScriptEnabled") + public void result(String result) { + runOnUiThread(() -> webView.loadUrl("javascript:render(\'" + result + "\')")); + } + + @Override + protected void onDestroy() { + adapter.stop(); + super.onDestroy(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_main, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case R.id.action_setting_network: + startActivity(new Intent(this, NetworkSettingActivity.class)); + break; + case R.id.action_setting_voice: + startActivity(new Intent(this, VoiceSettingActivity.class)); + break; + case R.id.action_about: + startActivity(new Intent(this, AboutActivity.class)); + break; + } + return super.onOptionsItemSelected(item); + } + + private String url() { + SharedPreferences spf = this.getSharedPreferences("crtech", Context.MODE_PRIVATE); + String address = spf.getString("address", "").replaceAll(" ", ""); + String path = spf.getString("path", "").replaceAll(" ", ""); + Integer port = spf.getInt("port", -1); + String link = address.concat(":").concat(String.valueOf(port)).concat(path); + return link.startsWith("http://") ? link : "http://".concat(link); + } + +} \ No newline at end of file diff --git a/app/src/main/java/chaoran/business/activity/NetworkSettingActivity.java b/app/src/main/java/chaoran/business/activity/NetworkSettingActivity.java new file mode 100644 index 0000000..498df06 --- /dev/null +++ b/app/src/main/java/chaoran/business/activity/NetworkSettingActivity.java @@ -0,0 +1,56 @@ +package chaoran.business.activity; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-02 FXY Created + ********************************************** + */ + + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.widget.Button; +import android.widget.EditText; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import chaoran.business.R; + +public class NetworkSettingActivity extends AppCompatActivity { + + private EditText address, path, port; + private Button save, cancel; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_setting_network); + initView(); + } + + + private void initView() { + address = findViewById(R.id.address); + path = findViewById(R.id.path); + port = findViewById(R.id.port); + save = findViewById(R.id.save); + cancel = findViewById(R.id.cancel); + setTitle(R.string.title_activity_setting_network); + SharedPreferences sharedPreferences = this.getSharedPreferences("crtech", Context.MODE_PRIVATE); + address.setText(sharedPreferences.getString("address", "")); + path.setText(sharedPreferences.getString("path", "")); + port.setText(String.valueOf(sharedPreferences.getInt("port", -1))); + cancel.setOnClickListener((e) -> this.finish()); + save.setOnClickListener((e) -> saveSetting()); + } + + private void saveSetting() { + SharedPreferences.Editor editor = this.getSharedPreferences("crtech", Context.MODE_PRIVATE).edit(); + editor.putString("address", address.getText().toString().trim()); + editor.putString("path", path.getText().toString().trim()); + editor.putInt("port", Integer.parseInt(port.getText().toString().trim())); + editor.commit(); + this.finish(); + } +} diff --git a/app/src/main/java/chaoran/business/activity/ResultListener.java b/app/src/main/java/chaoran/business/activity/ResultListener.java new file mode 100644 index 0000000..01123bf --- /dev/null +++ b/app/src/main/java/chaoran/business/activity/ResultListener.java @@ -0,0 +1,23 @@ +package chaoran.business.activity; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-01 FXY Created + ********************************************** + */ + +/** + * 结果监听器,用于回调结果 + * 调用前端render()函数 + */ +public interface ResultListener { + + /** + * js 调用方法 + * + * @param result + * @return + */ + public void result(String result); +} diff --git a/app/src/main/java/chaoran/business/activity/VoiceSettingActivity.java b/app/src/main/java/chaoran/business/activity/VoiceSettingActivity.java new file mode 100644 index 0000000..e4101fe --- /dev/null +++ b/app/src/main/java/chaoran/business/activity/VoiceSettingActivity.java @@ -0,0 +1,137 @@ +package chaoran.business.activity; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-05 FXY Created + ********************************************** + */ + + +import android.app.Activity; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.widget.*; +import chaoran.business.R; +import chaoran.business.vioce.TekVoiceEngine; +import chaoran.business.vioce.VoiceEngine; + +/** + * 播报语音设置 + */ +public class VoiceSettingActivity extends Activity { + + private EditText testText; + private RadioButton voiceF, voiceY; + private SeekBar voiceSize, voiceSpeed, voiceIndicate; + private Button save, cancel; + private SharedPreferences sharedPreferences; + private RadioGroup voiceMemberGroup; + + private VoiceEngine voiceEngine; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_setting_voice); + initView(); + initData(); + initListener(); + } + + private void initView() { + testText = findViewById(R.id.voice_test_text); + voiceF = findViewById(R.id.voice_member_xiaofeng); + voiceY = findViewById(R.id.voice_member_xiaoyan); + voiceSize = findViewById(R.id.voice_size); + voiceSpeed = findViewById(R.id.voice_speed); + voiceIndicate = findViewById(R.id.voice_indicate); + save = findViewById(R.id.save_voice_setting); + cancel = findViewById(R.id.cancel_voice_setting); + voiceMemberGroup = findViewById(R.id.voice_member_group); + voiceEngine = new TekVoiceEngine(this); + } + + private void initData() { + sharedPreferences = getSharedPreferences("voiceEngine", MODE_PRIVATE); + //设置测试文本 + testText.setText(sharedPreferences.getString("testText", testText.getText().toString())); + //设置播报人员 + String voiceMember = sharedPreferences.getString("voiceMember", "xiaofeng"); + if (voiceMember.equals("xiaofeng")) { + voiceF.setChecked(true); + voiceY.setChecked(false); + } else { + voiceY.setChecked(true); + voiceF.setChecked(false); + } + //设置功能选项 + voiceSize.setProgress(sharedPreferences.getInt("voiceSize", 100)); + voiceSpeed.setProgress(sharedPreferences.getInt("voiceSpeed", 80)); + voiceIndicate.setProgress(sharedPreferences.getInt("voiceIndicate", 50)); + } + + public void initListener() { + SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + //停止播放 + voiceEngine.stopSpeaking(); + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + //播放语音 + voiceEngine.setParam(voiceF.isChecked() ? "xiaofeng" : "xiaoyan", voiceSize.getProgress(), voiceIndicate.getProgress(), voiceSpeed.getProgress()); + voiceEngine.startSpeaking(testText.getText().toString()); + } + }; + voiceSize.setOnSeekBarChangeListener(seekBarChangeListener); + voiceIndicate.setOnSeekBarChangeListener(seekBarChangeListener); + voiceSpeed.setOnSeekBarChangeListener(seekBarChangeListener); + SharedPreferences.Editor editor = sharedPreferences.edit(); + save.setOnClickListener(a -> { + editor.putInt("voiceSize", voiceSize.getProgress()); + editor.putInt("voiceIndicate", voiceIndicate.getProgress()); + editor.putInt("voiceSpeed", voiceSpeed.getProgress()); + editor.putString("testText", testText.getText().toString()); + editor.putString("voiceMember", voiceF.isChecked() ? "xiaofeng" : "xiaoyan"); + editor.commit(); + voiceEngine.stopSpeaking(); + voiceEngine.destroy(); + Toast.makeText(this, "语音配置保存成功!", Toast.LENGTH_SHORT).show(); + this.finish(); + }); + cancel.setOnClickListener(a -> { + voiceEngine.stopSpeaking(); + voiceEngine.destroy(); + this.finish(); + }); + + voiceMemberGroup.setOnCheckedChangeListener((a, b) -> { + //播放语音 + voiceEngine.setParam(voiceF.isChecked() ? "xiaofeng" : "xiaoyan", voiceSize.getProgress(), voiceIndicate.getProgress(), voiceSpeed.getProgress()); + voiceEngine.startSpeaking(testText.getText().toString()); + }); + } + + @Override + protected void onStart() { + super.onStart(); + //初始化加载一次 + voiceEngine.setParam(voiceF.isChecked() ? "xiaofeng" : "xiaoyan", voiceSize.getProgress(), voiceIndicate.getProgress(), voiceSpeed.getProgress()); + voiceEngine.startSpeaking(testText.getText().toString()); + } + + @Override + protected void onDestroy() { + voiceEngine.stopSpeaking(); + voiceEngine.destroy(); + super.onDestroy(); + } +} diff --git a/app/src/main/java/chaoran/business/adapter/Adapter.java b/app/src/main/java/chaoran/business/adapter/Adapter.java new file mode 100644 index 0000000..2613467 --- /dev/null +++ b/app/src/main/java/chaoran/business/adapter/Adapter.java @@ -0,0 +1,32 @@ +package chaoran.business.adapter; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-01 FXY Created + ********************************************** + */ + + +/** + * 适配器基类 + * 同一品牌的设备,不论什么型号,用的是同一个适配器 + * 设备按品牌区分,而不按具体型号区分 + */ +public interface Adapter{ + + /** + * 开始扫描 + * + * @return + */ + public void start(); + + /** + * 结束扫描 + * + * @return + */ + public void stop(); + +} diff --git a/app/src/main/java/chaoran/business/adapter/AlpsAdapter.java b/app/src/main/java/chaoran/business/adapter/AlpsAdapter.java new file mode 100644 index 0000000..c776a94 --- /dev/null +++ b/app/src/main/java/chaoran/business/adapter/AlpsAdapter.java @@ -0,0 +1,65 @@ +package chaoran.business.adapter; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-03 FXY Created + ********************************************** + */ + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.media.AudioManager; +import android.media.SoundPool; +import android.os.Vibrator; +import chaoran.business.R; +import chaoran.business.activity.ResultListener; +import chaoran.business.strategy.Strategy; + +/** + * 阿尔卑斯适配器 + * CR-5W适用 + */ +public class AlpsAdapter implements Adapter { + private Context context; + private Strategy strategy; + private ResultListener resultListener; + + public AlpsAdapter(Context context, ResultListener resultListener) { + this.context = context; + this.resultListener = resultListener; + strategy = new Receiver(); + } + + @Override + public void start() { + strategy.executeStrategy(resultListener); + } + + @Override + public void stop() { + strategy.exclusiveStrategy(); + } + + public class Receiver extends BroadcastReceiver implements Strategy { + + @Override + public void onReceive(Context context, Intent intent) { + resultListener.result(intent.getStringExtra("BARCODE")); + } + + @Override + public void executeStrategy(ResultListener resultListener) { + IntentFilter filter = new IntentFilter(); + filter.addAction("com.barcode.sendBroadcast"); + context.registerReceiver(this, filter); + } + + @Override + public void exclusiveStrategy() { + context.unregisterReceiver(this); + } + } +} diff --git a/app/src/main/java/chaoran/business/adapter/IDataAdapter.java b/app/src/main/java/chaoran/business/adapter/IDataAdapter.java new file mode 100644 index 0000000..bc7fc73 --- /dev/null +++ b/app/src/main/java/chaoran/business/adapter/IDataAdapter.java @@ -0,0 +1,70 @@ +package chaoran.business.adapter; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-02 FXY Created + ********************************************** + */ + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import chaoran.business.activity.ResultListener; +import chaoran.business.strategy.Strategy; +import com.android.barcodescandemo.ScannerInerface; + +/** + * idata 适配器 + */ +public class IDataAdapter implements Adapter { + private Context context; + private ResultListener resultListener; + private Strategy strategy; + + public IDataAdapter(Context context, ResultListener resultListener) { + this.context = context; + this.resultListener = resultListener; + strategy = new Receiver(); + } + + @Override + public void start() { + strategy.executeStrategy(resultListener); + } + + @Override + public void stop() { + strategy.exclusiveStrategy(); + } + + public class Receiver extends BroadcastReceiver implements Strategy { + + private ScannerInerface scannerInerface; + + public Receiver() { + scannerInerface = new ScannerInerface(context); + scannerInerface.setOutputMode(1); + } + + @Override + public void onReceive(Context context, Intent intent) { + resultListener.result(intent.getStringExtra("value")); + } + + @Override + public void executeStrategy(ResultListener resultListener) { + scannerInerface.open(); + IntentFilter filter = new IntentFilter(); + filter.addAction("android.intent.action.SCANRESULT"); + context.registerReceiver(this, filter); + } + + @Override + public void exclusiveStrategy() { + context.unregisterReceiver(this); + scannerInerface.close(); + } + } +} diff --git a/app/src/main/java/chaoran/business/adapter/RockChipAdapter.java b/app/src/main/java/chaoran/business/adapter/RockChipAdapter.java new file mode 100644 index 0000000..be1ead4 --- /dev/null +++ b/app/src/main/java/chaoran/business/adapter/RockChipAdapter.java @@ -0,0 +1,118 @@ +package chaoran.business.adapter; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-01 FXY Created + ********************************************** + */ + + +import android.content.Context; +import android.media.AudioManager; +import android.media.SoundPool; +import android.os.Vibrator; +import chaoran.business.R; +import chaoran.business.activity.ResultListener; +import chaoran.business.strategy.Strategy; + +import java.io.*; + +/** + * 瑞芯适配器 + */ +public class RockChipAdapter implements Adapter { + + private Strategy strategy; + + private ResultListener resultListener; + + private Context context; + + @Override + public void start() { + strategy.executeStrategy(resultListener); + } + + @Override + public void stop() { + strategy.exclusiveStrategy(); + } + + public RockChipAdapter(Context context, ResultListener resultListener) { + this.resultListener = resultListener; + this.context = context; + this.strategy = new Reader(new File("/dev/ttyS1"), 115200, 0); + } + + public class Reader implements Strategy { + private FileDescriptor mFd; + private FileInputStream mFileInputStream; + private boolean running = true; + + public Reader(File device, int baudrate, int flags) { + + if (!device.canRead() || !device.canWrite()) { + try { + Process su; + su = Runtime.getRuntime().exec("/system/bin/su"); + String cmd = "chmod 777 " + device.getAbsolutePath() + "\n" + "exit\n"; + su.getOutputStream().write(cmd.getBytes()); + + if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) { + System.out.println("获取su命令权限失败,系统或许未root!"); + } + } catch (Exception e) { + e.printStackTrace(); + System.out.println("获取root权限失败"); + } + } + mFd = open(device.getAbsolutePath(), baudrate, flags); + if (mFd == null) { + System.out.println("获取文件描述符失败!"); + } + mFileInputStream = new FileInputStream(mFd); + } + + @Override + public void executeStrategy(ResultListener resultListener) { + new Thread(() -> { + while (running) { + String data = data(); + if (!data.equals("")) { + resultListener.result(data); + } + } + }).start(); + } + + @Override + public void exclusiveStrategy() { + running = false; + close(); + } + + private String data() { + if (mFileInputStream == null) return ""; + try { + int size = mFileInputStream.available(); + byte[] buffer = new byte[size]; + size = mFileInputStream.read(buffer); + if (size > 0) { + return new String(buffer); + } + } catch (IOException e) { + e.printStackTrace(); + } + return ""; + } + } + + static { + System.loadLibrary("rockchip"); + } + + private native static FileDescriptor open(String path, int baudrate, int flags); + + public native void close(); +} diff --git a/app/src/main/java/chaoran/business/adapter/TestAdapter.java b/app/src/main/java/chaoran/business/adapter/TestAdapter.java new file mode 100644 index 0000000..342671d --- /dev/null +++ b/app/src/main/java/chaoran/business/adapter/TestAdapter.java @@ -0,0 +1,44 @@ +package chaoran.business.adapter; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-01 FXY Created + ********************************************** + */ + + +import chaoran.business.activity.ResultListener; + +import static java.lang.Thread.sleep; + +public class TestAdapter implements Adapter { + + private ResultListener resultListener; + + public TestAdapter(ResultListener resultListener) { + this.resultListener = resultListener; + } + + @Override + public void start() { + new Thread(() -> { + int i = 0; + while (i < 10) { + resultListener.result(i + ""); + i++; + try { + sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + }).start(); + } + + @Override + public void stop() { + + } +} diff --git a/app/src/main/java/chaoran/business/adapter/UroBoAdapter.java b/app/src/main/java/chaoran/business/adapter/UroBoAdapter.java new file mode 100644 index 0000000..8b1563d --- /dev/null +++ b/app/src/main/java/chaoran/business/adapter/UroBoAdapter.java @@ -0,0 +1,86 @@ +package chaoran.business.adapter; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-01 FXY Created + ********************************************** + */ + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.device.ScanManager; +import android.device.scanner.configuration.Triggering; +import android.media.AudioManager; +import android.media.SoundPool; +import android.os.Vibrator; +import chaoran.business.R; +import chaoran.business.activity.ResultListener; +import chaoran.business.strategy.Strategy; + +/** + * 优博讯适配器 + */ +public class UroBoAdapter implements Adapter { + + private Strategy strategy; + private Context context; + private ResultListener resultListener; + + + public UroBoAdapter(Context context, ResultListener resultListener) { + this.context = context; + this.resultListener = resultListener; + this.strategy = new Receiver(); + } + + @Override + public void start() { + strategy.executeStrategy(resultListener); + } + + @Override + public void stop() { + strategy.exclusiveStrategy(); + } + + /** + * 广播接受者 + * 自省策略 + */ + public class Receiver extends BroadcastReceiver implements Strategy { + + private ScanManager mScanManager; + + public Receiver() { + mScanManager = new ScanManager(); + mScanManager.openScanner(); + mScanManager.switchOutputMode(0); + if (mScanManager.getTriggerMode() != Triggering.CONTINUOUS) + mScanManager.setTriggerMode(Triggering.CONTINUOUS); + } + + @Override + public void onReceive(Context context, Intent intent) { + String barcode = intent.getStringExtra("barcode_string"); + resultListener.result(barcode); + } + + @Override + public void executeStrategy(ResultListener resultListener) { + mScanManager.startDecode(); + IntentFilter filter = new IntentFilter(); + filter.addAction("android.intent.ACTION_DECODE_DATA"); + context.registerReceiver(this, filter); + } + + @Override + public void exclusiveStrategy() { + context.unregisterReceiver(this); + mScanManager.stopDecode(); + } + } + +} diff --git a/app/src/main/java/chaoran/business/application/InitApplication.java b/app/src/main/java/chaoran/business/application/InitApplication.java new file mode 100644 index 0000000..35d8d6e --- /dev/null +++ b/app/src/main/java/chaoran/business/application/InitApplication.java @@ -0,0 +1,28 @@ +package chaoran.business.application; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-08 FXY Created + ********************************************** + */ + + +import android.app.Application; +import chaoran.business.R; +import com.iflytek.cloud.SpeechConstant; +import com.iflytek.cloud.SpeechUtility; + +public class InitApplication extends Application { + @Override + public void onCreate() { + //讯飞离线语音配置 + StringBuffer param = new StringBuffer(); + param.append("appid=" + getString(R.string.app_id)); + param.append(","); + // 设置使用v5+ + param.append(SpeechConstant.ENGINE_MODE + "=" + SpeechConstant.MODE_MSC); + SpeechUtility.createUtility(this, param.toString()); + super.onCreate(); + } +} diff --git a/app/src/main/java/chaoran/business/strategy/Strategy.java b/app/src/main/java/chaoran/business/strategy/Strategy.java new file mode 100644 index 0000000..0d723dd --- /dev/null +++ b/app/src/main/java/chaoran/business/strategy/Strategy.java @@ -0,0 +1,31 @@ +package chaoran.business.strategy; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-01 FXY Created + ********************************************** + */ + +import chaoran.business.activity.ResultListener; + +/** + * 策略接口 + * 普通jar包调用时,此接口没用 + * 此包仅用于调用硬件相关驱动 + */ +public interface Strategy { + + /** + * 执行策略 + * + * @param resultListener + */ + public void executeStrategy(ResultListener resultListener); + + /** + * 排除策略 + */ + public void exclusiveStrategy(); + +} diff --git a/app/src/main/java/chaoran/business/vioce/TekVoiceEngine.java b/app/src/main/java/chaoran/business/vioce/TekVoiceEngine.java new file mode 100644 index 0000000..a09129b --- /dev/null +++ b/app/src/main/java/chaoran/business/vioce/TekVoiceEngine.java @@ -0,0 +1,222 @@ +package chaoran.business.vioce; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.Environment; +import android.util.Log; +import android.webkit.JavascriptInterface; +import android.widget.Toast; +import chaoran.business.R; +import com.iflytek.cloud.*; +import com.iflytek.cloud.util.ResourceUtil; +import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-05 FXY Created + ********************************************** + */ + +public class TekVoiceEngine implements VoiceEngine { + private static String TAG = "TekVoiceEngine"; + // 语音合成对象 + private SpeechSynthesizer mTts; + + //缓冲进度 + private int mPercentForBuffering = 0; + + //播放进度 + private int mPercentForPlaying = 0; + + private Toast mToast; + + private Context context; + + public TekVoiceEngine(Context context) { + this.context = context; + // 初始化合成对象 + mTts = SpeechSynthesizer.createSynthesizer(context, mTtsInitListener); + //设置合成引擎的参数 + loadParam(); + //初始化对话框 + mToast = Toast.makeText(context, "", Toast.LENGTH_SHORT); + } + + @Override + @JavascriptInterface + public void startSpeaking(String text) { + if (null == mTts) { + this.showTip("创建对象失败,请确认 libmsc.so 放置正确,\n 且有调用 createUtility 进行初始化"); + } + + if (mTts.isSpeaking()) + stopSpeaking(); + + int code = mTts.startSpeaking(text, mTtsListener); + if (code != ErrorCode.SUCCESS) { + showTip("语音合成失败,错误码: " + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案"); + } + } + + @Override + @JavascriptInterface + public void stopSpeaking() { + mTts.stopSpeaking(); + } + + + /** + * 初始化监听 + */ + private InitListener mTtsInitListener = code -> { + Log.d(TAG, "InitListener init() code = " + code); + if (code != ErrorCode.SUCCESS) { + showTip("初始化失败,错误码:" + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案"); + } + }; + + /** + * 合成回调监听。 + */ + private SynthesizerListener mTtsListener = new SynthesizerListener() { + + @Override + public void onSpeakBegin() { + Log.d(TAG, "开始播放:" + System.currentTimeMillis()); + } + + @Override + public void onSpeakPaused() { + showTip("暂停播放"); + } + + @Override + public void onSpeakResumed() { + showTip("继续播放"); + } + + @Override + public void onBufferProgress(int percent, int beginPos, int endPos, + String info) { + // 合成进度 + mPercentForBuffering = percent; + showTip(String.format(context.getString(R.string.tts_toast_format), + mPercentForBuffering, mPercentForPlaying)); + } + + @Override + public void onSpeakProgress(int percent, int beginPos, int endPos) { + // 播放进度 + mPercentForPlaying = percent; + showTip(String.format(context.getString(R.string.tts_toast_format), + mPercentForBuffering, mPercentForPlaying)); + } + + @Override + public void onCompleted(SpeechError error) { + if (error == null) { + showTip("播放完成"); + } else if (error != null) { + showTip(error.getPlainDescription(true)); + } + } + + @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_AUDIO_URL); + Log.d(TAG, "session id =" + sid); + } + } + }; + + + public void loadParam() { + + // 装载参数之前,先清空参数 + mTts.setParameter(SpeechConstant.PARAMS, null); + + SharedPreferences sharedPreferences = context.getSharedPreferences("voiceEngine", Context.MODE_PRIVATE); + + //设置使用本地引擎 + mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL); + + //设置发音人资源路径 + String voicerLocal = sharedPreferences.getString("voiceMember", "xiaofeng"); + mTts.setParameter(ResourceUtil.TTS_RES_PATH, getResourcePath(voicerLocal)); + + //设置发音人 + mTts.setParameter(SpeechConstant.VOICE_NAME, voicerLocal); + + //设置合成语速 + mTts.setParameter(SpeechConstant.SPEED, String.valueOf(sharedPreferences.getInt("voiceSpeed", 80))); + + //设置合成音调 + mTts.setParameter(SpeechConstant.PITCH, String.valueOf(sharedPreferences.getInt("voiceIndicate", 50))); + + //设置合成音量 + mTts.setParameter(SpeechConstant.VOLUME, String.valueOf(sharedPreferences.getInt("voiceSize", 100))); + + //设置播放器音频流类型 + mTts.setParameter(SpeechConstant.STREAM_TYPE, "3"); + + // 设置播放合成音频打断音乐播放,默认为true + mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true"); + + // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限 + mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav"); + + mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/tts.wav"); + } + + @Override + public void setParam(String voiceMember, Integer voiceSize, Integer voiceIndicate, Integer voiceSpeed) { + if (null != voiceMember) { + //设置发音人资源路径 + mTts.setParameter(ResourceUtil.TTS_RES_PATH, getResourcePath(voiceMember)); + //设置发音人 + mTts.setParameter(SpeechConstant.VOICE_NAME, voiceMember); + } + if (null != voiceSize) { + //设置合成音量 + mTts.setParameter(SpeechConstant.VOLUME, String.valueOf(voiceSize)); + } + if (null != voiceIndicate) { + //设置合成音调 + mTts.setParameter(SpeechConstant.PITCH, String.valueOf(voiceIndicate)); + } + if (null != voiceSpeed) { + //设置合成语速 + mTts.setParameter(SpeechConstant.SPEED, String.valueOf(voiceSpeed)); + } + } + + + private void showTip(String str) { + mToast.setText(str); + mToast.show(); + } + + //获取发音人资源路径 + private String getResourcePath(String voiceMember) { + StringBuffer tempBuffer = new StringBuffer(); + String type = "tts"; + //合成通用资源 + tempBuffer.append(ResourceUtil.generateResourcePath(context, RESOURCE_TYPE.assets, type.concat("/common.jet"))); + tempBuffer.append(";"); + tempBuffer.append(ResourceUtil.generateResourcePath(context, RESOURCE_TYPE.assets, type.concat("/").concat(voiceMember).concat(".jet"))); + return tempBuffer.toString(); + } + + public void destroy() { + if (null != mTts) { + mTts.stopSpeaking(); + // 退出时释放连接 + mTts.destroy(); + } + } +} diff --git a/app/src/main/java/chaoran/business/vioce/VoiceEngine.java b/app/src/main/java/chaoran/business/vioce/VoiceEngine.java new file mode 100644 index 0000000..22c5f2e --- /dev/null +++ b/app/src/main/java/chaoran/business/vioce/VoiceEngine.java @@ -0,0 +1,27 @@ +package chaoran.business.vioce; + +/* + ********************************************** + * DATE PERSON REASON + * 2021-02-05 FXY Created + ********************************************** + */ + + +public interface VoiceEngine { + + //开始说话 + public void startSpeaking(String text); + + //停止说话 + public void stopSpeaking(); + + //销毁资源 + public void destroy(); + + //装载参数,从配置文件中装载参数 + public void loadParam(); + + //设置参数 + public void setParam(String voiceMember, Integer voiceSize, Integer voiceIndicate, Integer voiceSpeed); +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.png b/app/src/main/res/drawable-v24/ic_launcher_foreground.png new file mode 100644 index 0000000..4fd7458 Binary files /dev/null and b/app/src/main/res/drawable-v24/ic_launcher_foreground.png differ diff --git a/app/src/main/res/drawable/ic_launcher.png b/app/src/main/res/drawable/ic_launcher.png new file mode 100644 index 0000000..4fd7458 Binary files /dev/null and b/app/src/main/res/drawable/ic_launcher.png differ diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml new file mode 100644 index 0000000..2df63a0 --- /dev/null +++ b/app/src/main/res/layout/activity_about.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..ec61af8 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_setting_network.xml b/app/src/main/res/layout/activity_setting_network.xml new file mode 100644 index 0000000..de38678 --- /dev/null +++ b/app/src/main/res/layout/activity_setting_network.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +