├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
├── androidTest
├── AndroidManifest.xml
├── java
│ └── com
│ │ └── onehilltech
│ │ └── metadata
│ │ ├── ManifestMetadataTest.java
│ │ ├── MetadataValues.java
│ │ ├── TestClass.java
│ │ └── test
│ │ └── TestActivity.java
└── res
│ └── values
│ ├── strings.xml
│ └── values.xml
└── main
├── AndroidManifest.xml
└── java
└── com
└── onehilltech
└── metadata
├── ManifestMetadata.java
├── MetadataMethod.java
├── MetadataProperty.java
└── ResourceType.java
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Gradle template
2 | .gradle
3 | build/
4 |
5 | # Ignore Gradle GUI config
6 | gradle-app.setting
7 |
8 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
9 | !gradle-wrapper.jar
10 | ### JetBrains template
11 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
12 |
13 | *.iml
14 |
15 | ## Directory-based project format:
16 | .idea/
17 | # if you remove the above rule, at least ignore the following:
18 |
19 | # User-specific stuff:
20 | # .idea/workspace.xml
21 | # .idea/tasks.xml
22 | # .idea/dictionaries
23 |
24 | # Sensitive or high-churn files:
25 | # .idea/dataSources.ids
26 | # .idea/dataSources.xml
27 | # .idea/sqlDataSources.xml
28 | # .idea/dynamic.xml
29 | # .idea/uiDesigner.xml
30 |
31 | # Gradle:
32 | # .idea/gradle.xml
33 | # .idea/libraries
34 |
35 | # Mongo Explorer plugin:
36 | # .idea/mongoSettings.xml
37 |
38 | ## File-based project format:
39 | *.ipr
40 | *.iws
41 |
42 | ## Plugin-specific files:
43 |
44 | # IntelliJ
45 | /out/
46 |
47 | # mpeltonen/sbt-idea plugin
48 | .idea_modules/
49 |
50 | # JIRA plugin
51 | atlassian-ide-plugin.xml
52 |
53 | # Crashlytics plugin (for Android Studio and IntelliJ)
54 | com_crashlytics_export_strings.xml
55 | crashlytics.properties
56 | crashlytics-build.properties
57 | ### Android template
58 | # Built application files
59 | *.apk
60 | *.ap_
61 |
62 | # Files for the Dalvik VM
63 | *.dex
64 |
65 | # Java class files
66 | *.class
67 |
68 | # Generated files
69 | bin/
70 | gen/
71 |
72 | # Gradle files
73 | .gradle/
74 | build/
75 |
76 | # Local configuration file (sdk path, etc)
77 | local.properties
78 | bintray.properties
79 |
80 | # Proguard folder generated by Eclipse
81 | proguard/
82 |
83 | # Log Files
84 | *.log
85 |
86 | # Android Studio Navigation editor temp files
87 | .navigation/
88 | ### Java template
89 | *.class
90 |
91 | # Mobile Tools for Java (J2ME)
92 | .mtj.tmp/
93 |
94 | # Package Files #
95 | *.jar
96 | *.war
97 | *.ear
98 |
99 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
100 | hs_err_pid*
101 |
102 | # Eclipse Files
103 | .classpath
104 | .project
105 | .settings/
106 | RemoteSystemsTempFiles/
107 | .metadata/
108 |
109 | # Maven Files
110 | target/
111 |
112 | */gen/
113 | */bin/
114 |
115 | *.class
116 | ### OSX template
117 | .DS_Store
118 | .AppleDouble
119 | .LSOverride
120 |
121 | # Icon must end with two \r
122 | Icon
123 |
124 | # Thumbnails
125 | ._*
126 |
127 | # Files that might appear in the root of a volume
128 | .DocumentRevisions-V100
129 | .fseventsd
130 | .Spotlight-V100
131 | .TemporaryItems
132 | .Trashes
133 | .VolumeIcon.icns
134 |
135 | # Directories potentially created on remote AFP share
136 | .AppleDB
137 | .AppleDesktop
138 | Network Trash Folder
139 | Temporary Items
140 | .apdisk
141 |
142 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | sudo: false
3 |
4 | env:
5 | global:
6 | - ANDROID_BUILD_TOOLS_VERSION=23.0.3
7 | - ADB_INSTALL_TIMEOUT=10
8 |
9 | matrix:
10 | - ANDROID_TARGET=android-23 ANDROID_ABI=armeabi-v7a
11 |
12 | android:
13 | components:
14 | # Use the latest revision of Android SDK Tools
15 | - platform-tools
16 | - tools
17 |
18 | # The BuildTools version used by your project
19 | - build-tools-$ANDROID_BUILD_TOOLS_VERSION
20 |
21 | # The SDK version used to compile your project
22 | - $ANDROID_TARGET
23 |
24 | # Additional components
25 | - extra-google-m2repository
26 | - extra-android-m2repository
27 |
28 | # Specify the system image to run emulator during tests
29 | - sys-img-$ANDROID_ABI-$ANDROID_TARGET
30 |
31 | before_script:
32 | # Create and start emulator
33 | - chmod +x gradlew
34 | - pip install --user codecov
35 | - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI
36 | - emulator -avd test -no-skin -no-audio -no-window &
37 | - android-wait-for-emulator
38 | - adb shell input keyevent 82 &
39 |
40 | script:
41 | - ./gradlew build connectedCheck -PdisablePreDex
42 |
43 | after_success:
44 | - codecov
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 One Hill Technologies, LLC
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | android-metadata
2 | ==================
3 |
4 | [](https://android-arsenal.com/details/1/4045)
5 | [](https://jitpack.io/#onehilltech/android-metadata)
6 | [](https://travis-ci.org/onehilltech/android-metadata)
7 | [](http://codecov.io/github/onehilltech/android-metadata?branch=master)
8 |
9 | A utility library for Android designed to simplify reading meta-data
10 | values from AndroidManifest.xml.
11 |
12 | * **Quickly** access a meta-data values from anywhere with few lines of code.
13 | * Read individual meta-data values into **type-specific** variables.
14 | * **Instantiate** objects from meta-data values.
15 | * Read one or more meta-data values into **annotated** Java classes.
16 | * Use meta-data values to pass configuration parameters to **third-party libraries**.
17 |
18 | ## Installation
19 |
20 | #### Gradle
21 |
22 | ```
23 | buildscript {
24 | repositories {
25 | maven { url "https://jitpack.io" }
26 | }
27 | }
28 |
29 | dependencies {
30 | compile com.github.onehilltech:android-metadata:x.y.z
31 | }
32 | ```
33 |
34 | ## Getting Started
35 |
36 | Here is the quickest and easiest way to load the metadata from AndroidManifest.xml
37 | and get a value. The value, by default, is a String value type.
38 |
39 | ```java
40 | ManifestMetadata metadata = ManifestMetadata.get (context);
41 |
42 | //
43 | String value = metadata.getValue ("appid");
44 | ```
45 |
46 | If the value is not a String type, then you can provide a hint:
47 |
48 | ```java
49 | ManifestMetadata metadata = ManifestMetadata.get (context);
50 |
51 | //
52 | Integer connTimeout = metadata.getValue ("conn.timeout", Integer.class);
53 | ```
54 |
55 | You can even directly load a resource from the metadata:
56 |
57 | ```java
58 | ManifestMetadata metadata = ManifestMetadata.get (context);
59 |
60 | //
61 | String appName = metadata.getValue ("appname", true, String.class);
62 | ```
63 |
64 | In some cases, you may need to provide additional information about
65 | the resource type since different resources types can have the same
66 | Java type:
67 |
68 | ```java
69 | ManifestMetadata metadata = ManifestMetadata.get (context);
70 |
71 | //
72 | Integer bgColor = metadata.getValue ("bgcolor", true, Integer.class, ResourceType.Color);
73 | ```
74 |
75 | ## Using Annotations to Load Metadata
76 |
77 | Here is the simplest example of using an annotation to define what
78 | meta-data value in AndroidManifest.xml it should be initialized with:
79 |
80 | ```java
81 | public class MyData {
82 | private String appid_;
83 |
84 | @MetadataProperty (name="my.message")
85 | public String message;
86 |
87 | @MetadataMethod (name="appid")
88 | public void setAppId (String appid) {
89 | this.appid_ = appid;
90 | }
91 | }
92 | ```
93 |
94 | In the example above, the field **message** will be initialized with
95 | the value of meta-data tag named **my.message**. You initialize all
96 | values with the **@Metadata** annotation using a single line of code:
97 |
98 | ```java
99 | MyData myData = new MyData ();
100 | ManifestMetadata.get (context).initFromMetadata (myData);
101 | ```
102 |
103 | This method will auto-detect the target type, and then assign the value.
104 | If the field is not assignable using the meta-data's value, then an
105 | exception will be thrown.
106 |
107 | ### Reading from a Resource
108 |
109 | In some cases, you will want to read the value from a resource (i.e.,
110 | you use android:resource in the meta-data tag). You can use the **@Metadata**
111 | annotation to read resource values as well:
112 |
113 | ```java
114 | public class MyData {
115 | private String appid_;
116 |
117 | @MetadataProperty (name="my.message", fromResource=true)
118 | public String message;
119 |
120 | @MetadataMethod (name="appid", fromResource=true)
121 | public void setAppId (String appid) {
122 | this.appid_ = appid;
123 | }
124 | }
125 | ```
126 |
127 | ### Giving Resource Type Hints
128 |
129 | There are some resources that have the same field type, such as integer
130 | and color. This makes it hard to auto-detect the resources type. We can
131 | therefore provide a hint as follows:
132 |
133 | ```java
134 | public class MyData {
135 | @MetadataProperty (name="my.message", fromResource=true, resourceType=ResourceType.Color)
136 | public int backgroundColor;
137 | }
138 | ```
139 |
140 | In the example above, the value for **backgroundColor** will be loaded
141 | from resources and interpreted as a color.
142 |
143 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.2.1'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | jcenter()
15 | maven { url "https://maven.google.com" }
16 | }
17 | }
18 |
19 | apply plugin: 'com.android.library'
20 |
21 | group = "com.onehilltech.android"
22 | version = "1.6.0"
23 |
24 | android {
25 | compileSdkVersion 28
26 | buildToolsVersion "28.0.3"
27 |
28 | defaultConfig {
29 | minSdkVersion 14
30 | targetSdkVersion 26
31 | versionCode 9
32 | versionName "1.5.2"
33 |
34 | testApplicationId 'com.onehilltech.metadata.test'
35 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
36 | }
37 |
38 | buildTypes {
39 | debug {
40 | testCoverageEnabled true
41 | }
42 |
43 | release {
44 | minifyEnabled false
45 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
46 | }
47 | }
48 |
49 | compileOptions {
50 | sourceCompatibility JavaVersion.VERSION_1_7
51 | }
52 |
53 | lintOptions {
54 | abortOnError false
55 | }
56 | }
57 |
58 | dependencies {
59 | androidTestImplementation 'androidx.test.ext:junit:1.0.0'
60 | androidTestImplementation 'androidx.test:runner:1.1.0'
61 | }
62 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | name=android-metadata
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onehilltech/android-metadata/d53a1acac4e33337764f9997f6d8aa4139ca4369/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Mar 17 00:05:30 EDT 2016
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-4.6-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 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onehilltech/android-metadata/d53a1acac4e33337764f9997f6d8aa4139ca4369/settings.gradle
--------------------------------------------------------------------------------
/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
20 |
21 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
33 |
34 |
37 |
38 |
41 |
42 |
43 |
46 |
47 |
50 |
51 |
54 |
55 |
58 |
59 |
62 |
63 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/androidTest/java/com/onehilltech/metadata/ManifestMetadataTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013, James H. Hill
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 | package com.onehilltech.metadata;
18 |
19 | import android.content.ComponentName;
20 | import android.content.Context;
21 | import android.content.pm.PackageManager.NameNotFoundException;
22 | import android.content.res.Resources;
23 | import android.os.Bundle;
24 |
25 | import com.onehilltech.metadata.test.TestActivity;
26 |
27 | import junit.framework.Assert;
28 |
29 | import org.junit.Test;
30 | import org.junit.runner.RunWith;
31 |
32 | import androidx.test.ext.junit.runners.AndroidJUnit4;
33 | import androidx.test.platform.app.InstrumentationRegistry;
34 |
35 | @RunWith (AndroidJUnit4.class)
36 | public class ManifestMetadataTest
37 | {
38 | public static final String METADATA_STRING = "metadata.string";
39 | public static final String METADATA_INTEGER = "metadata.integer";
40 | public static final String METADATA_CLASSNAME = "metadata.classname";
41 |
42 | public static final String METADATA_RESOURCE_STRING = "metadata.resource.string";
43 | public static final String METADATA_RESOURCE_INTEGER = "metadata.resource.integer";
44 |
45 | public static final String METADATA_RESOURCE_BOOLEAN_TRUE = "metadata.resource.boolean.true";
46 | public static final String METADATA_RESOURCE_BOOLEAN_FALSE = "metadata.resource.boolean.false";
47 | public static final String METADATA_RESOURCE_DIMENSION = "metadata.resource.dimension";
48 | public static final String METADATA_RESOURCE_COLOR = "metadata.resource.color";
49 |
50 | @Test
51 | public void testGetMetadata ()
52 | {
53 | try
54 | {
55 | Bundle metadata = ManifestMetadata.get (InstrumentationRegistry.getInstrumentation ().getContext ()).getMetadata ();
56 |
57 | Assert.assertEquals (true, metadata.containsKey (METADATA_STRING));
58 | Assert.assertEquals (true, metadata.containsKey (METADATA_INTEGER));
59 | Assert.assertEquals (true, metadata.containsKey (METADATA_CLASSNAME));
60 |
61 | Assert.assertEquals (true, metadata.containsKey (METADATA_RESOURCE_STRING));
62 | Assert.assertEquals (true, metadata.containsKey (METADATA_RESOURCE_INTEGER));
63 |
64 | Assert.assertEquals (true, metadata.containsKey (METADATA_RESOURCE_BOOLEAN_TRUE));
65 | Assert.assertEquals (true, metadata.containsKey (METADATA_RESOURCE_BOOLEAN_FALSE));
66 |
67 | Assert.assertEquals (true, metadata.containsKey (METADATA_RESOURCE_DIMENSION));
68 |
69 | Assert.assertEquals (true, metadata.containsKey (METADATA_RESOURCE_COLOR));
70 | }
71 | catch (NameNotFoundException e)
72 | {
73 | Assert.fail (e.getMessage ());
74 | }
75 | }
76 |
77 | @Test
78 | public void testGetMetadataValue ()
79 | {
80 | try
81 | {
82 | ManifestMetadata metadata = ManifestMetadata.get (InstrumentationRegistry.getInstrumentation ().getContext ());
83 | String value = metadata.getValue (METADATA_STRING);
84 | Assert.assertEquals ("Hello, World!", value);
85 |
86 | int intValue = metadata.getValue (METADATA_INTEGER, Integer.class);
87 | Assert.assertEquals (42, intValue);
88 | }
89 | catch (Exception e)
90 | {
91 | Assert.fail (e.getMessage ());
92 | }
93 | }
94 |
95 | @Test
96 | public void testLoadFromManifest ()
97 | {
98 | try
99 | {
100 | // Test @Metadata
101 |
102 | MetadataValues values = new MetadataValues ();
103 | ManifestMetadata.get (InstrumentationRegistry.getInstrumentation ().getContext ()).initFromMetadata (values);
104 | Resources r = InstrumentationRegistry.getInstrumentation ().getContext ().getResources ();
105 |
106 | Assert.assertEquals ("Hello, World!", values.theString);
107 | Assert.assertEquals (42, values.theInteger);
108 | Assert.assertEquals (TestClass.class, values.theClass);
109 |
110 | Assert.assertEquals ("Hello, World!", values.theStringResource);
111 | Assert.assertEquals (com.onehilltech.metadata.test.R.string.hello_world, values.theIntegerResource);
112 |
113 | Assert.assertTrue (values.theTrueValue);
114 | Assert.assertFalse (values.theFalseValue);
115 |
116 | Assert.assertEquals (r.getDimension (com.onehilltech.metadata.test.R.dimen.sample_dimen), values.theDimension);
117 |
118 | // Test @MetadataMethod
119 | Assert.assertEquals ("Hello, World!", values.getMetadataString ());
120 | }
121 | catch (Exception e)
122 | {
123 | e.printStackTrace ();
124 | Assert.fail (e.getMessage ());
125 | }
126 | }
127 |
128 | @Test
129 | public void testLoadFromManifestWithResourceType ()
130 | {
131 | try
132 | {
133 | MetadataValues values = new MetadataValues ();
134 | ManifestMetadata.get (InstrumentationRegistry.getInstrumentation ().getContext ()).initFromMetadata (values);
135 | Resources r =InstrumentationRegistry.getInstrumentation ().getContext ().getResources ();
136 |
137 | // Testing the resourceType method.
138 | Assert.assertEquals (r.getColor (com.onehilltech.metadata.test.R.color.black), values.colorBlack);
139 | }
140 | catch (Exception e)
141 | {
142 | e.printStackTrace ();
143 | Assert.fail (e.getMessage ());
144 | }
145 | }
146 |
147 | @Test(expected=NameNotFoundException.class)
148 | public void testNameNotFoundException () throws Exception
149 | {
150 | ManifestMetadata metadata = ManifestMetadata.get (InstrumentationRegistry.getInstrumentation ().getContext ());
151 | metadata.getValue ("foo", String.class);
152 | }
153 |
154 | @Test
155 | public void testActivityMetadata () throws Exception
156 | {
157 | Context context = InstrumentationRegistry.getInstrumentation ().getContext ();
158 | ComponentName componentName = new ComponentName (context, TestActivity.class);
159 | ManifestMetadata metadata = ManifestMetadata.get (context, componentName);
160 |
161 | Assert.assertEquals (1, metadata.getMetadata ().size ());
162 | Assert.assertEquals ("Hello, World", metadata.getValue ("metadata.activity.string"));
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/src/androidTest/java/com/onehilltech/metadata/MetadataValues.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013, James H. Hill
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 | package com.onehilltech.metadata;
18 |
19 | import android.content.res.XmlResourceParser;
20 |
21 | public class MetadataValues
22 | {
23 | //// Attribute Testers
24 |
25 | // android:value
26 | @MetadataProperty (name="metadata.string")
27 | public String theString;
28 |
29 | @MetadataProperty(name="metadata.integer")
30 | public int theInteger;
31 |
32 | @MetadataProperty(name="metadata.classname")
33 | public Class theClass;
34 |
35 | // android:resource
36 | @MetadataProperty(name="metadata.resource.string", fromResource=true)
37 | public String theStringResource;
38 |
39 | @MetadataProperty(name="metadata.resource.integer", fromResource=true)
40 | public int theIntegerResource;
41 |
42 | @MetadataProperty(name="metadata.resource.animation", fromResource=true)
43 | public XmlResourceParser theAnimation;
44 |
45 | @MetadataProperty(name="metadata.resource.boolean.true", fromResource=true)
46 | public boolean theTrueValue;
47 |
48 | @MetadataProperty(name="metadata.resource.boolean.false", fromResource=true)
49 | public Boolean theFalseValue;
50 |
51 | @MetadataProperty(name="metadata.resource.dimension", fromResource=true)
52 | public float theDimension;
53 |
54 | @MetadataProperty(name="metadata.resource.color", fromResource=true, resourceType= ResourceType.Color)
55 | public int colorBlack;
56 |
57 | //// Method Testers
58 |
59 | private String metadataString_;
60 |
61 | @MetadataMethod (name="metadata.string")
62 | public void setMetadataString (String str)
63 | {
64 | this.metadataString_ = str;
65 | }
66 |
67 | public String getMetadataString ()
68 | {
69 | return this.metadataString_;
70 | }
71 | }
--------------------------------------------------------------------------------
/src/androidTest/java/com/onehilltech/metadata/TestClass.java:
--------------------------------------------------------------------------------
1 | /**
2 | /**
3 | * Copyright (C) 2013, James H. Hill
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package com.onehilltech.metadata;
19 |
20 | public class TestClass
21 | {
22 |
23 | }
--------------------------------------------------------------------------------
/src/androidTest/java/com/onehilltech/metadata/test/TestActivity.java:
--------------------------------------------------------------------------------
1 | package com.onehilltech.metadata.test;
2 |
3 | import android.app.Activity;
4 |
5 | public class TestActivity extends Activity
6 | {
7 | }
8 |
--------------------------------------------------------------------------------
/src/androidTest/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello, World!
4 |
5 |
--------------------------------------------------------------------------------
/src/androidTest/res/values/values.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | false
5 |
6 | 5sp
7 |
8 | #000000
9 |
--------------------------------------------------------------------------------
/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
20 |
21 |
--------------------------------------------------------------------------------
/src/main/java/com/onehilltech/metadata/ManifestMetadata.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013, James H. Hill
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 | package com.onehilltech.metadata;
18 |
19 | import android.app.Activity;
20 | import android.content.ComponentName;
21 | import android.content.Context;
22 | import android.content.pm.ActivityInfo;
23 | import android.content.pm.ApplicationInfo;
24 | import android.content.pm.PackageManager;
25 | import android.content.pm.PackageManager.NameNotFoundException;
26 | import android.content.res.Resources;
27 | import android.content.res.XmlResourceParser;
28 | import android.os.Bundle;
29 | import android.util.Log;
30 |
31 | import java.lang.ref.WeakReference;
32 | import java.lang.reflect.Field;
33 | import java.lang.reflect.InvocationTargetException;
34 | import java.lang.reflect.Method;
35 | import java.util.HashMap;
36 |
37 | /**
38 | * Utility class for loading meta-data from AndroidManifest.xml. This
39 | * class defines methods that convert meta-data values into type-specific
40 | * values. It also provides methods for initializing annotated classes
41 | * with values defined in the meta-data.
42 | *
43 | * The class is a Singleton, and must be access using the get () method.
44 | * We use the Singleton pattern since there is only one manifest for a
45 | * mobile application, and we can better control access to it (and its
46 | * memory usage) via the singleton object.
47 | */
48 | public class ManifestMetadata
49 | {
50 | /// The metadata bundle
51 | private final Bundle metadata_;
52 |
53 | /// The application context for the program.
54 | private final Context context_;
55 |
56 | /// Singleton reference.
57 | private static WeakReference app_;
58 |
59 | private static final HashMap > activities_ = new HashMap<> ();
60 |
61 | private static final String TAG = "ManifestMetadata";
62 |
63 | /**
64 | * Get the singleton instance of the manifest. W
65 | * @param context Execution context
66 | * @return
67 | * @throws NameNotFoundException
68 | */
69 | public static ManifestMetadata get (Context context)
70 | throws NameNotFoundException
71 | {
72 | if (app_ != null && app_.get () != null)
73 | return app_.get ();
74 |
75 | // Load the metadata for the application.
76 | PackageManager pm = context.getPackageManager ();
77 | ApplicationInfo ai = pm.getApplicationInfo (context.getPackageName (), PackageManager.GET_META_DATA);
78 | ManifestMetadata mm = new ManifestMetadata (context, ai.metaData);
79 |
80 | app_ = new WeakReference <> (mm);
81 |
82 | return app_.get ();
83 | }
84 |
85 | /**
86 | * Get the metadata for the activity.
87 | *
88 | * @param activity
89 | * @return
90 | */
91 | @SuppressWarnings ("unused")
92 | public static ManifestMetadata get (Activity activity)
93 | throws PackageManager.NameNotFoundException
94 | {
95 | return get (activity, activity.getComponentName ());
96 | }
97 |
98 | /**
99 | * Get the metadata for a component.
100 | *
101 | * @param componentName
102 | * @return
103 | */
104 | public static ManifestMetadata get (Context context, ComponentName componentName)
105 | throws PackageManager.NameNotFoundException
106 | {
107 | // Check if we already have a reference to the metadata for this activity. If
108 | // so, then just return our reference to the client. We can do this since the
109 | // metadata will not change over the lifetime of the application.
110 | WeakReference metadata = activities_.get (componentName);
111 |
112 | if (metadata != null && metadata.get () != null)
113 | return metadata.get ();
114 |
115 | // Load the metadata for the application.
116 | PackageManager pm = context.getPackageManager ();
117 | ActivityInfo ai = pm.getActivityInfo (componentName, PackageManager.GET_META_DATA);
118 | ManifestMetadata mm = new ManifestMetadata (context, ai.metaData);
119 |
120 | // Cache the metadata for future reference.
121 | metadata = new WeakReference<> (mm);
122 | activities_.put (componentName, metadata);
123 |
124 | return mm;
125 | }
126 |
127 | /**
128 | * Default constructor.
129 | *
130 | * @param context
131 | * @throws NameNotFoundException
132 | */
133 | private ManifestMetadata (Context context, Bundle bundle)
134 | {
135 | this.context_ = context;
136 | this.metadata_ = bundle;
137 | }
138 |
139 | /**
140 | * Get the metadata bundle.
141 | *
142 | * @return
143 | */
144 | public Bundle getMetadata ()
145 | {
146 | return this.metadata_;
147 | }
148 |
149 | public boolean exists ()
150 | {
151 | return this.metadata_ != null;
152 | }
153 |
154 | /**
155 | * Get the value of a meta-data element in AndroidManifest.xml. The
156 | * value is returned as a String value type.
157 | *
158 | * @param name Name of the meta-data element
159 | * @return Value of the meta-data element
160 | */
161 | public String getValue (String name)
162 | {
163 | return this.metadata_.getString (name);
164 | }
165 |
166 | /**
167 | * Get the value of a metadata element in AndroidManifest.xml. If the
168 | * element exist, then a generic Object is return. If the value does not
169 | * exist, then an exception is thrown.
170 | */
171 | public T getValue (String name, Class typeHint)
172 | throws NameNotFoundException, IllegalArgumentException,
173 | ClassNotFoundException, IllegalAccessException, InvocationTargetException
174 | {
175 | return this.getValue (name, false, ResourceType.Auto, typeHint);
176 | }
177 |
178 | public T getValue (String name, boolean fromResource, Class typeHint)
179 | throws NameNotFoundException, IllegalArgumentException,
180 | ClassNotFoundException, IllegalAccessException, InvocationTargetException
181 | {
182 | return getValue (name, fromResource, ResourceType.Auto, typeHint);
183 | }
184 |
185 | @SuppressWarnings ("unchecked")
186 | public T getValue (String name,
187 | boolean fromResource,
188 | ResourceType resourceType,
189 | Class typeHint)
190 | throws NameNotFoundException, IllegalArgumentException,
191 | ClassNotFoundException, IllegalAccessException, InvocationTargetException
192 | {
193 | if (!this.metadata_.containsKey (name))
194 | throw new NameNotFoundException (name + " not defined in AndroidManifest.xml");
195 |
196 | return (T)this.getValueFromMetadata (name,
197 | fromResource,
198 | resourceType,
199 | typeHint);
200 | }
201 |
202 | /**
203 | * Load metadata from the manifest and initialize annotated values/methods
204 | * in the target object.
205 | *
206 | * @param target Instance of object with annotated class
207 | * @throws NameNotFoundException
208 | * @throws IllegalAccessException
209 | * @throws IllegalArgumentException
210 | * @throws ClassNotFoundException
211 | * @throws InvocationTargetException
212 | */
213 | public void initFromMetadata (T target)
214 | throws NameNotFoundException, IllegalArgumentException,
215 | IllegalAccessException, ClassNotFoundException, InvocationTargetException
216 | {
217 | if (this.metadata_ == null)
218 | return;
219 |
220 | // Get the class, and locate fields with @Metadata.
221 | Field [] fields = target.getClass ().getFields ();
222 |
223 | if (fields.length != 0)
224 | {
225 | // Iterate over each field in the class definition. If we find a
226 | // field with the @Metadata annotation, then we need to load its
227 | // value from AndroidManifest.xml.
228 | for (Field field : fields)
229 | {
230 | if (!field.isAnnotationPresent (MetadataProperty.class))
231 | continue;
232 |
233 | // Get the annotation value, and the target meta-data name.
234 | MetadataProperty annotation = field.getAnnotation (MetadataProperty.class);
235 | String targetName = annotation.name ();
236 |
237 | // If the meta-data name is an empty string, use the field name.
238 | if (targetName.equals (""))
239 | targetName = field.getName ();
240 |
241 | // Make sure that metadata does contain the target name before,
242 | // or there is no need to continue at this point.
243 | if (!this.metadata_.containsKey (targetName))
244 | continue;
245 |
246 | // Load the value from the bundle.
247 | Object theValue =
248 | this.getValueFromMetadata (targetName,
249 | annotation.fromResource (),
250 | annotation.resourceType (),
251 | field.getType ());
252 |
253 | // Finally, we can set the value!
254 | field.set (target, theValue);
255 | }
256 | }
257 |
258 | // Locate all methods with @MetadataMethod
259 | Method [] methods = target.getClass ().getMethods ();
260 |
261 | if (methods.length != 0)
262 | {
263 | // Iterate over each field in the class definition. If we find a
264 | // field with the @Metadata annotation, then we need to load its
265 | // value from AndroidManifest.xml.
266 | for (Method method : methods)
267 | {
268 | if (!method.isAnnotationPresent (MetadataMethod.class))
269 | continue;
270 |
271 | // Get the annotation value, and the target meta-data name. For methods,
272 | // the target name is required.
273 | MetadataMethod annotation = method.getAnnotation (MetadataMethod.class);
274 | String targetName = annotation.name ();
275 |
276 | // Make sure that meta-data does contain the target name before,
277 | // or there is no need to continue at this point.
278 | if (!this.metadata_.containsKey (targetName))
279 | continue;
280 |
281 | // Load the value from the bundle.
282 | Object theValue =
283 | this.getValueFromMetadata (targetName,
284 | annotation.fromResource (),
285 | annotation.resourceType (),
286 | method.getParameterTypes ()[0]);
287 |
288 | // Finally, we can set the value!
289 | method.invoke (target, theValue);
290 | }
291 | }
292 | }
293 |
294 | /**
295 | * Load a value from meta-data. The returned value is an Object of the
296 | * correct type. It is the responsibility of the caller to convert the
297 | * returned object to the correct type.
298 | *
299 | * For classes, the return object is an instance of the class. The class
300 | * therefore must have a default constructor defined. If one is not defined,
301 | * then an exception will be thrown.
302 | *
303 | * @param targetName Name of value in meta-data bundle
304 | * @param typeInfo Type information about the target property
305 | * @return
306 | * @throws ClassNotFoundException
307 | * @throws IllegalArgumentException
308 | * @throws IllegalAccessException
309 | * @throws InvocationTargetException
310 | */
311 | private Object getValueFromMetadata (String targetName,
312 | boolean fromResource,
313 | ResourceType rcType,
314 | Class > typeInfo)
315 | throws ClassNotFoundException, IllegalArgumentException,
316 | IllegalAccessException, InvocationTargetException
317 | {
318 | // Load the value from the bundle.
319 | Object theValue = this.metadata_.get (targetName);
320 |
321 | // The current value that we are reading from the bundle is actually
322 | // a resource id. We therefore need to convert the value to an Integer
323 | // so we can load it from the the resources.
324 | if (fromResource)
325 | {
326 | Integer rcid = (Integer)theValue;
327 |
328 | // Either, we are going to auto-detect the resource type based on the
329 | // type of the field, or we are given a hint in the annotation.
330 | if (rcType.equals (ResourceType.Auto))
331 | theValue = this.getValueFromResource (rcid, typeInfo);
332 | else
333 | theValue = this.getValueFromResource (rcid, rcType);
334 | }
335 |
336 | if (typeInfo.equals (Class.class))
337 | {
338 | // The value is a Class object. Let's load the class object.
339 | ClassLoader classLoader = this.context_.getClassLoader ();
340 | theValue = classLoader.loadClass ((String)theValue);
341 | }
342 |
343 | return theValue;
344 | }
345 |
346 | /**
347 | * Get the value from a resource. The value type is determined by
348 | * the field object type.
349 | *
350 | * @param rcid
351 | * @return
352 | */
353 | private Object getValueFromResource (int rcid, Class > typeInfo)
354 | {
355 | Resources r = this.context_.getResources ();
356 |
357 | if (typeInfo.isAssignableFrom (String.class))
358 | return r.getString (rcid);
359 | else if (typeInfo.isAssignableFrom (int.class) || typeInfo.isAssignableFrom (Integer.class))
360 | return rcid;
361 | else if (typeInfo.isAssignableFrom (boolean.class) || typeInfo.isAssignableFrom (Boolean.class))
362 | return r.getBoolean (rcid);
363 | else if (typeInfo.isAssignableFrom (float.class) || typeInfo.isAssignableFrom (Float.class))
364 | return r.getDimension (rcid);
365 | else if (typeInfo.isAssignableFrom (int[].class))
366 | return r.getIntArray (rcid);
367 | else if (typeInfo.isAssignableFrom (XmlResourceParser.class))
368 | return r.getAnimation (rcid);
369 | else
370 | return null;
371 | }
372 |
373 | /**
374 | * Get the value from a resource. The resource type is determined by
375 | * the rcType parameter.
376 | *
377 | * @param rcid
378 | * @param rcType
379 | * @return
380 | * @throws IllegalArgumentException
381 | * @throws IllegalAccessException
382 | * @throws InvocationTargetException
383 | */
384 | private Object getValueFromResource (int rcid, ResourceType rcType)
385 | throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
386 | {
387 | Method method = resourceTable_.get (rcType);
388 | return method.invoke (this.context_.getResources (), rcid);
389 | }
390 |
391 | private static final HashMap resourceTable_ = new HashMap ();
392 |
393 | static
394 | {
395 | installResourceMethodAccessor (ResourceType.Animation, "getAnimation");
396 | installResourceMethodAccessor (ResourceType.Boolean, "getBoolean");
397 | installResourceMethodAccessor (ResourceType.Color, "getColor");
398 | installResourceMethodAccessor (ResourceType.Dimension, "getDimension");
399 | installResourceMethodAccessor (ResourceType.DimensionPixelOffset, "getDimensionPixelOffset");
400 | installResourceMethodAccessor (ResourceType.DimensionPixelSize, "getDimensionPixelSize");
401 | installResourceMethodAccessor (ResourceType.Drawable, "getDrawable");
402 | installResourceMethodAccessor (ResourceType.Id, "getInteger");
403 | installResourceMethodAccessor (ResourceType.Integer, "getInteger");
404 | installResourceMethodAccessor (ResourceType.IntArray, "getIntArray");
405 | installResourceMethodAccessor (ResourceType.String, "getString");
406 | }
407 |
408 | /**
409 | * Install the resource access method for the specified resource type.
410 | *
411 | * @param rcType
412 | * @param methodName
413 | */
414 | private static void installResourceMethodAccessor (ResourceType rcType, String methodName)
415 | {
416 | Class clazz = Resources.class;
417 |
418 | try
419 | {
420 | resourceTable_.put (rcType, clazz.getMethod (methodName, int.class));
421 | }
422 | catch (SecurityException e)
423 | {
424 | Log.w (TAG, e.getMessage (), e);
425 | }
426 | catch (NoSuchMethodException e)
427 | {
428 | Log.w (TAG, e.getMessage (), e);
429 | }
430 | }
431 | }
--------------------------------------------------------------------------------
/src/main/java/com/onehilltech/metadata/MetadataMethod.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013, James H. Hill
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 | package com.onehilltech.metadata;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | /**
26 | * Metadata annotation for setter methods of a class. The setter method
27 | * can only have 1 parameter---the value read from metadata.
28 | */
29 | @Documented
30 | @Retention(RetentionPolicy.RUNTIME)
31 | @Target(ElementType.METHOD)
32 | public @interface MetadataMethod
33 | {
34 | /// Name of the metadata.
35 | String name ();
36 |
37 | /// The metadata value comes from a resource.
38 | boolean fromResource () default false;
39 |
40 | /// Get the hint for the resource type.
41 | ResourceType resourceType () default ResourceType.Auto;
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/onehilltech/metadata/MetadataProperty.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013, James H. Hill
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 | package com.onehilltech.metadata;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | /**
26 | * Metadata annotation for class attributes.
27 | */
28 | @Documented
29 | @Retention(RetentionPolicy.RUNTIME)
30 | @Target(ElementType.FIELD)
31 | public @interface MetadataProperty
32 | {
33 | /// Name of the metadata.
34 | String name () default "";
35 |
36 | /// The metadata value comes from a resource.
37 | boolean fromResource () default false;
38 |
39 | /// Get the hint for the resource type.
40 | ResourceType resourceType () default ResourceType.Auto;
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/onehilltech/metadata/ResourceType.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013, James H. Hill
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 | package com.onehilltech.metadata;
18 |
19 | /**
20 | * Enumeration of the different Android resource types. These values
21 | * are for providing a hint to the @Metadata annotation.
22 | */
23 | public enum ResourceType
24 | {
25 | Auto,
26 | Animation,
27 | Boolean,
28 | Color,
29 | Dimension,
30 | DimensionPixelOffset,
31 | DimensionPixelSize,
32 | Drawable,
33 | Id,
34 | Integer,
35 | IntArray,
36 | String
37 | }
38 |
--------------------------------------------------------------------------------