您的位置:首页 > 移动开发 > Objective-C

利用反射解决有些手机无法使用手电筒的问题

2011-11-16 17:13 351 查看
本次项目,遇到索尼手机无法使用手电筒的问题,但是HTC等用官方的方法可以搞定,经过调查发现,谷歌这小子把API隐藏了,于是乎想起了搞web时使用的反射,但是android的不能直接反射出private的常量和方法,因为andorid貌似把Class.java这个东西重新搞了,其实JDK里面是有这个方法的,需要

Class clazz=Class.forName("android.os.IHardwareService");

    clazz.getClass().getDeclaredFields();

这样才能拿到,下面是手电筒的解决方法:

首先是一个管理类:

public final class FlashlightManager {

private static final String TAG = FlashlightManager.class.getSimpleName();

private static final Object iHardwareService;
private static final Method setFlashEnabledMethod;
private static final Method getFlashEnabledMethod;

/**
* Use Static Intialize Object,Setting HardwareService Manager Object and
* flash method.
*/
static {
iHardwareService = getHardwareService();
setFlashEnabledMethod = getMethod("setFlashlightEnabled", iHardwareService, boolean.class);
getFlashEnabledMethod = getMethod("getFlashlightEnabled", iHardwareService, null);  //here must set null
if (iHardwareService == null) {
Log.v(TAG, "This device does supports control of a flashlight");
} else {
Log.v(TAG, "This device does not support control of a flashlight");
}
}

/**
* Get Hardware Service
*
* @return
*/
private static Object getHardwareService() {

// Use reflect get system service mamger object
Class<?> serviceManagerClass = maybeForName("android.os.ServiceManager");
if (serviceManagerClass == null) {
return null;
}

// Get getService function method object
Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class);
if (getServiceMethod == null) {
return null;
}

Object hardwareService = invoke(getServiceMethod, null, "hardware");
if (hardwareService == null) {
return null;
}

Class<?> iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub");
if (iHardwareServiceStubClass == null) {
return null;
}

Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface", IBinder.class);
if (asInterfaceMethod == null) {
return null;
}

return invoke(asInterfaceMethod, null, hardwareService);
}

/**
* Use reflect
*
* @param methodName
* @param iHardwareService
* @param argClasses
* @return
*/
private static Method getMethod(String methodName, Object iHardwareService, Class<?>... argClasses) {
if (iHardwareService == null) {
return null;
}
Class<?> proxyClass = iHardwareService.getClass();

// test
Method[] methods = proxyClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
Log.i("method---", methods[i].getName());
}

return maybeGetMethod(proxyClass, methodName, argClasses);
}

private static Class<?> maybeForName(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException cnfe) {
// OK
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while finding class " + name, re);
return null;
}
}

private static Method maybeGetMethod(Class<?> clazz, String name, Class<?>... argClasses) {
try {
return clazz.getMethod(name, argClasses);
} catch (NoSuchMethodException nsme) {
// OK
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while finding method " + name, re);
return null;
}
}

private static Object invoke(Method method, Object instance, Object... args) {
try {
return method.invoke(instance, args);
} catch (IllegalAccessException e) {
Log.w(TAG, "Unexpected error while invoking " + method, e);
return null;
} catch (InvocationTargetException e) {
Log.w(TAG, "Unexpected error while invoking " + method, e.getCause());
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while invoking " + method, re);
return null;
}
}

public static void enableFlashlight(Camera camera) {
setFlashlight(camera, true);
}

public static void disableFlashlight(Camera camera) {
setFlashlight(camera, false);
}

/**
* Set Flahlight if activate
*
* @param camera
* @param active
*/
private static void setFlashlight(Camera camera, boolean active) {
if (iHardwareService != null && setFlashEnabledMethod != null && getFlashEnabledMethod != null) {
try {
setFlashEnabledMethod.invoke(iHardwareService, active);
Boolean enabled = (Boolean) getFlashEnabledMethod.invoke(iHardwareService, (Object[]) null);
if (active && !enabled) setFlashlightConventional(camera, active);
} catch (Exception e) {
setFlashlightConventional(camera, active);
}
} else {
setFlashlightConventional(camera, active);
}
}

private static void setFlashlightConventional(Camera camera, boolean active) {
Parameters p = camera.getParameters();
// Set
if (active)
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
else
p.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
}
}


然后是具体调用方法:

private boolean isOpen;

private void flashLightoOpenOrClose(){
//Get System Camera
if(camera==null)camera=Camera.open();
isOpen=!isOpen;
if(isOpen){
FlashlightManager.enableFlashlight(camera);
}else{
FlashlightManager.disableFlashlight(camera);
}
}


今天生日,搞定了这么大个难题,实在爽.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