mirror of
https://github.com/zxing/zxing.git
synced 2024-11-09 20:44:03 -08:00
Initial checkin of RIM client from LifeMarks, after initial refactorings and style changes, etc. May still need work.
git-svn-id: https://zxing.googlecode.com/svn/trunk@546 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
3a1d1f1850
commit
c58ae8b68d
4
AUTHORS
4
AUTHORS
|
@ -8,7 +8,9 @@ Christian Brunschen (Google)
|
||||||
Daniel Switkin (Google)
|
Daniel Switkin (Google)
|
||||||
David Albert (Bug Labs)
|
David Albert (Bug Labs)
|
||||||
John Connolly (Bug Labs)
|
John Connolly (Bug Labs)
|
||||||
|
Joseph Wain (Google)
|
||||||
Matthew Schulkind (Google)
|
Matthew Schulkind (Google)
|
||||||
|
Matt York (LifeMarks)
|
||||||
Paul Hackenberger
|
Paul Hackenberger
|
||||||
Sean Owen (Google)
|
Sean Owen (Google)
|
||||||
Vince Francis
|
Vince Francis (LifeMarks)
|
||||||
|
|
67
rim/src/com/google/zxing/client/rim/AboutScreen.java
Normal file
67
rim/src/com/google/zxing/client/rim/AboutScreen.java
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim;
|
||||||
|
|
||||||
|
import net.rim.device.api.ui.Field;
|
||||||
|
import net.rim.device.api.ui.FieldChangeListener;
|
||||||
|
import net.rim.device.api.ui.Manager;
|
||||||
|
import net.rim.device.api.ui.Screen;
|
||||||
|
import net.rim.device.api.ui.Ui;
|
||||||
|
import net.rim.device.api.ui.UiEngine;
|
||||||
|
import net.rim.device.api.ui.DrawStyle;
|
||||||
|
import net.rim.device.api.ui.component.ButtonField;
|
||||||
|
import net.rim.device.api.ui.component.LabelField;
|
||||||
|
import net.rim.device.api.ui.container.MainScreen;
|
||||||
|
import net.rim.device.api.ui.container.VerticalFieldManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen used to display the application 'about' information.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
final class AboutScreen extends MainScreen {
|
||||||
|
|
||||||
|
AboutScreen() {
|
||||||
|
setTitle(new LabelField("ZXing - About", DrawStyle.ELLIPSIS | USE_ALL_WIDTH));
|
||||||
|
Manager vfm = new VerticalFieldManager(FIELD_HCENTER);
|
||||||
|
Field title = new LabelField("ZXing - BlackBerry Client", FIELD_HCENTER);
|
||||||
|
Field uri = new LabelField("http://code.google.com/p/zxing/", FIELD_HCENTER);
|
||||||
|
vfm.add(title);
|
||||||
|
vfm.add(uri);
|
||||||
|
Field okButton = new ButtonField("OK", FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
okButton.setChangeListener(new ButtonListener(this));
|
||||||
|
vfm.add(okButton);
|
||||||
|
add(vfm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to close the screen when the ok button is pressed.
|
||||||
|
*/
|
||||||
|
private static class ButtonListener implements FieldChangeListener {
|
||||||
|
private final Screen screen;
|
||||||
|
private ButtonListener(Screen screen) {
|
||||||
|
this.screen = screen;
|
||||||
|
}
|
||||||
|
public void fieldChanged(Field field, int context) {
|
||||||
|
UiEngine ui = Ui.getUiEngine();
|
||||||
|
ui.popScreen(screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim;
|
||||||
|
|
||||||
|
import com.google.zxing.client.rim.util.Log;
|
||||||
|
import net.rim.device.api.applicationcontrol.ApplicationPermissions;
|
||||||
|
import net.rim.device.api.applicationcontrol.ApplicationPermissionsManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the necessary permissions for the application.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
final class AppPermissionsManager {
|
||||||
|
|
||||||
|
private static final ApplicationPermissionsManager apm = ApplicationPermissionsManager.getInstance();
|
||||||
|
|
||||||
|
private AppPermissionsManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the required application permissions. Currently the required permissions are
|
||||||
|
* event injection (sending system level key strokes to other running applications) and
|
||||||
|
* accessing files (accessing the file when a qrcode image is saved to the file system).
|
||||||
|
*/
|
||||||
|
static void setPermissions() {
|
||||||
|
setPermission(ApplicationPermissions.PERMISSION_EVENT_INJECTOR);
|
||||||
|
setPermission(ApplicationPermissions.PERMISSION_FILE_API);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean setPermission(int permission) {
|
||||||
|
boolean updatedPermissions = false;
|
||||||
|
ApplicationPermissions ap = apm.getApplicationPermissions();
|
||||||
|
if (ap.containsPermissionKey(permission)) {
|
||||||
|
int eventInjectorPermission = ap.getPermission(permission);
|
||||||
|
Log.info("permission (" + permission + "): " + eventInjectorPermission);
|
||||||
|
if (eventInjectorPermission != ApplicationPermissions.VALUE_ALLOW) {
|
||||||
|
Log.info("Setting permission to VALUE_ALLOW.");
|
||||||
|
ap.addPermission(permission);
|
||||||
|
updatedPermissions = apm.invokePermissionsRequest(ap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.info("Setting permission (" + permission + ") to VALUE_ALLOW.");
|
||||||
|
ap.addPermission(permission);
|
||||||
|
updatedPermissions = apm.invokePermissionsRequest(ap);
|
||||||
|
}
|
||||||
|
Log.info("updatedPermissions: " + updatedPermissions);
|
||||||
|
return updatedPermissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
213
rim/src/com/google/zxing/client/rim/Camera.java
Normal file
213
rim/src/com/google/zxing/client/rim/Camera.java
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim;
|
||||||
|
|
||||||
|
import com.google.zxing.client.rim.util.Log;
|
||||||
|
import net.rim.blackberry.api.invoke.CameraArguments;
|
||||||
|
import net.rim.blackberry.api.invoke.Invoke;
|
||||||
|
import net.rim.device.api.system.Characters;
|
||||||
|
import net.rim.device.api.system.EventInjector;
|
||||||
|
import net.rim.device.api.ui.UiApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton used to control access to the camera.
|
||||||
|
* Unfortunatly, the Camera API only allows invoking the camera.
|
||||||
|
*
|
||||||
|
* Note: This code still contains experimental code to determine and set the camera resolution by
|
||||||
|
* using system level key events, but didn't not function reliably and is not used.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
final class Camera {
|
||||||
|
|
||||||
|
/** milliseconds to wait before starting key strokes */
|
||||||
|
private static final int INITIALIZATION_TIME_MS = 500; // simulator seems to need >= 500
|
||||||
|
private static final int KEY_PAUSE_TIME_MS = 100; // simulator seems to need >= 100
|
||||||
|
|
||||||
|
private static Camera instance;
|
||||||
|
|
||||||
|
/** Attempting to set camera resolution is disabled. */
|
||||||
|
private final boolean setResolution = false;
|
||||||
|
|
||||||
|
private Camera() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the single instance of the camera.
|
||||||
|
*/
|
||||||
|
static Camera getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new Camera();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the blackberry camera application.
|
||||||
|
*/
|
||||||
|
void invoke() {
|
||||||
|
Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, new CameraArguments());
|
||||||
|
if (setResolution) {
|
||||||
|
sleep(INITIALIZATION_TIME_MS);
|
||||||
|
setMinResolution();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exits the blackberry camera application.
|
||||||
|
*/
|
||||||
|
void exit() {
|
||||||
|
if (setResolution) {
|
||||||
|
setMaxResolution(); // for now, we dont know the original resolution setting. Assume it was max res.
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
}
|
||||||
|
sleep(3000); // this sleep is needed for the esc to be processed(3000 originally)
|
||||||
|
UiApplication app = UiApplication.getUiApplication();
|
||||||
|
if (app != null) {
|
||||||
|
Log.info("active app: " + app.getClass().getName());
|
||||||
|
if (app.isForeground()) {
|
||||||
|
Log.info("Lifemarks is the foreground app.");
|
||||||
|
} else {
|
||||||
|
Log.info("Lifemarks is not the foreground app. Attempt to close camera.");
|
||||||
|
keyUpAndDown(Characters.ESCAPE); // need two (no timeout in between esc key presses seems to work best)
|
||||||
|
keyUpAndDown(Characters.ESCAPE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.error("??? app is null ???");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the camera resolution to it's minimum.
|
||||||
|
* Note: currently disabled.
|
||||||
|
*/
|
||||||
|
private static void setMaxResolution() {
|
||||||
|
Log.info("Setting resolution to max.");
|
||||||
|
accessResolutionMenuAfterSave();
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN);
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN); // min res
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
trackBallClick(); // out of res menu
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
trackBallClick(); // into res menu
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_UP);
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_UP); // max res
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
trackBallClick(); // out of res menu
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.ESCAPE); // out of options
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
trackBallClick(); // yes to changes, even if there werent really any!
|
||||||
|
Log.info("Finished setting resolution to max.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the camera resolution to it's maximum.
|
||||||
|
* Note: currently disabled.
|
||||||
|
*/
|
||||||
|
private static void setMinResolution() {
|
||||||
|
Log.info("Setting resolution to min.");
|
||||||
|
accessResolutionMenu();
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_UP);
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_UP); // max res
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
trackBallClick(); // out of res menu
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
trackBallClick(); // into res menu
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN);
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN); // min res
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
trackBallClick(); // out of res menu
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.ESCAPE); // out of options
|
||||||
|
trackBallClick(); // yes to changes, even if there werent really any!
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void accessResolutionMenu() {
|
||||||
|
keyUpAndDown(Characters.CONTROL_MENU);
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN);
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
trackBallClick();
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN);
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN);
|
||||||
|
sleep(KEY_PAUSE_TIME_MS);
|
||||||
|
trackBallClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void accessResolutionMenuAfterSave() {
|
||||||
|
keyUpAndDown(Characters.CONTROL_MENU);
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN, 6, 0); // seems to be down 6 items on bb and 4 on simulator
|
||||||
|
trackBallClick();
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN);
|
||||||
|
keyUpAndDown(Characters.CONTROL_DOWN);
|
||||||
|
trackBallClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts the current thread to sleep for a given amount of time.
|
||||||
|
*/
|
||||||
|
private static void sleep(int time) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(time);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
// continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void trackBallClick() {
|
||||||
|
EventInjector.invokeEvent(
|
||||||
|
new EventInjector.NavigationEvent(EventInjector.NavigationEvent.NAVIGATION_CLICK, 0, 0, 1));
|
||||||
|
EventInjector.invokeEvent(
|
||||||
|
new EventInjector.NavigationEvent(EventInjector.NavigationEvent.NAVIGATION_UNCLICK, 0, 0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends system level key events a given number of times with the given delay between them.
|
||||||
|
*/
|
||||||
|
private static void keyUpAndDown(char character, int times, int delay) {
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
keyUpAndDown(character);
|
||||||
|
if (delay > 0) {
|
||||||
|
sleep(delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends one system level key event.
|
||||||
|
*/
|
||||||
|
private static void keyUpAndDown(char character) {
|
||||||
|
EventInjector.invokeEvent(new EventInjector.KeyEvent(EventInjector.KeyEvent.KEY_DOWN, character, 0, 1));
|
||||||
|
EventInjector.invokeEvent(new EventInjector.KeyEvent(EventInjector.KeyEvent.KEY_UP, character, 0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
65
rim/src/com/google/zxing/client/rim/HelpScreen.java
Normal file
65
rim/src/com/google/zxing/client/rim/HelpScreen.java
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim;
|
||||||
|
|
||||||
|
import net.rim.device.api.ui.DrawStyle;
|
||||||
|
import net.rim.device.api.ui.Field;
|
||||||
|
import net.rim.device.api.ui.FieldChangeListener;
|
||||||
|
import net.rim.device.api.ui.Screen;
|
||||||
|
import net.rim.device.api.ui.Ui;
|
||||||
|
import net.rim.device.api.ui.UiEngine;
|
||||||
|
import net.rim.device.api.ui.Manager;
|
||||||
|
import net.rim.device.api.ui.component.ButtonField;
|
||||||
|
import net.rim.device.api.ui.component.LabelField;
|
||||||
|
import net.rim.device.api.ui.container.MainScreen;
|
||||||
|
import net.rim.device.api.ui.container.VerticalFieldManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen used to display the application help information.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
final class HelpScreen extends MainScreen {
|
||||||
|
|
||||||
|
HelpScreen() {
|
||||||
|
setTitle(new LabelField("ZXing - Help", DrawStyle.ELLIPSIS | USE_ALL_WIDTH));
|
||||||
|
Manager vfm = new VerticalFieldManager(FIELD_HCENTER);
|
||||||
|
Field aboutText = new LabelField("help info...", FIELD_HCENTER);
|
||||||
|
vfm.add(aboutText);
|
||||||
|
Field okButton = new ButtonField("OK", FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
okButton.setChangeListener(new ButtonListener(this));
|
||||||
|
vfm.add(okButton);
|
||||||
|
add(vfm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the screen when the OK button is pressed.
|
||||||
|
*/
|
||||||
|
private static class ButtonListener implements FieldChangeListener {
|
||||||
|
private final Screen screen;
|
||||||
|
private ButtonListener(Screen screen) {
|
||||||
|
this.screen = screen;
|
||||||
|
}
|
||||||
|
public void fieldChanged(Field field, int context) {
|
||||||
|
UiEngine ui = Ui.getUiEngine();
|
||||||
|
ui.popScreen(screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
81
rim/src/com/google/zxing/client/rim/HistoryScreen.java
Normal file
81
rim/src/com/google/zxing/client/rim/HistoryScreen.java
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim;
|
||||||
|
|
||||||
|
import com.google.zxing.client.rim.persistence.history.DecodeHistory;
|
||||||
|
import com.google.zxing.client.rim.persistence.history.DecodeHistoryItem;
|
||||||
|
import com.google.zxing.client.rim.util.Log;
|
||||||
|
import net.rim.blackberry.api.browser.Browser;
|
||||||
|
import net.rim.blackberry.api.browser.BrowserSession;
|
||||||
|
import net.rim.device.api.ui.DrawStyle;
|
||||||
|
import net.rim.device.api.ui.Field;
|
||||||
|
import net.rim.device.api.ui.FieldChangeListener;
|
||||||
|
import net.rim.device.api.ui.Manager;
|
||||||
|
import net.rim.device.api.ui.FieldLabelProvider;
|
||||||
|
import net.rim.device.api.ui.component.ButtonField;
|
||||||
|
import net.rim.device.api.ui.component.LabelField;
|
||||||
|
import net.rim.device.api.ui.container.MainScreen;
|
||||||
|
import net.rim.device.api.ui.container.VerticalFieldManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen used to display the qrcode decoding history.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
final class HistoryScreen extends MainScreen {
|
||||||
|
|
||||||
|
HistoryScreen() {
|
||||||
|
setTitle(new LabelField("ZXing - History", DrawStyle.ELLIPSIS | USE_ALL_WIDTH));
|
||||||
|
Manager vfm = new VerticalFieldManager(FIELD_HCENTER | VERTICAL_SCROLL);
|
||||||
|
Log.debug("Num history items: " + DecodeHistory.getInstance().getNumItems());
|
||||||
|
DecodeHistory history = DecodeHistory.getInstance();
|
||||||
|
FieldChangeListener itemListener = new ButtonListener();
|
||||||
|
for (int i = 0; i < history.getNumItems(); i++) {
|
||||||
|
DecodeHistoryItem item = history.getItemAt(i);
|
||||||
|
Field labelButton = new ButtonField(item.getURI(), FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
labelButton.setChangeListener(itemListener);
|
||||||
|
vfm.add(labelButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
Field okButton = new ButtonField("OK", FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
okButton.setChangeListener(itemListener);
|
||||||
|
add(vfm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the screen when the OK button is pressed.
|
||||||
|
*/
|
||||||
|
private static class ButtonListener implements FieldChangeListener {
|
||||||
|
public void fieldChanged(Field field, int context) {
|
||||||
|
if (field instanceof ButtonField) {
|
||||||
|
BrowserSession browserSession = Browser.getDefaultSession();
|
||||||
|
browserSession.displayPage(((FieldLabelProvider) field).getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overriding this method removes the save changes prompt
|
||||||
|
*/
|
||||||
|
public boolean onSavePrompt() {
|
||||||
|
setDirty(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,35 +16,36 @@
|
||||||
|
|
||||||
package com.google.zxing.client.rim;
|
package com.google.zxing.client.rim;
|
||||||
|
|
||||||
|
import com.google.zxing.client.rim.util.Log;
|
||||||
import net.rim.device.api.io.file.FileSystemJournal;
|
import net.rim.device.api.io.file.FileSystemJournal;
|
||||||
import net.rim.device.api.io.file.FileSystemJournalEntry;
|
import net.rim.device.api.io.file.FileSystemJournalEntry;
|
||||||
import net.rim.device.api.io.file.FileSystemJournalListener;
|
import net.rim.device.api.io.file.FileSystemJournalListener;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sean Owen (srowen@google.com)
|
* The listener that is fired when an image file is added to the file system.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
*/
|
*/
|
||||||
final class ImageCapturedJournalListener implements FileSystemJournalListener {
|
final class QRCapturedJournalListener implements FileSystemJournalListener {
|
||||||
|
|
||||||
private final ZXingMainScreen screen;
|
private final ZXingLMMainScreen screen;
|
||||||
private long lastUSN;
|
|
||||||
|
|
||||||
ImageCapturedJournalListener(ZXingMainScreen screen) {
|
QRCapturedJournalListener(ZXingLMMainScreen screen) {
|
||||||
this.screen = screen;
|
this.screen = screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fileJournalChanged() {
|
public void fileJournalChanged() {
|
||||||
long nextUSN = FileSystemJournal.getNextUSN();
|
long lookUSN = FileSystemJournal.getNextUSN() - 1; // the last file added to the filesystem
|
||||||
for (long lookUSN = nextUSN - 1; lookUSN >= lastUSN; --lookUSN) {
|
Log.debug("lookUSN: " + lookUSN);
|
||||||
FileSystemJournalEntry entry = FileSystemJournal.getEntry(lookUSN);
|
FileSystemJournalEntry entry = FileSystemJournal.getEntry(lookUSN);
|
||||||
if (entry == null) {
|
if (entry != null && entry.getEvent() == FileSystemJournalEntry.FILE_ADDED) {
|
||||||
break;
|
Log.info("Got file: " + entry.getPath() + " @: " + new Date());
|
||||||
}
|
screen.imageSaved(entry.getPath());
|
||||||
if (entry.getEvent() == FileSystemJournalEntry.FILE_ADDED) {
|
|
||||||
screen.handleFile(entry.getPath());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastUSN = nextUSN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
104
rim/src/com/google/zxing/client/rim/SettingsScreen.java
Normal file
104
rim/src/com/google/zxing/client/rim/SettingsScreen.java
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim;
|
||||||
|
|
||||||
|
import com.google.zxing.client.rim.persistence.AppSettings;
|
||||||
|
import com.google.zxing.client.rim.persistence.history.DecodeHistory;
|
||||||
|
import com.google.zxing.client.rim.util.Log;
|
||||||
|
import net.rim.device.api.ui.Field;
|
||||||
|
import net.rim.device.api.ui.FieldChangeListener;
|
||||||
|
import net.rim.device.api.ui.Manager;
|
||||||
|
import net.rim.device.api.ui.Screen;
|
||||||
|
import net.rim.device.api.ui.Ui;
|
||||||
|
import net.rim.device.api.ui.UiEngine;
|
||||||
|
import net.rim.device.api.ui.DrawStyle;
|
||||||
|
import net.rim.device.api.ui.component.ButtonField;
|
||||||
|
import net.rim.device.api.ui.component.CheckboxField;
|
||||||
|
import net.rim.device.api.ui.component.LabelField;
|
||||||
|
import net.rim.device.api.ui.container.MainScreen;
|
||||||
|
import net.rim.device.api.ui.container.VerticalFieldManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Screen used to change application settings.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
final class SettingsScreen extends MainScreen {
|
||||||
|
|
||||||
|
private boolean changes;
|
||||||
|
private final AppSettings settings;
|
||||||
|
private final CheckboxField camResMsgCheckBox;
|
||||||
|
|
||||||
|
SettingsScreen() {
|
||||||
|
setTitle(new LabelField("ZXing - Settings", DrawStyle.ELLIPSIS | USE_ALL_WIDTH));
|
||||||
|
Manager vfm = new VerticalFieldManager(FIELD_HCENTER);
|
||||||
|
|
||||||
|
settings = AppSettings.getInstance();
|
||||||
|
Boolean cameraResMsgSetting = settings.getBooleanItem(AppSettings.SETTING_CAM_RES_MSG);
|
||||||
|
boolean cameraResMsgSettingBool = (cameraResMsgSetting != null) && cameraResMsgSetting.booleanValue();
|
||||||
|
// 0
|
||||||
|
camResMsgCheckBox = new CheckboxField("Don't show camera resolution message", cameraResMsgSettingBool);
|
||||||
|
camResMsgCheckBox.setChangeListener(new ButtonListener(this));
|
||||||
|
vfm.add(camResMsgCheckBox);
|
||||||
|
|
||||||
|
// 1
|
||||||
|
Field clearHistoryButton = new ButtonField("Clear History",FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
clearHistoryButton.setChangeListener(new ButtonListener(this));
|
||||||
|
vfm.add(clearHistoryButton);
|
||||||
|
|
||||||
|
// 2
|
||||||
|
Field okButton = new ButtonField("OK", FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
okButton.setChangeListener(new ButtonListener(this));
|
||||||
|
vfm.add(okButton);
|
||||||
|
|
||||||
|
add(vfm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for button clicks and executes the appropriate action.
|
||||||
|
*/
|
||||||
|
private final class ButtonListener implements FieldChangeListener {
|
||||||
|
private final Screen screen;
|
||||||
|
private ButtonListener(Screen screen) {
|
||||||
|
this.screen = screen;
|
||||||
|
}
|
||||||
|
public void fieldChanged(Field field, int context) {
|
||||||
|
Log.debug("Field: " + field.getIndex() + " , context: " + context);
|
||||||
|
switch (field.getIndex()) {
|
||||||
|
case 0:
|
||||||
|
settings.addItem(AppSettings.SETTING_CAM_RES_MSG,
|
||||||
|
(camResMsgCheckBox.getChecked()) ? Boolean.TRUE : Boolean.FALSE);
|
||||||
|
changes = true;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// TODO confirm
|
||||||
|
DecodeHistory.getInstance().clear();
|
||||||
|
DecodeHistory.getInstance().persist();
|
||||||
|
case 2: //ok
|
||||||
|
if (changes) {
|
||||||
|
AppSettings.getInstance().persist();
|
||||||
|
}
|
||||||
|
UiEngine ui = Ui.getUiEngine();
|
||||||
|
ui.popScreen(screen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
331
rim/src/com/google/zxing/client/rim/ZXingLMMainScreen.java
Normal file
331
rim/src/com/google/zxing/client/rim/ZXingLMMainScreen.java
Normal file
|
@ -0,0 +1,331 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim;
|
||||||
|
|
||||||
|
import com.google.zxing.DecodeHintType;
|
||||||
|
import com.google.zxing.MonochromeBitmapSource;
|
||||||
|
import com.google.zxing.MultiFormatReader;
|
||||||
|
import com.google.zxing.Reader;
|
||||||
|
import com.google.zxing.ReaderException;
|
||||||
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.client.j2me.LCDUIImageMonochromeBitmapSource;
|
||||||
|
import com.google.zxing.client.rim.persistence.AppSettings;
|
||||||
|
import com.google.zxing.client.rim.persistence.history.DecodeHistory;
|
||||||
|
import com.google.zxing.client.rim.persistence.history.DecodeHistoryItem;
|
||||||
|
import com.google.zxing.client.rim.util.Log;
|
||||||
|
import com.google.zxing.client.rim.util.ReasonableTimer;
|
||||||
|
import com.google.zxing.client.rim.util.URLDecoder;
|
||||||
|
import net.rim.blackberry.api.browser.Browser;
|
||||||
|
import net.rim.blackberry.api.browser.BrowserSession;
|
||||||
|
import net.rim.device.api.ui.DrawStyle;
|
||||||
|
import net.rim.device.api.ui.Field;
|
||||||
|
import net.rim.device.api.ui.FieldChangeListener;
|
||||||
|
import net.rim.device.api.ui.Manager;
|
||||||
|
import net.rim.device.api.ui.UiApplication;
|
||||||
|
import net.rim.device.api.ui.component.ButtonField;
|
||||||
|
import net.rim.device.api.ui.component.Dialog;
|
||||||
|
import net.rim.device.api.ui.component.LabelField;
|
||||||
|
import net.rim.device.api.ui.container.DialogFieldManager;
|
||||||
|
import net.rim.device.api.ui.container.MainScreen;
|
||||||
|
import net.rim.device.api.ui.container.PopupScreen;
|
||||||
|
import net.rim.device.api.ui.container.VerticalFieldManager;
|
||||||
|
|
||||||
|
import javax.microedition.io.Connector;
|
||||||
|
import javax.microedition.io.file.FileConnection;
|
||||||
|
import javax.microedition.lcdui.Image;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main appication menu screen.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
final class ZXingLMMainScreen extends MainScreen {
|
||||||
|
|
||||||
|
private final ZXingUiApplication app;
|
||||||
|
private final QRCapturedJournalListener imageListener;
|
||||||
|
private PopupScreen popup;
|
||||||
|
private final Reader reader;
|
||||||
|
private final Hashtable readerHints;
|
||||||
|
|
||||||
|
ZXingLMMainScreen() {
|
||||||
|
super(DEFAULT_MENU | DEFAULT_CLOSE);
|
||||||
|
setTitle(new LabelField("ZXing", DrawStyle.ELLIPSIS | USE_ALL_WIDTH));
|
||||||
|
setChangeListener(null);
|
||||||
|
|
||||||
|
Manager vfm = new VerticalFieldManager(USE_ALL_WIDTH);
|
||||||
|
FieldChangeListener buttonListener = new ButtonListener();
|
||||||
|
|
||||||
|
//0
|
||||||
|
Field snapButton = new ButtonField("Snap", FIELD_HCENTER | ButtonField.CONSUME_CLICK | USE_ALL_WIDTH);
|
||||||
|
snapButton.setChangeListener(buttonListener);
|
||||||
|
vfm.add(snapButton);
|
||||||
|
|
||||||
|
//1
|
||||||
|
Field historyButton = new ButtonField("History", FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
historyButton.setChangeListener(buttonListener);
|
||||||
|
vfm.add(historyButton);
|
||||||
|
|
||||||
|
//2
|
||||||
|
Field settingsButton = new ButtonField("Settings", FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
settingsButton.setChangeListener(buttonListener);
|
||||||
|
vfm.add(settingsButton);
|
||||||
|
|
||||||
|
//3
|
||||||
|
Field aboutButton = new ButtonField("About", FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
aboutButton.setChangeListener(buttonListener);
|
||||||
|
vfm.add(aboutButton);
|
||||||
|
|
||||||
|
//4
|
||||||
|
Field helpButton = new ButtonField("Help", FIELD_HCENTER | ButtonField.CONSUME_CLICK);
|
||||||
|
helpButton.setChangeListener(buttonListener);
|
||||||
|
vfm.add(helpButton);
|
||||||
|
|
||||||
|
vfm.setChangeListener(null);
|
||||||
|
add(vfm);
|
||||||
|
|
||||||
|
|
||||||
|
app = (ZXingUiApplication) UiApplication.getUiApplication();
|
||||||
|
imageListener = new QRCapturedJournalListener(this);
|
||||||
|
|
||||||
|
reader = new MultiFormatReader();
|
||||||
|
readerHints = new Hashtable(1);
|
||||||
|
readerHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the newly created file. If the file is a jpg image, from the camera, the images is assumed to be
|
||||||
|
* a qrcode and decoding is attempted.
|
||||||
|
*/
|
||||||
|
void imageSaved(String imagePath) {
|
||||||
|
Log.info("Image saved: " + imagePath);
|
||||||
|
app.removeFileSystemJournalListener(imageListener);
|
||||||
|
if (imagePath.endsWith(".jpg") && imagePath.indexOf("IMG") >= 0) // a blackberry camera image file
|
||||||
|
{
|
||||||
|
Log.info("imageSaved - Got file: " + imagePath);
|
||||||
|
Camera.getInstance().exit();
|
||||||
|
Log.info("camera exit finished");
|
||||||
|
app.requestForeground();
|
||||||
|
|
||||||
|
DialogFieldManager manager = new DialogFieldManager();
|
||||||
|
popup = new PopupScreen(manager);
|
||||||
|
manager.addCustomField(new LabelField("Decoding image..."));
|
||||||
|
|
||||||
|
app.pushScreen(popup); // original
|
||||||
|
Log.info("started progress screen.");
|
||||||
|
|
||||||
|
Runnable fct = new FileConnectionThread(imagePath);
|
||||||
|
Log.info("Starting file connection thread.");
|
||||||
|
app.invokeLater(fct);
|
||||||
|
Log.info("Finished file connection thread.");
|
||||||
|
} else {
|
||||||
|
Log.error("Failed to locate camera image.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the application and persists all required data.
|
||||||
|
*/
|
||||||
|
public void close() {
|
||||||
|
app.removeFileSystemJournalListener(imageListener);
|
||||||
|
DecodeHistory.getInstance().persist();
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is overriden to remove the 'save changes' dialog when exiting.
|
||||||
|
*/
|
||||||
|
public boolean onSavePrompt() {
|
||||||
|
setDirty(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for selected buttons and starts the required screen.
|
||||||
|
*/
|
||||||
|
private final class ButtonListener implements FieldChangeListener {
|
||||||
|
public void fieldChanged(Field field, int context) {
|
||||||
|
Log.debug("*** fieldChanged: " + field.getIndex());
|
||||||
|
switch (field.getIndex()) {
|
||||||
|
case 0: // snap
|
||||||
|
try {
|
||||||
|
app.addFileSystemJournalListener(imageListener);
|
||||||
|
Camera.getInstance().invoke(); // start camera
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Log.error("!!! Problem invoking camera.!!!: " + e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1: // history
|
||||||
|
app.pushScreen(new HistoryScreen());
|
||||||
|
break;
|
||||||
|
case 2: // settings
|
||||||
|
app.pushScreen(new SettingsScreen());
|
||||||
|
break;
|
||||||
|
case 3: //about
|
||||||
|
app.pushScreen(new AboutScreen());
|
||||||
|
break;
|
||||||
|
case 4: //help
|
||||||
|
app.pushScreen(new HelpScreen());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread that decodes the newly created image. If the image is successfully decoded and the data is a URL,
|
||||||
|
* the browser is invoked and pointed to the given URL.
|
||||||
|
*/
|
||||||
|
private final class FileConnectionThread implements Runnable {
|
||||||
|
|
||||||
|
private final String imagePath;
|
||||||
|
|
||||||
|
private FileConnectionThread(String imagePath) {
|
||||||
|
this.imagePath = imagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
FileConnection file = null;
|
||||||
|
InputStream is = null;
|
||||||
|
Image capturedImage = null;
|
||||||
|
try {
|
||||||
|
file = (FileConnection) Connector.open("file://" + imagePath, Connector.READ_WRITE);
|
||||||
|
is = file.openInputStream();
|
||||||
|
capturedImage = Image.createImage(is);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.error("Problem creating image: " + e);
|
||||||
|
removeProgressBar();
|
||||||
|
invalidate();
|
||||||
|
showMessage("An error occured processing the image.");
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
if (is != null) {
|
||||||
|
try {
|
||||||
|
is.close();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file != null && file.exists()) {
|
||||||
|
if (file.isOpen()) {
|
||||||
|
//file.close();
|
||||||
|
}
|
||||||
|
//file.delete();
|
||||||
|
Log.info("Deleted image file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (capturedImage != null) {
|
||||||
|
Log.info("Got image...");
|
||||||
|
MonochromeBitmapSource source = new LCDUIImageMonochromeBitmapSource(capturedImage);
|
||||||
|
Result result;
|
||||||
|
ReasonableTimer decodingTimer = null;
|
||||||
|
try {
|
||||||
|
decodingTimer = new ReasonableTimer();
|
||||||
|
Log.info("Attempting to decode image...");
|
||||||
|
result = reader.decode(source, readerHints);
|
||||||
|
decodingTimer.finished();
|
||||||
|
} catch (ReaderException e) {
|
||||||
|
Log.error("Could not decode image: " + e);
|
||||||
|
decodingTimer.finished();
|
||||||
|
removeProgressBar();
|
||||||
|
invalidate();
|
||||||
|
boolean showResolutionMsg =
|
||||||
|
!AppSettings.getInstance().getBooleanItem(AppSettings.SETTING_CAM_RES_MSG).booleanValue();
|
||||||
|
if (showResolutionMsg) {
|
||||||
|
showMessage("A QR Code was not found in the image. " +
|
||||||
|
"We detected that the decoding process took quite a while. " +
|
||||||
|
"It will be much faster if you decrease your camera's resolution (640x480).");
|
||||||
|
} else {
|
||||||
|
showMessage("A QR Code was not found in the image.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (result != null) {
|
||||||
|
String resultText = result.getText();
|
||||||
|
Log.info("result: " + resultText);
|
||||||
|
if (isURI(resultText)) {
|
||||||
|
resultText = URLDecoder.decode(resultText);
|
||||||
|
removeProgressBar();
|
||||||
|
invalidate();
|
||||||
|
if (!decodingTimer.wasResonableTime() &&
|
||||||
|
!AppSettings.getInstance().getBooleanItem(AppSettings.SETTING_CAM_RES_MSG).booleanValue()) {
|
||||||
|
showMessage("We detected that the decoding process took quite a while. " +
|
||||||
|
"It will be much faster if you decrease your camera's resolution (640x480).");
|
||||||
|
}
|
||||||
|
DecodeHistory.getInstance().addHistoryItem(new DecodeHistoryItem(resultText));
|
||||||
|
invokeBrowser(resultText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
removeProgressBar();
|
||||||
|
invalidate();
|
||||||
|
showMessage("A QR Code was not found in the image.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
removeProgressBar();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quick check to see if the result of decoding the qr code was a valid uri.
|
||||||
|
*/
|
||||||
|
private boolean isURI(String uri) {
|
||||||
|
return uri.startsWith("http://");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes the web browser and browses to the given uri.
|
||||||
|
*/
|
||||||
|
private void invokeBrowser(String uri) {
|
||||||
|
BrowserSession browserSession = Browser.getDefaultSession();
|
||||||
|
browserSession.displayPage(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncronized version of removing progress dialog.
|
||||||
|
* NOTE: All methods accessing the gui that are in seperate threads should syncronize on app.getEventLock()
|
||||||
|
*/
|
||||||
|
private void removeProgressBar() {
|
||||||
|
synchronized (app.getAppEventLock()) {
|
||||||
|
if (popup != null) {
|
||||||
|
app.popScreen(popup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncronized version of showing a message dialog.
|
||||||
|
* NOTE: All methods accessing the gui that are in seperate threads should syncronize on app.getEventLock()
|
||||||
|
*/
|
||||||
|
private void showMessage(String message) {
|
||||||
|
synchronized (app.getAppEventLock()) {
|
||||||
|
Dialog.alert(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,129 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2008 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.rim;
|
|
||||||
|
|
||||||
import com.google.zxing.MonochromeBitmapSource;
|
|
||||||
import com.google.zxing.MultiFormatReader;
|
|
||||||
import com.google.zxing.Reader;
|
|
||||||
import com.google.zxing.ReaderException;
|
|
||||||
import com.google.zxing.Result;
|
|
||||||
import com.google.zxing.client.j2me.LCDUIImageMonochromeBitmapSource;
|
|
||||||
import net.rim.blackberry.api.invoke.CameraArguments;
|
|
||||||
import net.rim.blackberry.api.invoke.Invoke;
|
|
||||||
import net.rim.device.api.system.Characters;
|
|
||||||
import net.rim.device.api.system.EventInjector;
|
|
||||||
import net.rim.device.api.ui.UiApplication;
|
|
||||||
import net.rim.device.api.ui.component.Dialog;
|
|
||||||
import net.rim.device.api.ui.component.LabelField;
|
|
||||||
import net.rim.device.api.ui.container.MainScreen;
|
|
||||||
|
|
||||||
import javax.microedition.io.Connector;
|
|
||||||
import javax.microedition.io.file.FileConnection;
|
|
||||||
import javax.microedition.lcdui.Image;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Sean Owen (srowen@google.com)
|
|
||||||
*/
|
|
||||||
final class ZXingMainScreen extends MainScreen {
|
|
||||||
|
|
||||||
private final ZXingUIApp app;
|
|
||||||
private final ImageCapturedJournalListener captureListener;
|
|
||||||
|
|
||||||
ZXingMainScreen() {
|
|
||||||
setTitle("ZXing Barcode Reader");
|
|
||||||
add(new LabelField("UNDER CONSTRUCTION"));
|
|
||||||
add(new LabelField("1. Press 'Enter' at right to launch the Camera application"));
|
|
||||||
add(new LabelField("2. Configure Camera to capture 640x480 image"));
|
|
||||||
add(new LabelField("3. Take a picture of a barcode"));
|
|
||||||
add(new LabelField("4. If not returned to this application to see result, close Camera application"));
|
|
||||||
app = (ZXingUIApp) UiApplication.getUiApplication();
|
|
||||||
captureListener = new ImageCapturedJournalListener(this);
|
|
||||||
app.addFileSystemJournalListener(captureListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean keyChar(char c, int status, int time) {
|
|
||||||
if (c == Characters.ENTER) {
|
|
||||||
Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, new CameraArguments());
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return super.keyChar(c, status, time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
app.removeFileSystemJournalListener(captureListener);
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showMessage(String msg) {
|
|
||||||
synchronized (app.getAppEventLock()) {
|
|
||||||
Dialog.alert(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleFile(String path) {
|
|
||||||
if (path.endsWith(".jpg") && path.indexOf("IMG") >= 0) {
|
|
||||||
// Get out of camera app
|
|
||||||
EventInjector.invokeEvent(new EventInjector.KeyEvent(EventInjector.KeyEvent.KEY_DOWN, Characters.ESCAPE, 0, 1));
|
|
||||||
EventInjector.invokeEvent(new EventInjector.KeyEvent(EventInjector.KeyEvent.KEY_UP, Characters.ESCAPE, 0, 1));
|
|
||||||
// Try to come to foreground for good measure
|
|
||||||
app.requestForeground();
|
|
||||||
try {
|
|
||||||
FileConnection file = null;
|
|
||||||
InputStream is = null;
|
|
||||||
Image capturedImage;
|
|
||||||
try {
|
|
||||||
file = (FileConnection) Connector.open("file://" + path);
|
|
||||||
is = file.openInputStream();
|
|
||||||
capturedImage = Image.createImage(is);
|
|
||||||
} finally {
|
|
||||||
if (is != null) {
|
|
||||||
try {
|
|
||||||
is.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
// continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (file != null) {
|
|
||||||
try {
|
|
||||||
file.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
// continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MonochromeBitmapSource source = new LCDUIImageMonochromeBitmapSource(capturedImage);
|
|
||||||
Reader reader = new MultiFormatReader();
|
|
||||||
Result result = reader.decode(source);
|
|
||||||
// If decode was successful...
|
|
||||||
try {
|
|
||||||
file.delete();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
// continue
|
|
||||||
}
|
|
||||||
showMessage(result.getText());
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
showMessage(ioe.getMessage());
|
|
||||||
} catch (ReaderException re) {
|
|
||||||
showMessage("Sorry, no barcode was found.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -16,19 +16,29 @@
|
||||||
|
|
||||||
package com.google.zxing.client.rim;
|
package com.google.zxing.client.rim;
|
||||||
|
|
||||||
|
import com.google.zxing.client.rim.persistence.AppSettings;
|
||||||
|
import com.google.zxing.client.rim.persistence.history.DecodeHistory;
|
||||||
import net.rim.device.api.ui.UiApplication;
|
import net.rim.device.api.ui.UiApplication;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sean Owen (srowen@google.com)
|
* Starts the application with the MenuScreen screen on the stack.
|
||||||
|
* As well, the required permissions are requested and the history and app settings are initialized.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
*/
|
*/
|
||||||
public final class ZXingUIApp extends UiApplication {
|
public final class ZXingUiApplication extends UiApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
private ZXingUiApplication() {
|
||||||
new ZXingUIApp().enterEventDispatcher();
|
pushScreen(new ZXingLMMainScreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
ZXingUIApp() {
|
public static void main(String[] args) {
|
||||||
pushScreen(new ZXingMainScreen());
|
AppPermissionsManager.setPermissions();
|
||||||
|
DecodeHistory.getInstance();
|
||||||
|
AppSettings.getInstance();
|
||||||
|
new ZXingUiApplication().enterEventDispatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
100
rim/src/com/google/zxing/client/rim/persistence/AppSettings.java
Normal file
100
rim/src/com/google/zxing/client/rim/persistence/AppSettings.java
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim.persistence;
|
||||||
|
|
||||||
|
import net.rim.device.api.system.PersistentObject;
|
||||||
|
import net.rim.device.api.system.PersistentStore;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton object that represents the persistent application settings data.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
public final class AppSettings {
|
||||||
|
|
||||||
|
public static final String SETTING_CAM_RES_MSG = "setting_cam_res_msg";
|
||||||
|
private static final long ID_LONG = 0x92ac4e8ac35b8aa0L;
|
||||||
|
|
||||||
|
private static AppSettings instance;
|
||||||
|
|
||||||
|
private final PersistentObject store;
|
||||||
|
private final Hashtable settingsItems;
|
||||||
|
|
||||||
|
private AppSettings() {
|
||||||
|
store = PersistentStore.getPersistentObject(ID_LONG);
|
||||||
|
Hashtable temp = (Hashtable) store.getContents();
|
||||||
|
settingsItems = temp == null ? new Hashtable() : temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AppSettings getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new AppSettings();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a setting object.
|
||||||
|
*/
|
||||||
|
public void addItem(String itemName, Object itemValue) {
|
||||||
|
settingsItems.put(itemName, itemValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all settings objects.
|
||||||
|
*/
|
||||||
|
public Hashtable getItems() {
|
||||||
|
return settingsItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a particular settings object by name.
|
||||||
|
*/
|
||||||
|
Object getItem(String itemName) {
|
||||||
|
return settingsItems.get(itemName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a particular boolean type settings object by name.
|
||||||
|
*/
|
||||||
|
public Boolean getBooleanItem(String itemName) {
|
||||||
|
Object value = getItem(itemName);
|
||||||
|
return value instanceof Boolean ? (Boolean) value : Boolean.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of settings.
|
||||||
|
*/
|
||||||
|
public int getNumItems() {
|
||||||
|
return settingsItems.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists the settings to the device.
|
||||||
|
*/
|
||||||
|
public void persist() {
|
||||||
|
synchronized (store) {
|
||||||
|
store.setContents(settingsItems);
|
||||||
|
store.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim.persistence.history;
|
||||||
|
|
||||||
|
import net.rim.device.api.system.PersistentObject;
|
||||||
|
import net.rim.device.api.system.PersistentStore;
|
||||||
|
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton used to persist the history of qrcode URLs decoded by the client.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
public class DecodeHistory {
|
||||||
|
|
||||||
|
private static final long ID_LONG = 0xb7cc76147b48ad0dL;
|
||||||
|
|
||||||
|
private static DecodeHistory instance;
|
||||||
|
|
||||||
|
private final PersistentObject store;
|
||||||
|
private final Vector historyItems;
|
||||||
|
|
||||||
|
private DecodeHistory() {
|
||||||
|
store = PersistentStore.getPersistentObject(ID_LONG);
|
||||||
|
Vector temp = (Vector) store.getContents();
|
||||||
|
historyItems = temp == null ? new Vector() : temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the single instance of this class.
|
||||||
|
*/
|
||||||
|
public static DecodeHistory getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new DecodeHistory();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a history object.
|
||||||
|
*/
|
||||||
|
public void addHistoryItem(DecodeHistoryItem item) {
|
||||||
|
historyItems.addElement(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all history objects.
|
||||||
|
*/
|
||||||
|
public Vector getItems() {
|
||||||
|
return historyItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a particular history object at a given index.
|
||||||
|
*/
|
||||||
|
public DecodeHistoryItem getItemAt(int index) {
|
||||||
|
return (DecodeHistoryItem) historyItems.elementAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of history objects.
|
||||||
|
*/
|
||||||
|
public int getNumItems() {
|
||||||
|
return historyItems.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the history.
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
historyItems.setSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists the history to the device.
|
||||||
|
*/
|
||||||
|
public void persist() {
|
||||||
|
synchronized (store) {
|
||||||
|
store.setContents(historyItems);
|
||||||
|
store.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim.persistence.history;
|
||||||
|
|
||||||
|
import net.rim.device.api.util.Persistable;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single decoded history item that is stored by the decode history.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
public final class DecodeHistoryItem implements Persistable {
|
||||||
|
|
||||||
|
private String date;
|
||||||
|
private String uri;
|
||||||
|
|
||||||
|
private DecodeHistoryItem() {
|
||||||
|
date = new Date().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecodeHistoryItem(String uri) {
|
||||||
|
this();
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(String date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setURI(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getURI() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
83
rim/src/com/google/zxing/client/rim/util/Log.java
Normal file
83
rim/src/com/google/zxing/client/rim/util/Log.java
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim.util;
|
||||||
|
|
||||||
|
import net.rim.device.api.system.EventLogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to write logging messages. When debugging, System.out is used to write to the simulator.
|
||||||
|
* When running on a real device, the EventLogger is used. To access the event log on a real device,
|
||||||
|
* go to the home screen, hold down ALT and type lglg.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
public final class Log {
|
||||||
|
|
||||||
|
private static final String LOG_ID_STRING = "zxing";
|
||||||
|
private static final long LOG_ID_LONG = 0x351e9b79fd52317L;
|
||||||
|
|
||||||
|
/** Used to determine if the log message should be set to System.out */
|
||||||
|
private static final boolean logToSystemOut;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Initializes the logger. Currently set to not log to System.out and log
|
||||||
|
// at the INFO level.
|
||||||
|
EventLogger.register(LOG_ID_LONG, LOG_ID_STRING, EventLogger.VIEWER_STRING);
|
||||||
|
EventLogger.setMinimumLevel(EventLogger.DEBUG_INFO); // set this to change logging level message.
|
||||||
|
logToSystemOut = false; // needs to be false for deployment to blackberry device and true for debuging on simulator.
|
||||||
|
}
|
||||||
|
|
||||||
|
private Log() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the given message at the debug level.
|
||||||
|
*/
|
||||||
|
public static void debug(String message) {
|
||||||
|
EventLogger.logEvent(LOG_ID_LONG, message.getBytes(), EventLogger.DEBUG_INFO);
|
||||||
|
logToSystemOut(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the given message at the info level.
|
||||||
|
*/
|
||||||
|
public static void info(String message) {
|
||||||
|
EventLogger.logEvent(LOG_ID_LONG, message.getBytes(), EventLogger.INFORMATION);
|
||||||
|
logToSystemOut(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the given message at the error level.
|
||||||
|
*/
|
||||||
|
public static void error(String message) {
|
||||||
|
EventLogger.logEvent(LOG_ID_LONG, message.getBytes(), EventLogger.ERROR);
|
||||||
|
logToSystemOut(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the given message to system.out.
|
||||||
|
* This is useful when debugging on the simulator.
|
||||||
|
*/
|
||||||
|
private static void logToSystemOut(String message) {
|
||||||
|
if (logToSystemOut) {
|
||||||
|
System.out.println(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to determine if something happend within a specified amount of time.
|
||||||
|
* For example, if a QR code was decoded in a resonable amount of time.
|
||||||
|
* If not, perhaps the user should lower their camera resolution.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
public final class ReasonableTimer {
|
||||||
|
|
||||||
|
// 2000 too low for qr decoding
|
||||||
|
private static final long DEF_RESONABLE_TIME = 2500; // in ms
|
||||||
|
|
||||||
|
private long reasonableTime;
|
||||||
|
private final long startTime;
|
||||||
|
private long finishTime;
|
||||||
|
|
||||||
|
public ReasonableTimer() {
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
reasonableTime = DEF_RESONABLE_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReasonableTimer(long reasonableTime) {
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
this.reasonableTime = reasonableTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the timing.
|
||||||
|
*/
|
||||||
|
public void finished() {
|
||||||
|
finishTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the timer finished in a reasonable amount of time.
|
||||||
|
*/
|
||||||
|
public boolean wasResonableTime() {
|
||||||
|
return finishTime - startTime <= reasonableTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the reasonable time to the given time
|
||||||
|
*/
|
||||||
|
public void setResonableTime(long reasonableTime) {
|
||||||
|
this.reasonableTime = reasonableTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the reasonable time.
|
||||||
|
*/
|
||||||
|
public long getResonableTime() {
|
||||||
|
return reasonableTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
84
rim/src/com/google/zxing/client/rim/util/URLDecoder.java
Normal file
84
rim/src/com/google/zxing/client/rim/util/URLDecoder.java
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008 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.rim.util;
|
||||||
|
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to decode URL encoded characters.
|
||||||
|
*
|
||||||
|
* This code was contributed by LifeMarks.
|
||||||
|
*
|
||||||
|
* @author Matt York (matt@lifemarks.mobi)
|
||||||
|
*/
|
||||||
|
public final class URLDecoder {
|
||||||
|
|
||||||
|
private URLDecoder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Hashtable decodingMap;
|
||||||
|
static {
|
||||||
|
decodingMap = new Hashtable(37);
|
||||||
|
decodingMap.put("%21", "!");
|
||||||
|
decodingMap.put("%2A", "*");
|
||||||
|
decodingMap.put("%2a", "*");
|
||||||
|
decodingMap.put("%27", "'");
|
||||||
|
decodingMap.put("%28", "(");
|
||||||
|
decodingMap.put("%29", ")");
|
||||||
|
decodingMap.put("%3B", ";");
|
||||||
|
decodingMap.put("%3b", ";");
|
||||||
|
decodingMap.put("%3A", ":");
|
||||||
|
decodingMap.put("%3a", ":");
|
||||||
|
decodingMap.put("%40", "@");
|
||||||
|
decodingMap.put("%26", "&");
|
||||||
|
decodingMap.put("%3D", "=");
|
||||||
|
decodingMap.put("%3d", "=");
|
||||||
|
decodingMap.put("%3B", "+");
|
||||||
|
decodingMap.put("%3b", "+");
|
||||||
|
decodingMap.put("%24", "$");
|
||||||
|
decodingMap.put("%2C", "`");
|
||||||
|
decodingMap.put("%2c", "`");
|
||||||
|
decodingMap.put("%2F", "/");
|
||||||
|
decodingMap.put("%2f", "/");
|
||||||
|
decodingMap.put("%3F", "?");
|
||||||
|
decodingMap.put("%3f", "?");
|
||||||
|
decodingMap.put("%25", "%");
|
||||||
|
decodingMap.put("%23", "#");
|
||||||
|
decodingMap.put("%5B", "[");
|
||||||
|
decodingMap.put("%5b", "[");
|
||||||
|
decodingMap.put("%5D", "]");
|
||||||
|
decodingMap.put("%5d", "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String decode(String uri) {
|
||||||
|
Log.info("Original uri: " + uri);
|
||||||
|
if (uri.indexOf('%') >= 0) { // skip this if no encoded chars
|
||||||
|
Enumeration keys = decodingMap.keys();
|
||||||
|
while (keys.hasMoreElements()) {
|
||||||
|
String encodedChar = (String) keys.nextElement();
|
||||||
|
int encodedCharIndex = uri.indexOf(encodedChar);
|
||||||
|
while (encodedCharIndex != -1) {
|
||||||
|
uri = uri.substring(0, encodedCharIndex) + decodingMap.get(encodedChar) + uri.substring(encodedCharIndex + encodedChar.length());
|
||||||
|
encodedCharIndex = uri.indexOf(encodedChar, encodedCharIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.info("Final URI: " + uri);
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue