Add support for queryIntentService() from Manfest. (#3153)
diff --git a/robolectric-resources/src/main/java/org/robolectric/manifest/AndroidManifest.java b/robolectric-resources/src/main/java/org/robolectric/manifest/AndroidManifest.java
index 32b2fd3..6e90753 100644
--- a/robolectric-resources/src/main/java/org/robolectric/manifest/AndroidManifest.java
+++ b/robolectric-resources/src/main/java/org/robolectric/manifest/AndroidManifest.java
@@ -280,7 +280,8 @@
String serviceName = resolveClassRef(namedItem.getTextContent());
MetaData metaData = new MetaData(getChildrenTags(serviceNode, "meta-data"));
- ServiceData service = new ServiceData(serviceName, metaData);
+ final List<IntentFilterData> intentFilterData = parseIntentFilters(serviceNode);
+ ServiceData service = new ServiceData(serviceName, metaData, intentFilterData);
List<Node> intentFilters = getChildrenTags(serviceNode, "intent-filter");
for (Node intentFilterNode : intentFilters) {
for (Node actionNode : getChildrenTags(intentFilterNode, "action")) {
@@ -290,7 +291,7 @@
}
}
}
-
+
Node permissionItem = serviceNode.getAttributes().getNamedItem("android:permission");
if (permissionItem != null) {
service.setPermission(permissionItem.getTextContent());
diff --git a/robolectric-resources/src/main/java/org/robolectric/manifest/ServiceData.java b/robolectric-resources/src/main/java/org/robolectric/manifest/ServiceData.java
index 36f93bf..cde5bcc 100644
--- a/robolectric-resources/src/main/java/org/robolectric/manifest/ServiceData.java
+++ b/robolectric-resources/src/main/java/org/robolectric/manifest/ServiceData.java
@@ -1,6 +1,7 @@
package org.robolectric.manifest;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
public class ServiceData {
@@ -8,11 +9,13 @@
private final MetaData metaData;
private final List<String> actions;
private String permission;
+ private List<IntentFilterData> intentFilters;
- public ServiceData(String className, MetaData metaData) {
+ public ServiceData(String className, MetaData metaData, List<IntentFilterData> intentFilterData) {
this.actions = new ArrayList<>();
this.className = className;
this.metaData = metaData;
+ intentFilters = new LinkedList<>(intentFilterData);
}
public String getClassName() {
@@ -38,4 +41,12 @@
public String getPermission() {
return permission;
}
+
+ /**
+ * Get the intent filters defined for activity.
+ * @return A list of intent filters. Not null.
+ */
+ public List<IntentFilterData> getIntentFilters() {
+ return intentFilters;
+ }
}
diff --git a/robolectric/src/main/java/org/robolectric/res/builder/DefaultPackageManager.java b/robolectric/src/main/java/org/robolectric/res/builder/DefaultPackageManager.java
index b8584be..c8e8d51 100644
--- a/robolectric/src/main/java/org/robolectric/res/builder/DefaultPackageManager.java
+++ b/robolectric/src/main/java/org/robolectric/res/builder/DefaultPackageManager.java
@@ -378,7 +378,42 @@
@Override
public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
- return queryIntent(intent, flags);
+ // Check the manually added resolve infos first.
+ List<ResolveInfo> resolveInfos = queryIntent(intent, flags);
+ if (!resolveInfos.isEmpty()) {
+ return resolveInfos;
+ }
+
+ // Check matches from the manifest.
+ resolveInfos = new ArrayList<>();
+ if (resolveInfos.isEmpty()) {
+ for (ServiceData service : applicationManifest.getServices()) {
+ IntentFilter intentFilter = matchIntentFilter(intent, service.getIntentFilters());
+ if (intentFilter != null) {
+ resolveInfos.add(getResolveInfo(service, intentFilter, applicationManifest.getPackageName()));
+ }
+ }
+ }
+
+ return resolveInfos;
+ }
+
+ private static ResolveInfo getResolveInfo(ServiceData service, IntentFilter intentFilter, String packageName) {
+ try {
+ ResolveInfo info = new ResolveInfo();
+ info.isDefault = intentFilter.hasCategory("Intent.CATEGORY_DEFAULT");
+ info.serviceInfo = new ServiceInfo();
+ info.serviceInfo.name = service.getClassName();
+ info.serviceInfo.packageName = packageName;
+ info.serviceInfo.applicationInfo = new ApplicationInfo();
+ info.filter = new IntentFilter();
+ for (Iterator<String> it = intentFilter.typesIterator(); it.hasNext(); ) {
+ info.filter.addDataType(it.next());
+ }
+ return info;
+ } catch (IntentFilter.MalformedMimeTypeException e) {
+ throw new RuntimeException(e);
+ }
}
@Override
@@ -861,7 +896,8 @@
activityName = activityData.getTargetActivityName();
}
- if (matchIntentFilter(activityData, intent)) {
+ IntentFilter intentFilter = matchIntentFilter(intent, activityData.getIntentFilters());
+ if (intentFilter != null) {
ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.resolvePackageName = packageName;
resolveInfo.activityInfo = new ActivityInfo();
@@ -875,8 +911,8 @@
return resolveInfoList;
}
- private boolean matchIntentFilter(ActivityData activityData, Intent intent) {
- for (IntentFilterData intentFilterData : activityData.getIntentFilters()) {
+ private IntentFilter matchIntentFilter(Intent intent, List<IntentFilterData> intentFilters) {
+ for (IntentFilterData intentFilterData : intentFilters) {
List<String> actionList = intentFilterData.getActions();
List<String> categoryList = intentFilterData.getCategories();
IntentFilter intentFilter = new IntentFilter();
@@ -928,10 +964,10 @@
intent.getData());
if (matchActionResult && (matchCategoriesResult == null) &&
(matchResult != IntentFilter.NO_MATCH_DATA && matchResult != IntentFilter.NO_MATCH_TYPE)){
- return true;
+ return intentFilter;
}
}
- return false;
+ return null;
}
@Override
diff --git a/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java b/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java
index 8819ae7..ddc3e47 100644
--- a/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java
+++ b/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java
@@ -92,10 +92,13 @@
assertThat(config.getServices().get(0).getClassName()).isEqualTo("com.foo.Service");
assertThat(config.getServices().get(0).getActions()).contains("org.robolectric.ACTION_DIFFERENT_PACKAGE");
+ assertThat(config.getServices().get(0).getIntentFilters()).isNotEmpty();
+ assertThat(config.getServices().get(0).getIntentFilters().get(0).getMimeTypes()).containsExactly("image/jpeg");
assertThat(config.getServices().get(1).getClassName()).isEqualTo("com.bar.ServiceWithoutIntentFilter");
assertThat(config.getServices().get(1).getActions()).isEmpty();
-
+ assertThat(config.getServices().get(1).getIntentFilters()).isEmpty();
+
assertThat(config.getServiceData("com.foo.Service").getClassName()).isEqualTo("com.foo.Service");
assertThat(config.getServiceData("com.bar.ServiceWithoutIntentFilter").getClassName()).isEqualTo("com.bar.ServiceWithoutIntentFilter");
assertEquals(config.getServiceData("com.foo.Service").getPermission(), "com.foo.Permission");
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowPackageManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowPackageManagerTest.java
index c6f4ea8..dd0d7fc 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowPackageManagerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowPackageManagerTest.java
@@ -422,9 +422,19 @@
shadowPackageManager.addResolveInfoForIntent(i, info);
- List<ResolveInfo> activities = shadowPackageManager.queryIntentServices(i, 0);
- assertThat(activities).hasSize(1);
- assertThat(activities.get(0).nonLocalizedLabel.toString()).isEqualTo(TEST_PACKAGE_LABEL);
+ List<ResolveInfo> services = shadowPackageManager.queryIntentServices(i, 0);
+ assertThat(services).hasSize(1);
+ assertThat(services.get(0).nonLocalizedLabel.toString()).isEqualTo(TEST_PACKAGE_LABEL);
+ }
+
+ @Test
+ @Config(manifest = "TestAndroidManifestWithServices.xml")
+ public void queryIntentServices_fromManifest() {
+ Intent i = new Intent("org.robolectric.ACTION_DIFFERENT_PACKAGE");
+ i.addCategory(Intent.CATEGORY_LAUNCHER);
+ i.setType("image/jpeg");
+ List<ResolveInfo> services = shadowPackageManager.queryIntentServices(i, 0);
+ assertThat(services).isNotEmpty();
}
@Test
diff --git a/robolectric/src/test/resources/TestAndroidManifestForActivitiesWithIntentFilter.xml b/robolectric/src/test/resources/TestAndroidManifestForActivitiesWithIntentFilter.xml
index 2fec297..a44e70a 100644
--- a/robolectric/src/test/resources/TestAndroidManifestForActivitiesWithIntentFilter.xml
+++ b/robolectric/src/test/resources/TestAndroidManifestForActivitiesWithIntentFilter.xml
@@ -10,5 +10,11 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
+ <service android:name="org.robolectric.shadows.TestService">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </service>
</application>
</manifest>
diff --git a/robolectric/src/test/resources/TestAndroidManifestWithServices.xml b/robolectric/src/test/resources/TestAndroidManifestWithServices.xml
index 7b50afc..bd1c131 100644
--- a/robolectric/src/test/resources/TestAndroidManifestWithServices.xml
+++ b/robolectric/src/test/resources/TestAndroidManifestWithServices.xml
@@ -5,6 +5,8 @@
<service android:name="com.foo.Service" android:permission="com.foo.Permission">
<intent-filter>
<action android:name="org.robolectric.ACTION_DIFFERENT_PACKAGE"/>
+ <data android:mimeType="image/jpeg"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</service>