aaa
Some checks failed
Flask 提示词大师 - CI/CD 流水线 / 代码质量检查 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 单元测试 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 集成测试 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 构建Docker镜像 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 部署到测试环境 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 部署到生产环境 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 部署监控系统 (push) Has been cancelled
155
example/(红头)项目编译Debug版本和Release版本apk的方法.txt
Normal file
@@ -0,0 +1,155 @@
|
||||
# Android 项目编译 Debug 和 Release 版本 APK 的方法
|
||||
|
||||
## 项目信息
|
||||
- **项目名称**: com.xunpaisoft.social
|
||||
- **项目路径**: D:\zhini\android-im
|
||||
- **JDK 要求**: Java 11 或更高版本
|
||||
- **推荐 JDK**: Android Studio 内置 JDK 21
|
||||
|
||||
## 环境准备
|
||||
|
||||
### 1. 检查 Java 版本
|
||||
```bash
|
||||
java -version
|
||||
```
|
||||
**注意**: 如果系统只有 Java 8,需要使用 Android Studio 的 JDK 21
|
||||
|
||||
### 2. 设置环境变量
|
||||
```powershell
|
||||
# 设置 Android Studio JDK 路径
|
||||
$env:JAVA_HOME="C:\Program Files\Android\Android Studio1\jbr"
|
||||
|
||||
# 设置 Android SDK 路径
|
||||
$env:ANDROID_HOME="C:\Users\$env:USERNAME\AppData\Local\Android\Sdk"
|
||||
```
|
||||
|
||||
## 编译方法
|
||||
|
||||
### 方法一:使用 Gradle Wrapper(推荐)
|
||||
|
||||
#### 1. Debug 版本编译
|
||||
```bash
|
||||
# 设置环境变量并编译 Debug 版本
|
||||
$env:JAVA_HOME="C:\Program Files\Android\Android Studio1\jbr"; $env:ANDROID_HOME="C:\Users\$env:USERNAME\AppData\Local\Android\Sdk"; .\gradlew.bat assembleDebug
|
||||
```
|
||||
|
||||
**编译结果**:
|
||||
- ✅ 编译状态: BUILD SUCCESSFUL
|
||||
- ⏱️ 编译时间: 约 34 秒
|
||||
- 📁 APK 位置: `app\build\outputs\apk\debug\app-debug.apk`
|
||||
|
||||
#### 2. Release 版本编译
|
||||
```bash
|
||||
# 设置环境变量并编译 Release 版本
|
||||
$env:JAVA_HOME="C:\Program Files\Android\Android Studio1\jbr"; $env:ANDROID_HOME="C:\Users\$env:USERNAME\AppData\Local\Android\Sdk"; .\gradlew.bat assembleRelease
|
||||
```
|
||||
|
||||
**编译结果**:
|
||||
- ✅ 编译状态: BUILD SUCCESSFUL
|
||||
- ⏱️ 编译时间: 约 3分48秒
|
||||
- 📁 APK 位置: `app\build\outputs\apk\release\app-release.apk`
|
||||
|
||||
### 方法二:使用 Android Studio(最简单)
|
||||
|
||||
1. **打开 Android Studio**
|
||||
2. **导入项目**: 选择 `D:\zhini\android-im` 目录
|
||||
3. **等待 Gradle 同步完成**
|
||||
4. **编译项目**:
|
||||
- **Debug 版本**: `Build` → `Build Bundle(s) / APK(s)` → `Build APK(s)`
|
||||
- **Release 版本**: `Build` → `Generate Signed Bundle / APK` → `APK`
|
||||
|
||||
## 安装 APK 到设备
|
||||
|
||||
### 安装 Debug 版本
|
||||
```bash
|
||||
adb install -r app\build\outputs\apk\debug\app-debug.apk
|
||||
```
|
||||
|
||||
### 安装 Release 版本
|
||||
```bash
|
||||
adb install -r app\build\outputs\apk\release\app-release.apk
|
||||
```
|
||||
|
||||
## 版本对比
|
||||
|
||||
| 特性 | Debug 版本 | Release 版本 |
|
||||
|------|------------|--------------|
|
||||
| **编译时间** | 约 34 秒 | 约 3分48秒 |
|
||||
| **APK 大小** | 较大 | 较小(优化后) |
|
||||
| **代码混淆** | 否 | 是(ProGuard) |
|
||||
| **调试信息** | 包含 | 移除 |
|
||||
| **性能** | 较慢 | 较快 |
|
||||
| **用途** | 开发测试 | 正式发布 |
|
||||
|
||||
## 常见问题解决
|
||||
|
||||
### 问题1: Java 版本不兼容
|
||||
**错误信息**: `Dependency requires at least JVM runtime version 11. This build uses a Java 8 JVM.`
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 停止现有 Gradle daemon
|
||||
.\gradlew.bat --stop
|
||||
|
||||
# 使用 Android Studio JDK 编译
|
||||
$env:JAVA_HOME="C:\Program Files\Android\Android Studio1\jbr"; .\gradlew.bat assembleDebug
|
||||
```
|
||||
|
||||
### 问题2: Gradle Wrapper 不存在
|
||||
**解决方案**: 项目已包含 `gradlew.bat` 文件,如果缺失可以重新创建。
|
||||
|
||||
### 问题3: 权限重复警告
|
||||
**现象**: 编译时出现权限重复警告
|
||||
**影响**: 不影响编译,但建议清理重复权限声明
|
||||
|
||||
## 编译命令总结
|
||||
|
||||
### 一键编译脚本
|
||||
```powershell
|
||||
# Debug 版本一键编译
|
||||
$env:JAVA_HOME="C:\Program Files\Android\Android Studio1\jbr"; $env:ANDROID_HOME="C:\Users\$env:USERNAME\AppData\Local\Android\Sdk"; .\gradlew.bat assembleDebug
|
||||
|
||||
# Release 版本一键编译
|
||||
$env:JAVA_HOME="C:\Program Files\Android\Android Studio1\jbr"; $env:ANDROID_HOME="C:\Users\$env:USERNAME\AppData\Local\Android\Sdk"; .\gradlew.bat assembleRelease
|
||||
```
|
||||
|
||||
### 清理和重新编译
|
||||
```bash
|
||||
# 清理项目
|
||||
.\gradlew.bat clean
|
||||
|
||||
# 重新编译 Debug 版本
|
||||
.\gradlew.bat assembleDebug
|
||||
|
||||
# 重新编译 Release 版本
|
||||
.\gradlew.bat assembleRelease
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **JDK 版本**: 必须使用 Java 11 或更高版本
|
||||
2. **环境变量**: 每次编译前需要设置正确的 JAVA_HOME
|
||||
3. **签名配置**: Release 版本需要配置签名文件
|
||||
4. **混淆规则**: Release 版本会应用 ProGuard 混淆规则
|
||||
5. **资源优化**: Release 版本会进行资源压缩和优化
|
||||
|
||||
## 文件位置
|
||||
|
||||
- **Debug APK**: `app\build\outputs\apk\debug\app-debug.apk`
|
||||
- **Release APK**: `app\build\outputs\apk\release\app-release.apk`
|
||||
- **Gradle Wrapper**: `gradlew.bat`
|
||||
- **构建配置**: `app\build.gradle`
|
||||
|
||||
## 成功标志
|
||||
|
||||
编译成功后会显示:
|
||||
```
|
||||
BUILD SUCCESSFUL in [时间]
|
||||
[数量] actionable tasks: [执行数量] executed, [跳过数量] up-to-date
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025年10月29日
|
||||
**适用版本**: Android Gradle Plugin 8.7.3
|
||||
**JDK 版本**: Android Studio JDK 21
|
||||
35
example/.gitignore
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# ---> Android
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Log/OS Files
|
||||
*.log
|
||||
|
||||
# Android Studio generated files and folders
|
||||
captures/
|
||||
.externalNativeBuild/
|
||||
.cxx/
|
||||
*.apk
|
||||
output.json
|
||||
|
||||
# IntelliJ
|
||||
*.iml
|
||||
.idea/
|
||||
misc.xml
|
||||
deploymentTargetDropDown.xml
|
||||
render.experimental.xml
|
||||
|
||||
# Keystore files
|
||||
*.jks
|
||||
*.keystore
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
google-services.json
|
||||
|
||||
# Android Profiling
|
||||
*.hprof
|
||||
|
||||
2
example/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# peizhen
|
||||
|
||||
1
example/app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
60
example/app/build.gradle
Normal file
@@ -0,0 +1,60 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
namespace 'com.ruilaizi.example'
|
||||
compileSdk 34
|
||||
defaultConfig {
|
||||
applicationId "com.ruilaizi.example"
|
||||
minSdk 24
|
||||
targetSdk 34
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
buildConfigField "String", "API_BASE_URL", "\"https://api.deepseek.com/v1/\""
|
||||
buildConfigField "String", "DEFAULT_API_KEY", "\"sk-fdf7cc1c73504e628ec0119b7e11b8cc\""
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
buildConfig true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.11.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.core:core:1.12.0'
|
||||
|
||||
// ViewModel & LiveData
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.7.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata:2.7.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime:2.7.0'
|
||||
|
||||
// Room
|
||||
implementation 'androidx.room:room-runtime:2.6.1'
|
||||
annotationProcessor 'androidx.room:room-compiler:2.6.1'
|
||||
|
||||
// Network
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||
|
||||
// Security: 可选,用于加密存储 API Key
|
||||
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
|
||||
|
||||
implementation 'com.readystatesoftware.systembartint:systembartint:1.0.4'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
}
|
||||
BIN
example/app/libs/ShareSDK-Wechat-Core-2.8.3.jar
Normal file
BIN
example/app/libs/eventbus-2.4.0.jar
Normal file
BIN
example/app/libs/fastjson-1.1.43.android.jar
Normal file
BIN
example/app/libs/wechat-sdk-android-without-mta-1.0.2.jar
Normal file
21
example/app/proguard-rules.pro
vendored
Normal file
@@ -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
|
||||
18
example/app/release/output-metadata.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 2,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "com.ruilaizi.service",
|
||||
"variantName": "release",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"versionCode": 101,
|
||||
"versionName": "1.0.1",
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
]
|
||||
}
|
||||
36
example/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:name=".BaseApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="com.ruilaizi.example.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths_public" />
|
||||
</provider>
|
||||
</application>
|
||||
</manifest>
|
||||
14264
example/app/src/main/assets/city.json
Normal file
97
example/app/src/main/assets/customerList.json
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"address": "",
|
||||
"budget": "",
|
||||
"customer_id": "49fc031a8b374e5c69b1640c2f77b5f4",
|
||||
"decoration": "1",
|
||||
"headimg": "http://192.168.1.3/upload/2020090409422893432.jpg",
|
||||
"name": "狗子",
|
||||
"phone": "13255558866",
|
||||
"source": "1",
|
||||
"source_name": "添加客户",
|
||||
"style_id": "",
|
||||
"style_name": "",
|
||||
"type": "new",
|
||||
"wechat": "— —"
|
||||
},
|
||||
{
|
||||
"address": "住址",
|
||||
"budget": "15万-20万",
|
||||
"customer_id": "4db0ac2253cb643bfb0ddeb6375a27b3",
|
||||
"decoration": "1",
|
||||
"headimg": "",
|
||||
"name": "阿爸。",
|
||||
"phone": "13458966692",
|
||||
"source": "1",
|
||||
"source_name": "添加客户",
|
||||
"style_id": "5",
|
||||
"style_name": "现代简约",
|
||||
"type": "old",
|
||||
"wechat": "call"
|
||||
},
|
||||
{
|
||||
"address": "一次是真的",
|
||||
"budget": "5万-10万",
|
||||
"customer_id": "5619a67e02a85290ad485d2e2b48b788",
|
||||
"decoration": "2",
|
||||
"headimg": "http://192.168.1.3/upload/2020090315102014899.jpg",
|
||||
"name": "在乎",
|
||||
"phone": "13278787787",
|
||||
"source": "1",
|
||||
"source_name": "添加客户",
|
||||
"style_id": "7",
|
||||
"style_name": "地中海",
|
||||
"type": "old",
|
||||
"wechat": "一次"
|
||||
},
|
||||
{
|
||||
"address": "",
|
||||
"budget": "",
|
||||
"customer_id": "638de5977746a9337b08d9caaee11393",
|
||||
"decoration": "2",
|
||||
"headimg": "http://192.168.1.3/upload/2020090409345081526.jpg",
|
||||
"name": "1212121",
|
||||
"phone": "21212121qwq",
|
||||
"source": "1",
|
||||
"source_name": "添加客户",
|
||||
"style_id": "",
|
||||
"style_name": "",
|
||||
"type": "new",
|
||||
"wechat": ""
|
||||
},
|
||||
{
|
||||
"address": "等,你,你",
|
||||
"budget": "20万以上",
|
||||
"customer_id": "7b4df32da7c8c08b55903117bb7cc8d9",
|
||||
"decoration": "1",
|
||||
"headimg": "http://192.168.1.3/upload/2020090409233368106.jpg",
|
||||
"name": "你在,他",
|
||||
"phone": "13826942573",
|
||||
"source": "1",
|
||||
"source_name": "添加客户",
|
||||
"style_id": "6",
|
||||
"style_name": "东南亚",
|
||||
"type": "new",
|
||||
"wechat": ""
|
||||
},
|
||||
{
|
||||
"address": "",
|
||||
"budget": "",
|
||||
"customer_id": "af8b2b183071a36cf216211c48890ce9",
|
||||
"decoration": "1",
|
||||
"headimg": "http://192.168.1.3/upload/2020090409364521615.jpg",
|
||||
"name": "二哈",
|
||||
"phone": "13245725369",
|
||||
"source": "0",
|
||||
"source_name": "",
|
||||
"style_id": "",
|
||||
"style_name": "",
|
||||
"type": "new",
|
||||
"wechat": "微信"
|
||||
}
|
||||
],
|
||||
"msg": "获取成功",
|
||||
"success": 0,
|
||||
"total": 4
|
||||
}
|
||||
804
example/app/src/main/assets/dede.json
Normal file
@@ -0,0 +1,804 @@
|
||||
{
|
||||
"v": "5.7.1",
|
||||
"fr": 120,
|
||||
"ip": 0,
|
||||
"op": 230,
|
||||
"w": 500,
|
||||
"h": 500,
|
||||
"nm": "加载动画",
|
||||
"ddd": 0,
|
||||
"assets": [
|
||||
{
|
||||
"id": "comp_0",
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 3",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
248,
|
||||
274,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"ind": 0,
|
||||
"ty": "sh",
|
||||
"ix": 1,
|
||||
"ks": {
|
||||
"a": 0,
|
||||
"k": {
|
||||
"i": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"o": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"v": [
|
||||
[
|
||||
-90,
|
||||
-28
|
||||
],
|
||||
[
|
||||
-21,
|
||||
38
|
||||
],
|
||||
[
|
||||
101,
|
||||
-105
|
||||
]
|
||||
],
|
||||
"c": false
|
||||
},
|
||||
"ix": 2
|
||||
},
|
||||
"nm": "路径 1",
|
||||
"mn": "ADBE Vector Shape - Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.149019613862,
|
||||
0.501960813999,
|
||||
0.921568632126,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 33,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 2,
|
||||
"lj": 2,
|
||||
"bm": 0,
|
||||
"nm": "描边 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
72,
|
||||
72
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "变换"
|
||||
}
|
||||
],
|
||||
"nm": "形状 1",
|
||||
"np": 2,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 1
|
||||
},
|
||||
"e": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0
|
||||
],
|
||||
"y": [
|
||||
0.982
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.333
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"t": 191,
|
||||
"s": [
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 230,
|
||||
"s": [
|
||||
100
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 3
|
||||
},
|
||||
"m": 1,
|
||||
"ix": 2,
|
||||
"nm": "修剪路径 1",
|
||||
"mn": "ADBE Vector Filter - Trim",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 191,
|
||||
"op": 231,
|
||||
"st": -69,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 2,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 2",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
251.5,
|
||||
256.5,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"d": 1,
|
||||
"ty": "el",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
321,
|
||||
321
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"nm": "椭圆路径 1",
|
||||
"mn": "ADBE Vector Shape - Ellipse",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.149019613862,
|
||||
0.501960813999,
|
||||
0.921568632126,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 20,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 2,
|
||||
"lj": 1,
|
||||
"ml": 4,
|
||||
"bm": 0,
|
||||
"nm": "描边 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
-1.5,
|
||||
-6.5
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "变换"
|
||||
}
|
||||
],
|
||||
"nm": "椭圆 1",
|
||||
"np": 2,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 1
|
||||
},
|
||||
"e": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 0,
|
||||
"s": [
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 46,
|
||||
"s": [
|
||||
25
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 96,
|
||||
"s": [
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 191,
|
||||
"s": [
|
||||
100
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 0,
|
||||
"s": [
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 96,
|
||||
"s": [
|
||||
360
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 191,
|
||||
"s": [
|
||||
720
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"m": 1,
|
||||
"ix": 2,
|
||||
"nm": "修剪路径 1",
|
||||
"mn": "ADBE Vector Filter - Trim",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 360,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 3,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 1",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
251.5,
|
||||
256.5,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"d": 1,
|
||||
"ty": "el",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
321,
|
||||
321
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"nm": "椭圆路径 1",
|
||||
"mn": "ADBE Vector Shape - Ellipse",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 21,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 1,
|
||||
"lj": 1,
|
||||
"ml": 4,
|
||||
"bm": 0,
|
||||
"nm": "描边 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
-1.5,
|
||||
-6.5
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "变换"
|
||||
}
|
||||
],
|
||||
"nm": "椭圆 1",
|
||||
"np": 2,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 360,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 0,
|
||||
"nm": "1",
|
||||
"refId": "comp_0",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
250,
|
||||
250,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
250,
|
||||
250,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"w": 500,
|
||||
"h": 500,
|
||||
"ip": 0,
|
||||
"op": 97,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": []
|
||||
}
|
||||
1
example/app/src/main/assets/edsf.json
Normal file
@@ -0,0 +1 @@
|
||||
{"v":"5.7.1","fr":120,"ip":0,"op":96,"w":500,"h":500,"nm":"合成 1","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[248,274,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-90,-28],[-21,38],[101,-105]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.149019607843,0.501960784314,0.921568627451,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[72,72],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[0.982]},"o":{"x":[0.333],"y":[0]},"t":191,"s":[0]},{"t":230,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":191,"op":231,"st":-69,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"形状图层 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[251.5,256.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[321,321],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.149019607843,0.501960784314,0.921568627451,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":15,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-1.5,-6.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[15]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":46,"s":[25]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":96,"s":[15]},{"t":191,"s":[100]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":96,"s":[360]},{"t":191,"s":[720]}],"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"形状图层 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[251.5,256.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[321,321],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.686274509804,0.686274509804,0.686274509804,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":15,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-1.5,-6.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":360,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"完整动画","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":500,"h":500,"ip":0,"op":96,"st":0,"bm":0}],"markers":[]}
|
||||
21
example/app/src/main/assets/fpList.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"customer_id": "ae0c5199fdf564f90796aec09482b85d",
|
||||
"fp_num": "2",
|
||||
"headimg": "localhost/upload/2020081115530962805.jpg",
|
||||
"industry": [
|
||||
{
|
||||
"customer_id": "ae0c5199fdf564f90796aec09482b85d",
|
||||
"industry": "家具",
|
||||
"type": "0"
|
||||
}
|
||||
],
|
||||
"name": "demo",
|
||||
"phone": "18831913290",
|
||||
"wechat": "wangyuxin283425757"
|
||||
}
|
||||
],
|
||||
"msg": "获取成功",
|
||||
"success": 0
|
||||
}
|
||||
34
example/app/src/main/assets/fpOrderInfo.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"budget": "",
|
||||
"decoration": "1",
|
||||
"enter_state": "0",
|
||||
"fp_time": "1970-01-01 08:00",
|
||||
"id": "1",
|
||||
"industry": "家具",
|
||||
"order": [
|
||||
{
|
||||
"fh_id": "1",
|
||||
"order_name": "qqq",
|
||||
"recudesum": "1.00",
|
||||
"time": "2020-09-08 10:14"
|
||||
}
|
||||
],
|
||||
"order_state": "0",
|
||||
"rob_time": "1970-01-01 08:00",
|
||||
"travel": "1",
|
||||
"type": "0",
|
||||
"type_time": "1970-01-01 08:00",
|
||||
"ygd_brand_name": "",
|
||||
"ygd_brand_type": "",
|
||||
"ygd_enter": "0",
|
||||
"ygd_order": "0",
|
||||
"ygd_rob_name": "",
|
||||
"ygd_state": "0",
|
||||
"ygd_store_name": ""
|
||||
}
|
||||
],
|
||||
"msg": "成功",
|
||||
"success": 0
|
||||
}
|
||||
373
example/app/src/main/assets/jiazaidonghua.json
Normal file
@@ -0,0 +1,373 @@
|
||||
{
|
||||
"v": "5.4.4",
|
||||
"fr": 25,
|
||||
"ip": 0,
|
||||
"op": 24,
|
||||
"w": 100,
|
||||
"h": 50,
|
||||
"nm": "合成 1",
|
||||
"ddd": 0,
|
||||
"assets": [],
|
||||
"layers": [{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 3",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [19.5, 25, 0],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [0, 0, 0],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [100, 100, 100],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [{
|
||||
"ty": "gr",
|
||||
"it": [{
|
||||
"d": 1,
|
||||
"ty": "el",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [20, 20],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [0, 0],
|
||||
"ix": 3
|
||||
},
|
||||
"nm": "椭圆路径 1",
|
||||
"mn": "ADBE Vector Shape - Ellipse",
|
||||
"hd": false
|
||||
}, {
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [0.117647058824, 0.117647058824, 0.117647058824, 1],
|
||||
"ix": 4
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 5
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "填充 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
}, {
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [0, 0],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [0, 0],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [100, 100],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "变换"
|
||||
}],
|
||||
"nm": "椭圆 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}],
|
||||
"ip": 6,
|
||||
"op": 256,
|
||||
"st": 6,
|
||||
"bm": 0
|
||||
}, {
|
||||
"ddd": 0,
|
||||
"ind": 2,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 1",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [50, 25, 0],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [0, 0, 0],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [100, 100, 100],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [{
|
||||
"ty": "gr",
|
||||
"it": [{
|
||||
"d": 1,
|
||||
"ty": "el",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [20, 20],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [0, 0],
|
||||
"ix": 3
|
||||
},
|
||||
"nm": "椭圆路径 1",
|
||||
"mn": "ADBE Vector Shape - Ellipse",
|
||||
"hd": false
|
||||
}, {
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [0.117647058824, 0.117647058824, 0.117647058824, 1],
|
||||
"ix": 4
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 5
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "填充 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
}, {
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [0, 0],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [0, 0],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [100, 100],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "变换"
|
||||
}],
|
||||
"nm": "椭圆 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}],
|
||||
"ip": 12,
|
||||
"op": 262,
|
||||
"st": 12,
|
||||
"bm": 0
|
||||
}, {
|
||||
"ddd": 0,
|
||||
"ind": 3,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 2",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [80.5, 25, 0],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [0, 0, 0],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [100, 100, 100],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [{
|
||||
"ty": "gr",
|
||||
"it": [{
|
||||
"d": 1,
|
||||
"ty": "el",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [20, 20],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [0, 0],
|
||||
"ix": 3
|
||||
},
|
||||
"nm": "椭圆路径 1",
|
||||
"mn": "ADBE Vector Shape - Ellipse",
|
||||
"hd": false
|
||||
}, {
|
||||
"ty": "fl",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [0.117647058824, 0.117647058824, 0.117647058824, 1],
|
||||
"ix": 4
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 5
|
||||
},
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "填充 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
}, {
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [0, 0],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [0, 0],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [100, 100],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "变换"
|
||||
}],
|
||||
"nm": "椭圆 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}],
|
||||
"ip": 18,
|
||||
"op": 268,
|
||||
"st": 18,
|
||||
"bm": 0
|
||||
}],
|
||||
"markers": []
|
||||
}
|
||||
16
example/app/src/main/assets/logingpwd.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"data":
|
||||
{
|
||||
"industry_name": "家具",
|
||||
"phone_number": "14729066305",
|
||||
"status": "0",
|
||||
"store_id": "1",
|
||||
"user_head": "",
|
||||
"user_name": "admin",
|
||||
"user_type": "2",
|
||||
"uuid": "3"
|
||||
}
|
||||
,
|
||||
"msg": "登陆成功",
|
||||
"success": 0
|
||||
}
|
||||
14
example/app/src/main/assets/orderList.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"customer_id": "ae0c5199fdf564f90796aec09482b85d",
|
||||
"headimg": "localhost/upload/2020081115530962805.jpg",
|
||||
"name": "demo",
|
||||
"order_num": "1",
|
||||
"phone": "18831913290",
|
||||
"wechat": "wangyuxin283425757"
|
||||
}
|
||||
],
|
||||
"msg": "获取成功",
|
||||
"success": 0
|
||||
}
|
||||
89
example/app/src/main/assets/privacy.html
Normal file
@@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>Document</title>
|
||||
<script src="http://www.fenghoo.com.cn/JS/fenghuSta/jquery.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="http://www.fenghoo.com.cn/JS/fenghuSta/yidongduan.js" type="text/javascript" charset="utf-8"></script>
|
||||
<style type="text/css">
|
||||
html,body,ul,li,ol{padding: 0;margin: 0;}
|
||||
body{
|
||||
width: 94%;
|
||||
margin-left: 3%;
|
||||
}
|
||||
li{list-style: none;text-indent: 2em;}
|
||||
li{
|
||||
font-size: .28rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<li>瑞来健康尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,瑞来健康会按照本隐私权政策的规定使用和披露您的个人信息。但瑞来健康将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,瑞来健康不会将这些信息对外披露或向第三方提供。瑞来健康会不时更新本隐私权政策。 您在同意瑞来健康服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于瑞来健康服务使用协议不可分割的一部分。 </li>
|
||||
<li>
|
||||
<h5>1. 适用范围</h5>
|
||||
<ol>
|
||||
<li>(a) 在您注册瑞来健康帐号时,您根据瑞来健康要求提供的个人注册信息;</li>
|
||||
<li>(b) 在您使用瑞来健康网络服务,或访问瑞来健康平台网页时,瑞来健康自动接收并记录的您的浏览器和计算机上的信息,包括但不限于您的IP地址、浏览器的类型、使用的语言、访问日期和时间、软硬件特征信息及您需求的网页记录等数据;</li>
|
||||
<li>(c) 瑞来健康通过合法途径从商业伙伴处取得的用户个人数据。 </li>
|
||||
<li>您了解并同意,以下信息不适用本隐私权政策:</li>
|
||||
<li>(a) 您在使用瑞来健康平台提供的搜索服务时输入的关键字信息;</li>
|
||||
<li>(b) 瑞来健康收集到的您在瑞来健康发布的有关信息数据,包括但不限于参与活动、成交信息及评价详情;</li>
|
||||
<li>(c) 违反法律规定或违反瑞来健康规则行为及瑞来健康已对您采取的措施。</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<h5>2. 信息使用</h5>
|
||||
<ol>
|
||||
<li>(a)瑞来健康不会向任何无关第三方提供、出售、出租、分享或交易您的个人信息,除非事先得到您的许可,或该第三方和瑞来健康(含瑞来健康关联公司)单独或共同为您提供服务,且在该服务结束后,其将被禁止访问包括其以前能够访问的所有这些资料。</li>
|
||||
<li>(b) 瑞来健康亦不允许任何第三方以任何手段收集、编辑、出售或者无偿传播您的个人信息。任何瑞来健康平台用户如从事上述活动,一经发现,瑞来健康有权立即终止与该用户的服务协议。</li>
|
||||
<li>(c) 为服务用户的目的,瑞来健康可能通过使用您的个人信息,向您提供您感兴趣的信息,包括但不限于向您发出产品和服务信息,或者与瑞来健康合作伙伴共享信息以便他们向您发送有关其产品和服务的信息(后者需要您的事先同意)。</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<h5>3. 信息披露</h5>
|
||||
<ol>
|
||||
<li>在如下情况下,瑞来健康将依据您的个人意愿或法律的规定全部或部分的披露您的个人信息:</li>
|
||||
<li>(a) 经您事先同意,向第三方披露;</li>
|
||||
<li>(b)为提供您所要求的产品和服务,而必须和第三方分享您的个人信息;</li>
|
||||
<li>(c) 根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露;</li>
|
||||
<li>(d) 如您出现违反中国有关法律、法规或者瑞来健康服务协议或相关规则的情况,需要向第三方披露;</li>
|
||||
<li>(e) 如您是适格的知识产权投诉人并已提起投诉,应被投诉人要求,向被投诉人披露,以便双方处理可能的权利纠纷;</li>
|
||||
<li>(f) 在瑞来健康平台上创建的某一交易中,如交易任何一方履行或部分履行了交易义务并提出信息披露请求的,瑞来健康有权决定向该用户提供其交易对方的联络方式等必要信息,以促成交易的完成或纠纷的解决。</li>
|
||||
<li>(g) 其它瑞来健康根据法律、法规或者网站政策认为合适的披露。</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<h5>4. 信息存储和交换</h5>
|
||||
<ol>
|
||||
<li>瑞来健康收集的有关您的信息和资料将保存在瑞来健康及(或)其关联公司的服务器上,这些信息和资料可能传送至您所在国家、地区或瑞来健康收集信息和资料所在地的境外并在境外被访问、存储和展示。</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<h5>5. Cookie的使用</h5>
|
||||
<ol>
|
||||
<li>(a) 在您未拒绝接受cookies的情况下,瑞来健康会在您的计算机上设定或取用cookies,以便您能登录或使用依赖于cookies的瑞来健康平台服务或功能。瑞来健康使用cookies可为您提供更加周到的个性化服务,包括推广服务。</li>
|
||||
<li>(b) 您有权选择接受或拒绝接受cookies。您可以通过修改浏览器设置的方式拒绝接受cookies。但如果您选择拒绝接受cookies,则您可能无法登录或使用依赖于cookies的瑞来健康网络服务或功能。</li>
|
||||
<li>(c) 通过瑞来健康所设cookies所取得的有关信息,将适用本政策。</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<h5>6. 信息安全</h5>
|
||||
<ol>
|
||||
<li>(a) 瑞来健康帐号均有安全保护功能,请妥善保管您的用户名及密码信息。瑞来健康将通过对用户密码进行加密等安全措施确保您的信息不丢失,不被滥用和变造。尽管有前述安全措施,但同时也请您注意在信息网络上不存在“完善的安全措施”。</li>
|
||||
<li>(b) 在使用瑞来健康网络服务进行网上交易时,您不可避免的要向交易对方或潜在的交易对方披露自己的个人信息,如联络方式或者邮政地址。请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息泄密,尤其是瑞来健康用户名及密码发生泄露,请您立即联络瑞来健康客服,以便瑞来健康采取相应措施。</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<h5>7.本隐私政策的更改</h5>
|
||||
<ol>
|
||||
<li>(a)如果决定更改隐私政策,我们会在本政策中、本公司网站中以及我们认为适当的位置发布这些更改,以便您了解我们如何收集、使用您的个人信息,哪些人可以访问这些信息,以及在什么情况下我们会透露这些信息。</li>
|
||||
<li>(b)本公司保留随时修改本政策的权利,因此请经常查看。如对本政策作出重大更改,本公司会通过网站通知的形式告知。方披露自己的个人信息,如联络方式或者邮政地址。请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息泄密,尤其是本应用用户名及密码发生泄露,请您立即联络本应用客服,以便本应用采取相应措施。</li>
|
||||
</ol>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
15
example/app/src/main/assets/privateList.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"connect_time": "10:48",
|
||||
"content": "",
|
||||
"nick_img": "",
|
||||
"nick_name": "私信昵称",
|
||||
"private_id": "1",
|
||||
"read_num": "0",
|
||||
"short_id": "私信id"
|
||||
}
|
||||
],
|
||||
"msg": "成功",
|
||||
"success": 0
|
||||
}
|
||||
5354
example/app/src/main/assets/province.json
Normal file
804
example/app/src/main/assets/ssssd.json
Normal file
@@ -0,0 +1,804 @@
|
||||
{
|
||||
"v": "5.7.1",
|
||||
"fr": 120,
|
||||
"ip": 0,
|
||||
"op": 96,
|
||||
"w": 500,
|
||||
"h": 500,
|
||||
"nm": "合成 1",
|
||||
"ddd": 0,
|
||||
"assets": [
|
||||
{
|
||||
"id": "comp_0",
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 3",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
248,
|
||||
274,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"ind": 0,
|
||||
"ty": "sh",
|
||||
"ix": 1,
|
||||
"ks": {
|
||||
"a": 0,
|
||||
"k": {
|
||||
"i": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"o": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"v": [
|
||||
[
|
||||
-90,
|
||||
-28
|
||||
],
|
||||
[
|
||||
-21,
|
||||
38
|
||||
],
|
||||
[
|
||||
101,
|
||||
-105
|
||||
]
|
||||
],
|
||||
"c": false
|
||||
},
|
||||
"ix": 2
|
||||
},
|
||||
"nm": "路径 1",
|
||||
"mn": "ADBE Vector Shape - Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.149019607843,
|
||||
0.501960784314,
|
||||
0.921568627451,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 33,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 2,
|
||||
"lj": 2,
|
||||
"bm": 0,
|
||||
"nm": "描边 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
72,
|
||||
72
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "变换"
|
||||
}
|
||||
],
|
||||
"nm": "形状 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 1
|
||||
},
|
||||
"e": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0
|
||||
],
|
||||
"y": [
|
||||
0.982
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.333
|
||||
],
|
||||
"y": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"t": 191,
|
||||
"s": [
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 230,
|
||||
"s": [
|
||||
100
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 3
|
||||
},
|
||||
"m": 1,
|
||||
"ix": 2,
|
||||
"nm": "修剪路径 1",
|
||||
"mn": "ADBE Vector Filter - Trim",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 191,
|
||||
"op": 231,
|
||||
"st": -69,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 2,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 2",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
251.5,
|
||||
256.5,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"d": 1,
|
||||
"ty": "el",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
321,
|
||||
321
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"nm": "椭圆路径 1",
|
||||
"mn": "ADBE Vector Shape - Ellipse",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.149019607843,
|
||||
0.501960784314,
|
||||
0.921568627451,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 15,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 2,
|
||||
"lj": 1,
|
||||
"ml": 4,
|
||||
"bm": 0,
|
||||
"nm": "描边 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
-1.5,
|
||||
-6.5
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "变换"
|
||||
}
|
||||
],
|
||||
"nm": "椭圆 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tm",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 1
|
||||
},
|
||||
"e": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 0,
|
||||
"s": [
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 46,
|
||||
"s": [
|
||||
25
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 96,
|
||||
"s": [
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 191,
|
||||
"s": [
|
||||
100
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"o": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 0,
|
||||
"s": [
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": {
|
||||
"x": [
|
||||
0.833
|
||||
],
|
||||
"y": [
|
||||
0.833
|
||||
]
|
||||
},
|
||||
"o": {
|
||||
"x": [
|
||||
0.167
|
||||
],
|
||||
"y": [
|
||||
0.167
|
||||
]
|
||||
},
|
||||
"t": 96,
|
||||
"s": [
|
||||
360
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 191,
|
||||
"s": [
|
||||
720
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"m": 1,
|
||||
"ix": 2,
|
||||
"nm": "修剪路径 1",
|
||||
"mn": "ADBE Vector Filter - Trim",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 360,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 3,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 1",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
251.5,
|
||||
256.5,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"d": 1,
|
||||
"ty": "el",
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
321,
|
||||
321
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"nm": "椭圆路径 1",
|
||||
"mn": "ADBE Vector Shape - Ellipse",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0.686274509804,
|
||||
0.686274509804,
|
||||
0.686274509804,
|
||||
1
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 4
|
||||
},
|
||||
"w": {
|
||||
"a": 0,
|
||||
"k": 15,
|
||||
"ix": 5
|
||||
},
|
||||
"lc": 1,
|
||||
"lj": 1,
|
||||
"ml": 4,
|
||||
"bm": 0,
|
||||
"nm": "描边 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
-1.5,
|
||||
-6.5
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 3
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 6
|
||||
},
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 7
|
||||
},
|
||||
"sk": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 4
|
||||
},
|
||||
"sa": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 5
|
||||
},
|
||||
"nm": "变换"
|
||||
}
|
||||
],
|
||||
"nm": "椭圆 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 360,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 0,
|
||||
"nm": "完整动画",
|
||||
"refId": "comp_0",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": {
|
||||
"a": 0,
|
||||
"k": 100,
|
||||
"ix": 11
|
||||
},
|
||||
"r": {
|
||||
"a": 0,
|
||||
"k": 0,
|
||||
"ix": 10
|
||||
},
|
||||
"p": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
250,
|
||||
250,
|
||||
0
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"a": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
250,
|
||||
250,
|
||||
0
|
||||
],
|
||||
"ix": 1
|
||||
},
|
||||
"s": {
|
||||
"a": 0,
|
||||
"k": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"ix": 6
|
||||
}
|
||||
},
|
||||
"ao": 0,
|
||||
"w": 500,
|
||||
"h": 500,
|
||||
"ip": 0,
|
||||
"op": 96,
|
||||
"st": 0,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": []
|
||||
}
|
||||
27
example/app/src/main/assets/yunweixin.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"result": {
|
||||
"data": {
|
||||
"image": [
|
||||
{
|
||||
"order_img": "http://localhost/file.php?img=order__2020__09__23__2020092317123855002746__2020092317534044856.jpg",
|
||||
"order_img_cloud": ""
|
||||
}
|
||||
],
|
||||
"order": {
|
||||
"address": "陕西省西安市雁塔区科技二路清华科技园",
|
||||
"contractnum": "",
|
||||
"custorname": "demo",
|
||||
"custorphone": "13575542727",
|
||||
"ordernum": "2020092317123855002746",
|
||||
"ordertype": "4",
|
||||
"recudesum": "100000.00",
|
||||
"remark": "出彩出差错错错",
|
||||
"systemtime": "2020-09-23 17:53:40",
|
||||
"user_name": "王总"
|
||||
}
|
||||
},
|
||||
"msg": "获取成功",
|
||||
"success": 0
|
||||
},
|
||||
"status": 0
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.ruilaizi.example;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* 模板项目 Application,可在此做全局初始化。
|
||||
*/
|
||||
public class BaseApplication extends Application {
|
||||
|
||||
private static Context sContext;
|
||||
private static BaseApplication sInstance;
|
||||
|
||||
public static BaseApplication getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public static Context getContext() {
|
||||
return sContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
sInstance = this;
|
||||
sContext = getApplicationContext();
|
||||
}
|
||||
}
|
||||
198
example/app/src/main/java/com/ruilaizi/example/MainActivity.java
Normal file
@@ -0,0 +1,198 @@
|
||||
package com.ruilaizi.example;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.chip.Chip;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.slider.Slider;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.ruilaizi.example.databinding.ActivityMainBinding;
|
||||
import com.ruilaizi.example.ui.MainViewModel;
|
||||
|
||||
/**
|
||||
* 文思泉涌 - AI 文本生成助手主界面。
|
||||
* Material 3 风格,预设提示、输入、参数滑块、生成、流式结果与复制/重新生成/续写。
|
||||
*/
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private ActivityMainBinding binding;
|
||||
private MainViewModel viewModel;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
viewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(MainViewModel.class);
|
||||
|
||||
setupPresets();
|
||||
setupInput();
|
||||
setupSliders();
|
||||
setupGenerateButton();
|
||||
setupResultAndActions();
|
||||
if (binding.btnSettings != null) {
|
||||
binding.btnSettings.setOnClickListener(v -> showApiKeyDialog());
|
||||
}
|
||||
observeViewModel();
|
||||
showApiKeyHintIfNeeded();
|
||||
}
|
||||
|
||||
private void setupPresets() {
|
||||
setPresetChip(binding.presetEmail, getString(R.string.preset_email));
|
||||
setPresetChip(binding.presetProduct, getString(R.string.preset_product));
|
||||
setPresetChip(binding.presetStory, getString(R.string.preset_story));
|
||||
setPresetChip(binding.presetSummary, getString(R.string.preset_summary));
|
||||
setPresetChip(binding.presetPoem, getString(R.string.preset_poem));
|
||||
}
|
||||
|
||||
private void setPresetChip(Chip chip, String text) {
|
||||
if (chip == null) return;
|
||||
chip.setOnClickListener(v -> {
|
||||
TextInputEditText input = binding.inputPrompt;
|
||||
if (input != null) {
|
||||
Editable ed = input.getText();
|
||||
String current = ed != null ? ed.toString() : "";
|
||||
input.setText(current.isEmpty() ? text : current + "\n" + text);
|
||||
viewModel.setPrompt(input.getText() != null ? input.getText().toString() : "");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupInput() {
|
||||
TextInputEditText input = binding.inputPrompt;
|
||||
if (input != null) {
|
||||
input.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
viewModel.setPrompt(s != null ? s.toString() : "");
|
||||
}
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setupSliders() {
|
||||
Slider lengthSlider = binding.sliderLength;
|
||||
if (lengthSlider != null) {
|
||||
lengthSlider.setValue(1f);
|
||||
lengthSlider.addOnChangeListener((slider, value, fromUser) -> {
|
||||
if (fromUser) viewModel.setLengthLevel((int) value);
|
||||
});
|
||||
}
|
||||
Slider tempSlider = binding.sliderTemperature;
|
||||
if (tempSlider != null) {
|
||||
tempSlider.setValue(1f);
|
||||
tempSlider.addOnChangeListener((slider, value, fromUser) -> {
|
||||
if (fromUser) viewModel.setTemperatureLevel((int) value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setupGenerateButton() {
|
||||
MaterialButton btn = binding.btnGenerate;
|
||||
if (btn != null) {
|
||||
btn.setOnClickListener(v -> viewModel.generate());
|
||||
}
|
||||
}
|
||||
|
||||
private void setupResultAndActions() {
|
||||
MaterialButton copyBtn = binding.btnCopy;
|
||||
if (copyBtn != null) copyBtn.setOnClickListener(v -> viewModel.copyResult(this));
|
||||
MaterialButton regenBtn = binding.btnRegenerate;
|
||||
if (regenBtn != null) regenBtn.setOnClickListener(v -> viewModel.regenerate());
|
||||
MaterialButton continueBtn = binding.btnContinue;
|
||||
if (continueBtn != null) continueBtn.setOnClickListener(v -> viewModel.continueEdit());
|
||||
}
|
||||
|
||||
private void observeViewModel() {
|
||||
viewModel.getResultLiveData().observe(this, text -> {
|
||||
TextView resultText = binding.resultText;
|
||||
if (resultText != null) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
resultText.setText(R.string.result_placeholder);
|
||||
resultText.setTextColor(getResources().getColor(R.color.colorText, getTheme()));
|
||||
} else {
|
||||
resultText.setText(text);
|
||||
resultText.setTextColor(getResources().getColor(R.color.colorTextDark, getTheme()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
viewModel.getLoadingLiveData().observe(this, loading -> {
|
||||
ProgressBar progress = binding.progressBar;
|
||||
MaterialButton btn = binding.btnGenerate;
|
||||
if (progress != null) progress.setVisibility(loading != null && loading ? View.VISIBLE : View.GONE);
|
||||
if (btn != null) btn.setEnabled(loading == null || !loading);
|
||||
});
|
||||
|
||||
viewModel.getErrorLiveData().observe(this, error -> {
|
||||
if (error != null && !error.isEmpty()) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setMessage(error)
|
||||
.setPositiveButton(android.R.string.ok, (d, w) -> viewModel.clearError())
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
viewModel.getSnackbarLiveData().observe(this, msg -> {
|
||||
if (msg != null && !msg.isEmpty()) {
|
||||
Snackbar.make(binding.getRoot(), msg, Snackbar.LENGTH_SHORT).show();
|
||||
viewModel.clearSnackbar();
|
||||
}
|
||||
});
|
||||
|
||||
viewModel.getLengthLevelLiveData().observe(this, level -> {
|
||||
Slider s = binding.sliderLength;
|
||||
if (s != null && level != null && s.getValue() != level) s.setValue(level.floatValue());
|
||||
});
|
||||
viewModel.getTemperatureLevelLiveData().observe(this, level -> {
|
||||
Slider s = binding.sliderTemperature;
|
||||
if (s != null && level != null && s.getValue() != level) s.setValue(level.floatValue());
|
||||
});
|
||||
viewModel.getPromptLiveData().observe(this, prompt -> {
|
||||
TextInputEditText input = binding.inputPrompt;
|
||||
if (input != null && prompt != null) {
|
||||
String current = input.getText() != null ? input.getText().toString() : "";
|
||||
if (!current.equals(prompt)) input.setText(prompt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showApiKeyHintIfNeeded() {
|
||||
if (viewModel.getApiKey() == null || viewModel.getApiKey().isEmpty()) {
|
||||
Snackbar.make(binding.getRoot(), "请在设置中配置 API Key 后使用生成功能", Snackbar.LENGTH_LONG)
|
||||
.setAction("设置", v -> showApiKeyDialog())
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void showApiKeyDialog() {
|
||||
android.widget.EditText edit = new android.widget.EditText(this);
|
||||
edit.setHint("API Key(建议使用后端网关,不在此填写)");
|
||||
edit.setText(viewModel.getApiKey());
|
||||
edit.setMinEms(20);
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("API Key")
|
||||
.setView(edit)
|
||||
.setPositiveButton(android.R.string.ok, (d, w) -> {
|
||||
viewModel.setApiKey(edit.getText() != null ? edit.getText().toString().trim() : "");
|
||||
Snackbar.make(binding.getRoot(), "已保存", Snackbar.LENGTH_SHORT).show();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.ruilaizi.example.base;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.WindowManager;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.ruilaizi.example.dialog.LoadingDialog;
|
||||
import com.ruilaizi.example.utils.StatusBarUtil;
|
||||
import com.ruilaizi.example.utils.ToastUtils;
|
||||
|
||||
/**
|
||||
* 模板项目 Activity 基类,提供通用能力(状态栏、权限、Toast、Loading 等)。
|
||||
*/
|
||||
public abstract class BaseActivity extends FragmentActivity {
|
||||
|
||||
private LoadingDialog mProgressDialog;
|
||||
public static final int REQUEST_CALL_PERMISSION = 10111;
|
||||
protected final String TAG = this.getClass().getSimpleName();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
StatusBarUtil.transparencyBar(this);
|
||||
StatusBarUtil.StatusBarLightMode(this);
|
||||
initFontScale();
|
||||
}
|
||||
|
||||
protected void initFontScale() {
|
||||
Configuration configuration = getResources().getConfiguration();
|
||||
configuration.fontScale = 1f;
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
metrics.scaledDensity = configuration.fontScale * metrics.density;
|
||||
getBaseContext().getResources().updateConfiguration(configuration, metrics);
|
||||
}
|
||||
|
||||
public boolean checkReadPermission(String permission, int requestCode) {
|
||||
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
}
|
||||
ActivityCompat.requestPermissions(this, new String[]{permission}, requestCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void requestPermission(int code, String... permissions) {
|
||||
ActivityCompat.requestPermissions(this, permissions, code);
|
||||
}
|
||||
|
||||
public void showProgressDialog(String message, Context context) {
|
||||
if (mProgressDialog == null) {
|
||||
mProgressDialog = new LoadingDialog(context);
|
||||
mProgressDialog.setCanceledOnTouchOutside(false);
|
||||
}
|
||||
mProgressDialog.show();
|
||||
}
|
||||
|
||||
public void dismissProgressDialog() {
|
||||
if (mProgressDialog != null && mProgressDialog.isShowing()) {
|
||||
mProgressDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasPermission(String... permissions) {
|
||||
for (String p : permissions) {
|
||||
if (ContextCompat.checkSelfPermission(this, p) != PackageManager.PERMISSION_GRANTED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void hiddenStatusBar() {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
}
|
||||
|
||||
public void startActivity(Class<?> clz) {
|
||||
startActivity(new Intent(this, clz));
|
||||
}
|
||||
|
||||
public void changeStatusBarColor(@ColorRes int color) {
|
||||
}
|
||||
|
||||
/** 简单提示对话框 */
|
||||
public void messageDialog(String msg) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setMessage(msg)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public boolean isNetworkConnected(Context context, String tipWhenNoNetwork) {
|
||||
if (!com.ruilaizi.example.utils.NetUtils.isConnected(context)) {
|
||||
ToastUtils.showToast(context, tipWhenNoNetwork);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 子类在布局中提供 id 为 iv_left_btn 的 View 时,可调用此方法绑定返回。 */
|
||||
public void initNormalBack() {
|
||||
int id = getResources().getIdentifier("iv_left_btn", "id", getPackageName());
|
||||
if (id != 0) {
|
||||
View back = findViewById(id);
|
||||
if (back != null) back.setOnClickListener(v -> finish());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.ruilaizi.example.common;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2016/1/10.
|
||||
* 作者:xudiwei
|
||||
* <p>
|
||||
* 描述:常量类
|
||||
*/
|
||||
|
||||
public class Constants {
|
||||
/**
|
||||
* 模拟网络请求成功
|
||||
*/
|
||||
public static final int SUCCESS = 1;
|
||||
/**
|
||||
* 模拟网络请求失败
|
||||
*/
|
||||
public static final int FAILE = 0;
|
||||
|
||||
/**
|
||||
* 模拟数据网络耗时
|
||||
*/
|
||||
public static final int LOADING_TIME = 1500;
|
||||
|
||||
/**
|
||||
* 模拟数据每页长度
|
||||
*/
|
||||
public static final int LIMIT = 20;
|
||||
|
||||
/**
|
||||
* 讯飞语音appid
|
||||
*/
|
||||
public static final String IFLYTEK_APPID = "58a176c2";
|
||||
/**
|
||||
* 当前App创建在Sd卡里的根目录,其它的目录都要创建在App_root_dir里面。
|
||||
*/
|
||||
public static final String APP_ROOT_DIR = "LifeTree";
|
||||
/**
|
||||
* 存图片的dir
|
||||
*/
|
||||
public static final String IMG_DIR = APP_ROOT_DIR + "/img";
|
||||
/**
|
||||
* 图片预览里保存图片的目录
|
||||
*/
|
||||
public static final String SAVE_IMG_DIR = APP_ROOT_DIR + "/save";
|
||||
/**
|
||||
* apk下载存放目录
|
||||
*/
|
||||
public static final String APK_DIR = APP_ROOT_DIR + "/apk";
|
||||
/**
|
||||
* 缓存目录
|
||||
*/
|
||||
public static final String CACHE_DIR = APP_ROOT_DIR + "/cache";
|
||||
/**
|
||||
* SharedPreferences 文件名
|
||||
*/
|
||||
public static final String SP_CONFIG_FILE_NAME = "config";
|
||||
private static final String TAG = "Constants";
|
||||
/**
|
||||
* 当前用户的user_id(token)
|
||||
*/
|
||||
private static String userId = "";
|
||||
/**
|
||||
* 当前用户的角色 1=普通用户 2=老师 3=义工
|
||||
*/
|
||||
// private static int role = -1;
|
||||
/**
|
||||
* 当前用户所在的班级
|
||||
*/
|
||||
private static String classId = "";
|
||||
/**
|
||||
* 当前用户的IMidentify
|
||||
*/
|
||||
private static String identify = "";
|
||||
|
||||
|
||||
/**
|
||||
* 消息内存中的用户相关的信息。
|
||||
*/
|
||||
public static void clearAccountInfo() {
|
||||
userId = "";
|
||||
//role = -1;
|
||||
classId = "";
|
||||
identify = "";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ruilaizi.example.data.api;
|
||||
|
||||
/**
|
||||
* AI 流式生成接口。实现类可对接 OpenAI / Gemini / 国内合规 API。
|
||||
*/
|
||||
public interface AIService {
|
||||
|
||||
/**
|
||||
* 请求流式生成。在后台线程执行,通过 callback 在主线程或调用线程回调。
|
||||
*
|
||||
* @param prompt 用户提示词
|
||||
* @param maxTokens 最大 token 数(短/中/长 可映射为具体数值)
|
||||
* @param temperature 温度 0~2
|
||||
* @param apiKey API 密钥(由调用方从 ApiKeyProvider 获取)
|
||||
* @param callback 流式回调
|
||||
*/
|
||||
void requestStream(String prompt, int maxTokens, float temperature,
|
||||
String apiKey, StreamCallback callback);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.ruilaizi.example.data.api;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.security.crypto.EncryptedSharedPreferences;
|
||||
import androidx.security.crypto.MasterKey;
|
||||
|
||||
import com.ruilaizi.example.BuildConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* 提供 API Key,优先使用用户设置(EncryptedSharedPreferences)。
|
||||
* 未设置时使用 BuildConfig.DEFAULT_API_KEY(打包进 APK 的默认 DeepSeek Key)。
|
||||
*/
|
||||
public class ApiKeyProvider {
|
||||
|
||||
private static final String PREFS_NAME = "api_key_prefs";
|
||||
private static final String KEY_API_KEY = "api_key";
|
||||
|
||||
private final SharedPreferences prefs;
|
||||
|
||||
public ApiKeyProvider(Context context) {
|
||||
SharedPreferences fallback = context.getApplicationContext()
|
||||
.getSharedPreferences(PREFS_NAME + "_plain", Context.MODE_PRIVATE);
|
||||
SharedPreferences encrypted = fallback;
|
||||
try {
|
||||
MasterKey masterKey = new MasterKey.Builder(context.getApplicationContext())
|
||||
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
||||
.build();
|
||||
encrypted = EncryptedSharedPreferences.create(
|
||||
context.getApplicationContext(),
|
||||
PREFS_NAME,
|
||||
masterKey,
|
||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||
);
|
||||
} catch (GeneralSecurityException | IOException ignored) {
|
||||
}
|
||||
prefs = encrypted;
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
String saved = prefs.getString(KEY_API_KEY, "");
|
||||
if (!TextUtils.isEmpty(saved)) return saved;
|
||||
return BuildConfig.DEFAULT_API_KEY != null ? BuildConfig.DEFAULT_API_KEY : "";
|
||||
}
|
||||
|
||||
public void setApiKey(String apiKey) {
|
||||
prefs.edit().putString(KEY_API_KEY, apiKey != null ? apiKey : "").apply();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.ruilaizi.example.data.api;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import com.ruilaizi.example.BuildConfig;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* 使用 HttpURLConnection 实现 OpenAI 兼容的 Chat Completions 流式接口(SSE)。
|
||||
* 当前默认对接 DeepSeek API(https://api.deepseek.com/v1),模型 deepseek-chat。
|
||||
*/
|
||||
public class OpenAIStreamService implements AIService {
|
||||
|
||||
private static final String TAG = "OpenAIStreamService";
|
||||
private static final String CHAT_URL = "chat/completions";
|
||||
private static final String MODEL_DEEPSEEK = "deepseek-chat";
|
||||
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
private final String baseUrl;
|
||||
|
||||
public OpenAIStreamService(String baseUrl) {
|
||||
this.baseUrl = baseUrl == null || baseUrl.isEmpty()
|
||||
? BuildConfig.API_BASE_URL
|
||||
: baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestStream(String prompt, int maxTokens, float temperature,
|
||||
String apiKey, StreamCallback callback) {
|
||||
if (callback == null) return;
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
doRequestStream(prompt, maxTokens, temperature, apiKey, callback);
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, "requestStream error", t);
|
||||
postError(callback, t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doRequestStream(String prompt, int maxTokens, float temperature,
|
||||
String apiKey, StreamCallback callback) throws Exception {
|
||||
String urlStr = baseUrl + CHAT_URL;
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setConnectTimeout(30_000);
|
||||
conn.setReadTimeout(60_000);
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
conn.setRequestProperty("Authorization", "Bearer " + apiKey);
|
||||
conn.setRequestProperty("Accept", "text/event-stream");
|
||||
|
||||
JSONObject body = new JSONObject();
|
||||
body.put("model", MODEL_DEEPSEEK);
|
||||
body.put("stream", true);
|
||||
body.put("max_tokens", maxTokens);
|
||||
body.put("temperature", temperature);
|
||||
JSONArray messages = new JSONArray();
|
||||
JSONObject user = new JSONObject();
|
||||
user.put("role", "user");
|
||||
user.put("content", prompt);
|
||||
messages.put(user);
|
||||
body.put("messages", messages);
|
||||
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
os.write(body.toString().getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
int code = conn.getResponseCode();
|
||||
if (code != 200) {
|
||||
String err = readAll(conn.getErrorStream());
|
||||
throw new RuntimeException("HTTP " + code + ": " + err);
|
||||
}
|
||||
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
||||
String line;
|
||||
StringBuilder fullContent = new StringBuilder();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.startsWith("data: ")) {
|
||||
String data = line.substring(6).trim();
|
||||
if ("[DONE]".equals(data)) break;
|
||||
try {
|
||||
JSONObject obj = new JSONObject(data);
|
||||
JSONArray choices = obj.optJSONArray("choices");
|
||||
if (choices != null && choices.length() > 0) {
|
||||
JSONObject choice = choices.getJSONObject(0);
|
||||
JSONObject delta = choice.optJSONObject("delta");
|
||||
if (delta != null && delta.has("content")) {
|
||||
String content = delta.getString("content");
|
||||
fullContent.append(content);
|
||||
postChunk(callback, content);
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
postComplete(callback);
|
||||
}
|
||||
|
||||
private static String readAll(java.io.InputStream is) {
|
||||
if (is == null) return "";
|
||||
try (BufferedReader r = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = r.readLine()) != null) sb.append(line).append("\n");
|
||||
return sb.toString();
|
||||
} catch (Exception e) {
|
||||
return e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
private void postChunk(StreamCallback callback, String chunk) {
|
||||
mainHandler.post(() -> callback.onChunk(chunk));
|
||||
}
|
||||
|
||||
private void postComplete(StreamCallback callback) {
|
||||
mainHandler.post(callback::onComplete);
|
||||
}
|
||||
|
||||
private void postError(StreamCallback callback, Throwable t) {
|
||||
mainHandler.post(() -> callback.onError(t));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruilaizi.example.data.api;
|
||||
|
||||
/**
|
||||
* 流式生成时的回调:每收到一段文本就回调一次,结束时 onComplete,出错时 onError。
|
||||
*/
|
||||
public interface StreamCallback {
|
||||
|
||||
void onChunk(String textChunk);
|
||||
|
||||
void onComplete();
|
||||
|
||||
void onError(Throwable t);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruilaizi.example.data.db;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.room.Database;
|
||||
import androidx.room.Room;
|
||||
import androidx.room.RoomDatabase;
|
||||
|
||||
@Database(entities = {GenerationRecord.class}, version = 1, exportSchema = false)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
|
||||
private static volatile AppDatabase INSTANCE;
|
||||
|
||||
public static AppDatabase getInstance(Context context) {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AppDatabase.class) {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = Room.databaseBuilder(
|
||||
context.getApplicationContext(),
|
||||
AppDatabase.class,
|
||||
"wensiquanyong_db"
|
||||
).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public abstract GenerationRecordDao generationRecordDao();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.ruilaizi.example.data.db;
|
||||
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
/**
|
||||
* 单条生成记录,用于 Room 缓存最近生成内容。
|
||||
*/
|
||||
@Entity(tableName = "generation_records")
|
||||
public class GenerationRecord {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
public long id;
|
||||
|
||||
/** 用户输入的提示词 */
|
||||
public String prompt;
|
||||
/** AI 生成的结果全文 */
|
||||
public String result;
|
||||
/** 生成长度:0 短 1 中 2 长 */
|
||||
public int maxTokensLevel;
|
||||
/** 创意程度:0 保守 1 平衡 2 创意 */
|
||||
public int temperatureLevel;
|
||||
/** 创建时间戳 */
|
||||
public long createdAt;
|
||||
|
||||
public GenerationRecord() {}
|
||||
|
||||
@Ignore
|
||||
public GenerationRecord(String prompt, String result, int maxTokensLevel, int temperatureLevel) {
|
||||
this.prompt = prompt;
|
||||
this.result = result;
|
||||
this.maxTokensLevel = maxTokensLevel;
|
||||
this.temperatureLevel = temperatureLevel;
|
||||
this.createdAt = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ruilaizi.example.data.db;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Dao
|
||||
public interface GenerationRecordDao {
|
||||
|
||||
@Insert
|
||||
long insert(GenerationRecord record);
|
||||
|
||||
@Query("SELECT * FROM generation_records ORDER BY createdAt DESC LIMIT 10")
|
||||
LiveData<List<GenerationRecord>> getRecentRecords();
|
||||
|
||||
@Query("DELETE FROM generation_records WHERE id NOT IN (SELECT id FROM generation_records ORDER BY createdAt DESC LIMIT 10)")
|
||||
void keepOnlyRecent();
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.ruilaizi.example.data.repository;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
|
||||
import com.ruilaizi.example.data.api.AIService;
|
||||
import com.ruilaizi.example.data.api.ApiKeyProvider;
|
||||
import com.ruilaizi.example.data.api.StreamCallback;
|
||||
import com.ruilaizi.example.data.db.AppDatabase;
|
||||
import com.ruilaizi.example.data.db.GenerationRecord;
|
||||
import com.ruilaizi.example.data.db.GenerationRecordDao;
|
||||
|
||||
/**
|
||||
* 生成业务仓库:调用 AI 流式接口,并缓存记录到 Room。
|
||||
*/
|
||||
public class GenerationRepository {
|
||||
|
||||
private final AIService aiService;
|
||||
private final ApiKeyProvider apiKeyProvider;
|
||||
private final GenerationRecordDao dao;
|
||||
|
||||
public GenerationRepository(Context context) {
|
||||
apiKeyProvider = new ApiKeyProvider(context);
|
||||
aiService = new com.ruilaizi.example.data.api.OpenAIStreamService(null);
|
||||
dao = AppDatabase.getInstance(context).generationRecordDao();
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
return apiKeyProvider.getApiKey();
|
||||
}
|
||||
|
||||
public void setApiKey(String key) {
|
||||
apiKeyProvider.setApiKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将长度档位转为 max_tokens:0 短 1 中 2 长
|
||||
*/
|
||||
public static int levelToMaxTokens(int level) {
|
||||
switch (level) {
|
||||
case 0: return 256;
|
||||
case 1: return 512;
|
||||
case 2: return 1024;
|
||||
default: return 512;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将创意档位转为 temperature:0 保守 1 平衡 2 创意
|
||||
*/
|
||||
public static float levelToTemperature(int level) {
|
||||
switch (level) {
|
||||
case 0: return 0.3f;
|
||||
case 1: return 0.7f;
|
||||
case 2: return 1.2f;
|
||||
default: return 0.7f;
|
||||
}
|
||||
}
|
||||
|
||||
public void requestStream(String prompt, int maxTokensLevel, int temperatureLevel,
|
||||
StreamCallback callback) {
|
||||
int maxTokens = levelToMaxTokens(maxTokensLevel);
|
||||
float temperature = levelToTemperature(temperatureLevel);
|
||||
String apiKey = apiKeyProvider.getApiKey();
|
||||
aiService.requestStream(prompt, maxTokens, temperature, apiKey, callback);
|
||||
}
|
||||
|
||||
public void saveRecord(GenerationRecord record) {
|
||||
new Thread(() -> {
|
||||
dao.insert(record);
|
||||
dao.keepOnlyRecent();
|
||||
}).start();
|
||||
}
|
||||
|
||||
public LiveData<java.util.List<GenerationRecord>> getRecentRecords() {
|
||||
return dao.getRecentRecords();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.ruilaizi.example.dialog;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
/**
|
||||
* 日期:2017.01.11
|
||||
* <p>
|
||||
* 作者:xudiwei
|
||||
* <p>
|
||||
* 描述:base对话框
|
||||
*/
|
||||
public class BaseDialog extends Dialog implements View.OnClickListener {
|
||||
|
||||
protected Context mContext;
|
||||
private View view;
|
||||
private boolean isDismiss = true;
|
||||
|
||||
public BaseDialog(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public BaseDialog(Context context, int themeResId) {
|
||||
super(context, themeResId);
|
||||
}
|
||||
|
||||
public BaseDialog(Context context, View view, int themeResId) {
|
||||
super(context, themeResId);
|
||||
this.mContext = context;
|
||||
this.view = view;
|
||||
this.view.setOnClickListener(this);
|
||||
setContentView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
|
||||
WindowManager windowManager = ((Activity) mContext).getWindowManager();
|
||||
Display display = windowManager.getDefaultDisplay();
|
||||
WindowManager.LayoutParams lp = getWindow().getAttributes();
|
||||
lp.width = display.getWidth(); //设置宽度
|
||||
getWindow().setAttributes(lp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isDismiss) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当点击对话框外面时是否关闭对话框,默认是要关闭对话框
|
||||
*
|
||||
* @param b
|
||||
*/
|
||||
public void clickOutsideDismiss(boolean b) {
|
||||
this.isDismiss = b;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.ruilaizi.example.dialog;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import com.ruilaizi.example.R;
|
||||
|
||||
/**
|
||||
* Created by: xudiwei
|
||||
* <p>
|
||||
* on: 2017/5/16.
|
||||
* <p>
|
||||
* 描述:加载中禁止用户手机关闭的对话框
|
||||
*/
|
||||
|
||||
public class LoadingDialog extends BaseDialog {
|
||||
private boolean mClose = true;
|
||||
|
||||
public LoadingDialog(Context context) {
|
||||
super(context, View.inflate(context, R.layout.dialog_loading, null), R.style.loadingDialog);
|
||||
setCanceledOnTouchOutside(false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// super.onClick(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
super.onBackPressed();
|
||||
if (mClose) {
|
||||
((Activity) mContext).finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当用户按下返回键时是否关闭Activity
|
||||
* @param close
|
||||
*/
|
||||
public void setPressBackCloseActivity(boolean close) {
|
||||
this.mClose = close;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package com.ruilaizi.example.ui;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.ruilaizi.example.data.api.StreamCallback;
|
||||
import com.ruilaizi.example.data.db.GenerationRecord;
|
||||
import com.ruilaizi.example.data.repository.GenerationRepository;
|
||||
|
||||
/**
|
||||
* 主界面 MVVM ViewModel:提示词、参数、生成结果、加载状态及复制/重新生成/续写。
|
||||
*/
|
||||
public class MainViewModel extends AndroidViewModel {
|
||||
|
||||
private final GenerationRepository repository;
|
||||
private final MutableLiveData<String> promptLiveData = new MutableLiveData<>("");
|
||||
private final MutableLiveData<String> resultLiveData = new MutableLiveData<>("");
|
||||
private final MutableLiveData<Boolean> loadingLiveData = new MutableLiveData<>(false);
|
||||
private final MutableLiveData<String> errorLiveData = new MutableLiveData<>();
|
||||
private final MutableLiveData<String> snackbarLiveData = new MutableLiveData<>();
|
||||
|
||||
/** 生成长度:0 短 1 中 2 长 */
|
||||
private final MutableLiveData<Integer> lengthLevelLiveData = new MutableLiveData<>(1);
|
||||
/** 创意程度:0 保守 1 平衡 2 创意 */
|
||||
private final MutableLiveData<Integer> temperatureLevelLiveData = new MutableLiveData<>(1);
|
||||
|
||||
/** 最近一次生成用的 prompt,用于“重新生成” */
|
||||
private String lastPrompt;
|
||||
private int lastLengthLevel = 1;
|
||||
private int lastTemperatureLevel = 1;
|
||||
|
||||
private final StringBuilder streamingBuffer = new StringBuilder();
|
||||
|
||||
public MainViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
repository = new GenerationRepository(application);
|
||||
}
|
||||
|
||||
public LiveData<String> getPromptLiveData() { return promptLiveData; }
|
||||
public LiveData<String> getResultLiveData() { return resultLiveData; }
|
||||
public LiveData<Boolean> getLoadingLiveData() { return loadingLiveData; }
|
||||
public LiveData<String> getErrorLiveData() { return errorLiveData; }
|
||||
public LiveData<String> getSnackbarLiveData() { return snackbarLiveData; }
|
||||
public LiveData<Integer> getLengthLevelLiveData() { return lengthLevelLiveData; }
|
||||
public LiveData<Integer> getTemperatureLevelLiveData() { return temperatureLevelLiveData; }
|
||||
|
||||
public void setPrompt(String prompt) {
|
||||
promptLiveData.setValue(prompt != null ? prompt : "");
|
||||
}
|
||||
|
||||
public void setLengthLevel(int level) {
|
||||
if (level < 0) level = 0;
|
||||
if (level > 2) level = 2;
|
||||
lengthLevelLiveData.setValue(level);
|
||||
}
|
||||
|
||||
public void setTemperatureLevel(int level) {
|
||||
if (level < 0) level = 0;
|
||||
if (level > 2) level = 2;
|
||||
temperatureLevelLiveData.setValue(level);
|
||||
}
|
||||
|
||||
/** 生成:使用当前 prompt 与参数 */
|
||||
public void generate() {
|
||||
String prompt = promptLiveData.getValue();
|
||||
if (prompt == null) prompt = "";
|
||||
prompt = prompt.trim();
|
||||
if (prompt.isEmpty()) {
|
||||
snackbarLiveData.setValue("请输入提示词");
|
||||
return;
|
||||
}
|
||||
if (repository.getApiKey() == null || repository.getApiKey().isEmpty()) {
|
||||
errorLiveData.setValue("请先在设置中配置 API Key,或使用后端网关");
|
||||
return;
|
||||
}
|
||||
lastPrompt = prompt;
|
||||
lastLengthLevel = lengthLevelLiveData.getValue() != null ? lengthLevelLiveData.getValue() : 1;
|
||||
lastTemperatureLevel = temperatureLevelLiveData.getValue() != null ? temperatureLevelLiveData.getValue() : 1;
|
||||
streamingBuffer.setLength(0);
|
||||
resultLiveData.setValue("");
|
||||
loadingLiveData.setValue(true);
|
||||
errorLiveData.setValue(null);
|
||||
|
||||
repository.requestStream(prompt, lastLengthLevel, lastTemperatureLevel, new StreamCallback() {
|
||||
@Override
|
||||
public void onChunk(String textChunk) {
|
||||
streamingBuffer.append(textChunk);
|
||||
resultLiveData.postValue(streamingBuffer.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
loadingLiveData.postValue(false);
|
||||
String full = streamingBuffer.toString();
|
||||
if (full.length() > 0) {
|
||||
repository.saveRecord(new GenerationRecord(
|
||||
lastPrompt, full, lastLengthLevel, lastTemperatureLevel));
|
||||
}
|
||||
snackbarLiveData.postValue("生成完成");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
loadingLiveData.postValue(false);
|
||||
errorLiveData.postValue(t != null ? t.getMessage() : "生成失败");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 重新生成:用上次的 prompt 和参数再调一次 */
|
||||
public void regenerate() {
|
||||
if (lastPrompt != null && !lastPrompt.isEmpty()) {
|
||||
setPrompt(lastPrompt);
|
||||
setLengthLevel(lastLengthLevel);
|
||||
setTemperatureLevel(lastTemperatureLevel);
|
||||
generate();
|
||||
} else {
|
||||
snackbarLiveData.setValue("请先完成一次生成");
|
||||
}
|
||||
}
|
||||
|
||||
/** 续写:把当前结果作为新 prompt,清空结果区,可编辑后生成 */
|
||||
public void continueEdit() {
|
||||
String result = resultLiveData.getValue();
|
||||
if (result != null && !result.isEmpty()) {
|
||||
setPrompt(result);
|
||||
resultLiveData.setValue("");
|
||||
snackbarLiveData.setValue("已填入输入框,可修改后点击生成");
|
||||
} else {
|
||||
snackbarLiveData.setValue("暂无生成结果可续写");
|
||||
}
|
||||
}
|
||||
|
||||
/** 复制结果到剪贴板 */
|
||||
public void copyResult(Context context) {
|
||||
String result = resultLiveData.getValue();
|
||||
if (result == null || result.isEmpty()) {
|
||||
snackbarLiveData.setValue("暂无内容可复制");
|
||||
return;
|
||||
}
|
||||
ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (cm != null) {
|
||||
cm.setPrimaryClip(ClipData.newPlainText("AI生成", result));
|
||||
snackbarLiveData.setValue("已复制到剪贴板");
|
||||
}
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
return repository.getApiKey();
|
||||
}
|
||||
|
||||
public void setApiKey(String key) {
|
||||
repository.setApiKey(key);
|
||||
}
|
||||
|
||||
public void clearError() {
|
||||
errorLiveData.setValue(null);
|
||||
}
|
||||
|
||||
public void clearSnackbar() {
|
||||
snackbarLiveData.setValue(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2016 android@19code.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.ruilaizi.example.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.ScanResult;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Blog : http://blog.csdn.net/u011240877
|
||||
* 网络工具
|
||||
*
|
||||
*/
|
||||
public class NetUtils {
|
||||
|
||||
public static final String NETWORK_TYPE_WIFI = "wifi";
|
||||
public static final String NETWORK_TYPE_3G = "3g";
|
||||
public static final String NETWORK_TYPE_2G = "2g";
|
||||
public static final String NETWORK_TYPE_WAP = "wap";
|
||||
public static final String NETWORK_TYPE_UNKNOWN = "unknown";
|
||||
public static final String NETWORK_TYPE_DISCONNECT = "disconnect";
|
||||
|
||||
public static int getNetworkType(Context context) {
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo networkInfo = connectivityManager == null ? null : connectivityManager.getActiveNetworkInfo();
|
||||
return networkInfo == null ? -1 : networkInfo.getType();
|
||||
}
|
||||
|
||||
public static String getNetworkTypeName(Context context) {
|
||||
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo networkInfo;
|
||||
String type = NETWORK_TYPE_DISCONNECT;
|
||||
if (manager == null || (networkInfo = manager.getActiveNetworkInfo()) == null) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (networkInfo.isConnected()) {
|
||||
String typeName = networkInfo.getTypeName();
|
||||
if ("WIFI".equalsIgnoreCase(typeName)) {
|
||||
type = NETWORK_TYPE_WIFI;
|
||||
} else if ("MOBILE".equalsIgnoreCase(typeName)) {
|
||||
//String proxyHost = android.net.Proxy.getDefaultHost();//deprecated
|
||||
String proxyHost = System.getProperty("http.proxyHost");
|
||||
type = TextUtils.isEmpty(proxyHost) ? (isFastMobileNetwork(context) ? NETWORK_TYPE_3G : NETWORK_TYPE_2G) : NETWORK_TYPE_WAP;
|
||||
} else {
|
||||
type = NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean isConnected(Context context) {
|
||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo info = cm.getActiveNetworkInfo();
|
||||
if (info != null && info.isConnected()) {
|
||||
if (info.getState() == NetworkInfo.State.CONNECTED) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isNetworkAvailable(Context context) {
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
if (connectivity != null) {
|
||||
NetworkInfo info = connectivity.getActiveNetworkInfo();
|
||||
return info.isAvailable();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isWiFi(Context cxt) {
|
||||
ConnectivityManager cm = (ConnectivityManager) cxt.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
// wifi的状态:ConnectivityManager.TYPE_WIFI
|
||||
// 3G的状态:ConnectivityManager.TYPE_MOBILE
|
||||
return cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
|
||||
}
|
||||
|
||||
//unchecked
|
||||
public static void openNetSetting(Activity act) {
|
||||
Intent intent = new Intent();
|
||||
ComponentName cm = new ComponentName("com.android.settings", "com.android.settings.WirelessSettings");
|
||||
intent.setComponent(cm);
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
act.startActivityForResult(intent, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether is fast mobile network
|
||||
*/
|
||||
|
||||
private static boolean isFastMobileNetwork(Context context) {
|
||||
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (telephonyManager == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (telephonyManager.getNetworkType()) {
|
||||
case TelephonyManager.NETWORK_TYPE_1xRTT:
|
||||
return false;
|
||||
case TelephonyManager.NETWORK_TYPE_CDMA:
|
||||
return false;
|
||||
case TelephonyManager.NETWORK_TYPE_EDGE:
|
||||
return false;
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_0:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_A:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_GPRS:
|
||||
return false;
|
||||
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_HSPA:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_UMTS:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_EHRPD:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_B:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_HSPAP:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_IDEN:
|
||||
return false;
|
||||
case TelephonyManager.NETWORK_TYPE_LTE:
|
||||
return true;
|
||||
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setWifiEnabled(Context context, boolean enabled) {
|
||||
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
wifiManager.setWifiEnabled(enabled);
|
||||
}
|
||||
|
||||
public static void setDataEnabled(Context context, boolean enabled) {
|
||||
ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
Class<?> conMgrClass = null;
|
||||
Field iConMgrField = null;
|
||||
Object iConMgr = null;
|
||||
Class<?> iConMgrClass = null;
|
||||
Method setMobileDataEnabledMethod = null;
|
||||
try {
|
||||
conMgrClass = Class.forName(conMgr.getClass().getName());
|
||||
iConMgrField = conMgrClass.getDeclaredField("mService");
|
||||
iConMgrField.setAccessible(true);
|
||||
iConMgr = iConMgrField.get(conMgr);
|
||||
iConMgrClass = Class.forName(iConMgr.getClass().getName());
|
||||
setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
|
||||
setMobileDataEnabledMethod.setAccessible(true);
|
||||
setMobileDataEnabledMethod.invoke(iConMgr, enabled);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ScanResult> getWifiScanResults(Context context) {
|
||||
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
return wifiManager.startScan() ? wifiManager.getScanResults() : null;
|
||||
}
|
||||
|
||||
public static ScanResult getScanResultsByBSSID(Context context, String bssid) {
|
||||
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
ScanResult scanResult = null;
|
||||
boolean f = wifiManager.startScan();
|
||||
if (!f) {
|
||||
getScanResultsByBSSID(context, bssid);
|
||||
}
|
||||
List<ScanResult> list = wifiManager.getScanResults();
|
||||
if (list != null) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
scanResult = list.get(i);
|
||||
if (scanResult.BSSID.equals(bssid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return scanResult;
|
||||
}
|
||||
|
||||
public static WifiInfo getWifiConnectionInfo(Context context) {
|
||||
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
return wifiManager.getConnectionInfo();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package com.ruilaizi.example.utils;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.readystatesoftware.systembartint.SystemBarTintManager;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Created by XiaoQiang on 2017/6/21.
|
||||
*/
|
||||
public class StatusBarUtil {
|
||||
|
||||
/**
|
||||
* 修改状态栏为全透明
|
||||
* @param activity
|
||||
*/
|
||||
@TargetApi(19)
|
||||
public static void transparencyBar(Activity activity){
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = activity.getWindow();
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.setStatusBarColor(Color.WHITE);
|
||||
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
Window window =activity.getWindow();
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
|
||||
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改状态栏颜色,支持4.4以上版本
|
||||
* @param activity
|
||||
* @param colorId
|
||||
*/
|
||||
public static void setStatusBarColor(Activity activity,int colorId) {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = activity.getWindow();
|
||||
// window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.setStatusBarColor(activity.getResources().getColor(colorId));
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
//使用SystemBarTint库使4.4版本状态栏变色,需要先将状态栏设置为透明
|
||||
transparencyBar(activity);
|
||||
SystemBarTintManager tintManager = new SystemBarTintManager(activity);
|
||||
tintManager.setStatusBarTintEnabled(true);
|
||||
tintManager.setStatusBarTintResource(colorId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*状态栏亮色模式,设置状态栏黑色文字、图标,
|
||||
* 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android
|
||||
* @param activity
|
||||
* @return 1:MIUUI 2:Flyme 3:android6.0
|
||||
*/
|
||||
public static int StatusBarLightMode(Activity activity){
|
||||
int result=0;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if(MIUISetStatusBarLightMode(activity, true)){
|
||||
result=1;
|
||||
}else if(FlymeSetStatusBarLightMode(activity.getWindow(), true)){
|
||||
result=2;
|
||||
}else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
result=3;
|
||||
}else{
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = activity.getWindow();
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.setStatusBarColor(Color.BLACK);
|
||||
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
Window window =activity.getWindow();
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
|
||||
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 已知系统类型时,设置状态栏黑色文字、图标。
|
||||
* 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android
|
||||
* @param activity
|
||||
* @param type 1:MIUUI 2:Flyme 3:android6.0
|
||||
*/
|
||||
public static void StatusBarLightMode(Activity activity,int type){
|
||||
if(type==1){
|
||||
MIUISetStatusBarLightMode(activity, true);
|
||||
}else if(type==2){
|
||||
FlymeSetStatusBarLightMode(activity.getWindow(), true);
|
||||
}else if(type==3){
|
||||
activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态栏暗色模式,清除MIUI、flyme或6.0以上版本状态栏黑色文字、图标
|
||||
*/
|
||||
public static void StatusBarDarkMode(Activity activity,int type){
|
||||
if(type==1){
|
||||
MIUISetStatusBarLightMode(activity, false);
|
||||
}else if(type==2){
|
||||
FlymeSetStatusBarLightMode(activity.getWindow(), false);
|
||||
}else if(type==3){
|
||||
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置状态栏图标为深色和魅族特定的文字风格
|
||||
* 可以用来判断是否为Flyme用户
|
||||
* @param window 需要设置的窗口
|
||||
* @param dark 是否把状态栏文字及图标颜色设置为深色
|
||||
* @return boolean 成功执行返回true
|
||||
*
|
||||
*/
|
||||
public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
|
||||
boolean result = false;
|
||||
if (window != null) {
|
||||
try {
|
||||
WindowManager.LayoutParams lp = window.getAttributes();
|
||||
Field darkFlag = WindowManager.LayoutParams.class
|
||||
.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
|
||||
Field meizuFlags = WindowManager.LayoutParams.class
|
||||
.getDeclaredField("meizuFlags");
|
||||
darkFlag.setAccessible(true);
|
||||
meizuFlags.setAccessible(true);
|
||||
int bit = darkFlag.getInt(null);
|
||||
int value = meizuFlags.getInt(lp);
|
||||
if (dark) {
|
||||
value |= bit;
|
||||
} else {
|
||||
value &= ~bit;
|
||||
}
|
||||
meizuFlags.setInt(lp, value);
|
||||
window.setAttributes(lp);
|
||||
result = true;
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要MIUIV6以上
|
||||
* @param activity
|
||||
* @param dark 是否把状态栏文字及图标颜色设置为深色
|
||||
* @return boolean 成功执行返回true
|
||||
*
|
||||
*/
|
||||
public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
|
||||
boolean result = false;
|
||||
Window window=activity.getWindow();
|
||||
if (window != null) {
|
||||
Class clazz = window.getClass();
|
||||
try {
|
||||
int darkModeFlag = 0;
|
||||
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
if(dark){
|
||||
extraFlagField.invoke(window,darkModeFlag,darkModeFlag);//状态栏透明且黑色字体
|
||||
}else{
|
||||
extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
|
||||
}
|
||||
result=true;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
//开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
|
||||
if(dark){
|
||||
activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
}else {
|
||||
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
}
|
||||
}
|
||||
}catch (Exception e){
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ruilaizi.example.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* 模板项目 Toast 工具类。
|
||||
*/
|
||||
public class ToastUtils {
|
||||
|
||||
public static void showToast(Context context, String message) {
|
||||
Toast.makeText(context.getApplicationContext(), message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public static void showToast(Context context, int stringResId) {
|
||||
Toast.makeText(context.getApplicationContext(), stringResId, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
6
example/app/src/main/res/anim/dialog_dismiss.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:toYDelta="100%p"
|
||||
android:duration="500" />
|
||||
</set>
|
||||
18
example/app/src/main/res/anim/dialog_in_anim.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!--
|
||||
有四种动画:alpha (透明变化) translate(位置移动) scale(缩放) rotate(旋转),
|
||||
android:duration: 动画运行时间,定义在多次时间(ms)内完成动画
|
||||
android:startOffset: 延迟一定时间后运行动画
|
||||
fromXDelta: X轴方向开始位置,可以是%,也可以是具体的像素 具体见图
|
||||
toXDelta: X轴方向结束位置,可以是%,也可以是具体的像素
|
||||
fromYDelta: Y轴方向开始位置,可以是%,也可以是具体的像素
|
||||
toYDelta: Y轴方向结束位置,可以是%,也可以是具体的像素
|
||||
-->
|
||||
<translate
|
||||
android:duration="500"
|
||||
android:fromXDelta="0"
|
||||
android:fromYDelta="100%p"
|
||||
android:toXDelta="0"
|
||||
android:toYDelta="0%p" />
|
||||
</set>
|
||||
9
example/app/src/main/res/anim/dialog_out_anim.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="500"
|
||||
android:fromXDelta="0"
|
||||
android:fromYDelta="0%p"
|
||||
android:toXDelta="0"
|
||||
android:toYDelta="100%p" />
|
||||
</set>
|
||||
6
example/app/src/main/res/anim/dialog_show.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:fromYDelta="100%p"
|
||||
android:duration="500" />
|
||||
</set>
|
||||
8
example/app/src/main/res/anim/push_bottom_in2.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- 上下滑入式 -->
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromYDelta="100%p"
|
||||
android:toYDelta="0%p" />
|
||||
</set>
|
||||
11
example/app/src/main/res/anim/push_bottom_out2.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- 上下滑入式 -->
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromYDelta="0"
|
||||
android:toYDelta="100%p" />
|
||||
|
||||
|
||||
</set>
|
||||
6
example/app/src/main/res/anim/scale_in.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="300"
|
||||
android:fromAlpha="0.0"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:toAlpha="1.0" />
|
||||
6
example/app/src/main/res/anim/scale_out.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="300"
|
||||
android:fromAlpha="1.0"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:toAlpha="0.0" />
|
||||
16
example/app/src/main/res/anim/slide_in_bottom.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
>
|
||||
|
||||
<translate
|
||||
android:duration="@android:integer/config_mediumAnimTime"
|
||||
android:fromYDelta="100%p"
|
||||
android:toYDelta="0" />
|
||||
|
||||
<alpha
|
||||
android:duration="@android:integer/config_mediumAnimTime"
|
||||
android:fromAlpha="0.95"
|
||||
android:toAlpha="1" />
|
||||
|
||||
</set>
|
||||
14
example/app/src/main/res/anim/slide_out_bottom.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<translate
|
||||
android:duration="@android:integer/config_mediumAnimTime"
|
||||
android:fromYDelta="0"
|
||||
android:toYDelta="100%p" />
|
||||
|
||||
<alpha
|
||||
android:duration="@android:integer/config_mediumAnimTime"
|
||||
android:fromAlpha="1"
|
||||
android:toAlpha="0.95" />
|
||||
|
||||
</set>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/colorAccent" android:state_selected="true"/>
|
||||
<item android:color="@color/colorTextDark" android:state_selected="false"/>
|
||||
</selector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/colorAccent" android:state_enabled="true"/>
|
||||
<item android:color="@color/colorText" android:state_enabled="false"/>
|
||||
</selector>
|
||||
5
example/app/src/main/res/color/selector_tag_text.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/colorPrimary" android:state_checked="true" />
|
||||
<item android:color="@color/colorAccent" />
|
||||
</selector><!-- From: file:/D:/Android/work/MerchantEdition/app/src/main/res/drawable/main_menu_selector.xml -->
|
||||
BIN
example/app/src/main/res/drawable-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
example/app/src/main/res/drawable-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
@@ -0,0 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
BIN
example/app/src/main/res/drawable-xhdpi/buybuybuy.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
example/app/src/main/res/drawable-xhdpi/chat_left_bg.9.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
example/app/src/main/res/drawable-xhdpi/chat_left_qp.9.png
Normal file
|
After Width: | Height: | Size: 488 B |
BIN
example/app/src/main/res/drawable-xhdpi/chat_right_bg.9.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
example/app/src/main/res/drawable-xhdpi/chat_right_qp.9.png
Normal file
|
After Width: | Height: | Size: 567 B |
BIN
example/app/src/main/res/drawable-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
example/app/src/main/res/drawable-xhdpi/to_down.png
Normal file
|
After Width: | Height: | Size: 549 B |
BIN
example/app/src/main/res/drawable-xhdpi/video_icon.png
Normal file
|
After Width: | Height: | Size: 469 B |
BIN
example/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
170
example/app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
||||
6
example/app/src/main/res/drawable/shape_dialog.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape android:shape="rectangle"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#ff848484" />
|
||||
<corners android:topLeftRadius="13dp" android:topRightRadius="13dp" android:bottomLeftRadius="13dp" android:bottomRightRadius="13dp" />
|
||||
</shape>
|
||||
288
example/app/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,288 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorSurface"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 标题栏:应用名 + 设置 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/colorPrimary"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold" />
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_settings"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="设置" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 预设提示区 -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="常用提示"
|
||||
android:textColor="@color/colorTextSecondary"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/preset_chip_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleSelection="false"
|
||||
app:selectionRequired="false"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/preset_email"
|
||||
style="@style/Widget.MaterialComponents.Chip.Choice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/preset_email" />
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/preset_product"
|
||||
style="@style/Widget.MaterialComponents.Chip.Choice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/preset_product" />
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/preset_story"
|
||||
style="@style/Widget.MaterialComponents.Chip.Choice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/preset_story" />
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/preset_summary"
|
||||
style="@style/Widget.MaterialComponents.Chip.Choice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/preset_summary" />
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/preset_poem"
|
||||
style="@style/Widget.MaterialComponents.Chip.Choice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/preset_poem" />
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
|
||||
<!-- 输入区 -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/prompt_hint"
|
||||
app:boxBackgroundColor="@color/colorCard"
|
||||
app:boxStrokeColor="@color/colorPrimary"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_prompt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minLines="4"
|
||||
android:gravity="top"
|
||||
android:inputType="textMultiLine|textCapSentences" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- 生成长度 -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="生成长度"
|
||||
android:textColor="@color/colorTextSecondary"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="4dp" />
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider_length"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="2"
|
||||
android:stepSize="1"
|
||||
android:value="1"
|
||||
app:labelBehavior="gone"
|
||||
android:layout_marginBottom="8dp" />
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="12dp">
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/length_short"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/colorTextSecondary" />
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/length_medium"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/colorTextSecondary" />
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/length_long"
|
||||
android:textSize="12sp"
|
||||
android:gravity="end"
|
||||
android:textColor="@color/colorTextSecondary" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 创意程度 -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="创意程度"
|
||||
android:textColor="@color/colorTextSecondary"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="4dp" />
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider_temperature"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="2"
|
||||
android:stepSize="1"
|
||||
android:value="1"
|
||||
app:labelBehavior="gone"
|
||||
android:layout_marginBottom="8dp" />
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="16dp">
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/temp_conservative"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/colorTextSecondary" />
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/temp_balanced"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/colorTextSecondary" />
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/temp_creative"
|
||||
android:textSize="12sp"
|
||||
android:gravity="end"
|
||||
android:textColor="@color/colorTextSecondary" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 生成按钮 -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_generate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:text="@string/btn_generate"
|
||||
app:backgroundTint="@color/colorPrimary"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:layout_marginBottom="20dp" />
|
||||
|
||||
<!-- 加载指示 -->
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- 结果展示区 -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="生成结果"
|
||||
android:textColor="@color/colorTextSecondary"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="@color/colorCard"
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
android:minHeight="120dp"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fillViewport="true"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/result_placeholder"
|
||||
android:textColor="@color/colorText"
|
||||
android:textSize="15sp"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
tools:text="这里是流式显示的结果文本…" />
|
||||
</ScrollView>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- 操作按钮栏 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="24dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_copy"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/btn_copy" />
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_regenerate"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/btn_regenerate" />
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_continue"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/btn_continue" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
30
example/app/src/main/res/layout/dialog_loading.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/shape_dialog"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:indeterminateTint="@color/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/loading"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
example/app/src/main/res/mipmap-hdpi/add_icon.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/address_icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/camera_icon.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/chakan_icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/daifukuan_icon.png
Normal file
|
After Width: | Height: | Size: 809 B |
BIN
example/app/src/main/res/mipmap-hdpi/feiyong_icon.jpg
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/fragment_my_bg.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/fuwubiaozun_icon.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/fuwuzhong_icon.png
Normal file
|
After Width: | Height: | Size: 857 B |
BIN
example/app/src/main/res/mipmap-hdpi/fw_icon.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/home_bj.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/icon_activity.png
Normal file
|
After Width: | Height: | Size: 869 B |
BIN
example/app/src/main/res/mipmap-hdpi/icon_add_des.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/icon_address_blue.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/icon_balance.png
Normal file
|
After Width: | Height: | Size: 953 B |
BIN
example/app/src/main/res/mipmap-hdpi/icon_cheched_false.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/icon_cheched_true.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/icon_clear.png
Normal file
|
After Width: | Height: | Size: 697 B |
BIN
example/app/src/main/res/mipmap-hdpi/icon_cus_new.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/icon_default_empty.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/icon_default_head.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
example/app/src/main/res/mipmap-hdpi/icon_delete.png
Normal file
|
After Width: | Height: | Size: 683 B |