liumingming

sdk

Showing 35 changed files with 2803 additions and 0 deletions
  1 +*.iml
  2 +.gradle
  3 +/local.properties
  4 +/.idea/workspace.xml
  5 +/.idea/libraries
  6 +.DS_Store
  7 +/build
  8 +.idea/*
  9 +../.idea
  10 +.idea/sonarlint/
  11 +/captures
  12 +.externalNativeBuild
  1 +/build
  1 +apply plugin: 'com.jfrog.bintray'
  2 +
  3 +version = android.defaultConfig.versionName
  4 +
  5 +if (project.hasProperty("android")) { // Android libraries
  6 + task sourcesJar(type: Jar) {
  7 + classifier = 'sources'
  8 + from android.sourceSets.main.java.srcDirs
  9 + }
  10 +
  11 +// task javadoc(type: Javadoc) {
  12 +// source = android.sourceSets.main.java.srcDirs
  13 +// classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
  14 +// }
  15 +} else { // Java libraries
  16 + task sourcesJar(type: Jar, dependsOn: classes) {
  17 + classifier = 'sources'
  18 + from sourceSets.main.allSource
  19 + }
  20 +}
  21 +
  22 +//task javadocJar(type: Jar, dependsOn: javadoc) {
  23 +// classifier = 'javadoc'
  24 +// from javadoc.destinationDir
  25 +//}
  26 +
  27 +artifacts {
  28 +// archives javadocJar
  29 + archives sourcesJar
  30 +}
  31 +
  32 +// Bintray
  33 +//Properties properties = new Properties()
  34 +//properties.load(project.rootProject.file('local.properties').newDataInputStream())
  35 +
  36 +bintray {
  37 +// user = properties.getProperty("bintray.user")
  38 +// key = properties.getProperty("bintray.apikey")
  39 +
  40 + user = rootProject.ext.user
  41 + key = rootProject.ext.apikey
  42 +
  43 +// user = 'hh-medic'
  44 +// key = 'c3a4fa32ed2a3cd54d736d04307bb86c12c11ff8'
  45 +
  46 + configurations = ['archives']
  47 + pkg {
  48 + repo = rootProject.ext.repo
  49 + name = rootProject.ext.name
  50 + if (rootProject.ext.isCompany) {
  51 + userOrg = "hh-medic"
  52 + }
  53 + desc = rootProject.ext.name
  54 + websiteUrl = rootProject.ext.url
  55 + vcsUrl = rootProject.ext.vcsUrl
  56 + licenses = ["Apache-2.0"]
  57 + publish = true
  58 + }
  59 +}
  1 +import java.text.SimpleDateFormat
  2 +
  3 +apply plugin: 'com.android.library'
  4 +//apply plugin: 'com.jfrog.bintray'
  5 +//apply plugin: 'com.github.dcendents.android-maven'
  6 +
  7 +static def buildTime() {
  8 + def df = new SimpleDateFormat("MMddHHmm")
  9 + return df.format(new Date())
  10 +}
  11 +
  12 +// versionCode按时间自增
  13 +static def increasedVersionCode(){
  14 + return (int)(System.currentTimeMillis()/1000/60)
  15 +}
  16 +
  17 +def baseVersion = "1.1.0"
  18 +
  19 +
  20 +android {
  21 + compileSdkVersion 28
  22 +
  23 + defaultConfig {
  24 + useLibrary 'org.apache.http.legacy'
  25 +// applicationId "com.hhmedic.android.sdk.base"
  26 + minSdkVersion 17
  27 + targetSdkVersion 28
  28 + versionCode increasedVersionCode()
  29 + versionName "${baseVersion}.${buildTime()}"
  30 +
  31 + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  32 + }
  33 +
  34 + buildTypes {
  35 + release {
  36 + minifyEnabled false
  37 +// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  38 + }
  39 +
  40 + debug{
  41 +
  42 + minifyEnabled false
  43 +// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  44 + }
  45 + }
  46 +
  47 +
  48 +
  49 + lintOptions
  50 + {
  51 + checkReleaseBuilds false
  52 + abortOnError false
  53 + }
  54 +
  55 + compileOptions {
  56 + sourceCompatibility JavaVersion.VERSION_1_8
  57 + targetCompatibility JavaVersion.VERSION_1_8
  58 + }
  59 +
  60 +
  61 +}
  62 +
  63 +dependencies {
  64 +
  65 + implementation fileTree(dir: 'libs', include: ['*.jar'])
  66 +
  67 + implementation 'androidx.appcompat:appcompat:1.2.0'
  68 +
  69 + api 'com.google.code.gson:gson:2.8.0'
  70 +
  71 +// implementation 'com.orhanobut:logger:2.2.0'
  72 +}
  73 +
  74 +
  75 +repositories {
  76 + mavenCentral()
  77 + maven {
  78 + credentials {
  79 + username 'hh-public'
  80 + password 'OFGB5wX0'
  81 + }
  82 + url 'http://develop.hh-medic.com/repository/maven-public'
  83 + }
  84 +}
  85 +
  86 +//apply from:'maven-release-aar.gradle'
  87 +apply from:'bintray.gradle'
  88 +apply from:'install.gradle'
  1 +apply plugin: 'com.github.dcendents.android-maven'
  2 +
  3 +group = rootProject.ext.groupId // Maven Group ID for the artifact
  4 +
  5 +install {
  6 + repositories.mavenInstaller {
  7 + // This generates POM.xml with proper parameters
  8 + pom {
  9 + project {
  10 + packaging 'aar'
  11 + groupId rootProject.ext.groupId
  12 + artifactId rootProject.ext.artifactId
  13 +
  14 + // Add your description here
  15 + name rootProject.ext.name
  16 + description rootProject.ext.description
  17 + url rootProject.ext.url
  18 +
  19 + // Set your license
  20 + licenses {
  21 + license {
  22 + name rootProject.ext.license_name
  23 + url rootProject.ext.license_url
  24 + }
  25 + }
  26 + developers {
  27 + developer {
  28 + id rootProject.ext.developer_id
  29 + name rootProject.ext.developer_name
  30 + email rootProject.ext.email
  31 + }
  32 + }
  33 + scm {
  34 + connection rootProject.ext.url
  35 + developerConnection rootProject.ext.url
  36 + url rootProject.ext.url
  37 +
  38 + }
  39 + }
  40 + }
  41 + }
  42 +}
  1 +// 1.maven-插件
  2 +apply plugin: 'maven'
  3 +
  4 +// 2.maven-信息
  5 +//ext {// ext is a gradle closure allowing the declaration of global properties
  6 +// PUBLISH_GROUP_ID = 'com.hhmedic.android.sdk'
  7 +// PUBLISH_ARTIFACT_ID = 'nim'
  8 +// PUBLISH_VERSION = android.defaultConfig.versionName
  9 +//}
  10 +
  11 +def PUBLISH_URL = 'http://develop.hh-medic.com/repository/maven-releases/'
  12 +
  13 +def PUBLISH_GROUP_ID = 'com.hhmedic.android.sdk'
  14 +
  15 +def PUBLISH_ARTIFACT_ID = "base_small"
  16 +
  17 +def PUBLISH_VERSION = android.defaultConfig.versionName
  18 +
  19 +
  20 +// 3.maven-输出路径
  21 +uploadArchives {
  22 +// repositories.mavenDeployer {
  23 +// //这里就是最后输出地址,在自己电脑上新建个文件夹,把文件夹路径粘贴在此
  24 +// //注意”file://“ + 路径,有三个斜杠,别漏了
  25 +// repository(url: "file:///Workspace/Workshop/HHSDKAndroidOutput")
  26 +//
  27 +// pom.project {
  28 +// groupId project.PUBLISH_GROUP_ID
  29 +// artifactId project.PUBLISH_ARTIFACT_ID
  30 +// version project.PUBLISH_VERSION
  31 +// }
  32 +// }
  33 +
  34 +
  35 + repositories{
  36 + mavenDeployer{
  37 + repository(url: PUBLISH_URL) {
  38 + authentication(userName: "hh-user", password: "hi9rqvdR")
  39 + }
  40 +
  41 + pom.groupId = PUBLISH_GROUP_ID
  42 + pom.artifactId = PUBLISH_ARTIFACT_ID
  43 + pom.version = PUBLISH_VERSION
  44 +
  45 + pom.project {
  46 + licenses {
  47 + license {
  48 + name 'The Apache Software License, Version 2.0'
  49 + url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
  50 + }
  51 + }
  52 + }
  53 + }
  54 + }
  55 +}
  56 +
  57 +//以下代码会生成jar包源文件,如果是不开源码,请不要输入这段
  58 +//aar包内包含注释
  59 +//task androidSourcesJar(type: Jar) {
  60 +// classifier = 'sources'
  61 +// from android.sourceSets.main.java.sourceFiles
  62 +//}
  63 +//
  64 +//artifacts {
  65 +// archives androidSourcesJar
  66 +//}
  1 +## Add project specific ProGuard rules here.
  2 +## You can control the set of applied configuration files using the
  3 +## proguardFiles setting in build.gradle.
  4 +##
  5 +## For more details, see
  6 +## http://developer.android.com/guide/developing/tools/proguard.html
  7 +#
  8 +## If your project uses WebView with JS, uncomment the following
  9 +## and specify the fully qualified class name to the JavaScript interface
  10 +## class:
  11 +##-keepclassmembers class fqcn.of.javascript.interface.for.webview {
  12 +## public *;
  13 +##}
  14 +#
  15 +## Uncomment this to preserve the line number information for
  16 +## debugging stack traces.
  17 +##-keepattributes SourceFile,LineNumberTable
  18 +#
  19 +## If you keep the line number information, uncomment this to
  20 +## hide the original source file name.
  21 +##-renamesourcefileattribute SourceFile
  22 +#
  23 +#-ignorewarnings
  24 +#-keepattributes *Annotation*
  25 +#-keepattributes Exceptions
  26 +#-keepattributes InnerClasses
  27 +#-keepattributes Signature
  28 +#-keepattributes SourceFile,LineNumberTable
  29 +#
  30 +#
  31 +##指定代码的压缩级别
  32 +#-optimizationpasses 5
  33 +#
  34 +##包明不混合大小写
  35 +#-dontusemixedcaseclassnames
  36 +#
  37 +##不去忽略非公共的库类
  38 +#-dontskipnonpubliclibraryclasses
  39 +#
  40 +# #优化 不优化输入的类文件
  41 +#-dontoptimize
  42 +#
  43 +# #预校验
  44 +#-dontpreverify
  45 +#
  46 +# #混淆时是否记录日志
  47 +#-verbose
  48 +#
  49 +# # 混淆时所采用的算法
  50 +#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
  51 +#
  52 +##保护注解
  53 +#-keepattributes *Annotation*
  54 +#
  55 +## 保持哪些类不被混淆
  56 +#-keep public class * extends android.app.Fragment
  57 +#-keep public class * extends android.app.Activity
  58 +#-keep public class * extends android.app.Application
  59 +#-keep public class * extends android.app.Service
  60 +#-keep public class * extends android.content.BroadcastReceiver
  61 +#-keep public class * extends android.content.ContentProvider
  62 +#-keep public class * extends android.app.backup.BackupAgentHelper
  63 +#-keep public class * extends android.preference.Preference
  64 +#-keep public class com.android.vending.licensing.ILicensingService
  65 +##如果有引用v4包可以添加下面这行
  66 +#-keep public class * extends android.support.v4.app.Fragment
  67 +#
  68 +#
  69 +###记录生成的日志数据,gradle build时在本项目根目录输出##
  70 +##apk 包内所有 class 的内部结构
  71 +##-dump proguard/class_files.txt
  72 +##未混淆的类和成员
  73 +##-printseeds proguard/seeds.txt
  74 +##列出从 apk 中删除的代码
  75 +##-printusage proguard/unused.txt
  76 +##混淆前后的映射
  77 +##-printmapping proguard/mapping.txt
  78 +#########记录生成的日志数据,gradle build时 在本项目根目录输出-end######
  79 +#
  80 +#
  81 +##如果引用了v4或者v7包
  82 +#-dontwarn android.support.**
  83 +#
  84 +#####混淆保护自己项目的部分代码以及引用的第三方jar包library-end####
  85 +#
  86 +#
  87 +#
  88 +##保持 native 方法不被混淆
  89 +#-keepclasseswithmembernames class * {
  90 +# native <methods>;
  91 +#}
  92 +#
  93 +##保持自定义控件类不被混淆
  94 +#-keepclasseswithmembers class * {
  95 +# public <init>(android.content.Context, android.util.AttributeSet);
  96 +#}
  97 +#
  98 +##保持自定义控件类不被混淆
  99 +#-keepclassmembers class * extends android.app.Activity {
  100 +# public void *(android.view.View);
  101 +#}
  102 +#
  103 +#-keep public class * extends android.view.View {
  104 +# public <init>(android.content.Context);
  105 +# public <init>(android.content.Context, android.util.AttributeSet);
  106 +# public <init>(android.content.Context, android.util.AttributeSet, int);
  107 +# public void set*(...);
  108 +#}
  109 +#
  110 +##保持 Parcelable 不被混淆
  111 +#-keep class * implements android.os.Parcelable {
  112 +# public static final android.os.Parcelable$Creator *;
  113 +#}
  114 +#
  115 +##保持 Serializable 不被混淆
  116 +#-keepnames class * implements java.io.Serializable
  117 +#
  118 +##保持 Serializable 不被混淆并且enum 类也不被混淆
  119 +#-keepclassmembers class * implements java.io.Serializable {
  120 +# static final long serialVersionUID;
  121 +# private static final java.io.ObjectStreamField[] serialPersistentFields;
  122 +# !static !transient <fields>;
  123 +# !private <fields>;
  124 +# !private <methods>;
  125 +# private void writeObject(java.io.ObjectOutputStream);
  126 +# private void readObject(java.io.ObjectInputStream);
  127 +# java.lang.Object writeReplace();
  128 +# java.lang.Object readResolve();
  129 +#}
  130 +#
  131 +##保持枚举 enum 类不被混淆
  132 +#-keepclassmembers enum * {
  133 +# public static **[] values();
  134 +# public static ** valueOf(java.lang.String);
  135 +#}
  136 +#
  137 +#-keepclassmembers class * {
  138 +# public void *ButtonClicked(android.view.View);
  139 +#}
  140 +#
  141 +##不混淆资源类
  142 +#-keepclassmembers class **.R$* {
  143 +# public static <fields>;
  144 +#}
  145 +#
  146 +#-keep interface * {
  147 +# <methods>;
  148 +#}
  149 +#
  150 +#-keep public class * extends android.app.Dialog
  151 +#
  152 +#
  153 +#
  154 +#
  155 +##-dontwarn com.xiaomi.push.**
  156 +##-keep class com.xiaomi.** {*;}
  157 +##-keep class org.apache.** {*;}
  158 +##-keep class com.google.** {*;}
  159 +##-dontnote com.xiaomi.**
  160 +#
  161 +#
  162 +#-dontwarn com.bumptech.glide.**
  163 +#
  164 +#-dontwarn java.lang.invoke.**
  165 +#
  166 +#-dontnote org.apache.http.**
  167 +#-dontnote android.net.http.**
  168 +#
  169 +#-dontnote android.os.**
  170 +#-dontnote com.android.internal.**
  171 +#-dontnote android.view.**
  172 +#
  173 +#
  174 +#
  175 +#-keep class com.hhmedic.android.sdk.base.utils.** {*;}
  176 +#-keep class com.hhmedic.android.sdk.base.net.HHNetErrorHelper {*;}
  177 +#-keep class com.hhmedic.android.sdk.base.net.HHSecurityInfo {*;}
  178 +#
  179 +#-keep class com.hhmedic.android.sdk.base.BaseConfig {*;}
  180 +#
  181 +#
  182 +#-keep class com.hhmedic.android.sdk.base.net.dns.* {*;}
  183 +#-keep class com.hhmedic.android.sdk.base.net.open.* {*;}
  184 +#-keep class com.hhmedic.android.sdk.base.controller.** {*;}
  185 +#-keep class com.hhmedic.android.sdk.base.net.HHNetApplicationConfig {*;}
  186 +#-keep class com.hhmedic.android.sdk.base.user.Caches {*;}
  187 +#-keep class com.hhmedic.android.sdk.base.user.UserExtension {*;}
  188 +#-keep class com.hhmedic.android.sdk.base.user.HHUser {*;}
  189 +#-keep class com.hhmedic.android.sdk.base.net.HHRequestQueue {*;}
  190 +#
  191 +#-keep class com.hhmedic.android.sdk.base.net.volley.*{*;}
  192 +#-keep class com.hhmedic.android.sdk.base.net.volley.toolbox.*{*;}
  193 +#-keep class com.hhmedic.android.sdk.base.net.ErrorCode{*;}
  194 +#-keep class com.hhmedic.android.sdk.base.net.HHNetConfig{*;}
  195 +#-keep class com.hhmedic.android.sdk.base.net.HHNetConstants{*;}
  196 +#
  197 +#-dontwarn okio.**
  198 +#-keep class okhttp3.**{*;}
  199 +#-keep class okio.**{*;}
  200 +#-keep class com.zhy.http.**{*;}
  201 +#-keep class com.alexvasilkov.**{*;}
  202 +#-keep class com.bumptech.glide.**{*;}
  203 +#-keep class android.arch.**{*;}
  204 +#-keep class com.google.gson.**{*;}
  205 +#
  206 +#-dontnote com.bumptech.glide.**
  207 +#-dontnote com.google.gson.**
  208 +#-dontnote okhttp3.internal.**
  209 +#-dontnote okhttp3.**
  210 +#-dontnote okio.**
  211 +#
  212 +#-keepattributes *Annotation*
  213 +#-keep @**annotation** class * {*;}
  214 +#
  215 +#
  216 +#-dontnote com.ut.**
  217 +#-dontnote android.net.**
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3 + package="com.hhmedic.android.sdk.base">
  4 +
  5 +
  6 +
  7 +</manifest>
  1 +package com.hhmedic.android.sdk.base;
  2 +
  3 +import android.os.Build;
  4 +import android.text.TextUtils;
  5 +
  6 +import java.util.UUID;
  7 +
  8 +public class BaseConfig {
  9 +
  10 +
  11 + public static boolean isTest = false;
  12 +
  13 + public static boolean canPrintLog = false;
  14 +
  15 + public static boolean isDebug = false;
  16 +
  17 + private static String DEVICE_ID;
  18 +
  19 + private static String mPId;
  20 +
  21 + private static String mCoopId;
  22 +
  23 + private static String mHardwareId;
  24 +
  25 + private static String mSdkVersion;
  26 +
  27 + private static String mAppVersion;
  28 +
  29 + static {
  30 +
  31 + DEVICE_ID = getUniqueID();
  32 + }
  33 +
  34 +
  35 + public static String getPid(){
  36 +
  37 + if (TextUtils.isEmpty(mPId)){
  38 +
  39 + mPId = "3001";
  40 + }
  41 +
  42 + return mPId;
  43 + }
  44 +
  45 +
  46 + public static String getCoopId(){
  47 +
  48 + if (TextUtils.isEmpty(mCoopId)){
  49 +
  50 + mCoopId = "coopId";
  51 + }
  52 +
  53 + return mCoopId;
  54 + }
  55 +
  56 +
  57 +
  58 +
  59 + public static String getDeviceId(){
  60 +
  61 + return DEVICE_ID;
  62 + }
  63 +
  64 +
  65 + public static String getHardwareId(){
  66 +
  67 + return mHardwareId;
  68 + }
  69 +
  70 +
  71 +
  72 + public static void setPid(String pid) {
  73 +
  74 + mPId = pid;
  75 + }
  76 +
  77 + public static void setHardwareId(String id){
  78 +
  79 + mHardwareId = id;
  80 + }
  81 +
  82 + public static void setCoopId(String id) {
  83 +
  84 + mCoopId = id;
  85 + }
  86 +
  87 +
  88 + public static void setSdkVersion(String version){
  89 +
  90 + mSdkVersion = version;
  91 + }
  92 +
  93 +
  94 + public static void setAppVersion(String version){
  95 +
  96 + mAppVersion = version;
  97 + }
  98 +
  99 +
  100 + public static String getAppVersion(){
  101 +
  102 + if (TextUtils.isEmpty(mAppVersion)){
  103 +
  104 + return getSdkVersion();
  105 + }
  106 +
  107 + return mAppVersion;
  108 +
  109 + }
  110 +
  111 +
  112 + public static String getSdkVersion(){
  113 +
  114 + if (TextUtils.isEmpty(mSdkVersion)){
  115 +
  116 + return "2.6.0";
  117 +
  118 + }
  119 +
  120 + return mSdkVersion;
  121 + }
  122 +
  123 +
  124 + private static String getUniqueID()
  125 + {
  126 + // If all else fails, if the user does have lower than API 9 (lower
  127 + // than Gingerbread), has reset their device or 'Secure.ANDROID_ID'
  128 + // returns 'null', then simply the ID returned will be solely based
  129 + // off their Android device information. This is where the collisions
  130 + // can happen.
  131 + // Thanks http://www.pocketmagic.net/?p=1662!
  132 + // Try not to use DISPLAY, HOST or ID - these items could change.
  133 + // If there are collisions, there will be overlapping data
  134 + String m_szDevIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10) + (Build.CPU_ABI.length() % 10) + (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
  135 +
  136 + // Thanks to @Roman SL!
  137 + // http://stackoverflow.com/a/4789483/950427
  138 + // Only devices with API >= 9 have android.os.Build.SERIAL
  139 + // http://developer.android.com/reference/android/os/Build.html#SERIAL
  140 + // If a user upgrades software or roots their device, there will be a duplicate entry
  141 + String serial = null;
  142 + try {
  143 + serial = Build.class.getField("SERIAL").get(null).toString();
  144 +
  145 + // Go ahead and return the serial for api => 9
  146 + return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
  147 + } catch (Exception exception) {
  148 + // String needs to be initialized
  149 + serial = "serial"; // some value
  150 + }
  151 +
  152 + // Thanks @Joe!
  153 + // http://stackoverflow.com/a/2853253/950427
  154 + // Finally, combine the values we have found by using the UUID class to create a unique identifier
  155 + return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
  156 + }
  157 +
  158 +
  159 +}
  1 +package com.hhmedic.android.sdk.base.utils;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.Context;
  5 +
  6 +public class HHActivityCompat {
  7 +
  8 + public static boolean isDead(Context context) {
  9 +
  10 + if (context == null) {
  11 + return true;
  12 + }
  13 + if (context instanceof Activity) {
  14 + Activity activity = (Activity)context;
  15 + if (activity.isFinishing() || activity.isDestroyed()) {
  16 + return true;
  17 + }
  18 + }
  19 + return false;
  20 + }
  21 +}
  1 +package com.hhmedic.android.sdk.base.utils;
  2 +
  3 +import android.text.TextUtils;
  4 +
  5 +
  6 +import java.text.ParseException;
  7 +import java.text.SimpleDateFormat;
  8 +import java.util.Calendar;
  9 +import java.util.Date;
  10 +import java.util.HashMap;
  11 +import java.util.Map;
  12 +
  13 +/**
  14 + * Created by iOS on 2017/2/16.
  15 + *
  16 + */
  17 +
  18 +public class HHDateUtils
  19 +{
  20 +
  21 +
  22 + public static final String MONTH = "month";
  23 +
  24 + public static final String DAY = "day";
  25 +
  26 + private static final String NORMAL_FORMAT = "yyyy-MM-dd HH:mm";
  27 +
  28 + private static final String DATE_FORMAT = "yyyy-MM-dd";
  29 +
  30 + public static final String DATE_FORMAT_ALL = "yyyy-MM-dd HH:mm:ss";
  31 +
  32 + public static final String DATE_FORMAT_NO_SP = "yyyyMMdd";
  33 +
  34 + public static final String CHINA_MONTH = "MM月dd日";
  35 +
  36 + public static String formatTime(long time)
  37 + {
  38 + return formatTime(time,NORMAL_FORMAT);
  39 + }
  40 +
  41 +
  42 + public static String formatDay(long time)
  43 + {
  44 + return formatTime(time,DATE_FORMAT);
  45 + }
  46 +
  47 + public static String formatDay(Date date)
  48 + {
  49 + return formatDay(date,DATE_FORMAT);
  50 + }
  51 +
  52 + private HHDateUtils()
  53 + {
  54 +
  55 + }
  56 +
  57 + public static String formatDay(Date date,String formart)
  58 + {
  59 + if (date == null)
  60 + {
  61 + return "";
  62 + }
  63 +
  64 + return formatDate(date,formart);
  65 + }
  66 +
  67 + public static String formatTime(long time, String formatStr)
  68 + {
  69 +// if (time <=0)
  70 +// {
  71 +// return null;
  72 +// }
  73 +
  74 + SimpleDateFormat format = new SimpleDateFormat(formatStr);
  75 +
  76 + return format.format(new Date(time));
  77 + }
  78 +
  79 +
  80 + public static String formatDate(Date date, String formatStr)
  81 + {
  82 + if (date ==null)
  83 + {
  84 + return null;
  85 + }
  86 +
  87 + SimpleDateFormat format = new SimpleDateFormat(formatStr);
  88 +
  89 + return format.format(date);
  90 + }
  91 +
  92 +
  93 +
  94 +
  95 + public static String formatTimeFromLong(long time)
  96 + {
  97 + long se = time /1000;
  98 +
  99 + long m = se/60;
  100 +
  101 + long la = se%60;
  102 +
  103 +
  104 + String split = la < 10 ? "0" :"";
  105 +
  106 + if (m>0)
  107 + {
  108 + return m + ":" + split +la;
  109 + }
  110 + else
  111 + {
  112 + return "0:" + split +la;
  113 + }
  114 +
  115 + }
  116 +
  117 +
  118 +
  119 + public static long timeStr2Long(String time)
  120 + {
  121 + return timeStr2Long(time,DATE_FORMAT);
  122 +
  123 + }
  124 +
  125 +
  126 + public static long timeStr2Long(String time,String formatStr)
  127 + {
  128 + if (TextUtils.isEmpty(time))
  129 + {
  130 + return 0;
  131 + }
  132 +
  133 + SimpleDateFormat format = new SimpleDateFormat(formatStr);
  134 +
  135 + try
  136 + {
  137 + Date date = format.parse(time);
  138 +
  139 + return date.getTime();
  140 + }
  141 + catch (ParseException e)
  142 + {
  143 + Logger.e(e.getMessage());
  144 + }
  145 +
  146 +
  147 + return 0;
  148 +
  149 + }
  150 +
  151 +
  152 +
  153 + public static Date str2Date(String time)
  154 + {
  155 + if (TextUtils.isEmpty(time))
  156 + {
  157 + return null;
  158 + }
  159 +
  160 + SimpleDateFormat format = new SimpleDateFormat(NORMAL_FORMAT);
  161 +
  162 + try
  163 + {
  164 + return format.parse(time);
  165 + }
  166 + catch (ParseException e)
  167 + {
  168 + e.printStackTrace();
  169 + }
  170 +
  171 + return null;
  172 +
  173 +
  174 + }
  175 +
  176 +
  177 +
  178 + public static String parseTime(Date date)
  179 + {
  180 + return parseTime(date,"HH时mm分");
  181 + }
  182 +
  183 + public static String parseNormal(Date date)
  184 + {
  185 + return parseTime(date,"HH:mm");
  186 + }
  187 +
  188 + private static String parseTime(Date date, String formatStr)
  189 + {
  190 + SimpleDateFormat format = new SimpleDateFormat(formatStr);
  191 +
  192 + return format.format(date);
  193 + }
  194 +
  195 +
  196 +
  197 + public static Map<String,String> formart(Date date)
  198 + {
  199 +
  200 + HashMap<String,String> result = new HashMap<>();
  201 +
  202 + Calendar cal = Calendar.getInstance();
  203 +
  204 + cal.setTime(date);
  205 +
  206 +
  207 + int month = cal.get(Calendar.MONTH) + 1;
  208 +
  209 + String mStr = String.valueOf(month);
  210 +
  211 + if (month <10)
  212 + {
  213 + mStr = "0"+mStr;
  214 + }
  215 +
  216 + result.put(MONTH,(mStr+"月"));
  217 +
  218 + result.put(DAY,String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));
  219 +
  220 + return result;
  221 + }
  222 +}
  1 +package com.hhmedic.android.sdk.base.utils;
  2 +
  3 +import android.content.Context;
  4 +import android.os.Environment;
  5 +
  6 +import java.io.File;
  7 +import java.io.IOException;
  8 +
  9 +/**
  10 + * Created by iOS on 2017/8/15.
  11 + *
  12 + */
  13 +
  14 +public class HHDirUtils
  15 +{
  16 +
  17 + private static final String TEMP = "temp";
  18 +
  19 + public static String getTempPath(Context context,String name)
  20 + {
  21 +
  22 + String dir = getCacheDir(context,TEMP);
  23 +
  24 +
  25 + return dir + File.separator + name;
  26 +
  27 + }
  28 +
  29 +
  30 +
  31 + private static String getCacheDir(Context context, String dir)
  32 + {
  33 +
  34 + File cacheDir = getCacheDirectory(context);
  35 +
  36 + String path = cacheDir.getAbsolutePath() + File.separator +dir;
  37 +
  38 + File file = new File(path);
  39 +
  40 + if (!file.exists())
  41 + {
  42 + file.mkdir();
  43 + }
  44 +
  45 + return path;
  46 +
  47 + }
  48 +
  49 +
  50 + private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";
  51 + private static final String INDIVIDUAL_DIR_NAME = "uil-images";
  52 +
  53 +
  54 + public static File getCacheDirectory(Context context) {
  55 + return getCacheDirectory(context, true);
  56 + }
  57 +
  58 + public static File getCacheDirectory(Context context, boolean preferExternal) {
  59 + File appCacheDir = null;
  60 +
  61 + String externalStorageState;
  62 + try {
  63 + externalStorageState = Environment.getExternalStorageState();
  64 + } catch (NullPointerException var5) {
  65 + externalStorageState = "";
  66 + } catch (IncompatibleClassChangeError var6) {
  67 + externalStorageState = "";
  68 + }
  69 +
  70 + if(preferExternal && "mounted".equals(externalStorageState) && hasExternalStoragePermission(context)) {
  71 + appCacheDir = getExternalCacheDir(context);
  72 + }
  73 +
  74 + if(appCacheDir == null) {
  75 + appCacheDir = context.getCacheDir();
  76 + }
  77 +
  78 + if(appCacheDir == null) {
  79 + String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/";
  80 + appCacheDir = new File(cacheDirPath);
  81 + }
  82 +
  83 + return appCacheDir;
  84 + }
  85 +
  86 + public static File getIndividualCacheDirectory(Context context) {
  87 + return getIndividualCacheDirectory(context, "uil-images");
  88 + }
  89 +
  90 + public static File getIndividualCacheDirectory(Context context, String cacheDir) {
  91 + File appCacheDir = getCacheDirectory(context);
  92 + File individualCacheDir = new File(appCacheDir, cacheDir);
  93 + if(!individualCacheDir.exists() && !individualCacheDir.mkdir()) {
  94 + individualCacheDir = appCacheDir;
  95 + }
  96 +
  97 + return individualCacheDir;
  98 + }
  99 +
  100 + public static File getOwnCacheDirectory(Context context, String cacheDir) {
  101 + File appCacheDir = null;
  102 + if("mounted".equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
  103 + appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir);
  104 + }
  105 +
  106 + if(appCacheDir == null || !appCacheDir.exists() && !appCacheDir.mkdirs()) {
  107 + appCacheDir = context.getCacheDir();
  108 + }
  109 +
  110 + return appCacheDir;
  111 + }
  112 +
  113 + public static File getOwnCacheDirectory(Context context, String cacheDir, boolean preferExternal) {
  114 + File appCacheDir = null;
  115 + if(preferExternal && "mounted".equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
  116 + appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir);
  117 + }
  118 +
  119 + if(appCacheDir == null || !appCacheDir.exists() && !appCacheDir.mkdirs()) {
  120 + appCacheDir = context.getCacheDir();
  121 + }
  122 +
  123 + return appCacheDir;
  124 + }
  125 +
  126 + private static File getExternalCacheDir(Context context) {
  127 + File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
  128 + File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
  129 + if(!appCacheDir.exists()) {
  130 + if(!appCacheDir.mkdirs()) {
  131 + return null;
  132 + }
  133 +
  134 + try {
  135 + (new File(appCacheDir, ".nomedia")).createNewFile();
  136 + } catch (IOException var4) {
  137 + }
  138 + }
  139 +
  140 + return appCacheDir;
  141 + }
  142 +
  143 + private static boolean hasExternalStoragePermission(Context context) {
  144 + int perm = context.checkCallingOrSelfPermission("android.permission.WRITE_EXTERNAL_STORAGE");
  145 + return perm == 0;
  146 + }
  147 +}
  1 +package com.hhmedic.android.sdk.base.utils;
  2 +
  3 +import androidx.core.content.FileProvider;
  4 +
  5 +public class HHFileProvider extends FileProvider {
  6 +}
  1 +package com.hhmedic.android.sdk.base.utils;
  2 +
  3 +import android.content.ContentUris;
  4 +import android.content.Context;
  5 +import android.database.Cursor;
  6 +import android.graphics.Bitmap;
  7 +import android.net.Uri;
  8 +import android.os.Build;
  9 +import android.os.Environment;
  10 +import android.provider.DocumentsContract;
  11 +import android.provider.MediaStore;
  12 +import android.view.View;
  13 +
  14 +
  15 +import java.io.ByteArrayOutputStream;
  16 +import java.io.File;
  17 +import java.io.FileOutputStream;
  18 +import java.io.IOException;
  19 +
  20 +/**
  21 + * Created by iOS on 2016/11/25.
  22 + *
  23 + *
  24 + */
  25 +
  26 +public class HHImageUtils
  27 +{
  28 + public static Bitmap getCacheBitmapFromView(View view)
  29 + {
  30 + final boolean drawingCacheEnabled = true;
  31 +
  32 + view.setDrawingCacheEnabled(drawingCacheEnabled);
  33 +
  34 + view.buildDrawingCache(drawingCacheEnabled);
  35 +
  36 + final Bitmap drawingCache = view.getDrawingCache();
  37 +
  38 + Bitmap bitmap;
  39 +
  40 + if (drawingCache != null)
  41 + {
  42 + bitmap = Bitmap.createBitmap(drawingCache);
  43 +
  44 + view.setDrawingCacheEnabled(false);
  45 + }
  46 +
  47 + else
  48 + {
  49 + bitmap = null;
  50 + }
  51 +
  52 +
  53 + return bitmap;
  54 + }
  55 +
  56 +
  57 + /**
  58 + * uri转换
  59 + *
  60 + * @param contentURI path
  61 + * @return path
  62 + */
  63 + public static String convertUri(Uri contentURI, Context context)
  64 + {
  65 + try
  66 + {
  67 +
  68 + Logger.e(contentURI.toString());
  69 +
  70 + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
  71 +
  72 + // DocumentProvider
  73 + if (isKitKat && DocumentsContract.isDocumentUri(context, contentURI)) {
  74 + // ExternalStorageProvider
  75 + if (isExternalStorageDocument(contentURI)) {
  76 + final String docId = DocumentsContract.getDocumentId(contentURI);
  77 + final String[] split = docId.split(":");
  78 + final String type = split[0];
  79 +
  80 + if ("primary".equalsIgnoreCase(type)) {
  81 + return Environment.getExternalStorageDirectory() + "/" + split[1];
  82 + }
  83 +
  84 +
  85 + }
  86 + // DownloadsProvider
  87 + else if (isDownloadsDocument(contentURI)) {
  88 +
  89 + final String id = DocumentsContract.getDocumentId(contentURI);
  90 + final Uri contentUri = ContentUris.withAppendedId(
  91 + Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
  92 +
  93 + return getDataColumn(context, contentUri, null, null);
  94 + }
  95 + // MediaProvider
  96 + else if (isMediaDocument(contentURI)) {
  97 + final String docId = DocumentsContract.getDocumentId(contentURI);
  98 + final String[] split = docId.split(":");
  99 + final String type = split[0];
  100 +
  101 + Uri contentUri = null;
  102 + if ("image".equals(type)) {
  103 + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
  104 + } else if ("video".equals(type)) {
  105 + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
  106 + } else if ("audio".equals(type)) {
  107 + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
  108 + }
  109 +
  110 + final String selection = "_id=?";
  111 + final String[] selectionArgs = new String[] {
  112 + split[1]
  113 + };
  114 +
  115 + return getDataColumn(context, contentUri, selection, selectionArgs);
  116 + }
  117 + }
  118 +
  119 +
  120 + String result;
  121 + Cursor cursor = context.getContentResolver().query(contentURI, null, null, null, null);
  122 + if (cursor == null)
  123 + {
  124 + // Source is Dropbox or other similar local file path
  125 + result = contentURI.getPath();
  126 + }
  127 + else
  128 + {
  129 + cursor.moveToFirst();
  130 + int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
  131 + result = cursor.getString(idx);
  132 + cursor.close();
  133 + }
  134 +
  135 + return result;
  136 + }
  137 + catch (Exception e)
  138 + {
  139 + e.printStackTrace();
  140 + }
  141 +
  142 + return null;
  143 +
  144 + }
  145 +
  146 +
  147 + private static String getDataColumn(Context context, Uri uri, String selection,
  148 + String[] selectionArgs) {
  149 +
  150 + Cursor cursor = null;
  151 + final String column = "_data";
  152 + final String[] projection = {
  153 + column
  154 + };
  155 +
  156 + try {
  157 + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
  158 + null);
  159 + if (cursor != null && cursor.moveToFirst()) {
  160 + final int column_index = cursor.getColumnIndexOrThrow(column);
  161 + return cursor.getString(column_index);
  162 + }
  163 + } finally {
  164 + if (cursor != null)
  165 + cursor.close();
  166 + }
  167 + return null;
  168 + }
  169 +
  170 +
  171 +
  172 + private static boolean isExternalStorageDocument(Uri uri) {
  173 + return "com.android.externalstorage.documents".equals(uri.getAuthority());
  174 + }
  175 +
  176 + /**
  177 + * @param uri The Uri to check.
  178 + * @return Whether the Uri authority is DownloadsProvider.
  179 + */
  180 + private static boolean isDownloadsDocument(Uri uri) {
  181 + return "com.android.providers.downloads.documents".equals(uri.getAuthority());
  182 + }
  183 +
  184 + /**
  185 + * @param uri The Uri to check.
  186 + * @return Whether the Uri authority is MediaProvider.
  187 + */
  188 + private static boolean isMediaDocument(Uri uri) {
  189 + return "com.android.providers.media.documents".equals(uri.getAuthority());
  190 + }
  191 +
  192 +
  193 +
  194 +
  195 + public static boolean bitmaoSaveFile(Bitmap image,String filePath)
  196 + {
  197 + File file = new File(filePath);
  198 +
  199 + if (file.exists())
  200 + {
  201 + file.delete();
  202 + }
  203 +
  204 + FileOutputStream out = null;
  205 +
  206 + try
  207 + {
  208 + out = new FileOutputStream(file);
  209 +
  210 + image.compress(Bitmap.CompressFormat.PNG, 90, out);
  211 +
  212 + }
  213 + catch (Exception e)
  214 + {
  215 + e.printStackTrace();
  216 +
  217 + return false;
  218 + }
  219 + finally {
  220 +
  221 + if (out!=null)
  222 + {
  223 + try {
  224 + out.flush();
  225 + out.close();
  226 + } catch (IOException e) {
  227 + e.printStackTrace();
  228 + }
  229 +
  230 + }
  231 + }
  232 +
  233 +
  234 + return true;
  235 +
  236 + }
  237 +
  238 +
  239 +
  240 +
  241 +
  242 + public static byte[] bitmap2byte(Bitmap bitmap)
  243 + {
  244 + if (bitmap == null)
  245 + {
  246 + return null;
  247 + }
  248 +
  249 + ByteArrayOutputStream baos = null;
  250 +
  251 + try
  252 + {
  253 + baos=new ByteArrayOutputStream();
  254 +
  255 + bitmap.compress(Bitmap.CompressFormat.PNG, 50, baos);
  256 +
  257 + byte [] bitmapByte =baos.toByteArray();
  258 +
  259 + return bitmapByte;
  260 + }
  261 + catch (Exception e)
  262 + {
  263 + e.printStackTrace();
  264 + }
  265 + finally {
  266 +
  267 + bitmap.recycle();
  268 +
  269 + if (baos!=null)
  270 + {
  271 + try {
  272 + baos.close();
  273 + } catch (IOException e) {
  274 + e.printStackTrace();
  275 + }
  276 + }
  277 + }
  278 +
  279 + return null;
  280 +
  281 + }
  282 +
  283 +
  284 +
  285 + public static String createImagePath(Context context)
  286 + {
  287 + return HHDirUtils.getTempPath(context,String.valueOf(System.currentTimeMillis())+".jpg");
  288 + }
  289 +
  290 +
  291 +}
  1 +package com.hhmedic.android.sdk.base.utils;
  2 +
  3 +import android.text.Html;
  4 +import android.text.Spanned;
  5 +import android.text.TextUtils;
  6 +import android.util.Base64;
  7 +
  8 +
  9 +import com.hhmedic.android.sdk.base.utils.secret.HHSecretUtils;
  10 +
  11 +import java.io.UnsupportedEncodingException;
  12 +import java.net.URLEncoder;
  13 +import java.util.ArrayList;
  14 +import java.util.Collections;
  15 +import java.util.List;
  16 +import java.util.Map;
  17 +
  18 +/**
  19 + * Created by iOS on 2016/11/3.
  20 + *
  21 + */
  22 +
  23 +public final class HHStringUtils
  24 +{
  25 +
  26 + private static String WHITE_SPACE = " ";
  27 +
  28 + public static String getSHA1(String str)
  29 + {
  30 + return HHSecretUtils.getSHA1(str);
  31 +
  32 + }
  33 +
  34 + public static String createLinkString(Map<String, Object> params,boolean urlEncode)
  35 + {
  36 + List<String> keys = new ArrayList<String>(params.keySet());
  37 +
  38 + Collections.sort(keys);
  39 +
  40 + String prestr = "";
  41 +
  42 + for (int i = 0; i < keys.size(); i++)
  43 + {
  44 + String key = keys.get(i);
  45 +
  46 + if (params.get(key)==null)
  47 + {
  48 + continue;
  49 + }
  50 + String value = params.get(key).toString();
  51 +
  52 + if(urlEncode)
  53 + {
  54 + value = urlEncode(value);
  55 + }
  56 +
  57 + if (i == keys.size() - 1)
  58 + {//拼接时,不包括最后一个&字符
  59 + prestr = prestr + key + "=" + value;
  60 + }
  61 + else
  62 + {
  63 + prestr = prestr + key + "=" + value + "&";
  64 + }
  65 + }
  66 + return prestr;
  67 + }
  68 +
  69 +
  70 + public static String urlEncode(String value)
  71 + {
  72 + try
  73 + {
  74 + value = URLEncoder.encode(value,"UTF-8");
  75 +
  76 + } catch (UnsupportedEncodingException e) {
  77 + Logger.e("urlEncode error:"+e.getLocalizedMessage());
  78 + }
  79 +
  80 + return value;
  81 + }
  82 +
  83 +
  84 +
  85 + private static byte[] getContentBytes(String content, String charset)
  86 + {
  87 + if (TextUtils.isEmpty(charset))
  88 + {
  89 + return content.getBytes();
  90 + }
  91 + try
  92 + {
  93 + return content.getBytes(charset);
  94 + }
  95 + catch (UnsupportedEncodingException e)
  96 + {
  97 + Logger.e("getContentBytes error:"+e.getLocalizedMessage());
  98 + }
  99 +
  100 + return null;
  101 + }
  102 +
  103 +
  104 + public static Spanned formatHtml(String content)
  105 + {
  106 + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N)
  107 + {
  108 + return Html.fromHtml(content,Html.FROM_HTML_MODE_LEGACY);
  109 + }
  110 + else
  111 + {
  112 + return Html.fromHtml(content);
  113 + }
  114 + }
  115 +
  116 +
  117 + public static String base64(String str)
  118 + {
  119 +
  120 + try
  121 + {
  122 + return Base64.encodeToString(str.getBytes("UTF-8"),Base64.NO_WRAP);
  123 + }
  124 + catch (UnsupportedEncodingException e)
  125 + {
  126 + Logger.e("base64 error:"+e.getLocalizedMessage());
  127 + }
  128 +
  129 + return "";
  130 + }
  131 +
  132 +
  133 + public static String base64(byte[] data)
  134 + {
  135 + if (data == null)
  136 + {
  137 + return null;
  138 + }
  139 +
  140 + return Base64.encodeToString(data,Base64.NO_WRAP);
  141 + }
  142 +
  143 +
  144 +
  145 +
  146 +}
  1 +package com.hhmedic.android.sdk.base.utils;
  2 +
  3 +import android.app.Activity;
  4 +import android.app.ActivityManager;
  5 +import android.content.Context;
  6 +import android.text.TextUtils;
  7 +import android.util.DisplayMetrics;
  8 +import android.view.View;
  9 +import android.widget.Toast;
  10 +
  11 +
  12 +/**
  13 + * Created by iOS on 2018/4/11.
  14 + *
  15 + *
  16 + */
  17 +
  18 +public class HHUtils
  19 +{
  20 +
  21 +
  22 +
  23 + private static long lastClickTime;
  24 +
  25 + /// 是否快速连续点击
  26 + public static boolean isFastClick()
  27 + {
  28 + long time = System.currentTimeMillis();
  29 + if (time - lastClickTime < 300) {
  30 + return true;
  31 + }
  32 + lastClickTime = time;
  33 + return false;
  34 + }
  35 +
  36 +
  37 +
  38 + public static float density;
  39 +
  40 + public static int screenWidth;
  41 + public static int screenHeight;
  42 + public static int screenMin;// 宽高中,小的一边
  43 + public static int screenMax;// 宽高中,较大的值
  44 +
  45 +
  46 +
  47 +
  48 + public static void init(Context context) {
  49 + if (null == context) {
  50 + return;
  51 + }
  52 +
  53 + DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics();
  54 +
  55 + screenWidth = dm.widthPixels;
  56 + screenHeight = dm.heightPixels;
  57 + screenMin = (screenWidth > screenHeight) ? screenHeight : screenWidth;
  58 +
  59 + density = dm.density;
  60 + }
  61 +
  62 +
  63 + public static int screenOffset(Activity activity, View globalView) {
  64 + DisplayMetrics dm = new DisplayMetrics();
  65 +
  66 + activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
  67 +
  68 + int topOffset = dm.heightPixels - globalView.getMeasuredHeight();
  69 +
  70 + return Math.abs(topOffset);
  71 + }
  72 +
  73 +
  74 +
  75 + public static int dip2px(float dipValue) {
  76 + return (int) (dipValue * density + 0.5f);
  77 + }
  78 +
  79 +
  80 +
  81 +
  82 +
  83 +
  84 + public static void errorTips(Context context,String tips)
  85 + {
  86 + if (TextUtils.isEmpty(tips) || context == null)
  87 + {
  88 + return;
  89 + }
  90 +
  91 +
  92 + try
  93 + {
  94 + Toast.makeText(context,tips,Toast.LENGTH_LONG).show();
  95 + }
  96 + catch (Exception e)
  97 + {
  98 + Logger.e(e.toString());
  99 + }
  100 + }
  101 +}
  1 +package com.hhmedic.android.sdk.base.utils;
  2 +
  3 +import android.text.TextUtils;
  4 +import android.util.Log;
  5 +
  6 +import com.hhmedic.android.sdk.base.BaseConfig;
  7 +
  8 +public class Logger {
  9 +
  10 +
  11 + public static void e(String tips){
  12 +
  13 + if (!BaseConfig.isDebug){
  14 +
  15 + return;
  16 + }
  17 +
  18 + if (!TextUtils.isEmpty(tips)){
  19 +
  20 + Log.e("HH",tips);
  21 + }
  22 + }
  23 +}
  1 +package com.hhmedic.android.sdk.base.utils;
  2 +
  3 +import java.util.HashMap;
  4 +
  5 +/**
  6 + * Created by iOS on 2018/4/4.
  7 + *
  8 + *
  9 + *
  10 + */
  11 +
  12 +public class Maps
  13 +{
  14 +
  15 +
  16 + public static HashMap<String,Object> of(String k1,Object v1)
  17 + {
  18 + HashMap<String,Object> map = new HashMap<>();
  19 +
  20 + map.put(k1,v1);
  21 +
  22 + return map;
  23 + }
  24 +
  25 +
  26 +
  27 + public static HashMap<String,Object> of(String k1,String v1,String k2,String v2)
  28 + {
  29 + HashMap<String,Object> map = new HashMap<>();
  30 +
  31 + map.put(k1,v1);
  32 +
  33 + map.put(k2,v2);
  34 +
  35 + return map;
  36 + }
  37 +
  38 +
  39 +
  40 + public static HashMap<String,Object> of(String k1,Object v1,String k2,Object v2)
  41 + {
  42 + HashMap<String,Object> map = new HashMap<>();
  43 +
  44 + map.put(k1,v1);
  45 +
  46 + map.put(k2,v2);
  47 +
  48 + return map;
  49 + }
  50 +
  51 +
  52 + public static HashMap<String,Object> of(String k1,String v1,String k2,long v2)
  53 + {
  54 + HashMap<String,Object> map = new HashMap<>();
  55 +
  56 + map.put(k1,v1);
  57 +
  58 + map.put(k2,v2);
  59 +
  60 + return map;
  61 + }
  62 +
  63 + public static HashMap<String,Object> of(String k1,Object v1,String k2,Object v2,String k3,Object v3)
  64 + {
  65 + HashMap<String,Object> map = new HashMap<>();
  66 +
  67 + map.put(k1,v1);
  68 +
  69 + map.put(k2,v2);
  70 +
  71 + map.put(k3,v3);
  72 +
  73 + return map;
  74 + }
  75 +
  76 +
  77 + public static HashMap<String,Object> of(String k1,Object v1,String k2,Object v2,String k3,Object v3,String k4,Object v4)
  78 + {
  79 + HashMap<String,Object> map = new HashMap<>();
  80 +
  81 + map.put(k1,v1);
  82 +
  83 + map.put(k2,v2);
  84 +
  85 + map.put(k3,v3);
  86 +
  87 + map.put(k4,v4);
  88 +
  89 + return map;
  90 + }
  91 +}
  1 +package com.hhmedic.android.sdk.base.utils.cache;
  2 +
  3 +import android.util.Base64;
  4 +
  5 +import com.hhmedic.android.sdk.base.utils.secret.HHDesConfig;
  6 +//
  7 +//
  8 +//import com.hhmedic.android.sdk.base.utils.secret.HHDesConfig;
  9 +//
  10 +//import javax.crypto.Cipher;
  11 +//import javax.crypto.spec.IvParameterSpec;
  12 +//import javax.crypto.spec.SecretKeySpec;
  13 +
  14 +/**
  15 + * Created by iOS on 2017/1/12.
  16 + *
  17 + */
  18 +
  19 +class HHDes
  20 +{
  21 +
  22 + private static byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0};
  23 +
  24 + static String encode(String str) throws Exception
  25 + {
  26 +// IvParameterSpec zeroIv = new IvParameterSpec(iv);
  27 +// SecretKeySpec key = new SecretKeySpec(HHDesConfig.getSIMPLE().getBytes(HHDesConfig.getENCODING()), HHDesConfig.getDES());
  28 +// Cipher cipher = Cipher.getInstance(HHDesConfig.getDES());
  29 +// cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
  30 +// byte[] encryptedData = cipher.doFinal(str.getBytes(HHDesConfig.getENCODING()));
  31 +// return Base64.encodeToString(encryptedData, 1);
  32 +
  33 + return Base64.encodeToString(str.getBytes(HHDesConfig.getENCODING()),1);
  34 + }
  35 +
  36 + static String decode(String str) throws Exception
  37 + {
  38 +// IvParameterSpec zeroIv = new IvParameterSpec(iv);
  39 +// SecretKeySpec key = new SecretKeySpec(HHDesConfig.getSIMPLE().getBytes(HHDesConfig.getENCODING()), HHDesConfig.getDES());
  40 +// Cipher cipher = Cipher.getInstance(HHDesConfig.getDES());
  41 +// cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);
  42 +// byte[] decryptData = cipher.doFinal(Base64.decode(str, 1));
  43 +//
  44 +// return new String(decryptData,HHDesConfig.getENCODING());
  45 +
  46 + return new String(Base64.decode(str, 1), HHDesConfig.getENCODING());
  47 + }
  48 +}
  1 +package com.hhmedic.android.sdk.base.utils.cache;
  2 +
  3 +import android.content.Context;
  4 +import android.content.SharedPreferences;
  5 +import android.text.TextUtils;
  6 +
  7 +import com.hhmedic.android.sdk.base.utils.Logger;
  8 +import com.hhmedic.android.sdk.base.utils.secret.HHSecretUtils;
  9 +
  10 +/**
  11 + * Created by iOS on 2017/1/12.
  12 + *
  13 + */
  14 +
  15 +public class HHSharedPreferences
  16 +{
  17 +
  18 + private static final String COMMON = "hh_common";
  19 +
  20 + private static SharedPreferences mSharedPre;
  21 +
  22 +
  23 + public static void init(Context context)
  24 + {
  25 + initShared(context,COMMON);
  26 + }
  27 +
  28 +
  29 + public static void check(Context context)
  30 + {
  31 + if (mSharedPre == null)
  32 + {
  33 + init(context);
  34 + }
  35 + }
  36 +
  37 +
  38 + public static void putString(String key,String value)
  39 + {
  40 + try
  41 + {
  42 + mSharedPre.edit().putString(HHSecretUtils.getSHA1(key), HHDes.encode(value)).apply();
  43 + }
  44 + catch (Exception e)
  45 + {
  46 + Logger.e(e.toString());
  47 + }
  48 +
  49 + }
  50 +
  51 +
  52 + private static void initShared(Context context,String nameSpace)
  53 + {
  54 + mSharedPre = context.getSharedPreferences(HHSecretUtils.getSHA1(nameSpace),Context.MODE_PRIVATE);
  55 + }
  56 +
  57 +
  58 +
  59 + public static String getValue(String key)
  60 + {
  61 + return getValue(COMMON,key);
  62 + }
  63 +
  64 + public static String getValue(String nameSpace,String key)
  65 + {
  66 + try
  67 + {
  68 + SharedPreferences shared = mSharedPre;
  69 +
  70 + String content = shared.getString(HHSecretUtils.getSHA1(key),"");
  71 +
  72 + if (TextUtils.isEmpty(content))
  73 + {
  74 + return "";
  75 + }
  76 +
  77 + return HHDes.decode(content);
  78 + }
  79 + catch (Exception e)
  80 + {
  81 + Logger.e(e.toString());
  82 + }
  83 +
  84 + return "";
  85 + }
  86 +
  87 +
  88 +
  89 + public static void clear()
  90 + {
  91 + if (mSharedPre !=null)
  92 + {
  93 + mSharedPre.edit().clear().apply();
  94 + }
  95 + }
  96 +
  97 +
  98 + public static void removeKey(String key)
  99 + {
  100 + if (mSharedPre != null && !TextUtils.isEmpty(key))
  101 + {
  102 + mSharedPre.edit().remove(HHSecretUtils.getSHA1(key)).apply();
  103 + }
  104 + }
  105 +}
  1 +package com.hhmedic.android.sdk.base.utils.luban;
  2 +
  3 +import android.text.TextUtils;
  4 +
  5 +import java.io.File;
  6 +import java.util.ArrayList;
  7 +import java.util.List;
  8 +
  9 +class Checker {
  10 + private static List<String> format = new ArrayList<>();
  11 + private static final String JPG = "jpg";
  12 + private static final String JPEG = "jpeg";
  13 + private static final String PNG = "png";
  14 + private static final String WEBP = "webp";
  15 + private static final String GIF = "gif";
  16 +
  17 + static {
  18 + format.add(JPG);
  19 + format.add(JPEG);
  20 + format.add(PNG);
  21 + format.add(WEBP);
  22 + format.add(GIF);
  23 + }
  24 +
  25 + static boolean isImage(String path) {
  26 + if (TextUtils.isEmpty(path)) {
  27 + return false;
  28 + }
  29 +
  30 + String suffix = path.substring(path.lastIndexOf(".") + 1, path.length());
  31 + return format.contains(suffix.toLowerCase());
  32 + }
  33 +
  34 + static boolean isJPG(String path) {
  35 + if (TextUtils.isEmpty(path)) {
  36 + return false;
  37 + }
  38 +
  39 + String suffix = path.substring(path.lastIndexOf("."), path.length()).toLowerCase();
  40 + return suffix.contains(JPG) || suffix.contains(JPEG);
  41 + }
  42 +
  43 + static String checkSuffix(String path) {
  44 + if (TextUtils.isEmpty(path)) {
  45 + return ".jpg";
  46 + }
  47 +
  48 + return path.substring(path.lastIndexOf("."), path.length());
  49 + }
  50 +
  51 + static boolean isNeedCompress(int leastCompressSize, String path) {
  52 + if (leastCompressSize > 0) {
  53 + File source = new File(path);
  54 + if (!source.exists()) {
  55 + return false;
  56 + }
  57 +
  58 + if (source.length() <= (leastCompressSize << 10)) {
  59 + return false;
  60 + }
  61 + }
  62 + return true;
  63 + }
  64 +}
  1 +package com.hhmedic.android.sdk.base.utils.luban;
  2 +
  3 +import android.graphics.Bitmap;
  4 +import android.graphics.BitmapFactory;
  5 +import android.graphics.Matrix;
  6 +import android.media.ExifInterface;
  7 +
  8 +import java.io.ByteArrayOutputStream;
  9 +import java.io.File;
  10 +import java.io.FileOutputStream;
  11 +import java.io.IOException;
  12 +
  13 +
  14 +/**
  15 + * Responsible for starting compress and managing active and cached resources.
  16 + */
  17 +class Engine {
  18 + private ExifInterface srcExif;
  19 + private String srcImg;
  20 + private File tagImg;
  21 + private int srcWidth;
  22 + private int srcHeight;
  23 +
  24 + Engine(String srcImg, File tagImg) throws IOException {
  25 + if (Checker.isJPG(srcImg)) {
  26 + this.srcExif = new ExifInterface(srcImg);
  27 + }
  28 + this.tagImg = tagImg;
  29 + this.srcImg = srcImg;
  30 +
  31 + BitmapFactory.Options options = new BitmapFactory.Options();
  32 + options.inJustDecodeBounds = true;
  33 + options.inSampleSize = 1;
  34 +
  35 + BitmapFactory.decodeFile(srcImg, options);
  36 + this.srcWidth = options.outWidth;
  37 + this.srcHeight = options.outHeight;
  38 + }
  39 +
  40 + private int computeSize() {
  41 + srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;
  42 + srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;
  43 +
  44 + int longSide = Math.max(srcWidth, srcHeight);
  45 + int shortSide = Math.min(srcWidth, srcHeight);
  46 +
  47 + float scale = ((float) shortSide / longSide);
  48 + if (scale <= 1 && scale > 0.5625) {
  49 + if (longSide < 2000) {
  50 + return 1;
  51 + } else if (longSide >= 2000 && longSide < 4990) {
  52 + return 2;
  53 + } else if (longSide > 4990 && longSide < 10240) {
  54 + return 4;
  55 + } else {
  56 + return longSide / 1280 == 0 ? 1 : longSide / 1280;
  57 + }
  58 + } else if (scale <= 0.5625 && scale > 0.5) {
  59 + return longSide / 1280 == 0 ? 1 : longSide / 1280;
  60 + } else {
  61 + return (int) Math.ceil(longSide / (1280.0 / scale));
  62 + }
  63 + }
  64 +
  65 + private Bitmap rotatingImage(Bitmap bitmap) {
  66 + if (srcExif == null) return bitmap;
  67 +
  68 + Matrix matrix = new Matrix();
  69 + int angle = 0;
  70 + int orientation = srcExif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
  71 + switch (orientation) {
  72 + case ExifInterface.ORIENTATION_ROTATE_90:
  73 + angle = 90;
  74 + break;
  75 + case ExifInterface.ORIENTATION_ROTATE_180:
  76 + angle = 180;
  77 + break;
  78 + case ExifInterface.ORIENTATION_ROTATE_270:
  79 + angle = 270;
  80 + break;
  81 + }
  82 +
  83 + matrix.postRotate(angle);
  84 +
  85 + return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
  86 + }
  87 +
  88 + File compress() throws Exception {
  89 + BitmapFactory.Options options = new BitmapFactory.Options();
  90 + options.inSampleSize = computeSize();
  91 +
  92 + Bitmap tagBitmap = BitmapFactory.decodeFile(srcImg, options);
  93 + ByteArrayOutputStream stream = new ByteArrayOutputStream();
  94 +
  95 + tagBitmap = rotatingImage(tagBitmap);
  96 +
  97 + if (tagBitmap == null)
  98 + {
  99 + tagBitmap = BitmapFactory.decodeFile(srcImg, options);
  100 + }
  101 +
  102 + tagBitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
  103 +
  104 + tagBitmap.recycle();
  105 +
  106 + FileOutputStream fos = new FileOutputStream(tagImg);
  107 + fos.write(stream.toByteArray());
  108 + fos.flush();
  109 + fos.close();
  110 + stream.close();
  111 +
  112 + return tagImg;
  113 + }
  114 +}
  1 +package com.hhmedic.android.sdk.base.utils.luban;
  2 +
  3 +import android.content.Context;
  4 +import android.os.AsyncTask;
  5 +import android.os.Handler;
  6 +import android.os.Looper;
  7 +import android.os.Message;
  8 +import android.text.TextUtils;
  9 +import android.util.Log;
  10 +
  11 +import androidx.annotation.Nullable;
  12 +import androidx.annotation.UiThread;
  13 +import androidx.annotation.WorkerThread;
  14 +
  15 +import java.io.File;
  16 +import java.util.ArrayList;
  17 +import java.util.Iterator;
  18 +import java.util.List;
  19 +
  20 +
  21 +public class Luban implements Handler.Callback {
  22 + private static final String TAG = "Luban";
  23 + private static final String DEFAULT_DISK_CACHE_DIR = "luban_disk_cache";
  24 +
  25 + private static final int MSG_COMPRESS_SUCCESS = 0;
  26 + private static final int MSG_COMPRESS_START = 1;
  27 + private static final int MSG_COMPRESS_ERROR = 2;
  28 +
  29 + private String mTargetDir;
  30 + private List<String> mPaths;
  31 + private int mLeastCompressSize;
  32 + private OnCompressListener mCompressListener;
  33 +
  34 + private Handler mHandler;
  35 +
  36 + private Luban(Builder builder) {
  37 + this.mPaths = builder.mPaths;
  38 + this.mTargetDir = builder.mTargetDir;
  39 + this.mCompressListener = builder.mCompressListener;
  40 + this.mLeastCompressSize = builder.mLeastCompressSize;
  41 + mHandler = new Handler(Looper.getMainLooper(), this);
  42 + }
  43 +
  44 + public static Builder with(Context context) {
  45 + return new Builder(context);
  46 + }
  47 +
  48 + /**
  49 + * Returns a mFile with a cache audio name in the private cache directory.
  50 + *
  51 + * @param context
  52 + * A context.
  53 + */
  54 + private File getImageCacheFile(Context context, String suffix) {
  55 + if (TextUtils.isEmpty(mTargetDir)) {
  56 + mTargetDir = getImageCacheDir(context).getAbsolutePath();
  57 + }
  58 +
  59 + String cacheBuilder = mTargetDir + "/" +
  60 + System.currentTimeMillis() +
  61 + (int) (Math.random() * 1000) +
  62 + (TextUtils.isEmpty(suffix) ? ".jpg" : suffix);
  63 +
  64 + return new File(cacheBuilder);
  65 + }
  66 +
  67 + /**
  68 + * Returns a directory with a default name in the private cache directory of the application to
  69 + * use to store retrieved audio.
  70 + *
  71 + * @param context
  72 + * A context.
  73 + *
  74 + * @see #getImageCacheDir(Context, String)
  75 + */
  76 + @Nullable
  77 + private File getImageCacheDir(Context context) {
  78 + return getImageCacheDir(context, DEFAULT_DISK_CACHE_DIR);
  79 + }
  80 +
  81 + /**
  82 + * Returns a directory with the given name in the private cache directory of the application to
  83 + * use to store retrieved media and thumbnails.
  84 + *
  85 + * @param context
  86 + * A context.
  87 + * @param cacheName
  88 + * The name of the subdirectory in which to store the cache.
  89 + *
  90 + * @see #getImageCacheDir(Context)
  91 + */
  92 + @Nullable
  93 + private File getImageCacheDir(Context context, String cacheName) {
  94 + File cacheDir = context.getExternalCacheDir();
  95 + if (cacheDir != null) {
  96 + File result = new File(cacheDir, cacheName);
  97 + if (!result.mkdirs() && (!result.exists() || !result.isDirectory())) {
  98 + // File wasn't able to create a directory, or the result exists but not a directory
  99 + return null;
  100 + }
  101 + return result;
  102 + }
  103 + if (Log.isLoggable(TAG, Log.ERROR)) {
  104 + Log.e(TAG, "default disk cache dir is null");
  105 + }
  106 + return null;
  107 + }
  108 +
  109 + /**
  110 + * start asynchronous compress thread
  111 + */
  112 + @UiThread
  113 + private void launch(final Context context) {
  114 + if (mPaths == null || mPaths.size() == 0 && mCompressListener != null) {
  115 + mCompressListener.onError(new NullPointerException("image file cannot be null"));
  116 + }
  117 +
  118 + Iterator<String> iterator = mPaths.iterator();
  119 + while (iterator.hasNext()) {
  120 + final String path = iterator.next();
  121 + if (Checker.isImage(path)) {
  122 + AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() {
  123 + @Override public void run() {
  124 + try {
  125 + mHandler.sendMessage(mHandler.obtainMessage(MSG_COMPRESS_START));
  126 +
  127 + File result = Checker.isNeedCompress(mLeastCompressSize, path) ?
  128 + new Engine(path, getImageCacheFile(context, Checker.checkSuffix(path))).compress() :
  129 + new File(path);
  130 +
  131 + mHandler.sendMessage(mHandler.obtainMessage(MSG_COMPRESS_SUCCESS, result));
  132 + } catch (Exception e) {
  133 + mHandler.sendMessage(mHandler.obtainMessage(MSG_COMPRESS_ERROR, e));
  134 + }
  135 + }
  136 + });
  137 + } else {
  138 + mCompressListener.onError(new IllegalArgumentException("can not read the path : " + path));
  139 + }
  140 + iterator.remove();
  141 + }
  142 + }
  143 +
  144 + /**
  145 + * start compress and return the mFile
  146 + */
  147 + @WorkerThread
  148 + private File get(String path, Context context) throws Exception {
  149 + return new Engine(path, getImageCacheFile(context, Checker.checkSuffix(path))).compress();
  150 + }
  151 +
  152 + @WorkerThread private List<File> get(Context context) throws Exception {
  153 + List<File> results = new ArrayList<>();
  154 + Iterator<String> iterator = mPaths.iterator();
  155 +
  156 + while (iterator.hasNext()) {
  157 + String path = iterator.next();
  158 + if (Checker.isImage(path)) {
  159 + results.add(new Engine(path, getImageCacheFile(context, Checker.checkSuffix(path))).compress());
  160 + }
  161 + iterator.remove();
  162 + }
  163 +
  164 + return results;
  165 + }
  166 +
  167 + @Override
  168 + public boolean handleMessage(Message msg) {
  169 + if (mCompressListener == null) return false;
  170 +
  171 + switch (msg.what) {
  172 + case MSG_COMPRESS_START:
  173 + mCompressListener.onStart();
  174 + break;
  175 + case MSG_COMPRESS_SUCCESS:
  176 + mCompressListener.onSuccess((File) msg.obj);
  177 + break;
  178 + case MSG_COMPRESS_ERROR:
  179 + mCompressListener.onError((Throwable) msg.obj);
  180 + break;
  181 + }
  182 + return false;
  183 + }
  184 +
  185 + public static class Builder {
  186 + private Context context;
  187 + private String mTargetDir;
  188 + private List<String> mPaths;
  189 + private int mLeastCompressSize = 100;
  190 + private OnCompressListener mCompressListener;
  191 +
  192 + Builder(Context context) {
  193 + this.context = context;
  194 + this.mPaths = new ArrayList<>();
  195 + }
  196 +
  197 + private Luban build() {
  198 + return new Luban(this);
  199 + }
  200 +
  201 + public Builder load(File file) {
  202 + this.mPaths.add(file.getAbsolutePath());
  203 + return this;
  204 + }
  205 +
  206 + public Builder load(String string) {
  207 + this.mPaths.add(string);
  208 + return this;
  209 + }
  210 +
  211 + public Builder load(List<String> list) {
  212 + this.mPaths.addAll(list);
  213 + return this;
  214 + }
  215 +
  216 + public Builder putGear(int gear) {
  217 + return this;
  218 + }
  219 +
  220 + public Builder setCompressListener(OnCompressListener listener) {
  221 + this.mCompressListener = listener;
  222 + return this;
  223 + }
  224 +
  225 + public Builder setTargetDir(String targetDir) {
  226 + this.mTargetDir = targetDir;
  227 + return this;
  228 + }
  229 +
  230 + /**
  231 + * do not compress when the origin image file size less than one value
  232 + *
  233 + * @param size
  234 + * the value of file size, unit KB, default 100K
  235 + */
  236 + public Builder ignoreBy(int size) {
  237 + this.mLeastCompressSize = size;
  238 + return this;
  239 + }
  240 +
  241 + /**
  242 + * begin compress image with asynchronous
  243 + */
  244 + public void launch() {
  245 + build().launch(context);
  246 + }
  247 +
  248 + public File get(String path) throws Exception {
  249 + return build().get(path, context);
  250 + }
  251 +
  252 + /**
  253 + * begin compress image with synchronize
  254 + *
  255 + * @return the thumb image file list
  256 + */
  257 + public List<File> get() throws Exception {
  258 + return build().get(context);
  259 + }
  260 + }
  261 +}
  1 +package com.hhmedic.android.sdk.base.utils.luban;
  2 +
  3 +import java.io.File;
  4 +
  5 +public interface OnCompressListener {
  6 +
  7 + /**
  8 + * Fired when the compression is started, override to handle in your own code
  9 + */
  10 + void onStart();
  11 +
  12 + /**
  13 + * Fired when a compression returns successfully, override to handle in your own code
  14 + */
  15 + void onSuccess(File file);
  16 +
  17 + /**
  18 + * Fired when a compression fails to complete, override to handle in your own code
  19 + */
  20 + void onError(Throwable e);
  21 +}
  1 +package com.hhmedic.android.sdk.base.utils.secret;
  2 +
  3 +import java.security.MessageDigest;
  4 +
  5 +/**
  6 + * Created by iOS on 2018/1/3.
  7 + *
  8 + *
  9 + */
  10 +
  11 +public class HHCheckSumBuilder
  12 +{
  13 +
  14 +
  15 +
  16 + // 计算并获取CheckSum
  17 + public static String getCheckSum(String appSecret, String nonce, String curTime)
  18 + {
  19 + return encode("sha1", appSecret + nonce + curTime);
  20 + }
  21 +
  22 + // 计算并获取md5值
  23 + public static String getMD5(String requestBody)
  24 + {
  25 + return encode("md5", requestBody);
  26 + }
  27 +
  28 + private static String encode(String algorithm, String value) {
  29 + if (value == null) {
  30 + return null;
  31 + }
  32 + try {
  33 + MessageDigest messageDigest
  34 + = MessageDigest.getInstance(algorithm);
  35 + messageDigest.update(value.getBytes());
  36 + return getFormattedText(messageDigest.digest());
  37 + } catch (Exception e) {
  38 + throw new RuntimeException(e);
  39 + }
  40 + }
  41 + private static String getFormattedText(byte[] bytes) {
  42 + int len = bytes.length;
  43 + StringBuilder buf = new StringBuilder(len * 2);
  44 + for (int j = 0; j < len; j++) {
  45 + buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
  46 + buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
  47 + }
  48 + return buf.toString();
  49 + }
  50 + private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
  51 + '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  52 +}
  1 +package com.hhmedic.android.sdk.base.utils.secret;
  2 +
  3 +public class HHDesConfig {
  4 +
  5 + public static String getDES() {
  6 + return "DES";
  7 + }
  8 +
  9 + public static String getENCODING() {
  10 + return "UTF-8";
  11 + }
  12 +
  13 + public static String getSIMPLE() {
  14 + return "pacs_des";
  15 + }
  16 +}
  1 +package com.hhmedic.android.sdk.base.utils.secret;
  2 +
  3 +import java.security.MessageDigest;
  4 +
  5 +public class HHSecretUtils {
  6 +
  7 + public static String getSHA1(String str)
  8 + {
  9 + try
  10 + {
  11 + MessageDigest md5 = MessageDigest.getInstance("SHA-1");
  12 +
  13 + md5.update(str.getBytes("UTF-8"));
  14 +
  15 + byte[] m = md5.digest();//加密
  16 +
  17 + return get16String(m);
  18 + }
  19 + catch (Exception e)
  20 + {
  21 + e.printStackTrace();
  22 + }
  23 +
  24 + return "";
  25 +
  26 + }
  27 +
  28 + private static String get16String(byte[] messageDigest)
  29 + {
  30 + StringBuilder hexString = new StringBuilder();
  31 + // 字节数组转换为 十六进制 数
  32 + for (int i = 0; i < messageDigest.length; i++)
  33 + {
  34 + String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
  35 +
  36 + if (shaHex.length() < 2)
  37 + {
  38 + hexString.append(0);
  39 + }
  40 +
  41 + hexString.append(shaHex);
  42 + }
  43 +
  44 + return hexString.toString();
  45 +
  46 + }
  47 +
  48 +
  49 +
  50 + public static String createToken(long uuid)
  51 + {
  52 + String uuidStr = String.valueOf(uuid) + "HEHUAN_2015";
  53 +
  54 + return string2MD5(uuidStr);
  55 + }
  56 +
  57 +
  58 + private static String string2MD5(String inStr)
  59 + {
  60 + MessageDigest md5 = null;
  61 + try
  62 + {
  63 + md5 = MessageDigest.getInstance("MD5");
  64 + }
  65 + catch (Exception e)
  66 + {
  67 + System.out.println(e.toString());
  68 + e.printStackTrace();
  69 + return "";
  70 + }
  71 + char[] charArray = inStr.toCharArray();
  72 + byte[] byteArray = new byte[charArray.length];
  73 +
  74 + for (int i = 0; i < charArray.length; i++)
  75 + byteArray[i] = (byte) charArray[i];
  76 + byte[] md5Bytes = md5.digest(byteArray);
  77 + StringBuilder hexValue = new StringBuilder();
  78 + for (int i = 0; i < md5Bytes.length; i++){
  79 + int val = ((int) md5Bytes[i]) & 0xff;
  80 + if (val < 16)
  81 + hexValue.append("0");
  82 + hexValue.append(Integer.toHexString(val));
  83 + }
  84 + return hexValue.toString();
  85 +
  86 + }
  87 +}
  1 +// Top-level build file where you can add configuration options common to all sub-projects/modules.
  2 +
  3 +buildscript {
  4 +
  5 + repositories {
  6 + google()
  7 + jcenter()
  8 +
  9 + }
  10 + dependencies {
  11 + classpath 'com.android.tools.build:gradle:3.4.2'
  12 + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5'
  13 + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
  14 + }
  15 +}
  16 +
  17 +allprojects {
  18 + repositories {
  19 + google()
  20 + jcenter()
  21 +
  22 + }
  23 +}
  24 +
  25 +task clean(type: Delete) {
  26 + delete rootProject.buildDir
  27 +}
  28 +
  29 +apply from:'publish_config.gradle'
  1 +# Project-wide Gradle settings.
  2 +# IDE (e.g. Android Studio) users:
  3 +# Gradle settings configured through the IDE *will override*
  4 +# any settings specified in this file.
  5 +# For more details on how to configure your build environment visit
  6 +# http://www.gradle.org/docs/current/userguide/build_environment.html
  7 +# Specifies the JVM arguments used for the daemon process.
  8 +# The setting is particularly useful for tweaking memory settings.
  9 +org.gradle.jvmargs=-Xmx1536m
  10 +# When configured, Gradle will run in incubating parallel mode.
  11 +# This option should only be used with decoupled projects. More details, visit
  12 +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
  13 +# org.gradle.parallel=true
  14 +
  15 +
  16 +#android.useAndroidX=true
  17 +## Automatically convert third-party libraries to use AndroidX
  18 +#android.enableJetifier=true
  19 +#android.enableD8=true
No preview for this file type
  1 +#Mon Jul 20 16:09:02 CST 2020
  2 +distributionBase=GRADLE_USER_HOME
  3 +distributionPath=wrapper/dists
  4 +zipStoreBase=GRADLE_USER_HOME
  5 +zipStorePath=wrapper/dists
  6 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
  1 +#!/usr/bin/env sh
  2 +
  3 +##############################################################################
  4 +##
  5 +## Gradle start up script for UN*X
  6 +##
  7 +##############################################################################
  8 +
  9 +# Attempt to set APP_HOME
  10 +# Resolve links: $0 may be a link
  11 +PRG="$0"
  12 +# Need this for relative symlinks.
  13 +while [ -h "$PRG" ] ; do
  14 + ls=`ls -ld "$PRG"`
  15 + link=`expr "$ls" : '.*-> \(.*\)$'`
  16 + if expr "$link" : '/.*' > /dev/null; then
  17 + PRG="$link"
  18 + else
  19 + PRG=`dirname "$PRG"`"/$link"
  20 + fi
  21 +done
  22 +SAVED="`pwd`"
  23 +cd "`dirname \"$PRG\"`/" >/dev/null
  24 +APP_HOME="`pwd -P`"
  25 +cd "$SAVED" >/dev/null
  26 +
  27 +APP_NAME="Gradle"
  28 +APP_BASE_NAME=`basename "$0"`
  29 +
  30 +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
  31 +DEFAULT_JVM_OPTS=""
  32 +
  33 +# Use the maximum available, or set MAX_FD != -1 to use that value.
  34 +MAX_FD="maximum"
  35 +
  36 +warn () {
  37 + echo "$*"
  38 +}
  39 +
  40 +die () {
  41 + echo
  42 + echo "$*"
  43 + echo
  44 + exit 1
  45 +}
  46 +
  47 +# OS specific support (must be 'true' or 'false').
  48 +cygwin=false
  49 +msys=false
  50 +darwin=false
  51 +nonstop=false
  52 +case "`uname`" in
  53 + CYGWIN* )
  54 + cygwin=true
  55 + ;;
  56 + Darwin* )
  57 + darwin=true
  58 + ;;
  59 + MINGW* )
  60 + msys=true
  61 + ;;
  62 + NONSTOP* )
  63 + nonstop=true
  64 + ;;
  65 +esac
  66 +
  67 +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
  68 +
  69 +# Determine the Java command to use to start the JVM.
  70 +if [ -n "$JAVA_HOME" ] ; then
  71 + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
  72 + # IBM's JDK on AIX uses strange locations for the executables
  73 + JAVACMD="$JAVA_HOME/jre/sh/java"
  74 + else
  75 + JAVACMD="$JAVA_HOME/bin/java"
  76 + fi
  77 + if [ ! -x "$JAVACMD" ] ; then
  78 + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
  79 +
  80 +Please set the JAVA_HOME variable in your environment to match the
  81 +location of your Java installation."
  82 + fi
  83 +else
  84 + JAVACMD="java"
  85 + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
  86 +
  87 +Please set the JAVA_HOME variable in your environment to match the
  88 +location of your Java installation."
  89 +fi
  90 +
  91 +# Increase the maximum file descriptors if we can.
  92 +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
  93 + MAX_FD_LIMIT=`ulimit -H -n`
  94 + if [ $? -eq 0 ] ; then
  95 + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
  96 + MAX_FD="$MAX_FD_LIMIT"
  97 + fi
  98 + ulimit -n $MAX_FD
  99 + if [ $? -ne 0 ] ; then
  100 + warn "Could not set maximum file descriptor limit: $MAX_FD"
  101 + fi
  102 + else
  103 + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
  104 + fi
  105 +fi
  106 +
  107 +# For Darwin, add options to specify how the application appears in the dock
  108 +if $darwin; then
  109 + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
  110 +fi
  111 +
  112 +# For Cygwin, switch paths to Windows format before running java
  113 +if $cygwin ; then
  114 + APP_HOME=`cygpath --path --mixed "$APP_HOME"`
  115 + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
  116 + JAVACMD=`cygpath --unix "$JAVACMD"`
  117 +
  118 + # We build the pattern for arguments to be converted via cygpath
  119 + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
  120 + SEP=""
  121 + for dir in $ROOTDIRSRAW ; do
  122 + ROOTDIRS="$ROOTDIRS$SEP$dir"
  123 + SEP="|"
  124 + done
  125 + OURCYGPATTERN="(^($ROOTDIRS))"
  126 + # Add a user-defined pattern to the cygpath arguments
  127 + if [ "$GRADLE_CYGPATTERN" != "" ] ; then
  128 + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
  129 + fi
  130 + # Now convert the arguments - kludge to limit ourselves to /bin/sh
  131 + i=0
  132 + for arg in "$@" ; do
  133 + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
  134 + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
  135 +
  136 + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
  137 + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
  138 + else
  139 + eval `echo args$i`="\"$arg\""
  140 + fi
  141 + i=$((i+1))
  142 + done
  143 + case $i in
  144 + (0) set -- ;;
  145 + (1) set -- "$args0" ;;
  146 + (2) set -- "$args0" "$args1" ;;
  147 + (3) set -- "$args0" "$args1" "$args2" ;;
  148 + (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
  149 + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
  150 + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
  151 + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
  152 + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
  153 + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
  154 + esac
  155 +fi
  156 +
  157 +# Escape application args
  158 +save () {
  159 + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
  160 + echo " "
  161 +}
  162 +APP_ARGS=$(save "$@")
  163 +
  164 +# Collect all arguments for the java command, following the shell quoting and substitution rules
  165 +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
  166 +
  167 +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
  168 +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
  169 + cd "$(dirname "$0")"
  170 +fi
  171 +
  172 +exec "$JAVACMD" "$@"
  1 +@if "%DEBUG%" == "" @echo off
  2 +@rem ##########################################################################
  3 +@rem
  4 +@rem Gradle startup script for Windows
  5 +@rem
  6 +@rem ##########################################################################
  7 +
  8 +@rem Set local scope for the variables with windows NT shell
  9 +if "%OS%"=="Windows_NT" setlocal
  10 +
  11 +set DIRNAME=%~dp0
  12 +if "%DIRNAME%" == "" set DIRNAME=.
  13 +set APP_BASE_NAME=%~n0
  14 +set APP_HOME=%DIRNAME%
  15 +
  16 +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
  17 +set DEFAULT_JVM_OPTS=
  18 +
  19 +@rem Find java.exe
  20 +if defined JAVA_HOME goto findJavaFromJavaHome
  21 +
  22 +set JAVA_EXE=java.exe
  23 +%JAVA_EXE% -version >NUL 2>&1
  24 +if "%ERRORLEVEL%" == "0" goto init
  25 +
  26 +echo.
  27 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
  28 +echo.
  29 +echo Please set the JAVA_HOME variable in your environment to match the
  30 +echo location of your Java installation.
  31 +
  32 +goto fail
  33 +
  34 +:findJavaFromJavaHome
  35 +set JAVA_HOME=%JAVA_HOME:"=%
  36 +set JAVA_EXE=%JAVA_HOME%/bin/java.exe
  37 +
  38 +if exist "%JAVA_EXE%" goto init
  39 +
  40 +echo.
  41 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
  42 +echo.
  43 +echo Please set the JAVA_HOME variable in your environment to match the
  44 +echo location of your Java installation.
  45 +
  46 +goto fail
  47 +
  48 +:init
  49 +@rem Get command-line arguments, handling Windows variants
  50 +
  51 +if not "%OS%" == "Windows_NT" goto win9xME_args
  52 +
  53 +:win9xME_args
  54 +@rem Slurp the command line arguments.
  55 +set CMD_LINE_ARGS=
  56 +set _SKIP=2
  57 +
  58 +:win9xME_args_slurp
  59 +if "x%~1" == "x" goto execute
  60 +
  61 +set CMD_LINE_ARGS=%*
  62 +
  63 +:execute
  64 +@rem Setup the command line
  65 +
  66 +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
  67 +
  68 +@rem Execute Gradle
  69 +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
  70 +
  71 +:end
  72 +@rem End local scope for the variables with windows NT shell
  73 +if "%ERRORLEVEL%"=="0" goto mainEnd
  74 +
  75 +:fail
  76 +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
  77 +rem the _cmd.exe /c_ return code!
  78 +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
  79 +exit /b 1
  80 +
  81 +:mainEnd
  82 +if "%OS%"=="Windows_NT" endlocal
  83 +
  84 +:omega
  1 +ext {
  2 +
  3 + isCompany = false//控制是发布到企业账号还是个人账号
  4 +
  5 + user = isCompany ? "hhmedic" : "hhclient"
  6 + apikey = isCompany ? "6501341d8094b0482a82e3e6eb3b205d2925b194" : "89c96bff0896bb09eb50b53affb8616e18aece15"
  7 +
  8 + url = "https://www.hh-medic.com" //整体用到的URL
  9 + groupId = "com.hhmedic.android.sdk" //SDK引用包名
  10 + artifactId = "base_small" //SDK引用ID
  11 + name = "base_small" //描述
  12 + description = "base_small" //描述
  13 +
  14 + license_name = "The Apache Software License, Version 2.0" //协议名称
  15 + license_url = "http://www.apache.org/licenses/LICENSE-2.0.txt" //协议地址
  16 +
  17 + developer_id = isCompany ? "hhmedic" : "hhclient" //开发者账号
  18 + developer_name = "hhmedic" //开发者昵称
  19 + email = "liumingming@hh-medic.com" //开发者邮箱
  20 +
  21 + repo = "maven" //bintray上定义的Repositories
  22 +
  23 + vcsUrl = "http://code.hh-medic.com/dev-client/hhsdk.android.base.git"
  24 +}
  1 +rootProject.name='sdk.base'
  2 +include ':app'