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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_setting_voice.xml b/app/src/main/res/layout/activity_setting_voice.xml
new file mode 100644
index 0000000..5b5671f
--- /dev/null
+++ b/app/src/main/res/layout/activity_setting_voice.xml
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000..d465b5a
--- /dev/null
+++ b/app/src/main/res/menu/menu_main.xml
@@ -0,0 +1,22 @@
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.png b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.png
new file mode 100644
index 0000000..4fd7458
Binary files /dev/null and b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..4fd7458
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..4fd7458
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..4fd7458
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4fd7458
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4fd7458
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/raw/beep.ogg b/app/src/main/res/raw/beep.ogg
new file mode 100644
index 0000000..1419947
Binary files /dev/null and b/app/src/main/res/raw/beep.ogg differ
diff --git a/app/src/main/res/raw/didi.ogg b/app/src/main/res/raw/didi.ogg
new file mode 100644
index 0000000..3ea31f3
Binary files /dev/null and b/app/src/main/res/raw/didi.ogg differ
diff --git a/app/src/main/res/raw/dudu.ogg b/app/src/main/res/raw/dudu.ogg
new file mode 100644
index 0000000..265cc4b
Binary files /dev/null and b/app/src/main/res/raw/dudu.ogg differ
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..afd7c75
--- /dev/null
+++ b/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..9309de9
--- /dev/null
+++ b/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
new file mode 100644
index 0000000..6cf9ed4
--- /dev/null
+++ b/app/src/main/res/values/arrays.xml
@@ -0,0 +1,12 @@
+
+
+
+ - Reply
+ - Reply to all
+
+
+
+ - reply
+ - reply_all
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..e00c2dd
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e089776
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,16 @@
+
+ 超然扫描
+ 网络设置
+ 网络设置界面
+ 语音设置
+ 语音设置界面
+ 主页
+ 关于
+ 这是关于界面的内容
+
+
+ 601c9ec6
+
+
+ 缓冲进度为%d%%,播放进度为%d%%
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..1b3c1d7
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..c8d7712
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath "com.android.tools.build:gradle:4.1.0"
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..8f30b89
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,24 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+
+RELEASE_STOREFILE=E:/AndroidStudioProject/signKey.jks
+RELEASE_STORE_PASSWORD=123456
+RELEASE_KEY_ALIAS=fxy
+RELEASE_KEY_PASSWORD=123456
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..a8543a4
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Feb 01 13:41:10 CST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..2a4538c
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "pda-web"
\ No newline at end of file