Potrzebuje pomocy przy połączeniu dwóch aplikacji napisanych na androida.
Z kolegą stworzyliśmy dwie oddzielne aplikacje i z tych dwóch chcemy stworzyć jedną. Problem próbowałem rozwiązać następująco:
-moją aplikacje dołączyłem do aplikacji kolegi jako bibliotekę (przez Properties->Android->w sekcji Library dołaczenie aplikacji jako biblioteki).
Pojawił się problem z uruchomieniem dołączonej aplikacji jako biblioteki.
Aplikacja ma po wciśnięciu przycisku wywoływać skaner OCR(aplikacja jako biblioteka) wykorzystujący tesseract.
W MainActivity.java wywołuję przycisk:
public void oceruj(View view)
{
Intent intent = new Intent(getApplicationContext(), edu.sfsu.cs.orange.ocr.CaptureActivity.class);
startActivity(intent);
}
Który ma za zadanie uruchomić klasę CaptureActivity.java z pakietu edu.sfsu.cs.orange.ocr
package edu.sfsu.cs.orange.ocr;
import edu.sfsu.cs.orange.ocr.BeepManager;
import com.googlecode.tesseract.android.TessBaseAPI;
import edu.sfsu.cs.orange.ocr.camera.CameraManager;
import edu.sfsu.cs.orange.ocr.camera.ShutterButton;
import edu.sfsu.cs.orange.ocr.HelpActivity;
import edu.sfsu.cs.orange.ocr.OcrResult;
import edu.sfsu.cs.orange.ocr.PreferencesActivity;
import edu.sfsu.cs.orange.ocr.language.LanguageCodeHelper;
import edu.sfsu.cs.orange.ocr.language.TranslateAsyncTask;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.text.SpannableStringBuilder;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
/**
* This activity opens the camera and does the actual scanning on a background thread. It draws a
* viewfinder to help the user place the barcode correctly, shows feedback as the image processing
* is happening, and then overlays the results when a scan is successful.
*
* The code for this class was adapted from the ZXing project: http://code.google.com/p/zxing/
*/
public final class CaptureActivity extends Activity implements SurfaceHolder.Callback,
ShutterButton.OnShutterButtonListener {
private static final String TAG = CaptureActivity.class.getSimpleName();
// Note: These constants will be overridden by any default values defined in preferences.xml.
/** ISO 639-3 language code indicating the default recognition language. */
public static final String DEFAULT_SOURCE_LANGUAGE_CODE = "eng";
/** ISO 639-1 language code indicating the default target language for translation. */
public static final String DEFAULT_TARGET_LANGUAGE_CODE = "es";
/** The default online machine translation service to use. */
public static final String DEFAULT_TRANSLATOR = "Bing Translator";
/** The default OCR engine to use. */
public static final String DEFAULT_OCR_ENGINE_MODE = "Tesseract";
/** The default page segmentation mode to use. */
public static final String DEFAULT_PAGE_SEGMENTATION_MODE = "Auto";
/** Whether to use autofocus by default. */
public static final boolean DEFAULT_TOGGLE_AUTO_FOCUS = true;
/** Whether to beep by default when the shutter button is pressed. */
public static final boolean DEFAULT_TOGGLE_BEEP = true;
/** Whether to initially show a looping, real-time OCR display. */
public static final boolean DEFAULT_TOGGLE_CONTINUOUS = false;
/** Whether to initially reverse the image returned by the camera. */
public static final boolean DEFAULT_TOGGLE_REVERSED_IMAGE = false;
/** Whether to enable the use of online translation services be default. */
public static final boolean DEFAULT_TOGGLE_TRANSLATION = true;
/** Whether the light should be initially activated by default. */
public static final boolean DEFAULT_TOGGLE_LIGHT = false;
/** Flag to display the real-time recognition results at the top of the scanning screen. */
private static final boolean CONTINUOUS_DISPLAY_RECOGNIZED_TEXT = true;
/** Flag to display recognition-related statistics on the scanning screen. */
private static final boolean CONTINUOUS_DISPLAY_METADATA = true;
/** Flag to enable display of the on-screen shutter button. */
private static final boolean DISPLAY_SHUTTER_BUTTON = true;
/** Languages for which Cube data is available. */
static final String[] CUBE_SUPPORTED_LANGUAGES = {
"ara", // Arabic
"eng", // English
"hin" // Hindi
};
/** Languages that require Cube, and cannot run using Tesseract. */
private static final String[] CUBE_REQUIRED_LANGUAGES = {
"ara" // Arabic
};
/** Resource to use for data file downloads. */
static final String DOWNLOAD_BASE = "http://tesseract-ocr.googlecode.com/files/";
/** Download filename for orientation and script detection (OSD) data. */
static final String OSD_FILENAME = "tesseract-ocr-3.01.osd.tar";
/** Destination filename for orientation and script detection (OSD) data. */
static final String OSD_FILENAME_BASE = "osd.traineddata";
/** Minimum mean confidence score necessary to not reject single-shot OCR result. Currently unused. */
static final int MINIMUM_MEAN_CONFIDENCE = 0; // 0 means don't reject any scored results
// Context menu
private static final int SETTINGS_ID = Menu.FIRST;
private static final int ABOUT_ID = Menu.FIRST + 1;
// Options menu, for copy to clipboard
private static final int OPTIONS_COPY_RECOGNIZED_TEXT_ID = Menu.FIRST;
private static final int OPTIONS_COPY_TRANSLATED_TEXT_ID = Menu.FIRST + 1;
private static final int OPTIONS_SHARE_RECOGNIZED_TEXT_ID = Menu.FIRST + 2;
private static final int OPTIONS_SHARE_TRANSLATED_TEXT_ID = Menu.FIRST + 3;
private CameraManager cameraManager;
private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private TextView statusViewBottom;
private TextView statusViewTop;
private TextView ocrResultView;
private TextView translationView;
private View cameraButtonView;
private View resultView;
private View progressView;
private OcrResult lastResult;
private Bitmap lastBitmap;
private boolean hasSurface;
private BeepManager beepManager;
private TessBaseAPI baseApi; // Java interface for the Tesseract OCR engine
private String sourceLanguageCodeOcr; // ISO 639-3 language code
private String sourceLanguageReadable; // Language name, for example, "English"
private String sourceLanguageCodeTranslation; // ISO 639-1 language code
private String targetLanguageCodeTranslation; // ISO 639-1 language code
private String targetLanguageReadable; // Language name, for example, "English"
private int pageSegmentationMode = TessBaseAPI.PSM_AUTO;
private int ocrEngineMode = TessBaseAPI.OEM_TESSERACT_ONLY;
private String characterBlacklist;
private String characterWhitelist;
private ShutterButton shutterButton;
// private ToggleButton torchButton;
private boolean isTranslationActive; // Whether we want to show translations
private boolean isContinuousModeActive; // Whether we are doing OCR in continuous mode
private SharedPreferences prefs;
private OnSharedPreferenceChangeListener listener;
private ProgressDialog dialog; // for initOcr - language download & unzip
private ProgressDialog indeterminateDialog; // also for initOcr - init OCR engine
private boolean isEngineReady;
private boolean isPaused;
private static boolean isFirstLaunch; // True if this is the first time the app is being run
Handler getHandler() {
return handler;
}
TessBaseAPI getBaseApi() {
return baseApi;
}
CameraManager getCameraManager() {
return cameraManager;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
checkFirstLaunch();
if (isFirstLaunch) {
setDefaultPreferences();
}
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.capture);
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
cameraButtonView = findViewById(R.id.camera_button_view);
resultView = findViewById(R.id.result_view);
statusViewBottom = (TextView) findViewById(R.id.status_view_bottom);
registerForContextMenu(statusViewBottom);
statusViewTop = (TextView) findViewById(R.id.status_view_top);
registerForContextMenu(statusViewTop);
handler = null;
lastResult = null;
hasSurface = false;
beepManager = new BeepManager(this);
// Camera shutter button
if (DISPLAY_SHUTTER_BUTTON) {
shutterButton = (ShutterButton) findViewById(R.id.shutter_button);
shutterButton.setOnShutterButtonListener(this);
}
ocrResultView = (TextView) findViewById(R.id.ocr_result_text_view);
registerForContextMenu(ocrResultView);
translationView = (TextView) findViewById(R.id.translation_text_view);
registerForContextMenu(translationView);
progressView = (View) findViewById(R.id.indeterminate_progress_indicator_view);
cameraManager = new CameraManager(getApplication());
viewfinderView.setCameraManager(cameraManager);
// Set listener to change the size of the viewfinder rectangle.
viewfinderView.setOnTouchListener(new View.OnTouchListener() {
int lastX = -1;
int lastY = -1;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = -1;
lastY = -1;
return true;
case MotionEvent.ACTION_MOVE:
int currentX = (int) event.getX();
int currentY = (int) event.getY();
try {
Rect rect = cameraManager.getFramingRect();
final int BUFFER = 50;
final int BIG_BUFFER = 60;
if (lastX >= 0) {
// Adjust the size of the viewfinder rectangle. Check if the touch event occurs in the corner areas first, because the regions overlap.
if (((currentX >= rect.left - BIG_BUFFER && currentX <= rect.left + BIG_BUFFER) || (lastX >= rect.left - BIG_BUFFER && lastX <= rect.left + BIG_BUFFER))
&& ((currentY <= rect.top + BIG_BUFFER && currentY >= rect.top - BIG_BUFFER) || (lastY <= rect.top + BIG_BUFFER && lastY >= rect.top - BIG_BUFFER))) {
// Top left corner: adjust both top and left sides
cameraManager.adjustFramingRect( 2 * (lastX - currentX), 2 * (lastY - currentY));
viewfinderView.removeResultText();
} else if (((currentX >= rect.right - BIG_BUFFER && currentX <= rect.right + BIG_BUFFER) || (lastX >= rect.right - BIG_BUFFER && lastX <= rect.right + BIG_BUFFER))
&& ((currentY <= rect.top + BIG_BUFFER && currentY >= rect.top - BIG_BUFFER) || (lastY <= rect.top + BIG_BUFFER && lastY >= rect.top - BIG_BUFFER))) {
// Top right corner: adjust both top and right sides
cameraManager.adjustFramingRect( 2 * (currentX - lastX), 2 * (lastY - currentY));
viewfinderView.removeResultText();
} else if (((currentX >= rect.left - BIG_BUFFER && currentX <= rect.left + BIG_BUFFER) || (lastX >= rect.left - BIG_BUFFER && lastX <= rect.left + BIG_BUFFER))
&& ((currentY <= rect.bottom + BIG_BUFFER && currentY >= rect.bottom - BIG_BUFFER) || (lastY <= rect.bottom + BIG_BUFFER && lastY >= rect.bottom - BIG_BUFFER))) {
// Bottom left corner: adjust both bottom and left sides
cameraManager.adjustFramingRect(2 * (lastX - currentX), 2 * (currentY - lastY));
viewfinderView.removeResultText();
} else if (((currentX >= rect.right - BIG_BUFFER && currentX <= rect.right + BIG_BUFFER) || (lastX >= rect.right - BIG_BUFFER && lastX <= rect.right + BIG_BUFFER))
&& ((currentY <= rect.bottom + BIG_BUFFER && currentY >= rect.bottom - BIG_BUFFER) || (lastY <= rect.bottom + BIG_BUFFER && lastY >= rect.bottom - BIG_BUFFER))) {
// Bottom right corner: adjust both bottom and right sides
cameraManager.adjustFramingRect(2 * (currentX - lastX), 2 * (currentY - lastY));
viewfinderView.removeResultText();
} else if (((currentX >= rect.left - BUFFER && currentX <= rect.left + BUFFER) || (lastX >= rect.left - BUFFER && lastX <= rect.left + BUFFER))
&& ((currentY <= rect.bottom && currentY >= rect.top) || (lastY <= rect.bottom && lastY >= rect.top))) {
// Adjusting left side: event falls within BUFFER pixels of left side, and between top and bottom side limits
cameraManager.adjustFramingRect(2 * (lastX - currentX), 0);
viewfinderView.removeResultText();
} else if (((currentX >= rect.right - BUFFER && currentX <= rect.right + BUFFER) || (lastX >= rect.right - BUFFER && lastX <= rect.right + BUFFER))
&& ((currentY <= rect.bottom && currentY >= rect.top) || (lastY <= rect.bottom && lastY >= rect.top))) {
// Adjusting right side: event falls within BUFFER pixels of right side, and between top and bottom side limits
cameraManager.adjustFramingRect(2 * (currentX - lastX), 0);
viewfinderView.removeResultText();
} else if (((currentY <= rect.top + BUFFER && currentY >= rect.top - BUFFER) || (lastY <= rect.top + BUFFER && lastY >= rect.top - BUFFER))
&& ((currentX <= rect.right && currentX >= rect.left) || (lastX <= rect.right && lastX >= rect.left))) {
// Adjusting top side: event falls within BUFFER pixels of top side, and between left and right side limits
cameraManager.adjustFramingRect(0, 2 * (lastY - currentY));
viewfinderView.removeResultText();
} else if (((currentY <= rect.bottom + BUFFER && currentY >= rect.bottom - BUFFER) || (lastY <= rect.bottom + BUFFER && lastY >= rect.bottom - BUFFER))
&& ((currentX <= rect.right && currentX >= rect.left) || (lastX <= rect.right && lastX >= rect.left))) {
// Adjusting bottom side: event falls within BUFFER pixels of bottom side, and between left and right side limits
cameraManager.adjustFramingRect(0, 2 * (currentY - lastY));
viewfinderView.removeResultText();
}
}
} catch (NullPointerException e) {
Log.e(TAG, "Framing rect not available", e);
}
v.invalidate();
lastX = currentX;
lastY = currentY;
return true;
case MotionEvent.ACTION_UP:
lastX = -1;
lastY = -1;
return true;
}
return false;
}
});
isEngineReady = false;
}
@Override
protected void onResume() {
super.onResume();
resetStatusView();
String previousSourceLanguageCodeOcr = sourceLanguageCodeOcr;
int previousOcrEngineMode = ocrEngineMode;
retrievePreferences();
// Set up the camera preview surface.
surfaceView = (SurfaceView) findViewById(R.id.preview_view);
surfaceHolder = surfaceView.getHolder();
if (!hasSurface) {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
// Comment out the following block to test non-OCR functions without an SD card
// Do OCR engine initialization, if necessary
boolean doNewInit = (baseApi == null) || !sourceLanguageCodeOcr.equals(previousSourceLanguageCodeOcr) ||
ocrEngineMode != previousOcrEngineMode;
if (doNewInit) {
// Initialize the OCR engine
File storageDirectory = getStorageDirectory();
if (storageDirectory != null) {
initOcrEngine(storageDirectory, sourceLanguageCodeOcr, sourceLanguageReadable);
}
} else {
// We already have the engine initialized, so just start the camera.
resumeOCR();
}
}
/**
* Method to start or restart recognition after the OCR engine has been initialized,
* or after the app regains focus. Sets state related settings and OCR engine parameters,
* and requests camera initialization.
*/
void resumeOCR() {
Log.d(TAG, "resumeOCR()");
// This method is called when Tesseract has already been successfully initialized, so set
// isEngineReady = true here.
isEngineReady = true;
isPaused = false;
if (handler != null) {
handler.resetState();
}
if (baseApi != null) {
baseApi.setPageSegMode(pageSegmentationMode);
baseApi.setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, characterBlacklist);
baseApi.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, characterWhitelist);
}
if (hasSurface) {
// The activity was paused but not stopped, so the surface still exists. Therefore
// surfaceCreated() won't be called, so init the camera here.
initCamera(surfaceHolder);
}
}
/** Called when the shutter button is pressed in continuous mode. */
void onShutterButtonPressContinuous() {
isPaused = true;
handler.stop();
beepManager.playBeepSoundAndVibrate();
if (lastResult != null) {
handleOcrDecode(lastResult);
} else {
Toast toast = Toast.makeText(this, "OCR failed. Please try again.", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP, 0, 0);
toast.show();
resumeContinuousDecoding();
}
}
/** Called to resume recognition after translation in continuous mode. */
@SuppressWarnings("unused")
void resumeContinuousDecoding() {
isPaused = false;
resetStatusView();
setStatusViewForContinuous();
DecodeHandler.resetDecodeState();
handler.resetState();
if (shutterButton != null && DISPLAY_SHUTTER_BUTTON) {
shutterButton.setVisibility(View.VISIBLE);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated()");
if (holder == null) {
Log.e(TAG, "surfaceCreated gave us a null surface");
}
// Only initialize the camera if the OCR engine is ready to go.
if (!hasSurface && isEngineReady) {
Log.d(TAG, "surfaceCreated(): calling initCamera()...");
initCamera(holder);
}
hasSurface = true;
}
/** Initializes the camera and starts the handler to begin previewing. */
private void initCamera(SurfaceHolder surfaceHolder) {
Log.d(TAG, "initCamera()");
if (surfaceHolder == null) {
throw new IllegalStateException("No SurfaceHolder provided");
}
try {
// Open and initialize the camera
cameraManager.openDriver(surfaceHolder);
// Creating the handler starts the preview, which can also throw a RuntimeException.
handler = new CaptureActivityHandler(this, cameraManager, isContinuousModeActive);
} catch (IOException ioe) {
showErrorMessage("Error", "Could not initialize camera. Please try restarting device.");
} catch (RuntimeException e) {
// Barcode Scanner has seen crashes in the wild of this variety:
// java.?lang.?RuntimeException: Fail to connect to camera service
showErrorMessage("Error", "Could not initialize camera. Please try restarting device.");
}
}
@Override
protected void onPause() {
if (handler != null) {
handler.quitSynchronously();
}
// Stop using the camera, to avoid conflicting with other camera-based apps
cameraManager.closeDriver();
if (!hasSurface) {
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.removeCallback(this);
}
super.onPause();
}
void stopHandler() {
if (handler != null) {
handler.stop();
}
}
@Override
protected void onDestroy() {
if (baseApi != null) {
baseApi.end();
}
super.onDestroy();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// First check if we're paused in continuous mode, and if so, just unpause.
if (isPaused) {
Log.d(TAG, "only resuming continuous recognition, not quitting...");
resumeContinuousDecoding();
return true;
}
// Exit the app if we're not viewing an OCR result.
if (lastResult == null) {
setResult(RESULT_CANCELED);
finish();
return true;
} else {
// Go back to previewing in regular OCR mode.
resetStatusView();
if (handler != null) {
handler.sendEmptyMessage(R.id.restart_preview);
}
return true;
}
} else if (keyCode == KeyEvent.KEYCODE_CAMERA) {
if (isContinuousModeActive) {
onShutterButtonPressContinuous();
} else {
handler.hardwareShutterButtonClick();
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_FOCUS) {
// Only perform autofocus if user is not holding down the button.
if (event.getRepeatCount() == 0) {
cameraManager.requestAutoFocus(500L);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// MenuInflater inflater = getMenuInflater();
// inflater.inflate(R.menu.options_menu, menu);
super.onCreateOptionsMenu(menu);
menu.add(0, SETTINGS_ID, 0, "Settings").setIcon(android.R.drawable.ic_menu_preferences);
menu.add(0, ABOUT_ID, 0, "About").setIcon(android.R.drawable.ic_menu_info_details);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
switch (item.getItemId()) {
case SETTINGS_ID: {
intent = new Intent().setClass(this, PreferencesActivity.class);
startActivity(intent);
break;
}
case ABOUT_ID: {
intent = new Intent(this, HelpActivity.class);
intent.putExtra(HelpActivity.REQUESTED_PAGE_KEY, HelpActivity.ABOUT_PAGE);
startActivity(intent);
break;
}
}
return super.onOptionsItemSelected(item);
}
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
/** Sets the necessary language code values for the given OCR language. */
private boolean setSourceLanguage(String languageCode) {
sourceLanguageCodeOcr = languageCode;
sourceLanguageCodeTranslation = LanguageCodeHelper.mapLanguageCode(languageCode);
sourceLanguageReadable = LanguageCodeHelper.getOcrLanguageName(this, languageCode);
return true;
}
/** Sets the necessary language code values for the translation target language. */
private boolean setTargetLanguage(String languageCode) {
targetLanguageCodeTranslation = languageCode;
targetLanguageReadable = LanguageCodeHelper.getTranslationLanguageName(this, languageCode);
return true;
}
/** Finds the proper location on the SD card where we can save files. */
private File getStorageDirectory() {
//Log.d(TAG, "getStorageDirectory(): API level is " + Integer.valueOf(android.os.Build.VERSION.SDK_INT));
String state = null;
try {
state = Environment.getExternalStorageState();
} catch (RuntimeException e) {
Log.e(TAG, "Is the SD card visible?", e);
showErrorMessage("Error", "Required external storage (such as an SD card) is unavailable.");
}
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
// We can read and write the media
// if (Integer.valueOf(android.os.Build.VERSION.SDK_INT) > 7) {
// For Android 2.2 and above
try {
return getExternalFilesDir(Environment.MEDIA_MOUNTED);
} catch (NullPointerException e) {
// We get an error here if the SD card is visible, but full
Log.e(TAG, "External storage is unavailable");
showErrorMessage("Error", "Required external storage (such as an SD card) is full or unavailable.");
}
// } else {
// // For Android 2.1 and below, explicitly give the path as, for example,
// // "/mnt/sdcard/Android/data/edu.sfsu.cs.orange.ocr/files/"
// return new File(Environment.getExternalStorageDirectory().toString() + File.separator +
// "Android" + File.separator + "data" + File.separator + getPackageName() +
// File.separator + "files" + File.separator);
// }
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
Log.e(TAG, "External storage is read-only");
showErrorMessage("Error", "Required external storage (such as an SD card) is unavailable for data storage.");
} else {
// Something else is wrong. It may be one of many other states, but all we need
// to know is we can neither read nor write
Log.e(TAG, "External storage is unavailable");
showErrorMessage("Error", "Required external storage (such as an SD card) is unavailable or corrupted.");
}
return null;
}
/**
* Requests initialization of the OCR engine with the given parameters.
*
* @param storageRoot Path to location of the tessdata directory to use
* @param languageCode Three-letter ISO 639-3 language code for OCR
* @param languageName Name of the language for OCR, for example, "English"
*/
private void initOcrEngine(File storageRoot, String languageCode, String languageName) {
isEngineReady = false;
// Set up the dialog box for the thermometer-style download progress indicator
if (dialog != null) {
dialog.dismiss();
}
dialog = new ProgressDialog(this);
// If we have a language that only runs using Cube, then set the ocrEngineMode to Cube
if (ocrEngineMode != TessBaseAPI.OEM_CUBE_ONLY) {
for (String s : CUBE_REQUIRED_LANGUAGES) {
if (s.equals(languageCode)) {
ocrEngineMode = TessBaseAPI.OEM_CUBE_ONLY;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putString(PreferencesActivity.KEY_OCR_ENGINE_MODE, getOcrEngineModeName()).commit();
}
}
}
// If our language doesn't support Cube, then set the ocrEngineMode to Tesseract
if (ocrEngineMode != TessBaseAPI.OEM_TESSERACT_ONLY) {
boolean cubeOk = false;
for (String s : CUBE_SUPPORTED_LANGUAGES) {
if (s.equals(languageCode)) {
cubeOk = true;
}
}
if (!cubeOk) {
ocrEngineMode = TessBaseAPI.OEM_TESSERACT_ONLY;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putString(PreferencesActivity.KEY_OCR_ENGINE_MODE, getOcrEngineModeName()).commit();
}
}
// Display the name of the OCR engine we're initializing in the indeterminate progress dialog box
indeterminateDialog = new ProgressDialog(this);
indeterminateDialog.setTitle("Please wait");
String ocrEngineModeName = getOcrEngineModeName();
if (ocrEngineModeName.equals("Both")) {
indeterminateDialog.setMessage("Initializing Cube and Tesseract OCR engines for " + languageName + "...");
} else {
indeterminateDialog.setMessage("Initializing " + ocrEngineModeName + " OCR engine for " + languageName + "...");
}
indeterminateDialog.setCancelable(false);
indeterminateDialog.show();
if (handler != null) {
handler.quitSynchronously();
}
// Disable continuous mode if we're using Cube. This will prevent bad states for devices
// with low memory that crash when running OCR with Cube, and prevent unwanted delays.
if (ocrEngineMode == TessBaseAPI.OEM_CUBE_ONLY || ocrEngineMode == TessBaseAPI.OEM_TESSERACT_CUBE_COMBINED) {
Log.d(TAG, "Disabling continuous preview");
isContinuousModeActive = false;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putBoolean(PreferencesActivity.KEY_CONTINUOUS_PREVIEW, false);
}
// Start AsyncTask to install language data and init OCR
baseApi = new TessBaseAPI();
new OcrInitAsyncTask(this, baseApi, dialog, indeterminateDialog, languageCode, languageName, ocrEngineMode)
.execute(storageRoot.toString());
}
/**
* Displays information relating to the result of OCR, and requests a translation if necessary.
*
* @param ocrResult Object representing successful OCR results
* @return True if a non-null result was received for OCR
*/
boolean handleOcrDecode(OcrResult ocrResult) {
lastResult = ocrResult;
// Test whether the result is null
if (ocrResult.getText() == null || ocrResult.getText().equals("")) {
Toast toast = Toast.makeText(this, "OCR failed. Please try again.", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP, 0, 0);
toast.show();
return false;
}
// Turn off capture-related UI elements
shutterButton.setVisibility(View.GONE);
statusViewBottom.setVisibility(View.GONE);
statusViewTop.setVisibility(View.GONE);
cameraButtonView.setVisibility(View.GONE);
viewfinderView.setVisibility(View.GONE);
resultView.setVisibility(View.VISIBLE);
ImageView bitmapImageView = (ImageView) findViewById(R.id.image_view);
lastBitmap = ocrResult.getBitmap();
if (lastBitmap == null) {
bitmapImageView.setImageBitmap(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher));
} else {
bitmapImageView.setImageBitmap(lastBitmap);
}
// Display the recognized text
TextView sourceLanguageTextView = (TextView) findViewById(R.id.source_language_text_view);
sourceLanguageTextView.setText(sourceLanguageReadable);
TextView ocrResultTextView = (TextView) findViewById(R.id.ocr_result_text_view);
ocrResultTextView.setText(ocrResult.getText());
// Crudely scale betweeen 22 and 32 -- bigger font for shorter text
int scaledSize = Math.max(22, 32 - ocrResult.getText().length() / 4);
ocrResultTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, scaledSize);
TextView translationLanguageLabelTextView = (TextView) findViewById(R.id.translation_language_label_text_view);
TextView translationLanguageTextView = (TextView) findViewById(R.id.translation_language_text_view);
TextView translationTextView = (TextView) findViewById(R.id.translation_text_view);
if (isTranslationActive) {
// Handle translation text fields
translationLanguageLabelTextView.setVisibility(View.VISIBLE);
translationLanguageTextView.setText(targetLanguageReadable);
translationLanguageTextView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL), Typeface.NORMAL);
translationLanguageTextView.setVisibility(View.VISIBLE);
// Activate/re-activate the indeterminate progress indicator
translationTextView.setVisibility(View.GONE);
progressView.setVisibility(View.VISIBLE);
setProgressBarVisibility(true);
// Get the translation asynchronously
new TranslateAsyncTask(this, sourceLanguageCodeTranslation, targetLanguageCodeTranslation,
ocrResult.getText()).execute();
} else {
translationLanguageLabelTextView.setVisibility(View.GONE);
translationLanguageTextView.setVisibility(View.GONE);
translationTextView.setVisibility(View.GONE);
progressView.setVisibility(View.GONE);
setProgressBarVisibility(false);
}
return true;
}
/**
* Displays information relating to the results of a successful real-time OCR request.
*
* @param ocrResult Object representing successful OCR results
*/
void handleOcrContinuousDecode(OcrResult ocrResult) {
lastResult = ocrResult;
// Send an OcrResultText object to the ViewfinderView for text rendering
viewfinderView.addResultText(new OcrResultText(ocrResult.getText(),
ocrResult.getWordConfidences(),
ocrResult.getMeanConfidence(),
ocrResult.getBitmapDimensions(),
ocrResult.getRegionBoundingBoxes(),
ocrResult.getTextlineBoundingBoxes(),
ocrResult.getStripBoundingBoxes(),
ocrResult.getWordBoundingBoxes(),
ocrResult.getCharacterBoundingBoxes()));
Integer meanConfidence = ocrResult.getMeanConfidence();
if (CONTINUOUS_DISPLAY_RECOGNIZED_TEXT) {
// Display the recognized text on the screen
statusViewTop.setText(ocrResult.getText());
int scaledSize = Math.max(22, 32 - ocrResult.getText().length() / 4);
statusViewTop.setTextSize(TypedValue.COMPLEX_UNIT_SP, scaledSize);
statusViewTop.setTextColor(Color.BLACK);
statusViewTop.setBackgroundResource(R.color.status_top_text_background);
statusViewTop.getBackground().setAlpha(meanConfidence * (255 / 100));
}
if (CONTINUOUS_DISPLAY_METADATA) {
// Display recognition-related metadata at the bottom of the screen
long recognitionTimeRequired = ocrResult.getRecognitionTimeRequired();
statusViewBottom.setTextSize(14);
statusViewBottom.setText("OCR: " + sourceLanguageReadable + " - Mean confidence: " +
meanConfidence.toString() + " - Time required: " + recognitionTimeRequired + " ms");
}
}
/**
* Version of handleOcrContinuousDecode for failed OCR requests. Displays a failure message.
*
* @param obj Metadata for the failed OCR request.
*/
void handleOcrContinuousDecode(OcrResultFailure obj) {
lastResult = null;
viewfinderView.removeResultText();
// Reset the text in the recognized text box.
statusViewTop.setText("");
if (CONTINUOUS_DISPLAY_METADATA) {
// Color text delimited by '-' as red.
statusViewBottom.setTextSize(14);
CharSequence cs = setSpanBetweenTokens("OCR: " + sourceLanguageReadable + " - OCR failed - Time required: "
+ obj.getTimeRequired() + " ms", "-", new ForegroundColorSpan(0xFFFF0000));
statusViewBottom.setText(cs);
}
}
/**
* Given either a Spannable String or a regular String and a token, apply
* the given CharacterStyle to the span between the tokens.
*
* NOTE: This method was adapted from:
* http://www.androidengineer.com/2010/08/easy-method-for-formatting-android.html
*
* <p>
* For example, {@code setSpanBetweenTokens("Hello ##world##!", "##", new
* ForegroundColorSpan(0xFFFF0000));} will return a CharSequence {@code
* "Hello world!"} with {@code world} in red.
*
*/
private CharSequence setSpanBetweenTokens(CharSequence text, String token,
CharacterStyle... cs) {
// Start and end refer to the points where the span will apply
int tokenLen = token.length();
int start = text.toString().indexOf(token) + tokenLen;
int end = text.toString().indexOf(token, start);
if (start > -1 && end > -1) {
// Copy the spannable string to a mutable spannable string
SpannableStringBuilder ssb = new SpannableStringBuilder(text);
for (CharacterStyle c : cs)
ssb.setSpan(c, start, end, 0);
text = ssb;
}
return text;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (v.equals(ocrResultView)) {
menu.add(Menu.NONE, OPTIONS_COPY_RECOGNIZED_TEXT_ID, Menu.NONE, "Copy recognized text");
menu.add(Menu.NONE, OPTIONS_SHARE_RECOGNIZED_TEXT_ID, Menu.NONE, "Share recognized text");
} else if (v.equals(translationView)){
menu.add(Menu.NONE, OPTIONS_COPY_TRANSLATED_TEXT_ID, Menu.NONE, "Copy translated text");
menu.add(Menu.NONE, OPTIONS_SHARE_TRANSLATED_TEXT_ID, Menu.NONE, "Share translated text");
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
switch (item.getItemId()) {
case OPTIONS_COPY_RECOGNIZED_TEXT_ID:
clipboardManager.setText(ocrResultView.getText());
if (clipboardManager.hasText()) {
Toast toast = Toast.makeText(this, "Text copied.", Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
}
return true;
case OPTIONS_SHARE_RECOGNIZED_TEXT_ID:
Intent shareRecognizedTextIntent = new Intent(android.content.Intent.ACTION_SEND);
shareRecognizedTextIntent.setType("text/plain");
shareRecognizedTextIntent.putExtra(android.content.Intent.EXTRA_TEXT, ocrResultView.getText());
startActivity(Intent.createChooser(shareRecognizedTextIntent, "Share via"));
return true;
case OPTIONS_COPY_TRANSLATED_TEXT_ID:
clipboardManager.setText(translationView.getText());
if (clipboardManager.hasText()) {
Toast toast = Toast.makeText(this, "Text copied.", Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
}
return true;
case OPTIONS_SHARE_TRANSLATED_TEXT_ID:
Intent shareTranslatedTextIntent = new Intent(android.content.Intent.ACTION_SEND);
shareTranslatedTextIntent.setType("text/plain");
shareTranslatedTextIntent.putExtra(android.content.Intent.EXTRA_TEXT, translationView.getText());
startActivity(Intent.createChooser(shareTranslatedTextIntent, "Share via"));
return true;
default:
return super.onContextItemSelected(item);
}
}
/**
* Resets view elements.
*/
private void resetStatusView() {
resultView.setVisibility(View.GONE);
if (CONTINUOUS_DISPLAY_METADATA) {
statusViewBottom.setText("");
statusViewBottom.setTextSize(14);
statusViewBottom.setTextColor(getResources().getColor(R.color.status_text));
statusViewBottom.setVisibility(View.VISIBLE);
}
if (CONTINUOUS_DISPLAY_RECOGNIZED_TEXT) {
statusViewTop.setText("");
statusViewTop.setTextSize(14);
statusViewTop.setVisibility(View.VISIBLE);
}
viewfinderView.setVisibility(View.VISIBLE);
cameraButtonView.setVisibility(View.VISIBLE);
if (DISPLAY_SHUTTER_BUTTON) {
shutterButton.setVisibility(View.VISIBLE);
}
lastResult = null;
viewfinderView.removeResultText();
}
/** Displays a pop-up message showing the name of the current OCR source language. */
void showLanguageName() {
Toast toast = Toast.makeText(this, "OCR: " + sourceLanguageReadable, Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP, 0, 0);
toast.show();
}
/**
* Displays an initial message to the user while waiting for the first OCR request to be
* completed after starting realtime OCR.
*/
void setStatusViewForContinuous() {
viewfinderView.removeResultText();
if (CONTINUOUS_DISPLAY_METADATA) {
statusViewBottom.setText("OCR: " + sourceLanguageReadable + " - waiting for OCR...");
}
}
@SuppressWarnings("unused")
void setButtonVisibility(boolean visible) {
if (shutterButton != null && visible == true && DISPLAY_SHUTTER_BUTTON) {
shutterButton.setVisibility(View.VISIBLE);
} else if (shutterButton != null) {
shutterButton.setVisibility(View.GONE);
}
}
/**
* Enables/disables the shutter button to prevent double-clicks on the button.
*
* @param clickable True if the button should accept a click
*/
void setShutterButtonClickable(boolean clickable) {
shutterButton.setClickable(clickable);
}
/** Request the viewfinder to be invalidated. */
void drawViewfinder() {
viewfinderView.drawViewfinder();
}
@Override
public void onShutterButtonClick(ShutterButton b) {
if (isContinuousModeActive) {
onShutterButtonPressContinuous();
} else {
if (handler != null) {
handler.shutterButtonClick();
}
}
}
@Override
public void onShutterButtonFocus(ShutterButton b, boolean pressed) {
requestDelayedAutoFocus();
}
/**
* Requests autofocus after a 350 ms delay. This delay prevents requesting focus when the user
* just wants to click the shutter button without focusing. Quick button press/release will
* trigger onShutterButtonClick() before the focus kicks in.
*/
private void requestDelayedAutoFocus() {
// Wait 350 ms before focusing to avoid interfering with quick button presses when
// the user just wants to take a picture without focusing.
cameraManager.requestAutoFocus(350L);
}
static boolean getFirstLaunch() {
return isFirstLaunch;
}
/**
* We want the help screen to be shown automatically the first time a new version of the app is
* run. The easiest way to do this is to check android:versionCode from the manifest, and compare
* it to a value stored as a preference.
*/
private boolean checkFirstLaunch() {
try {
PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);
int currentVersion = info.versionCode;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
int lastVersion = prefs.getInt(PreferencesActivity.KEY_HELP_VERSION_SHOWN, 0);
if (lastVersion == 0) {
isFirstLaunch = true;
} else {
isFirstLaunch = false;
}
if (currentVersion > lastVersion) {
// Record the last version for which we last displayed the What's New (Help) page
prefs.edit().putInt(PreferencesActivity.KEY_HELP_VERSION_SHOWN, currentVersion).commit();
Intent intent = new Intent(this, HelpActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
// Show the default page on a clean install, and the what's new page on an upgrade.
String page = lastVersion == 0 ? HelpActivity.DEFAULT_PAGE : HelpActivity.WHATS_NEW_PAGE;
intent.putExtra(HelpActivity.REQUESTED_PAGE_KEY, page);
startActivity(intent);
return true;
}
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, e);
}
return false;
}
/**
* Returns a string that represents which OCR engine(s) are currently set to be run.
*
* @return OCR engine mode
*/
String getOcrEngineModeName() {
String ocrEngineModeName = "";
String[] ocrEngineModes = getResources().getStringArray(R.array.ocrenginemodes);
if (ocrEngineMode == TessBaseAPI.OEM_TESSERACT_ONLY) {
ocrEngineModeName = ocrEngineModes[0];
} else if (ocrEngineMode == TessBaseAPI.OEM_CUBE_ONLY) {
ocrEngineModeName = ocrEngineModes[1];
} else if (ocrEngineMode == TessBaseAPI.OEM_TESSERACT_CUBE_COMBINED) {
ocrEngineModeName = ocrEngineModes[2];
}
return ocrEngineModeName;
}
/**
* Gets values from shared preferences and sets the corresponding data members in this activity.
*/
private void retrievePreferences() {
prefs = PreferenceManager.getDefaultSharedPreferences(this);
// Retrieve from preferences, and set in this Activity, the language preferences
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
setSourceLanguage(prefs.getString(PreferencesActivity.KEY_SOURCE_LANGUAGE_PREFERENCE, CaptureActivity.DEFAULT_SOURCE_LANGUAGE_CODE));
setTargetLanguage(prefs.getString(PreferencesActivity.KEY_TARGET_LANGUAGE_PREFERENCE, CaptureActivity.DEFAULT_TARGET_LANGUAGE_CODE));
isTranslationActive = prefs.getBoolean(PreferencesActivity.KEY_TOGGLE_TRANSLATION, false);
// Retrieve from preferences, and set in this Activity, the capture mode preference
if (prefs.getBoolean(PreferencesActivity.KEY_CONTINUOUS_PREVIEW, CaptureActivity.DEFAULT_TOGGLE_CONTINUOUS)) {
isContinuousModeActive = true;
} else {
isContinuousModeActive = false;
}
// Retrieve from preferences, and set in this Activity, the page segmentation mode preference
String[] pageSegmentationModes = getResources().getStringArray(R.array.pagesegmentationmodes);
String pageSegmentationModeName = prefs.getString(PreferencesActivity.KEY_PAGE_SEGMENTATION_MODE, pageSegmentationModes[0]);
if (pageSegmentationModeName.equals(pageSegmentationModes[0])) {
pageSegmentationMode = TessBaseAPI.PSM_AUTO_OSD;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[1])) {
pageSegmentationMode = TessBaseAPI.PSM_AUTO;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[2])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_BLOCK;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[3])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_CHAR;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[4])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_COLUMN;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[5])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_LINE;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[6])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_WORD;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[7])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_BLOCK_VERT_TEXT;
}
// Retrieve from preferences, and set in this Activity, the OCR engine mode
String[] ocrEngineModes = getResources().getStringArray(R.array.ocrenginemodes);
String ocrEngineModeName = prefs.getString(PreferencesActivity.KEY_OCR_ENGINE_MODE, ocrEngineModes[0]);
if (ocrEngineModeName.equals(ocrEngineModes[0])) {
ocrEngineMode = TessBaseAPI.OEM_TESSERACT_ONLY;
} else if (ocrEngineModeName.equals(ocrEngineModes[1])) {
ocrEngineMode = TessBaseAPI.OEM_CUBE_ONLY;
} else if (ocrEngineModeName.equals(ocrEngineModes[2])) {
ocrEngineMode = TessBaseAPI.OEM_TESSERACT_CUBE_COMBINED;
}
// Retrieve from preferences, and set in this Activity, the character blacklist and whitelist
characterBlacklist = OcrCharacterHelper.getBlacklist(prefs, sourceLanguageCodeOcr);
characterWhitelist = OcrCharacterHelper.getWhitelist(prefs, sourceLanguageCodeOcr);
prefs.registerOnSharedPreferenceChangeListener(listener);
beepManager.updatePrefs();
}
/**
* Sets default values for preferences. To be called the first time this app is run.
*/
private void setDefaultPreferences() {
prefs = PreferenceManager.getDefaultSharedPreferences(this);
// Continuous preview
prefs.edit().putBoolean(PreferencesActivity.KEY_CONTINUOUS_PREVIEW, CaptureActivity.DEFAULT_TOGGLE_CONTINUOUS).commit();
// Recognition language
prefs.edit().putString(PreferencesActivity.KEY_SOURCE_LANGUAGE_PREFERENCE, CaptureActivity.DEFAULT_SOURCE_LANGUAGE_CODE).commit();
// Translation
prefs.edit().putBoolean(PreferencesActivity.KEY_TOGGLE_TRANSLATION, CaptureActivity.DEFAULT_TOGGLE_TRANSLATION).commit();
// Translation target language
prefs.edit().putString(PreferencesActivity.KEY_TARGET_LANGUAGE_PREFERENCE, CaptureActivity.DEFAULT_TARGET_LANGUAGE_CODE).commit();
// Translator
prefs.edit().putString(PreferencesActivity.KEY_TRANSLATOR, CaptureActivity.DEFAULT_TRANSLATOR).commit();
// OCR Engine
prefs.edit().putString(PreferencesActivity.KEY_OCR_ENGINE_MODE, CaptureActivity.DEFAULT_OCR_ENGINE_MODE).commit();
// Autofocus
prefs.edit().putBoolean(PreferencesActivity.KEY_AUTO_FOCUS, CaptureActivity.DEFAULT_TOGGLE_AUTO_FOCUS).commit();
// Beep
prefs.edit().putBoolean(PreferencesActivity.KEY_PLAY_BEEP, CaptureActivity.DEFAULT_TOGGLE_BEEP).commit();
// Character blacklist
prefs.edit().putString(PreferencesActivity.KEY_CHARACTER_BLACKLIST,
OcrCharacterHelper.getDefaultBlacklist(CaptureActivity.DEFAULT_SOURCE_LANGUAGE_CODE)).commit();
// Character whitelist
prefs.edit().putString(PreferencesActivity.KEY_CHARACTER_WHITELIST,
OcrCharacterHelper.getDefaultWhitelist(CaptureActivity.DEFAULT_SOURCE_LANGUAGE_CODE)).commit();
// Page segmentation mode
prefs.edit().putString(PreferencesActivity.KEY_PAGE_SEGMENTATION_MODE, CaptureActivity.DEFAULT_PAGE_SEGMENTATION_MODE).commit();
// Reversed camera image
prefs.edit().putBoolean(PreferencesActivity.KEY_REVERSE_IMAGE, CaptureActivity.DEFAULT_TOGGLE_REVERSED_IMAGE).commit();
// Light
prefs.edit().putBoolean(PreferencesActivity.KEY_TOGGLE_LIGHT, CaptureActivity.DEFAULT_TOGGLE_LIGHT).commit();
}
void displayProgressDialog() {
// Set up the indeterminate progress dialog box
indeterminateDialog = new ProgressDialog(this);
indeterminateDialog.setTitle("Please wait");
String ocrEngineModeName = getOcrEngineModeName();
if (ocrEngineModeName.equals("Both")) {
indeterminateDialog.setMessage("Performing OCR using Cube and Tesseract...");
} else {
indeterminateDialog.setMessage("Performing OCR using " + ocrEngineModeName + "...");
}
indeterminateDialog.setCancelable(false);
indeterminateDialog.show();
}
ProgressDialog getProgressDialog() {
return indeterminateDialog;
}
/**
* Displays an error message dialog box to the user on the UI thread.
*
* @param title The title for the dialog box
* @param message The error message to be displayed
*/
void showErrorMessage(String title, String message) {
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message)
.setOnCancelListener(new FinishListener(this))
.setPositiveButton( "Done", new FinishListener(this))
.show();
}
}