init
85
.gitignore
vendored
普通文件
@ -0,0 +1,85 @@
|
|||||||
|
# Built application files
|
||||||
|
*.apk
|
||||||
|
*.aar
|
||||||
|
*.ap_
|
||||||
|
*.aab
|
||||||
|
|
||||||
|
# Files for the ART/Dalvik VM
|
||||||
|
*.dex
|
||||||
|
|
||||||
|
# Java class files
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
out/
|
||||||
|
# Uncomment the following line in case you need and you don't have the release build type files in your app
|
||||||
|
# release/
|
||||||
|
|
||||||
|
# Gradle files
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Proguard folder generated by Eclipse
|
||||||
|
proguard/
|
||||||
|
|
||||||
|
# Log Files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Android Studio Navigation editor temp files
|
||||||
|
.navigation/
|
||||||
|
|
||||||
|
# Android Studio captures folder
|
||||||
|
captures/
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
*.iml
|
||||||
|
.idea/
|
||||||
|
# Android Studio 3 in .gitignore file.
|
||||||
|
.idea/caches
|
||||||
|
.idea/modules.xml
|
||||||
|
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||||
|
.idea/navEditor.xml
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
|
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||||
|
#*.jks
|
||||||
|
#*.keystore
|
||||||
|
|
||||||
|
# External native build folder generated in Android Studio 2.2 and later
|
||||||
|
.externalNativeBuild
|
||||||
|
.cxx/
|
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase)
|
||||||
|
# google-services.json
|
||||||
|
|
||||||
|
# Freeline
|
||||||
|
freeline.py
|
||||||
|
freeline/
|
||||||
|
freeline_project_description.json
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots
|
||||||
|
fastlane/test_output
|
||||||
|
fastlane/readme.md
|
||||||
|
|
||||||
|
# Version control
|
||||||
|
vcs.xml
|
||||||
|
|
||||||
|
# lint
|
||||||
|
lint/intermediates/
|
||||||
|
lint/generated/
|
||||||
|
lint/outputs/
|
||||||
|
lint/tmp/
|
||||||
|
# lint/reports/
|
||||||
|
|
||||||
|
/app/key
|
||||||
|
output-metadata.json
|
||||||
|
# Android Profiling
|
||||||
|
*.hprof
|
||||||
1
app/.gitignore
vendored
普通文件
@ -0,0 +1 @@
|
|||||||
|
/build
|
||||||
85
app/build.gradle
普通文件
@ -0,0 +1,85 @@
|
|||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
apply plugin: 'kotlin-kapt'
|
||||||
|
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion versions.compileSdk
|
||||||
|
buildToolsVersion versions.buildTools
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId apps.applicationId
|
||||||
|
minSdkVersion versions.minSdk
|
||||||
|
targetSdkVersion versions.targetSdk
|
||||||
|
versionCode versions.versionCode
|
||||||
|
versionName versions.versionName
|
||||||
|
|
||||||
|
manifestPlaceholders = [
|
||||||
|
APP_NAME: apps.applicationName,
|
||||||
|
APP_ID : apps.applicationId,
|
||||||
|
]
|
||||||
|
buildConfigField("String", "APP_Name", "\"" + apps.applicationName + "\"")
|
||||||
|
|
||||||
|
flavorDimensions "versioncode"
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
debug {
|
||||||
|
minifyEnabled false
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationVariants.all { variant ->
|
||||||
|
variant.outputs.all { output ->
|
||||||
|
if ("debug" != variant.buildType.name) {
|
||||||
|
def now = new Date()
|
||||||
|
def path = "../../../../../apks/${variant.buildType.name}/v${defaultConfig.versionName}_" + now.format("yyyy.MM.dd_HH")
|
||||||
|
outputFileName = path + "/${applicationId}.apk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
signingConfigs {
|
||||||
|
debug {
|
||||||
|
keyAlias 'xuqm'
|
||||||
|
keyPassword 'xuqinmin1022'
|
||||||
|
storeFile file('key')
|
||||||
|
storePassword 'xuqinmin1022'
|
||||||
|
}
|
||||||
|
releaseConfig {}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
jniLibs.srcDirs = ['libs']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
androidExtensions {
|
||||||
|
experimental = true
|
||||||
|
}
|
||||||
|
namespace 'com.bjca.hp.acupuncture'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: "libs", include: ["*.jar","*.aar"])
|
||||||
|
implementation project(path: ':core')
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
|
|
||||||
|
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||||
|
implementation 'com.google.android.material:material:1.3.0'
|
||||||
|
|
||||||
|
implementation 'tp.xmaihh:serialport:2.1'
|
||||||
|
|
||||||
|
implementation 'com.rabbitmq:amqp-client:5.15.0'
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
21
app/proguard-rules.pro
vendored
普通文件
@ -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
|
||||||
76
app/src/main/AndroidManifest.xml
普通文件
@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- 网络权限 -->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- <uses-permission android:name="android.permission.READ_LOGS" /> -->
|
||||||
|
<uses-feature android:name="android.hardware.camera" />
|
||||||
|
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name=".MyApplication"
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="${APP_NAME}"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/AppTheme"
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
|
tools:replace="android:label">
|
||||||
|
<activity
|
||||||
|
android:name=".ui.TestActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".ui.SettingActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name=".receiver.BootCompleteReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true">
|
||||||
|
|
||||||
|
<!-- 接收启动完成的广播 -->
|
||||||
|
<intent-filter android:priority="1000">
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".ui.MainActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".ui.WelcomeActivity"
|
||||||
|
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="${APP_ID}.fileprovider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/filepaths" />
|
||||||
|
</provider>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="design_width_in_dp"
|
||||||
|
android:value="540" />
|
||||||
|
<meta-data
|
||||||
|
android:name="design_height_in_dp"
|
||||||
|
android:value="960" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.bjca.hp.acupuncture;
|
||||||
|
|
||||||
|
import com.xuqm.base.App;
|
||||||
|
import com.xuqm.base.di.component.AppComponent;
|
||||||
|
import com.xuqm.base.di.manager.HttpManager;
|
||||||
|
import com.bjca.hp.acupuncture.common.CrashHandler;
|
||||||
|
import com.bjca.hp.acupuncture.repository.HeaderInterceptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuqm
|
||||||
|
*/
|
||||||
|
public class MyApplication extends App {
|
||||||
|
|
||||||
|
public static String baseUrl = "http://10.10.203.120:31734";
|
||||||
|
public static AppComponent appComponent1;
|
||||||
|
public static AppComponent appComponent2;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
appComponent = HttpManager.getAppComponent(baseUrl, new HeaderInterceptor(getApplicationContext()));
|
||||||
|
appComponent1 = HttpManager.getAppComponent("http://10.10.203.120:35662", new HeaderInterceptor(getApplicationContext()));
|
||||||
|
appComponent2 = HttpManager.getAppComponent("http://10.10.203.120:31669", new HeaderInterceptor(getApplicationContext()));
|
||||||
|
|
||||||
|
CrashHandler.getInstance().init(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean showLog() {
|
||||||
|
return super.showLog();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,166 @@
|
|||||||
|
package com.bjca.hp.acupuncture.common;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/*************************************************************************************************
|
||||||
|
* <pre>
|
||||||
|
* @包路径: cn.org.bjca.wcert.ywq.utils.crash
|
||||||
|
* @版权所有: 北京数字认证股份有限公司 (C) 2017
|
||||||
|
*
|
||||||
|
* @类描述:
|
||||||
|
* @版本: V1.5.1
|
||||||
|
* @作者 daizhenhong
|
||||||
|
* @创建时间 2017/12/13 下午4:22
|
||||||
|
*
|
||||||
|
* @修改记录:
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
----------- 时间 | 修改人 | 修改的方法 | 修改描述 ---------------
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
</pre>
|
||||||
|
************************************************************************************************/
|
||||||
|
public class CrashHandler implements Thread.UncaughtExceptionHandler {
|
||||||
|
|
||||||
|
|
||||||
|
private static String TAG = "CrashHandler";
|
||||||
|
// 系统默认的UncaughtException处理类
|
||||||
|
private Thread.UncaughtExceptionHandler mDefaultHandler;
|
||||||
|
// 用于格式化日期,作为日志文件名的一部分
|
||||||
|
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
private static CrashHandler mCrashHandler;
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
|
||||||
|
private CrashHandler() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CrashHandler getInstance() {
|
||||||
|
if (mCrashHandler == null) {
|
||||||
|
synchronized (CrashHandler.class) {
|
||||||
|
mCrashHandler = new CrashHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mCrashHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(Thread thread, Throwable throwable) {
|
||||||
|
if (!handleException(throwable) && mDefaultHandler != null) {
|
||||||
|
// 如果用户没有处理则让系统默认的异常处理器来处理
|
||||||
|
mDefaultHandler.uncaughtException(thread, throwable);
|
||||||
|
} else {
|
||||||
|
SystemClock.sleep(2000);
|
||||||
|
// 退出程序
|
||||||
|
android.os.Process.killProcess(android.os.Process.myPid());
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean handleException(Throwable ex) {
|
||||||
|
if (ex == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
saveCrashInfoFile(ex);
|
||||||
|
SystemClock.sleep(2000);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String saveCrashInfoFile(Throwable ex) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
|
if (hasSdcard())
|
||||||
|
try {
|
||||||
|
SimpleDateFormat sDateFormat = new SimpleDateFormat(
|
||||||
|
"yyyy-MM-dd HH:mm:ss", Locale.CHINA);
|
||||||
|
String date = sDateFormat.format(new Date());
|
||||||
|
sb.append("\r\n" + date + "\n");
|
||||||
|
|
||||||
|
Writer writer = new StringWriter();
|
||||||
|
PrintWriter printWriter = new PrintWriter(writer);
|
||||||
|
ex.printStackTrace(printWriter);
|
||||||
|
Throwable cause = ex.getCause();
|
||||||
|
while (cause != null) {
|
||||||
|
cause.printStackTrace(printWriter);
|
||||||
|
cause = cause.getCause();
|
||||||
|
}
|
||||||
|
printWriter.flush();
|
||||||
|
printWriter.close();
|
||||||
|
String result = writer.toString();
|
||||||
|
sb.append(result);
|
||||||
|
|
||||||
|
String fileName = writeFile(sb.toString());
|
||||||
|
return fileName;
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "an error occured while writing file...", e);
|
||||||
|
sb.append("an error occured while writing file...\r\n");
|
||||||
|
writeFile(sb.toString());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String writeFile(String text) {
|
||||||
|
Log.e("writeFile", text);
|
||||||
|
String time = formatter.format(new Date());
|
||||||
|
String fileName = "crash-demo-" + time + ".log";
|
||||||
|
|
||||||
|
String path = getGlobalpath();
|
||||||
|
|
||||||
|
File dir = new File(path);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
dir.mkdir();
|
||||||
|
}
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
try {
|
||||||
|
fos = new FileOutputStream(path + fileName, true);
|
||||||
|
fos.write(text.getBytes());
|
||||||
|
fos.flush();
|
||||||
|
fos.close();
|
||||||
|
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getGlobalpath() {
|
||||||
|
return Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||||
|
+ File.separator + "crash" + File.separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean hasSdcard(){
|
||||||
|
return Environment.getExternalStorageState()
|
||||||
|
.equals(Environment.MEDIA_MOUNTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,248 @@
|
|||||||
|
package com.bjca.hp.acupuncture.common;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.rabbitmq.client.AMQP;
|
||||||
|
import com.rabbitmq.client.AlreadyClosedException;
|
||||||
|
import com.rabbitmq.client.Channel;
|
||||||
|
import com.rabbitmq.client.Connection;
|
||||||
|
import com.rabbitmq.client.ConnectionFactory;
|
||||||
|
import com.rabbitmq.client.DefaultConsumer;
|
||||||
|
import com.rabbitmq.client.Envelope;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* <pre></pre>
|
||||||
|
* @文件名称: RabbitMQClient
|
||||||
|
* @包 路 径: com.bjca.hp.acupuncture.common
|
||||||
|
* @版权所有:北京数字医信责任有限公司 (C) 2022
|
||||||
|
*
|
||||||
|
* @类描述:
|
||||||
|
* @版本: V1.0
|
||||||
|
* @创建人: xuqm
|
||||||
|
* @创建时间:2022/6/15 下午 02:19
|
||||||
|
* @修改记录:
|
||||||
|
*/
|
||||||
|
public class RabbitMQClient {
|
||||||
|
private final String TAG = "RabbitMQ";
|
||||||
|
private final String FLAG_SEND = "send";
|
||||||
|
private final String FLAG_RECEIVE = "receive";
|
||||||
|
|
||||||
|
private final ConnectionFactory factory;
|
||||||
|
private Connection connection;
|
||||||
|
private Map<String, Channel> channelMap = new HashMap<>();
|
||||||
|
|
||||||
|
public static final String EXCHANGETYPE_FANOUT = "fanout"; //不用匹配路由,发送给所有绑定转换器的队列
|
||||||
|
public static final String EXCHANGETYPE_DIRECT = "direct"; //匹配路由一致,才发送给绑定转换器队列
|
||||||
|
public static final String EXCHANGETYPE_TOPIC = "topic"; // 通配符* 和 # 匹配路由一致,才发送给绑定转换器队列
|
||||||
|
|
||||||
|
|
||||||
|
public RabbitMQClient(String hostIp, int port, String username, String password) {
|
||||||
|
factory = new ConnectionFactory();
|
||||||
|
factory.setUsername(username);
|
||||||
|
factory.setPassword(password);
|
||||||
|
factory.setHost(hostIp);
|
||||||
|
factory.setPort(port);
|
||||||
|
factory.setVirtualHost("/");//类似数据库的意思
|
||||||
|
factory.setConnectionTimeout(15 * 1000); //连接时间设置为10秒
|
||||||
|
factory.setAutomaticRecoveryEnabled(true); //恢复连接,通道
|
||||||
|
factory.setTopologyRecoveryEnabled(true); //恢复通道中 转换器,队列,绑定关系等
|
||||||
|
factory.setNetworkRecoveryInterval(5 * 1000); //恢复连接间隔,默认5秒
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message 需要发送的消息
|
||||||
|
* @param queueName 管道名称
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion
|
||||||
|
**/
|
||||||
|
public void sendQueueMessage(String message, String queueName) throws IOException, TimeoutException, AlreadyClosedException {
|
||||||
|
if (connection == null || !connection.isOpen()) {
|
||||||
|
connection = factory.newConnection();
|
||||||
|
}
|
||||||
|
if (!channelMap.containsKey(FLAG_SEND + queueName)) {
|
||||||
|
Channel channel = connection.createChannel();
|
||||||
|
channel.queueDeclare(queueName, false, false, false, null);
|
||||||
|
channelMap.put(FLAG_SEND + queueName, channel);
|
||||||
|
}
|
||||||
|
//空名字的交换机,需要设置routingKey,此时会将routingKey 作为 队列名使用
|
||||||
|
channelMap.get(FLAG_SEND + queueName).basicPublish("", queueName, null, message.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param exchangeName 交换机名称
|
||||||
|
* @param message 需要发送的消息
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @param routingKey 路由规则
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion 发送 exchangeType direct 类型的信息
|
||||||
|
**/
|
||||||
|
public void sendDirectTypeMessage(String exchangeName, String message, String queueName, String routingKey) throws IOException, TimeoutException, AlreadyClosedException {
|
||||||
|
if (connection == null || !connection.isOpen()) {
|
||||||
|
connection = factory.newConnection();
|
||||||
|
}
|
||||||
|
if (!channelMap.containsKey(FLAG_SEND + exchangeName + EXCHANGETYPE_DIRECT + queueName)) {
|
||||||
|
Channel channel = connection.createChannel();
|
||||||
|
channel.queueDeclare(queueName, false, false, false, null);
|
||||||
|
channel.exchangeDeclare(exchangeName, EXCHANGETYPE_DIRECT);
|
||||||
|
channelMap.put(FLAG_SEND + exchangeName + EXCHANGETYPE_DIRECT + queueName, channel);
|
||||||
|
}
|
||||||
|
channelMap.get(FLAG_SEND + exchangeName + EXCHANGETYPE_DIRECT + queueName).basicPublish(exchangeName, routingKey, null, message.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param exchangeName 交换机名称
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @param message 发送的消息
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion 发送 exchangeType fanout 类型的信息
|
||||||
|
**/
|
||||||
|
public void sendFanoutTypeMessage(String exchangeName, String queueName, String message) throws IOException, TimeoutException, AlreadyClosedException {
|
||||||
|
if (connection == null || !connection.isOpen()) {
|
||||||
|
connection = factory.newConnection();
|
||||||
|
}
|
||||||
|
if (!channelMap.containsKey(FLAG_SEND + exchangeName + EXCHANGETYPE_FANOUT + queueName)) {
|
||||||
|
Channel channel = connection.createChannel();
|
||||||
|
channel.queueDeclare(queueName, false, false, false, null);
|
||||||
|
channel.exchangeDeclare(exchangeName, EXCHANGETYPE_FANOUT);
|
||||||
|
channelMap.put(FLAG_SEND + exchangeName + EXCHANGETYPE_FANOUT + queueName, channel);
|
||||||
|
}
|
||||||
|
channelMap.get(FLAG_SEND + exchangeName + EXCHANGETYPE_FANOUT + queueName).basicPublish(exchangeName, "", null, message.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param exchangeName 交换机名称
|
||||||
|
* @param exchangeType 模式
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @param message 需要发送的消息
|
||||||
|
* @param routingKey 路由规则
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion
|
||||||
|
**/
|
||||||
|
public void sendExchangeNameQueueMessage(String exchangeName, String exchangeType, String message, String queueName, String routingKey) throws IOException, TimeoutException, AlreadyClosedException {
|
||||||
|
if (connection == null || !connection.isOpen()) {
|
||||||
|
connection = factory.newConnection();
|
||||||
|
}
|
||||||
|
if (!channelMap.containsKey(FLAG_SEND + exchangeName + exchangeType + queueName)) {
|
||||||
|
Channel channel = connection.createChannel();
|
||||||
|
channel.queueDeclare(queueName, false, false, false, null);
|
||||||
|
channel.exchangeDeclare(exchangeName, exchangeType);
|
||||||
|
channelMap.put(FLAG_SEND + exchangeName + exchangeType + queueName, channel);
|
||||||
|
}
|
||||||
|
if (exchangeType.equals(EXCHANGETYPE_FANOUT)) {
|
||||||
|
channelMap.get(FLAG_SEND + exchangeName + exchangeType + queueName).basicPublish(exchangeName, "", null, message.getBytes());
|
||||||
|
} else if (exchangeType.equals(EXCHANGETYPE_DIRECT)) {
|
||||||
|
channelMap.get(FLAG_SEND + exchangeName + exchangeType + queueName).basicPublish(exchangeName, routingKey, null, message.getBytes());
|
||||||
|
} else if (exchangeType.equals(EXCHANGETYPE_TOPIC)) {
|
||||||
|
channelMap.get(FLAG_SEND + exchangeName + exchangeType + queueName).basicPublish(exchangeName, routingKey, null, message.getBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion
|
||||||
|
**/
|
||||||
|
public void receiveQueueMessage(final String queueName, final ResponseListener listener)
|
||||||
|
throws IOException, TimeoutException, AlreadyClosedException {
|
||||||
|
receiveQueueRoutingKeyMessage(queueName, "", "", "", listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @param routingKey 路由规则
|
||||||
|
* @param exchangeName 交换机名称
|
||||||
|
* @param exchangeType 交换机类型
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion
|
||||||
|
**/
|
||||||
|
public void receiveQueueRoutingKeyMessage(String queueName, final String routingKey, String exchangeName, String exchangeType, final ResponseListener listener)
|
||||||
|
throws IOException, TimeoutException, AlreadyClosedException {
|
||||||
|
|
||||||
|
if (exchangeType.equals(EXCHANGETYPE_DIRECT) || exchangeType.equals(EXCHANGETYPE_TOPIC)) {
|
||||||
|
if (TextUtils.isEmpty(routingKey)) {
|
||||||
|
throw new NullPointerException("路由规则不能为空");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(routingKey)) {
|
||||||
|
if (TextUtils.isEmpty(exchangeName)) {
|
||||||
|
throw new NullPointerException("交换机名称不能为空");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!channelMap.containsKey(FLAG_RECEIVE + routingKey + queueName)) {
|
||||||
|
if (connection == null || !connection.isOpen()) {
|
||||||
|
connection = factory.newConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Channel channel = connection.createChannel();
|
||||||
|
channel.queueDeclare(queueName, true, false, false, null);
|
||||||
|
//绑定转换器,使用路由筛选消息
|
||||||
|
if (!TextUtils.isEmpty(routingKey)) {
|
||||||
|
channel.exchangeDeclare(exchangeName, exchangeType);
|
||||||
|
channel.queueBind(queueName, exchangeName, routingKey); //设置绑定
|
||||||
|
}
|
||||||
|
//监听队列
|
||||||
|
channel.basicConsume(queueName, false, new DefaultConsumer(channel) {
|
||||||
|
@Override
|
||||||
|
public void handleDelivery(String consumerTag, Envelope envelope,
|
||||||
|
AMQP.BasicProperties properties, byte[] body)
|
||||||
|
throws IOException {
|
||||||
|
String message = new String(body, "UTF-8");
|
||||||
|
if (listener != null) {
|
||||||
|
listener.receive(message);
|
||||||
|
}
|
||||||
|
channel.basicAck(envelope.getDeliveryTag(), false); //消息应答
|
||||||
|
}
|
||||||
|
});
|
||||||
|
channelMap.put(FLAG_RECEIVE + routingKey + queueName, channel);
|
||||||
|
Log.e(TAG,"已经连接上了,队列名称:" + queueName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭所有资源
|
||||||
|
*/
|
||||||
|
public void close() {
|
||||||
|
for (Channel next : channelMap.values()) {
|
||||||
|
if (next != null && next.isOpen()) {
|
||||||
|
try {
|
||||||
|
next.close();
|
||||||
|
} catch (IOException | TimeoutException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
channelMap.clear();
|
||||||
|
if (connection != null && connection.isOpen()) {
|
||||||
|
try {
|
||||||
|
connection.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface ResponseListener {
|
||||||
|
void receive(String message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,239 @@
|
|||||||
|
package com.bjca.hp.acupuncture.common;
|
||||||
|
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.rabbitmq.client.AlreadyClosedException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* <pre></pre>
|
||||||
|
* @文件名称: RabbitMQUtil
|
||||||
|
* @包 路 径: com.bjca.hp.acupuncture.common
|
||||||
|
* @版权所有:北京数字医信责任有限公司 (C) 2022
|
||||||
|
*
|
||||||
|
* @类描述:
|
||||||
|
* @版本: V1.0
|
||||||
|
* @创建人: xuqm
|
||||||
|
* @创建时间:2022/6/15 下午 02:22
|
||||||
|
* @修改记录:
|
||||||
|
*/
|
||||||
|
public class RabbitMQUtil {
|
||||||
|
private boolean isRunning = true;
|
||||||
|
private RabbitMQClient rabbitMQ;
|
||||||
|
private ExecutorService executor;
|
||||||
|
|
||||||
|
|
||||||
|
public RabbitMQUtil(String hostIp, int port, String username, String password) {
|
||||||
|
rabbitMQ = new RabbitMQClient(hostIp, port, username, password);
|
||||||
|
executor = Executors.newSingleThreadExecutor(); //根据项目需要设置常用线程个数
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message 发送的消息
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion
|
||||||
|
**/
|
||||||
|
public void sendMessage(final String message, final String queueName, final SendMessageListener sendMessageListener,final ErrorMessageListener errorMessageListener) {
|
||||||
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
rabbitMQ.sendQueueMessage(message, queueName);
|
||||||
|
if (sendMessageListener != null) sendMessageListener.sendMessage(true);
|
||||||
|
} catch (IOException | TimeoutException | AlreadyClosedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
if (errorMessageListener!=null){
|
||||||
|
errorMessageListener.errorMessage(e);
|
||||||
|
}
|
||||||
|
if (sendMessageListener != null) sendMessageListener.sendMessage(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message 发送的消息
|
||||||
|
* @param exchangeName 交换机名称
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion
|
||||||
|
**/
|
||||||
|
public void sendMessage(final String message, final String exchangeName, final String exchangeType, final String queueName, final String routingKey, final SendMessageListener sendMessageListener,final ErrorMessageListener errorMessageListener) {
|
||||||
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
rabbitMQ.sendExchangeNameQueueMessage(exchangeName, exchangeType, message, queueName, routingKey);
|
||||||
|
if (sendMessageListener != null) sendMessageListener.sendMessage(true);
|
||||||
|
} catch (IOException | TimeoutException | AlreadyClosedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
if (errorMessageListener!=null){
|
||||||
|
errorMessageListener.errorMessage(e);
|
||||||
|
}
|
||||||
|
if (sendMessageListener != null) sendMessageListener.sendMessage(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param exchangeName 交换机名称
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @param message 需要发送的消息
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion
|
||||||
|
**/
|
||||||
|
public void sendFanoutTypeMessage(final String exchangeName, final String message, final String queueName, final SendMessageListener sendMessageListener,final ErrorMessageListener errorMessageListener) {
|
||||||
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
rabbitMQ.sendFanoutTypeMessage(exchangeName, queueName, message);
|
||||||
|
if (sendMessageListener != null) sendMessageListener.sendMessage(true);
|
||||||
|
} catch (IOException | TimeoutException | AlreadyClosedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
if (errorMessageListener!=null){
|
||||||
|
errorMessageListener.errorMessage(e);
|
||||||
|
}
|
||||||
|
if (sendMessageListener != null) sendMessageListener.sendMessage(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param exchangeName 交换机名称
|
||||||
|
* @param message 需要发送的消息
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @param routingKey 路由规则
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion 发送 exchangeType direct 类型的信息
|
||||||
|
**/
|
||||||
|
public void sendDirectTypeMessage(final String exchangeName, final String queueName, final String message, final String routingKey, final SendMessageListener sendMessageListener,final ErrorMessageListener errorMessageListener) {
|
||||||
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
rabbitMQ.sendDirectTypeMessage(exchangeName, queueName, message, routingKey);
|
||||||
|
if (sendMessageListener != null) sendMessageListener.sendMessage(true);
|
||||||
|
} catch (IOException | TimeoutException | AlreadyClosedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
if (errorMessageListener!=null){
|
||||||
|
errorMessageListener.errorMessage(e);
|
||||||
|
}
|
||||||
|
if (sendMessageListener != null) sendMessageListener.sendMessage(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param queueName 队列名称
|
||||||
|
* @date 创建时间:2020/9/8 0008
|
||||||
|
* @auther gaoxiaoxiong
|
||||||
|
* @Descriptiion
|
||||||
|
**/
|
||||||
|
public void receiveQueueMessage(String queueName, final ReceiveMessageListener listener,final ErrorMessageListener errorMessageListener) {
|
||||||
|
String newQueueName = null;
|
||||||
|
if (TextUtils.isEmpty(queueName)){
|
||||||
|
newQueueName = createDefaultQueueName(queueName);
|
||||||
|
}else {
|
||||||
|
newQueueName = queueName;
|
||||||
|
}
|
||||||
|
final String finalNewQueueName = newQueueName;
|
||||||
|
executor.execute(() -> {
|
||||||
|
while (isRunning) {
|
||||||
|
try {
|
||||||
|
rabbitMQ.receiveQueueMessage(finalNewQueueName, message -> {
|
||||||
|
if (listener != null) listener.receiveMessage(message);
|
||||||
|
});
|
||||||
|
} catch (IOException | TimeoutException | AlreadyClosedException e) {
|
||||||
|
if (errorMessageListener!=null){
|
||||||
|
errorMessageListener.errorMessage(e);
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
SystemClock.sleep(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void receiveQueueRoutingKeyMessage(String queueName, final String routingKey, final String exchangeName, final String exchangeType, final ReceiveMessageListener listener,final ErrorMessageListener errorMessageListener) {
|
||||||
|
String newQueueName = null;
|
||||||
|
if (TextUtils.isEmpty(queueName)){
|
||||||
|
newQueueName = createDefaultQueueName(queueName);
|
||||||
|
}else {
|
||||||
|
newQueueName = queueName;
|
||||||
|
}
|
||||||
|
final String finalNewQueueName = newQueueName;
|
||||||
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (isRunning) {
|
||||||
|
try {
|
||||||
|
rabbitMQ.receiveQueueRoutingKeyMessage(finalNewQueueName, routingKey, exchangeName, exchangeType, new RabbitMQClient.ResponseListener() {
|
||||||
|
@Override
|
||||||
|
public void receive(String message) {
|
||||||
|
if (listener != null) listener.receiveMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
} catch (IOException | TimeoutException | AlreadyClosedException e) {
|
||||||
|
if (errorMessageListener!=null){
|
||||||
|
errorMessageListener.errorMessage(e);
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
SystemClock.sleep(5000); //等待五秒
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public String createDefaultQueueName(String routingKey) {
|
||||||
|
if (TextUtils.isEmpty(routingKey)){
|
||||||
|
routingKey = "";
|
||||||
|
}
|
||||||
|
return routingKey + "@" + UUID.randomUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 建议:
|
||||||
|
* 在application中关闭或者在结束工作时关闭
|
||||||
|
*/
|
||||||
|
public void close() {
|
||||||
|
isRunning = false;
|
||||||
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
rabbitMQ.close();
|
||||||
|
executor.shutdownNow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface ReceiveMessageListener {
|
||||||
|
void receiveMessage(String message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface SendMessageListener {
|
||||||
|
void sendMessage(boolean isSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ErrorMessageListener{
|
||||||
|
void errorMessage(Exception e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
package com.bjca.hp.acupuncture.common
|
||||||
|
|
||||||
|
const val SHARE_RISK_LOCATION = "share_risk_location"
|
||||||
|
const val SHARE_RISK_PURE = "share_risk_pure"
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
package com.bjca.hp.acupuncture.model
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class DrugUsage(
|
||||||
|
|
||||||
|
@field:SerializedName("total")
|
||||||
|
val total: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("size")
|
||||||
|
val size: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("nulls")
|
||||||
|
val nulls: Any,
|
||||||
|
|
||||||
|
@field:SerializedName("index")
|
||||||
|
val index: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("items")
|
||||||
|
val items: List<ItemsItem5>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ItemsItem5(
|
||||||
|
|
||||||
|
@field:SerializedName("code")
|
||||||
|
val code: String,
|
||||||
|
|
||||||
|
@field:SerializedName("sysCodes")
|
||||||
|
val sysCodes: Any,
|
||||||
|
|
||||||
|
@field:SerializedName("seqNo")
|
||||||
|
val seqNo: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("memo")
|
||||||
|
val memo: Any,
|
||||||
|
|
||||||
|
@field:SerializedName("global")
|
||||||
|
val global: Boolean,
|
||||||
|
|
||||||
|
@field:SerializedName("type")
|
||||||
|
val type: String,
|
||||||
|
|
||||||
|
@field:SerializedName("parentType")
|
||||||
|
val parentType: Any,
|
||||||
|
|
||||||
|
@field:SerializedName("parentCode")
|
||||||
|
val parentCode: Any,
|
||||||
|
|
||||||
|
@field:SerializedName("codeChain")
|
||||||
|
val codeChain: String,
|
||||||
|
|
||||||
|
@field:SerializedName("ifMaster")
|
||||||
|
val ifMaster: Boolean,
|
||||||
|
|
||||||
|
@field:SerializedName("extra")
|
||||||
|
val extra: Any,
|
||||||
|
|
||||||
|
@field:SerializedName("disabled")
|
||||||
|
val disabled: Boolean,
|
||||||
|
|
||||||
|
@field:SerializedName("lockKey")
|
||||||
|
val lockKey: String,
|
||||||
|
|
||||||
|
@field:SerializedName("id")
|
||||||
|
val id: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("text")
|
||||||
|
val text: String,
|
||||||
|
|
||||||
|
@field:SerializedName("shortCode")
|
||||||
|
val shortCode: String
|
||||||
|
)
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
package com.bjca.hp.acupuncture.model
|
||||||
|
|
||||||
|
|
||||||
|
data class ItemsItems(
|
||||||
|
val assessorName: String,
|
||||||
|
val storehouseCode: String,
|
||||||
|
val sysCode: String,
|
||||||
|
val ifStateExpense: Boolean,
|
||||||
|
val patientId: Int,
|
||||||
|
val usage: String,
|
||||||
|
val medicalAdvice: String,
|
||||||
|
val dosagePerTime: String,
|
||||||
|
val frequency: String,
|
||||||
|
val approveUserId: Int,
|
||||||
|
val itemName: String,
|
||||||
|
val price: Double,
|
||||||
|
val paymentId: Int,
|
||||||
|
val patientAge: String,
|
||||||
|
val cashierId: String,
|
||||||
|
val lockKey: String,
|
||||||
|
val id: Int,
|
||||||
|
val ifInjury: Boolean,
|
||||||
|
val paymentState: String,
|
||||||
|
val invoiceNo: String,
|
||||||
|
val barcode: String,
|
||||||
|
val originalPaymentId: String,
|
||||||
|
val diagnosis: String,
|
||||||
|
val drugRpType: String,
|
||||||
|
val originalInvoiceNo: String,
|
||||||
|
val examineReason: String,
|
||||||
|
val opNo: String,
|
||||||
|
val name: String,
|
||||||
|
val executorDeptCode: String,
|
||||||
|
val assessorCode: String,
|
||||||
|
val refundDate: String,
|
||||||
|
val deptCode: String,
|
||||||
|
val makeMethod: String,
|
||||||
|
val distributeState: String,
|
||||||
|
val rpFeeType: String,
|
||||||
|
val no: String,
|
||||||
|
val settleId: String,
|
||||||
|
val approveDate: String,
|
||||||
|
val originalNo: String,
|
||||||
|
val patientGender: String,
|
||||||
|
val appNo: String,
|
||||||
|
val settleDate: String,
|
||||||
|
val adviceNo: String,
|
||||||
|
val doctorName: String,
|
||||||
|
val rpSettleType: String,
|
||||||
|
val doctorId: Int,
|
||||||
|
val offsetState: String,
|
||||||
|
val disabled: Boolean,
|
||||||
|
val drugRestrict: String,
|
||||||
|
val rpClass: String,
|
||||||
|
val groupNo: String,
|
||||||
|
val cashierName: String,
|
||||||
|
val ifInsurance: Boolean,
|
||||||
|
val examineResult: String,
|
||||||
|
val patientName: String,
|
||||||
|
val dosageUnit: String,
|
||||||
|
val cost: Int,
|
||||||
|
val quantity: String,
|
||||||
|
val ifDivide: String,
|
||||||
|
val excessDrugExplain: String,
|
||||||
|
val approveUserName: String,
|
||||||
|
val rpStatisticType: String,
|
||||||
|
val days: String,
|
||||||
|
val cashierCode: String,
|
||||||
|
val paymentDate: String,
|
||||||
|
val quantityPerDay: String
|
||||||
|
)
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package com.bjca.hp.acupuncture.model
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* <pre></pre>
|
||||||
|
* @文件名称: MqMessage
|
||||||
|
* @包 路 径: com.bjca.hp.acupuncture.model
|
||||||
|
* @版权所有:北京数字医信责任有限公司 (C) 2022
|
||||||
|
*
|
||||||
|
* @类描述:
|
||||||
|
* @版本: V1.0
|
||||||
|
* @创建人: xuqm
|
||||||
|
* @创建时间:2022/6/20 下午 05:06
|
||||||
|
* @修改记录:
|
||||||
|
*/
|
||||||
|
data class MqMessage(val no:String)
|
||||||
@ -0,0 +1,168 @@
|
|||||||
|
package com.bjca.hp.acupuncture.model
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class RegModel(
|
||||||
|
|
||||||
|
@field:SerializedName("total")
|
||||||
|
val total: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("size")
|
||||||
|
val size: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("nulls")
|
||||||
|
val nulls: String,
|
||||||
|
|
||||||
|
@field:SerializedName("index")
|
||||||
|
val index: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("items")
|
||||||
|
val items: List<ItemsItem3>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ItemsItem3(
|
||||||
|
|
||||||
|
@field:SerializedName("date")
|
||||||
|
val date: String,
|
||||||
|
|
||||||
|
@field:SerializedName("additionUserId")
|
||||||
|
val additionUserId: String,
|
||||||
|
|
||||||
|
@field:SerializedName("deptName")
|
||||||
|
val deptName: String,
|
||||||
|
|
||||||
|
@field:SerializedName("seqNo")
|
||||||
|
val seqNo: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("patientId")
|
||||||
|
val patientId: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("signInDate")
|
||||||
|
val signInDate: String,
|
||||||
|
|
||||||
|
@field:SerializedName("patientGender")
|
||||||
|
val patientGender: String,
|
||||||
|
|
||||||
|
@field:SerializedName("opType")
|
||||||
|
val opType: String,
|
||||||
|
|
||||||
|
@field:SerializedName("ifSubsequent")
|
||||||
|
val ifSubsequent: Boolean,
|
||||||
|
|
||||||
|
@field:SerializedName("registrarName")
|
||||||
|
val registrarName: String,
|
||||||
|
|
||||||
|
@field:SerializedName("ifDoctorAdd")
|
||||||
|
val ifDoctorAdd: Boolean,
|
||||||
|
|
||||||
|
@field:SerializedName("cardNo")
|
||||||
|
val cardNo: String,
|
||||||
|
|
||||||
|
@field:SerializedName("additionUserName")
|
||||||
|
val additionUserName: String,
|
||||||
|
|
||||||
|
@field:SerializedName("treatDate")
|
||||||
|
val treatDate: String,
|
||||||
|
|
||||||
|
@field:SerializedName("takingDate")
|
||||||
|
val takingDate: String,
|
||||||
|
|
||||||
|
@field:SerializedName("ifDeleted")
|
||||||
|
val ifDeleted: Boolean,
|
||||||
|
|
||||||
|
@field:SerializedName("doctorName")
|
||||||
|
val doctorName: String,
|
||||||
|
|
||||||
|
@field:SerializedName("appointmentChannelCode")
|
||||||
|
val appointmentChannelCode: String,
|
||||||
|
|
||||||
|
@field:SerializedName("lineNo")
|
||||||
|
val lineNo: Double,
|
||||||
|
|
||||||
|
@field:SerializedName("doctorId")
|
||||||
|
val doctorId: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("price")
|
||||||
|
val price: Double,
|
||||||
|
|
||||||
|
@field:SerializedName("ifAddition")
|
||||||
|
val ifAddition: Boolean,
|
||||||
|
|
||||||
|
@field:SerializedName("patientAge")
|
||||||
|
val patientAge: String,
|
||||||
|
|
||||||
|
@field:SerializedName("lockKey")
|
||||||
|
val lockKey: String,
|
||||||
|
|
||||||
|
@field:SerializedName("id")
|
||||||
|
val id: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("state")
|
||||||
|
val state: String,
|
||||||
|
|
||||||
|
@field:SerializedName("paymentState")
|
||||||
|
val paymentState: String,
|
||||||
|
|
||||||
|
@field:SerializedName("regType")
|
||||||
|
val regType: String,
|
||||||
|
|
||||||
|
@field:SerializedName("periodEnd")
|
||||||
|
val periodEnd: String,
|
||||||
|
|
||||||
|
@field:SerializedName("registrarId")
|
||||||
|
val registrarId: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("patientName")
|
||||||
|
val patientName: String,
|
||||||
|
|
||||||
|
@field:SerializedName("targetId")
|
||||||
|
val targetId: String,
|
||||||
|
|
||||||
|
@field:SerializedName("cardType")
|
||||||
|
val cardType: String,
|
||||||
|
|
||||||
|
@field:SerializedName("pay")
|
||||||
|
val pay: Double,
|
||||||
|
|
||||||
|
@field:SerializedName("lineId")
|
||||||
|
val lineId: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("occupationalInjury")
|
||||||
|
val occupationalInjury: String,
|
||||||
|
|
||||||
|
@field:SerializedName("version")
|
||||||
|
val version: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("patientPhone")
|
||||||
|
val patientPhone: String,
|
||||||
|
|
||||||
|
@field:SerializedName("ifEmergency")
|
||||||
|
val ifEmergency: Boolean,
|
||||||
|
|
||||||
|
@field:SerializedName("patientLevel")
|
||||||
|
val patientLevel: String,
|
||||||
|
|
||||||
|
@field:SerializedName("periodType")
|
||||||
|
val periodType: String,
|
||||||
|
|
||||||
|
@field:SerializedName("opNo")
|
||||||
|
val opNo: String,
|
||||||
|
|
||||||
|
@field:SerializedName("ifMaternityInsurance")
|
||||||
|
val ifMaternityInsurance: Boolean,
|
||||||
|
|
||||||
|
@field:SerializedName("periodStart")
|
||||||
|
val periodStart: String,
|
||||||
|
|
||||||
|
@field:SerializedName("appointmentDate")
|
||||||
|
val appointmentDate: String,
|
||||||
|
|
||||||
|
@field:SerializedName("appCardType")
|
||||||
|
val appCardType: String,
|
||||||
|
|
||||||
|
@field:SerializedName("deptCode")
|
||||||
|
val deptCode: String,
|
||||||
|
|
||||||
|
@field:SerializedName("appCardNo")
|
||||||
|
val appCardNo: String
|
||||||
|
)
|
||||||
@ -0,0 +1,153 @@
|
|||||||
|
package com.bjca.hp.acupuncture.model
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class RpDetailModel(
|
||||||
|
|
||||||
|
@field:SerializedName("total")
|
||||||
|
val total: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("size")
|
||||||
|
val size: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("nulls")
|
||||||
|
val nulls: String,
|
||||||
|
|
||||||
|
@field:SerializedName("index")
|
||||||
|
val index: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("items")
|
||||||
|
val items: List<ItemsItem2>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ItemsItem2(
|
||||||
|
|
||||||
|
@field:SerializedName("shelfIndex")
|
||||||
|
val shelfIndex: String,
|
||||||
|
|
||||||
|
@field:SerializedName("shelfCommand")
|
||||||
|
val shelfCommand: String,
|
||||||
|
|
||||||
|
@field:SerializedName("standard")
|
||||||
|
val standard: String,
|
||||||
|
|
||||||
|
@field:SerializedName("no")
|
||||||
|
val no: String,
|
||||||
|
|
||||||
|
@field:SerializedName("storehouseCode")
|
||||||
|
val storehouseCode: String,
|
||||||
|
|
||||||
|
@field:SerializedName("code")
|
||||||
|
val code: String,
|
||||||
|
|
||||||
|
@field:SerializedName("usage")
|
||||||
|
val usage: String,
|
||||||
|
|
||||||
|
@field:SerializedName("appNo")
|
||||||
|
val appNo: String,
|
||||||
|
|
||||||
|
@field:SerializedName("memo")
|
||||||
|
val memo: String,
|
||||||
|
|
||||||
|
@field:SerializedName("herbalSpecialUsage")
|
||||||
|
val herbalSpecialUsage: String,
|
||||||
|
|
||||||
|
@field:SerializedName("restrict")
|
||||||
|
val restrict: String,
|
||||||
|
|
||||||
|
@field:SerializedName("type")
|
||||||
|
val type: String,
|
||||||
|
|
||||||
|
@field:SerializedName("dosagePerTime")
|
||||||
|
val dosagePerTime: String,
|
||||||
|
|
||||||
|
@field:SerializedName("frequency")
|
||||||
|
val frequency: String,
|
||||||
|
|
||||||
|
@field:SerializedName("insuranceCode")
|
||||||
|
val insuranceCode: String,
|
||||||
|
|
||||||
|
@field:SerializedName("totalDose")
|
||||||
|
val totalDose: String,
|
||||||
|
|
||||||
|
@field:SerializedName("times")
|
||||||
|
val times: String,
|
||||||
|
|
||||||
|
@field:SerializedName("price")
|
||||||
|
val price: Double,
|
||||||
|
|
||||||
|
@field:SerializedName("mnemonic")
|
||||||
|
val mnemonic: String,
|
||||||
|
|
||||||
|
@field:SerializedName("offsetState")
|
||||||
|
val offsetState: String,
|
||||||
|
|
||||||
|
@field:SerializedName("warning")
|
||||||
|
val warning: String,
|
||||||
|
|
||||||
|
@field:SerializedName("lockKey")
|
||||||
|
val lockKey: String,
|
||||||
|
|
||||||
|
@field:SerializedName("id")
|
||||||
|
val id: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("rpClass")
|
||||||
|
val rpClass: String,
|
||||||
|
|
||||||
|
@field:SerializedName("groupNo")
|
||||||
|
val groupNo: String,
|
||||||
|
|
||||||
|
@field:SerializedName("key")
|
||||||
|
val key: String,
|
||||||
|
|
||||||
|
@field:SerializedName("dosageUnit")
|
||||||
|
val dosageUnit: String,
|
||||||
|
|
||||||
|
@field:SerializedName("quantity")
|
||||||
|
val quantity: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("cost")
|
||||||
|
val cost: Double,
|
||||||
|
|
||||||
|
@field:SerializedName("rpNo")
|
||||||
|
val rpNo: String,
|
||||||
|
|
||||||
|
@field:SerializedName("lotNumber")
|
||||||
|
val lotNumber: String,
|
||||||
|
|
||||||
|
@field:SerializedName("manufacturerCode")
|
||||||
|
val manufacturerCode: String,
|
||||||
|
|
||||||
|
@field:SerializedName("approvalNumber")
|
||||||
|
val approvalNumber: String,
|
||||||
|
|
||||||
|
@field:SerializedName("feeType")
|
||||||
|
val feeType: String,
|
||||||
|
|
||||||
|
@field:SerializedName("unit")
|
||||||
|
val unit: String,
|
||||||
|
|
||||||
|
@field:SerializedName("symptom")
|
||||||
|
val symptom: String,
|
||||||
|
|
||||||
|
@field:SerializedName("form")
|
||||||
|
val form: String,
|
||||||
|
|
||||||
|
@field:SerializedName("opNo")
|
||||||
|
val opNo: String,
|
||||||
|
|
||||||
|
@field:SerializedName("name")
|
||||||
|
val name: String,
|
||||||
|
|
||||||
|
@field:SerializedName("parts")
|
||||||
|
val parts: String,
|
||||||
|
|
||||||
|
@field:SerializedName("days")
|
||||||
|
val days: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("executorDeptCode")
|
||||||
|
val executorDeptCode: String,
|
||||||
|
|
||||||
|
@field:SerializedName("offsetId")
|
||||||
|
val offsetId: Any
|
||||||
|
)
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.bjca.hp.acupuncture.model
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class RpModel(
|
||||||
|
|
||||||
|
@field:SerializedName("total")
|
||||||
|
val total: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("size")
|
||||||
|
val size: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("nulls")
|
||||||
|
val nulls: Any,
|
||||||
|
|
||||||
|
@field:SerializedName("index")
|
||||||
|
val index: Int,
|
||||||
|
|
||||||
|
@field:SerializedName("items")
|
||||||
|
val items: List<ItemsItems>
|
||||||
|
)
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
package com.bjca.hp.acupuncture.model
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import com.xuqm.base.adapter.BaseItem
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
data class WelcomeLIstModel(
|
||||||
|
|
||||||
|
@field:SerializedName("total")
|
||||||
|
val total: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("size")
|
||||||
|
val size: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("nulls")
|
||||||
|
val nulls: Any? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("index")
|
||||||
|
val index: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("items")
|
||||||
|
val items: ArrayList<ItemsItem> = arrayListOf()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ItemsItem(
|
||||||
|
|
||||||
|
@field:SerializedName("standard")
|
||||||
|
val standard: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("storehouseCode")
|
||||||
|
val storehouseCode: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("shelfIndex")
|
||||||
|
val shelfIndex: Any? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("code")
|
||||||
|
val code: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("purpose")
|
||||||
|
val purpose: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("supplierCode")
|
||||||
|
val supplierCode: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("herbalSku")
|
||||||
|
val herbalSku: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("type")
|
||||||
|
val type: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("restrict")
|
||||||
|
val restrict: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("rate")
|
||||||
|
val rate: Double? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("price")
|
||||||
|
val price: Double? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("srcId")
|
||||||
|
val srcId: Any? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("disabled")
|
||||||
|
val disabled: Boolean? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("lockKey")
|
||||||
|
val lockKey: Any? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("id")
|
||||||
|
val id: Int? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("applyQuantity")
|
||||||
|
val applyQuantity: Double? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("shortCode")
|
||||||
|
val shortCode: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("expirationDate")
|
||||||
|
val expirationDate: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("brandName")
|
||||||
|
val brandName: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("cost")
|
||||||
|
val cost: Double? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("quantity")
|
||||||
|
val quantity: Double? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("lotNumber")
|
||||||
|
val lotNumber: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("manufacturerCode")
|
||||||
|
val manufacturerCode: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("feeType")
|
||||||
|
val feeType: Any? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("approvalNumber")
|
||||||
|
val approvalNumber: Any? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("ceilType")
|
||||||
|
val ceilType: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("unit")
|
||||||
|
val unit: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("form")
|
||||||
|
val form: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("name")
|
||||||
|
val name: String? = null
|
||||||
|
) : BaseItem()
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.bjca.hp.acupuncture.receiver
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import com.bjca.hp.acupuncture.ui.MainActivity
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* <pre></pre>
|
||||||
|
* @文件名称: BootCompleteReceiver
|
||||||
|
* @包 路 径: com.bjca.hp.acupuncture.receiver
|
||||||
|
* @版权所有:北京数字医信责任有限公司 (C) 2022
|
||||||
|
*
|
||||||
|
* @类描述:
|
||||||
|
* @版本: V1.0
|
||||||
|
* @创建人: xuqm
|
||||||
|
* @创建时间:2022/6/24 下午 06:34
|
||||||
|
* @修改记录:
|
||||||
|
*/
|
||||||
|
class BootCompleteReceiver : BroadcastReceiver(){
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if(Intent.ACTION_BOOT_COMPLETED == intent.action){
|
||||||
|
val thisIntent = Intent(context, MainActivity::class.java)
|
||||||
|
thisIntent.action = "android.intent.action.MAIN";
|
||||||
|
thisIntent.addCategory("android.intent.category.LAUNCHER");
|
||||||
|
thisIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
|
context.startActivity(thisIntent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,130 @@
|
|||||||
|
package com.bjca.hp.acupuncture.repository
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.xuqm.base.common.SHARE_UESR_TOKEN
|
||||||
|
import com.xuqm.base.extensions.getStringForPreferences
|
||||||
|
import com.xuqm.base.extensions.log
|
||||||
|
import com.xuqm.base.extensions.loge
|
||||||
|
import okhttp3.Headers
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Response
|
||||||
|
import okhttp3.internal.http.HttpHeaders
|
||||||
|
import okhttp3.internal.http.StatusLine
|
||||||
|
import okio.Buffer
|
||||||
|
import okio.BufferedSource
|
||||||
|
import okio.GzipSource
|
||||||
|
import java.io.EOFException
|
||||||
|
import java.net.HttpURLConnection
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderInterceptor(val context: Context) : Interceptor {
|
||||||
|
val UTF8 = Charset.forName("UTF-8")
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val original = chain.request()
|
||||||
|
|
||||||
|
//请求定制:添加请求头
|
||||||
|
val requestBuilder = original.newBuilder()
|
||||||
|
.header("Authentication", context.getStringForPreferences(SHARE_UESR_TOKEN))
|
||||||
|
.addHeader("Content-Type", "application/json;charset=UTF-8")
|
||||||
|
|
||||||
|
// context.getStringForPreferences(SHARE_UESR_TOKEN).loge()
|
||||||
|
|
||||||
|
val request = requestBuilder.build()
|
||||||
|
"${request.url()}(${request.method()})".loge()
|
||||||
|
|
||||||
|
val headers = request.headers()
|
||||||
|
|
||||||
|
// request.body()?.also {
|
||||||
|
//
|
||||||
|
// if (!bodyHasUnknownEncoding(headers)) {
|
||||||
|
// val buffer = Buffer()
|
||||||
|
// it.writeTo(buffer)
|
||||||
|
//
|
||||||
|
// var charset = Charset.forName("UTF-8")
|
||||||
|
// it.contentType()?.also { its -> charset = its.charset(Charset.forName("UTF-8"))!! }
|
||||||
|
//
|
||||||
|
//// if (isPlaintext(buffer)) {
|
||||||
|
//// buffer.readString(charset).loge()
|
||||||
|
//// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
val response = chain.proceed(request)
|
||||||
|
|
||||||
|
response.body()?.also {
|
||||||
|
if (!bodyHasUnknownEncoding(headers) && hasBody(response)) {
|
||||||
|
val source: BufferedSource = it.source()
|
||||||
|
source.request(Long.MAX_VALUE) // Buffer the entire body.
|
||||||
|
var buffer = source.buffer
|
||||||
|
if ("gzip".equals(headers.get("Content-Encoding"), ignoreCase = true)) {
|
||||||
|
var gzippedResponseBody: GzipSource? = null
|
||||||
|
try {
|
||||||
|
gzippedResponseBody = GzipSource(buffer.clone())
|
||||||
|
buffer = Buffer()
|
||||||
|
buffer.writeAll(gzippedResponseBody)
|
||||||
|
} finally {
|
||||||
|
gzippedResponseBody?.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var charset = UTF8
|
||||||
|
it.contentType()?.also { its -> charset = its.charset(Charset.forName("UTF-8"))!! }
|
||||||
|
|
||||||
|
|
||||||
|
if (isPlaintext(buffer)) {
|
||||||
|
buffer.clone().readString(charset).log()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bodyHasUnknownEncoding(headers: Headers): Boolean {
|
||||||
|
val contentEncoding = headers["Content-Encoding"]
|
||||||
|
return (contentEncoding != null && !contentEncoding.equals("identity", ignoreCase = true)
|
||||||
|
&& !contentEncoding.equals("gzip", ignoreCase = true))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isPlaintext(buffer: Buffer): Boolean {
|
||||||
|
return try {
|
||||||
|
val prefix = Buffer()
|
||||||
|
val byteCount = if (buffer.size < 64) buffer.size else 64
|
||||||
|
buffer.copyTo(prefix, 0, byteCount)
|
||||||
|
for (i in 0..15) {
|
||||||
|
if (prefix.exhausted()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
val codePoint = prefix.readUtf8CodePoint()
|
||||||
|
if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} catch (e: EOFException) {
|
||||||
|
false // Truncated UTF-8 sequence.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasBody(response: Response): Boolean {
|
||||||
|
// HEAD requests never yield a body regardless of the response headers.
|
||||||
|
if (response.request().method() == "HEAD") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val responseCode = response.code()
|
||||||
|
if ((responseCode < StatusLine.HTTP_CONTINUE || responseCode >= 200)
|
||||||
|
&& responseCode != HttpURLConnection.HTTP_NO_CONTENT && responseCode != HttpURLConnection.HTTP_NOT_MODIFIED
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Content-Length or Transfer-Encoding headers disagree with the response code, the
|
||||||
|
// response is malformed. For best compatibility, we honor the headers.
|
||||||
|
return HttpHeaders.contentLength(response) != -1L || "chunked".equals(
|
||||||
|
response.header("Transfer-Encoding"),
|
||||||
|
ignoreCase = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.bjca.hp.acupuncture.repository
|
||||||
|
|
||||||
|
import com.bjca.hp.acupuncture.model.*
|
||||||
|
import com.xuqm.sdhbwfu.core.model.HttpResult
|
||||||
|
import io.reactivex.Observable
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Path
|
||||||
|
import retrofit2.http.Query
|
||||||
|
|
||||||
|
|
||||||
|
interface Service {
|
||||||
|
@GET("drug/stock/standard?storehouseCode=2&type=&form=&purpose=&restrict=&danger=&antibiotic=&keyword=&manufacturerCode=&supplierCode=&expirationDateMin=&expirationDateMax=&sort=id&asc=false&papeIndexOnView=2&pageSize=20&tenantId=101")
|
||||||
|
fun standard(@Query("pageIndex") pageIndex: Int): Observable<WelcomeLIstModel>
|
||||||
|
|
||||||
|
// op/rp?no=CF220609004247&rpClass=药品&tenantId=101
|
||||||
|
@GET("op/rp?rpClass=药品&tenantId=101")
|
||||||
|
fun rp(@Query("no") no: String): Observable<RpModel>
|
||||||
|
|
||||||
|
// op/rpDetail?opNo=MZ220321036030&rpNo=CF220323001947&tenantId=101
|
||||||
|
@GET("op/rpDetail?tenantId=101")
|
||||||
|
fun rpDetail(@Query("opNo") opNo: String, @Query("rpNo") rpNo: String): Observable<RpDetailModel>
|
||||||
|
|
||||||
|
// op/reg?opNo=MZ220321036030&tenantId=101
|
||||||
|
@GET("op/reg?tenantId=101")
|
||||||
|
fun reg(@Query("opNo") opNo: String): Observable<RegModel>
|
||||||
|
|
||||||
|
// dict/DrugUsage?sort=id&asc=false&pageIndexOnView=1&pageSize=100&dictType=DrugType&pageIndex=0
|
||||||
|
@GET("dict/DrugUsage?sort=id&asc=false&pageIndexOnView=1&pageSize=100&dictType=DrugType&pageIndex=0")
|
||||||
|
fun drugUsage(): Observable<DrugUsage>
|
||||||
|
}
|
||||||
@ -0,0 +1,243 @@
|
|||||||
|
package com.bjca.hp.acupuncture.ui
|
||||||
|
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import com.bigkoo.alertview.AlertView
|
||||||
|
import com.bjca.hp.acupuncture.MyApplication
|
||||||
|
import com.bjca.hp.acupuncture.R
|
||||||
|
import com.bjca.hp.acupuncture.databinding.ActivityMainBinding
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItem2
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItem3
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItem5
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItems
|
||||||
|
import com.bjca.hp.acupuncture.viewmodel.MainVM
|
||||||
|
import com.xuqm.base.adapter.CommonAdapter
|
||||||
|
import com.xuqm.base.adapter.ViewHolder
|
||||||
|
import com.xuqm.base.dialog.loading.LoadingDialog
|
||||||
|
import com.xuqm.base.extensions.loge
|
||||||
|
import com.xuqm.base.ui.BaseActivity
|
||||||
|
import com.xuqm.sdhbwfu.core.extensions.linearLayoutManager
|
||||||
|
import com.xuqm.sdhbwfu.core.extensions.showMessage
|
||||||
|
import tp.xmaihh.serialport.SerialHelper
|
||||||
|
import tp.xmaihh.serialport.bean.ComBean
|
||||||
|
|
||||||
|
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||||
|
override fun fullscreen(): Boolean = true
|
||||||
|
override fun getLayoutId(): Int = R.layout.activity_main
|
||||||
|
|
||||||
|
private val vm: MainVM by viewModels()
|
||||||
|
|
||||||
|
override fun initView(savedInstanceState: Bundle?) {
|
||||||
|
super.initView(savedInstanceState)
|
||||||
|
|
||||||
|
|
||||||
|
sourceHanSansCNBold =
|
||||||
|
Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Bold.ttf")
|
||||||
|
sourceHanSansCNMedium =
|
||||||
|
Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Medium.ttf")
|
||||||
|
sourceHanSansCNNormal =
|
||||||
|
Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Normal.ttf")
|
||||||
|
sourceHanSansCNRegular =
|
||||||
|
Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Regular.ttf")
|
||||||
|
din =
|
||||||
|
Typeface.createFromAsset(mContext?.assets, "fonts/DIN-Alternate-Bold.ttf")
|
||||||
|
|
||||||
|
binding.title.typeface = sourceHanSansCNBold
|
||||||
|
binding.name.typeface = sourceHanSansCNBold
|
||||||
|
binding.tags.typeface = sourceHanSansCNMedium
|
||||||
|
binding.btn.typeface = sourceHanSansCNBold
|
||||||
|
|
||||||
|
binding.title1.typeface = sourceHanSansCNMedium
|
||||||
|
binding.title2.typeface = sourceHanSansCNMedium
|
||||||
|
binding.title3.typeface = sourceHanSansCNMedium
|
||||||
|
binding.title5.typeface = sourceHanSansCNMedium
|
||||||
|
|
||||||
|
binding.n1.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v1.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n2.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v2.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n3.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v3.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n4.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v4.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n5.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v5.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n6.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v6.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n7.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v7.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n8.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v8.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n9.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v9.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n10.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v10.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n11.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v11.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n12.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v12.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n13.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v13.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n14.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v14.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n15.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v15.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n16.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v16.typeface = sourceHanSansCNRegular
|
||||||
|
binding.n17.typeface = sourceHanSansCNRegular
|
||||||
|
binding.v17.typeface = sourceHanSansCNRegular
|
||||||
|
|
||||||
|
|
||||||
|
binding.list.linearLayoutManager(mContext, 15)
|
||||||
|
binding.list.adapter = adapter
|
||||||
|
|
||||||
|
|
||||||
|
binding.btn.setOnClickListener {
|
||||||
|
LoadingDialog.showDialog("")
|
||||||
|
|
||||||
|
if (adapter.datas.size > 0)
|
||||||
|
sndMessage(0)
|
||||||
|
else {
|
||||||
|
// s.sendHex("0105002cff004DF3"); // 发送Hex
|
||||||
|
|
||||||
|
MyApplication.getInstance().runOnUiThreadDelay({
|
||||||
|
try {
|
||||||
|
s.sendHex("02050001ff00DDC9"); // 发送Hex
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.showMessage()
|
||||||
|
}
|
||||||
|
LoadingDialog.dismissDialog()
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sndMessage(i: Int) {
|
||||||
|
if (i >= adapter.datas.size) {
|
||||||
|
LoadingDialog.dismissDialog()
|
||||||
|
AlertView(
|
||||||
|
"取药完成", adapter.datas.map { it.shelfIndex}.joinToString(), null, arrayOf("确定"), null, mContext,
|
||||||
|
AlertView.Style.Alert
|
||||||
|
) { _, _ ->
|
||||||
|
mContext.finish()
|
||||||
|
}.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
s.sendHex(adapter.datas[i].shelfCommand); // 发送Hex
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.showMessage()
|
||||||
|
}
|
||||||
|
MyApplication.getInstance().runOnUiThreadDelay({
|
||||||
|
sndMessage(i + 1)
|
||||||
|
}, 2300)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var sourceHanSansCNBold: Typeface
|
||||||
|
lateinit var sourceHanSansCNMedium: Typeface
|
||||||
|
lateinit var sourceHanSansCNNormal: Typeface
|
||||||
|
lateinit var sourceHanSansCNRegular: Typeface
|
||||||
|
lateinit var din: Typeface
|
||||||
|
|
||||||
|
var rp: ItemsItems? = null
|
||||||
|
var regM: ItemsItem3? = null
|
||||||
|
var usages: List<ItemsItem5> = listOf()
|
||||||
|
lateinit var s: SerialHelper
|
||||||
|
override fun initData() {
|
||||||
|
super.initData()
|
||||||
|
s = object : SerialHelper("/dev/ttyS0", 38400) {
|
||||||
|
override fun onDataReceived(paramComBean: ComBean?) {
|
||||||
|
paramComBean?.bRec?.loge()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
s.open()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.showMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.status.observe(this) {
|
||||||
|
rp = it
|
||||||
|
rerresh()
|
||||||
|
}
|
||||||
|
vm.regM.observe(this) {
|
||||||
|
regM = it
|
||||||
|
rerresh()
|
||||||
|
}
|
||||||
|
vm.usages.observe(this) {
|
||||||
|
usages = it ?: listOf()
|
||||||
|
intent.getStringExtra("opNo")?.let { it1 -> vm.getRp(it1) }
|
||||||
|
}
|
||||||
|
vm.rpDetail.observe(this) {
|
||||||
|
adapter.setmDatas(it)
|
||||||
|
}
|
||||||
|
vm.drugUsage()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUsage(code: String): String {
|
||||||
|
var text = "--"
|
||||||
|
usages.forEach {
|
||||||
|
if (it.code == code) {
|
||||||
|
text = it.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rerresh() {
|
||||||
|
rp?.let {
|
||||||
|
binding.v8.text = it.diagnosis
|
||||||
|
binding.v14.text = it.doctorName
|
||||||
|
binding.v16.text = "${it.price}元"
|
||||||
|
binding.v13.text = it.approveUserName
|
||||||
|
binding.v11.text = it.no
|
||||||
|
}
|
||||||
|
regM?.let {
|
||||||
|
binding.v1.text = it.patientName
|
||||||
|
binding.v2.text = it.patientGender
|
||||||
|
binding.v3.text = "${it.patientAge}"
|
||||||
|
binding.v4.text = it.patientPhone
|
||||||
|
binding.v5.text = ""
|
||||||
|
|
||||||
|
binding.v6.text = it.appCardNo
|
||||||
|
binding.v7.text = it.deptName
|
||||||
|
binding.v9.text = it.date
|
||||||
|
binding.v10.text = it.opType
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val adapter = object : CommonAdapter<ItemsItem2>(R.layout.item_main) {
|
||||||
|
override fun convert(holder: ViewHolder, item: ItemsItem2, position: Int) {
|
||||||
|
|
||||||
|
holder.setTypeface(R.id.index, sourceHanSansCNMedium)
|
||||||
|
.setText(R.id.index, "${position + 1}")
|
||||||
|
.setTypeface(R.id.n1, sourceHanSansCNRegular)
|
||||||
|
.setTypeface(R.id.v1, sourceHanSansCNRegular)
|
||||||
|
.setText(R.id.v1, item.name)//名称
|
||||||
|
.setTypeface(R.id.n2, sourceHanSansCNRegular)
|
||||||
|
.setTypeface(R.id.v1, sourceHanSansCNRegular)
|
||||||
|
.setText(R.id.v2, item.standard)//规格
|
||||||
|
.setTypeface(R.id.n3, sourceHanSansCNRegular)
|
||||||
|
.setTypeface(R.id.v3, sourceHanSansCNRegular)
|
||||||
|
.setText(R.id.v3, "${item.quantity}${item.unit}")//数量
|
||||||
|
.setTypeface(R.id.n4, sourceHanSansCNRegular)
|
||||||
|
.setTypeface(R.id.v4, sourceHanSansCNRegular)
|
||||||
|
.setText(R.id.v4, getUsage(item.usage))//使用方法---码表
|
||||||
|
.setTypeface(R.id.n5, sourceHanSansCNRegular)
|
||||||
|
.setTypeface(R.id.v5, sourceHanSansCNRegular)
|
||||||
|
.setText(R.id.v5, "${item.dosagePerTime}${item.dosageUnit}")//用量
|
||||||
|
.setTypeface(R.id.n6, sourceHanSansCNRegular)
|
||||||
|
.setTypeface(R.id.v6, sourceHanSansCNRegular)
|
||||||
|
.setText(R.id.v6, item.frequency)//频次---码表
|
||||||
|
.setTypeface(R.id.n7, sourceHanSansCNRegular)
|
||||||
|
.setTypeface(R.id.v7, sourceHanSansCNRegular)
|
||||||
|
.setText(R.id.v7, "${item.days}天")//使用周期
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,209 @@
|
|||||||
|
package com.bjca.hp.acupuncture.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import com.bjca.hp.acupuncture.MyApplication
|
||||||
|
import com.bjca.hp.acupuncture.R
|
||||||
|
import com.bjca.hp.acupuncture.databinding.ActivitySettingBinding
|
||||||
|
import com.xuqm.base.extensions.loge
|
||||||
|
import com.xuqm.base.ui.BaseActivity
|
||||||
|
import com.xuqm.sdhbwfu.core.extensions.showMessage
|
||||||
|
import kotlinx.android.synthetic.main.activity_setting.*
|
||||||
|
import tp.xmaihh.serialport.SerialHelper
|
||||||
|
import tp.xmaihh.serialport.bean.ComBean
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class SettingActivity : BaseActivity<ActivitySettingBinding>() {
|
||||||
|
override fun getLayoutId(): Int = R.layout.activity_setting
|
||||||
|
override fun initView(savedInstanceState: Bundle?) {
|
||||||
|
super.initView(savedInstanceState)
|
||||||
|
binding.a13.setOnClickListener {
|
||||||
|
|
||||||
|
val a11 = binding.a11.text.toString().toInt()
|
||||||
|
if (a11 <= 0 || a11 > 9) {
|
||||||
|
"请输入正确的柜号,从1开始".showMessage()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
val a12 = binding.a12.text.toString().toInt()
|
||||||
|
if (a12 <= 0) {
|
||||||
|
"请输入正确的柜门号,从1开始".showMessage()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
val b1 = "0${a11}05${intToHex(a12, 4)}ff00"
|
||||||
|
val b2 = getCRC(b1)
|
||||||
|
try {
|
||||||
|
s.sendHex("${b1}${b2}"); // 发送Hex
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.showMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
binding.a24.setOnClickListener {
|
||||||
|
|
||||||
|
val a21 = binding.a21.text.toString().toInt()
|
||||||
|
if (a21 <= 0 || a21 > 9) {
|
||||||
|
"请输入正确的柜号,从1开始".showMessage()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
val a22 = binding.a22.text.toString().toInt()
|
||||||
|
if (a22 <= 0) {
|
||||||
|
"请输入正确的柜门号,从1开始".showMessage()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
val a23 = binding.a23.text.toString().toInt()
|
||||||
|
if (a23 <= 0) {
|
||||||
|
"请输入正确的柜门号,从1开始".showMessage()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
sndMessage(a21, a22, a23)
|
||||||
|
|
||||||
|
}
|
||||||
|
binding.a31.setOnClickListener {
|
||||||
|
sndMessage(1, 1, 84)
|
||||||
|
}
|
||||||
|
binding.a32.setOnClickListener {
|
||||||
|
sndMessage(2, 1, 84)
|
||||||
|
}
|
||||||
|
binding.a33.setOnClickListener {
|
||||||
|
sndMessage(3, 1, 84)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun sndMessage(i: Int, ii: Int, iii: Int) {
|
||||||
|
if (ii > iii) return
|
||||||
|
val b1 = "0${i}05${intToHex(ii, 4)}ff00"
|
||||||
|
val b2 = getCRC(b1)
|
||||||
|
try {
|
||||||
|
s.sendHex("${b1}${b2}"); // 发送Hex
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.showMessage()
|
||||||
|
}
|
||||||
|
MyApplication.getInstance().runOnUiThreadDelay({
|
||||||
|
sndMessage(i, ii + 1, iii)
|
||||||
|
}, 2300)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lateinit var s: SerialHelper
|
||||||
|
override fun initData() {
|
||||||
|
super.initData()
|
||||||
|
s = object : SerialHelper("/dev/ttyS0", 38400) {
|
||||||
|
override fun onDataReceived(paramComBean: ComBean?) {
|
||||||
|
paramComBean?.bRec?.loge()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
s.open()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.showMessage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 10进制转16进制.
|
||||||
|
*
|
||||||
|
* @param n 10进制数
|
||||||
|
* @param size 转换后的16进制位数
|
||||||
|
* @return 转换结果
|
||||||
|
*/
|
||||||
|
private fun intToHex(n: Int, size: Int): String {
|
||||||
|
var n = n
|
||||||
|
var s = StringBuffer()
|
||||||
|
var a: String
|
||||||
|
val b = charArrayOf(
|
||||||
|
'0',
|
||||||
|
'1',
|
||||||
|
'2',
|
||||||
|
'3',
|
||||||
|
'4',
|
||||||
|
'5',
|
||||||
|
'6',
|
||||||
|
'7',
|
||||||
|
'8',
|
||||||
|
'9',
|
||||||
|
'A',
|
||||||
|
'B',
|
||||||
|
'C',
|
||||||
|
'D',
|
||||||
|
'E',
|
||||||
|
'F'
|
||||||
|
)
|
||||||
|
while (n != 0) {
|
||||||
|
s = s.append(b[n % 16])
|
||||||
|
n = n / 16
|
||||||
|
}
|
||||||
|
a = s.reverse().toString()
|
||||||
|
a = add_zero(a, size)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add_zero(str: String, size: Int): String {
|
||||||
|
var str = str
|
||||||
|
if (str.length < size) {
|
||||||
|
str = "0$str"
|
||||||
|
str = add_zero(str, size)
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getCRC(data: String): String {
|
||||||
|
var data = data
|
||||||
|
data = data.replace(" ", "")
|
||||||
|
val len = data.length
|
||||||
|
if (len % 2 != 0) {
|
||||||
|
return "0000"
|
||||||
|
}
|
||||||
|
val num = len / 2
|
||||||
|
val para = ByteArray(num)
|
||||||
|
for (i in 0 until num) {
|
||||||
|
val value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16)
|
||||||
|
para[i] = value.toByte()
|
||||||
|
}
|
||||||
|
return getCRC(para)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算CRC16校验码
|
||||||
|
*
|
||||||
|
* @param bytes
|
||||||
|
* 字节数组
|
||||||
|
* @return [String] 校验码
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
fun getCRC(bytes: ByteArray): String {
|
||||||
|
// CRC寄存器全为1
|
||||||
|
var CRC = 0x0000ffff
|
||||||
|
// 多项式校验值
|
||||||
|
val POLYNOMIAL = 0x0000a001
|
||||||
|
var i: Int
|
||||||
|
var j: Int
|
||||||
|
i = 0
|
||||||
|
while (i < bytes.size) {
|
||||||
|
CRC = CRC xor (bytes[i].toInt() and 0x000000ff)
|
||||||
|
j = 0
|
||||||
|
while (j < 8) {
|
||||||
|
if (CRC and 0x00000001 != 0) {
|
||||||
|
CRC = CRC shr 1
|
||||||
|
CRC = CRC xor POLYNOMIAL
|
||||||
|
} else {
|
||||||
|
CRC = CRC shr 1
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
// 结果转换为16进制
|
||||||
|
var result = Integer.toHexString(CRC).uppercase(Locale.getDefault())
|
||||||
|
if (result.length != 4) {
|
||||||
|
val sb = StringBuffer("0000")
|
||||||
|
result = sb.replace(4 - result.length, 4, result).toString()
|
||||||
|
}
|
||||||
|
//高位在前地位在后
|
||||||
|
//return result.substring(2, 4) + " " + result.substring(0, 2);
|
||||||
|
// 交换高低位,低位在前高位在后
|
||||||
|
return result.substring(2, 4) + result.substring(0, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.bjca.hp.acupuncture.ui
|
||||||
|
|
||||||
|
import android.os.Build.VERSION_CODES.R
|
||||||
|
import android.os.Bundle
|
||||||
|
import com.bjca.hp.acupuncture.R
|
||||||
|
import com.bjca.hp.acupuncture.databinding.ActivityTestBinding
|
||||||
|
import com.xuqm.base.common.ToolsHelper
|
||||||
|
import com.xuqm.base.extensions.getStringForPreferences
|
||||||
|
import com.xuqm.base.extensions.putString
|
||||||
|
import com.xuqm.base.ui.BaseActivity
|
||||||
|
import com.xuqm.base.web.XWebViewHelper
|
||||||
|
|
||||||
|
class TestActivity : BaseActivity<ActivityTestBinding>() {
|
||||||
|
override fun getLayoutId(): Int = R.layout.activity_test
|
||||||
|
override fun initView(savedInstanceState: Bundle?) {
|
||||||
|
super.initView(savedInstanceState)
|
||||||
|
|
||||||
|
val str = getStringForPreferences("wurl")
|
||||||
|
if (!ToolsHelper.isNull(str))
|
||||||
|
binding.editUrl.setText(str)
|
||||||
|
|
||||||
|
binding.btn.setOnClickListener {
|
||||||
|
|
||||||
|
val url =
|
||||||
|
if (ToolsHelper.isNull(binding.editUrl.text)) "https://web.sdk.qcloud.com/trtc/webrtc/demo/quick-demo-vue3-ts/index.html#/"
|
||||||
|
else binding.editUrl.text.toString()
|
||||||
|
|
||||||
|
putString("wurl", url)
|
||||||
|
XWebViewHelper.startWebNoTopBar(
|
||||||
|
mContext,
|
||||||
|
url
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,166 @@
|
|||||||
|
package com.bjca.hp.acupuncture.ui
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.os.Bundle
|
||||||
|
import com.bjca.hp.acupuncture.R
|
||||||
|
import com.bjca.hp.acupuncture.common.RabbitMQUtil
|
||||||
|
import com.bjca.hp.acupuncture.databinding.ActivityWelcomeBinding
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItem
|
||||||
|
import com.bjca.hp.acupuncture.viewmodel.WelcomeVM
|
||||||
|
import com.xuqm.base.adapter.BasePagedAdapter
|
||||||
|
import com.xuqm.base.adapter.CommonPagedAdapter
|
||||||
|
import com.xuqm.base.adapter.ViewHolder
|
||||||
|
import com.xuqm.base.ui.BaseListFormLayoutActivity
|
||||||
|
import com.xuqm.sdhbwfu.core.extensions.gridLayoutManager
|
||||||
|
import com.xuqm.sdhbwfu.core.extensions.runWithPermission
|
||||||
|
import com.xuqm.sdhbwfu.core.extensions.toStrings
|
||||||
|
|
||||||
|
class WelcomeActivity : BaseListFormLayoutActivity<ItemsItem, WelcomeVM, ActivityWelcomeBinding>() {
|
||||||
|
|
||||||
|
override fun getLayoutId(): Int = R.layout.activity_welcome
|
||||||
|
override fun fullscreen(): Boolean = true
|
||||||
|
|
||||||
|
// lateinit var s: SerialHelper
|
||||||
|
|
||||||
|
lateinit var sourceHanSansCNBold: Typeface
|
||||||
|
lateinit var sourceHanSansCNMedium: Typeface
|
||||||
|
lateinit var sourceHanSansCNNormal: Typeface
|
||||||
|
lateinit var din: Typeface
|
||||||
|
lateinit var mq: RabbitMQUtil
|
||||||
|
|
||||||
|
private var oldTime = 0L
|
||||||
|
private var index = 0
|
||||||
|
|
||||||
|
override fun initView(savedInstanceState: Bundle?) {
|
||||||
|
super.initView(savedInstanceState)
|
||||||
|
|
||||||
|
sourceHanSansCNBold =
|
||||||
|
Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Bold.ttf")
|
||||||
|
sourceHanSansCNMedium =
|
||||||
|
Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Medium.ttf")
|
||||||
|
sourceHanSansCNNormal =
|
||||||
|
Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Normal.ttf")
|
||||||
|
din =
|
||||||
|
Typeface.createFromAsset(mContext?.assets, "fonts/DIN-Alternate-Bold.ttf")
|
||||||
|
|
||||||
|
|
||||||
|
binding.title.typeface = sourceHanSansCNBold
|
||||||
|
|
||||||
|
binding.title.setOnClickListener {
|
||||||
|
val newTime = System.currentTimeMillis()
|
||||||
|
if (newTime - oldTime < 2500 && oldTime != 0L) {
|
||||||
|
if (index > 5) {
|
||||||
|
startActivity(Intent(mContext, SettingActivity::class.java))
|
||||||
|
index = 0
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
} else {
|
||||||
|
oldTime = newTime
|
||||||
|
index = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// binding.list.gridLayoutManager(mContext, 6, 2)
|
||||||
|
// binding.list.adapter = adapter
|
||||||
|
|
||||||
|
// adapter.setmDatas(arrayListOf("空调", "水泵", "空气净化器", "阳台", "灯"))
|
||||||
|
recyclerView.gridLayoutManager(mContext, 21, 3)
|
||||||
|
|
||||||
|
|
||||||
|
adapter.setItemLongClickListener { _, _, _ ->
|
||||||
|
startActivity(Intent(mContext, MainActivity::class.java))
|
||||||
|
return@setItemLongClickListener true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
mq.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initData() {
|
||||||
|
super.initData()
|
||||||
|
|
||||||
|
|
||||||
|
runWithPermission(
|
||||||
|
"android.permission.MODIFY_AUDIO_SETTINGS",
|
||||||
|
"android.permission.RECORD_AUDIO",
|
||||||
|
"android.permission.CAMERA"
|
||||||
|
) {
|
||||||
|
startActivity(Intent(mContext, TestActivity::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
// XWebViewHelper.startWebNoTopBar(mContext,"https://mdtdemo.51trust.com/")
|
||||||
|
// mq = RabbitMQUtil("10.10.202.11", 5672, "guest", "guest")
|
||||||
|
//
|
||||||
|
// mq.receiveQueueMessage("RpNoByMedicineCabinet",
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// startActivity(Intent(mContext, MainActivity::class.java)
|
||||||
|
// .apply {
|
||||||
|
// putExtra(
|
||||||
|
// "opNo",
|
||||||
|
// GsonImplHelp.get().toObject(it, MqMessage::class.java).no
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// ) {
|
||||||
|
// it.loge()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// s = object : SerialHelper("/dev/ttyS0", 38400) {
|
||||||
|
// override fun onDataReceived(paramComBean: ComBean?) {
|
||||||
|
// paramComBean?.bRec?.loge()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// s.setStickPackageHelper {
|
||||||
|
// try {
|
||||||
|
// val available = it.available()
|
||||||
|
// if (available > 0) {
|
||||||
|
// val buffer = ByteArray(available)
|
||||||
|
// val size = it.read(buffer)
|
||||||
|
// if (size > 0) {
|
||||||
|
// return@setStickPackageHelper buffer;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// SystemClock.sleep(50);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } catch (e: IOException) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// return@setStickPackageHelper null
|
||||||
|
// }
|
||||||
|
|
||||||
|
// s.sendHex("02050001ff00DDC9"); // 发送Hex
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val adapter = object : CommonPagedAdapter<ItemsItem>(R.layout.item_welcome) {
|
||||||
|
override fun convert(holder: ViewHolder, item: ItemsItem, position: Int) {
|
||||||
|
holder
|
||||||
|
.setTypeface(R.id.index, sourceHanSansCNMedium)
|
||||||
|
.setTypeface(R.id.name, sourceHanSansCNBold)
|
||||||
|
.setTypeface(R.id.hint, sourceHanSansCNNormal)
|
||||||
|
.setTypeface(R.id.number, din)
|
||||||
|
.setTypeface(R.id.unit, sourceHanSansCNNormal)
|
||||||
|
.setTypeface(R.id.balance, sourceHanSansCNNormal)
|
||||||
|
.setText(R.id.index, "${position + 1}")
|
||||||
|
.setText(R.id.name, item.name)
|
||||||
|
.setText(R.id.hint, item.supplierCode)
|
||||||
|
.setText(R.id.number, item.price?.toStrings())
|
||||||
|
.setText(R.id.unit, "元/${item.unit}")
|
||||||
|
.setText(R.id.balance, "剩余:${item.quantity}${item.unit}")
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun adapter(): BasePagedAdapter<ItemsItem> = adapter
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
package com.bjca.hp.acupuncture.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.bjca.hp.acupuncture.MyApplication
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItem2
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItem3
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItem5
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItems
|
||||||
|
import com.bjca.hp.acupuncture.repository.Service
|
||||||
|
import com.xuqm.base.di.manager.HttpManager
|
||||||
|
import com.xuqm.base.extensions.showMessage
|
||||||
|
import com.xuqm.sdhbwfu.core.viewModel.BaseViewModel
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* <pre></pre>
|
||||||
|
* @文件名称: WelcomeVM
|
||||||
|
* @包 路 径: com.bjca.hp.acupuncture.viewmodel
|
||||||
|
* @版权所有:北京数字医信责任有限公司 (C) 2022
|
||||||
|
*
|
||||||
|
* @类描述:
|
||||||
|
* @版本: V1.0
|
||||||
|
* @创建人: xuqm
|
||||||
|
* @创建时间:2022/6/17 下午 02:33
|
||||||
|
* @修改记录:
|
||||||
|
*/
|
||||||
|
class MainVM : BaseViewModel() {
|
||||||
|
|
||||||
|
|
||||||
|
private val _status = MutableLiveData<ItemsItems>()
|
||||||
|
val status: LiveData<ItemsItems> = _status
|
||||||
|
|
||||||
|
fun getRp(opNo:String = "CF220609004247" ) {
|
||||||
|
HttpManager.getApi(MyApplication.appComponent1, Service::class.java)
|
||||||
|
.rp(opNo)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
{
|
||||||
|
_status.postValue(it.items[0])
|
||||||
|
rpDetail(it.items[0].opNo, it.items[0].no)
|
||||||
|
reg(it.items[0].opNo)
|
||||||
|
}, {
|
||||||
|
_status.postValue(null)
|
||||||
|
showMessage(it.toString())
|
||||||
|
}
|
||||||
|
).adds()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _rpDetail = MutableLiveData<List<ItemsItem2>>()
|
||||||
|
val rpDetail: LiveData<List<ItemsItem2>> = _rpDetail
|
||||||
|
|
||||||
|
fun rpDetail(opNo: String, rpNo: String) {
|
||||||
|
HttpManager.getApi(MyApplication.appComponent1, Service::class.java)
|
||||||
|
.rpDetail(opNo, rpNo)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
{
|
||||||
|
_rpDetail.postValue(it.items)
|
||||||
|
}, {
|
||||||
|
_rpDetail.postValue(null)
|
||||||
|
showMessage(it.toString())
|
||||||
|
}
|
||||||
|
).adds()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _regM = MutableLiveData<ItemsItem3>()
|
||||||
|
val regM: LiveData<ItemsItem3> = _regM
|
||||||
|
fun reg(opNo: String) {
|
||||||
|
HttpManager.getApi(MyApplication.appComponent1, Service::class.java)
|
||||||
|
.reg(opNo)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
{
|
||||||
|
_regM.postValue(it?.items?.get(0))
|
||||||
|
}, {
|
||||||
|
_regM.postValue(null)
|
||||||
|
showMessage(it.toString())
|
||||||
|
}
|
||||||
|
).adds()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _usages = MutableLiveData<List<ItemsItem5>>()
|
||||||
|
val usages: LiveData<List<ItemsItem5>> = _usages
|
||||||
|
fun drugUsage() {
|
||||||
|
HttpManager.getApi(MyApplication.appComponent2, Service::class.java)
|
||||||
|
.drugUsage()
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
{
|
||||||
|
_usages.postValue(it.items)
|
||||||
|
}, {
|
||||||
|
_usages.postValue(null)
|
||||||
|
showMessage(it.toString())
|
||||||
|
}
|
||||||
|
).adds()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package com.bjca.hp.acupuncture.viewmodel
|
||||||
|
|
||||||
|
import com.bjca.hp.acupuncture.model.ItemsItem
|
||||||
|
import com.bjca.hp.acupuncture.repository.Service
|
||||||
|
import com.xuqm.base.di.manager.HttpManager
|
||||||
|
import com.xuqm.base.extensions.showMessage
|
||||||
|
import com.xuqm.base.viewmodel.BaseListViewModel
|
||||||
|
import com.xuqm.base.viewmodel.callback.Response
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* <pre></pre>
|
||||||
|
* @文件名称: WelcomeVM
|
||||||
|
* @包 路 径: com.bjca.hp.acupuncture.viewmodel
|
||||||
|
* @版权所有:北京数字医信责任有限公司 (C) 2022
|
||||||
|
*
|
||||||
|
* @类描述:
|
||||||
|
* @版本: V1.0
|
||||||
|
* @创建人: xuqm
|
||||||
|
* @创建时间:2022/6/17 下午 02:33
|
||||||
|
* @修改记录:
|
||||||
|
*/
|
||||||
|
class WelcomeVM : BaseListViewModel<ItemsItem>() {
|
||||||
|
override fun loadData(page: Int, onResponse: Response<ItemsItem>) {
|
||||||
|
add(
|
||||||
|
HttpManager.getApi(Service::class.java)
|
||||||
|
.standard(page)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
{
|
||||||
|
onResponse.onResponse(it.items)
|
||||||
|
}, {
|
||||||
|
onResponse.onResponse(null)
|
||||||
|
// showMessage(it)
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.bjca.hp.acupuncture.widget;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* <pre></pre>
|
||||||
|
* @文件名称: ColorUser
|
||||||
|
* @包 路 径: com.bjca.hp.acupuncture.widget
|
||||||
|
* @版权所有:北京数字医信责任有限公司 (C) 2022
|
||||||
|
*
|
||||||
|
* @类描述:
|
||||||
|
* @版本: V1.0
|
||||||
|
* @创建人: xuqm
|
||||||
|
* @创建时间:2022/1/19 上午 10:58
|
||||||
|
* @修改记录:
|
||||||
|
*/
|
||||||
|
public class ColorUser {
|
||||||
|
@ColorInt
|
||||||
|
public static final int ce = 0xFF04E8EE;
|
||||||
|
@ColorInt
|
||||||
|
public static final int cs = 0x003A6FF2;
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<stroke android:width="0.5dp" android:color="#00000014" />
|
||||||
|
<corners android:radius="5dp" />
|
||||||
|
<solid android:color="@color/white"/>
|
||||||
|
</shape>
|
||||||
|
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<corners android:radius="1dp" />
|
||||||
|
<solid android:color="#F1F9F5"/>
|
||||||
|
</shape>
|
||||||
|
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<corners android:radius="2dp" />
|
||||||
|
<solid android:color="#BA7D45" />
|
||||||
|
</shape>
|
||||||
|
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<corners android:bottomRightRadius="1dp" android:topRightRadius="1dp" />
|
||||||
|
<solid android:color="#FFFFFF" />
|
||||||
|
</shape>
|
||||||
|
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<corners android:bottomLeftRadius="1dp" android:topLeftRadius="1dp" />
|
||||||
|
<solid android:color="#BA7D45" />
|
||||||
|
</shape>
|
||||||
|
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<corners android:radius="1dp" />
|
||||||
|
<stroke android:width="1dp" android:color="#5EA564" />
|
||||||
|
</shape>
|
||||||
|
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,698 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#BA7D45"
|
||||||
|
tools:context=".ui.MainActivity">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="联创明医医院智慧药柜"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="15dp"
|
||||||
|
android:layout_marginTop="76dp"
|
||||||
|
android:background="@drawable/bg_main"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:background="@drawable/bg_main"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="广州黄埔区明医医院处方笺"
|
||||||
|
android:textColor="#202020"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tags"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="17.5dp"
|
||||||
|
android:background="@drawable/bg_main_tag"
|
||||||
|
android:paddingHorizontal="7.5dp"
|
||||||
|
android:paddingVertical="4.5dp"
|
||||||
|
android:text="普通"
|
||||||
|
android:textColor="#5EA564" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingHorizontal="15dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="3"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:background="#BA7D45"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/title1"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/title1"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/title1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="患者信息"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="姓名:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="性别:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n3"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="年龄:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v3"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n4"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="电话:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v4"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n5"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="地址:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v5"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="4"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:background="#BA7D45"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/title2"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/title2"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/title2" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="就诊信息"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n6"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="就诊卡号:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v6"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n7"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="就诊科别:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v7"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n8"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="诊断结果:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v8"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n9"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="就诊日期:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v9"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="4"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:background="#BA7D45"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/title3"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/title3"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/title3" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title3"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="医疗信息"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n10"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="医疗类别:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v10"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n11"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="医疗/医保卡:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v11"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="129dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@color/ic_launcher_background" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="15dp"
|
||||||
|
android:layout_marginTop="20dp">
|
||||||
|
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:background="#BA7D45"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/title4"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/title4"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/title4" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title4"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="药品及使用说明"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<com.xuqm.base.view.MaxLimitRecyclerView
|
||||||
|
android:id="@+id/list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:maxLength="6"
|
||||||
|
android:paddingHorizontal="15dp"
|
||||||
|
app:limit_maxHeight="350dp" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="15dp"
|
||||||
|
android:layout_marginTop="20dp">
|
||||||
|
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:background="#BA7D45"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/title5"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/title5"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/title5" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title5"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="药品及使用说明"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingHorizontal="15dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n12"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="药师:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v12"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n13"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="审方:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v13"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n14"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="医师:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v14"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n15"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="调配:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v15"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="智慧药柜"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n16"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="药品金额:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v16"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n17"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="核对发药:"
|
||||||
|
android:textColor="#ff848484"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v17"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="--"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="11sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btn"
|
||||||
|
android:layout_width="170dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="45dp"
|
||||||
|
android:layout_marginBottom="45dp"
|
||||||
|
android:background="@drawable/bg_main_btn"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="确认发药"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
||||||
@ -0,0 +1,167 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout>
|
||||||
|
|
||||||
|
<LinearLayout 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:orientation="vertical"
|
||||||
|
tools:context=".ui.SettingActivity">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="40dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="开指定柜门"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="68dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:background="@drawable/bg_button"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/a11"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="柜号(1.2.3)"
|
||||||
|
android:inputType="number" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/a12"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="窗口号"
|
||||||
|
android:inputType="number" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/a13"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_button_red"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="开门"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="40dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="开指定指定范围内柜门"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="68dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:background="@drawable/bg_button"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/a21"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="柜号(1.2.3)"
|
||||||
|
android:inputType="number" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/a22"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="开始窗口号"
|
||||||
|
android:inputType="number" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/a23"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="结束窗口号"
|
||||||
|
android:inputType="number" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/a24"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_button_red"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="开门"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="40dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="一键开门"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="68dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:background="@drawable/bg_button"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/a31"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_button_red"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="一号柜"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/a32"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:background="@drawable/bg_button_red"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="二号柜"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/a33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_button_red"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="三号柜"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</layout>
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.TestActivity">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/edit_url"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="150dp"
|
||||||
|
android:text="https://web.sdk.qcloud.com/trtc/webrtc/demo/quick-demo-vue3-ts/index.html#/"
|
||||||
|
android:textSize="21sp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:text="进入页面"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/edit_url" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#BA7D45"
|
||||||
|
tools:context=".ui.WelcomeActivity">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="联创明医医院智慧药柜"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/baseRefreshLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginBottom="34dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/title">
|
||||||
|
|
||||||
|
<com.xuqm.base.view.EmptyView
|
||||||
|
android:id="@+id/baseEmptyView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/baseRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:overScrollMode="never" />
|
||||||
|
|
||||||
|
</com.xuqm.base.view.EmptyView>
|
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
||||||
@ -0,0 +1,224 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/index"
|
||||||
|
android:layout_width="25dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/bg_main_item_index"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="1"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/bg_main_item_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingHorizontal="6dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/index">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="25"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/n1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="药品名称"
|
||||||
|
android:textColor="#ffacabab"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/v1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:lines="1"
|
||||||
|
android:text="药品名称药品名称药品名称药品名称药品名称药品名称药品名称"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="18"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/n2"
|
||||||
|
android:text="规格"
|
||||||
|
android:textColor="#ffacabab"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:lines="1"
|
||||||
|
android:text="0.5g*10粒"
|
||||||
|
android:id="@+id/v2"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="9"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:id="@+id/n3"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="数量"
|
||||||
|
android:textColor="#ffacabab"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:lines="1"
|
||||||
|
android:id="@+id/v3"
|
||||||
|
android:text="1盒"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="12"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/n4"
|
||||||
|
android:text="使用方法"
|
||||||
|
android:textColor="#ffacabab"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:lines="1"
|
||||||
|
android:text="口服"
|
||||||
|
android:id="@+id/v4"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="12"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:id="@+id/n5"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="用量"
|
||||||
|
android:textColor="#ffacabab"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:lines="1"
|
||||||
|
android:id="@+id/v5"
|
||||||
|
android:text="6g"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="13"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="频次"
|
||||||
|
android:id="@+id/n6"
|
||||||
|
android:textColor="#ffacabab"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:lines="1"
|
||||||
|
android:id="@+id/v6"
|
||||||
|
android:text="每日1次"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="10"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/n7"
|
||||||
|
android:text="使用周期"
|
||||||
|
android:textColor="#ffacabab"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:lines="1"
|
||||||
|
android:id="@+id/v7"
|
||||||
|
android:text="2天"
|
||||||
|
android:textColor="#ff202020"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="130dp"
|
||||||
|
android:background="@drawable/bg_item_welcome">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/index"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:background="#BA7D45"
|
||||||
|
android:paddingHorizontal="7.5dp"
|
||||||
|
android:paddingVertical="3.5dp"
|
||||||
|
android:text="01"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="13sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:text="活血止痛胶囊(10mg/盒)"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/index"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/index" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/hint"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:text="广东联合制药"
|
||||||
|
android:textColor="#A4ADBA"
|
||||||
|
android:textSize="10sp"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/index"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/number"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:text="12.5"
|
||||||
|
android:textColor="#FF4600"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/index" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/unit"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="元/盒"
|
||||||
|
android:textColor="#FF4600"
|
||||||
|
android:layout_marginBottom="3dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/number"
|
||||||
|
android:textSize="10sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/number" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/balance"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="剩余:100盒"
|
||||||
|
android:textColor="#333333"
|
||||||
|
android:layout_marginBottom="3dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/number"
|
||||||
|
android:textSize="11sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
||||||
|
之后 宽度: | 高度: | 大小: 286 KiB |
|
之后 宽度: | 高度: | 大小: 286 KiB |
|
之后 宽度: | 高度: | 大小: 7.3 KiB |
|
之后 宽度: | 高度: | 大小: 286 KiB |
|
之后 宽度: | 高度: | 大小: 4.4 KiB |
|
之后 宽度: | 高度: | 大小: 79 KiB |
|
之后 宽度: | 高度: | 大小: 286 KiB |
|
之后 宽度: | 高度: | 大小: 1.5 KiB |
|
之后 宽度: | 高度: | 大小: 136 KiB |
|
之后 宽度: | 高度: | 大小: 28 KiB |
|
之后 宽度: | 高度: | 大小: 286 KiB |
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="colorPrimary">#33a6ff</color>
|
||||||
|
<color name="colorPrimaryDark">#00574B</color>
|
||||||
|
<color name="colorAccent">#7e53c5</color>
|
||||||
|
<color name="bg_lapss_line">#BBBBBB</color>
|
||||||
|
<color name="black_filter_10">#10000000</color>
|
||||||
|
<color name="textcolor">#797979</color>
|
||||||
|
<color name="textcolor_blue">#33a6ff</color>
|
||||||
|
|
||||||
|
<color name="backgroundColor">#10142B</color>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Test</string>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<resources>
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
<item name="android:windowTranslucentStatus">true</item>
|
||||||
|
<item name="backgroundColor">#F1F4F7</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DialogTheme" parent="Theme.AppCompat.Light.Dialog">
|
||||||
|
<item name="windowActionBar">false</item>
|
||||||
|
<item name="windowNoTitle">true</item>
|
||||||
|
<item name="android:windowLightStatusBar">false</item>
|
||||||
|
<item name="android:windowCloseOnTouchOutside">false</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths>
|
||||||
|
<external-path
|
||||||
|
name="external"
|
||||||
|
path="." />
|
||||||
|
</paths>
|
||||||
2
base/.gitattributes
vendored
普通文件
@ -0,0 +1,2 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
||||||
83
base/.gitignore
vendored
普通文件
@ -0,0 +1,83 @@
|
|||||||
|
# Built application files
|
||||||
|
*.apk
|
||||||
|
*.ap_
|
||||||
|
*.aab
|
||||||
|
|
||||||
|
# Files for the ART/Dalvik VM
|
||||||
|
*.dex
|
||||||
|
|
||||||
|
# Java class files
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
out/
|
||||||
|
# Uncomment the following line in case you need and you don't have the release build type files in your app
|
||||||
|
# release/
|
||||||
|
|
||||||
|
# Gradle files
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Proguard folder generated by Eclipse
|
||||||
|
proguard/
|
||||||
|
|
||||||
|
# Log Files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Android Studio Navigation editor temp files
|
||||||
|
.navigation/
|
||||||
|
|
||||||
|
# Android Studio captures folder
|
||||||
|
captures/
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
*.iml
|
||||||
|
.idea/workspace.xml
|
||||||
|
.idea/tasks.xml
|
||||||
|
.idea/gradle.xml
|
||||||
|
.idea/assetWizardSettings.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
.idea/libraries
|
||||||
|
# Android Studio 3 in .gitignore file.
|
||||||
|
.idea/caches
|
||||||
|
.idea/modules.xml
|
||||||
|
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||||
|
.idea/navEditor.xml
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
|
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||||
|
#*.jks
|
||||||
|
#*.keystore
|
||||||
|
|
||||||
|
# External native build folder generated in Android Studio 2.2 and later
|
||||||
|
.externalNativeBuild
|
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase)
|
||||||
|
# google-services.json
|
||||||
|
|
||||||
|
# Freeline
|
||||||
|
freeline.py
|
||||||
|
freeline/
|
||||||
|
freeline_project_description.json
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots
|
||||||
|
fastlane/test_output
|
||||||
|
fastlane/readme.md
|
||||||
|
|
||||||
|
# Version control
|
||||||
|
vcs.xml
|
||||||
|
|
||||||
|
# lint
|
||||||
|
lint/intermediates/
|
||||||
|
lint/generated/
|
||||||
|
lint/outputs/
|
||||||
|
lint/tmp/
|
||||||
|
# lint/reports/
|
||||||
184
base/README.md
普通文件
@ -0,0 +1,184 @@
|
|||||||
|
[TOC]
|
||||||
|
|
||||||
|
|
||||||
|
# WebSocket
|
||||||
|
|
||||||
|
``````kotlin
|
||||||
|
WebSocketHandler.getInstance("ws://192.168.3.20:8765")
|
||||||
|
``````
|
||||||
|
|
||||||
|
# 线程
|
||||||
|
|
||||||
|
## UI线程执行
|
||||||
|
|
||||||
|
````kotlin
|
||||||
|
runOnUiThread { "提示信息".showMessage() }
|
||||||
|
````
|
||||||
|
|
||||||
|
````kotlin
|
||||||
|
App.getInstance().runOnUiThread() {}
|
||||||
|
````
|
||||||
|
|
||||||
|
## 延时执行
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
App.getInstance().runOnUiThreadDelay({},1100)
|
||||||
|
```
|
||||||
|
|
||||||
|
# 常用工具
|
||||||
|
|
||||||
|
## Toast
|
||||||
|
|
||||||
|
````kotlin
|
||||||
|
"连接完成".showMessage()
|
||||||
|
````
|
||||||
|
|
||||||
|
````kotlin
|
||||||
|
ToolsHelper.showMessage("")
|
||||||
|
````
|
||||||
|
|
||||||
|
## Log
|
||||||
|
|
||||||
|
````kotlin
|
||||||
|
"".loge()
|
||||||
|
````
|
||||||
|
|
||||||
|
````kotlin
|
||||||
|
"".log()
|
||||||
|
````
|
||||||
|
|
||||||
|
````kotlin
|
||||||
|
LogHelper.d("")
|
||||||
|
````
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 常用方法
|
||||||
|
|
||||||
|
## 双击退出
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
|
||||||
|
private var oldTime = 0L
|
||||||
|
override fun onBackPressed() {
|
||||||
|
val newTime = System.currentTimeMillis()
|
||||||
|
if (newTime - oldTime < 1500 && oldTime != 0L)
|
||||||
|
AppManager.getInstance().exit()
|
||||||
|
else {
|
||||||
|
oldTime = newTime
|
||||||
|
ToolsHelper.showMessage("双击退出")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 界面
|
||||||
|
|
||||||
|
> 所有界面继承`BaseFragment`,`BaseActivity`,`BaseListActivity`等
|
||||||
|
>
|
||||||
|
> 页面`layout`跟节点必须为`layout`
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
</layout>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 列表页面
|
||||||
|
|
||||||
|
### 纯列表
|
||||||
|
|
||||||
|
> `BaseListActivity`
|
||||||
|
|
||||||
|
### 自定义布局列表
|
||||||
|
|
||||||
|
> `BaseListFormLayoutActivity`
|
||||||
|
>
|
||||||
|
> 布局列表部分必须使用下面的方法和id
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/baseRefreshLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.xuqm.base.view.EmptyView
|
||||||
|
android:id="@+id/baseEmptyView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/baseRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:overScrollMode="never" />
|
||||||
|
|
||||||
|
</com.xuqm.base.view.EmptyView>
|
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 界面控件使用
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
binding.btn1.setOnClickListener {
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 导航栏
|
||||||
|
|
||||||
|
> 使用base自带导航栏的情况下,可以操控对应控件
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
baseBinding.baseToolbar.backBtn.setOnClickListener {}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
94
base/build.gradle
普通文件
@ -0,0 +1,94 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
|
// 声明aar包的版本号
|
||||||
|
def aarVersion = "0.0.1.101"
|
||||||
|
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion versions.compileSdk
|
||||||
|
buildToolsVersion versions.buildTools
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion versions.minSdk
|
||||||
|
targetSdkVersion versions.targetSdk
|
||||||
|
flavorDimensions "versioncode"
|
||||||
|
buildConfigField("String", "APP_ID", "\"" + apps.applicationId + "\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
productFlavors productF
|
||||||
|
namespace 'com.xuqm.base'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
|
||||||
|
api androidxDependencies
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
|
|
||||||
|
|
||||||
|
implementation 'org.jetbrains.anko:anko-commons:0.10.5'
|
||||||
|
|
||||||
|
annotationProcessor compilerDependencies
|
||||||
|
commonDependencies.each { k, v ->
|
||||||
|
api(v) {
|
||||||
|
//去除第三方的重复support库
|
||||||
|
exclude group: 'com.android.support'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//扫码二维码
|
||||||
|
api 'com.huawei.hms:scanplus:1.1.1.301'
|
||||||
|
}
|
||||||
|
// 这个是把源码打入aar包中的任务
|
||||||
|
task sourceJar(type: Jar) {
|
||||||
|
archiveClassifier.set('sources')
|
||||||
|
from android.sourceSets.main.java.srcDirs
|
||||||
|
}
|
||||||
|
afterEvaluate {
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
// 这里的debug名字是自己起的
|
||||||
|
release(MavenPublication) {
|
||||||
|
groupId = 'cn.org.bjca.trust.android'
|
||||||
|
artifactId = 'base'
|
||||||
|
version = aarVersion
|
||||||
|
// 这里除了有debug 还有release
|
||||||
|
from components.release
|
||||||
|
// 运行任务,把源码打进去
|
||||||
|
artifact sourceJar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 添加仓库地址
|
||||||
|
repositories {
|
||||||
|
// 本地仓库
|
||||||
|
// mavenLocal()
|
||||||
|
// 当上传到远端仓库
|
||||||
|
// maven {
|
||||||
|
// allowInsecureProtocol true
|
||||||
|
// url("http://nexus.51trust.net/repository/android-hosted/")
|
||||||
|
// credentials {
|
||||||
|
// username = "deployment"
|
||||||
|
// password = "deployment123"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
maven {
|
||||||
|
allowInsecureProtocol true
|
||||||
|
url("http://xuqinmin.com.cn:8081/repository/android-releases/")
|
||||||
|
credentials {
|
||||||
|
username = "admin"
|
||||||
|
password = "xuqinmin1022"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
base/consumer-rules.pro
普通文件
21
base/proguard-rules.pro
vendored
普通文件
@ -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
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- 7.0之后安装apk、需要权限 -->
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
|
|
||||||
|
<permission android:name="android.permission.INSTALL_PACKAGES" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.webkit.PermissionRequest" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.webkit.resource.VIDEO_CAPTURE" />
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<activity android:name=".web.XWebViewActivity" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
@ -0,0 +1,155 @@
|
|||||||
|
package com.livinglifetechway.quickpermissions_kotlin
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.livinglifetechway.quickpermissions_kotlin.util.PermissionCheckerFragment
|
||||||
|
import com.livinglifetechway.quickpermissions_kotlin.util.PermissionsUtil
|
||||||
|
import com.livinglifetechway.quickpermissions_kotlin.util.QuickPermissionsRequest
|
||||||
|
import com.livinglifetechway.quickpermissions_kotlin.util.QuickPermissionsOptions
|
||||||
|
|
||||||
|
private const val TAG = "runWithPermissions"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects code to ask for permissions before executing any code that requires permissions
|
||||||
|
* defined in the annotation
|
||||||
|
*/
|
||||||
|
fun Context?.runWithPermissions(
|
||||||
|
vararg permissions: String,
|
||||||
|
options: QuickPermissionsOptions = QuickPermissionsOptions(),
|
||||||
|
callback: () -> Unit
|
||||||
|
): Any? {
|
||||||
|
return runWithPermissionsHandler(this, permissions, callback, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects code to ask for permissions before executing any code that requires permissions
|
||||||
|
* defined in the annotation
|
||||||
|
*/
|
||||||
|
fun Fragment?.runWithPermissions(
|
||||||
|
vararg permissions: String,
|
||||||
|
options: QuickPermissionsOptions = QuickPermissionsOptions(),
|
||||||
|
callback: () -> Unit
|
||||||
|
): Any? {
|
||||||
|
return runWithPermissionsHandler(this, permissions, callback, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runWithPermissionsHandler(target: Any?, permissions: Array<out String>, callback: () -> Unit, options: QuickPermissionsOptions): Nothing? {
|
||||||
|
Log.d(TAG, "runWithPermissions: start")
|
||||||
|
|
||||||
|
// get the permissions defined in annotation
|
||||||
|
Log.d(TAG, "runWithPermissions: permissions to check: $permissions")
|
||||||
|
|
||||||
|
// get target
|
||||||
|
if (target is AppCompatActivity || target is Fragment) {
|
||||||
|
Log.d(TAG, "runWithPermissions: context found")
|
||||||
|
|
||||||
|
val context = when (target) {
|
||||||
|
is Context -> target
|
||||||
|
is Fragment -> target.context
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we have the permissions
|
||||||
|
if (PermissionsUtil.hasSelfPermission(context, arrayOf(*permissions))) {
|
||||||
|
Log.d(TAG, "runWithPermissions: already has required permissions. Proceed with the execution.")
|
||||||
|
callback()
|
||||||
|
} else {
|
||||||
|
// we don't have required permissions
|
||||||
|
// begin the permission request flow
|
||||||
|
|
||||||
|
Log.d(TAG, "runWithPermissions: doesn't have required permissions")
|
||||||
|
|
||||||
|
// check if we have permission checker fragment already attached
|
||||||
|
|
||||||
|
// support for AppCompatActivity and Activity
|
||||||
|
var permissionCheckerFragment = when (context) {
|
||||||
|
// for app compat activity
|
||||||
|
is AppCompatActivity -> context.supportFragmentManager?.findFragmentByTag(PermissionCheckerFragment::class.java.canonicalName) as PermissionCheckerFragment?
|
||||||
|
// for support fragment
|
||||||
|
is Fragment -> context.childFragmentManager.findFragmentByTag(PermissionCheckerFragment::class.java.canonicalName) as PermissionCheckerFragment?
|
||||||
|
// else return null
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if permission check fragment is added or not
|
||||||
|
// if not, add that fragment
|
||||||
|
if (permissionCheckerFragment == null) {
|
||||||
|
Log.d(TAG, "runWithPermissions: adding headless fragment for asking permissions")
|
||||||
|
permissionCheckerFragment = PermissionCheckerFragment.newInstance()
|
||||||
|
when (context) {
|
||||||
|
is AppCompatActivity -> {
|
||||||
|
context.supportFragmentManager.beginTransaction().apply {
|
||||||
|
add(permissionCheckerFragment, PermissionCheckerFragment::class.java.canonicalName)
|
||||||
|
commit()
|
||||||
|
}
|
||||||
|
// make sure fragment is added before we do any context based operations
|
||||||
|
context.supportFragmentManager?.executePendingTransactions()
|
||||||
|
}
|
||||||
|
is Fragment -> {
|
||||||
|
// this does not work at the moment
|
||||||
|
context.childFragmentManager.beginTransaction().apply {
|
||||||
|
add(permissionCheckerFragment, PermissionCheckerFragment::class.java.canonicalName)
|
||||||
|
commit()
|
||||||
|
}
|
||||||
|
// make sure fragment is added before we do any context based operations
|
||||||
|
context.childFragmentManager.executePendingTransactions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set callback to permission checker fragment
|
||||||
|
permissionCheckerFragment.setListener(object : PermissionCheckerFragment.QuickPermissionsCallback {
|
||||||
|
override fun onPermissionsGranted(quickPermissionsRequest: QuickPermissionsRequest?) {
|
||||||
|
Log.d(TAG, "runWithPermissions: got permissions")
|
||||||
|
try {
|
||||||
|
callback()
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
throwable.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPermissionsDenied(quickPermissionsRequest: QuickPermissionsRequest?) {
|
||||||
|
quickPermissionsRequest?.permissionsDeniedMethod?.invoke(quickPermissionsRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldShowRequestPermissionsRationale(quickPermissionsRequest: QuickPermissionsRequest?) {
|
||||||
|
quickPermissionsRequest?.rationaleMethod?.invoke(quickPermissionsRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPermissionsPermanentlyDenied(quickPermissionsRequest: QuickPermissionsRequest?) {
|
||||||
|
quickPermissionsRequest?.permanentDeniedMethod?.invoke(quickPermissionsRequest)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// create permission request instance
|
||||||
|
val permissionRequest = QuickPermissionsRequest(permissionCheckerFragment, arrayOf(*permissions))
|
||||||
|
permissionRequest.handleRationale = options.handleRationale
|
||||||
|
permissionRequest.handlePermanentlyDenied = options.handlePermanentlyDenied
|
||||||
|
permissionRequest.rationaleMessage = if (options.rationaleMessage.isBlank())
|
||||||
|
"These permissions are required to perform this feature. Please allow us to use this feature. "
|
||||||
|
else
|
||||||
|
options.rationaleMessage
|
||||||
|
permissionRequest.permanentlyDeniedMessage = if (options.permanentlyDeniedMessage.isBlank())
|
||||||
|
"Some permissions are permanently denied which are required to perform this operation. Please open app settings to grant these permissions."
|
||||||
|
else
|
||||||
|
options.permanentlyDeniedMessage
|
||||||
|
permissionRequest.rationaleMethod = options.rationaleMethod
|
||||||
|
permissionRequest.permanentDeniedMethod = options.permanentDeniedMethod
|
||||||
|
permissionRequest.permissionsDeniedMethod = options.permissionsDeniedMethod
|
||||||
|
|
||||||
|
// begin the flow by requesting permissions
|
||||||
|
permissionCheckerFragment.setRequestPermissionsRequest(permissionRequest)
|
||||||
|
|
||||||
|
// start requesting permissions for the first time
|
||||||
|
permissionCheckerFragment.requestPermissionsFromUser()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// context is null
|
||||||
|
// cannot handle the permission checking from the any class other than AppCompatActivity/Fragment
|
||||||
|
// crash the app RIGHT NOW!
|
||||||
|
throw IllegalStateException("Found " + target!!::class.java.canonicalName + " : No support from any classes other than AppCompatActivity/Fragment")
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
@ -0,0 +1,237 @@
|
|||||||
|
package com.livinglifetechway.quickpermissions_kotlin.util
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.net.Uri.fromParts
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import org.jetbrains.anko.alert
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This fragment holds the single permission request and holds it until the flow is completed
|
||||||
|
*/
|
||||||
|
class PermissionCheckerFragment : Fragment() {
|
||||||
|
|
||||||
|
private var quickPermissionsRequest: QuickPermissionsRequest? = null
|
||||||
|
|
||||||
|
interface QuickPermissionsCallback {
|
||||||
|
fun shouldShowRequestPermissionsRationale(quickPermissionsRequest: QuickPermissionsRequest?)
|
||||||
|
fun onPermissionsGranted(quickPermissionsRequest: QuickPermissionsRequest?)
|
||||||
|
fun onPermissionsPermanentlyDenied(quickPermissionsRequest: QuickPermissionsRequest?)
|
||||||
|
fun onPermissionsDenied(quickPermissionsRequest: QuickPermissionsRequest?)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "QuickPermissionsKotlin"
|
||||||
|
private const val PERMISSIONS_REQUEST_CODE = 199
|
||||||
|
fun newInstance(): PermissionCheckerFragment = PermissionCheckerFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mListener: QuickPermissionsCallback? = null
|
||||||
|
|
||||||
|
fun setListener(listener: QuickPermissionsCallback) {
|
||||||
|
mListener = listener
|
||||||
|
Log.d(TAG, "onCreate: listeners set")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeListener() {
|
||||||
|
mListener = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
Log.d(TAG, "onCreate: permission fragment created")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setRequestPermissionsRequest(quickPermissionsRequest: QuickPermissionsRequest?) {
|
||||||
|
this.quickPermissionsRequest = quickPermissionsRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeRequestPermissionsRequest() {
|
||||||
|
quickPermissionsRequest = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clean() {
|
||||||
|
if (quickPermissionsRequest != null) {
|
||||||
|
// permission request flow is finishing
|
||||||
|
// let the caller receive callback about it
|
||||||
|
if (quickPermissionsRequest?.deniedPermissions?.size ?: 0 > 0)
|
||||||
|
mListener?.onPermissionsDenied(quickPermissionsRequest)
|
||||||
|
|
||||||
|
removeRequestPermissionsRequest()
|
||||||
|
removeListener()
|
||||||
|
} else {
|
||||||
|
Log.w(
|
||||||
|
TAG, "clean: QuickPermissionsRequest has already completed its flow. " +
|
||||||
|
"No further callbacks will be called for the current flow."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestPermissionsFromUser() {
|
||||||
|
if (quickPermissionsRequest != null) {
|
||||||
|
Log.d(TAG, "requestPermissionsFromUser: requesting permissions")
|
||||||
|
requestPermissions(
|
||||||
|
quickPermissionsRequest?.permissions.orEmpty(),
|
||||||
|
PERMISSIONS_REQUEST_CODE
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Log.w(
|
||||||
|
TAG,
|
||||||
|
"requestPermissionsFromUser: QuickPermissionsRequest has already completed its flow. " +
|
||||||
|
"Cannot request permissions again from the request received from the callback. " +
|
||||||
|
"You can start the new flow by calling runWithPermissions() { } again."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(
|
||||||
|
requestCode: Int,
|
||||||
|
permissions: Array<String>,
|
||||||
|
grantResults: IntArray
|
||||||
|
) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
|
Log.d(TAG, "passing callback")
|
||||||
|
|
||||||
|
// check if permissions granted
|
||||||
|
handlePermissionResult(permissions, grantResults)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks and takes the action based on permission results retrieved from onRequestPermissionsResult
|
||||||
|
* and from the settings activity
|
||||||
|
*
|
||||||
|
* @param permissions List of Permissions
|
||||||
|
* @param grantResults A list of permission result <b>Granted</b> or <b>Denied</b>
|
||||||
|
*/
|
||||||
|
private fun handlePermissionResult(permissions: Array<String>, grantResults: IntArray) {
|
||||||
|
// add a check with the permissions list
|
||||||
|
// if the permissions list is empty, that means system has told that permissions request
|
||||||
|
// is invalid somehow or discarded the previous request
|
||||||
|
// this can happen in case when the multiple permissions requests are sent
|
||||||
|
// simultaneously to the system
|
||||||
|
if (permissions.isEmpty()) {
|
||||||
|
Log.w(
|
||||||
|
TAG,
|
||||||
|
"handlePermissionResult: Permissions result discarded. You might have called multiple permissions request simultaneously"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PermissionsUtil.hasSelfPermission(context, permissions)) {
|
||||||
|
|
||||||
|
// set the denied permissions to empty as all the permissions are granted
|
||||||
|
// this is required as clean will be called which can invoke on permissions denied
|
||||||
|
// if it finds some permissions in the denied list
|
||||||
|
quickPermissionsRequest?.deniedPermissions = emptyArray()
|
||||||
|
|
||||||
|
// we are good to go!
|
||||||
|
mListener?.onPermissionsGranted(quickPermissionsRequest)
|
||||||
|
|
||||||
|
// flow complete
|
||||||
|
clean()
|
||||||
|
} else {
|
||||||
|
// we are still missing permissions
|
||||||
|
val deniedPermissions = PermissionsUtil.getDeniedPermissions(permissions, grantResults)
|
||||||
|
quickPermissionsRequest?.deniedPermissions = deniedPermissions
|
||||||
|
|
||||||
|
// check if rationale dialog should be shown or not
|
||||||
|
var shouldShowRationale = true
|
||||||
|
var isPermanentlyDenied = false
|
||||||
|
for (i in 0 until deniedPermissions.size) {
|
||||||
|
val deniedPermission = deniedPermissions[i]
|
||||||
|
val rationale = shouldShowRequestPermissionRationale(deniedPermission)
|
||||||
|
if (!rationale) {
|
||||||
|
shouldShowRationale = false
|
||||||
|
isPermanentlyDenied = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quickPermissionsRequest?.handlePermanentlyDenied == true && isPermanentlyDenied) {
|
||||||
|
|
||||||
|
quickPermissionsRequest?.permanentDeniedMethod?.let {
|
||||||
|
// get list of permanently denied methods
|
||||||
|
quickPermissionsRequest?.permanentlyDeniedPermissions =
|
||||||
|
PermissionsUtil.getPermanentlyDeniedPermissions(
|
||||||
|
this,
|
||||||
|
permissions,
|
||||||
|
grantResults
|
||||||
|
)
|
||||||
|
mListener?.onPermissionsPermanentlyDenied(quickPermissionsRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
activity?.alert {
|
||||||
|
message = quickPermissionsRequest?.permanentlyDeniedMessage.orEmpty()
|
||||||
|
positiveButton("SETTINGS") {
|
||||||
|
openAppSettings()
|
||||||
|
}
|
||||||
|
negativeButton("CANCEL") {
|
||||||
|
clean()
|
||||||
|
}
|
||||||
|
}?.apply { isCancelable = false }?.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// if should show rationale dialog
|
||||||
|
if (quickPermissionsRequest?.handleRationale == true && shouldShowRationale) {
|
||||||
|
|
||||||
|
quickPermissionsRequest?.rationaleMethod?.let {
|
||||||
|
mListener?.shouldShowRequestPermissionsRationale(quickPermissionsRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
activity?.alert {
|
||||||
|
message = quickPermissionsRequest?.rationaleMessage.orEmpty()
|
||||||
|
positiveButton("TRY AGAIN") {
|
||||||
|
requestPermissionsFromUser()
|
||||||
|
}
|
||||||
|
negativeButton("CANCEL") {
|
||||||
|
clean()
|
||||||
|
}
|
||||||
|
}?.apply { isCancelable = false }?.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// if handlePermanentlyDenied = false and handleRationale = false
|
||||||
|
// This will call permissionsDenied method
|
||||||
|
clean()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openAppSettings() {
|
||||||
|
if (quickPermissionsRequest != null) {
|
||||||
|
val intent = Intent(
|
||||||
|
ACTION_APPLICATION_DETAILS_SETTINGS,
|
||||||
|
fromParts("package", activity?.packageName, null)
|
||||||
|
)
|
||||||
|
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
startActivityForResult(intent, PERMISSIONS_REQUEST_CODE)
|
||||||
|
} else {
|
||||||
|
Log.w(
|
||||||
|
TAG,
|
||||||
|
"openAppSettings: QuickPermissionsRequest has already completed its flow. Cannot open app settings"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
if (requestCode == PERMISSIONS_REQUEST_CODE) {
|
||||||
|
val permissions = quickPermissionsRequest?.permissions ?: emptyArray()
|
||||||
|
val grantResults = IntArray(permissions.size)
|
||||||
|
permissions.forEachIndexed { index, s ->
|
||||||
|
grantResults[index] = context?.let { ActivityCompat.checkSelfPermission(it, s) }
|
||||||
|
?: PackageManager.PERMISSION_DENIED
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePermissionResult(permissions, grantResults)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
package com.livinglifetechway.quickpermissions_kotlin.util
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class that wraps access to the runtime permissions API in M and provides basic helper
|
||||||
|
* methods.
|
||||||
|
*/
|
||||||
|
object PermissionsUtil {
|
||||||
|
|
||||||
|
fun getDeniedPermissions(permissions: Array<String>, grantResults: IntArray): Array<String> =
|
||||||
|
permissions.filterIndexed { index, s ->
|
||||||
|
grantResults[index] == PackageManager.PERMISSION_DENIED
|
||||||
|
}.toTypedArray()
|
||||||
|
|
||||||
|
fun getPermanentlyDeniedPermissions(
|
||||||
|
fragment: Fragment,
|
||||||
|
permissions: Array<String>,
|
||||||
|
grantResults: IntArray
|
||||||
|
): Array<String> =
|
||||||
|
permissions.filterIndexed { index, s ->
|
||||||
|
grantResults[index] == PackageManager.PERMISSION_DENIED && !fragment.shouldShowRequestPermissionRationale(
|
||||||
|
s
|
||||||
|
)
|
||||||
|
}.toTypedArray()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the Activity has access to all given permissions.
|
||||||
|
* Always returns true on platforms below M.
|
||||||
|
*
|
||||||
|
* @see Activity.checkSelfPermission
|
||||||
|
*/
|
||||||
|
fun hasSelfPermission(activity: Context?, permissions: Array<String>): Boolean {
|
||||||
|
// Verify that all required permissions have been granted
|
||||||
|
activity?.let {
|
||||||
|
for (permission in permissions) {
|
||||||
|
if (ActivityCompat.checkSelfPermission(
|
||||||
|
activity,
|
||||||
|
permission
|
||||||
|
) != PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package com.livinglifetechway.quickpermissions_kotlin.util
|
||||||
|
|
||||||
|
data class QuickPermissionsOptions(
|
||||||
|
var handleRationale: Boolean = true,
|
||||||
|
var rationaleMessage: String = "",
|
||||||
|
var handlePermanentlyDenied: Boolean = true,
|
||||||
|
var permanentlyDeniedMessage: String = "",
|
||||||
|
var rationaleMethod: ((QuickPermissionsRequest) -> Unit)? = null,
|
||||||
|
var permanentDeniedMethod: ((QuickPermissionsRequest) -> Unit)? = null,
|
||||||
|
var permissionsDeniedMethod: ((QuickPermissionsRequest) -> Unit)? = null
|
||||||
|
)
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.livinglifetechway.quickpermissions_kotlin.util
|
||||||
|
|
||||||
|
data class QuickPermissionsRequest(
|
||||||
|
private var target: PermissionCheckerFragment,
|
||||||
|
var permissions: Array<String> = emptyArray(),
|
||||||
|
var handleRationale: Boolean = true,
|
||||||
|
var rationaleMessage: String = "",
|
||||||
|
var handlePermanentlyDenied: Boolean = true,
|
||||||
|
var permanentlyDeniedMessage: String = "",
|
||||||
|
internal var rationaleMethod: ((QuickPermissionsRequest) -> Unit)? = null,
|
||||||
|
internal var permanentDeniedMethod: ((QuickPermissionsRequest) -> Unit)? = null,
|
||||||
|
internal var permissionsDeniedMethod: ((QuickPermissionsRequest) -> Unit)? = null,
|
||||||
|
var deniedPermissions: Array<String> = emptyArray(),
|
||||||
|
var permanentlyDeniedPermissions: Array<String> = emptyArray()
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Proceed with requesting permissions again with user request
|
||||||
|
*/
|
||||||
|
fun proceed() = target.requestPermissionsFromUser()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels the current permissions request flow
|
||||||
|
*/
|
||||||
|
fun cancel() = target.clean()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In case of permissions permanently denied, request user to enable from app settings
|
||||||
|
*/
|
||||||
|
fun openAppSettings() = target.openAppSettings()
|
||||||
|
}
|
||||||
@ -0,0 +1,111 @@
|
|||||||
|
package com.xuqm.base;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.orhanobut.logger.AndroidLogAdapter;
|
||||||
|
import com.orhanobut.logger.FormatStrategy;
|
||||||
|
import com.orhanobut.logger.Logger;
|
||||||
|
import com.orhanobut.logger.PrettyFormatStrategy;
|
||||||
|
import com.xuqm.base.di.component.AppComponent;
|
||||||
|
import com.xuqm.base.di.manager.HttpManager;
|
||||||
|
|
||||||
|
public class App extends Application {
|
||||||
|
|
||||||
|
public AppComponent appComponent;
|
||||||
|
// 宽高
|
||||||
|
private int width = 0, height = 0;
|
||||||
|
|
||||||
|
|
||||||
|
private static App instance;
|
||||||
|
|
||||||
|
public static App getInstance() {
|
||||||
|
if (null == instance) {
|
||||||
|
synchronized (App.class) {
|
||||||
|
if (null == instance)
|
||||||
|
instance = new App();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public App() {
|
||||||
|
instance = this;
|
||||||
|
handler = new Handler();
|
||||||
|
appComponent = HttpManager.getAppComponent("");
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://www.wanandroid.com/wxarticle/list/408/1/json
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
DisplayMetrics dm = new DisplayMetrics();
|
||||||
|
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
if (null != wm) {
|
||||||
|
wm.getDefaultDisplay().getMetrics(dm);
|
||||||
|
width = dm.widthPixels;// 屏幕宽度
|
||||||
|
height = dm.heightPixels;// 屏幕高度
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder()
|
||||||
|
.showThreadInfo(false) // (Optional) Whether to show thread info or not. Default true
|
||||||
|
.methodCount(0) // (Optional) How many method line to show. Default 2
|
||||||
|
.methodOffset(2) // (Optional) Hides internal method calls up to offset. Default 5
|
||||||
|
//.logStrategy(customLog) // (Optional) Changes the log strategy to print out. Default LogCat
|
||||||
|
.tag("LogHttpInfo") // (Optional) Global tag for every log. Default PRETTY_LOGGER
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy) {
|
||||||
|
@Override
|
||||||
|
public boolean isLoggable(int priority, @Nullable String tag) {
|
||||||
|
return showLog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否打印日志
|
||||||
|
*
|
||||||
|
* @return true-开启日志
|
||||||
|
*/
|
||||||
|
public boolean showLog() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Handler handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交主线程处理
|
||||||
|
*
|
||||||
|
* @param runnable runnable
|
||||||
|
*/
|
||||||
|
public void runOnUiThread(final Runnable runnable) {
|
||||||
|
handler.post(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交主线程,延时后处理
|
||||||
|
*
|
||||||
|
* @param runnable runnable
|
||||||
|
* @param delayMillis 延时时间
|
||||||
|
*/
|
||||||
|
public void runOnUiThreadDelay(final Runnable runnable, long delayMillis) {
|
||||||
|
handler.postDelayed(runnable, delayMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,222 @@
|
|||||||
|
package com.xuqm.base;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.xuqm.base.common.FileHelper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.lang.Thread.UncaughtExceptionHandler;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告.
|
||||||
|
*
|
||||||
|
* @author user
|
||||||
|
*/
|
||||||
|
public class CrashHandler implements UncaughtExceptionHandler {
|
||||||
|
|
||||||
|
public static final String TAG = "CrashHandler";
|
||||||
|
|
||||||
|
// CrashHandler 实例
|
||||||
|
private static CrashHandler INSTANCE = new CrashHandler();
|
||||||
|
|
||||||
|
// 程序的 Context 对象
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
// 系统默认的 UncaughtException 处理类
|
||||||
|
private UncaughtExceptionHandler mDefaultHandler;
|
||||||
|
|
||||||
|
// 用来存储设备信息和异常信息
|
||||||
|
private Map<String, String> infos = new HashMap<String, String>();
|
||||||
|
|
||||||
|
// 用于格式化日期,作为日志文件名的一部分
|
||||||
|
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保证只有一个 CrashHandler 实例
|
||||||
|
*/
|
||||||
|
private CrashHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 CrashHandler 实例 ,单例模式
|
||||||
|
*/
|
||||||
|
public static CrashHandler getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
public void init(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
// 获取系统默认的 UncaughtException 处理器
|
||||||
|
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
// 设置该 CrashHandler 为程序的默认处理器
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当 UncaughtException 发生时会转入该函数来处理
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(Thread thread, Throwable ex) {
|
||||||
|
if (!handleException(ex) && mDefaultHandler != null) {
|
||||||
|
// 如果用户没有处理则让系统默认的异常处理器来处理
|
||||||
|
mDefaultHandler.uncaughtException(thread, ex);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Thread.sleep(2000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(TAG, "error : ", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intent mIntent = new Intent(mContext, WelcomeActivity.class);
|
||||||
|
// mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
// mContext.startActivity(mIntent);
|
||||||
|
android.os.Process.killProcess(android.os.Process.myPid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义错误处理,收集错误信息,发送错误报告等操作均在此完成
|
||||||
|
*
|
||||||
|
* @param ex
|
||||||
|
* @return true:如果处理了该异常信息;否则返回 false
|
||||||
|
*/
|
||||||
|
private boolean handleException(Throwable ex) {
|
||||||
|
if (ex == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 Toast 来显示异常信息
|
||||||
|
new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Looper.prepare();
|
||||||
|
Toast.makeText(mContext, "好像出了点问题~~~", Toast.LENGTH_LONG).show();
|
||||||
|
Looper.loop();
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
|
||||||
|
// 收集设备参数信息
|
||||||
|
collectDeviceInfo(mContext);
|
||||||
|
// 保存日志文件
|
||||||
|
saveCrashInfo2File(ex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收集设备参数信息
|
||||||
|
*
|
||||||
|
* @param ctx
|
||||||
|
*/
|
||||||
|
public void collectDeviceInfo(Context ctx) {
|
||||||
|
try {
|
||||||
|
PackageManager pm = ctx.getPackageManager();
|
||||||
|
PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
|
||||||
|
|
||||||
|
if (pi != null) {
|
||||||
|
String versionName = pi.versionName == null ? "null" : pi.versionName;
|
||||||
|
String versionCode = pi.versionCode + "";
|
||||||
|
infos.put("versionName", versionName);
|
||||||
|
infos.put("versionCode", versionCode);
|
||||||
|
}
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
Log.e(TAG, "an error occured when collect package info", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Field[] fields = Build.class.getDeclaredFields();
|
||||||
|
for (Field field : fields) {
|
||||||
|
try {
|
||||||
|
field.setAccessible(true);
|
||||||
|
infos.put(field.getName(), field.get(null).toString());
|
||||||
|
Log.d(TAG, field.getName() + " : " + field.get(null));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "an error occured when collect crash info", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存错误信息到文件中 *
|
||||||
|
*
|
||||||
|
* @param ex
|
||||||
|
* @return 返回文件名称, 便于将文件传送到服务器
|
||||||
|
*/
|
||||||
|
private String saveCrashInfo2File(Throwable ex) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
for (Map.Entry<String, String> entry : infos.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
String value = entry.getValue();
|
||||||
|
sb.append(String.format("%s=%s\n", key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
Writer writer = new StringWriter();
|
||||||
|
PrintWriter printWriter = new PrintWriter(writer);
|
||||||
|
ex.printStackTrace(printWriter);
|
||||||
|
Throwable cause = ex.getCause();
|
||||||
|
while (cause != null) {
|
||||||
|
cause.printStackTrace(printWriter);
|
||||||
|
cause = cause.getCause();
|
||||||
|
}
|
||||||
|
printWriter.close();
|
||||||
|
|
||||||
|
String result = writer.toString();
|
||||||
|
sb.append(result);
|
||||||
|
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
String time = formatter.format(new Date());
|
||||||
|
String fileName = "crash-" + time + "-" + timestamp + ".log";
|
||||||
|
|
||||||
|
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||||
|
String path = String.format("%scrash/", FileHelper.getRootFilePath());
|
||||||
|
File dir = new File(path);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
dir.mkdirs();
|
||||||
|
}
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
try {
|
||||||
|
fos = new FileOutputStream(path + fileName);
|
||||||
|
fos.write(sb.toString().getBytes());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "an error occured while writing file...", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (fos != null) {
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileName;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有用到{@link com.xuqm.base.ui.BaseListActivity}来做的列表页
|
||||||
|
* 数据model都要继承BaseItem
|
||||||
|
*/
|
||||||
|
public class BaseItem {
|
||||||
|
private int s_id;
|
||||||
|
|
||||||
|
public int getS_id() {
|
||||||
|
return s_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setS_id(int s_id) {
|
||||||
|
this.s_id = s_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,186 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.xuqm.base.adapter.callback.AdapterItemClickListener;
|
||||||
|
import com.xuqm.base.adapter.callback.AdapterItemLongClickListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不用{@link BasePagedAdapter}的时候,可以用这个
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @param <T> 数据各式
|
||||||
|
*/
|
||||||
|
public abstract class BaseNormalAdapter<T> extends RecyclerView.Adapter<ViewHolder> {
|
||||||
|
private Context context;
|
||||||
|
private AdapterItemClickListener<T> itemClickListener;//item的点击事件
|
||||||
|
private AdapterItemLongClickListener<T> itemLongClickListener;//item的长按事件
|
||||||
|
private ItemViewDelegateManager<T> mItemViewDelegateManager;//ItemViewDelegate的管理类
|
||||||
|
|
||||||
|
private List<T> list;
|
||||||
|
|
||||||
|
private AdapterItemClickListener<T> listener;
|
||||||
|
|
||||||
|
public BaseNormalAdapter() {
|
||||||
|
this.list = new ArrayList<>();
|
||||||
|
mItemViewDelegateManager = new ItemViewDelegateManager<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseNormalAdapter(List<T> list) {
|
||||||
|
this.list = null == list ? new ArrayList<>() : list;
|
||||||
|
mItemViewDelegateManager = new ItemViewDelegateManager<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setmDatas(List<T> mDatas) {
|
||||||
|
this.list.clear();
|
||||||
|
this.addmDatas(null == mDatas ? new ArrayList<>() : mDatas);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> getDatas() {
|
||||||
|
return this.list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addmDatas(List<T> mDatas) {
|
||||||
|
this.list.addAll(mDatas);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItem(T item) {
|
||||||
|
this.list.add(item);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeItem(T item) {
|
||||||
|
this.list.remove(item);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
if (!useItemViewDelegateManager()) return super.getItemViewType(position);
|
||||||
|
return mItemViewDelegateManager.getItemViewType(list.get(position), position);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否有多种ItemViewType
|
||||||
|
* 根据mItemViewDelegateManager 里面存储的数量决定
|
||||||
|
*
|
||||||
|
* @return true 有多种ItemViewType
|
||||||
|
*/
|
||||||
|
private boolean useItemViewDelegateManager() {
|
||||||
|
return mItemViewDelegateManager.getItemViewDelegateCount() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加不同的item样式
|
||||||
|
*
|
||||||
|
* @param itemViewDelegate 自定义的item
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public BaseNormalAdapter addItemViewDelegate(ItemViewDelegate<T> itemViewDelegate) {
|
||||||
|
mItemViewDelegateManager.addDelegate(itemViewDelegate);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加不同的item样式
|
||||||
|
*
|
||||||
|
* @param viewType 自定义的item type 不能重复
|
||||||
|
* @param itemViewDelegate 自定义的item
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public BaseNormalAdapter addItemViewDelegate(int viewType, ItemViewDelegate<T> itemViewDelegate) {
|
||||||
|
mItemViewDelegateManager.addDelegate(viewType, itemViewDelegate);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
ItemViewDelegate itemViewDelegate = mItemViewDelegateManager.getItemViewDelegate(viewType);
|
||||||
|
int layoutId = itemViewDelegate.getItemViewLayoutId();//这里拿到自定义的layoutId
|
||||||
|
context = parent.getContext();//context没用传递过来,这里自己获取到
|
||||||
|
return new ViewHolder(context, parent, layoutId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
if (null != itemClickListener) {
|
||||||
|
holder.itemView.setOnClickListener(v -> itemClickListener.onClick(holder.itemView, list.get(position), position));
|
||||||
|
}
|
||||||
|
if (null != itemLongClickListener) {
|
||||||
|
holder.itemView.setOnLongClickListener(v -> itemLongClickListener.onClick(holder.itemView, list.get(position), position));
|
||||||
|
}
|
||||||
|
convert(holder, list.get(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置item点击监听
|
||||||
|
*
|
||||||
|
* @param itemClickListener item的点击事件
|
||||||
|
*/
|
||||||
|
public void setItemClickListener(AdapterItemClickListener<T> itemClickListener) {
|
||||||
|
this.itemClickListener = itemClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置item长按监听
|
||||||
|
*
|
||||||
|
* @param itemLongClickListener item的长按事件
|
||||||
|
*/
|
||||||
|
public void setItemLongClickListener(AdapterItemLongClickListener<T> itemLongClickListener) {
|
||||||
|
this.itemLongClickListener = itemLongClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部分情况可以需要用到这个,比如item里面元素想要和item使用同一个回调处理
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected AdapterItemClickListener<T> getItemClickListener() {
|
||||||
|
return itemClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ui绘制的事件,分发给ItemViewDelegate自己处理
|
||||||
|
* 比如settext() setOnClickListener()这些
|
||||||
|
*
|
||||||
|
* @param holder holder
|
||||||
|
* @param item item
|
||||||
|
*/
|
||||||
|
public void convert(ViewHolder holder, T item) {
|
||||||
|
mItemViewDelegateManager.convert(holder, item, holder.getAdapterPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新知道item
|
||||||
|
*
|
||||||
|
* @param position position
|
||||||
|
*/
|
||||||
|
public void changeItem(int position) {
|
||||||
|
if (0 <= position && position < getItemCount()) {
|
||||||
|
notifyItemChanged(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeItem(int position, Object payload) {
|
||||||
|
if (0 <= position && position < getItemCount()) {
|
||||||
|
notifyItemChanged(position, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,157 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.paging.PagedListAdapter;
|
||||||
|
|
||||||
|
import com.xuqm.base.adapter.callback.AdapterItemClickListener;
|
||||||
|
import com.xuqm.base.adapter.callback.AdapterItemLongClickListener;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果用到了{@link com.xuqm.base.ui.BaseListActivity}来展示列表页面的话,需要adapter继承这个
|
||||||
|
* <p>
|
||||||
|
* 如果item只有一种类型,可以使用{@link CommonPagedAdapter}来展示
|
||||||
|
* <p>
|
||||||
|
* 如果不用{@link CommonPagedAdapter}的话,继承后需要使用{@link #addItemViewDelegate(ItemViewDelegate)}
|
||||||
|
* 来设置展示的页面
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public class BasePagedAdapter<T extends BaseItem> extends PagedListAdapter<T, ViewHolder> {
|
||||||
|
private Context context;
|
||||||
|
private AdapterItemClickListener<T> itemClickListener;//item的点击事件
|
||||||
|
private AdapterItemLongClickListener<T> itemLongClickListener;//item的长按事件
|
||||||
|
private ItemViewDelegateManager<T> mItemViewDelegateManager;//ItemViewDelegate的管理类
|
||||||
|
|
||||||
|
public BasePagedAdapter() {
|
||||||
|
super(new Diff<>());
|
||||||
|
mItemViewDelegateManager = new ItemViewDelegateManager<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
if (!useItemViewDelegateManager()) return super.getItemViewType(position);
|
||||||
|
return mItemViewDelegateManager.getItemViewType(getItem(position), position);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否有多种ItemViewType
|
||||||
|
* 根据mItemViewDelegateManager 里面存储的数量决定
|
||||||
|
*
|
||||||
|
* @return true 有多种ItemViewType
|
||||||
|
*/
|
||||||
|
private boolean useItemViewDelegateManager() {
|
||||||
|
return mItemViewDelegateManager.getItemViewDelegateCount() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加不同的item样式
|
||||||
|
*
|
||||||
|
* @param itemViewDelegate 自定义的item
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public BasePagedAdapter addItemViewDelegate(ItemViewDelegate<T> itemViewDelegate) {
|
||||||
|
mItemViewDelegateManager.addDelegate(itemViewDelegate);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加不同的item样式
|
||||||
|
*
|
||||||
|
* @param viewType 自定义的item type 不能重复
|
||||||
|
* @param itemViewDelegate 自定义的item
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public BasePagedAdapter addItemViewDelegate(int viewType, ItemViewDelegate<T> itemViewDelegate) {
|
||||||
|
mItemViewDelegateManager.addDelegate(viewType, itemViewDelegate);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
ItemViewDelegate itemViewDelegate = mItemViewDelegateManager.getItemViewDelegate(viewType);
|
||||||
|
int layoutId = itemViewDelegate.getItemViewLayoutId();//这里拿到自定义的layoutId
|
||||||
|
context = parent.getContext();//context没用传递过来,这里自己获取到
|
||||||
|
return new ViewHolder(context, parent, layoutId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
convert(holder, getItem(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) {
|
||||||
|
if (null != itemClickListener) {
|
||||||
|
holder.itemView.setOnClickListener(v -> itemClickListener.onClick(holder.itemView, getItem(position), position));
|
||||||
|
}
|
||||||
|
if (null != itemLongClickListener) {
|
||||||
|
holder.itemView.setOnLongClickListener(v -> itemLongClickListener.onClick(holder.itemView, getItem(position), position));
|
||||||
|
}
|
||||||
|
bindViewHolder(holder, getItem(position), position, payloads);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindViewHolder(ViewHolder holder, T item, int position, List<Object> payloads) {
|
||||||
|
convert(holder, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置item点击监听
|
||||||
|
*
|
||||||
|
* @param itemClickListener item的点击事件
|
||||||
|
*/
|
||||||
|
public void setItemClickListener(AdapterItemClickListener<T> itemClickListener) {
|
||||||
|
this.itemClickListener = itemClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置item长按监听
|
||||||
|
*
|
||||||
|
* @param itemLongClickListener item的长按事件
|
||||||
|
*/
|
||||||
|
public void setItemLongClickListener(AdapterItemLongClickListener<T> itemLongClickListener) {
|
||||||
|
this.itemLongClickListener = itemLongClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部分情况可以需要用到这个,比如item里面元素想要和item使用同一个回调处理
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected AdapterItemClickListener<T> getItemClickListener() {
|
||||||
|
return itemClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ui绘制的事件,分发给ItemViewDelegate自己处理
|
||||||
|
* 比如settext() setOnClickListener()这些
|
||||||
|
* @param holder holder
|
||||||
|
* @param item item
|
||||||
|
*/
|
||||||
|
public void convert(ViewHolder holder, T item) {
|
||||||
|
mItemViewDelegateManager.convert(holder, item, holder.getAdapterPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新知道item
|
||||||
|
* @param position position
|
||||||
|
*/
|
||||||
|
public void changeItem(int position) {
|
||||||
|
if (0 <= position && position < getItemCount()) {
|
||||||
|
notifyItemChanged(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeItem(int position, Object payload) {
|
||||||
|
if (0 <= position && position < getItemCount()) {
|
||||||
|
notifyItemChanged(position, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这个adapter主要是用来简化通用adapter
|
||||||
|
* 如果item只有一种样式,或者说不需要用到itemViewType,可以直接使用这个
|
||||||
|
* <p>
|
||||||
|
* 构造函数直接传入对应的layoutId,然后重写convert方法就可以了
|
||||||
|
* list不传的话,后面使用{@link #setmDatas(List)} 添加就可以了
|
||||||
|
*
|
||||||
|
* @param <T> item用到的数据类型
|
||||||
|
*/
|
||||||
|
public abstract class CommonAdapter<T> extends BaseNormalAdapter<T> {
|
||||||
|
|
||||||
|
|
||||||
|
protected CommonAdapter(final int layoutId) {
|
||||||
|
super();
|
||||||
|
addItemViewDelegate(new ItemViewDelegate<T>() {
|
||||||
|
@Override
|
||||||
|
public int getItemViewLayoutId() {
|
||||||
|
return layoutId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isForViewType(T item, int position) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convert(ViewHolder holder, T t, int position) {
|
||||||
|
CommonAdapter.this.convert(holder, t, position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CommonAdapter(final int layoutId, List<T> list) {
|
||||||
|
super(list);
|
||||||
|
addItemViewDelegate(new ItemViewDelegate<T>() {
|
||||||
|
@Override
|
||||||
|
public int getItemViewLayoutId() {
|
||||||
|
return layoutId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isForViewType(T item, int position) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convert(ViewHolder holder, T t, int position) {
|
||||||
|
CommonAdapter.this.convert(holder, t, position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void convert(ViewHolder holder, T item, int position);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这个adapter主要是用来简化通用列表页的绘制
|
||||||
|
* 如果item只有一种样式,或者说不需要用到itemViewType,可以直接使用这个
|
||||||
|
* <p>
|
||||||
|
* 构造函数直接传入对应的layoutId,然后重写convert方法就可以了
|
||||||
|
*
|
||||||
|
* @param <T> item用到的数据类型
|
||||||
|
*/
|
||||||
|
public abstract class CommonPagedAdapter<T extends BaseItem> extends BasePagedAdapter<T> {
|
||||||
|
|
||||||
|
|
||||||
|
protected CommonPagedAdapter(final int layoutId) {
|
||||||
|
super();
|
||||||
|
addItemViewDelegate(new ItemViewDelegate<T>() {
|
||||||
|
@Override
|
||||||
|
public int getItemViewLayoutId() {
|
||||||
|
return layoutId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isForViewType(T item, int position) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convert(ViewHolder holder, T t, int position) {
|
||||||
|
CommonPagedAdapter.this.convert(holder, t, position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void convert(ViewHolder holder, T item, int position);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
|
|
||||||
|
public class Diff<T extends BaseItem> extends DiffUtil.ItemCallback<T> {
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(@NonNull T oldItem, @NonNull T newItem) {
|
||||||
|
return oldItem.getS_id() == newItem.getS_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsTheSame(@NonNull T oldItem, @NonNull T newItem) {
|
||||||
|
return oldItem.getS_id() == newItem.getS_id();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.widget.HorizontalScrollView;
|
||||||
|
|
||||||
|
public class ElasticHorizontalScrollView extends HorizontalScrollView {
|
||||||
|
private float x;
|
||||||
|
private DisplayMetrics metrics;
|
||||||
|
private int threshold = 0;
|
||||||
|
|
||||||
|
public ElasticHorizontalScrollView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
|
||||||
|
metrics = getResources().getDisplayMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElasticHorizontalScrollView(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThreshold(int threshold) {
|
||||||
|
this.threshold = threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent ev) {
|
||||||
|
if (ev == null) {
|
||||||
|
return super.onTouchEvent(ev);
|
||||||
|
} else {
|
||||||
|
return commOnTouchEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
scrollTo(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean commOnTouchEvent(MotionEvent ev) {
|
||||||
|
int action = ev.getAction();
|
||||||
|
int length = threshold;
|
||||||
|
switch (action) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
x = ev.getX();
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
//复原位置
|
||||||
|
if ((ev.getX() - x) > 0) {
|
||||||
|
if (getScrollX() > length / 2) {
|
||||||
|
smoothScrollTo(length, 0);
|
||||||
|
} else {
|
||||||
|
smoothScrollTo(0, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (getScrollX() > length / 2) {
|
||||||
|
smoothScrollTo(length, 0);
|
||||||
|
} else {
|
||||||
|
smoothScrollTo(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
return super.onTouchEvent(ev);
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.lifecycle.Lifecycle;
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FragmentAdapter extends FragmentStateAdapter {
|
||||||
|
|
||||||
|
private List<Fragment> fragments;
|
||||||
|
|
||||||
|
public FragmentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle, List<Fragment> fragments) {
|
||||||
|
super(fragmentManager, lifecycle);
|
||||||
|
this.fragments = fragments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Fragment createFragment(int position) {
|
||||||
|
return fragments.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return fragments.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by zhy on 16/6/22.
|
||||||
|
*/
|
||||||
|
public interface ItemViewDelegate<T> {
|
||||||
|
|
||||||
|
int getItemViewLayoutId();//这个 ItemViewDelegate 将要展示的页面
|
||||||
|
|
||||||
|
boolean isForViewType(T item, int position); //条件判断,用来判断什么时候展示这个ItemViewDelegate
|
||||||
|
|
||||||
|
void convert(ViewHolder holder, T item, int position);//UI绘制与事件添加
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,95 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.collection.SparseArrayCompat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by zhy on 16/6/22.
|
||||||
|
*/
|
||||||
|
public class ItemViewDelegateManager<T> {
|
||||||
|
private SparseArrayCompat<ItemViewDelegate<T>> delegates = new SparseArrayCompat<>();
|
||||||
|
|
||||||
|
public int getItemViewDelegateCount() {
|
||||||
|
return delegates.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemViewDelegateManager<T> addDelegate(ItemViewDelegate<T> delegate) {
|
||||||
|
int viewType = delegates.size();
|
||||||
|
if (delegate != null) {
|
||||||
|
delegates.put(viewType, delegate);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemViewDelegateManager<T> addDelegate(int viewType, ItemViewDelegate<T> delegate) {
|
||||||
|
if (delegates.get(viewType) != null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"An ItemViewDelegate is already registered for the viewType = "
|
||||||
|
+ viewType
|
||||||
|
+ ". Already registered ItemViewDelegate is "
|
||||||
|
+ delegates.get(viewType));
|
||||||
|
}
|
||||||
|
delegates.put(viewType, delegate);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemViewDelegateManager<T> removeDelegate(ItemViewDelegate<T> delegate) {
|
||||||
|
if (delegate == null) {
|
||||||
|
throw new NullPointerException("ItemViewDelegate is null");
|
||||||
|
}
|
||||||
|
int indexToRemove = delegates.indexOfValue(delegate);
|
||||||
|
|
||||||
|
if (indexToRemove >= 0) {
|
||||||
|
delegates.removeAt(indexToRemove);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemViewDelegateManager<T> removeDelegate(int itemType) {
|
||||||
|
int indexToRemove = delegates.indexOfKey(itemType);
|
||||||
|
|
||||||
|
if (indexToRemove >= 0) {
|
||||||
|
delegates.removeAt(indexToRemove);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getItemViewType(T item, int position) {
|
||||||
|
int delegatesCount = delegates.size();
|
||||||
|
for (int i = 0; i < delegatesCount; i++) {
|
||||||
|
ItemViewDelegate<T> delegate = delegates.valueAt(i);
|
||||||
|
if (delegate.isForViewType(item, position)) {
|
||||||
|
return delegates.keyAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"No ItemViewDelegate added that matches position=" + position + " in data source");
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert(ViewHolder holder, T item, int position) {
|
||||||
|
int delegatesCount = delegates.size();
|
||||||
|
for (int i = 0; i < delegatesCount; i++) {
|
||||||
|
ItemViewDelegate<T> delegate = delegates.valueAt(i);
|
||||||
|
|
||||||
|
if (delegate.isForViewType(item, position)) {
|
||||||
|
delegate.convert(holder, item, position);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"No ItemViewDelegateManager added that matches position=" + position + " in data source");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ItemViewDelegate getItemViewDelegate(int viewType) {
|
||||||
|
return delegates.get(viewType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemViewLayoutId(int viewType) {
|
||||||
|
return getItemViewDelegate(viewType).getItemViewLayoutId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemViewType(ItemViewDelegate<T> itemViewDelegate) {
|
||||||
|
return delegates.indexOfValue(itemViewDelegate);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.LinearLayout.LayoutParams;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.xuqm.base.R;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jose.han
|
||||||
|
* @date 2019/7/19 0019
|
||||||
|
* @description 包装器,再原有的adpter 基础上,分装测滑功能,基于
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SlipReAdapter extends RecyclerView.Adapter<SlipReAdapter.RViewHolder> {
|
||||||
|
|
||||||
|
private RecyclerView.Adapter mAdapter;
|
||||||
|
private ISlipClickAction mISlipClickAction;
|
||||||
|
private int mSlipViewId;
|
||||||
|
public final static int MODE_DELETE = 0;
|
||||||
|
public final static int MODE_CLICK = 0;
|
||||||
|
private int mMode = MODE_DELETE;
|
||||||
|
private int mSlipWidth = 0;
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
private RecyclerView.Adapter mAdapter;
|
||||||
|
private ISlipClickAction mISlipClickAction;
|
||||||
|
private int mSlipViewId;
|
||||||
|
private int mMode;
|
||||||
|
private int mSlipWidth;
|
||||||
|
|
||||||
|
public Builder setAdapter(RecyclerView.Adapter adapter) {
|
||||||
|
mAdapter = adapter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setISlipClickAction(
|
||||||
|
ISlipClickAction ISlipClickAction) {
|
||||||
|
mISlipClickAction = ISlipClickAction;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setSlipViewId(int slipViewId) {
|
||||||
|
mSlipViewId = slipViewId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMode(int mode) {
|
||||||
|
mMode = mode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setSlipWidth(float slipWidth) {
|
||||||
|
mSlipWidth = (int) slipWidth;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SlipReAdapter build() {
|
||||||
|
SlipReAdapter slipReAdapter = new SlipReAdapter();
|
||||||
|
slipReAdapter.setAdapter(mAdapter);
|
||||||
|
slipReAdapter.setISlipClickAction(mISlipClickAction);
|
||||||
|
slipReAdapter.setMode(mMode);
|
||||||
|
slipReAdapter.setSlipViewId(mSlipViewId);
|
||||||
|
slipReAdapter.setSlipWidth(mSlipWidth);
|
||||||
|
return slipReAdapter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SlipReAdapter() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAdapter(RecyclerView.Adapter adapter) {
|
||||||
|
mAdapter = adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setISlipClickAction(
|
||||||
|
ISlipClickAction ISlipClickAction) {
|
||||||
|
mISlipClickAction = ISlipClickAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSlipViewId(int slipViewId) {
|
||||||
|
mSlipViewId = slipViewId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMode(int mode) {
|
||||||
|
mMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSlipWidth(int slipWidth) {
|
||||||
|
mSlipWidth = slipWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_slip, parent, false);
|
||||||
|
LinearLayout contentLL = view.findViewById(R.id.content_ll);
|
||||||
|
LinearLayout deleteLl = view.findViewById(R.id.delete_ll);
|
||||||
|
View delete = LayoutInflater.from(parent.getContext()).inflate(mSlipViewId, null, false);
|
||||||
|
deleteLl.addView(delete);
|
||||||
|
|
||||||
|
LayoutParams layoutParams = new LayoutParams(
|
||||||
|
parent.getResources().getDisplayMetrics().widthPixels,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
RecyclerView.ViewHolder viewHolder = mAdapter.onCreateViewHolder(parent, viewType);
|
||||||
|
viewHolder.itemView.setLayoutParams(layoutParams);
|
||||||
|
contentLL.addView(viewHolder.itemView);
|
||||||
|
|
||||||
|
return new RViewHolder(view, viewHolder, mSlipWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(final RViewHolder holder, final int position) {
|
||||||
|
mAdapter.onBindViewHolder(holder.mViewHolder, position);
|
||||||
|
holder.deleteLl.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
mISlipClickAction.onAction(holder.getAdapterPosition());
|
||||||
|
holder.mElasticHorizontalScrollView.reset();
|
||||||
|
Log.i("SlipReAdapter", "slip action and the pos is:" + holder.getAdapterPosition());
|
||||||
|
if (mMode == MODE_DELETE) {
|
||||||
|
notifyItemRemoved(holder.getAdapterPosition());
|
||||||
|
} else if (mMode == MODE_CLICK) {
|
||||||
|
notifyItemChanged(holder.getAdapterPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mAdapter != null ? mAdapter.getItemCount() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
private View deleteLl;
|
||||||
|
private ElasticHorizontalScrollView mElasticHorizontalScrollView;
|
||||||
|
private RecyclerView.ViewHolder mViewHolder;
|
||||||
|
|
||||||
|
public RViewHolder(View itemView, RecyclerView.ViewHolder viewHolder, int threshold) {
|
||||||
|
super(itemView);
|
||||||
|
mViewHolder = viewHolder;
|
||||||
|
deleteLl = itemView.findViewById(R.id.delete_ll);
|
||||||
|
mElasticHorizontalScrollView = itemView.findViewById(R.id.ElasticHorizontalScrollView);
|
||||||
|
if (threshold != 0) {
|
||||||
|
LayoutParams layoutParams = new LayoutParams(threshold,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
deleteLl.setLayoutParams(layoutParams);
|
||||||
|
mElasticHorizontalScrollView.setThreshold(threshold);
|
||||||
|
} else {
|
||||||
|
deleteLl.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int width = deleteLl.getWidth();
|
||||||
|
mElasticHorizontalScrollView.setThreshold(width);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ISlipClickAction {
|
||||||
|
|
||||||
|
public void onAction(int position);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
package com.xuqm.base.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.ColorRes;
|
||||||
|
import androidx.annotation.DrawableRes;
|
||||||
|
import androidx.annotation.IdRes;
|
||||||
|
import androidx.annotation.LayoutRes;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.xuqm.base.adapter.callback.AdapterClickListener;
|
||||||
|
import com.xuqm.base.common.ImageHelper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private ViewGroup parent;
|
||||||
|
private int layoutId;
|
||||||
|
|
||||||
|
private SparseArray<View> views = new SparseArray<>();
|
||||||
|
|
||||||
|
public ViewHolder(Context context, ViewGroup parent, @LayoutRes int layoutId) {
|
||||||
|
super(LayoutInflater.from(context).inflate(layoutId, parent, false));
|
||||||
|
this.context = context;
|
||||||
|
this.parent = parent;
|
||||||
|
this.layoutId = layoutId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends View> T getView(int viewId) {
|
||||||
|
View view = views.get(viewId);
|
||||||
|
if (null == view) {
|
||||||
|
view = itemView.findViewById(viewId);
|
||||||
|
if (null == view) throw new IllegalArgumentException("not found id");
|
||||||
|
views.put(viewId, view);
|
||||||
|
}
|
||||||
|
return (T) view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setText(@IdRes int viewId, CharSequence text) {
|
||||||
|
TextView textView = getView(viewId);
|
||||||
|
textView.setText(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setTypeface(@IdRes int viewId, Typeface typeface) {
|
||||||
|
TextView textView = getView(viewId);
|
||||||
|
textView.setTypeface(typeface);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setEnabled(@IdRes int viewId, boolean enabled) {
|
||||||
|
View view = getView(viewId);
|
||||||
|
view.setEnabled(enabled);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setBackgroundResource(@IdRes int viewId, @DrawableRes int resId) {
|
||||||
|
View textView = getView(viewId);
|
||||||
|
textView.setBackgroundResource(resId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ViewHolder setBackgroundColor(@IdRes int viewId, @ColorInt int color) {
|
||||||
|
View textView = getView(viewId);
|
||||||
|
textView.setBackgroundColor(color);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ViewHolder setTextColor(@IdRes int viewId, @ColorInt int color) {
|
||||||
|
TextView textView = getView(viewId);
|
||||||
|
textView.setTextColor(color);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setText(@IdRes int viewId, @StringRes int resId) {
|
||||||
|
TextView textView = getView(viewId);
|
||||||
|
textView.setText(context.getString(resId));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setImageResource(@IdRes int viewId, @DrawableRes int resId) {
|
||||||
|
ImageView imageView = getView(viewId);
|
||||||
|
imageView.setImageResource(resId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setImage(@IdRes int viewId, String url) {
|
||||||
|
ImageView imageView = getView(viewId);
|
||||||
|
ImageHelper.load(imageView, url);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ViewHolder setImage(@IdRes int viewId, Bitmap bitmap) {
|
||||||
|
ImageView imageView = getView(viewId);
|
||||||
|
ImageHelper.load(imageView, bitmap);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder gone(@IdRes int viewId) {
|
||||||
|
View view = getView(viewId);
|
||||||
|
view.setVisibility(View.GONE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ViewHolder invisible(@IdRes int viewId) {
|
||||||
|
View view = getView(viewId);
|
||||||
|
view.setVisibility(View.INVISIBLE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder gone(View view) {
|
||||||
|
view.setVisibility(View.GONE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder visible(@IdRes int viewId) {
|
||||||
|
View view = getView(viewId);
|
||||||
|
view.setVisibility(View.VISIBLE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setVisibility(@IdRes int viewId, boolean isVisible) {
|
||||||
|
View view = getView(viewId);
|
||||||
|
if (isVisible) view.setVisibility(View.VISIBLE);
|
||||||
|
else view.setVisibility(View.GONE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder visible(View view) {
|
||||||
|
view.setVisibility(View.VISIBLE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setClickListener(@IdRes int viewId, AdapterClickListener adapterClickListener) {
|
||||||
|
View view = getView(viewId);
|
||||||
|
if (null != view) view.setOnClickListener(adapterClickListener::onClick);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewHolder setClickListener(List<Integer> viewIds, AdapterClickListener adapterClickListener) {
|
||||||
|
for (Integer viewId : viewIds) {
|
||||||
|
View view = getView(viewId);
|
||||||
|
if (null != view) view.setOnClickListener(adapterClickListener::onClick);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.xuqm.base.adapter.callback;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* adapter中,为item元素设置点击时间时候用到的监听
|
||||||
|
*/
|
||||||
|
public interface AdapterClickListener {
|
||||||
|
void onClick(View view);
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package com.xuqm.base.adapter.callback;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* item设置点击事件的监听
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public interface AdapterItemClickListener<T> {
|
||||||
|
void onClick(View view, T item, int position);
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package com.xuqm.base.adapter.callback;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* item设置长按事件的监听
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public interface AdapterItemLongClickListener<T> {
|
||||||
|
boolean onClick(View view, T item, int position);
|
||||||
|
}
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
package com.xuqm.base.common;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* activity的管理栈
|
||||||
|
*/
|
||||||
|
public class AppManager {
|
||||||
|
|
||||||
|
|
||||||
|
public static AppManager getInstance() {
|
||||||
|
return APPHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class APPHolder {
|
||||||
|
private static final AppManager INSTANCE = new AppManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppManager() {
|
||||||
|
activityStack = new Stack<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Stack<Activity> activityStack;
|
||||||
|
|
||||||
|
//添加一个新的act
|
||||||
|
public void pushActivity(Activity activity) {
|
||||||
|
activityStack.add(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推出一个activity 其实toolbar的返回按钮,可以直接使用这个方法
|
||||||
|
*
|
||||||
|
* @param activity 需要退出的activity
|
||||||
|
*/
|
||||||
|
public void popActivity(Activity activity) {
|
||||||
|
if (activityStack != null && activityStack.size() > 0) {
|
||||||
|
if (activity != null) {
|
||||||
|
activity.finish();
|
||||||
|
activityStack.remove(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前最上面的那个activity
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Activity getActivity() {
|
||||||
|
return activityStack.lastElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* finish最后一个
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void finish() {
|
||||||
|
this.popActivity(this.getActivity());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* finish最后一个之外的所有页面
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void logout() {
|
||||||
|
if (activityStack.size() < 1)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < activityStack.size() - 1; i++) {
|
||||||
|
Activity activity = activityStack.firstElement();
|
||||||
|
if (activity == null) break;
|
||||||
|
popActivity(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出app
|
||||||
|
*/
|
||||||
|
public void exit() {
|
||||||
|
if (activityStack != null) {
|
||||||
|
while (activityStack.size() > 0) {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity == null) break;
|
||||||
|
popActivity(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
android.os.Process.killProcess(android.os.Process.myPid());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,218 @@
|
|||||||
|
package com.xuqm.base.common;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.FileProvider;
|
||||||
|
|
||||||
|
import com.xuqm.base.App;
|
||||||
|
import com.xuqm.base.BuildConfig;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class FileHelper {
|
||||||
|
|
||||||
|
|
||||||
|
public static String getRootFilePath() {
|
||||||
|
return App.getInstance().getExternalFilesDir(null).getPath() +
|
||||||
|
File.separator +
|
||||||
|
BuildConfig.APP_ID +
|
||||||
|
File.separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据路径创建文件夹
|
||||||
|
*
|
||||||
|
* @param filePath
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean createDirectory(String filePath) {
|
||||||
|
if (ToolsHelper.isNull(filePath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(filePath);
|
||||||
|
|
||||||
|
if (file.exists() && file.isDirectory()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return file.mkdirs();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete(String path) {
|
||||||
|
LogHelper.e(String.format("开始删除文件::%s", path));
|
||||||
|
File file = new File(path);
|
||||||
|
if (!file.exists()
|
||||||
|
|| !file.isFile())
|
||||||
|
return;
|
||||||
|
file.delete();
|
||||||
|
|
||||||
|
}
|
||||||
|
public static void delete(File file) {
|
||||||
|
LogHelper.e(String.format("开始删除文件::%s", file.getAbsoluteFile()));
|
||||||
|
if (!file.exists()
|
||||||
|
|| !file.isFile())
|
||||||
|
return;
|
||||||
|
file.delete();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getVoicePath() {
|
||||||
|
String path = getRootFilePath() +
|
||||||
|
"voice" +
|
||||||
|
File.separator;
|
||||||
|
|
||||||
|
return createDirectory(path) ? path : "";
|
||||||
|
}
|
||||||
|
public static String getImagePath() {
|
||||||
|
String path = getRootFilePath() +
|
||||||
|
"image" +
|
||||||
|
File.separator;
|
||||||
|
|
||||||
|
return createDirectory(path) ? path : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAppPath() {
|
||||||
|
String path = getRootFilePath() +
|
||||||
|
"apps" +
|
||||||
|
File.separator;
|
||||||
|
LogHelper.e(path);
|
||||||
|
|
||||||
|
return createDirectory(path) ? path : "";
|
||||||
|
}
|
||||||
|
public static String getDownloadPath() {
|
||||||
|
String path = getRootFilePath() +
|
||||||
|
"download" +
|
||||||
|
File.separator;
|
||||||
|
LogHelper.e(path);
|
||||||
|
|
||||||
|
return createDirectory(path) ? path : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取assets文件夹的文件
|
||||||
|
*
|
||||||
|
* @param strFileName 文件名,包含assets后面的路径
|
||||||
|
* @return 文件内容
|
||||||
|
*/
|
||||||
|
public static String readJSON(String strFileName) {
|
||||||
|
String strResult = "";
|
||||||
|
try (InputStream is = App.getInstance().getAssets().open(strFileName)) {
|
||||||
|
int size = is.available();
|
||||||
|
byte[] buffer = new byte[size];
|
||||||
|
is.read(buffer);
|
||||||
|
strResult = new String(buffer, StandardCharsets.UTF_8);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LogHelper.e("readJson", ex);
|
||||||
|
}
|
||||||
|
return strResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getBitmapFilePath(String path, String suffix) {
|
||||||
|
|
||||||
|
String pathStr = getRootFilePath() + "images" + File.separator + path + File.separator;
|
||||||
|
createDirectory(pathStr);
|
||||||
|
|
||||||
|
return pathStr + UUID.randomUUID() + "." + suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存图片到本地
|
||||||
|
*
|
||||||
|
* @param bitmap 图片
|
||||||
|
* @param filePath 保存到的文件 png
|
||||||
|
* @return 状态
|
||||||
|
*/
|
||||||
|
public static String saveBitmap(Bitmap bitmap, String filePath) {
|
||||||
|
if (bitmap == null)
|
||||||
|
return "";
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
try {
|
||||||
|
fos = new FileOutputStream(new File(filePath));
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
|
||||||
|
fos.flush();
|
||||||
|
return filePath;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (fos != null) {
|
||||||
|
try {
|
||||||
|
fos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void installAPK(String filePath) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction("android.intent.action.VIEW");
|
||||||
|
intent.addCategory("android.intent.category.DEFAULT");
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 广播里面操作需要加上这句,存在于一个独立的栈里
|
||||||
|
intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive");
|
||||||
|
App.getInstance().startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void openFile(Context activity, File file) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
// 设置intent的Action属性
|
||||||
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
|
// 获取文件file的MIME类型
|
||||||
|
String type = getMIMEType(file);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
}
|
||||||
|
// 设置intent的data和Type属性。
|
||||||
|
intent.setDataAndType(/* uri */FileHelper.getFileUri(file), type);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Uri getFileUri(@NonNull File file) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
return FileProvider.getUriForFile(AppManager.getInstance().getActivity(), BuildConfig.APP_ID + ".fileprovider", file);
|
||||||
|
} else {
|
||||||
|
return Uri.fromFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[][] MIME_MapTable = new String[][]{{".3gp", "video/3gpp"}, {".apk", "application/vnd.android.package-archive"}, {".asf", "video/x-ms-asf"}, {".avi", "video/x-msvideo"}, {".bin", "application/octet-stream"}, {".bmp", "image/bmp"}, {".c", "text/plain"}, {".class", "application/octet-stream"}, {".conf", "text/plain"}, {".cpp", "text/plain"}, {".doc", "application/msword"}, {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, {".xls", "application/vnd.ms-excel"}, {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, {".exe", "application/octet-stream"}, {".gif", "image/gif"}, {".gtar", "application/x-gtar"}, {".gz", "application/x-gzip"}, {".h", "text/plain"}, {".htm", "text/html"}, {".html", "text/html"}, {".jar", "application/java-archive"}, {".java", "text/plain"}, {".jpeg", "image/jpeg"}, {".jpg", "image/jpeg"}, {".eucppic", "image/jpeg"}, {".js", "application/x-javascript"}, {".log", "text/plain"}, {".m3u", "audio/x-mpegurl"}, {".m4a", "audio/mp4a-latm"}, {".m4b", "audio/mp4a-latm"}, {".m4p", "audio/mp4a-latm"}, {".m4u", "video/vnd.mpegurl"}, {".m4v", "video/x-m4v"}, {".mov", "video/quicktime"}, {".mp2", "audio/x-mpeg"}, {".mp3", "audio/x-mpeg"}, {".mp4", "video/mp4"}, {".mpc", "application/vnd.mpohun.certificate"}, {".mpe", "video/mpeg"}, {".mpeg", "video/mpeg"}, {".mpg", "video/mpeg"}, {".mpg4", "video/mp4"}, {".mpga", "audio/mpeg"}, {".msg", "application/vnd.ms-outlook"}, {".ogg", "audio/ogg"}, {".pdf", "application/pdf"}, {".png", "image/png"}, {".pps", "application/vnd.ms-powerpoint"}, {".ppt", "application/vnd.ms-powerpoint"}, {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, {".prop", "text/plain"}, {".rc", "text/plain"}, {".rmvb", "audio/x-pn-realaudio"}, {".rtf", "application/rtf"}, {".sh", "text/plain"}, {".tar", "application/x-tar"}, {".tgz", "application/x-compressed"}, {".txt", "text/plain"}, {".wav", "audio/x-wav"}, {".wma", "audio/x-ms-wma"}, {".wmv", "audio/x-ms-wmv"}, {".wps", "application/vnd.ms-works"}, {".xml", "text/plain"}, {".z", "application/x-compress"}, {".zip", "application/x-zip-compressed"}, {"", "*/*"}};
|
||||||
|
|
||||||
|
public static String getMIMEType(File file) {
|
||||||
|
String type = "*/*";
|
||||||
|
String fName = file.getName();
|
||||||
|
int dotIndex = fName.lastIndexOf(".");
|
||||||
|
if (dotIndex < 0) {
|
||||||
|
return type;
|
||||||
|
} else {
|
||||||
|
String end = fName.substring(dotIndex, fName.length()).toLowerCase();
|
||||||
|
if (end == "") {
|
||||||
|
return type;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < MIME_MapTable.length; ++i) {
|
||||||
|
if (end.equals(MIME_MapTable[i][0])) {
|
||||||
|
type = MIME_MapTable[i][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,230 @@
|
|||||||
|
package com.xuqm.base.common
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.PointF
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.annotation.NonNull
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawable
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import com.bumptech.glide.request.target.BitmapImageViewTarget
|
||||||
|
import com.bumptech.glide.request.target.ImageViewTarget
|
||||||
|
import com.luck.picture.lib.engine.ImageEngine
|
||||||
|
import com.luck.picture.lib.listener.OnImageCompleteCallback
|
||||||
|
import com.luck.picture.lib.tools.MediaUtils
|
||||||
|
import com.luck.picture.lib.widget.longimage.ImageSource
|
||||||
|
import com.luck.picture.lib.widget.longimage.ImageViewState
|
||||||
|
import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView
|
||||||
|
import com.xuqm.base.R
|
||||||
|
import org.jetbrains.annotations.NotNull
|
||||||
|
|
||||||
|
|
||||||
|
class GlideEngine private constructor() : ImageEngine {
|
||||||
|
/**
|
||||||
|
* 加载图片
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
*/
|
||||||
|
override fun loadImage(
|
||||||
|
@NotNull context: Context,
|
||||||
|
@NotNull url: String,
|
||||||
|
@NotNull imageView: ImageView
|
||||||
|
) {
|
||||||
|
Glide.with(context)
|
||||||
|
.load(url)
|
||||||
|
.into(imageView)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载网络图片适配长图方案
|
||||||
|
* # 注意:此方法只有加载网络图片才会回调
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
* @param longImageView
|
||||||
|
* @param callback 网络图片加载回调监听 {link after version 2.5.1 Please use the #OnImageCompleteCallback#}
|
||||||
|
*/
|
||||||
|
override fun loadImage(
|
||||||
|
@NotNull context: Context, @NotNull url: String,
|
||||||
|
@NotNull imageView: ImageView,
|
||||||
|
longImageView: SubsamplingScaleImageView, callback: OnImageCompleteCallback
|
||||||
|
) {
|
||||||
|
Glide.with(context)
|
||||||
|
.asBitmap()
|
||||||
|
.load(url)
|
||||||
|
.into(object : ImageViewTarget<Bitmap?>(imageView) {
|
||||||
|
override fun onLoadStarted(@NonNull placeholder: Drawable?) {
|
||||||
|
super.onLoadStarted(placeholder)
|
||||||
|
callback.onShowLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLoadFailed(@NonNull errorDrawable: Drawable?) {
|
||||||
|
super.onLoadFailed(errorDrawable)
|
||||||
|
callback.onHideLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setResource(@NonNull resource: Bitmap?) {
|
||||||
|
callback.onHideLoading()
|
||||||
|
if (resource != null) {
|
||||||
|
val eqLongImage: Boolean = MediaUtils.isLongImg(
|
||||||
|
resource.width,
|
||||||
|
resource.height
|
||||||
|
)
|
||||||
|
longImageView.visibility = if (eqLongImage) View.VISIBLE else View.GONE
|
||||||
|
imageView.visibility = if (eqLongImage) View.GONE else View.VISIBLE
|
||||||
|
if (eqLongImage) {
|
||||||
|
// 加载长图
|
||||||
|
longImageView.isQuickScaleEnabled = true
|
||||||
|
longImageView.isZoomEnabled = true
|
||||||
|
longImageView.isPanEnabled = true
|
||||||
|
longImageView.setDoubleTapZoomDuration(100)
|
||||||
|
longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP)
|
||||||
|
longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER)
|
||||||
|
longImageView.setImage(
|
||||||
|
ImageSource.bitmap(resource),
|
||||||
|
ImageViewState(0f, PointF(0f, 0f), 0)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// 普通图片
|
||||||
|
imageView.setImageBitmap(resource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载网络图片适配长图方案
|
||||||
|
* # 注意:此方法只有加载网络图片才会回调
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param url
|
||||||
|
* @param imageView
|
||||||
|
* @param longImageView
|
||||||
|
* @ 已废弃
|
||||||
|
*/
|
||||||
|
override fun loadImage(
|
||||||
|
@NotNull context: Context, @NotNull url: String,
|
||||||
|
@NotNull imageView: ImageView,
|
||||||
|
longImageView: SubsamplingScaleImageView
|
||||||
|
) {
|
||||||
|
Glide.with(context)
|
||||||
|
.asBitmap()
|
||||||
|
.load(url)
|
||||||
|
.into(object : ImageViewTarget<Bitmap?>(imageView) {
|
||||||
|
override fun setResource(@NonNull resource: Bitmap?) {
|
||||||
|
if (resource != null) {
|
||||||
|
val eqLongImage: Boolean = MediaUtils.isLongImg(
|
||||||
|
resource.width,
|
||||||
|
resource.height
|
||||||
|
)
|
||||||
|
longImageView.visibility = if (eqLongImage) View.VISIBLE else View.GONE
|
||||||
|
imageView.visibility = if (eqLongImage) View.GONE else View.VISIBLE
|
||||||
|
if (eqLongImage) {
|
||||||
|
// 加载长图
|
||||||
|
longImageView.isQuickScaleEnabled = true
|
||||||
|
longImageView.isZoomEnabled = true
|
||||||
|
longImageView.isPanEnabled = true
|
||||||
|
longImageView.setDoubleTapZoomDuration(100)
|
||||||
|
longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP)
|
||||||
|
longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER)
|
||||||
|
longImageView.setImage(
|
||||||
|
ImageSource.bitmap(resource),
|
||||||
|
ImageViewState(0f, PointF(0f, 0f), 0)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// 普通图片
|
||||||
|
imageView.setImageBitmap(resource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载相册目录
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片路径
|
||||||
|
* @param imageView 承载图片ImageView
|
||||||
|
*/
|
||||||
|
override fun loadFolderImage(
|
||||||
|
@NotNull context: Context,
|
||||||
|
@NotNull url: String,
|
||||||
|
@NotNull imageView: ImageView
|
||||||
|
) {
|
||||||
|
Glide.with(context)
|
||||||
|
.asBitmap()
|
||||||
|
.load(url)
|
||||||
|
.override(180, 180)
|
||||||
|
.centerCrop()
|
||||||
|
.sizeMultiplier(0.5f)
|
||||||
|
.apply(RequestOptions().placeholder(R.drawable.picture_image_placeholder))
|
||||||
|
.into(object : BitmapImageViewTarget(imageView) {
|
||||||
|
override fun setResource(resource: Bitmap?) {
|
||||||
|
val circularBitmapDrawable: RoundedBitmapDrawable =
|
||||||
|
RoundedBitmapDrawableFactory.create(context.resources, resource)
|
||||||
|
circularBitmapDrawable.cornerRadius = 8f
|
||||||
|
imageView.setImageDrawable(circularBitmapDrawable)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载gif
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片路径
|
||||||
|
* @param imageView 承载图片ImageView
|
||||||
|
*/
|
||||||
|
override fun loadAsGifImage(
|
||||||
|
@NotNull context: Context, @NotNull url: String,
|
||||||
|
@NotNull imageView: ImageView
|
||||||
|
) {
|
||||||
|
Glide.with(context)
|
||||||
|
.asGif()
|
||||||
|
.load(url)
|
||||||
|
.into(imageView)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载图片列表图片
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param url 图片路径
|
||||||
|
* @param imageView 承载图片ImageView
|
||||||
|
*/
|
||||||
|
override fun loadGridImage(
|
||||||
|
@NotNull context: Context,
|
||||||
|
@NotNull url: String,
|
||||||
|
@NotNull imageView: ImageView
|
||||||
|
) {
|
||||||
|
Glide.with(context)
|
||||||
|
.load(url)
|
||||||
|
.override(200, 200)
|
||||||
|
.centerCrop()
|
||||||
|
.apply(RequestOptions().placeholder(R.drawable.picture_image_placeholder))
|
||||||
|
.into(imageView)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private var instance: GlideEngine? = null
|
||||||
|
fun createGlideEngine(): GlideEngine? {
|
||||||
|
if (null == instance) {
|
||||||
|
synchronized(GlideEngine::class.java) {
|
||||||
|
if (null == instance) {
|
||||||
|
instance = GlideEngine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
package com.xuqm.base.common;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by xuqm on 2016/6/3.
|
||||||
|
*/
|
||||||
|
public class GsonImplHelp extends Json {
|
||||||
|
private Gson gson = new Gson();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJson(Object src) {
|
||||||
|
return gson.toJson(src);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T toObject(String json, Class<T> claxx) {
|
||||||
|
return gson.fromJson(json, claxx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T toObject(byte[] bytes, Class<T> claxx) {
|
||||||
|
return gson.fromJson(new String(bytes), claxx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> List<T> toList(String json, Class<T> clazz) {
|
||||||
|
JsonArray jsonArray = new JsonParser().parse(json).getAsJsonArray();
|
||||||
|
|
||||||
|
List<T> list = new ArrayList<>();
|
||||||
|
for (JsonElement jsonElement : jsonArray) {
|
||||||
|
list.add(gson.fromJson(jsonElement, clazz)); //cls
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> stringToArray(String s, Class<T[]> cls) {
|
||||||
|
T[] array = new Gson().fromJson(s, cls);
|
||||||
|
return Arrays.asList(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
package com.xuqm.base.common;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.util.Base64;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* <pre></pre>
|
||||||
|
* @文件名称: ImageHelp
|
||||||
|
* @包 路 径: com.xuqm.base.common
|
||||||
|
* @版权所有:北京数字医信责任有限公司 (C) 2021
|
||||||
|
*
|
||||||
|
* @类描述:
|
||||||
|
* @版本: V1.0
|
||||||
|
* @创建人: xuqm
|
||||||
|
* @创建时间:2021/9/26 下午 06:11
|
||||||
|
* @修改记录:
|
||||||
|
*/
|
||||||
|
public class ImageHelp {
|
||||||
|
/*
|
||||||
|
* bitmap转base64
|
||||||
|
* */
|
||||||
|
public static String bitmapToBase64(Bitmap bitmap) {
|
||||||
|
String result = null;
|
||||||
|
ByteArrayOutputStream baos = null;
|
||||||
|
try {
|
||||||
|
if (bitmap != null) {
|
||||||
|
baos = new ByteArrayOutputStream();
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
|
||||||
|
|
||||||
|
baos.flush();
|
||||||
|
baos.close();
|
||||||
|
|
||||||
|
byte[] bitmapBytes = baos.toByteArray();
|
||||||
|
result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (baos != null) {
|
||||||
|
baos.flush();
|
||||||
|
baos.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* base64转为bitmap
|
||||||
|
*
|
||||||
|
* @param base64Data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap base64ToBitmap(String base64Data) {
|
||||||
|
byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT);
|
||||||
|
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package com.xuqm.base.common;
|
||||||
|
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一个image相关的工具类
|
||||||
|
*/
|
||||||
|
public class ImageHelper {
|
||||||
|
/**
|
||||||
|
* 给imageView添加图片的方法
|
||||||
|
*
|
||||||
|
* @param imageView 需要添加图片的控件
|
||||||
|
* @param url url地址,可以是path draw等
|
||||||
|
*/
|
||||||
|
public static void load(ImageView imageView, Object url) {
|
||||||
|
Glide.with(imageView).load(url).into(imageView);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package com.xuqm.base.common;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by xuqm on 2016/6/3.
|
||||||
|
*/
|
||||||
|
public abstract class Json {
|
||||||
|
private static Json json;
|
||||||
|
|
||||||
|
Json() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Json get() {
|
||||||
|
if (json == null) {
|
||||||
|
json = new GsonImplHelp();
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String toJson(Object src);
|
||||||
|
|
||||||
|
public abstract <T> T toObject(String json, Class<T> claxx);
|
||||||
|
|
||||||
|
public abstract <T> T toObject(byte[] bytes, Class<T> claxx);
|
||||||
|
|
||||||
|
public abstract <T> List<T> toList(String json, Class<T> claxx);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
package com.xuqm.base.common;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.orhanobut.logger.Logger;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志库用的是 KLog
|
||||||
|
* 平常自己调试时候不想用那么多,就随便写了个类
|
||||||
|
*/
|
||||||
|
public class LogHelper {
|
||||||
|
|
||||||
|
|
||||||
|
public static void d(String tag, Object object) {
|
||||||
|
Logger.t(tag).d(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void d(Object object) {
|
||||||
|
StackTraceElement caller = getCallerStackTraceElement();
|
||||||
|
String tag = generateTag(caller);
|
||||||
|
Logger.t(tag).d(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void d(@NonNull String message, @Nullable Object... args) {
|
||||||
|
Logger.t(message).d(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void e(String tag, Object object) {
|
||||||
|
Logger.t(tag).e(object.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void e(Object object) {
|
||||||
|
if (null == object){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StackTraceElement caller = getCallerStackTraceElement();
|
||||||
|
String tag = generateTag(caller);
|
||||||
|
Logger.t(tag).e("=====>" + object.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void e(String msg, Throwable tr) {
|
||||||
|
StackTraceElement caller = getCallerStackTraceElement();
|
||||||
|
String tag = generateTag(caller);
|
||||||
|
Logger.t(tag).e(tr, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void e(String tag, String msg, Throwable tr) {
|
||||||
|
Logger.t(tag).e(tr, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void json(String msg) {
|
||||||
|
StackTraceElement caller = getCallerStackTraceElement();
|
||||||
|
String tag = generateTag(caller);
|
||||||
|
Logger.t(tag).json(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void json(String tag, String msg) {
|
||||||
|
Logger.t(tag).json(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String generateTag(StackTraceElement caller) {
|
||||||
|
String tag = "%s.%s(L:%d)";
|
||||||
|
String callerClazzName = caller.getClassName();
|
||||||
|
callerClazzName = callerClazzName.substring(callerClazzName.lastIndexOf(".") + 1);
|
||||||
|
return String.format(Locale.getDefault(), tag, callerClazzName, caller.getMethodName(), caller.getLineNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StackTraceElement getCallerStackTraceElement() {
|
||||||
|
return Thread.currentThread().getStackTrace()[4];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package com.xuqm.base.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下拉刷新的状态码表
|
||||||
|
*/
|
||||||
|
public enum RefreshResult {
|
||||||
|
SUCCEED, FAILED, NO_DATA, NO_MORE
|
||||||
|
}
|
||||||