/* * @copyright 2010 Evan Leybourn * @license GNU General Public License * * This file is part of Book Catalogue. * * Book Catalogue is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Book Catalogue is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Book Catalogue. If not, see <http://www.gnu.org/licenses/>. */ package com.eleybourn.bookcatalogue; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.text.InputType; import android.view.View; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.EditText; import android.widget.ImageButton; import android.widget.Toast; import com.eleybourn.bookcatalogue.debug.Tracker; import com.eleybourn.bookcatalogue.scanner.Scanner; import com.eleybourn.bookcatalogue.scanner.ScannerManager; import com.eleybourn.bookcatalogue.utils.AsinUtils; import com.eleybourn.bookcatalogue.utils.IsbnUtils; import com.eleybourn.bookcatalogue.utils.Logger; import com.eleybourn.bookcatalogue.utils.SoundManager; import com.eleybourn.bookcatalogue.utils.Utils; /** * This class is called by the BookCatalogue activity and will search the interwebs for * book details based on either a typed in or scanned ISBN. * * It currently only searches Google Books, but Amazon will be coming soon. */ public class BookISBNSearch extends ActivityWithTasks { //private static final int CREATE_BOOK = 0; public static final String BY = "by"; // private static Integer mIdCounter = 0; // private final int mId; // // { // synchronized(mIdCounter) { // mId = ++mIdCounter; // } // } private boolean mScannerStarted = false; private EditText mIsbnText; private EditText mTitleText; private AutoCompleteTextView mAuthorText; private ArrayAdapter<String> mAuthorAdapter = null; private Button mConfirmButton; private CatalogueDBAdapter mDbHelper; private String mAuthor; private String mTitle; private String mIsbn; /* * Mode this activity is in; MANUAL = data entry, SCAN = data from scanner. * For SCAN, it loops repeatedly starting the scanner. */ private static final int MODE_MANUAL = 1; private static final int MODE_SCAN = 2; private int mMode; // Flag to indicate the Activity should not 'finish()' because // an alert is being displayed. The Alter will call finish(). private boolean mDisplayingAlert = false; // Object to manage preferred (or found) scanner private Scanner mScanner = null; // The last Intent returned as a result of creating a book. private Intent mLastBookIntent = null; // Object managing current search. long mSearchManagerId = 0; // A list of author names we have already searched for in this session ArrayList<String> mAuthorNames = new ArrayList<String>(); /** * Called when the activity is first created. This function will search the interwebs for * book details based on either a typed in or scanned ISBN. * * @param savedInstanceState The saved bundle (from pausing). Can be null. */ @Override protected void onCreate(Bundle savedInstanceState) { Tracker.enterOnCreate(this); try { super.onCreate(savedInstanceState); if (savedInstanceState != null) mSearchManagerId = savedInstanceState.getLong("SearchManagerId"); //System.out.println("BookISBNSearch OnCreate SIS=" + (savedInstanceState == null? "N" : "Y")); //do we have a network connection? boolean network_available = Utils.isNetworkAvailable(this); if (network_available == false) { Toast.makeText(this, R.string.no_connection, Toast.LENGTH_LONG).show(); finish(); return; } Utils.showLtAlertIfNecessary(this, false, "search"); Bundle extras = getIntent().getExtras(); mDbHelper = new CatalogueDBAdapter(this); mDbHelper.open(); mIsbn = extras.getString("isbn"); String by = extras.getString(BY); if (savedInstanceState != null) { if (savedInstanceState.containsKey("mScannerStarted")) mScannerStarted = savedInstanceState.getBoolean("mScannerStarted"); else { //System.out.println(mId + " OnCreate mScannerStarted NOT PRESENT"); } } // BUG NOTE 1: // // There is a bizarre bug that seems to only affect some users in which this activity // is called AFTER the user has finished and the passed Intent has neither a ISBN nor a // "BY" in the Extras. Following all the code that starts this activity suggests that // the activity is ALWAYS started with the intent data. The problems always occur AFTER // adding a book, which confirms that the activity has been started correctly. // // In order to avoid this problem, we just check for nulls and finish(). THIS IS NOT A FIX // it is a MESSY WORK-AROUND. // // TODO: Find out why BookISBNSearch gets restarted with no data // // So...we save the extras in savedInstanceState, and look for it when missing // if (mIsbn == null && (by == null || by.equals("") ) ) { Logger.logError(new RuntimeException("Empty args for BookISBNSearch")); if (savedInstanceState != null) { if (mIsbn == null && savedInstanceState.containsKey("isbn")) mIsbn = savedInstanceState.getString("isbn"); if ( (by == null || by.equals("") ) && savedInstanceState.containsKey(BY)) by = savedInstanceState.getString(BY); } // If they are still null, we can't proceed. if (mIsbn == null && (by == null || by.equals("") ) ) { finish(); return; } } // Default to MANUAL mMode = MODE_MANUAL; if (mIsbn != null) { //System.out.println(mId + " OnCreate got ISBN"); //ISBN has been passed by another component setContentView(R.layout.isbn_search); mIsbnText = (EditText) findViewById(R.id.isbn); mIsbnText.setText(mIsbn); go(mIsbn, "", ""); } else if (by.equals("isbn")) { // System.out.println(mId + " OnCreate BY ISBN"); setContentView(R.layout.isbn_search); mIsbnText = (EditText) findViewById(R.id.isbn); mConfirmButton = (Button) findViewById(R.id.search); // Not sure this is a great idea; we CAN diable keypad for this item completely. //android.view.inputmethod.InputMethodManager imm // = (android.view.inputmethod.InputMethodManager) // getSystemService(android.content.Context.INPUT_METHOD_SERVICE); //imm.hideSoftInputFromWindow(mIsbnText.getWindowToken(), 0); // For now, just make sure it's hidden on entry getWindow().setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); final CheckBox allowAsinCb = (CheckBox) BookISBNSearch.this.findViewById(R.id.asinCheckbox); allowAsinCb.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { mIsbnText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS|InputType.TYPE_CLASS_TEXT); getWindow().setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); } else { mIsbnText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS|InputType.TYPE_CLASS_TEXT); getWindow().setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); } }}); // Set the number buttons Button button1 = (Button) findViewById(R.id.isbn_1); button1.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("1"); } }); Button button2 = (Button) findViewById(R.id.isbn_2); button2.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("2"); } }); Button button3 = (Button) findViewById(R.id.isbn_3); button3.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("3"); } }); Button button4 = (Button) findViewById(R.id.isbn_4); button4.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("4"); } }); Button button5 = (Button) findViewById(R.id.isbn_5); button5.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("5"); } }); Button button6 = (Button) findViewById(R.id.isbn_6); button6.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("6"); } }); Button button7 = (Button) findViewById(R.id.isbn_7); button7.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("7"); } }); Button button8 = (Button) findViewById(R.id.isbn_8); button8.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("8"); } }); Button button9 = (Button) findViewById(R.id.isbn_9); button9.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("9"); } }); Button buttonX = (Button) findViewById(R.id.isbn_X); buttonX.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("X"); } }); Button button0 = (Button) findViewById(R.id.isbn_0); button0.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { handleIsbnKey("0"); } }); ImageButton buttonDel = (ImageButton) findViewById(R.id.isbn_del); buttonDel.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { try { int start = mIsbnText.getSelectionStart(); int end = mIsbnText.getSelectionEnd(); if (start < end) { // We have a selection. Delete it. mIsbnText.getText().replace(start, end, ""); mIsbnText.setSelection(start, start); } else { // Delete char before cursor if (start > 0) { mIsbnText.getText().replace(start-1, start, ""); mIsbnText.setSelection(start-1, start-1); } } } catch (StringIndexOutOfBoundsException e) { //do nothing - empty string } } }); mConfirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { String mIsbn = mIsbnText.getText().toString(); go(mIsbn, "", ""); } }); } else if (by.equals("name")) { // System.out.println(mId + " OnCreate BY NAME"); setContentView(R.layout.name_search); this.setTitle(R.string.search_hint); this.initAuthorList(); mTitleText = (EditText) findViewById(R.id.title); mConfirmButton = (Button) findViewById(R.id.search); mConfirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { String mAuthor = mAuthorText.getText().toString(); String mTitle = mTitleText.getText().toString(); ArrayAdapter<String> adapter = mAuthorAdapter; if (adapter.getPosition(mAuthor) < 0){ // Based on code from filipeximenes we also need to update the adapter here in // case no author or book is added, but we still want to see 'recent' entries. if (!mAuthor.trim().equals("")) { boolean found = false; for(String s: mAuthorNames) { if (s.equalsIgnoreCase(mAuthor)) { found = true; break; } } if (!found) { // Keep a list of names as typed to use when we recreate list mAuthorNames.add(mAuthor); // Add to adapter, in case search produces no results adapter.add(mAuthor); } } } go("", mAuthor, mTitle); } }); } else if (by.equals("scan")) { // System.out.println(mId + " OnCreate BY SCAN"); // Use the scanner to get ISBNs mMode = MODE_SCAN; setContentView(R.layout.isbn_scan); mIsbnText = (EditText) findViewById(R.id.isbn); /** * Use the preferred barcode scanner to search for a isbn * Prompt users to install the application if they do not have it installed. */ try { // Start the scanner IF this is a real 'first time' call. if (savedInstanceState == null) { startScannerActivity(); } else { // It's a saved state, so see if we have an ISBN if (savedInstanceState.containsKey("isbn")) { go(savedInstanceState.getString("isbn"),"",""); } } } catch (java.lang.SecurityException e) { AlertDialog alertDialog = new AlertDialog.Builder(BookISBNSearch.this).setMessage(R.string.bad_scanner).create(); alertDialog.setTitle(R.string.install_scan_title); alertDialog.setIcon(android.R.drawable.ic_menu_info_details); alertDialog.setButton2("ZXing", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.zxing.client.android")); startActivity(marketIntent); finish(); } }); alertDialog.setButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //do nothing finish(); } }); // Prevent the activity result from closing this activity. mDisplayingAlert = true; alertDialog.show(); return; } catch (ActivityNotFoundException e) { // Verify - this can be a dangerous operation AlertDialog alertDialog = new AlertDialog.Builder(BookISBNSearch.this).setMessage(R.string.install_scan).create(); alertDialog.setTitle(R.string.install_scan_title); alertDialog.setIcon(android.R.drawable.ic_menu_info_details); alertDialog.setButton("pic2shop", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //TODO Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.visionsmarts.pic2shop")); startActivity(marketIntent); finish(); } }); alertDialog.setButton3("ZXing", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.zxing.client.android")); startActivity(marketIntent); finish(); } }); alertDialog.setButton2("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //do nothing finish(); } }); // Prevent the activity result from closing this activity. mDisplayingAlert = true; alertDialog.show(); return; } } } finally { Tracker.exitOnCreate(this); } } /* * Handle character insertion at cursor position in EditText */ private void handleIsbnKey(String key) { int start = mIsbnText.getSelectionStart(); int end = mIsbnText.getSelectionEnd(); mIsbnText.getText().replace(start, end, key); mIsbnText.setSelection(start+1, start+1); // Get instance of Vibrator from current Context //NOTE: Removed due to complaints //Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); // Vibrate for 50 milliseconds //v.vibrate(50); } /* - MAJOR DATABASE ISSUES FOR THIS TO WORK!!! protected void checkISBN(final String isbn) { // If the book already exists, ask if the user wants to continue try { if (!isbn.equals("")) { Cursor book = mDbHelper.fetchBookByISBN(isbn); int rows = book.getCount(); if (rows != 0) { AlertDialog alertDialog = new AlertDialog.Builder(this).setMessage(R.string.duplicate_alert).create(); alertDialog.setTitle(R.string.duplicate_title); alertDialog.setIcon(android.R.drawable.ic_menu_info_details); alertDialog.setButton(this.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { go(isbn); return; } }); alertDialog.setButton2(this.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { finish(); return; } }); alertDialog.show(); } else { go(isbn); } } else { go(isbn); } } catch (Exception e) { Logger.logError(e); } } */ /* * Clear any data-entry fields that have been set. * Used when a book has been successfully added as we want to get ready for another. */ private void clearFields() { if (mIsbnText != null) mIsbnText.setText(""); if (mAuthorText != null) mAuthorText.setText(""); if (mTitleText != null) mTitleText.setText(""); } /** * This function takes the isbn and search google books (and soon amazon) * to extract the details of the book. The details will then get sent to the * BookEdit activity * * @param isbn The ISBN to search */ protected void go(String isbn, String author, String title) { //System.out.println(mId + " GO: isbn=" + isbn + ", author=" + author + ", title=" + title); // Save the details because we will do some async processing or an alert mIsbn = isbn; mAuthor = author; mTitle = title; // If the book already exists, do not continue try { if (isbn != null && !isbn.equals("")) { // If the layout has an 'Allow ASIN' checkbox, see if it is checked. final CheckBox allowAsinCb = (CheckBox) BookISBNSearch.this.findViewById(R.id.asinCheckbox); final boolean allowAsin = allowAsinCb != null ? allowAsinCb.isChecked() : false; if (!IsbnUtils.isValid(isbn) && (!allowAsin || !AsinUtils.isValid(isbn) ) ) { int msg; if (allowAsin) { msg = R.string.x_is_not_a_valid_isbn_or_asin; } else { msg = R.string.x_is_not_a_valid_isbn; } Toast.makeText(this, getString(msg, isbn), Toast.LENGTH_LONG).show(); if (mMode == MODE_SCAN) { // Optionally beep if scan failed. SoundManager.beepLow(); // reset the now-discarded details mIsbn = ""; mAuthor = ""; mTitle = ""; startScannerActivity(); } return; } else { if (mMode == MODE_SCAN) { // Optionally beep if scan was valid. SoundManager.beepHigh(); } // See if ISBN exists in catalogue final long existingId = mDbHelper.getIdFromIsbn(isbn, true); if (existingId > 0) { // Verify - this can be a dangerous operation AlertDialog alertDialog = new AlertDialog.Builder(this).setMessage(R.string.duplicate_book_message).create(); alertDialog.setTitle(R.string.duplicate_book_title); alertDialog.setIcon(android.R.drawable.ic_menu_info_details); alertDialog.setButton2(this.getResources().getString(R.string.add), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { doSearchBook(); return; } }); alertDialog.setButton3(this.getResources().getString(R.string.edit_book), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { BookEdit.editBook(BookISBNSearch.this, existingId, BookEdit.TAB_EDIT); } }); alertDialog.setButton(this.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //do nothing if (mMode == MODE_SCAN) { // reset the now-discarded details mIsbn = ""; mAuthor = ""; mTitle = ""; startScannerActivity(); } return; } }); alertDialog.show(); return; } } } } catch (Exception e) { Logger.logError(e); } if (mSearchManagerId == 0) doSearchBook(); } private void doSearchBook() { // System.out.println(mId + " doSearchBook"); /* Delete any hanging around temporary thumbs */ try { File thumb = CatalogueDBAdapter.getTempThumbnail(); thumb.delete(); } catch (Exception e) { // do nothing - this is the expected behaviour } if ( (mAuthor != null && !mAuthor.equals("")) || (mTitle != null && !mTitle.equals("")) || (mIsbn != null && !mIsbn.equals("")) ) { //System.out.println(mId + " doSearchBook searching"); /* Get the book */ try { // Start the lookup in background. //mTaskManager.doProgress("Searching"); SearchManager sm = new SearchManager(getTaskManager(), mSearchHandler); mSearchManagerId = sm.getSenderId(); Tracker.handleEvent(this, "Searching" + mSearchManagerId, Tracker.States.Running); this.getTaskManager().doProgress(getString(R.string.searching_elipsis)); sm.search(mAuthor, mTitle, mIsbn, true, SearchManager.SEARCH_ALL); // reset the details so we don't restart the search unnecessarily mAuthor = ""; mTitle = ""; mIsbn = ""; } catch (Exception e) { Logger.logError(e); Toast.makeText(this, R.string.search_fail, Toast.LENGTH_LONG).show(); finish(); return; } } else { // System.out.println(mId + " doSearchBook no criteria"); if (mMode == MODE_SCAN) startScannerActivity(); return; } } private SearchManager.SearchListener mSearchHandler = new SearchManager.SearchListener() { @Override public boolean onSearchFinished(Bundle bookData, boolean cancelled) { return BookISBNSearch.this.onSearchFinished(bookData, cancelled); } }; private boolean onSearchFinished(Bundle bookData, boolean cancelled) { Tracker.handleEvent(this, "onSearchFinished" + mSearchManagerId, Tracker.States.Running); try { //System.out.println(mId + " onSearchFinished"); if (cancelled || bookData == null) { if (mMode == MODE_SCAN) startScannerActivity(); } else { getTaskManager().doProgress(getString(R.string.adding_book_elipsis)); createBook(bookData); // Clear the data entry fields ready for the next one clearFields(); } return true; } finally { // Clean up mSearchManagerId = 0; // Make sure the base message will be empty. this.getTaskManager().doProgress(null); } } @Override protected void onPause() { Tracker.enterOnPause(this); super.onPause(); if (mSearchManagerId != 0) SearchManager.getMessageSwitch().removeListener(mSearchManagerId, mSearchHandler); Tracker.exitOnPause(this); } @Override protected void onResume() { Tracker.enterOnResume(this); super.onResume(); if (mSearchManagerId != 0) SearchManager.getMessageSwitch().addListener(mSearchManagerId, mSearchHandler, true); Tracker.exitOnResume(this); } @Override protected void onDestroy() { Tracker.enterOnDestroy(this); super.onDestroy(); if (mDbHelper != null) mDbHelper.close(); Tracker.exitOnDestroy(this); } public String convertDate(String date) { if (date.length() == 2) { //assume yy try { if (Integer.parseInt(date) < 15) { date = "20" + date + "-01-01"; } else { date = "19" + date + "-01-01"; } } catch (Exception e) { date = ""; } } else if (date.length() == 4) { //assume yyyy date = date + "-01-01"; } else if (date.length() == 6) { //assume yyyymm date = date.substring(0, 4) + "-" + date.substring(4, 6) + "-01"; } else if (date.length() == 7) { //assume yyyy-mm date = date + "-01"; } return date; } /* * Load the BookEdit Activity * * return void */ private void createBook(Bundle book) { Intent i = new Intent(this, BookEdit.class); i.putExtra("bookData", book); startActivityForResult(i, UniqueId.ACTIVITY_EDIT_BOOK); //dismissProgress(); } /** * This is a straight passthrough */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { //System.out.println("BookISBNSearch onActivityResult " + resultCode); super.onActivityResult(requestCode, resultCode, intent); switch(requestCode) { case UniqueId.ACTIVITY_SCAN: mScannerStarted = false; try { if (resultCode == RESULT_OK) { // Scanner returned an ISBN...process it. String contents = mScanner.getBarcode(intent); mIsbnText.setText(contents); go(contents, "", ""); } else { // Scanner Cancelled/failed. Exit if no dialog present. if (mLastBookIntent != null) this.setResult(RESULT_OK, mLastBookIntent); else this.setResult(RESULT_CANCELED, mLastBookIntent); if (!mDisplayingAlert) finish(); } } catch (NullPointerException e) { Logger.logError(e); finish(); } break; case UniqueId.ACTIVITY_EDIT_BOOK: if (intent != null) mLastBookIntent = intent; // Created a book; save the intent and restart scanner if necessary. if (mMode == MODE_SCAN) startScannerActivity(); else // If the 'Back' button is pressed on a normal activity, set the default result to cancelled by setting it here. this.setResult(RESULT_CANCELED, mLastBookIntent); break; } // No matter what the activity was, rebuild the author list in case a new author was added. initAuthorList(); } private void initAuthorList() { // Get the author field, if present mAuthorText = (AutoCompleteTextView) findViewById(R.id.author); if (mAuthorText != null) { // Get all known authors and build a hash of the names final ArrayList<String> authors = mDbHelper.getAllAuthors(); final HashSet<String> uniqueNames = new HashSet<String>(); for(String s: authors) uniqueNames.add(s.toUpperCase()); // Add the names the user has already tried (to handle errors and mistakes) for(String s: mAuthorNames) { if (!uniqueNames.contains(s.toUpperCase())) authors.add(s); } // Now get an adapter based on the combined names mAuthorAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, authors); // Set it mAuthorText.setAdapter(mAuthorAdapter); } } /* * Start scanner activity. */ private void startScannerActivity() { //System.out.println(mId + " startScannerActivity"); if (mScanner == null) { mScanner = ScannerManager.getScanner(); } if (!mScannerStarted) { //System.out.println(mId + " startScannerActivity STARTING"); mScannerStarted = true; mScanner.startActivityForResult(this, UniqueId.ACTIVITY_SCAN); } else { //System.out.println(mId + " startScannerActivity SKIPPED"); } } /** * Ensure the TaskManager is restored. */ @Override protected void onRestoreInstanceState(Bundle inState) { //System.out.println(mId + " onRestoreInstanceState"); mSearchManagerId = inState.getLong("SearchManagerId"); // Now do 'standard' stuff mLastBookIntent = (Intent) inState.getParcelable("LastBookIntent"); // Call the super method only after we have the searchManager set up super.onRestoreInstanceState(inState); } @Override protected void onSaveInstanceState(Bundle inState) { super.onSaveInstanceState(inState); // Saving intent data is a kludge due to an apparent Android bug in some // handsets. Search for "BUG NOTE 1" in this source file for a discussion Bundle b = getIntent().getExtras(); if (b != null) { if (b.containsKey("isbn")) inState.putString("isbn", b.getString("isbn")); if (b.containsKey(BY)) inState.putString(BY, b.getString(BY)); } inState.putParcelable("LastBookIntent", mLastBookIntent); // Save the current search details as this may be called as a result of a rotate during an alert dialog. inState.putString("author", mAuthor); inState.putString("isbn", mIsbn); inState.putString("title", mTitle); inState.putBoolean("mScannerStarted", mScannerStarted); if (mSearchManagerId != 0) inState.putLong("SearchManagerId", mSearchManagerId); } }