Android中反射机制使用方法

前言

项目中有许多以前调用的API,Android studio提示已经过时,所以打算把过时的API替换掉,但是新的API是@hide的,需要反射来调用,于是便重温了一下反射机制。先上例子:wifi遗忘功能以前的实现方式是:

mWifiManager.removeNetwork(config.get(i).networkId);
mWifiManager.saveConfiguration();

但是新的实现方法是forget方法,由于forget方法是隐藏方法,所以利用反射机制调用:

    public static void forgetNetwork(WifiManager manager, int networkId) {
        if (manager == null) {
            return;
        }
        try {
           //如果不传入WiFimanager,我们可以利用Class类来获取
           // Class  wifiManagerClass = WifiManager.class;
           //Method forget = wifiManagerClass.getDeclaredMethod("forget", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
            Method forget = manager.getClass().getDeclaredMethod("forget", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
            if (forget != null) {
                forget.setAccessible(true);
                forget.invoke(manager, networkId, null);
              //forget.invoke(wifiManagerClass.newInstance(), networkId, null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Android反射机制调用API步骤

Android反射机制调用API有三个步骤:
1.获取Class对象

lass  wifiManagerClass = WifiManager.class;

2.获取方法

Method forget = wifiManagerClass.getDeclaredMethod("forget", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));

3.方法调用

forget.invoke(manager, networkId, null);

获取方法有getMethod(String name, Class[] parameterTypes, boolean recursivePublicMethods)和getDeclaredMethod(String name, Class... parameterTypes).其中getMethod获取public方法,getDeclaredMethod方法获取private方法。

获取方法和方法调用源码注释

getDeclaredMethod源码注释如下:

    /**
     * Returns a {@code Method} object that reflects the specified
     * declared method of the class or interface represented by this
     * {@code Class} object. The {@code name} parameter is a
     * {@code String} that specifies the simple name of the desired
     * method, and the {@code parameterTypes} parameter is an array of
     * {@code Class} objects that identify the method's formal parameter
     * types, in declared order.  If more than one method with the same
     * parameter types is declared in a class, and one of these methods has a
     * return type that is more specific than any of the others, that method is
     * returned; otherwise one of the methods is chosen arbitrarily.  If the
     * name is "<init>"or "<clinit>" a {@code NoSuchMethodException}
     * is raised.
     *
     * 

If this {@code Class} object represents an array type, then this * method does not find the {@code clone()} method. * 由源码注释可知,第一个参数为方法名,后面的都是方法的参数,如果一个方法重载了多次,则根据参数匹配度来判断是使用哪一个方法。 * @param name the name of the method * @param parameterTypes the parameter array * @return the {@code Method} object for the method of this class * matching the specified name and parameters * @throws NoSuchMethodException if a matching method is not found. * @throws NullPointerException if {@code name} is {@code null} * @throws SecurityException * If a security manager, s, is present and any of the * following conditions is met: * *

    * *
  • the caller's class loader is not the same as the * class loader of this class and invocation of * {@link SecurityManager#checkPermission * s.checkPermission} method with * {@code RuntimePermission("accessDeclaredMembers")} * denies access to the declared method * *
  • the caller's class loader is not the same as or an * ancestor of the class loader for the current class and * invocation of {@link SecurityManager#checkPackageAccess * s.checkPackageAccess()} denies access to the package * of this class * *
* * @jls 8.2 Class Members * @jls 8.4 Method Declarations * @since JDK1.1 */ @CallerSensitive public Method getDeclaredMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { return getMethod(name, parameterTypes, false); }

方法的调用invoke源码注释如下:

    /**   
     * Invokes the underlying method represented by this {@code Method}
     * object, on the specified object with the specified parameters.
     * Individual parameters are automatically unwrapped to match
     * primitive formal parameters, and both primitive and reference
     * parameters are subject to method invocation conversions as
     * necessary.
     *
     * 

If the underlying method is static, then the specified {@code obj} * argument is ignored. It may be null. * *

If the number of formal parameters required by the underlying method is * 0, the supplied {@code args} array may be of length 0 or null. * *

If the underlying method is an instance method, it is invoked * using dynamic method lookup as documented in The Java Language * Specification, Second Edition, section 15.12.4.4; in particular, * overriding based on the runtime type of the target object will occur. * *

If the underlying method is static, the class that declared * the method is initialized if it has not already been initialized. * *

If the method completes normally, the value it returns is * returned to the caller of invoke; if the value has a primitive * type, it is first appropriately wrapped in an object. However, * if the value has the type of an array of a primitive type, the * elements of the array are not wrapped in objects; in * other words, an array of primitive type is returned. If the * underlying method return type is void, the invocation returns * null. * 由注释可知第一个参数为调用该方法的实例对象,其他参数为该方法的参数 * @param obj the object the underlying method is invoked from * @param args the arguments used for the method call * @return the result of dispatching the method represented by * this object on {@code obj} with parameters * {@code args} * * @exception IllegalAccessException if this {@code Method} object * is enforcing Java language access control and the underlying * method is inaccessible. * @exception IllegalArgumentException if the method is an * instance method and the specified object argument * is not an instance of the class or interface * declaring the underlying method (or of a subclass * or implementor thereof); if the number of actual * and formal parameters differ; if an unwrapping * conversion for primitive arguments fails; or if, * after possible unwrapping, a parameter value * cannot be converted to the corresponding formal * parameter type by a method invocation conversion. * @exception InvocationTargetException if the underlying method * throws an exception. * @exception NullPointerException if the specified object is null * and the method is an instance method. * @exception ExceptionInInitializerError if the initialization * provoked by this method fails. */ @FastNative public native Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;

你可能感兴趣的:(Android中反射机制使用方法)