Added method to check if methods are available at runtime
Change-Id: Id5fd7b57eb27ce957a93771e9b9297fecd163bf9
diff --git a/src/com/android/contacts/common/compat/CompatUtils.java b/src/com/android/contacts/common/compat/CompatUtils.java
index 5215ac9..58a4eb7 100644
--- a/src/com/android/contacts/common/compat/CompatUtils.java
+++ b/src/com/android/contacts/common/compat/CompatUtils.java
@@ -17,6 +17,7 @@
import android.os.Build;
import android.support.annotation.Nullable;
+import android.text.TextUtils;
import android.util.Log;
import com.android.contacts.common.model.CPOWrapper;
@@ -116,10 +117,10 @@
*
* @param className the name of the class to look for.
* @return {@code true} if the given class is available, {@code false} otherwise or if className
- * is null.
+ * is empty.
*/
public static boolean isClassAvailable(@Nullable String className) {
- if (className == null) {
+ if (TextUtils.isEmpty(className)) {
return false;
}
try {
@@ -128,7 +129,36 @@
} catch (ClassNotFoundException e) {
return false;
} catch (Throwable t) {
- Log.e(TAG, "Unexpected exception when checking if class exists at runtime", t);
+ Log.e(TAG, "Unexpected exception when checking if class:" + className + " exists at "
+ + "runtime", t);
+ return false;
+ }
+ }
+
+ /**
+ * Determines if the given class's method is available to call. Can be used to check if system
+ * apis exist at runtime.
+ *
+ * @param className the name of the class to look for
+ * @param methodName the name of the method to look for
+ * @param parameterTypes the needed parameter types for the method to look for
+ * @return {@code true} if the given class is available, {@code false} otherwise or if className
+ * or methodName are empty.
+ */
+ public static boolean isMethodAvailable(@Nullable String className, @Nullable String methodName,
+ Class<?>... parameterTypes) {
+ if (TextUtils.isEmpty(className) || TextUtils.isEmpty(methodName)) {
+ return false;
+ }
+
+ try {
+ Class.forName(className).getMethod(methodName, parameterTypes);
+ return true;
+ } catch (ClassNotFoundException | NoSuchMethodException e) {
+ return false;
+ } catch (Throwable t) {
+ Log.e(TAG, "Unexpected exception when checking if method: " + className + "#"
+ + methodName + " exists at runtime", t);
return false;
}
}
diff --git a/tests/src/com/android/contacts/common/compat/CompatUtilsTest.java b/tests/src/com/android/contacts/common/compat/CompatUtilsTest.java
index 566a831..eaacbba 100644
--- a/tests/src/com/android/contacts/common/compat/CompatUtilsTest.java
+++ b/tests/src/com/android/contacts/common/compat/CompatUtilsTest.java
@@ -20,11 +20,75 @@
public class CompatUtilsTest extends AndroidTestCase {
- public void testClassAvailable() {
- assertTrue(CompatUtils.isClassAvailable(CompatUtils.class.getName()));
+ public void testIsClassAvailable_NullClassName() {
+ assertFalse(CompatUtils.isClassAvailable(null));
}
- public void testClassNotAvailable() {
- assertFalse(CompatUtils.isClassAvailable("com.android.contacts.common.NonexistantClass"));
+ public void testIsClassAvailable_EmptyClassName() {
+ assertFalse(CompatUtils.isClassAvailable(""));
+ }
+
+ public void testIsClassAvailable_NonexistentClass() {
+ assertFalse(CompatUtils.isClassAvailable("com.android.contacts.common.NonexistentClass"));
+ }
+
+ public void testIsClassAvailable() {
+ assertTrue(CompatUtils.isClassAvailable(BaseClass.class.getName()));
+ }
+
+ public void testIsMethodAvailable_NullClassName() {
+ assertFalse(CompatUtils.isMethodAvailable(null, "methodName"));
+ }
+
+ public void testIsMethodAvailable_EmptyClassName() {
+ assertFalse(CompatUtils.isMethodAvailable("", "methodName"));
+ }
+
+ public void testIsMethodAvailable_NullMethodName() {
+ assertFalse(CompatUtils.isMethodAvailable("className", null));
+ }
+
+ public void testIsMethodAvailable_EmptyMethodName() {
+ assertFalse(CompatUtils.isMethodAvailable("className", ""));
+ }
+
+ public void testIsMethodAvailable_NonexistentClass() {
+ assertFalse(CompatUtils.isMethodAvailable("com.android.contacts.common.NonexistentClass",
+ ""));
+ }
+
+ public void testIsMethodAvailable_NonexistentMethod() {
+ assertFalse(CompatUtils.isMethodAvailable(BaseClass.class.getName(), "derivedMethod"));
+ }
+
+ public void testIsMethodAvailable() {
+ assertTrue(CompatUtils.isMethodAvailable(BaseClass.class.getName(), "baseMethod"));
+ }
+
+ public void testIsMethodAvailable_InheritedMethod() {
+ assertTrue(CompatUtils.isMethodAvailable(DerivedClass.class.getName(), "baseMethod"));
+ }
+
+ public void testIsMethodAvailable_OverloadedMethod() {
+ assertTrue(CompatUtils.isMethodAvailable(DerivedClass.class.getName(), "overloadedMethod"));
+ assertTrue(CompatUtils.isMethodAvailable(DerivedClass.class.getName(), "overloadedMethod",
+ Integer.TYPE));
+ }
+
+ public void testIsMethodAvailable_NonexistentOverload() {
+ assertFalse(CompatUtils.isMethodAvailable(DerivedClass.class.getName(), "overloadedMethod",
+ Boolean.TYPE));
+ }
+
+ private class BaseClass {
+ public void baseMethod() {}
+ }
+
+ private class DerivedClass extends BaseClass {
+ public void derivedMethod() {}
+
+ public void overloadedMethod() {}
+
+ public void overloadedMethod(int i) {}
}
}