/* * Copyright 2012-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.schildbach.wallet.digitalcoin.util; import java.util.Collections; import java.util.SortedMap; import java.util.TreeMap; import android.os.Build; /** * <p> * Sometimes the application wants to access advanced functionality exposed by Android APIs that are only available in * later versions of the platform. While {@code Build.VERSION} can be used to determine the device's API level and alter * behavior accordingly, and it is possible to write code that uses both old and new APIs selectively, such code would * fail to load on older devices that do not have the new API methods. * </p> * * <p> * It is necessary to only load classes that use newer APIs than the device may support after the app has checked the * API level. This requires reflection, loading one of several implementations based on the API level. * </p> * * <p> * This class manages that process. Subclasses of this class manage access to implementations of a given interface in an * API-level-aware way. Subclasses implementation classes <em>by name</em>, and the minimum API level that the * implementation is compatible with. They also provide a default implementation. * </p> * * <p> * At runtime an appropriate implementation is then chosen, instantiated and returned from {@link #build()}. * </p> * * @param <T> * the interface which managed implementations implement * @author ZXing authors * @author Andreas Schildbach */ 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 void addImplementationClass(int minVersion, String className) { implementations.put(minVersion, className); } public 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 (Exception x) { throw new RuntimeException(x); } } } return defaultImplementation; } }