diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2017-05-18 17:28:31 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-05-18 17:28:34 +0000 |
commit | 52b0360b1a3af42893c35227992d5bd78d1a32c7 (patch) | |
tree | f8c63089059a53a924d99a759821fcc405d44263 | |
parent | ac6b06ff015ab321b726c5fa990ce368c8fbf399 (diff) | |
parent | b35cacc0b2f6d8b97e052ae14ed5971117dc8203 (diff) | |
download | layoutlib-52b0360b1a3af42893c35227992d5bd78d1a32c7.tar.gz |
Merge "Implement Resources.getIdentifier in layoutlib"
4 files changed, 178 insertions, 1 deletions
diff --git a/bridge/src/android/content/res/Resources_Delegate.java b/bridge/src/android/content/res/Resources_Delegate.java index 6e97b2bd44..0a5912974f 100644 --- a/bridge/src/android/content/res/Resources_Delegate.java +++ b/bridge/src/android/content/res/Resources_Delegate.java @@ -33,6 +33,7 @@ import com.android.layoutlib.bridge.impl.ResourceHelper; import com.android.layoutlib.bridge.util.NinePatchInputStream; import com.android.ninepatch.NinePatch; import com.android.resources.ResourceType; +import com.android.resources.ResourceUrl; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import com.android.tools.layoutlib.annotations.VisibleForTesting; import com.android.util.Pair; @@ -62,6 +63,9 @@ import java.util.Iterator; import java.util.Objects; import java.util.WeakHashMap; +import static com.android.SdkConstants.ANDROID_PKG; +import static com.android.SdkConstants.PREFIX_RESOURCE_REF; + @SuppressWarnings("deprecation") public class Resources_Delegate { private static WeakHashMap<Resources, LayoutlibCallback> sLayoutlibCallbacks = new @@ -437,7 +441,7 @@ public class Resources_Delegate { @NonNull private static String resolveReference(Resources resources, @NonNull String ref, boolean forceFrameworkOnly) { - if (ref.startsWith(SdkConstants.PREFIX_RESOURCE_REF) || ref.startsWith + if (ref.startsWith(PREFIX_RESOURCE_REF) || ref.startsWith (SdkConstants.PREFIX_THEME_REF)) { ResourceValue rv = getContext(resources).getRenderResources().findResValue(ref, forceFrameworkOnly); @@ -1014,6 +1018,69 @@ public class Resources_Delegate { throw new UnsupportedOperationException(); } + @VisibleForTesting + @Nullable + static ResourceUrl resourceUrlFromName(@NonNull String name, @Nullable String defType, + @Nullable + String defPackage) { + int colonIdx = name.indexOf(':'); + int slashIdx = name.indexOf('/'); + + if (colonIdx != -1 && slashIdx != -1) { + // Easy case + return ResourceUrl.parse(PREFIX_RESOURCE_REF + name); + } + + if (colonIdx == -1 && slashIdx == -1) { + if (defType == null) { + throw new IllegalArgumentException("name does not define a type an no defType was" + + " passed"); + } + + // It does not define package or type + return ResourceUrl.parse( + PREFIX_RESOURCE_REF + (defPackage != null ? defPackage + ":" : "") + defType + + "/" + name); + } + + if (colonIdx != -1) { + if (defType == null) { + throw new IllegalArgumentException("name does not define a type an no defType was" + + " passed"); + } + // We have package but no type + String pkg = name.substring(0, colonIdx); + ResourceType type = ResourceType.getEnum(defType); + return type != null ? ResourceUrl.create(pkg, type, name.substring(colonIdx + 1)) : + null; + } + + ResourceType type = ResourceType.getEnum(name.substring(0, slashIdx)); + if (type == null) { + return null; + } + // We have type but no package + return ResourceUrl.create(defPackage, + type, + name.substring(slashIdx + 1)); + } + + @LayoutlibDelegate + static int getIdentifier(Resources resources, String name, String defType, String defPackage) { + if (name == null) { + return 0; + } + + ResourceUrl url = resourceUrlFromName(name, defType, defPackage); + Integer id = null; + if (url != null) { + id = ANDROID_PKG.equals(url.namespace) ? Bridge.getResourceId(url.type, url.name) : + getLayoutlibCallback(resources).getResourceId(url.type, url.name); + } + + return id != null ? id : 0; + } + /** * Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource * type. diff --git a/bridge/tests/src/android/content/res/Resources_DelegateTest.java b/bridge/tests/src/android/content/res/Resources_DelegateTest.java new file mode 100644 index 0000000000..be39ab0712 --- /dev/null +++ b/bridge/tests/src/android/content/res/Resources_DelegateTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.res; + +import com.android.resources.ResourceType; +import com.android.resources.ResourceUrl; + +import org.junit.Test; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +public class Resources_DelegateTest { + private static void assertResourceUrl(@Nullable String pkg, @NonNull String name, + @NonNull ResourceType type, @Nullable ResourceUrl url) { + assertNotNull(url); + assertEquals(type, url.type); + assertEquals(pkg, url.namespace); + assertEquals(name, url.name); + } + + @Test + public void resourceUrlFromName() { + try { + Resources_Delegate.resourceUrlFromName("pkg:name", null, null); + fail("Expected IllegalArgumentException since no type was defined"); + } catch (IllegalArgumentException ignored) { + } + + assertNull(Resources_Delegate.resourceUrlFromName("package:invalid/name", null, null)); + assertNull(Resources_Delegate.resourceUrlFromName("package:name", "invalid", null)); + assertResourceUrl("package", "name", ResourceType.ID, + Resources_Delegate.resourceUrlFromName("package:name", "id", null)); + assertResourceUrl("package", "name", ResourceType.ID, + Resources_Delegate.resourceUrlFromName("name", "id", "package")); + assertResourceUrl("package", "test", ResourceType.STRING, + Resources_Delegate.resourceUrlFromName("package:string/test", null, null)); + assertResourceUrl(null, "test", ResourceType.STRING, + Resources_Delegate.resourceUrlFromName("string/test", null, null)); + + + // Type and package in the name take precedence over the passed defType and defPackage + assertResourceUrl("p1", "r1", ResourceType.STRING, + Resources_Delegate.resourceUrlFromName("p1:string/r1", "id", "p2")); + assertResourceUrl("p2", "r1", ResourceType.STRING, + Resources_Delegate.resourceUrlFromName("string/r1", "id", "p2")); + assertResourceUrl("p1", "r1", ResourceType.ID, + Resources_Delegate.resourceUrlFromName("p1:r1", "id", "p2")); + } +}
\ No newline at end of file diff --git a/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java b/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java index b0f39083bb..208c2d7030 100644 --- a/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java +++ b/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java @@ -20,6 +20,7 @@ import com.android.ide.common.rendering.api.RenderSession; import com.android.ide.common.rendering.api.SessionParams; import com.android.ide.common.rendering.api.SessionParams.RenderingMode; import com.android.ide.common.rendering.api.ViewInfo; +import com.android.internal.R; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.RenderParamsFlags; import com.android.layoutlib.bridge.impl.RenderAction; @@ -48,6 +49,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; /** @@ -533,4 +535,42 @@ public class RenderTests extends RenderTestBase { public void testRectangleShadow() throws Exception { renderAndVerify("shadows_test.xml", "shadows_test.png"); } + + @Test + public void testResourcesGetIdentifier() throws Exception { + // Setup + // Create the layout pull parser for our resources (empty.xml can not be part of the test + // app as it won't compile). + LayoutPullParser parser = LayoutPullParser.createFromPath("/empty.xml"); + // Create LayoutLibCallback. + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4, + layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22); + AssetManager assetManager = AssetManager.getSystem(); + DisplayMetrics metrics = new DisplayMetrics(); + Configuration configuration = RenderAction.getConfiguration(params); + BridgeContext context = new BridgeContext(params.getProjectKey(), metrics, params.getResources(), + params.getAssets(), params.getLayoutlibCallback(), configuration, + params.getTargetSdkVersion(), params.isRtlSupported()); + Resources resources = Resources_Delegate.initSystem(context, assetManager, metrics, + configuration, params.getLayoutlibCallback()); + int id = Resources_Delegate.getLayoutlibCallback(resources).getResourceId( + ResourceType.STRING, + "app_name"); + assertEquals(id, resources.getIdentifier("string/app_name", null, null)); + assertEquals(id, resources.getIdentifier("app_name", "string", null)); + assertEquals(0, resources.getIdentifier("string/does_not_exist", null, null)); + assertEquals(R.string.accept, resources.getIdentifier("android:string/accept", null, + null)); + assertEquals(R.string.accept, resources.getIdentifier("string/accept", null, + "android")); + assertEquals(R.id.message, resources.getIdentifier("id/message", null, + "android")); + assertEquals(R.string.accept, resources.getIdentifier("accept", "string", + "android")); + + context.disposeResources(); + } } diff --git a/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/create/src/com/android/tools/layoutlib/create/CreateInfo.java index cb0bc6d3c4..5951a67f6b 100644 --- a/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -133,6 +133,7 @@ public final class CreateInfo implements ICreateInfo { "android.content.res.Resources#getDimensionPixelSize", "android.content.res.Resources#getDrawable", "android.content.res.Resources#getFont", + "android.content.res.Resources#getIdentifier", "android.content.res.Resources#getIntArray", "android.content.res.Resources#getInteger", "android.content.res.Resources#getLayout", |