Skip to content

Commit

Permalink
Initial Commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobhyphenated committed Jul 22, 2013
0 parents commit 2924433
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 0 deletions.
45 changes: 45 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so

# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.rar
*.tar
*.zip

# Logs and databases #
######################
*.log
*.sql
*.sqlite

# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db

# IDE files #
#############
*xcuserdata*
/gen/**
/out/**
.classpath
.project
16 changes: 16 additions & 0 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cardinalsolutions.android.arch.autowire"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="17" />

<application
android:allowBackup="true" >

</application>

</manifest>
16 changes: 16 additions & 0 deletions bin/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cardinalsolutions.android.arch.autowire"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="17" />

<application
android:allowBackup="true" >

</application>

</manifest>
Binary file added bin/androidautowire.jar
Binary file not shown.
Binary file added ic_launcher-web.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions proguard-project.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
15 changes: 15 additions & 0 deletions project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

# Project target.
target=android-17
android.library=true
141 changes: 141 additions & 0 deletions src/com/cardinalsolutions/android/arch/autowire/AndroidAutowire.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package com.cardinalsolutions.android.arch.autowire;

import java.lang.reflect.Field;

import android.app.Activity;
import android.view.View;

/**
* Annotation handler class that will wire in the android views at runtime.
* <br /><br />
* This class will look for the {@code @AndroidView} annotation in the activity class.
* <br /><br />
* <strong>Example Usage:</strong>
* <br /><br />
* Base Class for Activity
* <pre class="prettyprint">
* public class BaseActivity extends Activity {
* ...
* {@code @Override}
* public void setContentView(int layoutResID){
* super.setContentView(layoutResID);
* AndroidAutowire.autowire(this, BaseActivity.class);
* }
* }
* </pre>
* Activity Class
* <pre class="prettyprint">
* public class MainActivity extends BaseActivity{
* {@code @AndroidView}
* private Button main_button;
*
* {@code @AndroidView(id="edit_text_field")}
* private EditText editText;
*
* {@code @AndroidView(resId=R.id.img_logo, required=false)}
* private ImageView logo;
*
* {@code @Override}
* protected void onCreate(Bundle savedInstanceState) {
* super.onCreate(savedInstanceState);
* setContentView(R.layout.activity_main)
* }
* }
* </pre>
* The layout xml :
* <pre class="prettyprint">
*
* &lt;EditText
* android:id="@+id/edit_text_field"
* android:layout_width="fill_parent"
* android:layout_height="wrap_content"
* android:inputType="textUri"
* /&gt;
*
* &lt;Button
* android:id="@+id/main_button"
* android:layout_width="fill_parent"
* android:layout_height="wrap_content"
* android:text="@string/test"
* /&gt;
*
* &lt;ImageView
* android:id="@+id/img_logo"
* android:layout_width="fill_parent"
* android:layout_height="wrap_content"
* android:text="@string/hello"
* /&gt;
* </pre>
* @author Jacob Kanipe-Illig ([email protected])
* Copyright (c) 2013
*/
public class AndroidAutowire {

/**
* Perform the wiring of the Android View using the {@link AndroidView} annotation.
* <br /><br />
* <strong>Usage:</strong><br /><br />
* Annotation all view fields in the activity to be autowired. Use {@code @AndroidView}.<br />
* If you do not specify the {@code id} or the {@code resId} parameters in the annotation, the name of the variable will be used as the id.
* <br />
* You may specify whether or not the field is required (true by default).
* <br /><br />
* After the call to {@code setContentView(layoutResID)} in the onCreate() method, you will call this
* {@code autowire(Activity thisClass, Class<?> baseClass)} method.
* <br />
* The first parameter is the Activity class being loaded. <br />
* The second parameter is the class of the base activity (if applicable).
*
* @param thisClass The activity being created.
* @param baseClass The Base activity. If there is inheritance in the activities, this is the highest level, the base activity,
* but not {@link Activity}. <br /><br />All views annotated with {@code @AndroidView} will be autowired in all Activity classes in the
* inheritance structure, from thisClass to baseClass inclusive. baseClass should not be {@link Activity} because no fields
* in {@link Activity} will need to be autowired. <br /><br /> If there is no parent class for your activity, use thisClass.class as baseClass.
* @throws AndroidAutowireException Indicates that there was an issue autowiring a view to an annotated field. Will not be thrown if required=false
* on the {@link AndroidView} annotation.
*/
public static void autowire(Activity thisClass, Class<?> baseClass) throws AndroidAutowireException{
Class<?> clazz = thisClass.getClass();
autowireViewsForClass(thisClass, clazz);
//Do this for all classes in the inheritance chain, until we get to this class
while(baseClass.isAssignableFrom(clazz.getSuperclass())){
clazz = clazz.getSuperclass();
autowireViewsForClass(thisClass, clazz);
}
}

private static void autowireViewsForClass(Activity thisActivity, Class<?> clazz){
for (Field field : clazz.getDeclaredFields()){
if(!field.isAnnotationPresent(AndroidView.class)){
continue;
}
if(!View.class.isAssignableFrom(field.getType())){
continue;
}
AndroidView androidView = field.getAnnotation(AndroidView.class);
int resId = androidView.resId();
if(resId == 0){
String viewId = androidView.id();
if(androidView.id().equals("")){
viewId = field.getName();
}
resId = thisActivity.getResources().getIdentifier(viewId, "id", thisActivity.getPackageName());
}
try {
View view = thisActivity.findViewById(resId);
if(view == null){
if(!androidView.required()){
continue;
}else{
throw new AndroidAutowireException("No view resource with the id of " + resId + " found. "
+" The required field " + field.getName() + " could not be autowired" );
}
}
field.setAccessible(true);
field.set(thisActivity,view);
} catch (Exception e){
throw new AndroidAutowireException("Cound not Autowire AndroidView: " + field.getName() + ". " + e.getMessage());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.cardinalsolutions.android.arch.autowire;

/**
* Exception dealing with an error while autowiring an android view
*
* @author Jacob Kanipe-Illig ([email protected])
* Copyright (c) 2013
*/
public class AndroidAutowireException extends RuntimeException {

private static final long serialVersionUID = 7445208526652970323L;

public AndroidAutowireException(String message){
super(message);
}
}
47 changes: 47 additions & 0 deletions src/com/cardinalsolutions/android/arch/autowire/AndroidView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.cardinalsolutions.android.arch.autowire;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Annotation to denote a field variable in an activity class that can be found by id at runtime.
* @author Jacob Kanipe-Illig ([email protected])
* Copyright (c) 2013
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface AndroidView {
/**
* You may optionally specify the id of the android view.
* If id is not set, assume the name of the field is the id.
* If the {@code resId} is set, this field will be ignored
* @return id
*/
String id() default "";

/**
* This View must be autowired. If required is true, then if the field cannot
* be autowired, and exception is thrown. No exception is thrown and the
* autowire will fail silently if required is false.
* <br /><br />
* defaults to {@code true}
* @return
*/
boolean required() default true;

/**
* Resource ID for the view. Example: {@code R.id.viewname}
* <br /><br />
* You may optionally specify this id of the android view. If the resId is set,
* this will be used to autowire the field. If it is not set, the {@code id} variable will
* be used. If the {@code id} is not set, then the name of the field is the id.
* <br /><br />
* Using resId is recommended as it is the most efficient way to autowire the view.
* @return
*/
int resId() default 0;
}

0 comments on commit 2924433

Please sign in to comment.