Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6edc0e6b authored by Brandon Maxwell's avatar Brandon Maxwell
Browse files

Added method to check if methods are available at runtime

Change-Id: Id5fd7b57eb27ce957a93771e9b9297fecd163bf9
parent 1e7130c4
Loading
Loading
Loading
Loading
+33 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.contacts.common.compat;

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 @@ public final class CompatUtils {
     *
     * @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 @@ public final class CompatUtils {
        } 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;
        }
    }
+68 −4
Original line number Diff line number Diff line
@@ -20,11 +20,75 @@ import android.test.AndroidTestCase;

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) {}
    }
}