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,35 @@
|
||||
package com.bjca.hp.acupuncture.ui
|
||||
|
||||
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
|
||||
}
|
||||