ShadowResources.java revision 9daa83d905eccca3b027ce27e4a77b3f57441a1e
133873d2b41a5cd2597b20a4e88eb8942944c0f23Tyler Schultzpackage com.xtremelabs.robolectric.shadows;
2b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
370a3ec81f0bda52d8388facf562a80e2d16ac96fGonçalo Silvaimport android.content.res.AssetManager;
46b77d40267d9b2d4d1b3e206f7d1bdd60a91d8c8Michael Portuesiimport android.content.res.Configuration;
5b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwinimport android.content.res.Resources;
6ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williamsimport android.content.res.TypedArray;
7b01474a3329222965d31068f5c33e59c6e6aa6a4Josh Lauer & Christian Williamsimport android.graphics.BitmapFactory;
8b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwinimport android.graphics.drawable.BitmapDrawable;
9b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwinimport android.graphics.drawable.Drawable;
10ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williamsimport android.util.AttributeSet;
11b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwinimport android.util.DisplayMetrics;
1270a3ec81f0bda52d8388facf562a80e2d16ac96fGonçalo Silvaimport com.xtremelabs.robolectric.Robolectric;
1322c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.Implementation;
1422c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.Implements;
15f64d95f87eb9715622e3f77eb0b369d60270054cChristian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.RealObject;
16f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakkerimport com.xtremelabs.robolectric.res.ResourceExtractor;
173f1d4fe696c2f3efe99b8ef39868c064928efb1aTyler Schultzimport com.xtremelabs.robolectric.res.ResourceLoader;
18b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
1924f155944b10583afd970905e5dbe0acdfc9e0efPhil Goodwin & Tyler Schultzimport java.io.InputStream;
2024f155944b10583afd970905e5dbe0acdfc9e0efPhil Goodwin & Tyler Schultzimport java.util.Locale;
2124f155944b10583afd970905e5dbe0acdfc9e0efPhil Goodwin & Tyler Schultz
22ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williamsimport static com.xtremelabs.robolectric.Robolectric.newInstanceOf;
2324f155944b10583afd970905e5dbe0acdfc9e0efPhil Goodwin & Tyler Schultzimport static com.xtremelabs.robolectric.Robolectric.shadowOf;
2424f155944b10583afd970905e5dbe0acdfc9e0efPhil Goodwin & Tyler Schultz
2559d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin/**
2659d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin * Shadow of {@code Resources} that simulates the loading of resources
2759d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin *
2859d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin * @see com.xtremelabs.robolectric.RobolectricTestRunner#RobolectricTestRunner(Class, String, String)
2959d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin */
30b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin@SuppressWarnings({"UnusedDeclaration"})
31b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin@Implements(Resources.class)
32afe0a89d904a7fe2f5980b9deb26cc3240192459Christian Williamspublic class ShadowResources {
33e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard    private float density = 1.0f;
34e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard
3508d5f9aec95a889473eaff1f5d6afefbaa2bd489Christian Williams    static Resources bind(Resources resources, ResourceLoader resourceLoader) {
36a8486da7c7a0b6a10e943c55992f34d9c256456dChristian Williams        ShadowResources shadowResources = shadowOf(resources);
3703ce698c2bb5b203761ce51694d2fa104be4a40dTyler Schultz        if (shadowResources.resourceLoader != null) throw new RuntimeException("ResourceLoader already set!");
3803ce698c2bb5b203761ce51694d2fa104be4a40dTyler Schultz        shadowResources.resourceLoader = resourceLoader;
3908d5f9aec95a889473eaff1f5d6afefbaa2bd489Christian Williams        return resources;
4008d5f9aec95a889473eaff1f5d6afefbaa2bd489Christian Williams    }
4108d5f9aec95a889473eaff1f5d6afefbaa2bd489Christian Williams
42b01474a3329222965d31068f5c33e59c6e6aa6a4Josh Lauer & Christian Williams    @RealObject Resources realResources;
4308d5f9aec95a889473eaff1f5d6afefbaa2bd489Christian Williams    private ResourceLoader resourceLoader;
4408d5f9aec95a889473eaff1f5d6afefbaa2bd489Christian Williams
45de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
46f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker    public  int getIdentifier(String name, String defType, String defPackage) {
47f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker        Integer index = 0;
48f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker
49f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker        ResourceExtractor resourceExtractor = resourceLoader.getResourceExtractor();
50f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker
51f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker        index = resourceExtractor.getResourceId(defType + "/" + name);
52f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker        if (index == null) {
53f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker            return 0;
54f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker        }
55f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker        return index;
56f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker    }
57f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker
58f320a2d3b8075716daf2a80f5a8f7890086fb609Mark Bakker    @Implementation
59b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    public int getColor(int id) throws Resources.NotFoundException {
6025cbf6f16c0fc8e6524935e6fa3d70ec2a92ed25Phil Goodwin & Tyler Schultz        return resourceLoader.getColorValue(id);
61b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    }
6240c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams
636b77d40267d9b2d4d1b3e206f7d1bdd60a91d8c8Michael Portuesi    @Implementation
646b77d40267d9b2d4d1b3e206f7d1bdd60a91d8c8Michael Portuesi    public Configuration getConfiguration() {
6540c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams        Configuration configuration = new Configuration();
6640c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams        configuration.setToDefaults();
6759dd302ae512cbebc117b8687a634421fcff0993Gautier Hayoun        if (configuration.locale == null) {
6859dd302ae512cbebc117b8687a634421fcff0993Gautier Hayoun            configuration.locale = Locale.getDefault();
6959dd302ae512cbebc117b8687a634421fcff0993Gautier Hayoun        }
7040c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams        return configuration;
716b77d40267d9b2d4d1b3e206f7d1bdd60a91d8c8Michael Portuesi    }
72b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
73de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
74b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    public String getString(int id) throws Resources.NotFoundException {
7525cbf6f16c0fc8e6524935e6fa3d70ec2a92ed25Phil Goodwin & Tyler Schultz        return resourceLoader.getStringValue(id);
76b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    }
77b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
78de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
79b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    public String getString(int id, Object... formatArgs) throws Resources.NotFoundException {
80b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin        String raw = getString(id);
81b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin        return String.format(Locale.ENGLISH, raw, formatArgs);
82b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    }
83b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
84de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
859daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel    public String getQuantityString(int id, int quantity, Object... formatArgs) throws Resources.NotFoundException {
869daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel        String raw = getQuantityString(id, quantity);
879daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel        return String.format(Locale.ENGLISH, raw, formatArgs);
889daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel    }
899daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel
909daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel    @Implementation
919daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel    public String getQuantityString(int id, int quantity) throws Resources.NotFoundException {
929daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel        return resourceLoader.getPluralStringValue(id, quantity);
939daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel    }
949daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel
959daa83d905eccca3b027ce27e4a77b3f57441a1eJan Berkel    @Implementation
96b63be1295e9d42211bd466585850db5897222aa1Macarse    public InputStream openRawResource(int id) throws Resources.NotFoundException {
9740c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams        return resourceLoader.getRawValue(id);
98b63be1295e9d42211bd466585850db5897222aa1Macarse    }
9940c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams
100b63be1295e9d42211bd466585850db5897222aa1Macarse    @Implementation
101b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    public String[] getStringArray(int id) throws Resources.NotFoundException {
10225cbf6f16c0fc8e6524935e6fa3d70ec2a92ed25Phil Goodwin & Tyler Schultz        String[] arrayValue = resourceLoader.getStringArrayValue(id);
103b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin        if (arrayValue == null) {
104b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin            throw new Resources.NotFoundException();
105b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin        }
106b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin        return arrayValue;
107b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    }
108b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
109de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
110bd9537bd36434865d4d25ef332bd388d39a51e34Christian Williams & Phil Goodwin    public CharSequence[] getTextArray(int id) throws Resources.NotFoundException {
111bd9537bd36434865d4d25ef332bd388d39a51e34Christian Williams & Phil Goodwin        return getStringArray(id);
112bd9537bd36434865d4d25ef332bd388d39a51e34Christian Williams & Phil Goodwin    }
113bd9537bd36434865d4d25ef332bd388d39a51e34Christian Williams & Phil Goodwin
114bd9537bd36434865d4d25ef332bd388d39a51e34Christian Williams & Phil Goodwin    @Implementation
115b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    public CharSequence getText(int id) throws Resources.NotFoundException {
116b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin        return getString(id);
117b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    }
118b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
119e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard    public void setDensity(float density) {
120e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard        this.density = density;
121e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard    }
122e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard
123de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
124b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    public DisplayMetrics getDisplayMetrics() {
125e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard        DisplayMetrics displayMetrics = new DisplayMetrics();
126e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard        displayMetrics.density = this.density;
127e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard        return displayMetrics;
128b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    }
129b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
130de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
131f1e19869f68b5b04688cc9701c3e2bf73cd35f76Ryan Richard    public Drawable getDrawable(int drawableResourceId) throws Resources.NotFoundException {
132dc2eb2cd17a7fa2777e6e4f5a7566d90b2413cb4Josh Lauer & Christian Williams        return new BitmapDrawable(BitmapFactory.decodeResource(realResources, drawableResourceId));
133b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    }
134b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
135de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
136fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin    public float getDimension(int id) throws Resources.NotFoundException {
137fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin        // todo: get this value from the xml resources and scale it by display metrics [xw 20101011]
13808d5f9aec95a889473eaff1f5d6afefbaa2bd489Christian Williams        if (resourceLoader.dimensions.containsKey(id)) {
13908d5f9aec95a889473eaff1f5d6afefbaa2bd489Christian Williams            return resourceLoader.dimensions.get(id);
140fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin        }
141fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin        return id - 0x7f000000;
142fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin    }
143b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
144fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin    @Implementation
145fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin    public int getDimensionPixelSize(int id) throws Resources.NotFoundException {
146b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin        // The int value returned from here is probably going to be handed to TextView.setTextSize(),
147b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin        // which takes a float. Avoid int-to-float conversion errors by returning a value generated from this
148b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin        // resource ID but which isn't too big (resource values in R.java are all greater than 0x7f000000).
149b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin
150fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin        return (int) getDimension(id);
151fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin    }
152fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin
153fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin    @Implementation
154fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin    public int getDimensionPixelOffset(int id) throws Resources.NotFoundException {
155fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin        return (int) getDimension(id);
156fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin    }
157fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin
158114296321cba71f8133713306049ce3b411e8563Gonçalo Silva    @Implementation
15940c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams    public AssetManager getAssets() {
160a6ff2c2b15018092af3a28697b521d1ca5e789f0Christian Williams & Phil Goodwin        return ShadowAssetManager.bind(Robolectric.newInstanceOf(AssetManager.class), resourceLoader);
161114296321cba71f8133713306049ce3b411e8563Gonçalo Silva    }
162fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin
163ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams    @Implementation
164ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams    public final android.content.res.Resources.Theme newTheme() {
165ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        return newInstanceOf(Resources.Theme.class);
166ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams    }
167ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams
16859d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin    /**
16959d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin     * Non-Android accessor that sets the value to be returned by {@link #getDimension(int)}
17059d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin     *
17140c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams     * @param id    ID to set the dimension for
17259d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin     * @param value value to be returned
17359d9df0f147b94712b36ad44939ebd2afa4cf1b7Phil Goodwin     */
174fba19865a86f986189561f961a27f664eb23ce38Chee Wong & Phil Goodwin    public void setDimension(int id, int value) {
17508d5f9aec95a889473eaff1f5d6afefbaa2bd489Christian Williams        resourceLoader.dimensions.put(id, value);
176b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin    }
177ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams
178ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams    @Implements(Resources.Theme.class)
179ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams    public static class ShadowTheme {
180ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        @Implementation
181ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        public TypedArray obtainStyledAttributes(int[] attrs) {
182ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams            return obtainStyledAttributes(0, attrs);
183ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        }
184ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams
185ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        @Implementation
186ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        public TypedArray obtainStyledAttributes(int resid, int[] attrs) throws android.content.res.Resources.NotFoundException {
187ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams            return obtainStyledAttributes(null, attrs, 0, 0);
188ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        }
189ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams
190ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        @Implementation
191ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
192ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams            return newInstanceOf(TypedArray.class);
193ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams        }
194ec63d3ad017965dc341bd0ce15f07c65f35b4a90Christian Williams    }
195b63effe7b28319e0430f0baa9b8d1b8ddd3ff307Christian Williams & Phil Goodwin}
196