Android: 利用反射机制挂载/卸载SD卡以及获取外部存储路径
一. 卸载 SD 卡
1 | public static void unmountVolume(String path) { |
二. 加载 SD 卡
1 | public static void mountVolume(String path) { |
三. 获取外置存储设备的路径
1 | public static String[] getVolumePaths(Context context) { |
四. 反射简介
什么是反射
反射阔以通过非常规手段直接获取并操作方法、字段等所有类的成员。
如何使用反射
这里简单介绍一下如何使用反射。仅能用于理解上面部分代码。如需全面深刻的理解,建议结合 这篇文章 并且动手实践以加深印象。
使用反射的必要条件,即反射的入口
获取需要操作类的
Class
对象,有三种方式:1) class.class
2) class.instance.getClass()
3) Class.forName()
如,上面的卸载 & 挂载 SD 卡部分的代码
Class.forName("android.os.ServiceManager")
即使用的方法 3;而获取外部存储设备的路径中StorageManager.class
即使用的方法 1;通过类的实例获取Class
的对象的话,就需要使用getClass()
方法了。获取指定的方法
当我们获取到类的
Class
对象后,就能通过此对象来操作类的成员,这里只介绍如何通过Class
对象来获取对象的方法。1
2
3
4Class<?> smClass = Class.forName("android.os.ServiceManager");
// 参数 1:需要指定获取方法的名的字符串,这里需要获取 getService(), 就传
Method getService = smClass.getMeDeclaredMethod("getService", String.class);
getService.invoke(smClass.newInstance(), )Class
类提供了以下 4 个函数来获取方法:1
2
3
4
5
6
7
8
9public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException
public Method[] getDeclaredMethods() throws SecurityException
public Method[] getMethods() throws SecurityException根据方法名就能明白这些方法的用途。下面来讲一下
getDeclaredMethod()
与getMethod()
的共同点与差别。共同点: 需要传入 方法名 以及 参数类型 来获取指定方法。方法的名字不难理解,你需要告诉程序,你想要哪一个方法。而参数类型,是为了避免方法重载,程序无法获知你需要的具体方法。方法名 以及 参数类型 就像坐标,帮程序准确定位。
区别:
getMethod
只能获取到使用public
修饰符修饰的方法,且能获取到继承父类中的方法;而getDeclaredMethod
阔以获取到所有该类中的方法,但无法获取父类中的任何办法。下面我们使用
getDeclaredMethods
和getMethods
来验证一下区别:Father:
1
2
3
4
5
6
7
8
9
10
11
12
13
14public class Father {
public Father() {
}
public void fatherMethod1() {
System.out.println("father's public method");
}
private void fatherMethod2() {
System.out.println("father's private method");
}
}Son:
1
2
3
4
5
6
7
8
9
10
11
12
13public class Son extends Father {
public Son() {
}
public void sonMethod1() {
System.out.println("son's public method");
}
private void sonMethod2() {
System.out.println("son's private method");
}
}ReflectTest:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public class ReflectTest {
public static void main(String[] args) {
try {
Class<?> sonClass = Class.forName("Son");
Method[] methods = sonClass.getMethods();
Method[] declaredMethods = sonClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println("getMethods----" + method);
}
for (Method method : declaredMethods) {
System.out.println("getDeclaredMethods----" + method);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}打印结果:
可以看到,
getMethods()
成功获取到使用public
修饰符修饰的方法,包括Object
中的方法。而getDeclaredMethods()
只获取到了Son
类中的所有方法,无法获得继承的方法。调用指定方法
调用方法使用:
1
public Object invoke(Object obj, Object... args)
参数1:指定类的实例,可以通过
Class.newInstance()
获得。通过反射获取类的实例有两种方法,我们这里使用最 简单的,也是不推荐用的。需要了解更多可以 点击这里看看参数2:调用该方法传入的值。(这里应该好理解吧?虽然我说得很抽象…)
代码部分:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public class ReflectTest {
public static void main(String[] args) {
try {
Class<?> sonClass = Class.forName("Son");
Method method1 = sonClass.getDeclaredMethod("sonMethod1", null);
method1.invoke(sonClass.newInstance(), null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}使用到的类都是上面用过的,就不再贴代码了。
可以看到,这里 参数2 我传入的值为 null, 因为该方法不需要参数。
打印结果:
至此好像就把最上边设计到的两三行代码讲完了…
五. 总结
- 获得
Class
对象有三种方法。 - 获得指定方法有两种方式,传入的参数为 方法名 以及 参数类型 ;获取方法集有两种方法。
- 调用方法使用
invoke
传入的参数为 类的实例 以及 方法值 ,如果该方法为静态,那么 类的实例 可以为null