本次项目,遇到索尼手机无法使用手电筒的问题,但是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); } }