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

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

今天生日,搞定了这么大个难题,实在爽.








你可能感兴趣的:(利用反射解决有些手机无法使用手电筒的问题)