1. 程式人生 > >Android 多版本Api適配

Android 多版本Api適配

背景:

Android從一開始釋出到現在已經迭代了很多的版本了,其中一些API也經歷了多次修改,比如開啟相機之類的,在Android api 9之前相機開啟就直接open了,但是Android Api 9之後,支援了多攝像頭,為了相機的開啟效率,將不推薦在直接使用open來開啟相機了,而且在open時傳遞相機的ID以來區分具體開啟哪顆攝像頭。

這樣在不同的Android版本下,可以就需要使用不同的api了。

適配方案:

不廢話直接給出適配方案,以開啟相機為例。

1、定義一個相機開啟的介面

public interface OpenCameraInterface
{

    Camera open();

}
2、實現預設開啟相機的介面
final class DefaultOpenCameraInterface implements OpenCameraInterface
{

    @Override
    public Camera open()
    {
        return Camera.open();
    }

}
3、實現指定版本以上開啟相機的介面
@TargetApi(9)
public final class GingerbreadOpenCameraInterface implements OpenCameraInterface
{

    @Override
    public Camera open()
    {

        int numCameras = Camera.getNumberOfCameras();
        if (numCameras == 0)
        {
            return null;
        }

        int index = 0;
        while (index < numCameras)
        {
            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
            Camera.getCameraInfo(index, cameraInfo);
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK)
            {
                break;
            }
            index++;
        }

        Camera camera;
        if (index < numCameras)
        {
            camera = Camera.open(index);
        }
        else
        {
            camera = Camera.open(0);
        }

        return camera;
    }

}
4、相機開啟的管理類
public final class OpenCameraManager extends PlatformSupportManager<OpenCameraInterface>
{

    public OpenCameraManager()
    {
        super(OpenCameraInterface.class, new DefaultOpenCameraInterface());
        addImplementationClass(9, GingerbreadOpenCameraInterface.class.getName());
    }

}

5、不同api適配管理類

public abstract class PlatformSupportManager<T>
{

    private final Class<T> managedInterface;

    private final T defaultImplementation;

    private final SortedMap<Integer, String> implementations;

    protected PlatformSupportManager(Class<T> managedInterface, T defaultImplementation)
    {
        if (!managedInterface.isInterface())
        {
            throw new IllegalArgumentException();
        }
        if (!managedInterface.isInstance(defaultImplementation))
        {
            throw new IllegalArgumentException();
        }
        this.managedInterface = managedInterface;
        this.defaultImplementation = defaultImplementation;
        this.implementations = new TreeMap<Integer, String>(Collections.reverseOrder());
    }

    protected final void addImplementationClass(int minVersion, String className)
    {
        implementations.put(minVersion, className);
    }

    public final T build()
    {
        for (Integer minVersion : implementations.keySet())
        {
            if (Build.VERSION.SDK_INT >= minVersion)
            {
                String className = implementations.get(minVersion);
                try
                {
                    Class<? extends T> clazz = Class.forName(className).asSubclass(managedInterface);
                    return clazz.getConstructor().newInstance();
                }
                catch (ClassNotFoundException cnfe)
                {
                }
                catch (IllegalAccessException iae)
                {
                }
                catch (InstantiationException ie)
                {
                }
                catch (NoSuchMethodException nsme)
                {
                }
                catch (InvocationTargetException ite)
                {
                }
            }
        }
        return defaultImplementation;
    }

}
6、實際使用開啟相機
Camera camera = new OpenCameraManager().build().open();

最後,這樣可以適配多個版本下不同的api,且對於使用場景來說改動很小。