Initial commit

This commit is contained in:
wangcongtao
2019-12-23 15:08:04 +08:00
commit 80cc1248b2
210 changed files with 17746 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx

116
.idea/codeStyles/Project.xml generated Normal file
View File

@@ -0,0 +1,116 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

16
.idea/gradle.xml generated Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<compositeConfiguration>
<compositeBuild compositeDefinitionSource="SCRIPT" />
</compositeConfiguration>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="resolveModulePerSourceSet" value="false" />
<option name="testRunner" value="PLATFORM" />
</GradleProjectSettings>
</option>
</component>
</project>

14
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
</configurations>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

12
.idea/runConfigurations.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

1
app/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

29
app/build.gradle Normal file
View File

@@ -0,0 +1,29 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
applicationId rootProject.ext.android.applicationId
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.androidxconstraintlayout
testImplementation rootProject.ext.dependencies.junit
androidTestImplementation rootProject.ext.dependencies.androidxjunit
androidTestImplementation rootProject.ext.dependencies.androidxespressocore
}

21
app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,27 @@
package com.mogo.launcher;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith( AndroidJUnit4.class )
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals( "com.mogo.launcher", appContext.getPackageName() );
}
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.launcher">
<application
android:name=".MogoApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme.App">
</application>
</manifest>

View File

@@ -0,0 +1,17 @@
package com.mogo.launcher;
import android.app.Application;
/**
* @author congtaowang
* @since 2019-12-18
* <p>
* Launcher application
*/
public class MogoApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
}
}

View File

@@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeWidth="1"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#008577"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">MogoLauncher</string>
</resources>

View File

@@ -0,0 +1,37 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.App" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:statusBarColor" tools:ignore="NewApi">@null</item>
<item name="android:windowEnterAnimation">@null</item>
<item name="android:windowExitAnimation">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowAnimationStyle">@style/Animation</item>
</style>
<style name="Animation">
<item name="android:activityOpenEnterAnimation">@null</item>
<item name="android:activityOpenExitAnimation">@null</item>
<item name="android:activityCloseEnterAnimation">@null</item>
<item name="android:activityCloseExitAnimation">@null</item>
<item name="android:taskOpenEnterAnimation">@null</item>
<item name="android:taskOpenExitAnimation">@null</item>
<item name="android:taskCloseEnterAnimation">@null</item>
<item name="android:taskCloseExitAnimation">@null</item>
<item name="android:taskToFrontEnterAnimation">@null</item>
<item name="android:taskToFrontExitAnimation">@null</item>
<item name="android:taskToBackEnterAnimation">@null</item>
<item name="android:taskToBackExitAnimation">@null</item>
</style>
</resources>

View File

@@ -0,0 +1,17 @@
package com.mogo.launcher;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals( 4, 2 + 2 );
}
}

45
build.gradle Normal file
View File

@@ -0,0 +1,45 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "config.gradle"
buildscript {
ext.kotlin_version = '1.3.61+'
repositories {
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
maven {
url 'http://nexus.zhidaoauto.com/repository/maven-releases/'
}
maven {
url 'http://nexus.zhidaoauto.com/repository/maven-public/'
}
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
maven {
url 'http://nexus.zhidaoauto.com/repository/maven-releases/'
}
maven {
url 'http://nexus.zhidaoauto.com/repository/maven-public/'
}
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

53
config.gradle Normal file
View File

@@ -0,0 +1,53 @@
ext {
android = [
applicationId : "com.mogo.launcher",
compileSdkVersion: 29,
buildToolsVersion: "29.0.2",
minSdkVersion : 19,
targetSdkVersion : 22,
versionCode : 1,
versionName : "1.0.0",
]
dependencies = [
// androidx
androidxappcompat : "androidx.appcompat:appcompat:1.0.2",
androidxconstraintlayout: "androidx.constraintlayout:constraintlayout:1.1.3",
// 测试
junit : "junit:junit:4.12",
androidxjunit : "androidx.test.ext:junit:1.1.0",
androidxespressocore : "androidx.test.espresso:espresso-core:3.1.1",
// 地图
amapnavi3dmap : "com.amap.api:navi-3dmap:latest.integration",
amapsearch : "com.amap.api:search:latest.integration",
amaplocation : "com.amap.api:location:latest.integration",
// json 转换
gson : "com.google.code.gson:gson:2.8.4",
// 内存泄漏检测
debugleakcanary : "com.squareup.leakcanary:leakcanary-android:1.6.1",
releaseleakcanary : "com.squareup.leakcanary:leakcanary-android-no-op:1.6.1",
testleakcanary : "com.squareup.leakcanary:leakcanary-android-no-op:1.6.1",
//rxJava
rxjava : "io.reactivex.rxjava2:rxjava:2.2.2",
rxandroid : "io.reactivex.rxjava2:rxandroid:2.1.0",
// arouter
arouter : "com.alibaba:arouter-api:1.5.0",
aroutercompiler : "com.alibaba:arouter-compiler:1.2.2",
// glide
glide : 'com.github.bumptech.glide:glide:4.8.0',
glideokhttp3 : 'com.github.bumptech.glide:okhttp3-integration:4.8.0',
glideanno : 'com.github.bumptech.glide:annotations:4.8.0',
glidecompiler : 'com.github.bumptech.glide:compiler:4.8.0',
supportannos : "com.android.support:support-annotations:28.0.0",
// fresco
fresco : 'com.facebook.fresco:fresco:1.1.0',
// 公司服务 - 语音
aiassist : "com.zhidaoauto.common:service:1.0.4",
// retrofit
retrofit : "com.squareup.retrofit2:retrofit:2.3.0",
retrofitadapter : "com.squareup.retrofit2:adapter-rxjava:2.1.0",
retrofitconvertergson : "com.squareup.retrofit2:converter-gson:2.3.0",
retrofitconverterscalars: "com.squareup.retrofit2:converter-scalars:2.1.0",
]
}

1
foudations/mogo-commons/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,31 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
api rootProject.ext.dependencies.aiassist
implementation project(":foudations:mogo-utils")
}

View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.commons" />

View File

@@ -0,0 +1,24 @@
package com.mogo.commons;
import android.app.Application;
/**
* @author congtaowang
* @since 2019-12-23
* <p>
* 描述
*/
public class AbsMogoApplication extends Application {
private static Application sApp;
@Override
public void onCreate() {
super.onCreate();
sApp = this;
}
public static Application getApp() {
return sApp;
}
}

View File

@@ -0,0 +1,12 @@
package com.mogo.commons.data;
import java.io.Serializable;
/**
* Created by congtaowang on 2019/1/7.
*/
public class BaseData implements Serializable, Cloneable {
public int code = -1;
public String msg;
}

View File

@@ -0,0 +1,18 @@
package com.mogo.commons.network;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
/**
* @author congtaowang
* @since 2019-08-30
* <p>
* 信任所有域名
*/
public class AllAllowedHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify( String hostname, SSLSession session ) {
return true;
}
}

View File

@@ -0,0 +1,30 @@
package com.mogo.commons.network;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* @author congtaowang
* @since 2019-08-30
* <p>
* 描述
*/
public class X509TrustManagerImpl implements X509TrustManager {
@Override
public void checkClientTrusted( X509Certificate[] chain, String authType ) throws CertificateException {
}
@Override
public void checkServerTrusted( X509Certificate[] chain, String authType ) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}

View File

@@ -0,0 +1,102 @@
package com.mogo.commons.voice;
import android.content.Context;
import com.zhidao.auto.platform.voice.VoiceClient;
import java.util.HashMap;
import java.util.Map;
/**
* @author congtaowang
* @since 2019-10-03
* <p>
* 语音助手通信助手
*/
public class AIAssist implements VoiceClient.VoiceCmdCallBack {
private static volatile AIAssist sInstance;
public static AIAssist getInstance( Context context ) {
if ( sInstance == null ) {
synchronized ( AIAssist.class ) {
if ( sInstance == null ) {
sInstance = new AIAssist( context );
}
}
}
return sInstance;
}
public synchronized void release() {
sInstance = null;
}
private final VoiceClient mVoiceClient;
private Map< String, IMogoVoiceCmdCallBack > mUnWakeupCmdMap = new HashMap<>();
private AIAssist( Context context ) {
// private constructor
mVoiceClient = new VoiceClient( context.getApplicationContext() );
mVoiceClient.setCallBack( this );
}
@Override
public void onCmdSelected( String cmd ) {
final IMogoVoiceCmdCallBack cmdCallBack = mUnWakeupCmdMap.get( cmd );
if ( cmdCallBack != null ) {
cmdCallBack.onCmdSelected( cmd );
}
}
@Override
public void onCmdAction( String speakText ) {
}
@Override
public void onCmdCancel( String speakText ) {
}
@Override
public void onSpeakEnd( String speakText ) {
IMogoVoiceCmdCallBack callBack = mUnWakeupCmdMap.get( speakText );
if ( callBack != null ) {
callBack.onSpeakEnd( speakText );
}
}
@Override
public void onSpeakSelectTimeOut( String speakText ) {
IMogoVoiceCmdCallBack callBack = mUnWakeupCmdMap.get( speakText );
if ( callBack != null ) {
callBack.onSpeakSelectTimeOut( speakText );
}
}
public void speakTTSVoice( String text ) {
try {
mVoiceClient.speakDefault( text );
} catch ( Exception e ) {
}
}
public void registerUnWakeupCommand( String cmd, String[] cmdWords, IMogoVoiceCmdCallBack callBack ) {
mUnWakeupCmdMap.put( cmd, callBack );
mVoiceClient.registerCustomWakeupCmd( cmd, cmdWords );
}
public void unregisterUnWakeupCommand( String cmd ) {
mUnWakeupCmdMap.remove( cmd );
mVoiceClient.unRegisterCustomWakeupCmd( cmd );
}
public void registerTTSCallback( String tts, IMogoVoiceCmdCallBack cmdCallBack ) {
mUnWakeupCmdMap.put( tts, cmdCallBack );
}
public void unregisterTTSCallback( String tts ) {
mUnWakeupCmdMap.remove( tts );
}
}

View File

@@ -0,0 +1,38 @@
package com.mogo.commons.voice;
public interface IMogoVoiceCmdCallBack {
/**
* 免唤醒命令响应回调
*
* @param cmd
*/
void onCmdSelected( String cmd );
/**
* 语音播报临时免唤醒“确定”命令
*
* @param speakText 播报内容
*/
void onCmdAction( String speakText );
/**
* 语音播报临时免唤醒“取消”命令
*
* @param speakText 播报内容
*/
void onCmdCancel( String speakText );
/**
* 语音播报完毕
*
* @param speakText 播报内容
*/
void onSpeakEnd( String speakText );
/**
* 语音播报完临时命令选择超时
*
* @param speakText 播报内容
*/
void onSpeakSelectTimeOut( String speakText );
}

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">mogo-commons</string>
</resources>

1
foudations/mogo-utils/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,40 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
api rootProject.ext.dependencies.glide
implementation rootProject.ext.dependencies.glideanno
implementation rootProject.ext.dependencies.glideokhttp3
implementation rootProject.ext.dependencies.supportannos
annotationProcessor rootProject.ext.dependencies.supportannos
annotationProcessor rootProject.ext.dependencies.glidecompiler
api rootProject.ext.dependencies.retrofit
api rootProject.ext.dependencies.retrofitadapter
api rootProject.ext.dependencies.retrofitconvertergson
api rootProject.ext.dependencies.retrofitconverterscalars
implementation rootProject.ext.dependencies.androidxappcompat
}

View File

View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,27 @@
package com.mogo.utils;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith( AndroidJUnit4.class )
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals( "com.mogo.utils.test", appContext.getPackageName() );
}
}

View File

@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.utils" />

View File

@@ -0,0 +1,335 @@
package com.mogo.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.HashMap;
public class ActivityLifecycleManager {
private Application mApplication;
/**
* 当前出于 Start 状态的 Activity
*/
private ArrayList< Activity > mStartedActivities = new ArrayList<>();
private ArrayList<AppStateListener> mAppStateListeners = new ArrayList<>();
/**
* 当前存活的 Activity
*/
private HashMap< Activity, ActivityTrace> mAliveActivities = new HashMap<>();
/**
* App 是否出于前台
*/
private volatile boolean mIsAppActive = false;
private Activity mCurrentResumedActivity;
/**
* Home 键事件广播的接受器
*/
private HomeKeyEventReceiver mHomeKeyEventReceiver;
/**
* Home 键事件监听者列表
*/
private ArrayList<HomeKeyEventListener> mHomeKeyEventListeners = new ArrayList<>();
private DefActivityLifecycleCallbacks mInnerActivityListener = new DefActivityLifecycleCallbacks() {
@Override
public void onActivityStarted( Activity activity) {
if (mStartedActivities.isEmpty()) {
mIsAppActive = true;
notifyAppStateChanged( AppStateListener.ACTIVE);
}
mStartedActivities.add(activity);
ActivityTrace trace = mAliveActivities.get(activity);
if (trace != null) {
trace.startCnt++;
}
}
@Override
public void onActivityStopped( Activity activity) {
mStartedActivities.remove(activity);
if (mStartedActivities.isEmpty()) {
mIsAppActive = false;
notifyAppStateChanged( AppStateListener.INACTIVE);
}
ActivityTrace trace = mAliveActivities.get(activity);
if (trace != null) {
trace.stopCnt++;
}
}
@Override
public void onActivityResumed( Activity activity) {
mCurrentResumedActivity = activity;
ActivityTrace trace = mAliveActivities.get(activity);
if (trace != null) {
trace.resumeCnt++;
}
}
@Override
public void onActivityPaused( Activity activity) {
ActivityTrace trace = mAliveActivities.get(activity);
if (trace != null) {
trace.pauseCnt++;
}
}
@Override
public void onActivityCreated( Activity activity, Bundle savedInstanceState) {
mAliveActivities.put(activity, new ActivityTrace(activity));
}
@Override
public void onActivityDestroyed( Activity activity) {
mAliveActivities.remove(activity);
}
};
private ActivityLifecycleManager() {}
public static ActivityLifecycleManager getInstance() {
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder{
private static final ActivityLifecycleManager INSTANCE = new ActivityLifecycleManager();
}
public void start( Application application) {
this.mApplication = application;
registerInnerActivityListener();
registerHomeKeyEventReceiver();
}
public void stop(){
unregisterActivityLifecycleCallbacks(mInnerActivityListener);
unregisterHomeKeyEventReceiver();
}
/**
* 注册 Activity 生命周期的回调
*
* @param callbacks Activity 生命周期的回调
*/
public void registerActivityLifecycleCallbacks( Application.ActivityLifecycleCallbacks callbacks) {
if (mApplication == null) {
return;
}
if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return;
}
mApplication.registerActivityLifecycleCallbacks(callbacks);
}
/**
* 取消注册 Activity 生命周期的回调
*
* @param callbacks Activity 生命周期的回调
*/
public void unregisterActivityLifecycleCallbacks( Application.ActivityLifecycleCallbacks callbacks) {
if (mApplication == null) {
return;
}
if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return;
}
mApplication.unregisterActivityLifecycleCallbacks(callbacks);
}
/**
* 应用是否出于前台
*/
public boolean isAppActive() {
return mIsAppActive;
}
public Activity getCurrentActivity(){
return mCurrentResumedActivity;
}
/**
* 添加应用状态的监听
*/
public void addAppStateListener(AppStateListener listener) {
synchronized (mAppStateListeners) {
mAppStateListeners.add(listener);
}
}
/**
* 移除应用状态的监听
*
* @param listener
*/
public void removeAppStateListener(AppStateListener listener) {
synchronized (mAppStateListeners) {
mAppStateListeners.remove(listener);
}
}
/**
* 添加 home 键的事件监听
*/
public void addHomeKeyEventListener(HomeKeyEventListener listener) {
if (listener == null) {
return;
}
synchronized (mHomeKeyEventListeners) {
mHomeKeyEventListeners.add(listener);
}
}
/**
* 移除 home 键的事件监听
*/
public void removeHomeKeyEventListener(HomeKeyEventListener listener) {
if (listener == null) {
return;
}
synchronized (mHomeKeyEventListeners) {
mHomeKeyEventListeners.remove(listener);
}
}
/**
* 注册Activity生命周期的监听
*/
private void registerInnerActivityListener() {
registerActivityLifecycleCallbacks(mInnerActivityListener);
}
private void notifyAppStateChanged(int state) {
Object[] listeners = collectAppStateListeners();
if (listeners != null) {
for (int i = 0; i < listeners.length; i++) {
((AppStateListener) listeners[i]).onStateChanged(state);
}
}
}
private Object[] collectAppStateListeners() {
Object[] listeners = null;
synchronized (mAppStateListeners) {
if (mAppStateListeners.size() > 0) {
listeners = mAppStateListeners.toArray();
}
}
return listeners;
}
private Object[] collectHomeKeyEventListeners() {
Object[] listeners = null;
synchronized (mHomeKeyEventListeners) {
if (mHomeKeyEventListeners.size() > 0) {
listeners = mHomeKeyEventListeners.toArray();
}
}
return listeners;
}
private void registerHomeKeyEventReceiver() {
android.content.IntentFilter filter = new android.content.IntentFilter();
filter.addAction( Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
mHomeKeyEventReceiver = new HomeKeyEventReceiver();
mApplication.registerReceiver(mHomeKeyEventReceiver, filter);
}
private void unregisterHomeKeyEventReceiver() {
mApplication.unregisterReceiver(mHomeKeyEventReceiver);
}
private void onHomeKeyPressed() {
Object[] listeners = collectHomeKeyEventListeners();
if (listeners != null) {
for (int i = 0; i < listeners.length; i++) {
((HomeKeyEventListener) listeners[i]).onHomeKeyPressed();
}
}
}
@TargetApi( Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public static abstract class DefActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated( Activity activity, Bundle savedInstanceState) {}
@Override
public void onActivityStarted( Activity activity) {}
@Override
public void onActivityResumed( Activity activity) {}
@Override
public void onActivityPaused( Activity activity) {}
@Override
public void onActivityStopped( Activity activity) {}
@Override
public void onActivitySaveInstanceState( Activity activity, Bundle outState) {}
@Override
public void onActivityDestroyed( Activity activity) {}
}
public interface AppStateListener {
int INACTIVE = 0;
int ACTIVE = 1;
/**
* App 状态的回调
*/
void onStateChanged( int state );
}
/**
* home 键的监听
*/
public interface HomeKeyEventListener {
void onHomeKeyPressed();
}
/**
* Activity 的生命周期调用痕迹
*/
static class ActivityTrace {
Activity activity;
int resumeCnt;
int pauseCnt;
int startCnt;
int stopCnt;
ActivityTrace( Activity activity) {
this.activity = activity;
}
}
private final class HomeKeyEventReceiver extends BroadcastReceiver {
private final String SYSTEM_DIALOG_REASON_KEY = "reason";
private final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
@Override
public void onReceive( Context context, Intent intent) {
String action = intent.getAction();
if ( Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
onHomeKeyPressed();
}
}
}
}
}

View File

