entry : map.entrySet()) {
172 | if (ObjectHelper.isEquals(entry.getValue(), value)) {
173 | return entry.getKey();
174 | }
175 | }
176 | return null;
177 | }
178 |
179 | /**
180 | * parse key-value pairs to map, ignore empty key
181 | *
182 | *
183 | * parseToMap("","","",true)=null
184 | * parseToMap(null,"","",true)=null
185 | * parseToMap("a:b,:","","",true)={(a,b)}
186 | * parseToMap("a:b,:d","","",true)={(a,b)}
187 | * parseToMap("a:b,c:d","","",true)={(a,b),(c,d)}
188 | * parseToMap("a=b, c = d","=",",",true)={(a,b),(c,d)}
189 | * parseToMap("a=b, c = d","=",",",false)={(a, b),( c , d)}
190 | * parseToMap("a=b, c=d","=", ",", false)={(a,b),( c,d)}
191 | * parseToMap("a=b; c=d","=", ";", false)={(a,b),( c,d)}
192 | * parseToMap("a=b, c=d", ",", ";", false)={(a=b, c=d)}
193 | *
194 | *
195 | * @param source key-value pairs
196 | * @param keyAndValueSeparator separator between key and value
197 | * @param keyAndValuePairSeparator separator between key-value pairs
198 | * @param ignoreSpace whether ignore space at the begging or end of key and value
199 | * @return
200 | */
201 | public static Map parseToMap(String source, String keyAndValueSeparator,
202 | String keyAndValuePairSeparator, boolean ignoreSpace) {
203 | if (ObjectHelper.isEmpty(source)) {
204 | return null;
205 | }
206 |
207 | if (ObjectHelper.isEmpty(keyAndValueSeparator)) {
208 | keyAndValueSeparator = DEFAULT_KEY_AND_VALUE_SEPARATOR;
209 | }
210 | if (ObjectHelper.isEmpty(keyAndValuePairSeparator)) {
211 | keyAndValuePairSeparator = DEFAULT_KEY_AND_VALUE_PAIR_SEPARATOR;
212 | }
213 | Map keyAndValueMap = new HashMap<>();
214 | String[] keyAndValueArray = source.split(keyAndValuePairSeparator);
215 | if (keyAndValueArray == null) {
216 | return null;
217 | }
218 |
219 | for (String valueEntity : keyAndValueArray) {
220 | if (!ObjectHelper.isEmpty(valueEntity)) {
221 | int separatorIndex = valueEntity.indexOf(keyAndValueSeparator);
222 | if (separatorIndex != -1) {
223 | if (ignoreSpace) {
224 | putNotEmptyKey(keyAndValueMap, valueEntity.substring(0, separatorIndex).trim(),
225 | valueEntity.substring(separatorIndex + 1).trim());
226 | } else {
227 | putNotEmptyKey(keyAndValueMap, valueEntity.substring(0, separatorIndex),
228 | valueEntity.substring(separatorIndex + 1));
229 | }
230 | }
231 | }
232 | }
233 | return keyAndValueMap;
234 | }
235 |
236 | /**
237 | * parse key-value pairs to map, ignore empty key
238 | *
239 | * @param source key-value pairs
240 | * @param ignoreSpace whether ignore space at the begging or end of key and value
241 | * @return
242 | * @see {@link #parseToMap(String, String, String, boolean)}, keyAndValueSeparator is
243 | * {@link #DEFAULT_KEY_AND_VALUE_SEPARATOR}, keyAndValuePairSeparator is
244 | * {@link #DEFAULT_KEY_AND_VALUE_PAIR_SEPARATOR}
245 | */
246 | public static Map parseToMap(String source, boolean ignoreSpace) {
247 | return parseToMap(source, DEFAULT_KEY_AND_VALUE_SEPARATOR, DEFAULT_KEY_AND_VALUE_PAIR_SEPARATOR, ignoreSpace);
248 | }
249 |
250 | /**
251 | * parse key-value pairs to map, ignore empty key, ignore space at the begging or end of key and value
252 | *
253 | * @param source key-value pairs
254 | * @return
255 | * @see {@link #parseToMap(String, String, String, boolean)}, keyAndValueSeparator is
256 | * {@link #DEFAULT_KEY_AND_VALUE_SEPARATOR}, keyAndValuePairSeparator is
257 | * {@link #DEFAULT_KEY_AND_VALUE_PAIR_SEPARATOR}, ignoreSpace is true
258 | */
259 | public static Map parseToMap(String source) {
260 | return parseToMap(source, DEFAULT_KEY_AND_VALUE_SEPARATOR, DEFAULT_KEY_AND_VALUE_PAIR_SEPARATOR, true);
261 | }
262 | }
263 |
--------------------------------------------------------------------------------
/collection/src/test/java/com/hwangjr/utils/collection/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.collection;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/debug/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/debug/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 9
9 | targetSdkVersion 23
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | testCompile 'junit:junit:4.12'
24 | compile 'com.android.support:appcompat-v7:23.1.1'
25 | }
26 |
--------------------------------------------------------------------------------
/debug/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/debug/src/androidTest/java/com/hwangjr/utils/debug/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.debug;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/debug/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/debug/src/main/java/com/hwangjr/utils/debug/AppWatcher.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.debug;
2 |
3 | import android.app.Activity;
4 | import android.app.ActivityManager;
5 | import android.app.ActivityManager.MemoryInfo;
6 | import android.content.Context;
7 | import android.util.Log;
8 |
9 | import java.util.Timer;
10 | import java.util.TimerTask;
11 |
12 | /**
13 | * watch app health
14 | */
15 | public class AppWatcher {
16 |
17 | private static AppWatcher sInstance = new AppWatcher();
18 |
19 | private Context mContext;
20 | private Timer mTimer;
21 | private TimerTask mTimerTask;
22 |
23 | private AppWatcher() {
24 | }
25 |
26 | public static AppWatcher getInstance() {
27 | return sInstance;
28 | }
29 |
30 | /**
31 | * Reference the context, must be application context
32 | *
33 | * @param context
34 | */
35 | public static void init(Context context) {
36 | sInstance.mContext = context;
37 | }
38 |
39 | /**
40 | * watch for memory usage and heap size per seconds
41 | */
42 | public void run() {
43 | mTimerTask = new TimerTask() {
44 | @Override
45 | public void run() {
46 | MemoryInfo memoryInfo = new MemoryInfo();
47 | ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Activity.ACTIVITY_SERVICE);
48 | activityManager.getMemoryInfo(memoryInfo);
49 | Runtime runtime = Runtime.getRuntime();
50 | String msg = String.format("free:%s%% %sKB total:%sKB max:%sKB ", runtime.freeMemory() * 100f / runtime.totalMemory(),
51 | runtime.freeMemory(), runtime.totalMemory() / 1024, runtime.maxMemory() / 1024);
52 | msg += String.format("native: free:%sKB total:%sKB max:%sKB", android.os.Debug.getNativeHeapFreeSize() / 1024,
53 | android.os.Debug.getNativeHeapAllocatedSize() / 1024, android.os.Debug.getNativeHeapSize() / 1024);
54 | msg += String.format("| availMem:%sKB", memoryInfo.availMem / 1024);
55 | Log.d("memory", msg);
56 | }
57 | };
58 | mTimer = new Timer();
59 | mTimer.schedule(mTimerTask, 1000, 1000);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/debug/src/main/java/com/hwangjr/utils/debug/StrictModeHelper.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.debug;
2 |
3 | import android.os.Build;
4 | import android.os.StrictMode;
5 |
6 | public class StrictModeHelper {
7 |
8 | /**
9 | * enable strict mode
10 | *
11 | * Usage:
12 | * if (BuildConfig.DEBUG) {
13 | * StrictModeHelper.enableStrictMode();
14 | * }
15 | */
16 | public static void enableStrictMode() {
17 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
18 | StrictMode.ThreadPolicy.Builder threadPolicyBuilder = new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog();
19 | StrictMode.VmPolicy.Builder vmPolicyBuilder = new StrictMode.VmPolicy.Builder().detectAll().penaltyLog();
20 |
21 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
22 | threadPolicyBuilder.penaltyFlashScreen().penaltyDeathOnNetwork();
23 | }
24 | StrictMode.setThreadPolicy(threadPolicyBuilder.build());
25 | StrictMode.setVmPolicy(vmPolicyBuilder.build());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/debug/src/test/java/com/hwangjr/utils/debug/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.debug;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | GROUP=com.hwangjr.utils
2 | VERSION_NAME=1.0.4-SNAPSHOT
3 |
4 | POM_DESCRIPTION=Common Tools For Android Developer.
5 |
6 | POM_URL=https://github.com/AndroidKnife/Utils
7 | POM_SCM_URL=https://github.com/AndroidKnife/Utils
8 | POM_SCM_CONNECTION=scm:git:git://github.com/AndroidKnife/Utils.git
9 | POM_SCM_DEV_CONNECTION=scm:git:git://github.com/AndroidKnife/Utils.git
10 |
11 | POM_LICENCE_NAME=The Apache Software License, Version 2.0
12 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
13 | POM_LICENCE_DIST=repo
14 |
15 | POM_DEVELOPER_ID=hwangjr
16 | POM_DEVELOPER_NAME=HwangJR
--------------------------------------------------------------------------------
/gradle/gradle-mvn-push.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Chris Banes
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: 'maven'
18 | apply plugin: 'signing'
19 |
20 | def isReleaseBuild() {
21 | return VERSION_NAME.contains("SNAPSHOT") == false
22 | }
23 |
24 | def getReleaseRepositoryUrl() {
25 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
26 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
27 | }
28 |
29 | def getSnapshotRepositoryUrl() {
30 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
31 | : "https://oss.sonatype.org/content/repositories/snapshots/"
32 | }
33 |
34 | def getRepositoryUsername() {
35 | return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
36 | }
37 |
38 | def getRepositoryPassword() {
39 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
40 | }
41 |
42 | afterEvaluate { project ->
43 | uploadArchives {
44 | repositories {
45 | mavenDeployer {
46 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
47 |
48 | pom.groupId = GROUP
49 | pom.artifactId = POM_ARTIFACT_ID
50 | pom.version = VERSION_NAME
51 |
52 | repository(url: getReleaseRepositoryUrl()) {
53 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
54 | }
55 | snapshotRepository(url: getSnapshotRepositoryUrl()) {
56 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
57 | }
58 |
59 | pom.project {
60 | name POM_NAME
61 | packaging POM_PACKAGING
62 | description POM_DESCRIPTION
63 | url POM_URL
64 |
65 | scm {
66 | url POM_SCM_URL
67 | connection POM_SCM_CONNECTION
68 | developerConnection POM_SCM_DEV_CONNECTION
69 | }
70 |
71 | licenses {
72 | license {
73 | name POM_LICENCE_NAME
74 | url POM_LICENCE_URL
75 | distribution POM_LICENCE_DIST
76 | }
77 | }
78 |
79 | developers {
80 | developer {
81 | id POM_DEVELOPER_ID
82 | name POM_DEVELOPER_NAME
83 | }
84 | }
85 | }
86 | }
87 | }
88 | }
89 |
90 | signing {
91 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
92 | sign configurations.archives
93 | }
94 |
95 | task androidJavadocs(type: Javadoc) {
96 | source = android.sourceSets.main.java.srcDirs
97 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
98 |
99 | if (JavaVersion.current().isJava8Compatible()) {
100 | allprojects {
101 | tasks.withType(Javadoc) {
102 | options.addStringOption('Xdoclint:none', '-quiet')
103 | }
104 | }
105 | }
106 | }
107 |
108 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
109 | classifier = 'javadoc'
110 | from androidJavadocs.destinationDir
111 | }
112 |
113 | task androidSourcesJar(type: Jar) {
114 | classifier = 'sources'
115 | from android.sourceSets.main.java.sourceFiles
116 | }
117 |
118 | artifacts {
119 | archives androidSourcesJar
120 | archives androidJavadocsJar
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndroidKnife/Utils/1cb05584faddd96a52d0970f24527f9ce0c22702/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/json/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/json/README.md:
--------------------------------------------------------------------------------
1 | json
2 | ------
3 |
4 | There are so many json libraries to parse json, like [google/gson](https://github.com/google/gson), [alibaba/fastjson](https://github.com/alibaba/fastjson), [FasterXML/jackson](https://github.com/FasterXML/jackson), etc..
5 |
6 | so why this library can exist? For 3 reasons:
7 | 1. Light, just two files [[Utils/JSONResolver.java](https://github.com/AndroidKnife/Utils/blob/master/json/src/main/java/com/hwangjr/utils/json/JSONResolver.java), [Utils/JSONNode.java](https://github.com/AndroidKnife/Utils/blob/master/json/src/main/java/com/hwangjr/utils/json/JSONNode.java)] to parse json, **suitable for `sdk` etc..**
8 | 2. Easy to use, use annotation to parse json
9 | 3. Less is more, focus on parse json, just it.
10 |
11 | This library provide:
12 | 1. Light json parse library, just two file: [[Utils/JSONResolver.java](https://github.com/AndroidKnife/Utils/blob/master/json/src/main/java/com/hwangjr/utils/json/JSONResolver.java), [Utils/JSONNode.java](https://github.com/AndroidKnife/Utils/blob/master/json/src/main/java/com/hwangjr/utils/json/JSONNode.java)]
13 | 2. [Utils/JSONGetter.java](https://github.com/AndroidKnife/Utils/blob/master/json/src/main/java/com/hwangjr/utils/json/JSONGetter.java) is an utility to get value from json object
14 | 3. [Utils/GSONWrapper.java at master · AndroidKnife/Utils](https://github.com/AndroidKnife/Utils/blob/master/json/src/main/java/com/hwangjr/utils/json/GSONWrapper.java) is an wrapper of gson, add JSONNode support
15 |
16 | That's all! Enjoy it!
17 |
18 | Usage
19 | -----
20 |
21 | This is just an utilities, so just call the function.
22 |
23 | More
24 | ------
25 | 1. [google/gson](https://github.com/google/gson)
26 | 2. [alibaba/fastjson](https://github.com/alibaba/fastjson)
27 | 3. [FasterXML/jackson](https://github.com/FasterXML/jackson)
--------------------------------------------------------------------------------
/json/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'checkstyle'
3 |
4 | checkstyle {
5 | toolVersion rootProject.ext.checkstyleVersion
6 | }
7 |
8 | task checkstyle(type: Checkstyle) {
9 | configFile rootProject.file('checkstyle.xml')
10 | source 'src/main/java'
11 | ignoreFailures false
12 | showViolations true
13 | include '**/*.java'
14 |
15 | classpath = files()
16 | }
17 |
18 | afterEvaluate {
19 | if (project.tasks.findByName('check')) {
20 | check.dependsOn('checkstyle')
21 | }
22 | }
23 |
24 | android {
25 | compileSdkVersion rootProject.ext.compileSdkVersion
26 | buildToolsVersion rootProject.ext.buildToolsVersion
27 |
28 | defaultConfig {
29 | minSdkVersion rootProject.ext.minSdkVersion
30 | targetSdkVersion rootProject.ext.targetSdkVersion
31 | consumerProguardFiles 'proguard-rules.pro'
32 | }
33 | }
34 |
35 | dependencies {
36 | testCompile deps.junit
37 |
38 | provided deps.gson
39 | compile project(':basic')
40 | compile project(':collection')
41 | }
42 |
43 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/json/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_ARTIFACT_ID=json
2 | POM_NAME=JSON
3 | POM_PACKAGING=aar
4 |
5 | #VERSION_NAME=1.0.1-SNAPSHOT
--------------------------------------------------------------------------------
/json/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 | -keepattributes *Annotation*,*Exceptions*,Signature
--------------------------------------------------------------------------------
/json/src/androidTest/java/com/hwangjr/utils/json/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.json;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/json/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/json/src/main/java/com/hwangjr/utils/json/GSONWrapper.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.json;
2 |
3 | import com.google.gson.ExclusionStrategy;
4 | import com.google.gson.FieldAttributes;
5 | import com.google.gson.FieldNamingStrategy;
6 | import com.google.gson.Gson;
7 | import com.google.gson.GsonBuilder;
8 |
9 | import java.lang.reflect.Field;
10 | import java.lang.reflect.Type;
11 |
12 | /**
13 | * Wrapper of Gson.
14 | */
15 | public class GSONWrapper {
16 |
17 | private Gson mGson;
18 |
19 | /**
20 | * Build the default gson.
21 | * This will set the field name strategy to {@link JFieldNamingStrategy} and
22 | * exclusion strategy to {@link JExclusionStrategy}
23 | *
24 | * @return gson
25 | */
26 | public static Gson buildGson() {
27 | GsonBuilder builder = new GsonBuilder().setFieldNamingStrategy(
28 | new JFieldNamingStrategy()).setExclusionStrategies(
29 | new JExclusionStrategy());
30 | Gson gson = builder.create();
31 | return gson;
32 | }
33 |
34 | public synchronized Gson getGson() {
35 | if (mGson == null) {
36 | mGson = buildGson();
37 | }
38 | return mGson;
39 | }
40 |
41 | /**
42 | * convert object to json string.
43 | *
44 | * @param src object
45 | * @return string of json
46 | */
47 | public String toJson(Object src) {
48 | return getGson().toJson(src);
49 | }
50 |
51 | /**
52 | * convert json string to the object.
53 | *
54 | * @param json json string
55 | * @param clazz object
56 | * @param
57 | * @return
58 | */
59 | public T fromJson(String json, Class clazz) {
60 | return getGson().fromJson(json, clazz);
61 | }
62 |
63 | /**
64 | * convert json string to the object.
65 | *
66 | * @param json json string
67 | * @param type type of object
68 | * @param
69 | * @return
70 | */
71 | public T fromJson(String json, Type type) {
72 | return getGson().fromJson(json, type);
73 | }
74 |
75 | private static class JFieldNamingStrategy implements FieldNamingStrategy {
76 |
77 | @Override
78 | public String translateName(Field f) {
79 | JSONNode colunmInfo = f.getAnnotation(JSONNode.class);
80 | if (colunmInfo != null) {
81 | return colunmInfo.key();
82 | }
83 | return f.getName();
84 | }
85 | }
86 |
87 | private static class JExclusionStrategy implements ExclusionStrategy {
88 |
89 | @Override
90 | public boolean shouldSkipClass(Class> clazz) {
91 | return false;
92 | }
93 |
94 | @Override
95 | public boolean shouldSkipField(FieldAttributes f) {
96 | return f.getAnnotation(JSONNode.class) == null;
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/json/src/main/java/com/hwangjr/utils/json/JSONNode.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.json;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | /**
10 | * Annotation For JSON.
11 | *
12 | * Key is the json name, desc is the description for the field.
13 | */
14 | @Target(ElementType.FIELD)
15 | @Retention(RetentionPolicy.RUNTIME)
16 | @Documented
17 | public @interface JSONNode {
18 |
19 | String key();
20 |
21 | String desc() default "";
22 | }
--------------------------------------------------------------------------------
/json/src/test/java/com/hwangjr/utils/json/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.json;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/screen/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/screen/README.md:
--------------------------------------------------------------------------------
1 | Screen
2 | ------
3 | This is a library screen library.
4 |
5 | Usage
6 | -----
7 |
8 | More
9 | ------
10 | None
--------------------------------------------------------------------------------
/screen/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'checkstyle'
3 |
4 | task checkstyle(type: Checkstyle) {
5 | configFile rootProject.file('checkstyle.xml')
6 | source 'src/main/java'
7 | ignoreFailures false
8 | showViolations true
9 | include '**/*.java'
10 |
11 | classpath = files()
12 | }
13 |
14 | afterEvaluate {
15 | if (project.tasks.findByName('check')) {
16 | check.dependsOn('checkstyle')
17 | }
18 | }
19 |
20 | android {
21 | compileSdkVersion rootProject.ext.compileSdkVersion
22 | buildToolsVersion rootProject.ext.buildToolsVersion
23 |
24 | defaultConfig {
25 | minSdkVersion rootProject.ext.minSdkVersion
26 | targetSdkVersion rootProject.ext.targetSdkVersion
27 | consumerProguardFiles 'proguard-rules.pro'
28 | }
29 | }
30 |
31 | dependencies {
32 | }
33 |
34 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/screen/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_ARTIFACT_ID=screen
2 | POM_NAME=Screen
3 | POM_PACKAGING=aar
4 |
5 | #VERSION_NAME=1.0.0-SNAPSHOT
--------------------------------------------------------------------------------
/screen/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/screen/src/androidTest/java/com/hwangjr/utils/screen/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.screen;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/screen/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/screen/src/main/java/com/hwangjr/utils/screen/DensityConverter.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.screen;
2 |
3 | import android.content.Context;
4 | import android.util.DisplayMetrics;
5 |
6 | /**
7 | * Utility to convert density.
8 | */
9 | public class DensityConverter {
10 |
11 | /**
12 | * convert pixel to dp
13 | */
14 | public static int px2dp(Context context, float pxValue) {
15 | float scale = context.getResources().getDisplayMetrics().density;
16 | return (int) (pxValue / scale + 0.5f);
17 | }
18 |
19 | /**
20 | * convert dp to px
21 | */
22 | public static int dp2px(Context context, float dpValue) {
23 | float scale = context.getResources().getDisplayMetrics().density;
24 | return (int) (dpValue * scale + 0.5f);
25 | }
26 |
27 | /**
28 | * convert px to sp
29 | */
30 | public static int px2sp(Context context, float pxValue) {
31 | float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
32 | return (int) (pxValue / fontScale + 0.5f);
33 | }
34 |
35 | /**
36 | * convert sp to px
37 | */
38 | public static int sp2px(Context context, float spValue) {
39 | float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
40 | return (int) (spValue * fontScale + 0.5f);
41 | }
42 |
43 | /**
44 | * get screen density. {@link DisplayMetrics#density}
45 | */
46 | public static float getDensity(Context context) {
47 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
48 | return dm.density;
49 | }
50 |
51 | /**
52 | * get scaled density.{@link DisplayMetrics#scaledDensity}
53 | *
54 | * @param context
55 | * @return
56 | */
57 | public static float getScaledDensity(Context context) {
58 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
59 | return dm.scaledDensity;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/screen/src/main/java/com/hwangjr/utils/screen/ScreenHelper.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.screen;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Rect;
6 | import android.util.DisplayMetrics;
7 | import android.view.Display;
8 | import android.view.Window;
9 | import android.view.WindowManager;
10 |
11 | /**
12 | * Utility for screen.
13 | * get the screen width and height, get status bar height etc..
14 | */
15 | public class ScreenHelper {
16 |
17 | /**
18 | * get screen width. {@link DisplayMetrics#widthPixels}
19 | */
20 | public static int getScreenWidth(Context context) {
21 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
22 | return dm.widthPixels;
23 | }
24 |
25 | /**
26 | * get screen height. {@link DisplayMetrics#heightPixels}
27 | */
28 | public static int getScreenHeight(Context context) {
29 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
30 | return dm.heightPixels;
31 | }
32 |
33 | /**
34 | * get device width. {@link Display#getWidth}
35 | */
36 | public static int getDeviceWidth(Context context) {
37 | WindowManager manager = (WindowManager) context
38 | .getSystemService(Context.WINDOW_SERVICE);
39 | return manager.getDefaultDisplay().getWidth();
40 | }
41 |
42 | /**
43 | * get device height. {@link Display#getHeight()}
44 | */
45 | public static int getDeviceHeight(Context context) {
46 | WindowManager manager = (WindowManager) context
47 | .getSystemService(Context.WINDOW_SERVICE);
48 | return manager.getDefaultDisplay().getHeight();
49 | }
50 |
51 | /**
52 | * get status bar height.
53 | *
54 | * rely on the fact that te status bar is shown at the time you make your computation,
55 | *
56 | * getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
57 | * this will not work!!
58 | *
59 | *
60 | * @param activity
61 | * @return
62 | */
63 | public static int getStatusBarHeight(Activity activity) {
64 | Rect frame = new Rect();
65 | activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
66 | return frame.top;
67 | }
68 |
69 | /**
70 | * get status bar height from dimension resource called status_bar_height.
71 | *
72 | * @param context
73 | * @return
74 | */
75 | public static int getStatusBarHeight(Context context) {
76 | int result = 0;
77 | int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
78 | if (resourceId > 0) {
79 | result = context.getResources().getDimensionPixelSize(resourceId);
80 | }
81 | return result;
82 | }
83 |
84 | /**
85 | * get status bar plus app bar height, just content's({@link Window#ID_ANDROID_CONTENT}) top.
86 | *
87 | * @param activity
88 | * @return
89 | */
90 | public static int getContentTopHeight(Activity activity) {
91 | return activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
92 | }
93 |
94 | /**
95 | * get app bar height
96 | *
97 | * @param activity
98 | * @return
99 | */
100 | public static int getAppBarHeight(Activity activity) {
101 | return getContentTopHeight(activity) - getStatusBarHeight((Context) activity);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/screen/src/main/java/com/hwangjr/utils/screen/ScreenShoot.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.screen;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.Canvas;
7 | import android.graphics.Picture;
8 | import android.os.Environment;
9 | import android.view.View;
10 | import android.webkit.WebView;
11 |
12 | import java.io.File;
13 | import java.io.FileNotFoundException;
14 | import java.io.FileOutputStream;
15 | import java.io.IOException;
16 | import java.text.SimpleDateFormat;
17 | import java.util.Date;
18 |
19 | /**
20 | * Shoot for activity and view etc..
21 | */
22 | public class ScreenShoot {
23 |
24 | /**
25 | * shoot the activity, exclude the status bar.
26 | */
27 | public static Bitmap shoot(Activity activity) {
28 | View view = activity.getWindow().getDecorView();
29 | Bitmap drawingCache = getViewDrawableCache(view);
30 | int statusBarHeight = ScreenHelper.getStatusBarHeight(activity);
31 | int width = ScreenHelper.getDeviceWidth(activity);
32 | int height = ScreenHelper.getDeviceHeight(activity);
33 | Bitmap bitmap = Bitmap.createBitmap(drawingCache, 0, statusBarHeight, width, height - statusBarHeight);
34 | view.destroyDrawingCache();
35 | return bitmap;
36 | }
37 |
38 | /**
39 | * shoot the view
40 | */
41 | public static Bitmap shoot(View view) {
42 | Bitmap drawingCache = getViewDrawableCache(view);
43 | Bitmap bitmap = Bitmap.createBitmap(drawingCache, 0, 0, drawingCache.getWidth(), drawingCache.getHeight());
44 | view.destroyDrawingCache();
45 | return bitmap;
46 | }
47 |
48 | /**
49 | * shoot the web view
50 | */
51 | public static Bitmap shoot(WebView webView) {
52 | Picture snapShot = webView.capturePicture();
53 | Bitmap bitmap = Bitmap.createBitmap(snapShot.getWidth(), snapShot.getHeight(), Bitmap.Config.ARGB_8888);
54 | Canvas canvas = new Canvas(bitmap);
55 | snapShot.draw(canvas);
56 | return bitmap;
57 | }
58 |
59 | /**
60 | * get view drawable cache.
61 | *
62 | * Remember to destroy the cache.{@link View#destroyDrawingCache()}
63 | *
64 | */
65 | private static Bitmap getViewDrawableCache(View view) {
66 | view.setDrawingCacheEnabled(true);
67 | view.buildDrawingCache();
68 | return view.getDrawingCache();
69 | }
70 |
71 | /**
72 | * shoot activity and save bitmap to default path.
73 | * if save succeed, it will return the path.
74 | * path : {@link #getDefaultPath(Context)}
75 | */
76 | public static String shootAndSave(Activity activity) {
77 | String filePath = getDefaultPath(activity);
78 | return saveBitmap(shoot(activity), filePath) ? filePath : "";
79 | }
80 |
81 | /**
82 | * shoot web view and save bitmap to default path.
83 | * if save succeed, it will return the path.
84 | * path : {@link #getDefaultPath(Context)}
85 | */
86 | public static String shootAndSave(WebView webView) {
87 | String filePath = getDefaultPath(webView.getContext());
88 | return saveBitmap(shoot(webView), filePath) ? filePath : "";
89 | }
90 |
91 | /**
92 | * save the bitmap to path.
93 | */
94 | public static boolean saveBitmap(Bitmap bitmap, String path) {
95 | FileOutputStream outputStream = null;
96 | try {
97 | outputStream = new FileOutputStream(path);
98 | if (outputStream != null) {
99 | bitmap.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
100 | outputStream.flush();
101 | outputStream.close();
102 | outputStream = null;
103 | return true;
104 | }
105 | } catch (FileNotFoundException e) {
106 | e.printStackTrace();
107 | } catch (IOException e) {
108 | e.printStackTrace();
109 | } finally {
110 | if (outputStream != null) {
111 | try {
112 | outputStream.close();
113 | } catch (IOException e) {
114 | e.printStackTrace();
115 | }
116 | }
117 | }
118 | return false;
119 | }
120 |
121 | /**
122 | * generate the default path for the file.
123 | * default file name format is: yyyyMMddHHmmss.png.
124 | */
125 | private static String getDefaultPath(Context context) {
126 | String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".png";
127 | String path = context.getFilesDir() + fileName;
128 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
129 | path = context.getExternalCacheDir() + File.separator + fileName;
130 | }
131 | return path;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/screen/src/test/java/com/hwangjr/utils/screen/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.screen;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':softinput', ':timber', ':json', ':xml', ':archives', ':shell', ':collection', ':basic', ':application', ':templete', ':debug', ':screen', ':animation'
2 |
--------------------------------------------------------------------------------
/shell/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/shell/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'checkstyle'
3 |
4 | checkstyle {
5 | toolVersion rootProject.ext.checkstyleVersion
6 | }
7 |
8 | task checkstyle(type: Checkstyle) {
9 | configFile rootProject.file('checkstyle.xml')
10 | source 'src/main/java'
11 | ignoreFailures false
12 | showViolations true
13 | include '**/*.java'
14 |
15 | classpath = files()
16 | }
17 |
18 | afterEvaluate {
19 | if (project.tasks.findByName('check')) {
20 | check.dependsOn('checkstyle')
21 | }
22 | }
23 |
24 | android {
25 | compileSdkVersion rootProject.ext.compileSdkVersion
26 | buildToolsVersion rootProject.ext.buildToolsVersion
27 |
28 | defaultConfig {
29 | minSdkVersion rootProject.ext.minSdkVersion
30 | targetSdkVersion rootProject.ext.targetSdkVersion
31 | consumerProguardFiles 'proguard-rules.pro'
32 | }
33 | }
34 |
35 | dependencies {
36 | testCompile deps.junit
37 | }
38 |
39 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/shell/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_ARTIFACT_ID=shell
2 | POM_NAME=Shell
3 | POM_PACKAGING=jar
4 |
5 | #VERSION_NAME=1.0.0-SNAPSHOT
--------------------------------------------------------------------------------
/shell/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/shell/src/androidTest/java/com/hwangjr/utils/shell/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.shell;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/shell/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/shell/src/main/java/com/hwangjr/utils/shell/ShellHelper.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.shell;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.DataOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStreamReader;
9 | import java.util.List;
10 |
11 | /**
12 | * Execute Shell For Android.
13 | *
14 | * This utility is used to check root permission or exec command.
15 | * While exec commands, the result will wrapped by {@link CommandResult}.
16 | */
17 | public class ShellHelper {
18 | public static final String COMMAND_SU = "su";
19 | public static final String COMMAND_SH = "sh";
20 | public static final String COMMAND_EXIT = "exit\n";
21 | public static final String COMMAND_LINE_END = "\n";
22 |
23 | private ShellHelper() {
24 | throw new AssertionError();
25 | }
26 |
27 | /**
28 | * check whether has root permission
29 | *
30 | * @return true has root permission, false don't have permission
31 | */
32 | public static boolean checkRootPermission() {
33 | return exec("echo root", true, false).result == 0;
34 | }
35 |
36 | /**
37 | * execute shell command, default return result msg
38 | *
39 | * @param command command
40 | * @param isRoot whether need to run with root
41 | * @return
42 | * @see ShellHelper#exec(String[], boolean, boolean)
43 | */
44 | public static CommandResult exec(String command, boolean isRoot) {
45 | return exec(new String[]{command}, isRoot, true);
46 | }
47 |
48 | /**
49 | * execute shell commands, default return result msg
50 | *
51 | * @param commands command list
52 | * @param isRoot whether need to run with root
53 | * @return
54 | * @see ShellHelper#exec(String[], boolean, boolean)
55 | */
56 | public static CommandResult exec(List commands, boolean isRoot) {
57 | return exec(commands == null ? null : commands.toArray(new String[]{}), isRoot, true);
58 | }
59 |
60 | /**
61 | * execute shell commands, default return result msg
62 | *
63 | * @param commands command array
64 | * @param isRoot whether need to run with root
65 | * @return
66 | * @see ShellHelper#exec(String[], boolean, boolean)
67 | */
68 | public static CommandResult exec(String[] commands, boolean isRoot) {
69 | return exec(commands, isRoot, true);
70 | }
71 |
72 | /**
73 | * execute shell command
74 | *
75 | * @param command command
76 | * @param isRoot whether need to run with root
77 | * @param isNeedResultMsg whether need result msg
78 | * @return
79 | * @see ShellHelper#exec(String[], boolean, boolean)
80 | */
81 | public static CommandResult exec(String command, boolean isRoot, boolean isNeedResultMsg) {
82 | return exec(new String[]{command}, isRoot, isNeedResultMsg);
83 | }
84 |
85 | /**
86 | * execute shell commands
87 | *
88 | * @param commands command list
89 | * @param isRoot whether need to run with root
90 | * @param isNeedResultMsg whether need result msg
91 | * @return
92 | * @see ShellHelper#exec(String[], boolean, boolean)
93 | */
94 | public static CommandResult exec(List commands, boolean isRoot, boolean isNeedResultMsg) {
95 | return exec(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg);
96 | }
97 |
98 | /**
99 | * execute shell commands
100 | *
101 | * @param commands command array
102 | * @param isRoot whether need to run with root
103 | * @param isNeedResultMsg whether need result msg
104 | * @return
105 | * - if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and
106 | * {@link CommandResult#errorMsg} is null.
107 | * - if {@link CommandResult#result} is -1, there maybe some exceptions.
108 | *
109 | */
110 | public static CommandResult exec(String[] commands, boolean isRoot, boolean isNeedResultMsg) {
111 | int result = -1;
112 | if (commands == null || commands.length == 0) {
113 | return new CommandResult(result, null, null);
114 | }
115 |
116 | Process process = null;
117 | BufferedReader successResult = null;
118 | BufferedReader errorResult = null;
119 | StringBuilder successMsg = null;
120 | StringBuilder errorMsg = null;
121 | DataOutputStream os = null;
122 |
123 | try {
124 | process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
125 | os = new DataOutputStream(process.getOutputStream());
126 | for (String command : commands) {
127 | if (!TextUtils.isEmpty(command)) {
128 | // do not use os.writeBytes(command), avoid chinese charset error
129 | os.write(command.getBytes());
130 | os.writeBytes(COMMAND_LINE_END);
131 | os.flush();
132 | }
133 | }
134 | os.writeBytes(COMMAND_EXIT);
135 | os.flush();
136 |
137 | result = process.waitFor();
138 | // get command result
139 | if (isNeedResultMsg) {
140 | successMsg = new StringBuilder();
141 | errorMsg = new StringBuilder();
142 | successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
143 | errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
144 | String s;
145 | while ((s = successResult.readLine()) != null) {
146 | successMsg.append(s);
147 | }
148 | while ((s = errorResult.readLine()) != null) {
149 | errorMsg.append(s);
150 | }
151 | }
152 | } catch (IOException e) {
153 | e.printStackTrace();
154 | } catch (Exception e) {
155 | e.printStackTrace();
156 | } finally {
157 | try {
158 | if (os != null) {
159 | os.close();
160 | }
161 | if (successResult != null) {
162 | successResult.close();
163 | }
164 | if (errorResult != null) {
165 | errorResult.close();
166 | }
167 | } catch (IOException e) {
168 | e.printStackTrace();
169 | }
170 | if (process != null) {
171 | process.destroy();
172 | }
173 | }
174 | return new CommandResult(result, successMsg == null ? null : successMsg.toString(),
175 | errorMsg == null ? null : errorMsg.toString());
176 | }
177 |
178 | /**
179 | * result of command
180 | *
181 | * - {@link CommandResult#result} means result of command, 0 means normal, else means error,
182 | * same to execute in linux shell
183 | * - {@link CommandResult#successMsg} means success message of command result
184 | * - {@link CommandResult#errorMsg} means error message of command result
185 | *
186 | */
187 | public static class CommandResult {
188 | /**
189 | * result of command
190 | **/
191 | public int result;
192 | /**
193 | * success message of command result
194 | **/
195 | public String successMsg;
196 | /**
197 | * error message of command result
198 | **/
199 | public String errorMsg;
200 |
201 | public CommandResult(int result) {
202 | this.result = result;
203 | }
204 |
205 | public CommandResult(int result, String successMsg, String errorMsg) {
206 | this.result = result;
207 | this.successMsg = successMsg;
208 | this.errorMsg = errorMsg;
209 | }
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/shell/src/test/java/com/hwangjr/utils/shell/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.shell;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/softinput/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/softinput/README.md:
--------------------------------------------------------------------------------
1 | SoftInput
2 | ------
3 |
4 | SoftInput has many functions to control the soft keyguard show/hide.
5 |
--------------------------------------------------------------------------------
/softinput/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'checkstyle'
3 |
4 | task checkstyle(type: Checkstyle) {
5 | configFile rootProject.file('checkstyle.xml')
6 | source 'src/main/java'
7 | ignoreFailures false
8 | showViolations true
9 | include '**/*.java'
10 |
11 | classpath = files()
12 | }
13 |
14 | afterEvaluate {
15 | if (project.tasks.findByName('check')) {
16 | check.dependsOn('checkstyle')
17 | }
18 | }
19 |
20 | android {
21 | compileSdkVersion rootProject.ext.compileSdkVersion
22 | buildToolsVersion rootProject.ext.buildToolsVersion
23 |
24 | defaultConfig {
25 | minSdkVersion rootProject.ext.minSdkVersion
26 | targetSdkVersion rootProject.ext.targetSdkVersion
27 | consumerProguardFiles 'proguard-rules.pro'
28 | }
29 | }
30 |
31 | dependencies {
32 | testCompile deps.junit
33 | }
34 |
35 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/softinput/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_ARTIFACT_ID=softinput
2 | POM_NAME=SoftInput
3 | POM_PACKAGING=aar
4 |
5 | #VERSION_NAME=1.0.2-SNAPSHOT
--------------------------------------------------------------------------------
/softinput/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/softinput/src/androidTest/java/com/hwangjr/utils/softinput/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.softinput;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/softinput/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/softinput/src/main/java/com/hwangjr/utils/softinput/SoftInput.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.softinput;
2 |
3 | import android.content.Context;
4 | import android.os.IBinder;
5 | import android.os.ResultReceiver;
6 | import android.view.View;
7 | import android.view.inputmethod.InputMethodManager;
8 |
9 | /**
10 | * Show/hide soft keyboard.
11 | */
12 | public class SoftInput {
13 |
14 | private SoftInput() {
15 | }
16 |
17 | /**
18 | * Show the input method's soft input area, so the user sees the input method window and can interact with it.
19 | * This can only be called from the currently active input method, as validated by the given token.
20 | *
21 | * @param view the current focused view
22 | */
23 | public static void showSoftInputFromInputMethod(View view) {
24 | if (view != null) {
25 | Context context = view.getContext();
26 | IBinder windowToken = view.getWindowToken();
27 | InputMethodManager inputMethodManager = (InputMethodManager) context
28 | .getSystemService(Context.INPUT_METHOD_SERVICE);
29 | inputMethodManager.showSoftInputFromInputMethod(windowToken, 0);
30 | }
31 | }
32 |
33 | /**
34 | * Request to hide the soft input window from the context of the window that is currently accepting input.
35 | * This should be called as a result of the user doing some actually than fairly explicitly requests to have the input window hidden.
36 | *
37 | * @param view the current focused view
38 | */
39 | public static boolean hideSoftInputFromWindow(View view) {
40 | boolean result = false;
41 | if (view != null) {
42 | Context context = view.getContext();
43 | IBinder windowToken = view.getWindowToken();
44 | InputMethodManager inputMethodManager = (InputMethodManager) context
45 | .getSystemService(Context.INPUT_METHOD_SERVICE);
46 | result = inputMethodManager.hideSoftInputFromWindow(windowToken, 0);
47 | }
48 | return result;
49 | }
50 |
51 | /**
52 | * Synonym for {@link InputMethodManager.showSoftInput(View, int, ResultReceiver)} without
53 | * a result receiver: explicitly request that the current input method's
54 | * soft input area be shown to the user, if needed.
55 | *
56 | * @param view the current focused view
57 | */
58 | public static boolean showSoftInput(View view) {
59 | boolean result = false;
60 | if (view != null) {
61 | InputMethodManager inputMethodManager = (InputMethodManager) view.getContext()
62 | .getSystemService(Context.INPUT_METHOD_SERVICE);
63 | result = inputMethodManager.showSoftInput(view, 0);
64 | }
65 | return result;
66 | }
67 |
68 | /**
69 | * Request to hide the soft input window from the context of the window that is currently accepting input.
70 | * This should be called as a result of the user doing some actually than fairly explicitly requests to have the input window hidden.
71 | *
72 | * @param view the current focused view
73 | */
74 | public static boolean hideSoftInput(View view) {
75 | return hideSoftInputFromWindow(view);
76 | }
77 |
78 | /**
79 | * This method toggles the input method window display.
80 | * If the input window is already displayed, it gets hidden. If not the input window will be displayed.
81 | *
82 | * @param context context to get the input service
83 | */
84 | public static void toggle(Context context) {
85 | if (context != null) {
86 | InputMethodManager inputMethodManager = (InputMethodManager) context
87 | .getSystemService(Context.INPUT_METHOD_SERVICE);
88 | inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/softinput/src/test/java/com/hwangjr/utils/softinput/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.softinput;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/templete/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/templete/README.md:
--------------------------------------------------------------------------------
1 | Templete
2 | ------
3 | This is a library templete.
4 |
5 | Usage
6 | -----
7 | Copy the files.
8 |
9 | More
10 | ------
11 | None
--------------------------------------------------------------------------------
/templete/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'checkstyle'
3 |
4 | task checkstyle(type: Checkstyle) {
5 | configFile rootProject.file('checkstyle.xml')
6 | source 'src/main/java'
7 | ignoreFailures false
8 | showViolations true
9 | include '**/*.java'
10 |
11 | classpath = files()
12 | }
13 |
14 | afterEvaluate {
15 | if (project.tasks.findByName('check')) {
16 | check.dependsOn('checkstyle')
17 | }
18 | }
19 |
20 | android {
21 | compileSdkVersion rootProject.ext.compileSdkVersion
22 | buildToolsVersion rootProject.ext.buildToolsVersion
23 |
24 | defaultConfig {
25 | minSdkVersion rootProject.ext.minSdkVersion
26 | targetSdkVersion rootProject.ext.targetSdkVersion
27 | consumerProguardFiles 'proguard-rules.pro'
28 | }
29 | }
30 |
31 | dependencies {
32 | }
33 |
34 | //apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/templete/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_ARTIFACT_ID=templete
2 | POM_NAME=Templete
3 | POM_PACKAGING=aar
4 |
5 | #VERSION_NAME=1.0.0-SNAPSHOT
--------------------------------------------------------------------------------
/templete/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/templete/src/androidTest/java/com/hwangjr/utils/templete/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.templete;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/templete/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/templete/src/test/java/com/hwangjr/utils/templete/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.templete;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/timber/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/timber/README.md:
--------------------------------------------------------------------------------
1 | Timber
2 | ------
3 |
4 | [Timber]((https://github.com/JakeWharton/timber)) is awesome, it can make `Log` to be a happy stuff!
5 |
6 | You also won't miss [Pidcat](http://github.com/JakeWharton/pidcat/) !
7 |
8 | So, why this library exists:
9 | > JakeWharton ([Minimum SDK · Issue #98 · JakeWharton/timber](https://github.com/JakeWharton/timber/issues/98))
10 | No one has given a compelling argument other than "because you can". Why
11 | should support be added for this API level no one is using?
12 |
13 | Usage
14 | -----
15 |
16 | Two easy steps:
17 |
18 | 1. Install any `Tree` instances you want in the `onCreate` of your application class.
19 | 2. Call `Timber`'s static methods everywhere throughout your app.
20 |
21 | Check out the sample app in `timber-sample/` to see it in action.
22 |
23 | More
24 | ------
25 |
26 | [JakeWharton/timber](https://github.com/JakeWharton/timber)
27 |
--------------------------------------------------------------------------------
/timber/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'checkstyle'
3 |
4 | task checkstyle(type: Checkstyle) {
5 | configFile rootProject.file('checkstyle.xml')
6 | source 'src/main/java'
7 | ignoreFailures false
8 | showViolations true
9 | include '**/*.java'
10 |
11 | classpath = files()
12 | }
13 |
14 | afterEvaluate {
15 | if (project.tasks.findByName('check')) {
16 | check.dependsOn('checkstyle')
17 | }
18 | }
19 |
20 | android {
21 | compileSdkVersion rootProject.ext.compileSdkVersion
22 | buildToolsVersion rootProject.ext.buildToolsVersion
23 |
24 | defaultConfig {
25 | minSdkVersion rootProject.ext.minSdkVersion
26 | targetSdkVersion rootProject.ext.targetSdkVersion
27 | consumerProguardFiles 'consumer-proguard-rules.pro'
28 | }
29 | }
30 |
31 | dependencies {
32 | provided deps.jbannotations
33 |
34 | testCompile deps.junit
35 | testCompile deps.festandroid
36 | testCompile deps.festassert
37 | testCompile deps.robolectric
38 | }
39 |
40 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/timber/consumer-proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -dontwarn org.jetbrains.annotations.**
2 |
--------------------------------------------------------------------------------
/timber/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_ARTIFACT_ID=timber
2 | POM_NAME=Timber
3 | POM_PACKAGING=aar
4 |
5 | VERSION_NAME=4.1.2-SNAPSHOT
--------------------------------------------------------------------------------
/timber/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/timber/src/test/java/timber/log/TimberTest.java:
--------------------------------------------------------------------------------
1 | package timber.log;
2 |
3 | import android.util.Log;
4 |
5 | import java.net.UnknownHostException;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.List;
9 | import java.util.concurrent.CountDownLatch;
10 | import org.junit.After;
11 | import org.junit.Before;
12 | import org.junit.Test;
13 | import org.junit.runner.RunWith;
14 | import org.robolectric.RobolectricTestRunner;
15 | import org.robolectric.annotation.Config;
16 | import org.robolectric.shadows.ShadowLog;
17 |
18 | import static org.fest.assertions.api.Assertions.assertThat;
19 | import static org.junit.Assert.fail;
20 | import static org.robolectric.shadows.ShadowLog.LogItem;
21 |
22 | @RunWith(RobolectricTestRunner.class) //
23 | @Config(manifest = Config.NONE)
24 | public class TimberTest {
25 | @Before @After public void setUpAndTearDown() {
26 | Timber.uprootAll();
27 | }
28 |
29 | // NOTE: This class references the line number. Keep it at the top so it does not change.
30 | @Test public void debugTreeCanAlterCreatedTag() {
31 | Timber.plant(new Timber.DebugTree() {
32 | @Override protected String createStackElementTag(StackTraceElement element) {
33 | return super.createStackElementTag(element) + ':' + element.getLineNumber();
34 | }
35 | });
36 |
37 | Timber.d("Test");
38 |
39 | assertLog()
40 | .hasDebugMessage("TimberTest:37", "Test")
41 | .hasNoMoreMessages();
42 | }
43 |
44 | @Test public void recursion() {
45 | Timber.Tree timber = Timber.asTree();
46 | try {
47 | Timber.plant(timber);
48 | fail();
49 | } catch (IllegalArgumentException e) {
50 | assertThat(e).hasMessage("Cannot plant Timber into itself.");
51 | }
52 | }
53 |
54 | @Test public void treeCount() {
55 | // inserts trees and checks if the amount of returned trees matches.
56 | assertThat(Timber.treeCount()).isEqualTo(0);
57 | for(int i= 1 ; i < 50 ; i++){
58 | Timber.plant(new Timber.DebugTree());
59 | assertThat(Timber.treeCount()).isEqualTo(i);
60 | }
61 | Timber.uprootAll();
62 | assertThat(Timber.treeCount()).isEqualTo(0);
63 | }
64 |
65 | @Test public void nullTree() {
66 | try {
67 | Timber.plant(null);
68 | fail();
69 | } catch (NullPointerException e) {
70 | assertThat(e).hasMessage("tree == null");
71 | }
72 | }
73 |
74 | @Test public void forestReturnsAllPlanted() {
75 | Timber.DebugTree tree1 = new Timber.DebugTree();
76 | Timber.DebugTree tree2 = new Timber.DebugTree();
77 | Timber.plant(tree1);
78 | Timber.plant(tree2);
79 |
80 | assertThat(Timber.forest()).containsExactly(tree1, tree2);
81 | }
82 |
83 | @Test public void uprootThrowsIfMissing() {
84 | try {
85 | Timber.uproot(new Timber.DebugTree());
86 | fail();
87 | } catch (IllegalArgumentException e) {
88 | assertThat(e).hasMessageStartingWith("Cannot uproot tree which is not planted: ");
89 | }
90 | }
91 |
92 | @Test public void uprootRemovesTree() {
93 | Timber.DebugTree tree1 = new Timber.DebugTree();
94 | Timber.DebugTree tree2 = new Timber.DebugTree();
95 | Timber.plant(tree1);
96 | Timber.plant(tree2);
97 | Timber.d("First");
98 | Timber.uproot(tree1);
99 | Timber.d("Second");
100 |
101 | assertLog()
102 | .hasDebugMessage("TimberTest", "First")
103 | .hasDebugMessage("TimberTest", "First")
104 | .hasDebugMessage("TimberTest", "Second")
105 | .hasNoMoreMessages();
106 | }
107 |
108 | @Test public void uprootAllRemovesAll() {
109 | Timber.DebugTree tree1 = new Timber.DebugTree();
110 | Timber.DebugTree tree2 = new Timber.DebugTree();
111 | Timber.plant(tree1);
112 | Timber.plant(tree2);
113 | Timber.d("First");
114 | Timber.uprootAll();
115 | Timber.d("Second");
116 |
117 | assertLog()
118 | .hasDebugMessage("TimberTest", "First")
119 | .hasDebugMessage("TimberTest", "First")
120 | .hasNoMoreMessages();
121 | }
122 |
123 | @Test public void noArgsDoesNotFormat() {
124 | Timber.plant(new Timber.DebugTree());
125 | Timber.d("te%st");
126 |
127 | assertLog()
128 | .hasDebugMessage("TimberTest", "te%st")
129 | .hasNoMoreMessages();
130 | }
131 |
132 | @Test public void debugTreeTagGeneration() {
133 | Timber.plant(new Timber.DebugTree());
134 | Timber.d("Hello, world!");
135 |
136 | assertLog()
137 | .hasDebugMessage("TimberTest", "Hello, world!")
138 | .hasNoMoreMessages();
139 | }
140 |
141 | @Test public void debugTreeTagGenerationStripsAnonymousClassMarker() {
142 | Timber.plant(new Timber.DebugTree());
143 | new Runnable() {
144 | @Override public void run() {
145 | Timber.d("Hello, world!");
146 |
147 | new Runnable() {
148 | @Override public void run() {
149 | Timber.d("Hello, world!");
150 | }
151 | }.run();
152 | }
153 | }.run();
154 |
155 | assertLog()
156 | .hasDebugMessage("TimberTest", "Hello, world!")
157 | .hasDebugMessage("TimberTest", "Hello, world!")
158 | .hasNoMoreMessages();
159 | }
160 |
161 | @Test public void debugTreeCustomTag() {
162 | Timber.plant(new Timber.DebugTree());
163 | Timber.tag("Custom").d("Hello, world!");
164 |
165 | assertLog()
166 | .hasDebugMessage("Custom", "Hello, world!")
167 | .hasNoMoreMessages();
168 | }
169 |
170 | @Test public void messageWithException() {
171 | Timber.plant(new Timber.DebugTree());
172 | NullPointerException datThrowable = new NullPointerException();
173 | Timber.e(datThrowable, "OMFG!");
174 |
175 | assertExceptionLogged("OMFG!", "java.lang.NullPointerException");
176 | }
177 |
178 | @Test public void exceptionFromSpawnedThread() throws InterruptedException {
179 | Timber.plant(new Timber.DebugTree());
180 | final NullPointerException datThrowable = new NullPointerException();
181 | final CountDownLatch latch = new CountDownLatch(1);
182 | new Thread() {
183 | @Override public void run() {
184 | Timber.e(datThrowable, "OMFG!");
185 | latch.countDown();
186 | }
187 | }.run();
188 | latch.await();
189 | assertExceptionLogged("OMFG!", "java.lang.NullPointerException");
190 | }
191 |
192 | @Test public void nullMessageWithThrowable() {
193 | Timber.plant(new Timber.DebugTree());
194 | final NullPointerException datThrowable = new NullPointerException();
195 | Timber.e(datThrowable, null);
196 |
197 | assertExceptionLogged("", "java.lang.NullPointerException");
198 | }
199 |
200 | @Test public void chunkAcrossNewlinesAndLimit() {
201 | Timber.plant(new Timber.DebugTree());
202 | Timber.d(repeat('a', 3000) + '\n' + repeat('b', 6000) + '\n' + repeat('c', 3000));
203 |
204 | assertLog()
205 | .hasDebugMessage("TimberTest", repeat('a', 3000))
206 | .hasDebugMessage("TimberTest", repeat('b', 4000))
207 | .hasDebugMessage("TimberTest", repeat('b', 2000))
208 | .hasDebugMessage("TimberTest", repeat('c', 3000))
209 | .hasNoMoreMessages();
210 | }
211 |
212 | @Test public void nullMessageWithoutThrowable() {
213 | Timber.plant(new Timber.DebugTree());
214 | Timber.d(null);
215 |
216 | assertLog().hasNoMoreMessages();
217 | }
218 |
219 | @Test public void logMessageCallback() {
220 | final List logs = new ArrayList();
221 | Timber.plant(new Timber.DebugTree() {
222 | @Override protected void log(int priority, String tag, String message, Throwable t) {
223 | logs.add(priority + " " + tag + " " + message);
224 | }
225 | });
226 |
227 | Timber.v("Verbose");
228 | Timber.tag("Custom").v("Verbose");
229 | Timber.d("Debug");
230 | Timber.tag("Custom").d("Debug");
231 | Timber.i("Info");
232 | Timber.tag("Custom").i("Info");
233 | Timber.w("Warn");
234 | Timber.tag("Custom").w("Warn");
235 | Timber.e("Error");
236 | Timber.tag("Custom").e("Error");
237 | Timber.wtf("Assert");
238 | Timber.tag("Custom").wtf("Assert");
239 |
240 | assertThat(logs).containsExactly( //
241 | "2 TimberTest Verbose", //
242 | "2 Custom Verbose", //
243 | "3 TimberTest Debug", //
244 | "3 Custom Debug", //
245 | "4 TimberTest Info", //
246 | "4 Custom Info", //
247 | "5 TimberTest Warn", //
248 | "5 Custom Warn", //
249 | "6 TimberTest Error", //
250 | "6 Custom Error", //
251 | "7 TimberTest Assert", //
252 | "7 Custom Assert" //
253 | );
254 | }
255 |
256 | @Test public void logAtSpecifiedPriority() {
257 | Timber.plant(new Timber.DebugTree());
258 |
259 | Timber.log(Log.VERBOSE, "Hello, World!");
260 | Timber.log(Log.DEBUG, "Hello, World!");
261 | Timber.log(Log.INFO, "Hello, World!");
262 | Timber.log(Log.WARN, "Hello, World!");
263 | Timber.log(Log.ERROR, "Hello, World!");
264 | Timber.log(Log.ASSERT, "Hello, World!");
265 |
266 | assertLog()
267 | .hasVerboseMessage("TimberTest", "Hello, World!")
268 | .hasDebugMessage("TimberTest", "Hello, World!")
269 | .hasInfoMessage("TimberTest", "Hello, World!")
270 | .hasWarnMessage("TimberTest", "Hello, World!")
271 | .hasErrorMessage("TimberTest", "Hello, World!")
272 | .hasAssertMessage("TimberTest", "Hello, World!")
273 | .hasNoMoreMessages();
274 | }
275 |
276 | @Test public void formatting() {
277 | Timber.plant(new Timber.DebugTree());
278 | Timber.v("Hello, %s!", "World");
279 | Timber.d("Hello, %s!", "World");
280 | Timber.i("Hello, %s!", "World");
281 | Timber.w("Hello, %s!", "World");
282 | Timber.e("Hello, %s!", "World");
283 | Timber.wtf("Hello, %s!", "World");
284 |
285 | assertLog()
286 | .hasVerboseMessage("TimberTest", "Hello, World!")
287 | .hasDebugMessage("TimberTest", "Hello, World!")
288 | .hasInfoMessage("TimberTest", "Hello, World!")
289 | .hasWarnMessage("TimberTest", "Hello, World!")
290 | .hasErrorMessage("TimberTest", "Hello, World!")
291 | .hasAssertMessage("TimberTest", "Hello, World!")
292 | .hasNoMoreMessages();
293 | }
294 |
295 | @Test public void isLoggableControlsLogging() {
296 | Timber.plant(new Timber.DebugTree() {
297 | @Override protected boolean isLoggable(int priority) {
298 | return priority == Log.INFO;
299 | }
300 | });
301 | Timber.v("Hello, World!");
302 | Timber.d("Hello, World!");
303 | Timber.i("Hello, World!");
304 | Timber.w("Hello, World!");
305 | Timber.e("Hello, World!");
306 | Timber.wtf("Hello, World!");
307 |
308 | assertLog()
309 | .hasInfoMessage("TimberTest", "Hello, World!")
310 | .hasNoMoreMessages();
311 | }
312 |
313 | @Test public void logsUnknownHostExceptions() {
314 | Timber.plant(new Timber.DebugTree());
315 | Timber.e(new UnknownHostException(), null);
316 |
317 | assertExceptionLogged("", "UnknownHostException");
318 | }
319 |
320 | private static String repeat(char c, int number) {
321 | char[] data = new char[number];
322 | Arrays.fill(data, c);
323 | return new String(data);
324 | }
325 |
326 | private static void assertExceptionLogged(String message, String exceptionClassname) {
327 | List logs = ShadowLog.getLogs();
328 | assertThat(logs).hasSize(1);
329 | LogItem log = logs.get(0);
330 | assertThat(log.type).isEqualTo(Log.ERROR);
331 | assertThat(log.tag).isEqualTo("TimberTest");
332 | assertThat(log.msg).startsWith(message);
333 | assertThat(log.msg).contains(exceptionClassname);
334 | // We use a low-level primitive that Robolectric doesn't populate.
335 | assertThat(log.throwable).isNull();
336 | }
337 |
338 | private static LogAssert assertLog() {
339 | return new LogAssert(ShadowLog.getLogs());
340 | }
341 |
342 | private static final class LogAssert {
343 | private final List items;
344 | private int index = 0;
345 |
346 | private LogAssert(List items) {
347 | this.items = items;
348 | }
349 |
350 | public LogAssert hasVerboseMessage(String tag, String message) {
351 | return hasMessage(Log.VERBOSE, tag, message);
352 | }
353 |
354 | public LogAssert hasDebugMessage(String tag, String message) {
355 | return hasMessage(Log.DEBUG, tag, message);
356 | }
357 |
358 | public LogAssert hasInfoMessage(String tag, String message) {
359 | return hasMessage(Log.INFO, tag, message);
360 | }
361 |
362 | public LogAssert hasWarnMessage(String tag, String message) {
363 | return hasMessage(Log.WARN, tag, message);
364 | }
365 |
366 | public LogAssert hasErrorMessage(String tag, String message) {
367 | return hasMessage(Log.ERROR, tag, message);
368 | }
369 |
370 | public LogAssert hasAssertMessage(String tag, String message) {
371 | return hasMessage(Log.ASSERT, tag, message);
372 | }
373 |
374 | private LogAssert hasMessage(int priority, String tag, String message) {
375 | LogItem item = items.get(index++);
376 | assertThat(item.type).isEqualTo(priority);
377 | assertThat(item.tag).isEqualTo(tag);
378 | assertThat(item.msg).isEqualTo(message);
379 | return this;
380 | }
381 |
382 | public void hasNoMoreMessages() {
383 | assertThat(items).hasSize(index);
384 | }
385 | }
386 | }
387 |
--------------------------------------------------------------------------------
/xml/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/xml/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'checkstyle'
3 |
4 | task checkstyle(type: Checkstyle) {
5 | configFile rootProject.file('checkstyle.xml')
6 | source 'src/main/java'
7 | ignoreFailures false
8 | showViolations true
9 | include '**/*.java'
10 |
11 | classpath = files()
12 | }
13 |
14 | afterEvaluate {
15 | if (project.tasks.findByName('check')) {
16 | check.dependsOn('checkstyle')
17 | }
18 | }
19 |
20 | android {
21 | compileSdkVersion rootProject.ext.compileSdkVersion
22 | buildToolsVersion rootProject.ext.buildToolsVersion
23 |
24 | defaultConfig {
25 | minSdkVersion rootProject.ext.minSdkVersion
26 | targetSdkVersion rootProject.ext.targetSdkVersion
27 | consumerProguardFiles 'proguard-rules.pro'
28 | }
29 | }
30 |
31 | dependencies {
32 | testCompile deps.junit
33 | }
34 |
35 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/xml/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_ARTIFACT_ID=xml
2 | POM_NAME=XML
3 | POM_PACKAGING=aar
4 |
5 | #VERSION_NAME=1.0.1-SNAPSHOT
--------------------------------------------------------------------------------
/xml/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 | -keepattributes *Annotation*,*Exceptions*,Signature
--------------------------------------------------------------------------------
/xml/src/androidTest/java/com/hwangjr/utils/xml/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.xml;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/xml/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/xml/src/main/java/com/hwangjr/utils/xml/XMLNode.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.xml;
2 |
3 | import java.util.HashMap;
4 | import java.util.LinkedList;
5 |
6 | public class XMLNode {
7 |
8 | public int mId;
9 | public String mName;
10 | public int mLevel;
11 | public long mFatherId;
12 | public LinkedList mChildrenList;
13 | public HashMap mAttributesMap;
14 | public String mText;
15 |
16 | public void addAttribute(String key, String value) {
17 | if (mAttributesMap == null) {
18 | mAttributesMap = new HashMap<>();
19 | }
20 | mAttributesMap.put(key, value);
21 | }
22 |
23 | public String getAttributeValue(String attributeName) {
24 | if (mAttributesMap == null) {
25 | return null;
26 | }
27 | return mAttributesMap.get(attributeName);
28 | }
29 |
30 | public void addChild(XMLNode node) {
31 | if (mChildrenList == null) {
32 | mChildrenList = new LinkedList<>();
33 | }
34 | mChildrenList.add(node);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/xml/src/main/java/com/hwangjr/utils/xml/XMLResolver.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.xml;
2 |
3 | import android.content.Context;
4 | import android.util.Xml;
5 |
6 | import org.xmlpull.v1.XmlPullParser;
7 | import org.xmlpull.v1.XmlPullParserException;
8 |
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.util.ArrayList;
12 | import java.util.LinkedList;
13 | import java.util.List;
14 |
15 | public class XMLResolver {
16 |
17 | public List readXml(XmlPullParser parser) {
18 | if (parser == null) {
19 | return null;
20 | }
21 |
22 | LinkedList nodeList = new LinkedList<>();
23 | try {
24 | int eventType = parser.getEventType();
25 | XMLNode node = null;
26 |
27 | while (eventType != XmlPullParser.END_DOCUMENT) {
28 | switch (eventType) {
29 | case XmlPullParser.START_TAG:
30 | node = initNode(parser);
31 | nodeList.add(node);
32 | break;
33 | case XmlPullParser.END_TAG:
34 | node = getLastNode(nodeList, parser.getName());
35 | if (node != null) {
36 | if (node.mLevel > 1 && nodeList.size() > 0) {
37 | XMLNode father = getFatherNode(nodeList, node);
38 | node.mFatherId = father.mId;
39 | father.addChild(node);
40 | }
41 | }
42 | break;
43 | case XmlPullParser.TEXT:
44 | node = getLastNode(nodeList, parser.getDepth());
45 | if (node != null) {
46 | if (parser.getText() != null && parser.getText().trim().length() > 0) {
47 | node.mText = parser.getText().trim();
48 | }
49 | }
50 | break;
51 | default:
52 | break;
53 | }
54 | eventType = parser.next();
55 | }
56 | } catch (IOException e) {
57 | e.printStackTrace();
58 | } catch (XmlPullParserException e) {
59 | e.printStackTrace();
60 | }
61 | return nodeList;
62 | }
63 |
64 | public List readXml(InputStream inputStream) {
65 | if (inputStream == null) {
66 | return null;
67 | }
68 |
69 | XmlPullParser parser = Xml.newPullParser();
70 | try {
71 | parser.setInput(inputStream, "utf-8");
72 | } catch (XmlPullParserException e) {
73 | e.printStackTrace();
74 | }
75 | return readXml(parser);
76 | }
77 |
78 | /**
79 | * Read the xml file under assets folder.
80 | *
81 | * @param context context
82 | * @param fileName file name
83 | * @return
84 | */
85 | public List readXml(Context context, String fileName) {
86 | InputStream inputStream = null;
87 | try {
88 | inputStream = context.getResources().getAssets().open(fileName);
89 | } catch (IOException e) {
90 | e.printStackTrace();
91 | }
92 | List list = readXml(inputStream);
93 | try {
94 | inputStream.close();
95 | } catch (IOException e) {
96 | e.printStackTrace();
97 | }
98 | inputStream = null;
99 | return list;
100 | }
101 |
102 | /**
103 | * get xml node from node name.
104 | *
105 | * @param list
106 | * @param nodeName
107 | * @return
108 | */
109 | public List getNode(List list, String nodeName) {
110 | List nodeList = new LinkedList();
111 | for (XMLNode node : list) {
112 | if (node.mName.equals(nodeName)) {
113 | nodeList.add(node);
114 | }
115 | }
116 | return nodeList;
117 | }
118 |
119 | /**
120 | * get node attributes from node name and attribute name
121 | *
122 | * @param list
123 | * @param nodeName
124 | * @param attributeName
125 | * @return
126 | */
127 | public List getAttributeValue(List list, String nodeName, String attributeName) {
128 | List valueList = new LinkedList();
129 | for (XMLNode node : list) {
130 | if (node.mName.equals(nodeName)) {
131 | String value = node.getAttributeValue(attributeName);
132 | if (value != null) {
133 | valueList.add(value);
134 | }
135 | }
136 | }
137 | return valueList;
138 | }
139 |
140 | /**
141 | * get first attribute value from node name and attribute name
142 | *
143 | * @param list
144 | * @param nodeName
145 | * @param attributeName
146 | * @return
147 | */
148 | public String getFirstAttributeValue(List list, String nodeName, String attributeName) {
149 | List valueList = getAttributeValue(list, nodeName, attributeName);
150 | if (valueList.size() > 0) {
151 | return valueList.get(0);
152 | }
153 | return null;
154 | }
155 |
156 | /**
157 | * get the child node from father node.
158 | *
159 | * @param source
160 | * @param fatherNode
161 | * @return
162 | */
163 | public List getChildNodes(List source, String fatherNode) {
164 | if (source == null) {
165 | return null;
166 | }
167 | List list = new ArrayList();
168 | for (XMLNode xmlNode : source) {
169 | if (xmlNode.mName.equals(fatherNode)) {
170 | list.add(xmlNode);
171 | }
172 | }
173 | return list;
174 | }
175 |
176 | public void print(List nodes) {
177 | for (XMLNode node : nodes) {
178 | StringBuilder builder = new StringBuilder();
179 | builder.append("node name: " + node.mName + ", node text: " + node.mText + "\n");
180 | if (node.mAttributesMap != null) {
181 | for (String key : node.mAttributesMap.keySet()) {
182 | String value = node.getAttributeValue(key);
183 | builder.append("attribute key: " + key + ", attribute value: " + value + "\n");
184 | }
185 | }
186 | }
187 | }
188 |
189 | private XMLNode initNode(XmlPullParser parser) {
190 | XMLNode node = new XMLNode();
191 | node.mId = node.hashCode();
192 | node.mName = parser.getName();
193 | node.mLevel = parser.getDepth();
194 | for (int i = 0; i < parser.getAttributeCount(); i++) {
195 | node.addAttribute(parser.getAttributeName(i), parser.getAttributeValue(i));
196 | }
197 | return node;
198 | }
199 |
200 | private XMLNode getLastNode(LinkedList nodeList, String name) {
201 | for (int i = nodeList.size() - 1; i >= 0; i--) {
202 | if (nodeList.get(i).mName.equals(name)) {
203 | return nodeList.get(i);
204 | }
205 | }
206 | return null;
207 | }
208 |
209 | private XMLNode getLastNode(LinkedList nodeList, int depth) {
210 | for (int i = nodeList.size() - 1; i >= 0; i--) {
211 | if (nodeList.get(i).mLevel == depth) {
212 | return nodeList.get(i);
213 | }
214 | }
215 | return null;
216 | }
217 |
218 | private XMLNode getFatherNode(LinkedList nodeList, XMLNode childNode) {
219 | for (int i = nodeList.size() - 1; i >= 0; i--) {
220 | if (nodeList.get(i).mLevel == childNode.mLevel - 1) {
221 | return nodeList.get(i);
222 | }
223 | }
224 | return null;
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/xml/src/test/java/com/hwangjr/utils/xml/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hwangjr.utils.xml;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------