Add framework for adding code targeting API levels higher than min supported. Add simplified backport of BS+ code for handling front, rotated cameras, to simply let a front camera open for now. Not guaranteed to work. Adjust optimization to keep these classes. Don't yet take away the Market filter requiring rear camera.

git-svn-id: https://zxing.googlecode.com/svn/trunk@2361 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2012-07-31 14:14:55 +00:00
parent d4db46ecf6
commit a7c40abe8f
8 changed files with 325 additions and 2 deletions

View file

@ -0,0 +1,67 @@
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
# Optimizations: If you don't want to optimize, use the
# proguard-android.txt configuration file instead of this one, which
# turns off the optimization flags. Adding optimization introduces
# certain risks, since for example not all optimizations performed by
# ProGuard works on all versions of Dalvik. The following flags turn
# off various optimizations known to have issues, but the list may not
# be complete or up to date. (The "arithmetic" optimization can be
# used if you are only targeting Android 2.0 or later.) Make sure you
# test thoroughly if you go this route.
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-optimizationpasses 5
-allowaccessmodification
-dontpreverify
# The remainder of this file is identical to the non-optimized version
# of the Proguard configuration file (except that the other file has
# flags to turn off optimization).
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose
-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
# ADDED
-keep class com.google.zxing.client.android.**
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
native <methods>;
}
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontwarn android.support.**

View file

@ -8,7 +8,7 @@
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt
proguard.config=proguard-android-optimize.txt
# Project target.
target=android-10

View file

@ -24,6 +24,7 @@ import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import com.google.zxing.client.android.PlanarYUVLuminanceSource;
import com.google.zxing.client.android.camera.open.OpenCameraManager;
import java.io.IOException;
@ -74,7 +75,7 @@ public final class CameraManager {
public synchronized void openDriver(SurfaceHolder holder) throws IOException {
Camera theCamera = camera;
if (theCamera == null) {
theCamera = Camera.open();
theCamera = new OpenCameraManager().build().open();
if (theCamera == null) {
throw new IOException();
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2012 ZXing 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 com.google.zxing.client.android.camera.open;
import android.hardware.Camera;
/**
* Default implementation for Android before API 9 / Gingerbread.
*/
final class DefaultOpenCameraInterface implements OpenCameraInterface {
/**
* Calls {@link Camera#open()}.
*/
@Override
public Camera open() {
return Camera.open();
}
}

View file

@ -0,0 +1,66 @@
/*
* Copyright (C) 2012 ZXing 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 com.google.zxing.client.android.camera.open;
import android.annotation.TargetApi;
import android.hardware.Camera;
import android.util.Log;
/**
* Implementation for Android API 9 (Gingerbread) and later. This opens up the possibility of accessing
* front cameras, and rotated cameras.
*/
@TargetApi(9)
public final class GingerbreadOpenCameraInterface implements OpenCameraInterface {
private static final String TAG = "GingerbreadOpenCamera";
/**
* Opens a rear-facing camera with {@link Camera#open(int)}, if one exists, or opens camera 0.
*/
@Override
public Camera open() {
int numCameras = Camera.getNumberOfCameras();
if (numCameras == 0) {
Log.w(TAG, "No cameras!");
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) {
Log.i(TAG, "Opening camera #" + index);
camera = Camera.open(index);
} else {
Log.i(TAG, "No camera facing back; returning camera #0");
camera = Camera.open(0);
}
return camera;
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (C) 2012 ZXing 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 com.google.zxing.client.android.camera.open;
import android.hardware.Camera;
/**
* Provides an abstracted means to open a {@link Camera}. The API changes over Android API versions and
* this allows the app to use newer API methods while retaining backwards-compatible behavior.
*/
public interface OpenCameraInterface {
Camera open();
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 2012 ZXing 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 com.google.zxing.client.android.camera.open;
import com.google.zxing.client.android.common.PlatformSupportManager;
/**
* Selects an appropriate implementation of {@link OpenCameraInterface} based on the device's
* API level.
*/
public final class OpenCameraManager extends PlatformSupportManager<OpenCameraInterface> {
public OpenCameraManager() {
super(OpenCameraInterface.class, new DefaultOpenCameraInterface());
addImplementationClass(9, "com.google.zxing.client.android.camera.open.GingerbreadOpenCameraInterface");
}
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (C) 2012 ZXing 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 com.google.zxing.client.android.common;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* <p>Sometimes the application wants to access advanced functionality exposed by Android APIs that are only available
* in later versions of the platform. While {@link 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
*/
public abstract class PlatformSupportManager<T> {
private static final String TAG = PlatformSupportManager.class.getSimpleName();
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);
Log.i(TAG, "Using implementation " + clazz + " of " + managedInterface + " for SDK " + minVersion);
return clazz.getConstructor().newInstance();
} catch (ClassNotFoundException cnfe) {
Log.w(TAG, cnfe);
} catch (IllegalAccessException iae) {
Log.w(TAG, iae);
} catch (InstantiationException ie) {
Log.w(TAG, ie);
} catch (NoSuchMethodException nsme) {
Log.w(TAG, nsme);
} catch (InvocationTargetException ite) {
Log.w(TAG, ite);
}
}
}
Log.i(TAG, "Using default implementation " + defaultImplementation.getClass() + " of " + managedInterface);
return defaultImplementation;
}
}