@@ -0,0 +1,84 @@
package com.mogo.utils;
import android.app.Activity;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
public class ActivityStack {
private static final Deque< Activity > ACTIVITY_STACK = new ArrayDeque<>();
public static synchronized void addActivity( Activity activity) {
if(activity != null){
ACTIVITY_STACK.offer(activity);
}
}
public static synchronized Activity currentActivity() {
return ACTIVITY_STACK.peekLast();
}
public static synchronized void finishCurrentActivity() {
Activity activity = ACTIVITY_STACK.pop();
if (!activity.isFinishing()) {
activity.finish();
}
}
public static synchronized void finishActivity( Activity activity) {
ACTIVITY_STACK.remove(activity);
if (!activity.isFinishing()) {
activity.finish();
}
}
public static synchronized void finishActivity( Class<? extends Activity > cls) {
Iterator< Activity > iterator = ACTIVITY_STACK.iterator();
while (iterator.hasNext()) {
Activity next = iterator.next();
if(next.getClass().equals(cls)){
iterator.remove();
if(!next.isFinishing()){
next.finish();
}
}
}
}
public static synchronized void finishActivityExcept( Class<?> cls) {
Iterator< Activity > iterator = ACTIVITY_STACK.iterator();
while (iterator.hasNext()) {
Activity next = iterator.next();
if (!next.getClass().equals(cls)) {
iterator.remove();
if(!next.isFinishing()){
next.finish();
}
}
}
}
public static synchronized void finishAllActivity() {
Iterator< Activity > iterator = ACTIVITY_STACK.iterator();
while (iterator.hasNext()) {
iterator.remove();
Activity next = iterator.next();
if(!next.isFinishing()){
next.finish();
}
}
}
public static synchronized boolean isActivityExist( Class<? extends Activity > cls){
Iterator< Activity > iterator = ACTIVITY_STACK.iterator();
while (iterator.hasNext()) {
Activity next = iterator.next();
if(next.getClass().equals(cls)){
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,464 @@
package com.mogo.utils;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.RandomAccess;
@SuppressWarnings({ "unchecked" })
public class ArrayUtils {
/**
* 加强版的asList会检查传入是否为null以保证不会抛出异常 并且返回的arraylist改为{@link ArrayList}
*
* @param <T>
* @param array
* @return
*/
public static <T> ArrayList<T> asList( T... array) {
if (array == null) {
return new ArrayList<T>(0);
}
ArrayList<T> list = new ArrayList<T>( Arrays.asList(array));
return list;
}
public static <T> List<T> asReadOnlyList( T... array) {
return new ReadOnlyArrayList<T>(array);
}
public static boolean contains( Object[] array, Object value) {
if (array == null) {
return false;
}
for ( Object object : array) {
if (object == null) {
if (value == null) {
return true;
}
} else if (object.equals(value)) {
return true;
}
}
return false;
}
/**
* 在已排序数组中查询是否存在某值
*
* @param array
* @param value
* @return
*/
public static boolean contains(int[] array, int value) {
return Arrays.binarySearch(array, value) >= 0 ? true : false;
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with <tt>false</tt> (if necessary) so the copy has the
* specified length. For all indices that are valid in both the original array and the copy, the two arrays will
* contain identical values. For any indices that are valid in the copy but not the original, the copy will contain
* <tt>false</tt>. Such indices will exist if and only if the specified length is greater than that of the original
* array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with false elements to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
*/
public static boolean[] copyOf(boolean[] original, int newLength) {
boolean[] copy = new boolean[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with zeros (if necessary) so the copy has the specified length.
* For all indices that are valid in both the original array and the copy, the two arrays will contain identical
* values. For any indices that are valid in the copy but not the original, the copy will contain <tt>(byte)0</tt>.
* Such indices will exist if and only if the specified length is greater than that of the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with zeros to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
*/
public static byte[] copyOf(byte[] original, int newLength) {
byte[] copy = new byte[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with null characters (if necessary) so the copy has the
* specified length. For all indices that are valid in both the original array and the copy, the two arrays will
* contain identical values. For any indices that are valid in the copy but not the original, the copy will contain
* <tt>'\\u000'</tt>. Such indices will exist if and only if the specified length is greater than that of the
* original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with null characters to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
*/
public static char[] copyOf(char[] original, int newLength) {
char[] copy = new char[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with zeros (if necessary) so the copy has the specified length.
* For all indices that are valid in both the original array and the copy, the two arrays will contain identical
* values. For any indices that are valid in the copy but not the original, the copy will contain <tt>0d</tt>. Such
* indices will exist if and only if the specified length is greater than that of the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with zeros to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
*/
public static double[] copyOf(double[] original, int newLength) {
double[] copy = new double[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with zeros (if necessary) so the copy has the specified length.
* For all indices that are valid in both the original array and the copy, the two arrays will contain identical
* values. For any indices that are valid in the copy but not the original, the copy will contain <tt>0f</tt>. Such
* indices will exist if and only if the specified length is greater than that of the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with zeros to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
*/
public static float[] copyOf(float[] original, int newLength) {
float[] copy = new float[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with zeros (if necessary) so the copy has the specified length.
* For all indices that are valid in both the original array and the copy, the two arrays will contain identical
* values. For any indices that are valid in the copy but not the original, the copy will contain <tt>0</tt>. Such
* indices will exist if and only if the specified length is greater than that of the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with zeros to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
*/
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with zeros (if necessary) so the copy has the specified length.
* For all indices that are valid in both the original array and the copy, the two arrays will contain identical
* values. For any indices that are valid in the copy but not the original, the copy will contain <tt>0L</tt>. Such
* indices will exist if and only if the specified length is greater than that of the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with zeros to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
*/
public static long[] copyOf(long[] original, int newLength) {
long[] copy = new long[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with zeros (if necessary) so the copy has the specified length.
* For all indices that are valid in both the original array and the copy, the two arrays will contain identical
* values. For any indices that are valid in the copy but not the original, the copy will contain <tt>(short)0</tt>.
* Such indices will exist if and only if the specified length is greater than that of the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with zeros to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
*/
public static short[] copyOf(short[] original, int newLength) {
short[] copy = new short[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with nulls (if necessary) so the copy has the specified length.
* For all indices that are valid in both the original array and the copy, the two arrays will contain identical
* values. For any indices that are valid in the copy but not the original, the copy will contain <tt>null</tt>.
* Such indices will exist if and only if the specified length is greater than that of the original array. The
* resulting array is of exactly the same class as the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with nulls to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
*/
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
/**
* 从jdk1.6拷贝过来android中没有这些方法。<br />
* Copies the specified array, truncating or padding with nulls (if necessary) so the copy has the specified length.
* For all indices that are valid in both the original array and the copy, the two arrays will contain identical
* values. For any indices that are valid in the copy but not the original, the copy will contain <tt>null</tt>.
* Such indices will exist if and only if the specified length is greater than that of the original array. The
* resulting array is of the class <tt>newType</tt>.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @param newType the class of the copy to be returned
* @return a copy of the original array, truncated or padded with nulls to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
* @throws ArrayStoreException if an element copied from <tt>original</tt> is not of a runtime type that can be
* stored in an array of class <tt>newType</tt>
*/
public static <T, U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
T[] copy = ( Object ) newType == ( Object ) Object[].class ? (T[]) new Object[newLength] : (T[]) Array.newInstance(
newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
/**
* 在数组中查询某值所在位置
*
* @param array
* @param value
* @return
*/
public static int indexOf(int[] array, int value) {
for (int i = 0; i < array.length; i++) {
if (array[i] == value) {
return i;
}
}
throw new ArrayIndexOutOfBoundsException(value + "is not in " + Arrays.toString(array));
}
/**
* 在数组中查询某值所在位置
*
* @param <T>
* @param array
* @param value
* @return
*/
public static <T> int indexOf(T[] array, T value) {
for (int i = 0; i < array.length; i++) {
if (array[i].equals(value)) {
return i;
}
}
throw new ArrayIndexOutOfBoundsException(value.toString() + "is not in " + Arrays.toString(array));
}
private static class ReadOnlyArrayList<E> extends AbstractList<E> implements List<E>, Serializable, RandomAccess {
private static final long serialVersionUID = 1L;
private final E[] a;
ReadOnlyArrayList(E[] storage) {
a = storage;
}
@Override
public boolean contains( Object object) {
if (a == null) {
return false;
}
if (object != null) {
for (E element : a) {
if (object.equals(element)) {
return true;
}
}
} else {
for (E element : a) {
if (element == null) {
return true;
}
}
}
return false;
}
@Override
public E get(int location) {
try {
return a[location];
} catch ( ArrayIndexOutOfBoundsException e) {
throw new IndexOutOfBoundsException();
} catch ( NullPointerException e) {
throw new IndexOutOfBoundsException();
}
}
@Override
public int indexOf( Object object) {
if (a == null) {
return -1;
}
if (object != null) {
for (int i = 0; i < a.length; i++) {
if (object.equals(a[i])) {
return i;
}
}
} else {
for (int i = 0; i < a.length; i++) {
if (a[i] == null) {
return i;
}
}
}
return -1;
}
@Override
public int lastIndexOf( Object object) {
if (a == null) {
return -1;
}
if (object != null) {
for (int i = a.length - 1; i >= 0; i--) {
if (object.equals(a[i])) {
return i;
}
}
} else {
for (int i = a.length - 1; i >= 0; i--) {
if (a[i] == null) {
return i;
}
}
}
return -1;
}
@Override
public E set(int location, E object) {
if (a == null) {
throw new IndexOutOfBoundsException();
}
try {
E result = a[location];
a[location] = object;
return result;
} catch ( ArrayIndexOutOfBoundsException e) {
throw new IndexOutOfBoundsException();
} catch ( ArrayStoreException e) {
throw new ClassCastException();
}
}
@Override
public int size() {
return a == null ? 0 : a.length;
}
@Override
public Object[] toArray() {
if (a == null) {
return new Object[0];
}
return a.clone();
}
@Override
public <T> T[] toArray(T[] contents) {
if (a == null) {
return contents;
}
int size = size();
if (size > contents.length) {
Class<?> ct = contents.getClass().getComponentType();
contents = (T[]) Array.newInstance(ct, size);
}
System.arraycopy(a, 0, contents, 0, size);
if (size < contents.length) {
contents[size] = null;
}
return contents;
}
}
/**
* @param array
* @return
*/
public static <T> boolean isEmpty( Collection<T> array) {
if (array == null || array.size() == 0) {
return true;
}
return false;
}
/**
* @param array
* @return
*/
public static <T> boolean isEmpty(T[] array) {
if (array == null || array.length == 0) {
return true;
}
return false;
}
/**
* 合并2个array
*
* @param head
* @param tail
* @return
*/
public static <T> T[] join(T[] head, T[] tail) {
if (head == null) {
return tail;
}
if (tail == null) {
return head;
}
Class<?> type = head.getClass().getComponentType();
T[] result = (T[]) Array.newInstance(type, head.length + tail.length);
System.arraycopy(head, 0, result, 0, head.length);
System.arraycopy(tail, 0, result, head.length, tail.length);
return result;
}
}

View File

@@ -0,0 +1,673 @@
package com.mogo.utils;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.media.ExifInterface;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.opengl.GLES10;
import android.os.Build;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
/**
* @author wangzhiyuan
* @since 2017/8/30
*/
public class BitmapHelper {
private static final String TAG = "BitmapHelper";
static int ONE_KB = 1024;
static int ONE_MB = ONE_KB * 1024;
static int SIZE_DEFAULT = 2048;
static int SIZE_LIMIT = 2048;
/**
* 根据原图添加圆角
*
* @param source
* @return
*/
public static Bitmap createRoundCornerImage( Bitmap source, float corner ) {
final Paint paint = new Paint();
paint.setAntiAlias( true );
Bitmap target = Bitmap.createBitmap( source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888 );
Canvas canvas = new Canvas( target );
RectF rect = new RectF( 0, 0, source.getWidth(), source.getHeight() );
canvas.drawRoundRect( rect, corner, corner, paint );
paint.setXfermode( new PorterDuffXfermode( PorterDuff.Mode.SRC_IN ) );
canvas.drawBitmap( source, 0, 0, paint );
return target;
}
public static byte[] bitmapToBytes( Bitmap bitmap ) {
if ( bitmap == null ) {
return null;
}
ByteArrayOutputStream bos = null;
byte[] result = null;
try {
bos = new ByteArrayOutputStream();
bitmap.compress( Bitmap.CompressFormat.JPEG, 100, bos );
result = bos.toByteArray();
} catch ( Exception e ) {
e.printStackTrace();
result = null;
} finally {
IOUtils.closeSilently( bos );
}
return result;
}
/**
* Use quality compression to compress bitmap's size to be smaller than a max size, and convert it to bytes thereafter.
* Note that this method will not report compressing ratio related data.
*
* @param bitmap data source
* @param maxSize unit in kb
* @return bytes after compressing bitmap to a size smaller than a specific max size.
*/
public static byte[] bitmapToBytes( Bitmap bitmap, int maxSize ) {
final long start = System.currentTimeMillis();
if ( bitmap == null ) {
return null;
}
final int maxSizeOfBytes = maxSize * ONE_KB;
ByteArrayOutputStream bos = null;
byte[] result = null;
try {
bos = new ByteArrayOutputStream();
int quality = 100;
int fullSize = 0;
do {
bos.reset();
bitmap.compress( Bitmap.CompressFormat.JPEG, quality, bos );
if ( quality == 100 ) {
fullSize = bos.size();
}
Log.i( TAG, "quality<---->size, " + quality + "<---->" + bos.size() / 1024 );
}
while ( bos.size() > maxSizeOfBytes && ( quality -= ( fullSize > ONE_MB ) ? 10 : 5 ) >= 0 );
result = bos.toByteArray();
final long end = System.currentTimeMillis();
Log.i( TAG,
"bitmap to bytes costs " + ( end - start ) + "ms, \n" +
"bitmap full size is " + ( fullSize / 1024 ) + "kb, \n" +
"bitmap final size is " + ( bos.size() / 1024 ) + "kb, \n" +
"bitmap quality is " + quality );
} catch ( Exception e ) {
e.printStackTrace();
result = null;
} finally {
IOUtils.closeSilently( bos );
}
return result;
}
/**
* Use quality compression to compress bitmap to be smaller than a specific max size.
*
* @param bitmap data source
* @param maxSize a specific max size which's unit is kb.
* @return a compressed bitmap smaller than the max size.
*/
public static Bitmap compressBitmap( Bitmap bitmap, int maxSize, final OnCompressListener listener ) {
if ( bitmap == null || bitmap.isRecycled() ) {
return null;
}
listener.onBeforeCompress();
ByteArrayOutputStream bos = null;
Bitmap target = null;
try {
bos = new ByteArrayOutputStream();
int quality = 100;
do {
bos.reset();
bitmap.compress( Bitmap.CompressFormat.JPEG, quality, bos );
}
while ( bos.size() / 1024 > maxSize && ( quality -= 5 ) >= 0 );
byte[] result = bos.toByteArray();
target = bytesToBitmap( result );
if ( listener != null ) {
listener.onCompressSuccess( result );
}
} catch ( Exception e ) {
e.printStackTrace();
target = null;
if ( listener != null ) {
listener.onCompressFailed( "压缩失败" );
}
} finally {
IOUtils.closeSilently( bos );
}
return target;
}
public static Bitmap compressBitmap( Bitmap bitmap, int maxSize ) {
if ( bitmap == null ) {
return null;
}
ByteArrayOutputStream bos = null;
Bitmap target = null;
try {
bos = new ByteArrayOutputStream();
int quality = 100;
do {
bos.reset();
bitmap.compress( Bitmap.CompressFormat.JPEG, quality, bos );
}
while ( bos.size() / 1024 > maxSize && ( quality -= 5 ) >= 0 );
byte[] result = bos.toByteArray();
target = bytesToBitmap( result );
} catch ( Exception e ) {
e.printStackTrace();
target = null;
} finally {
IOUtils.closeSilently( bos );
}
return target;
}
/**
* Decode an immutable bitmap from the specified byte array.
*
* @param b byte array of compressed image data
* @return an immutable bitmap or null in case of exception.
*/
public static Bitmap bytesToBitmap( byte[] b ) {
if ( b != null && b.length != 0 ) {
return BitmapFactory.decodeByteArray( b, 0, b.length );
} else {
return null;
}
}
/**
* Decode an immutable bitmap from the specified byte array.
*
* @param b byte array of compressed image data
* @param options Options that control downsampling and whether the
* image should be completely decoded, or just is size returned.
* @return an immutable bitmap or null in case of exception.
*/
public static Bitmap bytesToBitmap( byte[] b, BitmapFactory.Options options ) {
if ( b.length != 0 ) {
return BitmapFactory.decodeByteArray( b, 0, b.length, options );
} else {
return null;
}
}
/**
* Get max supported image size which will differ from different devices.
*
* @return max size related to the device.
*/
public static int getMaxSupportedImageSize() {
int textureLimit = getMaxTextureSize();
if ( textureLimit == 0 ) {
return SIZE_DEFAULT;
} else {
return Math.min( textureLimit, SIZE_LIMIT );
}
}
public static int getMaxTextureSize2() {
// The OpenGL texture size is the maximum size that can be drawn in an ImageView
int[] maxSize = new int[1];
GLES10.glGetIntegerv( GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0 );
return maxSize[0];
}
/**
* Decode a bitmap's input stream to find a proper inSampleSize according to device's max supported size.
*
* @param is bitmap's data source
* @param close whether to close input stream after work is done.
* @return a proper inSampleSize
*/
public static int findProperInSampleSize( InputStream is, boolean close ) {
// Just decode image size into options
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
BitmapFactory.decodeStream( is, null, options );
} catch ( Exception e ) {
e.printStackTrace();
} finally {
if ( close ) IOUtils.closeSilently( is );
}
int maxSize = getMaxSupportedImageSize();
int sampleSize = 1;
while ( options.outHeight / sampleSize > maxSize || options.outWidth / sampleSize > maxSize ) {
sampleSize = sampleSize << 1;
}
Log.i( TAG, "sample size is " + sampleSize );
return sampleSize;
}
/**
* Read a picture's degree from a file.
*
* @param file data source of a picture
* @return degrees range from 0 to 360
*/
public static int readPictureDegree( File file ) {
return readPictureDegree( file.getAbsolutePath() );
}
/**
* Read a picture's degree from a file, we use {@link ExifInterface} instead of {@link android.media.ExifInterface}
* to avoid some unexpected bugs.
*
* @param filePath file's absolute path which we can read data source of a picture from.
* @return degrees range from 0 to 360
*/
public static int readPictureDegree( String filePath ) {
int degree = 0;
try {
ExifInterface exifInterface = new ExifInterface( filePath );
int orientation = exifInterface.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL );
switch ( orientation ) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch ( Exception e ) {
e.printStackTrace();
}
Log.i( TAG, "ExifInterface, degree is " + degree );
return degree;
}
/**
* Rotate an bitmap to a specific angle.
*
* @param angle target angle
* @param bitmap data source
* @return Returns an immutable bitmap from subset of the source bitmap,
* transformed by the optional matrix. The new bitmap may be the
* same object as source, or a copy may have been made. It is
* initialized with the same density as the original bitmap.
* <p>
* If the source bitmap is immutable and the requested subset is the
* same as the source bitmap itself, then the source bitmap is
* returned and no new bitmap is created.
*/
public static Bitmap rotateBitmap( int angle, Bitmap bitmap ) {
if ( bitmap == null ) {
return null;
}
try {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Matrix matrix = new Matrix();
matrix.preRotate( angle );
return Bitmap.createBitmap( bitmap, 0, 0, width, height, matrix, true );
} catch ( Exception e ) {
e.printStackTrace();
return bitmap;
}
}
/**
* Get picture's absolute path according to its uri.
*
* @param context context
* @param uri picture's uri
* @return absolute path of uri.
*/
public static String getRealPathFromUri( Context context, Uri uri ) {
int sdkVersion = Build.VERSION.SDK_INT;
if ( sdkVersion >= 19 ) {
return getRealPathFromUriAboveApi19( context, uri );
} else {
return getRealPathFromUriBelowAPI19( context, uri );
}
}
/**
* Create a default {@link BitmapFactory.Options} .
* Note this options use rgb_565 and a proper inSampleSize in order to save memory.
*
* @param is data source of picture
* @param close whether to close data source
* @return options containing rgb_565 config and a proper inSampleSize.
*/
public static BitmapFactory.Options newDefaultOptions( InputStream is, boolean close ) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inSampleSize = BitmapHelper.findProperInSampleSize( is, close );
return options;
}
/**
* Save picture to local file.
*
* @param bitmap data source
* @param file local file to store picture.
*/
public static void savePicture( Bitmap bitmap, File file ) {
final long start = System.currentTimeMillis();
if ( bitmap == null || file == null ) {
Log.i( TAG, "保存失败, bitmap or file is null." );
return;
}
if ( file.getParentFile() != null && !file.getParentFile().exists() ) {
file.getParentFile().mkdirs();
}
try {
final FileOutputStream fos = new FileOutputStream( file );
bitmap.compress( Bitmap.CompressFormat.JPEG, 100, fos );
fos.flush();
fos.close();
if ( file.exists() ) {
Log.i( TAG, "保存成功" );
}
} catch ( Exception e ) {
e.printStackTrace();
}
Log.i( TAG, "saving picture costs " + ( System.currentTimeMillis() - start ) + "ms" );
}
/**
* 适配api19以下(不包括api19),根据uri获取图片的绝对路径
*
* @param context 上下文对象
* @param uri 图片的Uri
* @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
*/
private static String getRealPathFromUriBelowAPI19( Context context, Uri uri ) {
return getDataColumn( context, uri, null, null );
}
/**
* 适配api19及以上,根据uri获取图片的绝对路径
*
* @param context 上下文对象
* @param uri 图片的Uri
* @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
*/
@SuppressLint( "NewApi" )
private static String getRealPathFromUriAboveApi19( Context context, Uri uri ) {
String filePath = null;
try {
// 如果是document类型的 uri, 则通过document id来进行处理
if ( DocumentsContract.isDocumentUri( context, uri ) ) {
String documentId = DocumentsContract.getDocumentId( uri );
if ( isMediaDocument( uri ) ) {
// 使用':'分割
String id = documentId.split( ":" )[1];
String selection = MediaStore.Images.Media._ID + "=?";
String[] selectionArgs = {id};
filePath = getDataColumn( context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection, selectionArgs );
} else if ( isDownloadsDocument( uri ) ) {
Uri contentUri = ContentUris.withAppendedId( Uri.parse( "content://downloads/public_downloads" ), Long.valueOf( documentId ) );
filePath = getDataColumn( context, contentUri, null, null );
}
} else if ( "content".equalsIgnoreCase( uri.getScheme() ) ) {
filePath = getDataColumn( context, uri, null, null );
} else if ( "file".equals( uri.getScheme() ) ) {
filePath = uri.getPath();
}
} catch ( Exception e ) {
e.printStackTrace();
}
return filePath;
}
/**
* 获取数据库表中的 _data 列即返回Uri对应的文件路径
*/
private static String getDataColumn( Context context, Uri uri, String selection, String[] selectionArgs ) {
String path = null;
String[] projection = new String[]{MediaStore.Images.Media.DATA};
Cursor cursor = null;
try {
cursor = context.getContentResolver().query( uri, projection, selection, selectionArgs, null );
if ( cursor != null && cursor.moveToFirst() ) {
int columnIndex = cursor.getColumnIndexOrThrow( projection[0] );
path = cursor.getString( columnIndex );
}
} catch ( Exception e ) {
if ( cursor != null ) {
cursor.close();
cursor = null;
}
} finally {
if ( cursor != null ) {
cursor.close();
cursor = null;
}
}
return path;
}
/**
* @param uri the Uri to check
* @return Whether the Uri authority is MediaProvider
*/
private static boolean isMediaDocument( Uri uri ) {
return "com.android.providers.media.documents".equals( uri.getAuthority() );
}
/**
* @param uri the Uri to check
* @return Whether the Uri authority is DownloadsProvider
*/
private static boolean isDownloadsDocument( Uri uri ) {
return "com.android.providers.downloads.documents".equals( uri.getAuthority() );
}
public static int getMaxTextureSize() {
try {
// Safe minimum default size
final int IMAGE_MAX_BITMAP_DIMENSION = SIZE_DEFAULT;
// Get EGL Display
EGL10 egl = ( EGL10 ) EGLContext.getEGL();
EGLDisplay display = egl.eglGetDisplay( EGL10.EGL_DEFAULT_DISPLAY );
// Initialise
int[] version = new int[2];
egl.eglInitialize( display, version );
// Query total number of configurations
int[] totalConfigurations = new int[1];
egl.eglGetConfigs( display, null, 0, totalConfigurations );
// Query actual list configurations
EGLConfig[] configurationsList = new EGLConfig[totalConfigurations[0]];
egl.eglGetConfigs( display, configurationsList, totalConfigurations[0], totalConfigurations );
int[] textureSize = new int[1];
int maximumTextureSize = 0;
// Iterate through all the configurations to located the maximum texture size
for ( int i = 0; i < totalConfigurations[0]; i++ ) {
// Only need to check for width since opengl textures are always squared
egl.eglGetConfigAttrib( display, configurationsList[i], EGL10.EGL_MAX_PBUFFER_WIDTH, textureSize );
// Keep trackCustomEvent of the maximum texture size
if ( maximumTextureSize < textureSize[0] )
maximumTextureSize = textureSize[0];
}
// Release
egl.eglTerminate( display );
// Return largest texture size found, or default
return Math.max( maximumTextureSize, IMAGE_MAX_BITMAP_DIMENSION );
} catch ( Exception e ) {
e.printStackTrace();
}
return 0;
}
public static String bitmapToBase64( Bitmap bitmap ) {
String result = null;
try {
if ( bitmap != null ) {
result = Base64.encodeToString( bitmapToBytes( bitmap ), Base64.DEFAULT );
}
} catch ( Exception e ) {
e.printStackTrace();
}
return result;
}
public static Bitmap base64ToBitmap( String base64Data ) {
byte[] bytes = Base64.decode( base64Data, Base64.DEFAULT );
return BitmapFactory.decodeByteArray( bytes, 0, bytes.length );
}
/**
* 在系统返回的intent中获取图片信息并转化为uri
*
* @param data
* @return
*/
public static Uri convertUri( Context context, Intent data ) {
if ( data == null || data.getData() == null ) {
return null;
}
Uri localUri = data.getData();
String scheme = localUri.getScheme();
String imagePath = "";
if ( "content".equals( scheme ) ) {
String[] filePathColumns = {MediaStore.Images.Media.DATA};
Cursor c = context.getContentResolver().query( localUri, filePathColumns, null, null, null );
if ( c != null ) {
c.moveToFirst();
int columnIndex = c.getColumnIndex( filePathColumns[0] );
imagePath = c.getString( columnIndex );
c.close();
}
} else if ( "file".equals( scheme ) ) {//小米4选择云相册中的图片是根据此方法获得路径
imagePath = localUri.getPath();
}
if ( TextUtils.isEmpty( imagePath ) ) {
return localUri;
}
Uri uri = Uri.fromFile( new File( imagePath ) );
return uri != null ? uri : localUri;
}
public static Bitmap colorToBitmap( Context context, int colorResId ) {// drawable 转换成bitmap
Bitmap.Config config = Bitmap.Config.ARGB_8888;// 取drawable的颜色格式
Bitmap bitmap = Bitmap.createBitmap( 1, 1, config );// 建立对应bitmap
bitmap.eraseColor( context.getResources().getColor( colorResId ) );
return bitmap;
}
public static String getAlphaHexValue( float alpha ) {
String color = Integer.toHexString( ( int ) alpha * 255 );
return TextUtils.isEmpty( color ) ? color : color.toUpperCase();
}
/**
* 抓取本地视频缩略图(操作可能耗时,尽量异步进行)
*
* @param filePath
* @return
*/
public static Bitmap getVideoThumbnail( String filePath ) {
Bitmap b = null;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource( filePath );
b = retriever.getFrameAtTime();
} catch ( IllegalArgumentException e ) {
e.printStackTrace();
} catch ( RuntimeException e ) {
e.printStackTrace();
} finally {
try {
retriever.release();
} catch ( RuntimeException e ) {
e.printStackTrace();
}
}
return b;
}
public interface OnCompressListener {
void onCompressSuccess( byte[] data );
void onCompressFailed( String msg );
void onBeforeCompress();
}
}

View File

@@ -0,0 +1,199 @@
package com.mogo.utils;
import android.content.Context;
import android.graphics.Rect;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CheckUtils {
/**
* 检查任意Object是否为空
* <hr>
* shallow check : 不会检查容器内部的元素是否为空
*/
public static boolean isEmpty( Object obj) {
if (obj == null) {
return true;
}
if (obj instanceof Collection<?> ) {
// 检查各种Collection是否为空(List,Queue,Set)
return (( Collection<?> ) obj).isEmpty();
} else if (obj instanceof Map<?, ?> ) {
// 检查各种Map
return (( Map<?, ?> ) obj).isEmpty();
} else if (obj instanceof CharSequence ) {
// 检查各种CharSequence
return (( CharSequence ) obj).length() == 0;
} else if (obj.getClass().isArray()) {
// 检查各种base array
// return Array.getLength(obj) == 0;
if (obj instanceof Object[]) {
return (( Object[]) obj).length == 0;
} else if (obj instanceof int[]) {
return ((int[]) obj).length == 0;
} else if (obj instanceof long[]) {
return ((long[]) obj).length == 0;
} else if (obj instanceof short[]) {
return ((short[]) obj).length == 0;
} else if (obj instanceof double[]) {
return ((double[]) obj).length == 0;
} else if (obj instanceof float[]) {
return ((float[]) obj).length == 0;
} else if (obj instanceof boolean[]) {
return ((boolean[]) obj).length == 0;
} else if (obj instanceof char[]) {
return ((char[]) obj).length == 0;
} else if (obj instanceof byte[]) {
return ((byte[]) obj).length == 0;
}
}
return false;
}
public static boolean isExist( Object obj) {
return !isEmpty(obj);
}
public static boolean isContainsEmpty( Object... objs) {
if (isEmpty(objs)) {
return true;
}
for ( Object obj : objs) {
if (isEmpty(obj)) {
return true;
}
}
return false;
}
/**
* 是否为奇数
*/
public static boolean isOdd(int i) {
return i % 2 != 0;
}
/**
* 是否为偶数
*/
public static boolean isEven(int i) {
return i % 2 == 0;
}
/**
* 检查枚举组中是否包含指定枚举
*/
public static boolean isContainsEnum( @Nullable Enum<?>[] group, Enum<?> child) {
if (isEmpty(group)) {
return false;
}
for ( Enum<?> enums : group) {
if (enums == child) {
return true;
}
}
return false;
}
/**
* 快速点击事件
*/
private static long lastClickTime;
public static boolean isFastDoubleClick() {
long time = System.currentTimeMillis();
long timeD = time - lastClickTime;
long delayTime = 500L;
if (0L < timeD && timeD < delayTime) {
return true;
} else {
lastClickTime = time;
return false;
}
}
/**
* 网络是否可用
*/
public static boolean isNetworkConnected( Context context) {
if ( context == null ) {
return false;
}
ConnectivityManager cm = ( ConnectivityManager ) context.getSystemService( Context.CONNECTIVITY_SERVICE);
NetworkInfo network = null;
if (cm != null) {
network = cm.getActiveNetworkInfo();
}
return network != null && network.isAvailable() && network.isConnected();
}
/**
* 检查gps开关是否已打开
*/
public static boolean isGpsOpenStatus( Context context) {
if ( context == null ) {
return false;
}
String gps = Settings.System.getString(context.getContentResolver(), Settings.System.LOCATION_PROVIDERS_ALLOWED);
return !( TextUtils.isEmpty(gps) || !gps.contains("gps"));
}
/**
* 检查是否模拟位置
*/
public static boolean isOPenMockLocation( Context context) {
if ( context == null ) {
return false;
}
return Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0;
}
/**当前点击点是否在视图中*/
public static boolean isInsideView( MotionEvent event, View view) {
if (view != null && event != null) {
float eventX = event.getRawX();
float eventY = event.getRawY();
int[] contentArray = new int[2];
Rect contentRect = new Rect();
view.getLocationOnScreen(contentArray);
view.getDrawingRect(contentRect);
contentRect.offsetTo(contentArray[0], contentArray[1]);
return contentRect.contains((int) eventX, (int) eventY);
}
return false;
}
/**
* 判断扫描内容是否为url格式
*/
public static boolean isUrl( String url) {
if ( TextUtils.isEmpty(url)) {
return false;
}
String regex = "http(s)?://.*";
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m = pattern.matcher(url);
return m.matches();
}
}

View File

@@ -0,0 +1,573 @@
package com.mogo.utils;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CommonUtils {
private static String mMacSerial = null;
private static String mCPUSerial = null;
private static boolean isMacSerialNoObtained = false;
private static boolean isCPUSerialNoObtained = false;
private static final Pattern VERSION_NAME_PATTERN = Pattern.compile( "(\\d+\\.\\d+\\.\\d+)\\-*.*" );
public static String getAndroidID( Context context ) {
if ( context == null ) {
return "";
}
return Settings.Secure.getString( context.getContentResolver(), "android_id" );
}
public static String getCPUSerialno() {
if ( !TextUtils.isEmpty( mCPUSerial ) ) {
return mCPUSerial;
} else if ( isCPUSerialNoObtained ) {
mCPUSerial = "";
return mCPUSerial;
} else {
String str = "";
InputStreamReader ir = null;
LineNumberReader input = null;
try {
isCPUSerialNoObtained = true;
Process ex = Runtime.getRuntime().exec( "cat /proc/cpuinfo" );
if ( ex == null ) {
return null;
}
ir = new InputStreamReader( ex.getInputStream() );
input = new LineNumberReader( ir );
while ( null != str ) {
str = input.readLine();
if ( str != null ) {
mCPUSerial = str.trim();
break;
}
}
} catch ( IOException var4 ) {
var4.printStackTrace();
} finally {
if ( ir != null ) {
try {
ir.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
if ( input != null ) {
try {
input.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
return mCPUSerial;
}
}
public static int getVersionCode( Context context ) {
if ( context == null ) {
return 1;
}
String pkgName = context.getPackageName();
try {
PackageInfo e = context.getPackageManager().getPackageInfo( pkgName, 0 );
if ( e != null ) {
return e.versionCode;
}
} catch ( Exception var2 ) {
var2.printStackTrace();
}
return 1;
}
public static String getMacSerialno() {
if ( !TextUtils.isEmpty( mMacSerial ) ) {
return mMacSerial;
} else if ( isMacSerialNoObtained ) {
mMacSerial = "";
return mMacSerial;
} else {
String str = "";
InputStreamReader ir = null;
LineNumberReader input = null;
try {
isMacSerialNoObtained = true;
Process ex = Runtime.getRuntime().exec( "cat /sys/class/net/wlan0/address" );
if ( ex == null ) {
return null;
}
ir = new InputStreamReader( ex.getInputStream() );
input = new LineNumberReader( ir );
while ( null != str ) {
str = input.readLine();
if ( str != null ) {
mMacSerial = str.trim();
break;
}
}
} catch ( IOException var4 ) {
var4.printStackTrace();
} finally {
if ( ir != null ) {
try {
ir.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
if ( input != null ) {
try {
input.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
return mMacSerial;
}
}
/**
* 获取网络类型
*
* @return
*/
public static String getNetworkType( Context context ) {
String name = "UNKNOWN";
try {
ConnectivityManager connMgr = ( ConnectivityManager ) context.getSystemService( Context.CONNECTIVITY_SERVICE );
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if ( networkInfo != null ) {
if ( ConnectivityManager.TYPE_WIFI == networkInfo.getType() ) {
return "WIFI";
}
}
TelephonyManager tm = ( TelephonyManager ) context.getSystemService( Context.TELEPHONY_SERVICE );
if ( tm == null ) {
return name;
}
int type = tm.getNetworkType();
switch ( type ) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
name = "2G";
break;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
name = "3G";
break;
case TelephonyManager.NETWORK_TYPE_LTE:
name = "4G";
break;
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
name = "UNKNOWN";
break;
default:
name = "UNKNOWN";
break;
}
} catch ( Exception e ) {
}
return name;
}
/**
* 得到手机的IMEI号
*
* @return
*/
public static String getIMEI( Context context ) {
try {
TelephonyManager telephonyManager = ( TelephonyManager ) context.getSystemService( Context.TELEPHONY_SERVICE );
if ( telephonyManager != null &&
ContextCompat.checkSelfPermission( context, Manifest.permission.READ_PHONE_STATE ) == PackageManager.PERMISSION_GRANTED ) {
return telephonyManager.getDeviceId();
}
} catch ( Exception e ) {
}
return "";
}
/**
* 得到手机的IMSI号
*
* @return
*/
public static String getIMSI( Context context ) {
try {
TelephonyManager telephonyManager = ( TelephonyManager ) context.getSystemService( Context.TELEPHONY_SERVICE );
if ( telephonyManager != null &&
ActivityCompat.checkSelfPermission( context, Manifest.permission.READ_PHONE_STATE ) == PackageManager.PERMISSION_GRANTED ) {
return telephonyManager.getSubscriberId();
}
} catch ( Exception e ) {
}
return "";
}
public static String checkSimState( Context context ) {
String mString = "";
if ( context == null ) {
return mString;
}
TelephonyManager telephonyManager = ( TelephonyManager ) context.getSystemService( Context.TELEPHONY_SERVICE );
int simState = 0;
if ( telephonyManager != null ) {
simState = telephonyManager.getSimState();
}
switch ( simState ) {
case TelephonyManager.SIM_STATE_ABSENT:
mString = "无卡";
// do something
break;
case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
mString = "需要NetworkPIN解锁";
// do something
break;
case TelephonyManager.SIM_STATE_PIN_REQUIRED:
mString = "需要PIN解锁";
// do something
break;
case TelephonyManager.SIM_STATE_PUK_REQUIRED:
mString = "需要PUN解锁";
// do something
break;
case TelephonyManager.SIM_STATE_READY:
mString = "良好";
// do something
break;
case TelephonyManager.SIM_STATE_UNKNOWN:
mString = "未知状态";
// do something
break;
}
return mString;
}
/**
* 获取路由器Mac
*/
public static String getRouterMac( Context context ) {
if ( context == null ) {
return "";
}
WifiManager wifi = ( WifiManager ) context.getApplicationContext().getSystemService( Context.WIFI_SERVICE );
if ( wifi != null && wifi.getConnectionInfo() != null ) {
return wifi.getConnectionInfo().getBSSID();
}
return "";
}
/**
* 获取wifi名字
*/
public static String getWifiName( Context context ) {
if ( context == null ) {
return "";
}
WifiManager wifi = ( WifiManager ) context.getApplicationContext().getSystemService( Context.WIFI_SERVICE );
if ( wifi != null && wifi.getConnectionInfo() != null ) {
return wifi.getConnectionInfo().getSSID();
}
return "";
}
public static String getMobileIP( Context ctx ) {
if ( ctx == null ) {
return "";
}
ConnectivityManager mConnectivityManager = ( ConnectivityManager ) ctx.getSystemService( Context.CONNECTIVITY_SERVICE );// 获取系统的连接服务
// 实例化mActiveNetInfo对象
NetworkInfo mActiveNetInfo = null;// 获取网络连接的信息
if ( mConnectivityManager != null ) {
mActiveNetInfo = mConnectivityManager.getActiveNetworkInfo();
}
if ( mActiveNetInfo == null ) {
return "";
} else {
return getIp( mActiveNetInfo );
}
}
// 显示IP信息
private static String getIp( NetworkInfo mActiveNetInfo ) {
if ( mActiveNetInfo == null ) {
return "";
}
// 如果是WIFI网络
if ( mActiveNetInfo.getType() == ConnectivityManager.TYPE_WIFI ) {
return getLocalIPAddress();
}
// 如果是手机网络
else if ( mActiveNetInfo.getType() == ConnectivityManager.TYPE_MOBILE ) {
return getLocalIPAddress();
} else {
return "";
}
}
// 获取本地IP函数
private static String getLocalIPAddress() {
try {
Enumeration< NetworkInterface > mEnumeration = NetworkInterface.getNetworkInterfaces();
if ( mEnumeration != null ) {
while ( mEnumeration.hasMoreElements() ) {
NetworkInterface intf = mEnumeration.nextElement();
if ( intf != null && intf.getInetAddresses() != null ) {
Enumeration< InetAddress > enumIPAddr = intf.getInetAddresses();
while ( enumIPAddr.hasMoreElements() ) {
InetAddress inetAddress = enumIPAddr.nextElement();
// 如果不是回环地址
if ( inetAddress != null && !inetAddress.isLoopbackAddress() ) {
// 直接返回本地IP地址
return inetAddress.getHostAddress();
}
}
}
}
}
} catch ( SocketException ex ) {
ex.printStackTrace();
}
return "";
}
public static String getVersionName( Context context ) {
return getVersionName( context, true );
}
public static String getVersionName( Context context, boolean fullVersionName ) {
String appVersion = "";
try {
String packageName = context.getApplicationInfo().packageName;
appVersion = context.getPackageManager().getPackageInfo( packageName, 0 ).versionName;
if ( !fullVersionName && appVersion != null && appVersion.length() > 0 ) {
Matcher matcher = VERSION_NAME_PATTERN.matcher( appVersion );
if ( matcher.matches() ) {
appVersion = matcher.group( 1 );
}
}
} catch ( Exception e ) {
e.printStackTrace();
}
return appVersion;
}
public static String getAppName( Context context ) {
if ( context == null ) {
return "";
}
PackageManager pm = context.getPackageManager();
return context.getApplicationInfo().loadLabel( pm ).toString();
}
public static String getModel() {
String temp = Build.MODEL;
return TextUtils.isEmpty( temp ) ? "" : temp;
}
@TargetApi( Build.VERSION_CODES.JELLY_BEAN )
public static long getLeftMemory( Context context ) {
if ( context == null ) {
return -1;
}
if ( Build.VERSION.SDK_INT >= 16 ) {
ActivityManager mActivityManager = ( ActivityManager ) context.getSystemService( Context.ACTIVITY_SERVICE );
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
mActivityManager.getMemoryInfo( mi );
return ( mi.totalMem - mi.availMem ) / 1000;
}
return -1;
}
public static String encode( String string ) {
try {
return URLEncoder.encode( string, "UTF-8" );
} catch ( UnsupportedEncodingException e ) {
e.printStackTrace();
return "";
}
}
public static String decode( String string ) {
try {
return URLDecoder.decode( string, "UTF-8" );
} catch ( UnsupportedEncodingException e ) {
e.printStackTrace();
return "";
}
}
public static String getProcessName( Context context, int pid ) {
try {
ActivityManager manager = ( ActivityManager ) context.getSystemService( Context.ACTIVITY_SERVICE );
for ( ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses() ) {
if ( processInfo.pid == pid ) {
return processInfo.processName;
}
}
} catch ( Exception e ) {
}
return "";
}
public static int getStatusBarHeight( Context context ) {
if ( context == null ) {
return 0;
}
int statusBarHeight = 0;
try {
Class c = Class.forName( "com.android.internal.R$dimen" );
Object obj = c.newInstance();
Field field = c.getField( "status_bar_height" );
int x = Integer.parseInt( field.get( obj ).toString() );
statusBarHeight = context.getResources().getDimensionPixelSize( x );
} catch ( Exception e ) {
}
if ( statusBarHeight > 0 ) {
return statusBarHeight;
}
try {
int resourceId = context.getResources().getIdentifier( "status_bar_height", "dimen", "android" );
if ( resourceId > 0 ) {
statusBarHeight = context.getResources().getDimensionPixelSize( resourceId );
}
} catch ( Exception e ) {
}
return statusBarHeight;
}
/**
* 获取某个应用的版本名称
*
* @param context 应用上下文
* @param packageName 包名,如果为空,将获取 context 本身的版本名称
* @return
*/
public static String getVersionName( @NonNull Context context, @Nullable String packageName ) {
try {
packageName = TextUtils.isEmpty( packageName ) ? context.getPackageName() : packageName;
PackageManager packageManager = context.getPackageManager();
PackageInfo packInfo = packageManager.getPackageInfo( packageName, 0 );
return packInfo.versionName;
} catch ( Exception e ) {
return "";
}
}
/**
* 获取某个应用的版本号
*
* @param context 应用上下文
* @param packageName 包名,如果为空,将获取 context 本身的版本号
* @return
*/
public static int getVersionCode( @NonNull Context context, @Nullable String packageName ) {
try {
packageName = TextUtils.isEmpty( packageName ) ? context.getPackageName() : packageName;
PackageManager packageManager = context.getPackageManager();
PackageInfo packInfo = packageManager.getPackageInfo( packageName, 0 );
return packInfo.versionCode;
} catch ( Exception e ) {
return 0;
}
}
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
/**
* Schedule a countdown until a time in the future, with
* regular notifications on intervals along the way.
*
* Example of showing a 30 second countdown in a text field:
*
* <pre class="prettyprint">
* new CountDownTimer(30000, 1000) {
*
* public void onTick(long millisUntilFinished) {
* mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
* }
*
* public void onFinish() {
* mTextField.setText("done!");
* }
* }.start();
* </pre>
*
* The calls to {@link #onTick(long)} are synchronized to this object so that
* one call to {@link #onTick(long)} won't ever occur before the previous
* callback is complete. This is only relevant when the implementation of
* {@link #onTick(long)} takes an amount of time to execute that is significant
* compared to the countdown interval.
*/
public abstract class CountDownTimer {
/**
* Millis since epoch when alarm should stop.
*/
private final long mMillisInFuture;
/**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval;
private long mStopTimeInFuture;
/**
* boolean representing if the timer was cancelled
*/
private boolean mCancelled = false;
/**
* @param millisInFuture The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param countDownInterval The interval along the way to receive
* {@link #onTick(long)} callbacks.
*/
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
}
/**
* Cancel the countdown.
*/
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}
/**
* Start the countdown.
*/
public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
}
/**
* Callback fired on regular interval.
* @param millisUntilFinished The amount of time until finished.
*/
public abstract void onTick(long millisUntilFinished);
/**
* Callback fired when the time is up.
*/
public abstract void onFinish();
private static final int MSG = 1;
// handles counting down
private Handler mHandler = new Handler() {
@Override
public void handleMessage( Message msg) {
synchronized (CountDownTimer.this) {
if (mCancelled) {
return;
}
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
} else {
long lastTickStart = SystemClock.elapsedRealtime();
onTick(millisLeft);
// take into account user's onTick taking time to execute
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
// special case: user's onTick took more than interval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval;
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
}

View File

@@ -0,0 +1,452 @@
package com.mogo.utils;
import android.text.TextUtils;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Pattern;
public class DateTimeUtils {
public static final int DATETIME_FIELD_REFERSH = 10; // 刷新时间(分钟),
//
public static final long ONE_SECOND = 1000L;
public static final long ONE_MINUTE = ONE_SECOND * 60L;
public static final long ONE_HOUR = ONE_MINUTE * 60L;
public static final long ONE_DAY = ONE_HOUR * 24L;
public static final long ONE_MONTH = ONE_DAY * 24L;
public static final long ONE_YEAR = ONE_MONTH * 24L;
// 下面的pattern在print和parse时都可以使用
public static final String MM_Yue_dd_Ri = "MM月dd日";
public static final String MM_Yue_dd_Ri_HH_mm = "MM月dd日 HH:mm";
public static final String M_Yue_d_Ri = "M月d日";
public static final String d_Ri = "d日";
public static final String yyyyMMdd = "yyyyMMdd";
public static final String yyyy_MM_dd = "yyyy-MM-dd";
public static final String yyyy_MM = "yyyy-MM";
public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
public static final String yyyy_MM_dd_HH_mm = "yyyy-MM-dd HH:mm";
public static final String yyyyMMddHHmmss = "yyyyMMddHHmmss";
public static final String HH_mm = "HH:mm";
public static final String yyyy_Nian_MM_Yue_dd_Ri = "yyyy年MM月dd日";
public static final String yyyy_Nian_MM_Yue = "yyyy年MM月";
public static final String MM_yy = "MM/yy";
public static final String dd_MM = "dd/MM";
public static final String MM_dd = "MM-dd";
private static final String pattern2 = "MM 月 dd";
// 下面的pattern是print时用parse时不应使用只有时间没有日期
public static final String HH_mm_ss = "HH:mm:ss";
private static final String[] PATTERNS = {yyyy_MM_dd_HH_mm_ss, yyyy_MM_dd_HH_mm, yyyy_MM_dd, yyyyMMdd};
public static Calendar cleanCalendarTime( Calendar c) {
c.set( Calendar.HOUR_OF_DAY, 0);
c.set( Calendar.MINUTE, 0);
c.set( Calendar.SECOND, 0);
c.set( Calendar.MILLISECOND, 0);
return c;
}
/**
* 获得指定日期表示格式转换成Calendar的格式
*
* @param src
* @param fallback 若无法转换,返回一个默认值
* @return
*/
public static <T> Calendar getCalendar( T src, Calendar fallback) {
if (src != null) {
try {
return getCalendar(src);
} catch ( Exception e) {
}
}
return ( Calendar ) fallback.clone();
}
/**
* 获得日期类型
*
* @param src 任何可以表示时间的类型目前支持Calendar,Date,long,String
* @return Calendar类型表示的时间
* @throws IllegalArgumentException
*/
public static <T> Calendar getCalendar( T src) {
Calendar calendar = Calendar.getInstance();
calendar.setLenient(false);
if (src == null) {
return null;
} else if (src instanceof Calendar ) {
calendar.setTimeInMillis((( Calendar ) src).getTimeInMillis());
} else if (src instanceof Date ) {
calendar.setTime(( Date ) src);
} else if (src instanceof Long ) {
calendar.setTimeInMillis(( Long ) src);
} else if (src instanceof String ) {
String nSrc = ( String ) src;
if ( TextUtils.isEmpty(nSrc)) {
return null;
}
try {
// 直接匹配的时候不能匹配到月份或日期不是2位数的情况
if ( Pattern.compile("\\d{4}年\\d{1,2}月\\d{1,2}日").matcher(nSrc).find()) {
nSrc = fixDateString(nSrc);
return getCalendarByPattern(nSrc, yyyy_MM_dd);
}
return getCalendarByPatterns(nSrc, PATTERNS);
} catch ( Exception e) {
try {
calendar.setTimeInMillis( Long.valueOf(nSrc));
} catch ( NumberFormatException e1) {
throw new IllegalArgumentException(e1);
}
}
} else {
throw new IllegalArgumentException();
}
return calendar;
}
/**
* YYYY年MM月DD日 --> YYYY-MM-DD
*/
private static String fixDateString( String date) {
if ( TextUtils.isEmpty(date)) {
return date;
}
String[] dateArray = date.split("[年月日]");
if (dateArray.length == 1) {
dateArray = date.split("-");
}
for (int i = 0; i < 3; i++) {
if (dateArray[i].length() == 1) {
dateArray[i] = "0" + dateArray[i];
}
}
return dateArray[0] + "-" + dateArray[1] + "-" + dateArray[2];
}
/**
* 匹配pattern获得时间若无法解析抛出异常
*
* @param dateTimeStr
* @param patternStr
* @return
* @throws IllegalArgumentException
*/
public static Calendar getCalendarByPattern( String dateTimeStr, String patternStr) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(patternStr, Locale.US);
sdf.setLenient(false);
Date d = sdf.parse(dateTimeStr);
Calendar c = Calendar.getInstance();
c.setLenient(false);
c.setTimeInMillis(d.getTime());
return c;
} catch ( Exception e) {
throw new IllegalArgumentException(e);
}
}
/**
* 匹配pattern数组中的所有pattern解析时间格式若没有可以解析的方式则抛出异常
*
* @param dateTimeStr
* @param patternStr
* @return
* @throws IllegalArgumentException
*/
public static Calendar getCalendarByPatterns( String dateTimeStr, String[] patternStr) {
for ( String string : patternStr) {
try {
return getCalendarByPattern(dateTimeStr, string);
} catch ( Exception e) {
}
}
throw new IllegalArgumentException();
}
/**
* 是否有服务器时间
*/
public static boolean hasServerTime;
/**
* 本地时间和服务器时间的间隔 time server local gap millis
*/
public static long tslgapm;
/**
* 本地时间和服务器时间的间隔 time server string
*/
public static String tss;
/**
* 获取与服务器时间矫正过的当前时间
*/
public static Calendar getCurrentDateTime() {
Calendar now = Calendar.getInstance();
now.setLenient(false);
if (hasServerTime) {
now.setTimeInMillis(now.getTimeInMillis() + tslgapm);
}
return now;
}
public static Calendar getCurrentDate() {
return cleanCalendarTime(getCurrentDateTime());
}
public static long getCurTimeInMillis(){
return System.currentTimeMillis();
}
/**
* login时server的日期
*
* @return
*/
public static Calendar getLoginServerDate() {
return getCalendar(tss);
}
/**
* 获得基准日期增加间隔天
*/
public static Calendar getDateAdd( Calendar start, int interval) {
if (start == null) {
return null;
}
Calendar c = ( Calendar ) start.clone();
c.add( Calendar.DATE, interval);
return c;
}
/**
* 获得时间间隔
*
* @param from
* @param to
* @param unit 时间间隔单位{@link DateTimeUtils#ONE_SECOND},{@link DateTimeUtils#ONE_MINUTE},
* {@link DateTimeUtils#ONE_HOUR}, {@link DateTimeUtils#ONE_DAY}
* @return
*/
public static long getIntervalTimes( Calendar from, Calendar to, long unit) {
if (from == null || to == null) {
return 0;
}
return Math.abs(from.getTimeInMillis() - to.getTimeInMillis()) / unit;
}
/**
* 获得日期间隔 忽略小时
*
* @param startdate
* @param enddate
* @return
*/
public static int getIntervalDays( String startdate, String enddate, String pattern) {
int betweenDays = 0;
if (startdate == null || enddate == null) {
return betweenDays;
}
Calendar d1 = getCalendarByPattern(startdate, pattern);
Calendar d2 = getCalendarByPattern(enddate, pattern);
return getIntervalDays(d1, d2);
}
public static <T> int getIntervalDays(T from, T to) {
Calendar startdate = getCalendar(from);
Calendar enddate = getCalendar(to);
cleanCalendarTime(startdate);
cleanCalendarTime(enddate);
return (int) getIntervalTimes(startdate, enddate, ONE_DAY);
}
private static String[] weekdays = {"", "周日", "周一", "周二", "周三", "周四", "周五", "周六",};
private static String[] weekdays1 = {"", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六",};
/**
* calendar --> 周一~周日
*/
public static String getWeekDayFromCalendar( Calendar cal) {
if (cal == null) {
throw new IllegalArgumentException();
}
return weekdays[cal.get( Calendar.DAY_OF_WEEK)];
}
/**
* calendar --> 星期日~星期六
*/
public static String getWeekDayFromCalendar1( Calendar cal) {
if (cal == null) {
throw new IllegalArgumentException();
}
return weekdays1[cal.get( Calendar.DAY_OF_WEEK)];
}
/**
* 判断是否是闰年 这个方法不要改动!
*
* @param date(2009-10-13 || 2009年10月13日 || 2009)
* @return true 是 false 不是
*/
public static boolean isLeapyear( String date) {
Calendar calendar = getCalendar(date);
if (calendar != null) {
int year = calendar.get( Calendar.YEAR);
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
return false;
}
// 是否到刷新时间
public static boolean isRefersh(long beforeTime) {
return isRefersh(DATETIME_FIELD_REFERSH * 1000 * 60, beforeTime);
}
// 是否到刷新时间
public static boolean isRefersh(long gap, long beforeTime) {
return new Date().getTime() - beforeTime >= gap;
}
public static String printCalendarByPattern( Calendar c, String patternStr) {
if (null == c || null == patternStr) {
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat(patternStr, Locale.US);
sdf.setLenient(false);
return sdf.format(c.getTime());
}
/**
* 只通过年月日比较两个Calendar
*
* @return c1 < c2 = -1 ; c1 > c2 = 1 ; c1 == c2 = 0
*/
public static int compareCalendarIgnoreTime( Calendar c1, Calendar c2) {
if (c1.get( Calendar.YEAR) > c2.get( Calendar.YEAR)) {
return 1;
} else if (c1.get( Calendar.YEAR) < c2.get( Calendar.YEAR)) {
return -1;
} else {
if (c1.get( Calendar.MONTH) > c2.get( Calendar.MONTH)) {
return 1;
} else if (c1.get( Calendar.MONTH) < c2.get( Calendar.MONTH)) {
return -1;
} else {
if (c1.get( Calendar.DAY_OF_MONTH) > c2.get( Calendar.DAY_OF_MONTH)) {
return 1;
} else if (c1.get( Calendar.DAY_OF_MONTH) < c2.get( Calendar.DAY_OF_MONTH)) {
return -1;
} else {
return 0;
}
}
}
}
public static void setTimeWithHHmm( Calendar src, String HH_mm) {
if ( TextUtils.isEmpty(HH_mm) || null == src) {
return;
}
String s[] = HH_mm.split(":");
if (s.length != 2) {
return;
}
try {
cleanCalendarTime(src);
src.set( Calendar.HOUR_OF_DAY, Integer.valueOf(s[0]));
src.set( Calendar.MINUTE, Integer.valueOf(s[1]));
} catch ( NumberFormatException e) {
}
}
public static int getDayDiff(long time1, long time2) {
Date dateA = new Date(time1);
Date dateB = new Date(time2);
Calendar calDateA = Calendar.getInstance();
calDateA.setTime(dateA);
Calendar calDateB = Calendar.getInstance();
calDateB.setTime(dateB);
if (calDateA.get( Calendar.YEAR) == calDateB.get( Calendar.YEAR)
&& calDateA.get( Calendar.MONTH) == calDateB.get( Calendar.MONTH)) {
return calDateB.get( Calendar.DAY_OF_MONTH) - calDateA.get( Calendar.DAY_OF_MONTH);
} else if (calDateA.get( Calendar.YEAR) == calDateB.get( Calendar.YEAR) && ((calDateB.get( Calendar.MONTH) - calDateA.get( Calendar.MONTH)) == 1
|| (calDateB.get( Calendar.MONTH) - calDateA.get( Calendar.MONTH)) == -11)) {//处理跨年情况
return calDateB.get( Calendar.DAY_OF_MONTH) + (getCurrentMonthLastDay() - calDateA.get( Calendar.DAY_OF_MONTH));
}
return 0;
}
public static int getCurrentMonthLastDay() {
Calendar a = Calendar.getInstance();
a.set( Calendar.DATE, 1);
a.roll( Calendar.DATE, -1);
int maxDate = a.get( Calendar.DATE);
return maxDate;
}
public static String convertToChineseWeekNumber( int number) {
switch (number) {
case 1:
return "";
case 2:
return "";
case 3:
return "";
case 4:
return "";
case 5:
return "";
case 6:
return "";
case 0:
return "";
default:
return "";
}
}
/**
* 获取分钟数
*/
private static int getMinutes( String str, int blankCount) {
int ret = 0;
if (str.split(" ").length < (blankCount + 1)) {
return ret;
}
String hh_mm = str.split(" ")[blankCount];
String s = "";
if (!TextUtils.isEmpty(hh_mm) && hh_mm.length() >= 4) {
s = hh_mm.substring(3);
}
try {
ret = Integer.parseInt(s);
} catch ( NumberFormatException e) {
e.printStackTrace();
}
return ret;
}
/**
* 获取 06月07 格式的日期
* @param timestamp 时间戳
* @return
*/
public static String getTimeText( long timestamp) {
SimpleDateFormat format = new SimpleDateFormat(yyyy_Nian_MM_Yue_dd_Ri, Locale.US);
String strStart = format.format(new Date(timestamp));
return strStart;
}
}

View File

@@ -0,0 +1,118 @@
package com.mogo.utils;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import androidx.core.content.ContextCompat;
import com.mogo.utils.storage.SharedPrefsMgr;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public final class DeviceIdUtils {
public static final String KEY_DEVICE_ID = "deviceId";
private DeviceIdUtils() {}
private static void saveDeviceId( Context context, String deviceId){
SharedPrefsMgr.getInstance(context).putString(KEY_DEVICE_ID, deviceId);
}
public static String getDeviceId( Context context) {
if(context == null){
throw new NullPointerException("context must not be null.");
}
final Context appContext = context.getApplicationContext();
String deviceId = SharedPrefsMgr.getInstance( context ).getString( KEY_DEVICE_ID );
if ( TextUtils.isEmpty( deviceId )) {
deviceId = getDeviceIdInternal(appContext);
if (!TextUtils.isEmpty(deviceId)) {
saveDeviceId(appContext,deviceId);
} else {
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
if ( ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE ) == PackageManager.PERMISSION_GRANTED ) {
deviceId = (( TelephonyManager ) appContext.getSystemService( Context.TELEPHONY_SERVICE)).getSimSerialNumber();
}
}else{
deviceId = (( TelephonyManager ) appContext.getSystemService( Context.TELEPHONY_SERVICE)).getSimSerialNumber();
}
if (!TextUtils.isEmpty(deviceId)) {
saveDeviceId(appContext,deviceId);
} else {
deviceId = getDeviceSerial();
if (!TextUtils.isEmpty(deviceId) && !deviceId.equalsIgnoreCase("unknown")) {
saveDeviceId(appContext,deviceId);
} else {
deviceId = getAndroidId(appContext);
if (!TextUtils.isEmpty(deviceId)) {
saveDeviceId(appContext,deviceId);
} else {
deviceId = String.valueOf( System.currentTimeMillis());
saveDeviceId(appContext,deviceId);
}
}
}
}
}
return deviceId;
}
private static String getDeviceIdInternal( Context context) {
String id = "";
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
if ( ContextCompat.checkSelfPermission( context, Manifest.permission.READ_PHONE_STATE ) != PackageManager.PERMISSION_GRANTED ) {
return id;
}
}
TelephonyManager telephonymanager = ( TelephonyManager ) context.getSystemService( Context.TELEPHONY_SERVICE);
if (telephonymanager != null) {
id = telephonymanager.getDeviceId();
if ( TextUtils.isEmpty(id))
id = "";
}
return id;
}
private static String getAndroidId( Context context) {
String s = "";
s = Settings.Secure.getString(context.getContentResolver(), "android_id");
if ( TextUtils.isEmpty(s))
s = "";
return s;
}
private static String getDeviceSerial() {
String serial = "unknown";
try {
Class clazz = Class.forName("android.os.Build");
Class paraTypes = Class.forName("java.lang.String");
Method method = clazz.getDeclaredMethod("getString", paraTypes);
if (!method.isAccessible()) {
method.setAccessible(true);
}
serial = ( String ) method.invoke(new Build(), "ro.serialno");
} catch ( ClassNotFoundException e) {
e.printStackTrace();
} catch ( NoSuchMethodException e) {
e.printStackTrace();
} catch ( InvocationTargetException e) {
e.printStackTrace();
} catch ( IllegalAccessException e) {
e.printStackTrace();
}
return serial;
}
}

View File

@@ -0,0 +1,250 @@
package com.mogo.utils;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Base64;
import androidx.core.content.FileProvider;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
public class FileUtils {
public static boolean createFileDir( String fileDir ) {
if ( TextUtils.isEmpty( fileDir ) ) {
return false;
}
try {
File dir = new File( fileDir );
return dir.exists() || dir.mkdir();
} catch ( Exception e ) {
return false;
}
}
public static boolean createFileDir( File dir ) {
if ( dir == null ) {
return false;
}
try {
return dir.exists() || dir.mkdir();
} catch ( Exception e ) {
return false;
}
}
public static void writeToFile( String fileDir, String fileName, String content ) {
if ( fileDir == null || fileName == null || content == null ) {
return;
}
if ( !createFileDir( fileDir ) ) {
return;
}
FileOutputStream fos = null;
OutputStreamWriter osw = null;
try {
fos = new FileOutputStream( fileDir + fileName, true );
osw = new OutputStreamWriter( fos );
osw.write( content );
osw.flush();
} catch ( IOException e ) {
e.printStackTrace();
} finally {
IOUtils.closeSilently( fos );
IOUtils.closeSilently( osw );
}
}
/**
* Read a text file into a String, optionally limiting the length.
*/
public static String readTextFile( File file ) {
InputStream is = null;
BufferedInputStream bis = null;
ByteArrayOutputStream bos = null;
String text = null;
try {
is = new FileInputStream( file );
bis = new BufferedInputStream( is );
bos = new ByteArrayOutputStream();
int len;
byte[] data = new byte[1024];
do {
len = bis.read( data );
if ( len > 0 ) bos.write( data, 0, len );
} while ( len == data.length );
text = bos.toString();
} catch ( Exception e ) {
e.printStackTrace();
} finally {
IOUtils.closeSilently( is );
IOUtils.closeSilently( bis );
IOUtils.closeSilently( bos );
}
return text;
}
public static String fileToBase64( File file ) {
String base64 = null;
InputStream in = null;
try {
in = new FileInputStream( file );
byte[] bytes = new byte[in.available()];
int length = in.read( bytes );
base64 = Base64.encodeToString( bytes, 0, length, Base64.DEFAULT );
} catch ( FileNotFoundException e ) {
e.printStackTrace();
} catch ( IOException e ) {
e.printStackTrace();
} finally {
IOUtils.closeSilently( in );
}
return base64;
}
/**
* Writes string to file. Basically same as "echo -n $string > $filename"
*/
public static void stringToFile( String filename, String string ) {
FileWriter out = null;
try {
out = new FileWriter( filename );
out.write( string );
} catch ( Exception e ) {
e.printStackTrace();
} finally {
IOUtils.closeSilently( out );
}
}
public static InputStream stringToStream( String content ) {
InputStream inputStream = null;
try {
inputStream = new ByteArrayInputStream( content.getBytes() );
} catch ( Exception e ) {
e.printStackTrace();
}
return inputStream;
}
public static String streamToString( InputStream is ) throws IOException {
String content = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int i = -1;
while ( ( i = is.read() ) != -1 ) {
bos.write( i );
}
content = bos.toString();
} catch ( Exception e ) {
e.printStackTrace();
}
return content;
}
public static String getStringFromFile( Context context, String fileName ) {
FileInputStream fis = null;
ByteArrayOutputStream os = null;
String content = null;
try {
fis = context.openFileInput( fileName );
os = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = -1;
while ( ( length = fis.read( buffer ) ) != -1 ) {
os.write( buffer, 0, length );
}
content = os.toString();
} catch ( Exception e ) {
e.printStackTrace();
} finally {
IOUtils.closeSilently( fis );
IOUtils.closeSilently( os );
}
return content;
}
public static InputStream getStreamFromFile( Context context, String fileName ) {
FileInputStream fis = null;
try {
fis = context.openFileInput( fileName );
} catch ( Exception e ) {
e.printStackTrace();
}
return fis;
}
public static void saveStringToFile( Context context, String content, String fileName ) {
try {
FileOutputStream fos = context.openFileOutput( fileName, Context.MODE_PRIVATE );
fos.write( content.getBytes() );
IOUtils.closeSilently( fos );
} catch ( Exception e ) {
e.printStackTrace();
}
}
/**
* 将scheme为file的uri转成FileProvider 提供的content uri
*/
public static Uri convertFileUriToFileProviderUri( Context context, Uri uri ) {
if ( uri == null ) return null;
if ( ContentResolver.SCHEME_FILE.equals( uri.getScheme() ) ) {
return getUriForFile( context, new File( uri.getPath() ) );
}
return uri;
}
/**
* 创建一个用于拍照图片输出路径的Uri (FileProvider)
*/
public static Uri getUriForFile( Context context, File file ) {
return FileProvider.getUriForFile( context, getFileProviderName( context ), file );
}
public static String getFileProviderName( Context context ) {
return context.getPackageName() + ".fileprovider";
}
/**
* 把Uri 解析出文件绝对路径
*/
public static String parseOwnUri( Context context, Uri uri ) {
if ( uri == null ) return null;
String path;
if ( TextUtils.equals( uri.getAuthority(), getFileProviderName( context ) ) ) {
path = new File( uri.getPath() ).getAbsolutePath();
} else {
path = uri.getPath();
}
return path;
}
public static String getFileStreamPath( Context context, String name ) {
String absFileName = null;
try {
File file = context.getFileStreamPath( name );
if ( file != null && file.exists() ) {
absFileName = file.getAbsolutePath();
}
} catch ( Exception e ) {
e.printStackTrace();
}
return absFileName;
}
}

View File

@@ -0,0 +1,49 @@
package com.mogo.utils;
import androidx.annotation.Nullable;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.InputStream;
public class IOUtils {
public static byte[] inputToBytes( InputStream is) {
if(is == null){
return null;
}
ByteArrayOutputStream bos = null;
byte[] result = null;
try{
bos = new ByteArrayOutputStream();
byte[] buff = new byte[100];
int rc = 0;
while ((rc = is.read(buff, 0, 100)) > 0) {
bos.write(buff, 0, rc);
}
result = bos.toByteArray();
}catch ( Exception e){
e.printStackTrace();
result = null;
}finally {
closeSilently(bos);
}
return result;
}
public static void closeSilently(@Nullable Closeable c) {
if (c == null) return;
try {
c.close();
c = null;
} catch ( Throwable t) {
t.printStackTrace();
}
}
}

View File

@@ -0,0 +1,361 @@
package com.mogo.utils;
import android.net.Uri;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeMap;
public class IntentUtils {
/**
* urlDecode的时候会把'+'转换成' '
*
* @param uri
* @return
*/
public static TreeMap< String, String > splitParams2( Uri uri) {
if (uri == null) {
return new TreeMap< String, String >();
}
Set< String > keys = getQueryParameterNames(uri);
TreeMap< String, String > map = new TreeMap< String, String >();
for ( String key : keys) {
map.put(key, getQueryParameter(uri, key));
}
return map;
}
/**
* urlDecode时 <br />
* 4.0版本以后 '+' ->' ' <br />
* 2.3版本之前 '+' -> '+'<br />
*
* @param uri
* @return
*/
public static HashMap< String, String > splitParams1( Uri uri) {
if (uri == null) {
return new HashMap< String, String >();
}
Set< String > keys = getQueryParameterNames(uri);
HashMap< String, String > map = new HashMap< String, String >(keys.size());
for ( String key : keys) {
map.put(key, uri.getQueryParameter(key));
}
return map;
}
/**
* Searches the query string for the first value with the given key.
*
* <p>
* <strong>Warning:</strong> this decoded the '+' character as ' '.
*
* @param key which will be encoded
* @throws UnsupportedOperationException if this isn't a hierarchical URI
* @throws NullPointerException if key is null
* @return the decoded value or null if no parameter is found
*/
public static String getQueryParameter( Uri uri, String key) {
if (uri.isOpaque()) {
throw new UnsupportedOperationException("This isn't a hierarchical URI.");
}
if (key == null) {
throw new NullPointerException("key");
}
final String query = uri.getEncodedQuery();
if (query == null) {
return null;
}
final String encodedKey = Uri.encode(key, null);
final int length = query.length();
int start = 0;
do {
int nextAmpersand = query.indexOf('&', start);
int end = nextAmpersand != -1 ? nextAmpersand : length;
int separator = query.indexOf('=', start);
if (separator > end || separator == -1) {
separator = end;
}
if (separator - start == encodedKey.length()
&& query.regionMatches(start, encodedKey, 0, encodedKey.length())) {
if (separator == end) {
return "";
} else {
String encodedValue = query.substring(separator + 1, end);
return UriCodec.decode(encodedValue, true, UriCodec.UTF_8, false);
}
}
// Move start to end of name.
if (nextAmpersand != -1) {
start = nextAmpersand + 1;
} else {
break;
}
} while (true);
return null;
}
public static Set< String > getQueryParameterNames( Uri uri) {
if (uri.isOpaque()) {
throw new UnsupportedOperationException("This isn't a hierarchical URI.");
}
String query = uri.getEncodedQuery();
if (query == null) {
return Collections.emptySet();
}
Set< String > names = new LinkedHashSet< String >();
int start = 0;
do {
int next = query.indexOf('&', start);
int end = next == -1 ? query.length() : next;
int separator = query.indexOf('=', start);
if (separator > end || separator == -1) {
separator = end;
}
String name = query.substring(start, separator);
names.add( Uri.decode(name));
// Move start to end of name.
start = end + 1;
} while (start < query.length());
return Collections.unmodifiableSet(names);
}
/**
* Encodes and decodes {@code application/x-www-form-urlencoded} content. Subclasses define exactly which characters
* are legal.
*
* <p>
* By default, UTF-8 is used to encode escaped characters. A single input character like "\u0080" may be encoded to
* multiple octets like %C2%80.
*/
abstract static class UriCodec {
/**
* Returns true if {@code c} does not need to be escaped.
*/
protected abstract boolean isRetained(char c);
/**
* Throws if {@code s} is invalid according to this encoder.
*/
public final String validate( String uri, int start, int end, String name) throws URISyntaxException {
for (int i = start; i < end;) {
char ch = uri.charAt(i);
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9' || isRetained(ch)) {
i++;
} else if (ch == '%') {
if (i + 2 >= end) {
throw new URISyntaxException(uri, "Incomplete % sequence in " + name, i);
}
int d1 = hexToInt(uri.charAt(i + 1));
int d2 = hexToInt(uri.charAt(i + 2));
if (d1 == -1 || d2 == -1) {
throw new URISyntaxException(uri, "Invalid % sequence: " + uri.substring(i, i + 3) + " in "
+ name, i);
}
i += 3;
} else {
throw new URISyntaxException(uri, "Illegal character in " + name, i);
}
}
return uri.substring(start, end);
}
/**
* Throws if {@code s} contains characters that are not letters, digits or in {@code legal}.
*/
public static void validateSimple( String s, String legal) throws URISyntaxException {
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (!(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9' || legal.indexOf(ch) > -1)) {
throw new URISyntaxException(s, "Illegal character", i);
}
}
}
/**
* Encodes {@code s} and appends the orderList to {@code builder}.
*
* @param isPartiallyEncoded true to fix input that has already been partially or fully encoded. For example,
* input of "hello%20world" is unchanged with isPartiallyEncoded=true but would be double-escaped to
* "hello%2520world" otherwise.
* @throws UnsupportedEncodingException
*/
private void appendEncoded( StringBuilder builder, String s, Charset charset, boolean isPartiallyEncoded)
throws UnsupportedEncodingException {
if (s == null) {
throw new NullPointerException();
}
int escapeStart = -1;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || isRetained(c) || c == '%'
&& isPartiallyEncoded) {
if (escapeStart != -1) {
appendHex(builder, s.substring(escapeStart, i), charset);
escapeStart = -1;
}
if (c == '%' && isPartiallyEncoded) {
// this is an encoded 3-character sequence like "%20"
builder.append(s, i, i + 3);
i += 2;
} else if (c == ' ') {
builder.append('+');
} else {
builder.append(c);
}
} else if (escapeStart == -1) {
escapeStart = i;
}
}
if (escapeStart != -1) {
appendHex(builder, s.substring(escapeStart, s.length()), charset);
}
}
public final String encode( String s, Charset charset) throws UnsupportedEncodingException {
// Guess a bit larger for encoded form
StringBuilder builder = new StringBuilder(s.length() + 16);
appendEncoded(builder, s, charset, false);
return builder.toString();
}
static final Charset UTF_8 = Charset.forName("UTF-8");
public final void appendEncoded( StringBuilder builder, String s) throws UnsupportedEncodingException {
appendEncoded(builder, s, UTF_8, false);
}
public final void appendPartiallyEncoded( StringBuilder builder, String s) throws UnsupportedEncodingException {
appendEncoded(builder, s, UTF_8, true);
}
/**
* @param convertPlus true to convert '+' to ' '.
* @param throwOnFailure true to throw an IllegalArgumentException on invalid escape sequences; false to replace
* them with the replacement character (U+fffd).
* @throws UnsupportedEncodingException
*/
public static String decode( String s, boolean convertPlus, Charset charset, boolean throwOnFailure) {
if (s.indexOf('%') == -1 && (!convertPlus || s.indexOf('+') == -1)) {
return s;
}
StringBuilder result = new StringBuilder(s.length());
ByteArrayOutputStream out = new ByteArrayOutputStream();;
try {
for (int i = 0; i < s.length();) {
char c = s.charAt(i);
if (c == '%') {
do {
int d1, d2;
if (i + 2 < s.length() && (d1 = hexToInt(s.charAt(i + 1))) != -1
&& (d2 = hexToInt(s.charAt(i + 2))) != -1) {
out.write((byte) ((d1 << 4) + d2));
} else if (throwOnFailure) {
throw new IllegalArgumentException("Invalid % sequence at " + i + ": " + s);
} else {
byte[] replacement = "\ufffd".getBytes(charset.name());
out.write(replacement, 0, replacement.length);
}
i += 3;
} while (i < s.length() && s.charAt(i) == '%');
result.append(new String(out.toByteArray(), charset.name()));
out.reset();
} else {
if (convertPlus && c == '+') {
c = ' ';
}
result.append(c);
i++;
}
}
} catch ( UnsupportedEncodingException e) {
Log.e("IntentUtils",e.getMessage());
}finally {
try {
out.close();
} catch ( IOException e) {
Log.e("IntentUtils",e.getMessage());
}
}
return result.toString();
}
/**
* Like {@link Character#digit}, but without support for non-ASCII characters.
*/
private static int hexToInt(char c) {
if ('0' <= c && c <= '9') {
return c - '0';
} else if ('a' <= c && c <= 'f') {
return 10 + c - 'a';
} else if ('A' <= c && c <= 'F') {
return 10 + c - 'A';
} else {
return -1;
}
}
public static String decode( String s) throws UnsupportedEncodingException {
return decode(s, false, UTF_8, true);
}
private static void appendHex( StringBuilder builder, String s, Charset charset)
throws UnsupportedEncodingException {
for (byte b : s.getBytes(charset.name())) {
appendHex(builder, b);
}
}
private static void appendHex( StringBuilder sb, byte b) {
sb.append('%');
sb.append(byteToHexString(b, true));
}
/**
* The digits for every supported radix.
*/
private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z' };
private static final char[] UPPER_CASE_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z' };
public static String byteToHexString( byte b, boolean upperCase) {
char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
char[] buf = new char[2]; // We always want two digits.
buf[0] = digits[b >> 4 & 0xf];
buf[1] = digits[b & 0xf];
return new String(buf, 0, 2);
}
}
}

View File

@@ -0,0 +1,25 @@
package com.mogo.utils;
import java.util.Map;
import java.util.Set;
/**
* Created by congtaowang on 2018/11/20.
*/
public class MapUtils {
public static void putNotAllowNull( final Map< String, Object > target, final String key, final Object value ) {
if ( target != null && key != null && value != null ) {
target.put( key, value );
}
}
public static void putAllNotAllowNull( final Map< String, Object > target, final Map< String, Object > source ) {
if ( target != null && source != null && !source.isEmpty() ) {
final Set< String > keys = source.keySet();
for ( String key : keys ) {
putNotAllowNull( target, key, source.get( key ) );
}
}
}
}

View File

@@ -0,0 +1,398 @@
/*
* 创建日期2012-10-9
*/
package com.mogo.utils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherUtils {
/**
* 匹配Email地址
*/
public static final String REGEX_EMAIL = "^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$";
/**
* 匹配:手机号码
*/
public static final String REGEX_MOBILE_NUMBER = "^[1][3-9]\\d{9}$";
/**
* 正则表达式中使用的特殊的计算符号,如:'$', '*', ...
*/
public static final char[] PATTERN_REGEX_SPECIAL_CHARACTERS = { '$', // 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。
'(', ')', // 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
'*', // 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
'+', // 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
'.', // 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \。
'[', // 标记一个中括号表达式的开始。要匹配 [,请使用 \[。
'?', // 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
'\\', // 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。
'^', // 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。
'{', // 标记限定符表达式的开始。要匹配 {,请使用 \{。
'|', // 指明两项之间的一个选择。要匹配 |,请使用 \|。
};
/** 英文标点符号 */
private static final int TYPE_PUNCT = 1;
/** 数字 */
private static final int TYPE_DIGIT = 2;
/** 小写字母字符 */
private static final int TYPE_LOWER_LETTER = 3;
/** 大写字母字符 */
private static final int TYPE_UPPER_LETTER = 4;
/** 汉字字符串包括了中文标点符号 */
private static final int TYPE_CJK = 5;
/** 汉字字符串剔除了中文标点符号 */
private static final int TYPE_NO_PUNCTUATION_CJK = 6;
/** 是否是空白字符 */
private static final int TYPE_WHITESPACE = 7;
/** 不是字母 数字 英文标点符号 */
private static final int TYPE_NOT_PUNCT_DIGIT_LETTER = 8;
private static boolean isMatchesChar(int type, char ch) {
switch (type) {
case TYPE_PUNCT:
return isPunct(ch);
case TYPE_DIGIT:
return Character.isDigit(ch);
case TYPE_LOWER_LETTER:
return isLowerLetter(ch);
case TYPE_UPPER_LETTER:
return isUpperLetter(ch);
case TYPE_CJK:
return isCJK(ch);
case TYPE_NO_PUNCTUATION_CJK:
return isNoPunctuationCJK(ch);
case TYPE_WHITESPACE:
return Character.isWhitespace(ch);
case TYPE_NOT_PUNCT_DIGIT_LETTER:
return !( Character.isDigit(ch) || isLowerLetter(ch) || isUpperLetter(ch) || isPunct(ch));
default:
return false;
}
}
private static boolean isMatches(int type, String input) {
if (input != null && input.length() > 0) {
for (int i = input.length() - 1; i >= 0; i--) {
if (!isMatchesChar(type, input.charAt(i))) {
return false;
} else if (i == 0) {
return true;
}
}
}
return false;
}
private static boolean isMatchesInclude(int type, String input) {
if (input != null && input.length() > 0) {
for (int i = input.length() - 1; i >= 0; i--) {
if (isMatchesChar(type, input.charAt(i))) {
return true;
}
}
}
return false;
}
/**
* 匹配正则表达式
*
* @param regex
* @param input
* @return
*/
public static boolean isMatches( String regex, String input) {
return input == null ? false : Pattern.compile(regex).matcher(input).find();
}
/**
* 匹配正则表达式(忽略大小写)
*
* @param regex
* @param input
* @return
*/
public static boolean isMatchesIgnoreCase( String regex, String input) {
return input == null ? false : Pattern.compile(regex, Pattern.CASE_INSENSITIVE).matcher(input).find();
}
/**
* 是否是正则表达式中使用的特殊的计算符号,如:'$', '*', ...
*
* @param ch
* @return
*/
public static boolean isPatternRegexSpecialCharacter(char ch) {
for (int i = PATTERN_REGEX_SPECIAL_CHARACTERS.length - 1; i >= 0; i--) {
if (ch == PATTERN_REGEX_SPECIAL_CHARACTERS[i]) {
return true;
}
}
return false;
}
/**
* 是否是标点符号POSIX 字符类(仅 US-ASCII \p{Punct} 标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
*
* @param ch
* @return
*/
public static boolean isPunct(char ch) {
return (ch >= 0x21 && ch <= 0x2F) // !"#$%&'()*+,-./
|| (ch >= 0x3A && ch <= 0x40) // :;<=>?@
|| (ch >= 0x5B && ch <= 0x60) // [\]^_`
|| (ch >= 0x7B && ch <= 0x7E);// {|}~
}
/**
* 是否是标点符号字符串 中文标点识别不了
*
* @param input
* @return
*/
public static boolean isPunct( String input) {
return isMatches(TYPE_PUNCT, input);
}
/**
* 是否包含标点符号字符串
*
* @param input
* @return
*/
public static boolean isIncludePunct( String input) {
return isMatchesInclude(TYPE_PUNCT, input);
}
/**
* 是否包含非字母数字以及Punct规定的字符串
*
* @param input
* @return 含有则返回true否则 返回false
*/
public static boolean isIncludeInvalidChar( String input) {
return isMatchesInclude(TYPE_NOT_PUNCT_DIGIT_LETTER, input);
}
/**
* 是否是数字字符串
*
* @param input
* @return
*/
public static boolean isDigit( String input) {
return isMatches(TYPE_DIGIT, input);
}
/**
* 是否包含数字字符串
*
* @param input
* @return
*/
public static boolean isIncludeDigit( String input) {
return isMatchesInclude(TYPE_DIGIT, input);
}
/**
* 是否是小写字母字符([a-z]
*
* @param ch
* @return
*/
public static boolean isLowerLetter(char ch) {
return ch >= 0x61 && ch <= 0x7A;
}
/**
* 是否是小写字母字符串([a-z]
*
* @param input
* @return
*/
public static boolean isLowerLetter( String input) {
return isMatches(TYPE_LOWER_LETTER, input);
}
/**
* 是否包含小写字母字符串([a-z]
*
* @param input
* @return
*/
public static boolean isIncludeLowerLetter( String input) {
return isMatchesInclude(TYPE_LOWER_LETTER, input);
}
/**
* 是否是大写字母字符([A-Z]
*
* @param ch
* @return
*/
public static boolean isUpperLetter(char ch) {
return ch >= 0x41 && ch <= 0x5A;
}
/**
* 是否是大写字母字符串([A-Z]
*
* @param
* @return
*/
public static boolean isUpperLetter( String input) {
return isMatches(TYPE_UPPER_LETTER, input);
}
/**
* 是否包含大写字母字符串([A-Z]
*
* @param input
* @return
*/
public static boolean isIncludeUpperLetter( String input) {
return isMatchesInclude(TYPE_UPPER_LETTER, input);
}
/**
* 是否是字母字符串([A-Za-z]
*
* @param ch
* @return
*/
public static boolean isLetter(char ch) {
return isLowerLetter(ch) || isUpperLetter(ch);
}
/**
* 是否是汉字字符(广义上的汉字字符,很多都无法用输入法输出的汉字)
*
* @param c
* @return
*/
public static boolean isCJK(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS // CJK统一汉字 \\u4E00-\\u9fAF
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A // CJK统一汉字扩展-A \\u3400-\\u4dBF
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS // CJK兼容汉字 \\uF900-\\uFAFF
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION // CJK符号和标点 \\u3000-\\u303F
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION // 广义标点 \\u2000-\\u206F
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { // 半形及全形字符 \\uFF00-\\uFFEF
return true;
}
return false;
}
/**
* 是否是汉字字符(不包含标点)
*
* @param c
* @return
*/
public static boolean isNoPunctuationCJK(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS // CJK统一汉字 \\u4E00-\\u9fAF
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A // CJK统一汉字扩展-A \\u3400-\\u4dBF
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS) { // CJK兼容汉字 \\uF900-\\uFAFF
return true;
}
return false;
}
/**
* 是否是汉字字符(不包含标点)
*
* @param input
* @return
*/
public static boolean isNoPunctuationCJK( String input) {
return isMatches(TYPE_NO_PUNCTUATION_CJK, input);
}
/**
* 是否是汉字字符串(广义上的汉字字符,很多都无法用输入法输出的汉字)
*
* @param input
* @return
*/
public static boolean isCJK( String input) {
return isMatches(TYPE_CJK, input);
}
/**
* 是否包含汉字字符串(广义上的汉字字符,很多都无法用输入法输出的汉字)
*
* @param input
* @return
*/
public static boolean isIncludeCJK( String input) {
return isMatchesInclude(TYPE_CJK, input);
}
/**
* 是否是空白字符
*
* @param input
* @return
*/
public static boolean isWhitespace( String input) {
return isMatches(TYPE_WHITESPACE, input);
}
/**
* 是否包含空白字符
*
* @param input
* @return
*/
public static boolean isIncludeWhitespace( String input) {
return isMatchesInclude(TYPE_WHITESPACE, input);
}
/**
* 是否符合密码规则
*
* @param input
* @return
*/
public static boolean isFetionPassword( String input) {
// 密码必须含有字母和数字符号可选但是必须符合Punct标准,否则返回false
// 首先判断是否含有无效字符含有则返回false
if (isIncludeInvalidChar(input)) {
return false;
}
// 长度不符合要求,返回 false
if (input.length() < 6 || input.length() > 16) {
return false;
}
int tmpValue = 0;
if (isMatches("[A-Za-z]{1,15}", input)) {
tmpValue++;
}
if (isMatches("[0-9]{1,15}", input)) {
tmpValue++;
}
if (tmpValue >= 2) {
return true;
} else {
return false;
}
}
/**
* 1个或者多个0-9组成的数字
*
* @param str
* @return
*/
public static boolean isNumeric( String str) {
Pattern pattern = Pattern.compile("[0-9]+");
Matcher isNum = pattern.matcher(str);
if (!isNum.matches()) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,86 @@
package com.mogo.utils;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.os.Process;
import android.text.TextUtils;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
public class ProcessUtils {
public static boolean isMainProcess( Context context ) {
try {
ActivityManager activityManager = ( ( ActivityManager ) context.getSystemService( Context.ACTIVITY_SERVICE ) );
if ( activityManager == null ) {
return false;
}
List< RunningAppProcessInfo > raps = activityManager.getRunningAppProcesses();
if ( raps == null || raps.size() <= 0 ) {
return false;
}
int pid = Process.myPid();
String packageName = context.getPackageName();
for ( RunningAppProcessInfo info : raps ) {
if ( packageName.equals( info.processName ) ) {
return pid == info.pid;
}
}
return false;
} catch ( Exception e ) {
e.printStackTrace();
}
return false;
}
public static String getPackageName() {
String packageName = null;
BufferedReader reader = null;
try {
reader = new BufferedReader( new InputStreamReader( new FileInputStream( "/proc/" + Process.myPid() + "/cmdline" ) ) );
packageName = reader.readLine().trim();
} catch ( Exception e ) {
e.printStackTrace();
packageName = String.valueOf( Process.myPid() );
} finally {
if ( reader != null ) try {
reader.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
return packageName;
}
/**
* 获取进程号对应的进程名
*
* @param pid 进程号
* @return 进程名
*/
private static String getProcessName( int pid ) {
BufferedReader reader = null;
try {
reader = new BufferedReader( new FileReader( "/proc/" + pid + "/cmdline" ) );
String processName = reader.readLine();
if ( !TextUtils.isEmpty( processName ) ) {
processName = processName.trim();
}
return processName;
} catch ( Throwable t ) {
t.printStackTrace();
} finally {
IOUtils.closeSilently( reader );
}
return null;
}
}

View File

@@ -0,0 +1,73 @@
package com.mogo.utils;
import android.util.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@SuppressWarnings("rawtypes")
public class ReflectUtils {
public static Object getField( Class clazz, Object target, String name) throws Exception {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(target);
}
public static void setField( Class clazz, Object target, String name, Object value) throws Exception {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(target, value);
}
public static void setFieldNoException( Class clazz, Object target, String name, Object value) {
try {
ReflectUtils.setField(clazz, target, name, value);
} catch ( Exception e) {
Log.e("ReflectUtil",e.getMessage(),e);
}
}
@SuppressWarnings("unchecked")
public static Object invoke( Class clazz, Object target, String name, Object... args)
throws Exception {
Class[] parameterTypes = null;
if (args != null) {
parameterTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
parameterTypes[i] = args[i].getClass();
}
}
Method method = clazz.getDeclaredMethod(name, parameterTypes);
method.setAccessible(true);
return method.invoke(target, args);
}
@SuppressWarnings("unchecked")
public static Object invoke( Class clazz, Object target, String name, Class[] parameterTypes, Object... args)
throws Exception {
Method method = clazz.getDeclaredMethod(name, parameterTypes);
method.setAccessible(true);
return method.invoke(target, args);
}
@SuppressWarnings("unchecked")
public static <T> T invokeConstructor( Class<T> clazz, Class[] parameterTypes, Object... args)
throws Exception {
Constructor constructor = clazz.getDeclaredConstructor(parameterTypes);
constructor.setAccessible(true);
return (T) constructor.newInstance(args);
}
@SuppressWarnings("unchecked")
public static <T> T invokeConstructor( Class<T> clazz)
throws Exception {
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
return (T) constructor.newInstance();
}
}

View File

@@ -0,0 +1,72 @@
package com.mogo.utils;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
public class ResourcesHelper {
public static Resources getResources( Context context){
return context.getResources();
}
public static int getColor( Context context, int rid) {
return getResources(context).getColor(rid);
}
public static ColorStateList getColorStateList( Context context, int rid) {
return getResources(context).getColorStateList(rid);
}
public static String getString( Context context, int rid) {
return getResources(context).getString(rid);
}
public static String getString( Context context, int rid, int param1, int param2) {
return getResources(context).getString(rid, param1, param2);
}
public static String getString( Context context, int rid, String str) {
return getResources(context).getString(rid, str);
}
public static String[] getStringArray( Context context, int rid) {
return getResources(context).getStringArray(rid);
}
public static Drawable getDrawable( Context context, int rid) {
return getResources(context).getDrawable(rid);
}
public static float getDimension( Context context, int rid) {
return getResources(context).getDimension(rid);
}
public static DisplayMetrics getDisplayMetrics( Context context) {
return getResources(context).getDisplayMetrics();
}
public static int getDisplayMetrics( Context context, int x) {
return getResources(context).getDimensionPixelSize(x);
}
public static int getDimensionPixelSize( Context context, int x) {
return getResources(context).getDimensionPixelSize(x);
}
public static int getInteger( Context context, int rid) {
return getResources(context).getInteger(rid);
}
public static XmlResourceParser getXml( Context context, int rid) {
return getResources(context).getXml(rid);
}
public static Configuration getConfiguration( Context context) {
return getResources(context).getConfiguration();
}
}

View File

@@ -0,0 +1,33 @@
package com.mogo.utils;
import android.content.Context;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
/**
* Created by congtaowang on 2018/12/20.
*/
public class SoftKeyboardUtils {
public static void show( Context context ) {
try {
InputMethodManager imm = ( InputMethodManager ) context.getSystemService( Context.INPUT_METHOD_SERVICE );
if ( imm != null ) {
imm.toggleSoftInput( 0, InputMethodManager.HIDE_NOT_ALWAYS );
}
} catch ( Exception e ) {
e.printStackTrace();
}
}
public static void hidden( Context context, EditText editText ) {
try {
InputMethodManager imm = ( InputMethodManager ) context.getSystemService( Context.INPUT_METHOD_SERVICE );
if ( imm != null ) {
imm.hideSoftInputFromWindow( editText.getWindowToken(), 0 );
}
} catch ( Exception e ) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,16 @@
package com.mogo.utils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolService {
private static final ExecutorService SERVICE = Executors.newScheduledThreadPool( 1 );
private ThreadPoolService() {
}
public static void execute( Runnable task ) {
SERVICE.execute( task );
}
}

View File

@@ -0,0 +1,176 @@
package com.mogo.utils;
/**
* 2016/1/1 by congtaowang
*
* @Version 1.0
*/
import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import android.view.View;
import android.widget.Toast;
import com.mogo.utils.logger.Logger;
/**
* Init TipToast in your Application
*/
public final class TipToast {
private static final String TAG = "TipToast";
private static Toast sToast = null;
private static final Object sSyncObject = new Object();
private static Handler sHandler = null;
private static Context sContext;
private static ToastViewGenerator sGenerator;
public static void init( Context context, ToastViewGenerator generator ) {
TipToast.sContext = context;
sHandler = new Handler( context.getMainLooper() );
sGenerator = generator;
}
public static void recycle() {
sContext = null;
sHandler = null;
if ( sToast != null ) {
sToast.cancel();
sToast = null;
}
sGenerator = null;
}
private static void tip( final String message, int duration ) {
if ( !checkParams() ) {
return;
}
if ( TextUtils.isEmpty( message ) ) {
return;
}
new ToastThread( new StringToastRunnable( sContext, message, duration ) ).start();
}
private static void tip( final int msgId, int duration ) {
if ( !checkParams() ) {
return;
}
try {
if ( TextUtils.isEmpty( ResourcesHelper.getString( sContext, msgId ) ) ) {
return;
}
} catch ( Exception e ) {
return;
}
tip( ResourcesHelper.getString( sContext, msgId ), duration );
}
private static boolean checkParams() {
if ( sContext == null ) {
Logger.e( TAG, "context can't be null." );
return false;
}
if ( sHandler == null ) {
Logger.e( TAG, "sHandler can't be null." );
return false;
}
return true;
}
public static void tip( final String message ) {
tip( message, Toast.LENGTH_SHORT );
}
public static void tip( final int msgId ) {
tip( msgId, Toast.LENGTH_SHORT );
}
public static void longTip( String message ) {
tip( message, Toast.LENGTH_LONG );
}
public static void longTip( int msgId ) {
tip( msgId, Toast.LENGTH_LONG );
}
public static void shortTip( String message ) {
tip( message, Toast.LENGTH_SHORT );
}
public static void shortTip( int msgId ) {
tip( msgId, Toast.LENGTH_SHORT );
}
static class ToastThread extends Thread {
public ToastThread( Runnable runnable ) {
super( runnable );
}
}
static class StringToastRunnable implements Runnable {
Context context;
String msg;
int duration;
public StringToastRunnable( Context context, String msg, int duration ) {
this.context = context;
this.msg = msg;
this.duration = duration;
}
@Override
public void run() {
if ( sHandler == null ) {
return;
}
sHandler.post( new Runnable() {
@Override
public void run() {
synchronized ( sSyncObject ) {
if ( context == null ) {
return;
}
if ( sToast != null ) {
sToast.cancel();
}
if ( sGenerator == null ) {
sToast = Toast.makeText( context, msg, duration );
}
if ( sGenerator == null ) {
sToast = Toast.makeText( context, msg, duration );
} else {
sToast = new Toast( context );
final View view = sGenerator.make( context, msg );
if ( view != null ) {
sToast.setView( view );
sToast.setDuration( duration );
} else {
sToast = Toast.makeText( context, msg, duration );
}
}
if ( sToast != null ) {
sToast.show();
}
}
}
} );
}
}
public interface ToastViewGenerator {
View make( Context context, String message );
}
}

View File

@@ -0,0 +1,41 @@
package com.mogo.utils;
import android.os.Handler;
import android.os.Looper;
public class UiThreadHandler {
private static Handler sUiHandler = new Handler( Looper.getMainLooper() );
private static Object sToken = new Object();
public UiThreadHandler() {
}
public static boolean post( Runnable r ) {
return sUiHandler != null && sUiHandler.post( r );
}
public static boolean postDelayed( Runnable r, long delayMillis ) {
return sUiHandler != null && sUiHandler.postDelayed( r, delayMillis );
}
public static Handler getsUiHandler() {
return sUiHandler;
}
public static boolean postOnceDelayed( Runnable r, long delayMillis ) {
if ( sUiHandler == null ) {
return false;
} else {
sUiHandler.removeCallbacks( r, sToken );
return sUiHandler.postDelayed( r, delayMillis );
}
}
public static void removeCallbacks( Runnable runnable ) {
if ( sUiHandler != null ) {
sUiHandler.removeCallbacks( runnable );
}
}
}

View File

@@ -0,0 +1,10 @@
package com.mogo.utils;
/**
* @author congtaowang
* @since 2019-06-11
* <p>
* 验证格式工具类
*/
public class ValidateUtils {
}

View File

@@ -0,0 +1,71 @@
package com.mogo.utils;
import android.content.Context;
public class WindowUtils {
public static int getStatusBarHeight( Context context ) {
if ( context == null ) {
return 0;
} else {
int result = 0;
int resourceId = context.getResources().getIdentifier( "status_bar_height", "dimen", "android" );
if ( resourceId > 0 ) {
result = context.getResources().getDimensionPixelSize( resourceId );
}
return result;
}
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px( Context context, float dpValue ) {
if ( context == null ) {
return 0;
}
final float scale = context.getResources().getDisplayMetrics().density;
return ( int ) ( dpValue * scale + 0.5f );
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip( Context context, float pxValue ) {
if ( context == null ) {
return 0;
}
final float scale = context.getResources().getDisplayMetrics().density;
return ( int ) ( pxValue / scale + 0.5f );
}
public static String getScreenPixels( Context context ) {
if ( context == null ) {
return "";
}
return getScreenWidth( context ) + "*" + getScreenHeight( context );
}
public static int getScreenWidth( Context context ) {
if ( context == null ) {
return 0;
}
return context.getResources().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight( Context context ) {
if ( context == null ) {
return 0;
}
return context.getResources().getDisplayMetrics().heightPixels;
}
public static int getScreenDpi( Context context ) {
if ( context == null ) {
return 0;
}
return context.getResources().getDisplayMetrics().densityDpi;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
/**
* Defines common decoding methods for byte array decoders.
*
* @version $Id: BinaryDecoder.java 1379145 2012-08-30 21:02:52Z tn $
*/
public interface BinaryDecoder extends Decoder {
/**
* Decodes a byte array and returns the results as a byte array.
*
* @param source
* A byte array which has been encoded with the appropriate encoder
* @return a byte array that contains decoded content
* @throws DecoderException
* A decoder exception is thrown if a Decoder encounters a failure condition during the decode process.
*/
byte[] decode( byte[] source ) throws DecoderException;
}

View File

@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
/**
* Defines common encoding methods for byte array encoders.
*
* @version $Id: BinaryEncoder.java 1379145 2012-08-30 21:02:52Z tn $
*/
public interface BinaryEncoder extends Encoder {
/**
* Encodes a byte array and return the encoded data as a byte array.
*
* @param source
* Data to be encoded
* @return A byte array containing the encoded data
* @throws EncoderException
* thrown if the Encoder encounters a failure condition during the encoding process.
*/
byte[] encode( byte[] source ) throws EncoderException;
}

View File

@@ -0,0 +1,113 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
/**
* Character encoding names required of every implementation of the Java platform.
*
* From the Java documentation <a
* href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>:
* <p>
* <cite>Every implementation of the Java platform is required to support the following character encodings. Consult the
* release documentation for your implementation to see if any other encodings are supported. Consult the release
* documentation for your implementation to see if any other encodings are supported.</cite>
* </p>
*
* <ul>
* <li><code>US-ASCII</code><br>
* Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.</li>
* <li><code>ISO-8859-1</code><br>
* ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.</li>
* <li><code>UTF-8</code><br>
* Eight-bit Unicode Transformation Format.</li>
* <li><code>UTF-16BE</code><br>
* Sixteen-bit Unicode Transformation Format, big-endian byte order.</li>
* <li><code>UTF-16LE</code><br>
* Sixteen-bit Unicode Transformation Format, little-endian byte order.</li>
* <li><code>UTF-16</code><br>
* Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order
* accepted on input, big-endian used on output.)</li>
* </ul>
*
* This perhaps would best belong in the [lang] project. Even if a similar interface is defined in [lang], it is not
* foreseen that [codec] would be made to depend on [lang].
*
* <p>
* This class is immutable and thread-safe.
* </p>
*
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @since 1.4
* @version $Id: CharEncoding.java 1563226 2014-01-31 19:38:06Z ggregory $
*/
public class CharEncoding {
/**
* CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
*/
public static final String ISO_8859_1 = "ISO-8859-1";
/**
* Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of the Unicode character set.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
*/
public static final String US_ASCII = "US-ASCII";
/**
* Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory initial byte-order mark
* (either order accepted on input, big-endian used on output)
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
*/
public static final String UTF_16 = "UTF-16";
/**
* Sixteen-bit Unicode Transformation Format, big-endian byte order.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
*/
public static final String UTF_16BE = "UTF-16BE";
/**
* Sixteen-bit Unicode Transformation Format, little-endian byte order.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
*/
public static final String UTF_16LE = "UTF-16LE";
/**
* Eight-bit Unicode Transformation Format.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
*/
public static final String UTF_8 = "UTF-8";
}

View File

@@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
/**
* <p>
* Operations on {@link CharSequence} that are <code>null</code> safe.
* </p>
* <p>
* Copied from Apache Commons Lang r1586295 on April 10, 2014 (day of 3.3.2 release).
* </p>
*
* @see CharSequence
* @since 1.10
*/
public class CharSequenceUtils {
/**
* Green implementation of regionMatches.
*
* @param cs
* the <code>CharSequence</code> to be processed
* @param ignoreCase
* whether or not to be case insensitive
* @param thisStart
* the index to start on the <code>cs</code> CharSequence
* @param substring
* the <code>CharSequence</code> to be looked for
* @param start
* the index to start on the <code>substring</code> CharSequence
* @param length
* character length of the region
* @return whether the region matched
*/
static boolean regionMatches( final CharSequence cs, final boolean ignoreCase, final int thisStart,
final CharSequence substring, final int start, final int length) {
if (cs instanceof String && substring instanceof String ) {
return (( String ) cs).regionMatches(ignoreCase, thisStart, ( String ) substring, start, length);
}
int index1 = thisStart;
int index2 = start;
int tmpLen = length;
while (tmpLen-- > 0) {
char c1 = cs.charAt(index1++);
char c2 = substring.charAt(index2++);
if (c1 == c2) {
continue;
}
if (!ignoreCase) {
return false;
}
// The same check as in String.regionMatches():
if ( Character.toUpperCase(c1) != Character.toUpperCase(c2) &&
Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,156 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
import java.nio.charset.Charset;
/**
* Charsets required of every implementation of the Java platform.
*
* From the Java documentation <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard
* charsets</a>:
* <p>
* <cite>Every implementation of the Java platform is required to support the following character encodings. Consult the
* release documentation for your implementation to see if any other encodings are supported. Consult the release
* documentation for your implementation to see if any other encodings are supported. </cite>
* </p>
*
* <ul>
* <li><code>US-ASCII</code><br>
* Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.</li>
* <li><code>ISO-8859-1</code><br>
* ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.</li>
* <li><code>UTF-8</code><br>
* Eight-bit Unicode Transformation Format.</li>
* <li><code>UTF-16BE</code><br>
* Sixteen-bit Unicode Transformation Format, big-endian byte order.</li>
* <li><code>UTF-16LE</code><br>
* Sixteen-bit Unicode Transformation Format, little-endian byte order.</li>
* <li><code>UTF-16</code><br>
* Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order
* accepted on input, big-endian used on output.)</li>
* </ul>
*
* This perhaps would best belong in the Commons Lang project. Even if a similar class is defined in Commons Lang, it is
* not foreseen that Commons Codec would be made to depend on Commons Lang.
*
* <p>
* This class is immutable and thread-safe.
* </p>
*
* @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @since 1.7
* @version $Id: CharEncoding.java 1173287 2011-09-20 18:16:19Z ggregory $
*/
public class Charsets {
//
// This class should only contain Charset instances for required encodings. This guarantees that it will load
// correctly and without delay on all Java platforms.
//
/**
* Returns the given Charset or the default Charset if the given Charset is null.
*
* @param charset
* A charset or null.
* @return the given Charset or the default Charset if the given Charset is null
*/
public static Charset toCharset( final Charset charset) {
return charset == null ? Charset.defaultCharset() : charset;
}
/**
* Returns a Charset for the named charset. If the name is null, return the default Charset.
*
* @param charset
* The name of the requested charset, may be null.
* @return a Charset for the named charset
* @throws java.nio.charset.UnsupportedCharsetException
* If the named charset is unavailable
*/
public static Charset toCharset( final String charset) {
return charset == null ? Charset.defaultCharset() : Charset.forName(charset);
}
/**
* CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset ISO_8859_1 = Charset.forName(CharEncoding.ISO_8859_1);
/**
* Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of the Unicode character set.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset US_ASCII = Charset.forName(CharEncoding.US_ASCII);
/**
* Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory initial byte-order mark
* (either order accepted on input, big-endian used on output)
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset UTF_16 = Charset.forName(CharEncoding.UTF_16);
/**
* Sixteen-bit Unicode Transformation Format, big-endian byte order.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset UTF_16BE = Charset.forName(CharEncoding.UTF_16BE);
/**
* Sixteen-bit Unicode Transformation Format, little-endian byte order.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset UTF_16LE = Charset.forName(CharEncoding.UTF_16LE);
/**
* Eight-bit Unicode Transformation Format.
* <p>
* Every implementation of the Java platform is required to support this character encoding.
*
* @see <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset UTF_8 = Charset.forName(CharEncoding.UTF_8);
}

View File

@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
/**
* Provides the highest level of abstraction for Decoders.
* <p>
* This is the sister interface of {@link Encoder}. All Decoders implement this common generic interface.
* Allows a user to pass a generic Object to any Decoder implementation in the codec package.
* <p>
* One of the two interfaces at the center of the codec package.
*
* @version $Id: Decoder.java 1379145 2012-08-30 21:02:52Z tn $
*/
public interface Decoder {
/**
* Decodes an "encoded" Object and returns a "decoded" Object. Note that the implementation of this interface will
* try to cast the Object parameter to the specific type expected by a particular Decoder implementation. If a
* {@link ClassCastException} occurs this decode method will throw a DecoderException.
*
* @param source
* the object to decode
* @return a 'decoded" object
* @throws DecoderException
* a decoder exception can be thrown for any number of reasons. Some good candidates are that the
* parameter passed to this method is null, a param cannot be cast to the appropriate type for a
* specific encoder.
*/
Object decode( Object source ) throws DecoderException;
}

View File

@@ -0,0 +1,86 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
/**
* Thrown when there is a failure condition during the decoding process. This exception is thrown when a {@link Decoder}
* encounters a decoding specific exception such as invalid data, or characters outside of the expected range.
*
* @version $Id: DecoderException.java 1619948 2014-08-22 22:53:55Z ggregory $
*/
public class DecoderException extends Exception {
/**
* Declares the Serial Version Uid.
*
* @see <a href="http://c2.com/cgi/wiki?AlwaysDeclareSerialVersionUid">Always Declare Serial Version Uid</a>
*/
private static final long serialVersionUID = 1L;
/**
* Constructs a new exception with <code>null</code> as its detail message. The cause is not initialized, and may
* subsequently be initialized by a call to {@link #initCause}.
*
* @since 1.4
*/
public DecoderException() {
super();
}
/**
* Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
* be initialized by a call to {@link #initCause}.
*
* @param message
* The detail message which is saved for later retrieval by the {@link #getMessage()} method.
*/
public DecoderException(final String message) {
super(message);
}
/**
* Constructs a new exception with the specified detail message and cause.
* <p>
* Note that the detail message associated with <code>cause</code> is not automatically incorporated into this
* exception's detail message.
*
* @param message
* The detail message which is saved for later retrieval by the {@link #getMessage()} method.
* @param cause
* The cause which is saved for later retrieval by the {@link #getCause()} method. A <code>null</code>
* value is permitted, and indicates that the cause is nonexistent or unknown.
* @since 1.4
*/
public DecoderException( final String message, final Throwable cause) {
super(message, cause);
}
/**
* Constructs a new exception with the specified cause and a detail message of <code>(cause==null ?
* null : cause.toString())</code> (which typically contains the class and detail message of <code>cause</code>).
* This constructor is useful for exceptions that are little more than wrappers for other throwables.
*
* @param cause
* The cause which is saved for later retrieval by the {@link #getCause()} method. A <code>null</code>
* value is permitted, and indicates that the cause is nonexistent or unknown.
* @since 1.4
*/
public DecoderException(final Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,817 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* Operations to simplify common {@link MessageDigest} tasks.
* This class is immutable and thread-safe.
*
* @version $Id: DigestUtils.java 1634433 2014-10-27 01:10:47Z ggregory $
*/
public class DigestUtils {
private static final int STREAM_BUFFER_LENGTH = 1024;
/**
* Read through an InputStream and returns the digest for the data
*
* @param digest
* The MessageDigest to use (e.g. MD5)
* @param data
* Data to digest
* @return the digest
* @throws IOException
* On error reading from the stream
*/
private static byte[] digest( final MessageDigest digest, final InputStream data) throws IOException {
return updateDigest(digest, data).digest();
}
/**
* Returns a <code>MessageDigest</code> for the given <code>algorithm</code>.
*
* @param algorithm
* the name of the algorithm requested. See <a
* href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"
* >Appendix A in the Java Cryptography Architecture Reference Guide</a> for information about standard
* algorithm names.
* @return A digest instance.
* @see MessageDigest#getInstance(String)
* @throws IllegalArgumentException
* when a {@link NoSuchAlgorithmException} is caught.
*/
public static MessageDigest getDigest( final String algorithm) {
try {
return MessageDigest.getInstance(algorithm);
} catch (final NoSuchAlgorithmException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Returns an MD2 MessageDigest.
*
* @return An MD2 digest instance.
* @throws IllegalArgumentException
* when a {@link NoSuchAlgorithmException} is caught, which should never happen because MD2 is a
* built-in algorithm
* @see MessageDigestAlgorithms#MD2
* @since 1.7
*/
public static MessageDigest getMd2Digest() {
return getDigest(MessageDigestAlgorithms.MD2);
}
/**
* Returns an MD5 MessageDigest.
*
* @return An MD5 digest instance.
* @throws IllegalArgumentException
* when a {@link NoSuchAlgorithmException} is caught, which should never happen because MD5 is a
* built-in algorithm
* @see MessageDigestAlgorithms#MD5
*/
public static MessageDigest getMd5Digest() {
return getDigest(MessageDigestAlgorithms.MD5);
}
/**
* Returns an SHA-1 digest.
*
* @return An SHA-1 digest instance.
* @throws IllegalArgumentException
* when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-1 is a
* built-in algorithm
* @see MessageDigestAlgorithms#SHA_1
* @since 1.7
*/
public static MessageDigest getSha1Digest() {
return getDigest(MessageDigestAlgorithms.SHA_1);
}
/**
* Returns an SHA-256 digest.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @return An SHA-256 digest instance.
* @throws IllegalArgumentException
* when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-256 is a
* built-in algorithm
* @see MessageDigestAlgorithms#SHA_256
*/
public static MessageDigest getSha256Digest() {
return getDigest(MessageDigestAlgorithms.SHA_256);
}
/**
* Returns an SHA-384 digest.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @return An SHA-384 digest instance.
* @throws IllegalArgumentException
* when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-384 is a
* built-in algorithm
* @see MessageDigestAlgorithms#SHA_384
*/
public static MessageDigest getSha384Digest() {
return getDigest(MessageDigestAlgorithms.SHA_384);
}
/**
* Returns an SHA-512 digest.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @return An SHA-512 digest instance.
* @throws IllegalArgumentException
* when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-512 is a
* built-in algorithm
* @see MessageDigestAlgorithms#SHA_512
*/
public static MessageDigest getSha512Digest() {
return getDigest(MessageDigestAlgorithms.SHA_512);
}
/**
* Returns an SHA-1 digest.
*
* @return An SHA-1 digest instance.
* @throws IllegalArgumentException
* when a {@link NoSuchAlgorithmException} is caught
* @deprecated Use {@link #getSha1Digest()}
*/
@Deprecated
public static MessageDigest getShaDigest() {
return getSha1Digest();
}
/**
* Calculates the MD2 digest and returns the value as a 16 element <code>byte[]</code>.
*
* @param data
* Data to digest
* @return MD2 digest
* @since 1.7
*/
public static byte[] md2(final byte[] data) {
return getMd2Digest().digest(data);
}
/**
* Calculates the MD2 digest and returns the value as a 16 element <code>byte[]</code>.
*
* @param data
* Data to digest
* @return MD2 digest
* @throws IOException
* On error reading from the stream
* @since 1.7
*/
public static byte[] md2(final InputStream data) throws IOException {
return digest(getMd2Digest(), data);
}
/**
* Calculates the MD2 digest and returns the value as a 16 element <code>byte[]</code>.
*
* @param data
* Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
* @return MD2 digest
* @since 1.7
*/
public static byte[] md2(final String data) {
return md2(StringUtils.getBytesUtf8(data));
}
/**
* Calculates the MD2 digest and returns the value as a 32 character hex string.
*
* @param data
* Data to digest
* @return MD2 digest as a hex string
* @since 1.7
*/
public static String md2Hex( final byte[] data) {
return Hex.encodeHexString(md2(data));
}
/**
* Calculates the MD2 digest and returns the value as a 32 character hex string.
*
* @param data
* Data to digest
* @return MD2 digest as a hex string
* @throws IOException
* On error reading from the stream
* @since 1.7
*/
public static String md2Hex( final InputStream data) throws IOException {
return Hex.encodeHexString(md2(data));
}
/**
* Calculates the MD2 digest and returns the value as a 32 character hex string.
*
* @param data
* Data to digest
* @return MD2 digest as a hex string
* @since 1.7
*/
public static String md2Hex( final String data) {
return Hex.encodeHexString(md2(data));
}
/**
* Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
*
* @param data
* Data to digest
* @return MD5 digest
*/
public static byte[] md5(final byte[] data) {
return getMd5Digest().digest(data);
}
/**
* Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
*
* @param data
* Data to digest
* @return MD5 digest
* @throws IOException
* On error reading from the stream
* @since 1.4
*/
public static byte[] md5(final InputStream data) throws IOException {
return digest(getMd5Digest(), data);
}
/**
* Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
*
* @param data
* Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
* @return MD5 digest
*/
public static byte[] md5(final String data) {
return md5(StringUtils.getBytesUtf8(data));
}
/**
* Calculates the MD5 digest and returns the value as a 32 character hex string.
*
* @param data
* Data to digest
* @return MD5 digest as a hex string
*/
public static String md5Hex( final byte[] data) {
return Hex.encodeHexString(md5(data));
}
/**
* Calculates the MD5 digest and returns the value as a 32 character hex string.
*
* @param data
* Data to digest
* @return MD5 digest as a hex string
* @throws IOException
* On error reading from the stream
* @since 1.4
*/
public static String md5Hex( final InputStream data) throws IOException {
return Hex.encodeHexString(md5(data));
}
/**
* Calculates the MD5 digest and returns the value as a 32 character hex string.
*
* @param data
* Data to digest
* @return MD5 digest as a hex string
*/
public static String md5Hex( final String data) {
return Hex.encodeHexString(md5(data));
}
/**
* Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
*
* @param data
* Data to digest
* @return SHA-1 digest
* @deprecated Use {@link #sha1(byte[])}
*/
@Deprecated
public static byte[] sha(final byte[] data) {
return sha1(data);
}
/**
* Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
*
* @param data
* Data to digest
* @return SHA-1 digest
* @throws IOException
* On error reading from the stream
* @since 1.4
* @deprecated Use {@link #sha1(InputStream)}
*/
@Deprecated
public static byte[] sha(final InputStream data) throws IOException {
return sha1(data);
}
/**
* Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
*
* @param data
* Data to digest
* @return SHA-1 digest
* @deprecated Use {@link #sha1(String)}
*/
@Deprecated
public static byte[] sha(final String data) {
return sha1(data);
}
/**
* Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
*
* @param data
* Data to digest
* @return SHA-1 digest
* @since 1.7
*/
public static byte[] sha1(final byte[] data) {
return getSha1Digest().digest(data);
}
/**
* Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
*
* @param data
* Data to digest
* @return SHA-1 digest
* @throws IOException
* On error reading from the stream
* @since 1.7
*/
public static byte[] sha1(final InputStream data) throws IOException {
return digest(getSha1Digest(), data);
}
/**
* Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
*
* @param data
* Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
* @return SHA-1 digest
*/
public static byte[] sha1(final String data) {
return sha1(StringUtils.getBytesUtf8(data));
}
/**
* Calculates the SHA-1 digest and returns the value as a hex string.
*
* @param data
* Data to digest
* @return SHA-1 digest as a hex string
* @since 1.7
*/
public static String sha1Hex( final byte[] data) {
return Hex.encodeHexString(sha1(data));
}
/**
* Calculates the SHA-1 digest and returns the value as a hex string.
*
* @param data
* Data to digest
* @return SHA-1 digest as a hex string
* @throws IOException
* On error reading from the stream
* @since 1.7
*/
public static String sha1Hex( final InputStream data) throws IOException {
return Hex.encodeHexString(sha1(data));
}
/**
* Calculates the SHA-1 digest and returns the value as a hex string.
*
* @param data
* Data to digest
* @return SHA-1 digest as a hex string
* @since 1.7
*/
public static String sha1Hex( final String data) {
return Hex.encodeHexString(sha1(data));
}
/**
* Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-256 digest
* @since 1.4
*/
public static byte[] sha256(final byte[] data) {
return getSha256Digest().digest(data);
}
/**
* Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-256 digest
* @throws IOException
* On error reading from the stream
* @since 1.4
*/
public static byte[] sha256(final InputStream data) throws IOException {
return digest(getSha256Digest(), data);
}
/**
* Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
* @return SHA-256 digest
* @since 1.4
*/
public static byte[] sha256(final String data) {
return sha256(StringUtils.getBytesUtf8(data));
}
/**
* Calculates the SHA-256 digest and returns the value as a hex string.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-256 digest as a hex string
* @since 1.4
*/
public static String sha256Hex( final byte[] data) {
return Hex.encodeHexString(sha256(data));
}
/**
* Calculates the SHA-256 digest and returns the value as a hex string.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-256 digest as a hex string
* @throws IOException
* On error reading from the stream
* @since 1.4
*/
public static String sha256Hex( final InputStream data) throws IOException {
return Hex.encodeHexString(sha256(data));
}
/**
* Calculates the SHA-256 digest and returns the value as a hex string.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-256 digest as a hex string
* @since 1.4
*/
public static String sha256Hex( final String data) {
return Hex.encodeHexString(sha256(data));
}
/**
* Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-384 digest
* @since 1.4
*/
public static byte[] sha384(final byte[] data) {
return getSha384Digest().digest(data);
}
/**
* Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-384 digest
* @throws IOException
* On error reading from the stream
* @since 1.4
*/
public static byte[] sha384(final InputStream data) throws IOException {
return digest(getSha384Digest(), data);
}
/**
* Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
* @return SHA-384 digest
* @since 1.4
*/
public static byte[] sha384(final String data) {
return sha384(StringUtils.getBytesUtf8(data));
}
/**
* Calculates the SHA-384 digest and returns the value as a hex string.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-384 digest as a hex string
* @since 1.4
*/
public static String sha384Hex( final byte[] data) {
return Hex.encodeHexString(sha384(data));
}
/**
* Calculates the SHA-384 digest and returns the value as a hex string.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-384 digest as a hex string
* @throws IOException
* On error reading from the stream
* @since 1.4
*/
public static String sha384Hex( final InputStream data) throws IOException {
return Hex.encodeHexString(sha384(data));
}
/**
* Calculates the SHA-384 digest and returns the value as a hex string.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-384 digest as a hex string
* @since 1.4
*/
public static String sha384Hex( final String data) {
return Hex.encodeHexString(sha384(data));
}
/**
* Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-512 digest
* @since 1.4
*/
public static byte[] sha512(final byte[] data) {
return getSha512Digest().digest(data);
}
/**
* Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-512 digest
* @throws IOException
* On error reading from the stream
* @since 1.4
*/
public static byte[] sha512(final InputStream data) throws IOException {
return digest(getSha512Digest(), data);
}
/**
* Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
* @return SHA-512 digest
* @since 1.4
*/
public static byte[] sha512(final String data) {
return sha512(StringUtils.getBytesUtf8(data));
}
/**
* Calculates the SHA-512 digest and returns the value as a hex string.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-512 digest as a hex string
* @since 1.4
*/
public static String sha512Hex( final byte[] data) {
return Hex.encodeHexString(sha512(data));
}
/**
* Calculates the SHA-512 digest and returns the value as a hex string.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-512 digest as a hex string
* @throws IOException
* On error reading from the stream
* @since 1.4
*/
public static String sha512Hex( final InputStream data) throws IOException {
return Hex.encodeHexString(sha512(data));
}
/**
* Calculates the SHA-512 digest and returns the value as a hex string.
* <p>
* Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
* </p>
*
* @param data
* Data to digest
* @return SHA-512 digest as a hex string
* @since 1.4
*/
public static String sha512Hex( final String data) {
return Hex.encodeHexString(sha512(data));
}
/**
* Calculates the SHA-1 digest and returns the value as a hex string.
*
* @param data
* Data to digest
* @return SHA-1 digest as a hex string
* @deprecated Use {@link #sha1Hex(byte[])}
*/
@Deprecated
public static String shaHex( final byte[] data) {
return sha1Hex(data);
}
/**
* Calculates the SHA-1 digest and returns the value as a hex string.
*
* @param data
* Data to digest
* @return SHA-1 digest as a hex string
* @throws IOException
* On error reading from the stream
* @since 1.4
* @deprecated Use {@link #sha1Hex(InputStream)}
*/
@Deprecated
public static String shaHex( final InputStream data) throws IOException {
return sha1Hex(data);
}
/**
* Calculates the SHA-1 digest and returns the value as a hex string.
*
* @param data
* Data to digest
* @return SHA-1 digest as a hex string
* @deprecated Use {@link #sha1Hex(String)}
*/
@Deprecated
public static String shaHex( final String data) {
return sha1Hex(data);
}
/**
* Updates the given {@link MessageDigest}.
*
* @param messageDigest
* the {@link MessageDigest} to update
* @param valueToDigest
* the value to update the {@link MessageDigest} with
* @return the updated {@link MessageDigest}
* @since 1.7
*/
public static MessageDigest updateDigest( final MessageDigest messageDigest, final byte[] valueToDigest) {
messageDigest.update(valueToDigest);
return messageDigest;
}
/**
* Reads through an InputStream and updates the digest for the data
*
* @param digest
* The MessageDigest to use (e.g. MD5)
* @param data
* Data to digest
* @return the digest
* @throws IOException
* On error reading from the stream
* @since 1.8
*/
public static MessageDigest updateDigest( final MessageDigest digest, final InputStream data) throws IOException {
final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
while (read > -1) {
digest.update(buffer, 0, read);
read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
}
return digest;
}
/**
* Updates the given {@link MessageDigest}.
*
* @param messageDigest
* the {@link MessageDigest} to update
* @param valueToDigest
* the value to update the {@link MessageDigest} with;
* converted to bytes using {@link StringUtils#getBytesUtf8(String)}
* @return the updated {@link MessageDigest}
* @since 1.7
*/
public static MessageDigest updateDigest( final MessageDigest messageDigest, final String valueToDigest) {
messageDigest.update(StringUtils.getBytesUtf8(valueToDigest));
return messageDigest;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
/**
* Provides the highest level of abstraction for Encoders.
* <p>
* This is the sister interface of {@link Decoder}. Every implementation of Encoder provides this
* common generic interface which allows a user to pass a generic Object to any Encoder implementation
* in the codec package.
*
* @version $Id: Encoder.java 1379145 2012-08-30 21:02:52Z tn $
*/
public interface Encoder {
/**
* Encodes an "Object" and returns the encoded content as an Object. The Objects here may just be
* <code>byte[]</code> or <code>String</code>s depending on the implementation used.
*
* @param source
* An object to encode
* @return An "encoded" Object
* @throws EncoderException
* An encoder exception is thrown if the encoder experiences a failure condition during the encoding
* process.
*/
Object encode( Object source ) throws EncoderException;
}

View File

@@ -0,0 +1,89 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
/**
* Thrown when there is a failure condition during the encoding process. This exception is thrown when an
* {@link Encoder} encounters a encoding specific exception such as invalid data, inability to calculate a checksum,
* characters outside of the expected range.
*
* @version $Id: EncoderException.java 1619948 2014-08-22 22:53:55Z ggregory $
*/
public class EncoderException extends Exception {
/**
* Declares the Serial Version Uid.
*
* @see <a href="http://c2.com/cgi/wiki?AlwaysDeclareSerialVersionUid">Always Declare Serial Version Uid</a>
*/
private static final long serialVersionUID = 1L;
/**
* Constructs a new exception with <code>null</code> as its detail message. The cause is not initialized, and may
* subsequently be initialized by a call to {@link #initCause}.
*
* @since 1.4
*/
public EncoderException() {
super();
}
/**
* Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
* be initialized by a call to {@link #initCause}.
*
* @param message
* a useful message relating to the encoder specific error.
*/
public EncoderException(final String message) {
super(message);
}
/**
* Constructs a new exception with the specified detail message and cause.
*
* <p>
* Note that the detail message associated with <code>cause</code> is not automatically incorporated into this
* exception's detail message.
* </p>
*
* @param message
* The detail message which is saved for later retrieval by the {@link #getMessage()} method.
* @param cause
* The cause which is saved for later retrieval by the {@link #getCause()} method. A <code>null</code>
* value is permitted, and indicates that the cause is nonexistent or unknown.
* @since 1.4
*/
public EncoderException( final String message, final Throwable cause) {
super(message, cause);
}
/**
* Constructs a new exception with the specified cause and a detail message of <code>(cause==null ?
* null : cause.toString())</code> (which typically contains the class and detail message of <code>cause</code>).
* This constructor is useful for exceptions that are little more than wrappers for other throwables.
*
* @param cause
* The cause which is saved for later retrieval by the {@link #getCause()} method. A <code>null</code>
* value is permitted, and indicates that the cause is nonexistent or unknown.
* @since 1.4
*/
public EncoderException(final Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,328 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
import java.nio.charset.Charset;
/**
* Converts hexadecimal Strings. The charset used for certain operation can be set, the default is set in
* {@link #DEFAULT_CHARSET_NAME}
*
* This class is thread-safe.
*
* @since 1.1
* @version $Id: Hex.java 1619948 2014-08-22 22:53:55Z ggregory $
*/
public class Hex implements BinaryEncoder, BinaryDecoder {
/**
* Default charset name is {@link Charsets#UTF_8}
*
* @since 1.7
*/
public static final Charset DEFAULT_CHARSET = Charsets.UTF_8;
/**
* Default charset name is {@link CharEncoding#UTF_8}
*
* @since 1.4
*/
public static final String DEFAULT_CHARSET_NAME = CharEncoding.UTF_8;
/**
* Used to build output as Hex
*/
private static final char[] DIGITS_LOWER =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* Used to build output as Hex
*/
private static final char[] DIGITS_UPPER =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The
* returned array will be half the length of the passed array, as it takes two characters to represent any given
* byte. An exception is thrown if the passed char array has an odd number of elements.
*
* @param data
* An array of characters containing hexadecimal digits
* @return A byte array containing binary data decoded from the supplied char array.
* @throws DecoderException
* Thrown if an odd number or illegal of characters is supplied
*/
public static byte[] decodeHex(final char[] data) throws DecoderException {
final int len = data.length;
if ((len & 0x01) != 0) {
throw new DecoderException("Odd number of characters.");
}
final byte[] out = new byte[len >> 1];
// two characters form the hex value.
for (int i = 0, j = 0; j < len; i++) {
int f = toDigit(data[j], j) << 4;
j++;
f = f | toDigit(data[j], j);
j++;
out[i] = (byte) (f & 0xFF);
}
return out;
}
/**
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
* The returned array will be double the length of the passed array, as it takes two characters to represent any
* given byte.
*
* @param data
* a byte[] to convert to Hex characters
* @return A char[] containing hexadecimal characters
*/
public static char[] encodeHex(final byte[] data) {
return encodeHex(data, true);
}
/**
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
* The returned array will be double the length of the passed array, as it takes two characters to represent any
* given byte.
*
* @param data
* a byte[] to convert to Hex characters
* @param toLowerCase
* <code>true</code> converts to lowercase, <code>false</code> to uppercase
* @return A char[] containing hexadecimal characters
* @since 1.4
*/
public static char[] encodeHex(final byte[] data, final boolean toLowerCase) {
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
}
/**
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
* The returned array will be double the length of the passed array, as it takes two characters to represent any
* given byte.
*
* @param data
* a byte[] to convert to Hex characters
* @param toDigits
* the output alphabet
* @return A char[] containing hexadecimal characters
* @since 1.4
*/
protected static char[] encodeHex(final byte[] data, final char[] toDigits) {
final int l = data.length;
final char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
out[j++] = toDigits[0x0F & data[i]];
}
return out;
}
/**
* Converts an array of bytes into a String representing the hexadecimal values of each byte in order. The returned
* String will be double the length of the passed array, as it takes two characters to represent any given byte.
*
* @param data
* a byte[] to convert to Hex characters
* @return A String containing hexadecimal characters
* @since 1.4
*/
public static String encodeHexString( final byte[] data) {
return new String(encodeHex(data));
}
/**
* Converts a hexadecimal character to an integer.
*
* @param ch
* A character to convert to an integer digit
* @param index
* The index of the character in the source
* @return An integer
* @throws DecoderException
* Thrown if ch is an illegal hex character
*/
protected static int toDigit(final char ch, final int index) throws DecoderException {
final int digit = Character.digit(ch, 16);
if (digit == -1) {
throw new DecoderException("Illegal hexadecimal character " + ch + " at index " + index);
}
return digit;
}
private final Charset charset;
/**
* Creates a new codec with the default charset name {@link #DEFAULT_CHARSET}
*/
public Hex() {
// use default encoding
this.charset = DEFAULT_CHARSET;
}
/**
* Creates a new codec with the given Charset.
*
* @param charset
* the charset.
* @since 1.7
*/
public Hex(final Charset charset) {
this.charset = charset;
}
/**
* Creates a new codec with the given charset name.
*
* @param charsetName
* the charset name.
* @throws java.nio.charset.UnsupportedCharsetException
* If the named charset is unavailable
* @since 1.4
* @since 1.7 throws UnsupportedCharsetException if the named charset is unavailable
*/
public Hex(final String charsetName) {
this( Charset.forName(charsetName));
}
/**
* Converts an array of character bytes representing hexadecimal values into an array of bytes of those same values.
* The returned array will be half the length of the passed array, as it takes two characters to represent any given
* byte. An exception is thrown if the passed char array has an odd number of elements.
*
* @param array
* An array of character bytes containing hexadecimal digits
* @return A byte array containing binary data decoded from the supplied byte array (representing characters).
* @throws DecoderException
* Thrown if an odd number of characters is supplied to this function
* @see #decodeHex(char[])
*/
@Override
public byte[] decode(final byte[] array) throws DecoderException {
return decodeHex(new String(array, getCharset()).toCharArray());
}
/**
* Converts a String or an array of character bytes representing hexadecimal values into an array of bytes of those
* same values. The returned array will be half the length of the passed String or array, as it takes two characters
* to represent any given byte. An exception is thrown if the passed char array has an odd number of elements.
*
* @param object
* A String or, an array of character bytes containing hexadecimal digits
* @return A byte array containing binary data decoded from the supplied byte array (representing characters).
* @throws DecoderException
* Thrown if an odd number of characters is supplied to this function or the object is not a String or
* char[]
* @see #decodeHex(char[])
*/
@Override
public Object decode( final Object object) throws DecoderException {
try {
final char[] charArray = object instanceof String ? (( String ) object).toCharArray() : (char[]) object;
return decodeHex(charArray);
} catch (final ClassCastException e) {
throw new DecoderException(e.getMessage(), e);
}
}
/**
* Converts an array of bytes into an array of bytes for the characters representing the hexadecimal values of each
* byte in order. The returned array will be double the length of the passed array, as it takes two characters to
* represent any given byte.
* <p>
* The conversion from hexadecimal characters to the returned bytes is performed with the charset named by
* {@link #getCharset()}.
* </p>
*
* @param array
* a byte[] to convert to Hex characters
* @return A byte[] containing the bytes of the hexadecimal characters
* @since 1.7 No longer throws IllegalStateException if the charsetName is invalid.
* @see #encodeHex(byte[])
*/
@Override
public byte[] encode(final byte[] array) {
return encodeHexString(array).getBytes(this.getCharset());
}
/**
* Converts a String or an array of bytes into an array of characters representing the hexadecimal values of each
* byte in order. The returned array will be double the length of the passed String or array, as it takes two
* characters to represent any given byte.
* <p>
* The conversion from hexadecimal characters to bytes to be encoded to performed with the charset named by
* {@link #getCharset()}.
* </p>
*
* @param object
* a String, or byte[] to convert to Hex characters
* @return A char[] containing hexadecimal characters
* @throws EncoderException
* Thrown if the given object is not a String or byte[]
* @see #encodeHex(byte[])
*/
@Override
public Object encode( final Object object) throws EncoderException {
try {
final byte[] byteArray = object instanceof String ?
(( String ) object).getBytes(this.getCharset()) : (byte[]) object;
return encodeHex(byteArray);
} catch (final ClassCastException e) {
throw new EncoderException(e.getMessage(), e);
}
}
/**
* Gets the charset.
*
* @return the charset.
* @since 1.7
*/
public Charset getCharset() {
return this.charset;
}
/**
* Gets the charset name.
*
* @return the charset name.
* @since 1.4
*/
public String getCharsetName() {
return this.charset.name();
}
/**
* Returns a string representation of the object, which includes the charset name.
*
* @return a string representation of the object.
*/
@Override
public String toString() {
return super.toString() + "[charsetName=" + this.charset + "]";
}
}

View File

@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
import java.security.MessageDigest;
/**
* Standard {@link MessageDigest} algorithm names from the <cite>Java Cryptography Architecture Standard Algorithm Name
* Documentation</cite>.
* <p>
* This class is immutable and thread-safe.
* </p>
*
* @see <a href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html">Java Cryptography
* Architecture Standard Algorithm Name Documentation</a>
* @since 1.7
* @version $Id: MessageDigestAlgorithms.java 1585867 2014-04-09 00:12:36Z ggregory $
*/
public class MessageDigestAlgorithms {
private MessageDigestAlgorithms() {
// cannot be instantiated.
}
/**
* The MD2 message digest algorithm defined in RFC 1319.
*/
public static final String MD2 = "MD2";
/**
* The MD5 message digest algorithm defined in RFC 1321.
*/
public static final String MD5 = "MD5";
/**
* The SHA-1 hash algorithm defined in the FIPS PUB 180-2.
*/
public static final String SHA_1 = "SHA-1";
/**
* The SHA-256 hash algorithm defined in the FIPS PUB 180-2.
*/
public static final String SHA_256 = "SHA-256";
/**
* The SHA-384 hash algorithm defined in the FIPS PUB 180-2.
*/
public static final String SHA_384 = "SHA-384";
/**
* The SHA-512 hash algorithm defined in the FIPS PUB 180-2.
*/
public static final String SHA_512 = "SHA-512";
}

View File

@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
/**
* Defines common encoding methods for String encoders.
*
* @version $Id: StringEncoder.java 1379145 2012-08-30 21:02:52Z tn $
*/
public interface StringEncoder extends Encoder {
/**
* Encodes a String and returns a String.
*
* @param source
* the String to encode
* @return the encoded String
* @throws EncoderException
* thrown if there is an error condition during the encoding process.
*/
String encode( String source ) throws EncoderException;
}

View File

@@ -0,0 +1,384 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mogo.utils.digest;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
/**
* Converts String to and from bytes using the encodings required by the Java specification. These encodings are
* specified in <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">
* Standard charsets</a>.
*
* <p>This class is immutable and thread-safe.</p>
*
* @see CharEncoding
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @version $Id: StringUtils.java 1634456 2014-10-27 05:26:56Z ggregory $
* @since 1.4
*/
public class StringUtils {
/**
* <p>
* Compares two CharSequences, returning <code>true</code> if they represent equal sequences of characters.
* </p>
*
* <p>
* <code>null</code>s are handled without exceptions. Two <code>null</code> references are considered to be equal.
* The comparison is case sensitive.
* </p>
*
* <pre>
* StringUtils.equals(null, null) = true
* StringUtils.equals(null, "abc") = false
* StringUtils.equals("abc", null) = false
* StringUtils.equals("abc", "abc") = true
* StringUtils.equals("abc", "ABC") = false
* </pre>
*
* <p>
* Copied from Apache Commons Lang r1583482 on April 10, 2014 (day of 3.3.2 release).
* </p>
*
* @see Object#equals(Object)
* @param cs1
* the first CharSequence, may be <code>null</code>
* @param cs2
* the second CharSequence, may be <code>null</code>
* @return <code>true</code> if the CharSequences are equal (case-sensitive), or both <code>null</code>
* @since 1.10
*/
public static boolean equals( final CharSequence cs1, final CharSequence cs2) {
if (cs1 == cs2) {
return true;
}
if (cs1 == null || cs2 == null) {
return false;
}
if (cs1 instanceof String && cs2 instanceof String ) {
return cs1.equals(cs2);
}
return CharSequenceUtils.regionMatches(cs1, false, 0, cs2, 0, Math.max(cs1.length(), cs2.length()));
}
/**
* Calls {@link String#getBytes(Charset)}
*
* @param string
* The string to encode (if null, return null).
* @param charset
* The {@link Charset} to encode the <code>String</code>
* @return the encoded bytes
*/
private static byte[] getBytes( final String string, final Charset charset) {
if (string == null) {
return null;
}
return string.getBytes(charset);
}
/**
* Encodes the given string into a sequence of bytes using the ISO-8859-1 charset, storing the result into a new
* byte array.
*
* @param string
* the String to encode, may be <code>null</code>
* @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
* @throws NullPointerException
* Thrown if {@link Charsets#ISO_8859_1} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @see #getBytesUnchecked(String, String)
*/
public static byte[] getBytesIso8859_1(final String string) {
return getBytes(string, Charsets.ISO_8859_1);
}
/**
* Encodes the given string into a sequence of bytes using the named charset, storing the result into a new byte
* array.
* <p>
* This method catches {@link UnsupportedEncodingException} and rethrows it as {@link IllegalStateException}, which
* should never happen for a required charset name. Use this method when the encoding is required to be in the JRE.
* </p>
*
* @param string
* the String to encode, may be <code>null</code>
* @param charsetName
* The name of a required {@link Charset}
* @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
* @throws IllegalStateException
* Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen for a
* required charset name.
* @see CharEncoding
* @see String#getBytes(String)
*/
public static byte[] getBytesUnchecked( final String string, final String charsetName) {
if (string == null) {
return null;
}
try {
return string.getBytes(charsetName);
} catch (final UnsupportedEncodingException e) {
throw StringUtils.newIllegalStateException(charsetName, e);
}
}
/**
* Encodes the given string into a sequence of bytes using the US-ASCII charset, storing the result into a new byte
* array.
*
* @param string
* the String to encode, may be <code>null</code>
* @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
* @throws NullPointerException
* Thrown if {@link Charsets#US_ASCII} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @see #getBytesUnchecked(String, String)
*/
public static byte[] getBytesUsAscii(final String string) {
return getBytes(string, Charsets.US_ASCII);
}
/**
* Encodes the given string into a sequence of bytes using the UTF-16 charset, storing the result into a new byte
* array.
*
* @param string
* the String to encode, may be <code>null</code>
* @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
* @throws NullPointerException
* Thrown if {@link Charsets#UTF_16} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @see #getBytesUnchecked(String, String)
*/
public static byte[] getBytesUtf16(final String string) {
return getBytes(string, Charsets.UTF_16);
}
/**
* Encodes the given string into a sequence of bytes using the UTF-16BE charset, storing the result into a new byte
* array.
*
* @param string
* the String to encode, may be <code>null</code>
* @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
* @throws NullPointerException
* Thrown if {@link Charsets#UTF_16BE} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @see #getBytesUnchecked(String, String)
*/
public static byte[] getBytesUtf16Be(final String string) {
return getBytes(string, Charsets.UTF_16BE);
}
/**
* Encodes the given string into a sequence of bytes using the UTF-16LE charset, storing the result into a new byte
* array.
*
* @param string
* the String to encode, may be <code>null</code>
* @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
* @throws NullPointerException
* Thrown if {@link Charsets#UTF_16LE} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @see #getBytesUnchecked(String, String)
*/
public static byte[] getBytesUtf16Le(final String string) {
return getBytes(string, Charsets.UTF_16LE);
}
/**
* Encodes the given string into a sequence of bytes using the UTF-8 charset, storing the result into a new byte
* array.
*
* @param string
* the String to encode, may be <code>null</code>
* @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
* @throws NullPointerException
* Thrown if {@link Charsets#UTF_8} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
* @see #getBytesUnchecked(String, String)
*/
public static byte[] getBytesUtf8(final String string) {
return getBytes(string, Charsets.UTF_8);
}
private static IllegalStateException newIllegalStateException( final String charsetName,
final UnsupportedEncodingException e) {
return new IllegalStateException(charsetName + ": " + e);
}
/**
* Constructs a new <code>String</code> by decoding the specified array of bytes using the given charset.
*
* @param bytes
* The bytes to be decoded into characters
* @param charset
* The {@link Charset} to encode the <code>String</code>
* @return A new <code>String</code> decoded from the specified array of bytes using the given charset,
* or <code>null</code> if the input byte array was <code>null</code>.
* @throws NullPointerException
* Thrown if {@link Charsets#UTF_8} is not initialized, which should never happen since it is
* required by the Java platform specification.
*/
private static String newString( final byte[] bytes, final Charset charset) {
return bytes == null ? null : new String(bytes, charset);
}
/**
* Constructs a new <code>String</code> by decoding the specified array of bytes using the given charset.
* <p>
* This method catches {@link UnsupportedEncodingException} and re-throws it as {@link IllegalStateException}, which
* should never happen for a required charset name. Use this method when the encoding is required to be in the JRE.
* </p>
*
* @param bytes
* The bytes to be decoded into characters, may be <code>null</code>
* @param charsetName
* The name of a required {@link Charset}
* @return A new <code>String</code> decoded from the specified array of bytes using the given charset,
* or <code>null</code> if the input byte array was <code>null</code>.
* @throws IllegalStateException
* Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen for a
* required charset name.
* @see CharEncoding
* @see String#String(byte[], String)
*/
public static String newString( final byte[] bytes, final String charsetName) {
if (bytes == null) {
return null;
}
try {
return new String(bytes, charsetName);
} catch (final UnsupportedEncodingException e) {
throw StringUtils.newIllegalStateException(charsetName, e);
}
}
/**
* Constructs a new <code>String</code> by decoding the specified array of bytes using the ISO-8859-1 charset.
*
* @param bytes
* The bytes to be decoded into characters, may be <code>null</code>
* @return A new <code>String</code> decoded from the specified array of bytes using the ISO-8859-1 charset, or
* <code>null</code> if the input byte array was <code>null</code>.
* @throws NullPointerException
* Thrown if {@link Charsets#ISO_8859_1} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
*/
public static String newStringIso8859_1( final byte[] bytes) {
return new String(bytes, Charsets.ISO_8859_1);
}
/**
* Constructs a new <code>String</code> by decoding the specified array of bytes using the US-ASCII charset.
*
* @param bytes
* The bytes to be decoded into characters
* @return A new <code>String</code> decoded from the specified array of bytes using the US-ASCII charset,
* or <code>null</code> if the input byte array was <code>null</code>.
* @throws NullPointerException
* Thrown if {@link Charsets#US_ASCII} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
*/
public static String newStringUsAscii( final byte[] bytes) {
return new String(bytes, Charsets.US_ASCII);
}
/**
* Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-16 charset.
*
* @param bytes
* The bytes to be decoded into characters
* @return A new <code>String</code> decoded from the specified array of bytes using the UTF-16 charset
* or <code>null</code> if the input byte array was <code>null</code>.
* @throws NullPointerException
* Thrown if {@link Charsets#UTF_16} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
*/
public static String newStringUtf16( final byte[] bytes) {
return new String(bytes, Charsets.UTF_16);
}
/**
* Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-16BE charset.
*
* @param bytes
* The bytes to be decoded into characters
* @return A new <code>String</code> decoded from the specified array of bytes using the UTF-16BE charset,
* or <code>null</code> if the input byte array was <code>null</code>.
* @throws NullPointerException
* Thrown if {@link Charsets#UTF_16BE} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
*/
public static String newStringUtf16Be( final byte[] bytes) {
return new String(bytes, Charsets.UTF_16BE);
}
/**
* Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-16LE charset.
*
* @param bytes
* The bytes to be decoded into characters
* @return A new <code>String</code> decoded from the specified array of bytes using the UTF-16LE charset,
* or <code>null</code> if the input byte array was <code>null</code>.
* @throws NullPointerException
* Thrown if {@link Charsets#UTF_16LE} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
*/
public static String newStringUtf16Le( final byte[] bytes) {
return new String(bytes, Charsets.UTF_16LE);
}
/**
* Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-8 charset.
*
* @param bytes
* The bytes to be decoded into characters
* @return A new <code>String</code> decoded from the specified array of bytes using the UTF-8 charset,
* or <code>null</code> if the input byte array was <code>null</code>.
* @throws NullPointerException
* Thrown if {@link Charsets#UTF_8} is not initialized, which should never happen since it is
* required by the Java platform specification.
* @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException
*/
public static String newStringUtf8( final byte[] bytes) {
return newString(bytes, Charsets.UTF_8);
}
}

View File

@@ -0,0 +1,38 @@
package com.mogo.utils.glide;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.cache.ExternalPreferredCacheDiskCacheFactory;
import com.bumptech.glide.load.engine.cache.LruResourceCache;
import com.bumptech.glide.load.engine.cache.MemoryCache;
import com.bumptech.glide.module.AppGlideModule;
/**
* Created by congtaowang on 2018/12/17.
*/
@GlideModule
public class BaseGlideModule extends AppGlideModule {
public static final int MEMORY_CACHE_SIZE = 5 * 1024 * 1024;
public static final int DISK_CACHE_SIZE = 50 * 1024 * 1024;
public static final String DISK_CACHE_NAME = "glide";
@Override
public void applyOptions( Context context, GlideBuilder builder ) {
super.applyOptions( context, builder );
/**
* 更改缓存最总文件夹名称
*
* 是在sdcard/Android/data/包名/cache/DISK_CACHE_NAME目录当中
*/
builder.setMemoryCache( new LruResourceCache( MEMORY_CACHE_SIZE ) );
builder.setDiskCache( new ExternalPreferredCacheDiskCacheFactory( context, DISK_CACHE_NAME, DISK_CACHE_SIZE ) );
}
}

View File

@@ -0,0 +1,24 @@
package com.mogo.utils.logger;
public enum LogLevel {
OFF( Integer.MAX_VALUE),
VERBOSE(1),
DEBUG(2),
INFO(3),
WARN(4),
ERROR(5);
public final int level;
private LogLevel(final int level) {
this.level = level;
}
}

View File

@@ -0,0 +1,57 @@
package com.mogo.utils.logger;
public final class Logger {
private static final Printer sPrinter = new LoggerPrinter();
private Logger() {
}
public static Settings init() {
return sPrinter.init(LogLevel.DEBUG);
}
public static Settings init(LogLevel logLevel) {
return sPrinter.init(logLevel);
}
public static void d( String tag, String message, Object... args) {
if(isLoggable(LogLevel.DEBUG)) sPrinter.d(tag, message, args);
}
public static void e( String tag, String message, Object... args) {
if(isLoggable(LogLevel.ERROR)) sPrinter.e(tag, null, message, args);
}
public static void e( String tag, Throwable throwable, String message, Object... args) {
if(isLoggable(LogLevel.ERROR)) sPrinter.e(tag, throwable, message, args);
}
public static void i( String tag, String message, Object... args) {
if(isLoggable(LogLevel.INFO)) sPrinter.i(tag, message, args);
}
public static void v( String tag, String message, Object... args) {
if(isLoggable(LogLevel.VERBOSE)) sPrinter.v(tag, message, args);
}
public static void w( String tag, String message, Object... args) {
if(isLoggable(LogLevel.WARN)) sPrinter.w(tag, message, args);
}
public static void easyLog( String tag, String message) {
if(isLoggable(LogLevel.DEBUG)) sPrinter.d(tag, message);
}
public static void json( String tag, String json) {
if(isLoggable(LogLevel.DEBUG)) sPrinter.json(tag, json);
}
public static void xml( String tag, String xml) {
if(isLoggable(LogLevel.DEBUG)) sPrinter.xml(tag, xml);
}
private static boolean isLoggable(LogLevel logLevel){
return sPrinter.getSettings().getLogLevel().level <= logLevel.level;
}
}

View File

@@ -0,0 +1,261 @@
package com.mogo.utils.logger;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
final class LoggerPrinter implements Printer {
private static final String TAG = "LoggerPrinter";
private static final int CHUNK_SIZE = 4000;
private static final int JSON_INDENT = 4;
private static final int MIN_STACK_OFFSET = 3;
private static final char TOP_LEFT_CORNER = '╔';
private static final char BOTTOM_LEFT_CORNER = '╚';
private static final char MIDDLE_CORNER = '╟';
private static final char HORIZONTAL_DOUBLE_LINE = '║';
private static final String DOUBLE_DIVIDER = "════════════════════════════════════════════";
private static final String SINGLE_DIVIDER = "────────────────────────────────────────────";
private static final String TOP_BORDER = "╔════════════════════════════════════════════════════════════════════════════════════════";
private static final String BOTTOM_BORDER = "╚════════════════════════════════════════════════════════════════════════════════════════";
private static final String MIDDLE_BORDER = "╟────────────────────────────────────────────────────────────────────────────────────────";
private final Settings mSettings = new Settings();
LoggerPrinter() {
}
public Settings init(LogLevel logLevel) {
return mSettings.setLogLevel(logLevel);
}
public Settings getSettings() {
return mSettings;
}
public void d( String tag, String message, Object... args) {
this.log(tag, LogLevel.DEBUG, message, args);
}
public void e( String tag, String message, Object... args) {
this.e(tag, null, message, args);
}
public void e( String tag, Throwable throwable, String message, Object... args) {
if (throwable != null && message != null) {
message = message + " : " + throwable.toString();
}
if (throwable != null && message == null) {
message = throwable.toString();
}
if (message == null) {
message = "No message/exception is set";
}
this.log(tag, LogLevel.ERROR, message, args);
}
public void w( String tag, String message, Object... args) {
this.log(tag, LogLevel.WARN, message, args);
}
public void i( String tag, String message, Object... args) {
this.log(tag, LogLevel.INFO, message, args);
}
public void v( String tag, String message, Object... args) {
this.log(tag, LogLevel.VERBOSE, message, args);
}
public void json( String tag, String json) {
if ( TextUtils.isEmpty(json)) {
this.d(tag, "Empty/Null json content");
} else {
try {
String message;
if (json.startsWith("{")) {
JSONObject e1 = new JSONObject(json);
message = e1.toString(4);
this.d(tag, message);
return;
}
if (json.startsWith("[")) {
JSONArray e = new JSONArray(json);
message = e.toString(4);
this.d(tag, message);
}
} catch ( JSONException var4) {
this.e(tag, var4.getCause().getMessage() + "\n" + json);
}
}
}
public void xml( String tag, String xml) {
if ( TextUtils.isEmpty(xml)) {
this.d(tag, "Empty/Null xml content");
} else {
try {
StreamSource e = new StreamSource(new StringReader(xml));
StreamResult xmlOutput = new StreamResult(new StringWriter());
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty("indent", "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(e, xmlOutput);
this.d(tag, xmlOutput.getWriter().toString().replaceFirst(">", ">\n"));
} catch ( TransformerException var5) {
this.e(tag, var5.getCause().getMessage() + "\n" + xml);
}
}
}
public void normalLog( String tag, String message) {
if (!TextUtils.isEmpty(message)) {
this.logChunk(LogLevel.DEBUG, tag, message);
}
}
private synchronized void log( String tag, LogLevel logLevel, String msg, Object... args) {
String message = this.createMessage(msg, args);
int methodCount = this.getMethodCount();
this.logTopBorder(logLevel, tag);
this.logHeaderContent(logLevel, tag, methodCount);
byte[] bytes = message.getBytes();
int length = bytes.length;
if (length <= 4000) {
if (methodCount > 0) {
this.logDivider(logLevel, tag);
}
this.logContent(logLevel, tag, message);
this.logBottomBorder(logLevel, tag);
} else {
if (methodCount > 0) {
this.logDivider(logLevel, tag);
}
for (int i = 0; i < length; i += 4000) {
int count = Math.min(length - i, 4000);
this.logContent(logLevel, tag, new String(bytes, i, count));
}
this.logBottomBorder(logLevel, tag);
}
}
private void logTopBorder(LogLevel logLevel, String tag) {
this.logChunk(logLevel, tag, "╔════════════════════════════════════════════════════════════════════════════════════════");
}
private void logHeaderContent( LogLevel logLevel, String tag, int methodCount) {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
if (mSettings.isShowThreadInfo()) {
this.logChunk(logLevel, tag, "║ Thread: " + Thread.currentThread().getName());
this.logDivider(logLevel, tag);
}
String level = "";
int stackOffset = this.getStackOffset(trace) + mSettings.getMethodOffset();
if (methodCount + stackOffset > trace.length) {
methodCount = trace.length - stackOffset - 1;
}
for (int i = methodCount; i > 0; --i) {
int stackIndex = i + stackOffset;
if (stackIndex < trace.length) {
StringBuilder builder = new StringBuilder();
builder.append("").append(level).append(this.getSimpleClassName(trace[stackIndex].getClassName())).append(".").append(trace[stackIndex].getMethodName()).append(" ").append(" (").append(trace[stackIndex].getFileName()).append(":").append(trace[stackIndex].getLineNumber()).append(")");
level = level + " ";
this.logChunk(logLevel, tag, builder.toString());
}
}
}
private void logBottomBorder(LogLevel logLevel, String tag) {
this.logChunk(logLevel, tag, "╚════════════════════════════════════════════════════════════════════════════════════════");
}
private void logDivider(LogLevel logLevel, String tag) {
this.logChunk(logLevel, tag, "╟────────────────────────────────────────────────────────────────────────────────────────");
}
private void logContent( LogLevel logLevel, String tag, String chunk) {
String[] lines = chunk.split( System.getProperty("line.separator"));
for ( String line : lines) {
this.logChunk(logLevel, tag, "" + line);
}
}
private void logChunk( LogLevel logLevel, String tag, String chunk) {
String finalTag = this.checkTag(tag);
switch (logLevel) {
case VERBOSE:
Log.v(finalTag, chunk);
break;
case INFO:
Log.i(finalTag, chunk);
break;
case DEBUG:
Log.d(finalTag, chunk);
break;
case WARN:
Log.w(finalTag, chunk);
break;
case ERROR:
Log.e(finalTag, chunk);
break;
case OFF:
break;
}
}
private String getSimpleClassName( String name) {
int lastIndex = name.lastIndexOf(".");
return name.substring(lastIndex + 1);
}
private String checkTag( String tag) {
return TextUtils.isEmpty(tag) ? TAG : tag;
}
private String createMessage( String message, Object... args) {
return (args == null || args.length == 0) ? message : String.format(message, args);
}
private int getMethodCount() {
return mSettings.getMethodCount();
}
private int getStackOffset( StackTraceElement[] trace) {
for (int i = 3; i < trace.length; ++i) {
StackTraceElement e = trace[i];
String name = e.getClassName();
if (!name.equals(LoggerPrinter.class.getName()) && !name.equals(Logger.class.getName())) {
--i;
return i;
}
}
return -1;
}
}

View File

@@ -0,0 +1,26 @@
package com.mogo.utils.logger;
public interface Printer {
Settings init( LogLevel logLevel );
Settings getSettings();
void d( String tag, String message, Object... args );
void e( String tag, String message, Object... args );
void e( String tag, Throwable throwable, String message, Object... args );
void w( String tag, String message, Object... args );
void i( String tag, String message, Object... args );
void v( String tag, String message, Object... args );
void json( String tag, String json );
void xml( String tag, String xml );
void normalLog( String tag, String message );
}

View File

@@ -0,0 +1,52 @@
package com.mogo.utils.logger;
public final class Settings {
private int methodCount = 2;
private boolean showThreadInfo = true;
private int methodOffset = 0;
private LogLevel logLevel = LogLevel.DEBUG;
public Settings() {
}
public Settings hideThreadInfo() {
this.showThreadInfo = false;
return this;
}
public Settings setMethodCount(int methodCount) {
if(methodCount < 0) {
methodCount = 0;
}
this.methodCount = methodCount;
return this;
}
public Settings setLogLevel(LogLevel logLevel) {
this.logLevel = logLevel;
return this;
}
public Settings setMethodOffset(int offset) {
this.methodOffset = offset;
return this;
}
public int getMethodCount() {
return this.methodCount;
}
public boolean isShowThreadInfo() {
return this.showThreadInfo;
}
public LogLevel getLogLevel() {
return this.logLevel;
}
public int getMethodOffset() {
return this.methodOffset;
}
}

View File

@@ -0,0 +1,179 @@
package com.mogo.utils.network;
import android.text.TextUtils;
import com.mogo.utils.logger.Logger;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class BaseParams {
private static final String TAG = "BaseParams";
protected ConcurrentHashMap< String, Object > urlParams;
protected BaseParams() {
this.init();
}
public Object get( String key ) {
return this.urlParams != null && key != null ? this.urlParams.get( key ) : "";
}
protected BaseParams( Map< String, Object > source ) {
this.init();
Iterator iterator = source.entrySet().iterator();
while ( iterator.hasNext() ) {
Map.Entry entry = ( Map.Entry ) iterator.next();
this.put( ( String ) entry.getKey(), entry.getValue() );
}
}
protected BaseParams( String key, Object value ) {
this.init();
this.put( key, value );
}
protected BaseParams( Object... keysAndValues ) {
this.init();
int len = keysAndValues.length;
if ( len % 2 != 0 ) {
throw new IllegalArgumentException( "Supplied arguments must be even" );
} else {
for ( int i = 0; i < len; i += 2 ) {
String key = String.valueOf( keysAndValues[i] );
Object value = keysAndValues[i + 1];
this.put( key, value );
}
}
}
private boolean checkValue( final Object value ) {
if ( value instanceof CharSequence ) {
return !TextUtils.isEmpty( ( CharSequence ) value );
}
if ( value == null || value.getClass() == null ) {
return false;
}
final Class< ? > clazz = value.getClass();
return clazz.isPrimitive() ||
clazz.isAssignableFrom( Boolean.class ) ||
clazz.isAssignableFrom( Character.class ) ||
clazz.isAssignableFrom( Byte.class ) ||
clazz.isAssignableFrom( Short.class ) ||
clazz.isAssignableFrom( Integer.class ) ||
clazz.isAssignableFrom( Long.class ) ||
clazz.isAssignableFrom( Float.class ) ||
clazz.isAssignableFrom( Double.class );
}
private boolean checkKey( String key ) {
return !TextUtils.isEmpty( key );
}
public BaseParams put( String key, Object value ) {
if ( checkKey( key ) && checkValue( value ) ) {
urlParams.put( key, value );
} else {
Logger.e( TAG, "parameter key is illegal or parameter value is illegal" );
}
return this;
}
public Object remove( String key ) {
return this.urlParams.remove( key );
}
public String toString() {
StringBuilder result = new StringBuilder();
Iterator< Map.Entry< String, Object > > iterator = this.urlParams.entrySet().iterator();
while ( iterator.hasNext() ) {
Map.Entry< String, Object > entry = iterator.next();
if ( result.length() > 0 ) {
result.append( "&" );
}
result.append( entry.getKey() );
result.append( "=" );
result.append( entry.getValue() );
}
return result.toString();
}
private void init() {
this.urlParams = new ConcurrentHashMap< String, Object >();
}
public List< BasicNameValuePair > getParamsList() {
LinkedList< BasicNameValuePair > pairs = new LinkedList< BasicNameValuePair >();
Iterator< Map.Entry< String, Object > > iterator = this.urlParams.entrySet().iterator();
while ( iterator.hasNext() ) {
Map.Entry< String, Object > entry = iterator.next();
pairs.add( new BasicNameValuePair( entry.getKey(), entry.getValue() ) );
}
return pairs;
}
public Map< String, Object > getOriginMap() {
return urlParams;
}
public String getParamString() {
StringBuilder result = new StringBuilder();
Iterator< BasicNameValuePair > iterator = getParamsList().iterator();
while ( iterator.hasNext() ) {
BasicNameValuePair parameter = iterator.next();
String key = parameter.getName();
Object value = parameter.getValue();
if ( result.length() > 0 ) {
result.append( "&" );
}
result.append( key );
result.append( "=" );
result.append( value );
}
return result.toString();
}
public static class BasicNameValuePair {
private String name;
private Object value;
public BasicNameValuePair( String name, Object value ) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public Object getValue() {
return value;
}
public void setValue( Object value ) {
this.value = value;
}
}
}

View File

@@ -0,0 +1,10 @@
package com.mogo.utils.network;
public class CallerNotAliveException extends Exception {
public CallerNotAliveException( String message){
super(message);
}
}

View File

@@ -0,0 +1,13 @@
package com.mogo.utils.network;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention( RetentionPolicy.SOURCE)
@Target( ElementType.ANNOTATION_TYPE)
public @interface CallerRestrictTo {
Class<?>[] value();
}

View File

@@ -0,0 +1,29 @@
package com.mogo.utils.network;
import android.app.Activity;
import android.app.Dialog;
import android.app.Fragment;
import android.content.ContextWrapper;
import android.view.View;
import android.widget.PopupWindow;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention( RetentionPolicy.SOURCE )
@Target( ElementType.PARAMETER )
@CallerRestrictTo( {
Activity.class,
Fragment.class,
androidx.fragment.app.Fragment.class,
View.class,
Dialog.class,
PopupWindow.class,
ContextWrapper.class,
Object.class
} )
public @interface CallerType {
}

View File

@@ -0,0 +1,70 @@
package com.mogo.utils.network;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HttpParams extends BaseParams {
public HttpParams() {
}
public HttpParams( Map< String, Object > source) {
super(source);
}
public HttpParams( Object... keysAndValues) {
super(keysAndValues);
}
public HttpParams( String key, Object value) {
super(key, value);
}
public List<BasicNameValuePair> getParamList() {
List<BasicNameValuePair> list = getParamsList();
Collections.sort(list, new KVPairComparator());
return list;
}
public String getSortedParamsString() {
List<BasicNameValuePair> list = getParamList();
StringBuilder sb = new StringBuilder(NetConfig.instance().getSignaturePrefix());
for (BasicNameValuePair basicNameValuePair : list) {
sb.append(basicNameValuePair.getName());
sb.append(basicNameValuePair.getValue());
}
return sb.toString();
}
public Map< String, Object > getParamsMap() {
List<BasicNameValuePair> list = getParamList();
HashMap< String, Object > map = new HashMap< String, Object >();
for (BasicNameValuePair basicNameValuePair : list) {
map.put(basicNameValuePair.getName(), basicNameValuePair.getValue());
}
return map;
}
public String getSortedUrlParamsString() {
List<BasicNameValuePair> list = getParamList();
StringBuilder sb = new StringBuilder();
for (BasicNameValuePair basicNameValuePair : list) {
String key = basicNameValuePair.getName();
Object value = basicNameValuePair.getValue();
if (sb.length() > 0)
sb.append("&");
sb.append(key);
sb.append("=");
sb.append(value);
}
return sb.toString();
}
private class KVPairComparator implements Comparator<BasicNameValuePair> {
public int compare(BasicNameValuePair pairA, BasicNameValuePair pairB) {
return pairA.getName().compareTo(pairB.getName());
}
}
}

View File

@@ -0,0 +1,160 @@
package com.mogo.utils.network;
import android.app.Application;
import android.content.Context;
import androidx.collection.ArraySet;
import java.util.Map;
import java.util.Set;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import okhttp3.Interceptor;
import okhttp3.internal.tls.OkHostnameVerifier;
/**
* <p>
* This is a configuration class provided for clients.For better extension and customization,client can set customized parameters of network
* based on their own application. However you should set these parameters before you get the global instance
* of {@link okhttp3.OkHttpClient} by {@link OkHttpFactory} for the first time.<p/>
* <p>
* Some of the parameters have default values, so there is not a must to use this class.<p/>
*/
public final class NetConfig {
private long readTimeout = NetConstants.READ_TIMEOUT;
private long writeTimeout = NetConstants.WRITE_TIMEOUT;
private long connectTimeout = NetConstants.CONNECT_TIMEOUT;
private final Set< Interceptor > interceptors = new ArraySet<>();
private final Set< Interceptor > networkInterceptors = new ArraySet<>();
private final HostnameVerifier allowAllHostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify( String hostname, SSLSession session ) {
return true;
}
};
private String signaturePrefix = "com.foundation.network";
private HostnameVerifier hostnameVerifier = OkHostnameVerifier.INSTANCE;
private Map< String, Object > publicParams;
private boolean isLoggable;
private Context appContext;
private SSLContext sslContext;
private NetConfig() {
}
private static final class SingletonHolder {
private static final NetConfig INSTANCE = new NetConfig();
}
public static NetConfig instance() {
return SingletonHolder.INSTANCE;
}
public synchronized long getReadTimeout() {
return readTimeout;
}
public synchronized NetConfig setReadTimeout( int readTimeout ) {
this.readTimeout = readTimeout;
return this;
}
public synchronized long getWriteTimeout() {
return writeTimeout;
}
public synchronized NetConfig setWriteTimeout( int writeTimeout ) {
this.writeTimeout = writeTimeout;
return this;
}
public synchronized long getConnectTimeout() {
return connectTimeout;
}
public synchronized NetConfig setConnectTimeout( int connectTimeout ) {
this.connectTimeout = connectTimeout;
return this;
}
public synchronized HostnameVerifier getHostnameVerifier() {
return hostnameVerifier;
}
public synchronized NetConfig setHostnameVerifier( HostnameVerifier hostnameVerifier ) {
this.hostnameVerifier = hostnameVerifier;
return this;
}
public synchronized NetConfig setSignaturePrefix( String prefix ) {
this.signaturePrefix = prefix;
return this;
}
public synchronized String getSignaturePrefix() {
return signaturePrefix;
}
public synchronized Set< Interceptor > getInterceptors() {
return interceptors;
}
public synchronized NetConfig addInterceptor( Interceptor interceptor ) {
interceptors.add( interceptor );
return this;
}
public synchronized Set< Interceptor > getNetworkInterceptors() {
return networkInterceptors;
}
public synchronized NetConfig addNetworkInterceptor( Interceptor networkInterceptor ) {
networkInterceptors.add( networkInterceptor );
return this;
}
public synchronized NetConfig setPublicParams( Map< String, Object > publicParams ) {
this.publicParams = publicParams;
return this;
}
public synchronized Map< String, Object > getPublicParams() {
return publicParams;
}
public synchronized boolean isLoggable() {
return isLoggable;
}
public synchronized void setLoggable( boolean loggable ) {
isLoggable = loggable;
}
public synchronized NetConfig setAppContext( Context appContext ) {
if ( appContext instanceof Application ) {
this.appContext = appContext;
} else {
this.appContext = appContext.getApplicationContext();
}
return this;
}
public synchronized Context getAppContext() {
return appContext;
}
public synchronized SSLContext getSslContext() {
return sslContext;
}
public synchronized void setSslContext( SSLContext sslContext ) {
this.sslContext = sslContext;
}
}

View File

@@ -0,0 +1,13 @@
package com.mogo.utils.network;
public class NetConstants {
/** 无数据 */
public final static int NO_DATA = -800;
/** 数据返回正常 */
public final static int OK = 0;
public static final long READ_TIMEOUT = 20_000L;
public static final long WRITE_TIMEOUT = 20_000L;
public static final long CONNECT_TIMEOUT = 15_000L;
}

Some files were not shown because too many files have changed in this diff Show More