LayoutLibTestCallback.java revision 37dbb8b7f3c069196040eed3a03006647db7fa5b
1/* 2 * Copyright (C) 2014 The Android Open Source Project 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 17package com.android.layoutlib.bridge.intensive.setup; 18 19import com.android.SdkConstants; 20import com.android.ide.common.rendering.api.ActionBarCallback; 21import com.android.ide.common.rendering.api.AdapterBinding; 22import com.android.ide.common.rendering.api.ILayoutPullParser; 23import com.android.ide.common.rendering.api.LayoutlibCallback; 24import com.android.ide.common.rendering.api.ResourceReference; 25import com.android.ide.common.rendering.api.ResourceValue; 26import com.android.resources.ResourceType; 27import com.android.ide.common.resources.IntArrayWrapper; 28import com.android.util.Pair; 29import com.android.utils.ILogger; 30 31import java.io.File; 32import java.lang.reflect.Constructor; 33import java.lang.reflect.Field; 34import java.lang.reflect.Modifier; 35import java.util.Map; 36 37import com.google.android.collect.Maps; 38 39@SuppressWarnings("deprecation") // For Pair 40public class LayoutLibTestCallback extends LayoutlibCallback { 41 42 private static final String PROJECT_CLASSES_LOCATION = "/testApp/MyApplication/build/intermediates/classes/debug/"; 43 private static final String PACKAGE_NAME = "com.android.layoutlib.test.myapplication"; 44 45 private final Map<Integer, Pair<ResourceType, String>> mProjectResources = Maps.newHashMap(); 46 private final Map<IntArrayWrapper, String> mStyleableValueToNameMap = Maps.newHashMap(); 47 private final Map<ResourceType, Map<String, Integer>> mResources = Maps.newHashMap(); 48 private final ILogger mLog; 49 private final ActionBarCallback mActionBarCallback = new ActionBarCallback(); 50 private final ClassLoader mModuleClassLoader = new ModuleClassLoader(PROJECT_CLASSES_LOCATION); 51 52 public LayoutLibTestCallback(ILogger logger) { 53 mLog = logger; 54 } 55 56 public void initResources() throws ClassNotFoundException { 57 Class<?> rClass = mModuleClassLoader.loadClass(PACKAGE_NAME + ".R"); 58 Class<?>[] nestedClasses = rClass.getDeclaredClasses(); 59 for (Class<?> resClass : nestedClasses) { 60 final ResourceType resType = ResourceType.getEnum(resClass.getSimpleName()); 61 62 if (resType != null) { 63 final Map<String, Integer> resName2Id = Maps.newHashMap(); 64 mResources.put(resType, resName2Id); 65 66 for (Field field : resClass.getDeclaredFields()) { 67 final int modifiers = field.getModifiers(); 68 if (Modifier.isStatic(modifiers)) { // May not be final in library projects 69 final Class<?> type = field.getType(); 70 try { 71 if (type.isArray() && type.getComponentType() == int.class) { 72 mStyleableValueToNameMap.put( 73 new IntArrayWrapper((int[]) field.get(null)), 74 field.getName()); 75 } else if (type == int.class) { 76 final Integer value = (Integer) field.get(null); 77 mProjectResources.put(value, Pair.of(resType, field.getName())); 78 resName2Id.put(field.getName(), value); 79 } else { 80 mLog.error(null, "Unknown field type in R class: %1$s", type); 81 } 82 } catch (IllegalAccessException ignored) { 83 mLog.error(ignored, "Malformed R class: %1$s", PACKAGE_NAME + ".R"); 84 } 85 } 86 } 87 } 88 } 89 } 90 91 92 @Override 93 public Object loadView(String name, Class[] constructorSignature, Object[] constructorArgs) 94 throws Exception { 95 Class<?> viewClass = mModuleClassLoader.loadClass(name); 96 Constructor<?> viewConstructor = viewClass.getConstructor(constructorSignature); 97 viewConstructor.setAccessible(true); 98 return viewConstructor.newInstance(constructorArgs); 99 } 100 101 @Override 102 public String getNamespace() { 103 return String.format(SdkConstants.NS_CUSTOM_RESOURCES_S, 104 PACKAGE_NAME); 105 } 106 107 @Override 108 public Pair<ResourceType, String> resolveResourceId(int id) { 109 return mProjectResources.get(id); 110 } 111 112 @Override 113 public String resolveResourceId(int[] id) { 114 return mStyleableValueToNameMap.get(new IntArrayWrapper(id)); 115 } 116 117 @Override 118 public Integer getResourceId(ResourceType type, String name) { 119 return mResources.get(type).get(name); 120 } 121 122 @Override 123 public ILayoutPullParser getParser(String layoutName) { 124 org.junit.Assert.fail("This method shouldn't be called by this version of LayoutLib."); 125 return null; 126 } 127 128 @Override 129 public ILayoutPullParser getParser(ResourceValue layoutResource) { 130 return new LayoutPullParser(new File(layoutResource.getValue())); 131 } 132 133 @Override 134 public Object getAdapterItemValue(ResourceReference adapterView, Object adapterCookie, 135 ResourceReference itemRef, int fullPosition, int positionPerType, 136 int fullParentPosition, int parentPositionPerType, ResourceReference viewRef, 137 ViewAttribute viewAttribute, Object defaultValue) { 138 return null; 139 } 140 141 @Override 142 public AdapterBinding getAdapterBinding(ResourceReference adapterViewRef, Object adapterCookie, 143 Object viewObject) { 144 return null; 145 } 146 147 @Override 148 public ActionBarCallback getActionBarCallback() { 149 return mActionBarCallback; 150 } 151 152 @Override 153 public boolean supports(int ideFeature) { 154 return false; 155 } 156} 157