1 package org.robolectric; 2 3 import android.app.Activity; 4 import android.app.Fragment; 5 import android.app.IntentService; 6 import android.app.Service; 7 import android.app.backup.BackupAgent; 8 import android.content.ContentProvider; 9 import android.content.Intent; 10 import android.os.Bundle; 11 import android.util.AttributeSet; 12 import android.view.View; 13 import java.util.ServiceLoader; 14 import javax.xml.parsers.DocumentBuilder; 15 import javax.xml.parsers.DocumentBuilderFactory; 16 import javax.xml.parsers.ParserConfigurationException; 17 import org.robolectric.android.XmlResourceParserImpl; 18 import org.robolectric.android.controller.ActivityController; 19 import org.robolectric.android.controller.BackupAgentController; 20 import org.robolectric.android.controller.ContentProviderController; 21 import org.robolectric.android.controller.FragmentController; 22 import org.robolectric.android.controller.IntentServiceController; 23 import org.robolectric.android.controller.ServiceController; 24 import org.robolectric.internal.ShadowProvider; 25 import org.robolectric.res.ResName; 26 import org.robolectric.res.ResourceTable; 27 import org.robolectric.shadows.ShadowApplication; 28 import org.robolectric.util.ReflectionHelpers; 29 import org.robolectric.util.Scheduler; 30 import org.w3c.dom.Document; 31 import org.w3c.dom.Element; 32 33 public class Robolectric { 34 35 /** 36 * This method is internal and shouldn't be called by developers. 37 */ 38 @Deprecated 39 public static void reset() { 40 // No-op- is now handled in the test runner. Users should not be calling this method anyway. 41 } 42 43 public static <T extends Service> ServiceController<T> buildService(Class<T> serviceClass) { 44 return buildService(serviceClass, null); 45 } 46 47 public static <T extends Service> ServiceController<T> buildService(Class<T> serviceClass, Intent intent) { 48 return ServiceController.of(ReflectionHelpers.callConstructor(serviceClass), intent); 49 } 50 51 public static <T extends Service> T setupService(Class<T> serviceClass) { 52 return buildService(serviceClass).create().get(); 53 } 54 55 public static <T extends IntentService> IntentServiceController<T> buildIntentService(Class<T> serviceClass) { 56 return buildIntentService(serviceClass, null); 57 } 58 59 public static <T extends IntentService> IntentServiceController<T> buildIntentService(Class<T> serviceClass, Intent intent) { 60 return IntentServiceController.of(ReflectionHelpers.callConstructor(serviceClass, new ReflectionHelpers.ClassParameter<String>(String.class, "IntentService")), intent); 61 } 62 63 public static <T extends IntentService> T setupIntentService(Class<T> serviceClass) { 64 return buildIntentService(serviceClass).create().get(); 65 } 66 67 public static <T extends ContentProvider> ContentProviderController<T> buildContentProvider(Class<T> contentProviderClass) { 68 return ContentProviderController.of(ReflectionHelpers.callConstructor(contentProviderClass)); 69 } 70 71 public static <T extends ContentProvider> T setupContentProvider(Class<T> contentProviderClass) { 72 return buildContentProvider(contentProviderClass).create().get(); 73 } 74 75 public static <T extends ContentProvider> T setupContentProvider(Class<T> contentProviderClass, String authority) { 76 return buildContentProvider(contentProviderClass).create(authority).get(); 77 } 78 79 public static <T extends Activity> ActivityController<T> buildActivity(Class<T> activityClass) { 80 return buildActivity(activityClass, null); 81 } 82 83 public static <T extends Activity> ActivityController<T> buildActivity(Class<T> activityClass, Intent intent) { 84 return ActivityController.of(ReflectionHelpers.callConstructor(activityClass), intent); 85 } 86 87 public static <T extends Activity> T setupActivity(Class<T> activityClass) { 88 return buildActivity(activityClass).setup().get(); 89 } 90 91 public static <T extends Fragment> FragmentController<T> buildFragment(Class<T> fragmentClass) { 92 return FragmentController.of(ReflectionHelpers.callConstructor(fragmentClass)); 93 } 94 95 public static <T extends Fragment> FragmentController<T> buildFragment(Class<T> fragmentClass, 96 Bundle arguments) { 97 return FragmentController.of(ReflectionHelpers.callConstructor(fragmentClass), arguments); 98 } 99 100 public static <T extends Fragment> FragmentController<T> buildFragment(Class<T> fragmentClass, 101 Class<? extends Activity> activityClass) { 102 return FragmentController.of(ReflectionHelpers.callConstructor(fragmentClass), activityClass); 103 } 104 105 public static <T extends Fragment> FragmentController<T> buildFragment(Class<T> fragmentClass, Intent intent) { 106 return FragmentController.of(ReflectionHelpers.callConstructor(fragmentClass), intent); 107 } 108 109 public static <T extends Fragment> FragmentController<T> buildFragment(Class<T> fragmentClass, 110 Intent intent, 111 Bundle arguments) { 112 return FragmentController.of(ReflectionHelpers.callConstructor(fragmentClass), intent, arguments); 113 } 114 115 public static <T extends Fragment> FragmentController<T> buildFragment(Class<T> fragmentClass, 116 Class<? extends Activity> activityClass, 117 Intent intent) { 118 return FragmentController.of(ReflectionHelpers.callConstructor(fragmentClass), activityClass, intent); 119 } 120 121 public static <T extends Fragment> FragmentController<T> buildFragment(Class<T> fragmentClass, 122 Class<? extends Activity> activityClass, 123 Bundle arguments) { 124 return FragmentController.of(ReflectionHelpers.callConstructor(fragmentClass), activityClass, arguments); 125 } 126 127 public static <T extends Fragment> FragmentController<T> buildFragment(Class<T> fragmentClass, 128 Class<? extends Activity> activityClass, 129 Intent intent, 130 Bundle arguments) { 131 return FragmentController.of(ReflectionHelpers.callConstructor(fragmentClass), activityClass, intent, arguments); 132 } 133 134 public static <T extends BackupAgent> BackupAgentController<T> buildBackupAgent(Class<T> backupAgentClass) { 135 return BackupAgentController.of(ReflectionHelpers.callConstructor(backupAgentClass)); 136 } 137 138 public static <T extends BackupAgent> T setupBackupAgent(Class<T> backupAgentClass) { 139 return buildBackupAgent(backupAgentClass).create().get(); 140 } 141 142 /** 143 * Allows for the programatic creation of an {@link AttributeSet} useful for testing {@link View} classes without 144 * the need for creating XML snippets. 145 */ 146 public static AttributeSetBuilder buildAttributeSet() { 147 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 148 factory.setNamespaceAware(true); 149 factory.setIgnoringComments(true); 150 factory.setIgnoringElementContentWhitespace(true); 151 Document document; 152 try { 153 DocumentBuilder documentBuilder = factory.newDocumentBuilder(); 154 document = documentBuilder.newDocument(); 155 Element dummy = document.createElementNS("http://schemas.android.com/apk/res/" + RuntimeEnvironment.application.getPackageName(), "dummy"); 156 document.appendChild(dummy); 157 } catch (ParserConfigurationException e) { 158 throw new RuntimeException(e); 159 } 160 return new AttributeSetBuilder(document, RuntimeEnvironment.getCompileTimeResourceTable()); 161 } 162 163 public static class AttributeSetBuilder { 164 165 private Document doc; 166 private ResourceTable appResourceTable; 167 168 AttributeSetBuilder(Document doc, ResourceTable resourceTable) { 169 this.doc = doc; 170 this.appResourceTable = resourceTable; 171 } 172 173 public AttributeSetBuilder addAttribute(int resId, String value) { 174 ResName resName = appResourceTable.getResName(resId); 175 if ("style".equals(resName.name)) { 176 ((Element)doc.getFirstChild()).setAttribute(resName.name, value); 177 } else { 178 ((Element)doc.getFirstChild()).setAttributeNS(resName.getNamespaceUri(), resName.packageName + ":" + resName.name, value); 179 } 180 return this; 181 } 182 183 public AttributeSetBuilder setStyleAttribute(String value) { 184 ((Element)doc.getFirstChild()).setAttribute("style", value); 185 return this; 186 } 187 188 public AttributeSet build() { 189 XmlResourceParserImpl parser = new XmlResourceParserImpl(doc, null, RuntimeEnvironment.application.getPackageName(), RuntimeEnvironment.application.getPackageName(), appResourceTable); 190 try { 191 parser.next(); // Root document element 192 parser.next(); // "dummy" element 193 } catch (Exception e) { 194 throw new IllegalStateException("Expected single dummy element in the document to contain the attributes.", e); 195 } 196 197 return parser; 198 } 199 } 200 201 /** 202 * Return the foreground scheduler (e.g. the UI thread scheduler). 203 * 204 * @return Foreground scheduler. 205 */ 206 public static Scheduler getForegroundThreadScheduler() { 207 return ShadowApplication.getInstance().getForegroundThreadScheduler(); 208 } 209 210 /** 211 * Execute all runnables that have been enqueued on the foreground scheduler. 212 */ 213 public static void flushForegroundThreadScheduler() { 214 getForegroundThreadScheduler().advanceToLastPostedRunnable(); 215 } 216 217 /** 218 * Return the background scheduler. 219 * 220 * @return Background scheduler. 221 */ 222 public static Scheduler getBackgroundThreadScheduler() { 223 return ShadowApplication.getInstance().getBackgroundThreadScheduler(); 224 } 225 226 /** 227 * Execute all runnables that have been enqueued on the background scheduler. 228 */ 229 public static void flushBackgroundThreadScheduler() { 230 getBackgroundThreadScheduler().advanceToLastPostedRunnable(); 231 } 232 } 233