1a2043a8fff01f3e2d9a5e30dd1cf5fb6a5342f4dTyler Schultzpackage com.xtremelabs.robolectric.res;
247bd528af49de6d8459c8aeda60b88cc7a3c961fChristian Williams
3bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport static com.xtremelabs.robolectric.Robolectric.shadowOf;
4bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen
5bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport com.xtremelabs.robolectric.Robolectric;
6bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport com.xtremelabs.robolectric.shadows.ShadowContextWrapper;
7bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport com.xtremelabs.robolectric.util.I18nException;
8bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport com.xtremelabs.robolectric.util.PropertiesHelper;
9bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen
10828b5524de2393f92fdd52204c16a75e608db62fPhil Goodwinimport android.R;
115ec776796c773be831b2fd1cfd940da663f6c4c3Phil Goodwin & Tyler Schultzimport android.content.Context;
12fac8bbf7dfc7904540716be8649b2f5a5c9f6d15adriancowhamimport android.graphics.drawable.AnimationDrawable;
13fac8bbf7dfc7904540716be8649b2f5a5c9f6d15adriancowhamimport android.graphics.drawable.ColorDrawable;
14fac8bbf7dfc7904540716be8649b2f5a5c9f6d15adriancowhamimport android.graphics.drawable.Drawable;
155ec242e7f4ba642abb5cc3dceee0dc49ce2f1a3fRich Humphreyimport android.preference.PreferenceScreen;
16dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yaoimport android.text.TextUtils;
17b539366073ccb47433de7191dbbf519ed4ab2d8fPhil Goodwinimport android.view.Menu;
1825cbf6f16c0fc8e6524935e6fa3d70ec2a92ed25Phil Goodwin & Tyler Schultzimport android.view.View;
1925cbf6f16c0fc8e6524935e6fa3d70ec2a92ed25Phil Goodwin & Tyler Schultzimport android.view.ViewGroup;
2070650f03fb9161ce77255654517d34b67232588eChristian Williams & Phil Goodwin
21bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.io.BufferedReader;
22bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.io.File;
23bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.io.FileFilter;
24bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.io.FileInputStream;
25bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.io.IOException;
26bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.io.InputStream;
27bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.io.InputStreamReader;
288900025d7fa03579c0ae4d19255d3a8650cbf12aPhil Goodwin & Ryan Richardimport java.lang.reflect.Field;
29bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.util.HashSet;
30bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.util.Properties;
31bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogenimport java.util.Set;
328900025d7fa03579c0ae4d19255d3a8650cbf12aPhil Goodwin & Ryan Richard
3347bd528af49de6d8459c8aeda60b88cc7a3c961fChristian Williamspublic class ResourceLoader {
3448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private static final FileFilter MENU_DIR_FILE_FILTER = new FileFilter() {
3548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		@Override
3648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		public boolean accept( File file ) {
3748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			return isMenuDirectory( file.getPath() );
3848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
3948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	};
4048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private static final FileFilter LAYOUT_DIR_FILE_FILTER = new FileFilter() {
4148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		@Override
4248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		public boolean accept( File file ) {
4348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			return isLayoutDirectory( file.getPath() );
4448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
4548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	};
4648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private static final FileFilter DRAWABLE_DIR_FILE_FILTER = new FileFilter() {
4748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		@Override
4848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		public boolean accept( File file ) {
4948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			return isDrawableDirectory( file.getPath() );
5048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
5148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	};
5248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
5348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private File resourceDir;
5448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private File assetsDir;
5548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private int sdkVersion;
5648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private Class rClass;
5748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
5848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final ResourceExtractor resourceExtractor;
5948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private ViewLoader viewLoader;
6048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private MenuLoader menuLoader;
6148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private PreferenceLoader preferenceLoader;
6248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final StringResourceLoader stringResourceLoader;
6348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final PluralResourceLoader pluralResourceLoader;
6448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final StringArrayResourceLoader stringArrayResourceLoader;
6548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final AttrResourceLoader attrResourceLoader;
6648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final ColorResourceLoader colorResourceLoader;
6748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final DrawableResourceLoader drawableResourceLoader;
6848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final RawResourceLoader rawResourceLoader;
6948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final DimenResourceLoader dimenResourceLoader;
7048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private final IntegerResourceLoader integerResourceLoader;
7148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private boolean isInitialized = false;
7248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private boolean strictI18n = false;
73dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao	private String locale="";
747fb9367f21d1d50fa798098f24e0c3e9f7497324Jon Boekenoogen
75ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	private final Set<Integer> ninePatchDrawableIds = new HashSet<Integer>();
7648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
77dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao	public ResourceLoader(  int sdkVersion, Class rClass, File resourceDir, File assetsDir ) throws Exception {
78dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao		this( sdkVersion, rClass, resourceDir, assetsDir, "");
79dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao	}
807fb9367f21d1d50fa798098f24e0c3e9f7497324Jon Boekenoogen
81dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao	public ResourceLoader( int sdkVersion, Class rClass, File resourceDir, File assetsDir, String locale ) throws Exception {
8248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		this.sdkVersion = sdkVersion;
8348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		this.assetsDir = assetsDir;
8448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		this.rClass = rClass;
85dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao		this.locale = locale;
867fb9367f21d1d50fa798098f24e0c3e9f7497324Jon Boekenoogen
8748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		resourceExtractor = new ResourceExtractor();
88df5951775e9c13526de56166ccdb841aa910a674Jon Boekenoogen		if ( rClass != null ) {
89df5951775e9c13526de56166ccdb841aa910a674Jon Boekenoogen		  resourceExtractor.addLocalRClass( rClass );
90df5951775e9c13526de56166ccdb841aa910a674Jon Boekenoogen		}
9148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		resourceExtractor.addSystemRClass( R.class );
9248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
9348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		stringResourceLoader = new StringResourceLoader( resourceExtractor );
9448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		pluralResourceLoader = new PluralResourceLoader( resourceExtractor, stringResourceLoader );
9548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		stringArrayResourceLoader = new StringArrayResourceLoader( resourceExtractor, stringResourceLoader );
9648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		colorResourceLoader = new ColorResourceLoader( resourceExtractor );
9748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		attrResourceLoader = new AttrResourceLoader( resourceExtractor );
9848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		drawableResourceLoader = new DrawableResourceLoader( resourceExtractor, resourceDir );
9948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		rawResourceLoader = new RawResourceLoader( resourceExtractor, resourceDir );
10048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		dimenResourceLoader = new DimenResourceLoader( resourceExtractor );
10148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		integerResourceLoader = new IntegerResourceLoader( resourceExtractor );
10248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
10348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		this.resourceDir = resourceDir;
10448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
10548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
10648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public void setStrictI18n( boolean strict ) {
10748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		this.strictI18n = strict;
10848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( viewLoader != null ) {
10948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			viewLoader.setStrictI18n( strict );
11048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
11148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( menuLoader != null ) {
11248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			menuLoader.setStrictI18n( strict );
11348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
11448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( preferenceLoader != null ) {
11548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			preferenceLoader.setStrictI18n( strict );
11648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
11748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
11848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
11948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public boolean getStrictI18n() {
12048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return strictI18n;
12148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
12248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
12348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void init() {
12448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( isInitialized ) {
12548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			return;
12648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
1277fb9367f21d1d50fa798098f24e0c3e9f7497324Jon Boekenoogen
12848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		try {
12948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			if ( resourceDir != null ) {
13048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				viewLoader = new ViewLoader( resourceExtractor, attrResourceLoader );
13148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				menuLoader = new MenuLoader( resourceExtractor, attrResourceLoader );
13248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				preferenceLoader = new PreferenceLoader( resourceExtractor );
13348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
13448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				viewLoader.setStrictI18n( strictI18n );
13548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				menuLoader.setStrictI18n( strictI18n );
13648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				preferenceLoader.setStrictI18n( strictI18n );
13748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
13848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				File systemResourceDir = getSystemResourceDir( getPathToAndroidResources() );
13948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				File localValueResourceDir = getValueResourceDir( resourceDir );
14048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				File systemValueResourceDir = getValueResourceDir( systemResourceDir );
14148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				File preferenceDir = getPreferenceResourceDir( resourceDir );
14248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
14348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				loadStringResources( localValueResourceDir, systemValueResourceDir );
14448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				loadPluralsResources( localValueResourceDir, systemValueResourceDir );
14548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				loadValueResources( localValueResourceDir, systemValueResourceDir );
14648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				loadDimenResources( localValueResourceDir, systemValueResourceDir );
14734bf42d4b3689b33c474e2f6e2f6294c429ce1a6Maja Bratseth				loadIntegerResource( localValueResourceDir, systemValueResourceDir );
14848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				loadViewResources( systemResourceDir, resourceDir );
14948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				loadMenuResources( resourceDir );
15048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				loadDrawableResources( resourceDir );
15148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				loadPreferenceResources( preferenceDir );
1527fb9367f21d1d50fa798098f24e0c3e9f7497324Jon Boekenoogen
153ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi				listNinePatchResources(ninePatchDrawableIds, resourceDir);
15448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			} else {
15548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				viewLoader = null;
15648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				menuLoader = null;
15748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				preferenceLoader = null;
15848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			}
15948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		} catch ( I18nException e ) {
16048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			throw e;
16148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		} catch ( Exception e ) {
16248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			throw new RuntimeException( e );
16348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
16448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		isInitialized = true;
16548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
16648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
16748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private File getSystemResourceDir( String pathToAndroidResources ) {
16848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return pathToAndroidResources != null ? new File( pathToAndroidResources ) : null;
16948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
17048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
17148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadStringResources( File localResourceDir, File systemValueResourceDir ) throws Exception {
17248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		DocumentLoader stringResourceDocumentLoader = new DocumentLoader( this.stringResourceLoader );
17348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadValueResourcesFromDirs( stringResourceDocumentLoader, localResourceDir, systemValueResourceDir );
17448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
17548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
17648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadPluralsResources( File localResourceDir, File systemValueResourceDir ) throws Exception {
17748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		DocumentLoader stringResourceDocumentLoader = new DocumentLoader( this.pluralResourceLoader );
17848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadValueResourcesFromDirs( stringResourceDocumentLoader, localResourceDir, systemValueResourceDir );
17948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
18048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
18148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadValueResources( File localResourceDir, File systemValueResourceDir ) throws Exception {
18248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		DocumentLoader valueResourceLoader = new DocumentLoader( stringArrayResourceLoader, colorResourceLoader,
18348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				attrResourceLoader );
18448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadValueResourcesFromDirs( valueResourceLoader, localResourceDir, systemValueResourceDir );
18548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
18648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
18748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadDimenResources( File localResourceDir, File systemValueResourceDir ) throws Exception {
18848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		DocumentLoader dimenResourceDocumentLoader = new DocumentLoader( this.dimenResourceLoader );
18948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadValueResourcesFromDirs( dimenResourceDocumentLoader, localResourceDir, systemValueResourceDir );
19048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
19148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
19248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadIntegerResource( File localResourceDir, File systemValueResourceDir ) throws Exception {
19348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		DocumentLoader integerResourceDocumentLoader = new DocumentLoader( this.integerResourceLoader );
19448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadValueResourcesFromDirs( integerResourceDocumentLoader, localResourceDir, systemValueResourceDir );
19548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
19648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
19748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadViewResources( File systemResourceDir, File xmlResourceDir ) throws Exception {
19848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		DocumentLoader viewDocumentLoader = new DocumentLoader( viewLoader );
19948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadLayoutResourceXmlSubDirs( viewDocumentLoader, xmlResourceDir, false );
20048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadLayoutResourceXmlSubDirs( viewDocumentLoader, systemResourceDir, true );
20148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
20248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
20348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadMenuResources( File xmlResourceDir ) throws Exception {
20448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		DocumentLoader menuDocumentLoader = new DocumentLoader( menuLoader );
20548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadMenuResourceXmlDirs( menuDocumentLoader, xmlResourceDir );
20648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
20748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
20848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadDrawableResources( File xmlResourceDir ) throws Exception {
20948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		DocumentLoader drawableDocumentLoader = new DocumentLoader( drawableResourceLoader );
21048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadDrawableResourceXmlDirs( drawableDocumentLoader, xmlResourceDir );
21148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
21248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
21348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadPreferenceResources( File xmlResourceDir ) throws Exception {
21448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( xmlResourceDir.exists() ) {
21548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			DocumentLoader preferenceDocumentLoader = new DocumentLoader( preferenceLoader );
21648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			preferenceDocumentLoader.loadResourceXmlDir( xmlResourceDir );
21748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
21848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
21948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
22048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadLayoutResourceXmlSubDirs( DocumentLoader layoutDocumentLoader, File xmlResourceDir, boolean isSystem )
22148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			throws Exception {
22248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( xmlResourceDir != null ) {
22348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			layoutDocumentLoader.loadResourceXmlDirs( isSystem, xmlResourceDir.listFiles( LAYOUT_DIR_FILE_FILTER ) );
22448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
22548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
22648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
22748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadMenuResourceXmlDirs( DocumentLoader menuDocumentLoader, File xmlResourceDir ) throws Exception {
22848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( xmlResourceDir != null ) {
22948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			menuDocumentLoader.loadResourceXmlDirs( xmlResourceDir.listFiles( MENU_DIR_FILE_FILTER ) );
23048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
23148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
23248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
23348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadDrawableResourceXmlDirs( DocumentLoader drawableResourceLoader, File xmlResourceDir ) throws Exception {
23448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( xmlResourceDir != null ) {
23548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			drawableResourceLoader.loadResourceXmlDirs( xmlResourceDir.listFiles( DRAWABLE_DIR_FILE_FILTER ) );
23648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
23748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
23848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
23948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadValueResourcesFromDirs( DocumentLoader documentLoader, File localValueResourceDir,
24048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			File systemValueResourceDir ) throws Exception {
24148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadValueResourcesFromDir( documentLoader, localValueResourceDir );
24248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		loadSystemResourceXmlDir( documentLoader, systemValueResourceDir );
24348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
24448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
24548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadValueResourcesFromDir( DocumentLoader documentloader, File xmlResourceDir ) throws Exception {
24648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( xmlResourceDir != null ) {
24748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			documentloader.loadResourceXmlDir( xmlResourceDir );
24848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
24948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
25048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
25148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private void loadSystemResourceXmlDir( DocumentLoader documentLoader, File stringResourceDir ) throws Exception {
25248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( stringResourceDir != null ) {
25348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			documentLoader.loadSystemResourceXmlDir( stringResourceDir );
25448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
25548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
25648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
25748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private File getValueResourceDir( File xmlResourceDir ) {
258dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao		String valuesDir = "values";
259dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao		if( !TextUtils.isEmpty( locale ) ){
260dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao			valuesDir += "-"+ locale;
261dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao		}
262dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao		File result = ( xmlResourceDir != null ) ? new File( xmlResourceDir, valuesDir ) : null;
2637fb9367f21d1d50fa798098f24e0c3e9f7497324Jon Boekenoogen		if( result != null && !result.exists() ){
264dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao			throw new RuntimeException("Couldn't find value resource directory: " + result.getAbsolutePath() );
265dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao		}
266dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao		return result;
26748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
26848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
26948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private File getPreferenceResourceDir( File xmlResourceDir ) {
27048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return xmlResourceDir != null ? new File( xmlResourceDir, "xml" ) : null;
27148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
27248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
27348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private String getPathToAndroidResources() {
274bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen		String resFolder = getAndroidResourcePathFromLocalProperties();
275bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen		if (resFolder == null) {
276bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen			resFolder = getAndroidResourcePathFromSystemEnvironment();
277bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen			if (resFolder == null) {
278bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen				resFolder = getAndroidResourcePathFromSystemProperty();
279bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen				if (resFolder == null) {
280bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen					resFolder = getAndroidResourcePathByExecingWhichAndroid();
281bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen				}
282bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen			}
283bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen		}
284bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen
285bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen		// Go through last 5 sdk versions looking for resource folders.
286bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen		if (resFolder != null) {
287bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen			for (int i = sdkVersion; i >= sdkVersion - 5 && i >= 4; i--) {
288bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen				File resourcePath = new File(resFolder, getAndroidResourceSubPath(i));
289bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen				if (resourcePath.exists()) {
290bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen					return resourcePath.getAbsolutePath();
291bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen				} else {
292bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen					System.out.println("WARNING: Unable to find Android resources at: " +
293bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen							resourcePath.toString() + " continuing.");
294bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen				}
295bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen			}
296bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen		} else {
297bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen			System.out.println("WARNING: Unable to find path to Android SDK");
29848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
29948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
30048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return null;
30148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
30248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
30348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private String getAndroidResourcePathFromLocalProperties() {
30448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// Hand tested
30548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// This is the path most often taken by IntelliJ
30648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		File rootDir = resourceDir.getParentFile();
30748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		String localPropertiesFileName = "local.properties";
30848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		File localPropertiesFile = new File( rootDir, localPropertiesFileName );
30948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( !localPropertiesFile.exists() ) {
31048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			localPropertiesFile = new File( localPropertiesFileName );
31148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
31248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( localPropertiesFile.exists() ) {
31348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			Properties localProperties = new Properties();
31448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			try {
31548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				localProperties.load( new FileInputStream( localPropertiesFile ) );
31648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				PropertiesHelper.doSubstitutions( localProperties );
317bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen				return localProperties.getProperty( "sdk.dir" );
31848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			} catch ( IOException e ) {
31948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				// fine, we'll try something else
32048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			}
32148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
32248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return null;
32348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
32448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
32548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private String getAndroidResourcePathFromSystemEnvironment() {
32648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// Hand tested
327bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen		return System.getenv().get( "ANDROID_HOME" );
32848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
32948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
33048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private String getAndroidResourcePathFromSystemProperty() {
33148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// this is used by the android-maven-plugin
332bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen		return System.getProperty( "android.sdk.path" );
33348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
33448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
33548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	private String getAndroidResourcePathByExecingWhichAndroid() {
33648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// Hand tested
33748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// Should always work from the command line. Often fails in IDEs because
33848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// they don't pass the full PATH in the environment
33948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		try {
34048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			Process process = Runtime.getRuntime().exec( new String[] { "which", "android" } );
34148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			String sdkPath = new BufferedReader( new InputStreamReader( process.getInputStream() ) ).readLine();
34248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			if ( sdkPath != null && sdkPath.endsWith( "tools/android" ) ) {
343bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen			    return sdkPath.substring(0, sdkPath.indexOf( "tools/android"));
34448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			}
34548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		} catch ( IOException e ) {
34648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			// fine we'll try something else
34748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
34848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return null;
34948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
35048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
351bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen	private static String getAndroidResourceSubPath(int version) {
352bd20b3c07ba0d63c0e62744eef3c90b69cd6b126Jon Boekenoogen		return "platforms/android-" + version + "/data/res";
35348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
35448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
35548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	static boolean isLayoutDirectory( String path ) {
35648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return path.contains( File.separator + "layout" );
35748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
35848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
35948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	static boolean isDrawableDirectory( String path ) {
36048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return path.contains( File.separator + "drawable" );
36148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
36248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
36348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	static boolean isMenuDirectory( String path ) {
36448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return path.contains( File.separator + "menu" );
36548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
36648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
36748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	/*
36848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	 * For tests only...
36948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	 */
37048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	protected ResourceLoader( StringResourceLoader stringResourceLoader ) {
37148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		resourceExtractor = new ResourceExtractor();
37248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		this.stringResourceLoader = stringResourceLoader;
37348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		pluralResourceLoader = null;
37448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		viewLoader = null;
37548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		stringArrayResourceLoader = null;
37648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		attrResourceLoader = null;
37748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		colorResourceLoader = null;
37848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		drawableResourceLoader = null;
37948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		rawResourceLoader = null;
38048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		dimenResourceLoader = null;
38148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		integerResourceLoader = null;
38248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
38348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
38448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public static ResourceLoader getFrom( Context context ) {
38548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		ResourceLoader resourceLoader = shadowOf( context.getApplicationContext() ).getResourceLoader();
38648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		resourceLoader.init();
38748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return resourceLoader;
38848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
38948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
39048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public String getNameForId( int viewId ) {
39148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
39248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return resourceExtractor.getResourceName( viewId );
39348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
39448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
39548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public View inflateView( Context context, int resource, ViewGroup viewGroup ) {
39648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
39748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return viewLoader.inflateView( context, resource, viewGroup );
39848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
39948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
40048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public int getColorValue( int id ) {
40148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
40248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return colorResourceLoader.getValue( id );
40348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
40448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
40548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public String getStringValue( int id ) {
40648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
40748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return stringResourceLoader.getValue( id );
40848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
40948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
41048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public String getPluralStringValue( int id, int quantity ) {
41148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
41248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return pluralResourceLoader.getValue( id, quantity );
41348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
41448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
41548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public float getDimenValue( int id ) {
41648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
41748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return dimenResourceLoader.getValue( id );
41848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
41948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
42048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public int getIntegerValue( int id ) {
42148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
42248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return integerResourceLoader.getValue( id );
42348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
42448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
42548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public boolean isDrawableXml( int resourceId ) {
42648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
42748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return drawableResourceLoader.isXml( resourceId );
42848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
42948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
430aec1d0888fe04efd0cde7514e155870b18c41286Rick Kawala & Wei Wu    public boolean isAnimatableXml( int resourceId ) {
431aec1d0888fe04efd0cde7514e155870b18c41286Rick Kawala & Wei Wu        init();
432aec1d0888fe04efd0cde7514e155870b18c41286Rick Kawala & Wei Wu        return drawableResourceLoader.isAnimationDrawable( resourceId );
433aec1d0888fe04efd0cde7514e155870b18c41286Rick Kawala & Wei Wu    }
434aec1d0888fe04efd0cde7514e155870b18c41286Rick Kawala & Wei Wu
43548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public int[] getDrawableIds( int resourceId ) {
43648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
43748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return drawableResourceLoader.getDrawableIds( resourceId );
43848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
43948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
44048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public Drawable getXmlDrawable( int resourceId ) {
44148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return drawableResourceLoader.getXmlDrawable( resourceId );
44248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
44348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
44448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public Drawable getAnimDrawable( int resourceId ) {
44548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return getInnerRClassDrawable( resourceId, "$anim", AnimationDrawable.class );
44648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
44748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
44848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public Drawable getColorDrawable( int resourceId ) {
44948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return getInnerRClassDrawable( resourceId, "$color", ColorDrawable.class );
45048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
45148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
45248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	@SuppressWarnings("rawtypes")
453fac8bbf7dfc7904540716be8649b2f5a5c9f6d15adriancowham	private Drawable getInnerRClassDrawable( int drawableResourceId, String suffix, Class returnClass ) {
45448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		ShadowContextWrapper shadowApp = Robolectric.shadowOf( Robolectric.application );
45548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		Class rClass = shadowApp.getResourceLoader().getLocalRClass();
45648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
45748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// Check to make sure there is actually an R Class, if not
45848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// return just a BitmapDrawable
45948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		if ( rClass == null ) {
46048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			return null;
46148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
46248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
46348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		// Load the Inner Class for interrogation
46448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		Class animClass = null;
46548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		try {
46648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			animClass = Class.forName( rClass.getCanonicalName() + suffix );
46748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		} catch ( ClassNotFoundException e ) {
468fac8bbf7dfc7904540716be8649b2f5a5c9f6d15adriancowham			return null;
469fac8bbf7dfc7904540716be8649b2f5a5c9f6d15adriancowham		}
47048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
471fac8bbf7dfc7904540716be8649b2f5a5c9f6d15adriancowham		// Try to find the passed in resource ID
472fac8bbf7dfc7904540716be8649b2f5a5c9f6d15adriancowham		try {
47348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			for ( Field field : animClass.getDeclaredFields() ) {
47448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				if ( field.getInt( animClass ) == drawableResourceId ) {
47548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao					return ( Drawable ) returnClass.newInstance();
47648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao				}
47748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao			}
47848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		} catch ( Exception e ) {
47948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		}
48048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
481fac8bbf7dfc7904540716be8649b2f5a5c9f6d15adriancowham		return null;
48248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
4837fb9367f21d1d50fa798098f24e0c3e9f7497324Jon Boekenoogen
484ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	public boolean isNinePatchDrawable(int drawableResourceId) {
485ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi		return ninePatchDrawableIds.contains(drawableResourceId);
486ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	}
4877fb9367f21d1d50fa798098f24e0c3e9f7497324Jon Boekenoogen
488ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	/**
489ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	 * Returns a collection of resource IDs for all nine-patch drawables
490ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	 * in the project.
4917fb9367f21d1d50fa798098f24e0c3e9f7497324Jon Boekenoogen	 *
492ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	 * @param resourceIds
493ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	 * @param dir
494ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	 */
495ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	private void listNinePatchResources(Set<Integer> resourceIds, File dir) {
496ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi		File[] files = dir.listFiles();
497ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi		if (files != null) {
498ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi			for (File f : files) {
499ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi				if (f.isDirectory() && isDrawableDirectory(f.getPath())) {
500ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi					listNinePatchResources(resourceIds, f);
501ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi				} else {
502ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi					String name = f.getName();
503ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi					if (name.endsWith(".9.png")) {
504ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi						String[] tokens = name.split("\\.9\\.png$");
505ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi						resourceIds.add(resourceExtractor.getResourceId("@drawable/" + tokens[0]));
506ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi					}
507ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi				}
508ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi			}
509ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi		}
510ea277a780371ce94fb402f7853daefc3a8580f0cMichael Portuesi	}
51148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
51248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public InputStream getRawValue( int id ) {
51348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
51448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return rawResourceLoader.getValue( id );
51548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
51648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
51748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public String[] getStringArrayValue( int id ) {
51848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
51948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return stringArrayResourceLoader.getArrayValue( id );
52048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
52148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
52248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public void inflateMenu( Context context, int resource, Menu root ) {
52348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
52448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		menuLoader.inflateMenu( context, resource, root );
52548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
52648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
52748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public PreferenceScreen inflatePreferences( Context context, int resourceId ) {
52848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
52948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return preferenceLoader.inflatePreferences( context, resourceId );
53048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
53148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
53248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public File getAssetsBase() {
53348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return assetsDir;
53448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
53548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
53648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	@SuppressWarnings("rawtypes")
53748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public Class getLocalRClass() {
53848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return rClass;
53948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
54048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
54148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public void setLocalRClass( Class clazz ) {
54248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		rClass = clazz;
54348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
54448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
54548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public ResourceExtractor getResourceExtractor() {
54648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return resourceExtractor;
54748f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
54848f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
54948f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public ViewLoader.ViewNode getLayoutViewNode( String layoutName ) {
55048f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		return viewLoader.viewNodesByLayoutName.get( layoutName );
55148f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
55248f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao
55348f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	public void setLayoutQualifierSearchPath( String... locations ) {
55448f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		init();
55548f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao		viewLoader.setLayoutQualifierSearchPath( locations );
55648f3d7b9a3f4a9f3b719782cae007edac11ed454Wenhui Yao	}
55747bd528af49de6d8459c8aeda60b88cc7a3c961fChristian Williams}
558