0
0
mirror of https://github.com/ankidroid/Anki-Android.git synced 2024-09-20 12:02:16 +02:00

Added unRegisterReceiver on onDestroy in Ankidroid.java, cleaned the code in openDeckPicker (deckPath is always obtained form Preferences so it's not necessary to put it into the Intent), created a new control variable called deckLoaded, cleaned the content of the previous card for a better visualization and fixed various minor bugs.

This commit is contained in:
edu-zamora 2009-11-10 19:19:11 +08:00 committed by Nicolas Raoul
parent b0771235f8
commit ef249b5d29
4 changed files with 83 additions and 55 deletions

View File

@ -1,10 +1,10 @@
<html>
<body>
<h2>Ankidroid:<br/>
Flashcards for Android</h2>
Flashcards for Android</h2>
<p>Ankidroid can read .anki files produced by the desktop <a href="http://ichi2.net/anki">Anki</a> software.</p>
<p><b>Warning</b>: Ankidroid modifies .anki files in a way that is not compatible with the Anki desktop application. Do not copy .anki files from the SD card back to your computer.</p>
<p>You can report bugs <a href="http://code.google.com/p/ankidroid/issues">here</a> or discuss <a href="http://groups.google.com/group/anki-android">on the forum</a>.</p>
<p>Ankidroid is <a href="http://en.wikipedia.org/wiki/Open_source_software">open source software</a>, and everyone is encouraged to get <a href="http://github.com/nicolas-raoul/Anki-Android/tree/master">the source</a> and build on it :-)</p>
<p><b>Warning</b>: Ankidroid modifies .anki files in a way that is not yet compatible with the Anki desktop application. Do not copy .anki files from the SD card back to your computer.</p>
<p>You can report bugs and request new features or improvements <a href="http://code.google.com/p/ankidroid/issues">here</a>, discuss <a href="http://groups.google.com/group/anki-android">on the forum</a> or view the <a href="http://ichi2.net/anki/wiki/AndroidAnki">official wiki</a>.</p>
<p>Ankidroid is <a href="http://en.wikipedia.org/wiki/Open_source_software">open source software</a>, and everyone is encouraged to get the source from <a href="http://github.com/edu-zamora/Anki-Android/tree/master">here</a> or <a href="http://github.com/nicolas-raoul/Anki-Android/tree/master">here</a> and build on it :-)</p>
</body>
</html>

View File

@ -20,6 +20,11 @@ public class AnkiDb
*/
static public SQLiteDatabase database;
/**
* Tag for logging messages
*/
private static final String TAG = "Ankidroid";
/**
* Open a database connection to an ".anki" SQLite file.
*/
@ -96,7 +101,7 @@ public class AnkiDb
{
Card card = oneFromCursor(AnkiDb.database.rawQuery("SELECT id,interval,question,answer" + " FROM cards"
+ " ORDER BY random()" + " LIMIT 1", null));
Log.d("anki", "Selected card id " + card.id + " with interval " + card.interval);
Log.d(TAG, "Selected card id " + card.id + " with interval " + card.interval);
return card;
}
@ -107,7 +112,7 @@ public class AnkiDb
{
Card card = oneFromCursor(AnkiDb.database.rawQuery("SELECT id,interval,question,answer" + " FROM cards"
+ " WHERE priority > 0" + " ORDER BY interval" + " LIMIT 1", null));
Log.i("anki", "Selected card id " + card.id + " with interval " + card.interval);
Log.i(TAG, "Selected card id " + card.id + " with interval " + card.interval);
return card;
}
@ -140,7 +145,7 @@ public class AnkiDb
ContentValues values = new ContentValues();
values.put("interval", newInterval);
AnkiDb.database.update("cards", values, "id='" + id + "'", null);
Log.d("anki", "Spaced card to interval " + newInterval);
Log.d(TAG, "Spaced card to interval " + newInterval);
}
/**
@ -162,7 +167,7 @@ public class AnkiDb
ContentValues values = new ContentValues();
values.put("interval", newInterval);
AnkiDb.database.update("cards", values, "id='" + id + "'", null);
Log.d("anki", "Reset card with interval " + newInterval);
Log.d(TAG, "Reset card with interval " + newInterval);
}
}
}

View File

@ -66,6 +66,10 @@ public class Ankidroid extends Activity implements Runnable
public static final int MENU_ABOUT = 2;
/**
* Dialogs
*/
public static final int DIALOG_UPDATE = 0;
/**
* Possible outputs trying to load a deck
@ -87,13 +91,17 @@ public class Ankidroid extends Activity implements Runnable
* Variables to hold the state
*/
private ProgressDialog dialog;
private boolean layoutInitialized;
private BroadcastReceiver mUnmountReceiver = null;
//Indicates if a deck is trying to be load. onResume() won't try to load a deck if deckSelected is true
//We don't have to worry to set deckSelected to true, it's done automatically in displayProgressDialogAndLoadDeck()
//We have to set deckSelected to false only on these situations a deck has to be reload and when we know for sure no other thread is trying to load a deck (for example, when sd card is mounted again)
private boolean deckSelected;
private boolean deckLoaded;
//Name of the last deck loaded
private String deckFilename;
private boolean corporalPunishments;
@ -102,8 +110,6 @@ public class Ankidroid extends Activity implements Runnable
private boolean spacedRepetition;
private String deckPath;
public String cardTemplate;
private AnkiDb.Card currentCard;
@ -181,6 +187,8 @@ public class Ankidroid extends Activity implements Runnable
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate - savedInstanceState: " + savedInstanceState);
//checkUpdates();
registerExternalStorageListener();
initResourceValues();
@ -246,7 +254,6 @@ public class Ankidroid extends Activity implements Runnable
}
// Load sample deck.
deckFilename = SAMPLE_DECK_FILENAME;
//displayProgressDialogAndLoadDeck();
} else
{
// Show the deck picker.
@ -257,7 +264,7 @@ public class Ankidroid extends Activity implements Runnable
}
}
// Retrieve resource values.
public void initResourceValues()
{
@ -322,15 +329,39 @@ public class Ankidroid extends Activity implements Runnable
return false;
}
/*protected Dialog onCreateDialog(int id)
{
Dialog dialog;
switch(id)
{
case DIALOG_UPDATE:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Update available");
builder.setMessage("A new version of Ankidroid is available in Android Market. Would you like to install it?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Uri ankidroidMarketURI = Uri.parse("http://market.android.com/search?q=pname:com.ichi2.anki");
Intent searchUpdateIntent = new Intent(Intent.ACTION_VIEW, ankidroidMarketURI);
startActivity(searchUpdateIntent);
}
});
builder.setNegativeButton("No", null);
dialog = builder.create();
break;
default:
dialog = null;
}
return dialog;
}*/
public void openDeckPicker()
{
Log.i(TAG, "openDeckPicker");
deckSelected = false; // Make sure we open the database again in
// onResume() if user pressed "back".
Log.i(TAG, "openDeckPicker - deckSelected = " + deckSelected);
deckLoaded = false;
Intent decksPicker = new Intent(this, DeckPicker.class);
decksPicker.putExtra("com.ichi2.anki.Ankidroid.DeckPath", deckPath);
startActivityForResult(decksPicker, PICK_DECK_REQUEST);
Log.i(TAG, "openDeckPicker - Ending");
}
@ -367,8 +398,6 @@ public class Ankidroid extends Activity implements Runnable
if (!deckSelected)
{
Log.i(TAG, "onResume() - No deck selected before");
deckSelected = true;
Log.i(TAG, "onResume - deckSelected = " + deckSelected);
displayProgressDialogAndLoadDeck();
}
@ -377,6 +406,7 @@ public class Ankidroid extends Activity implements Runnable
@Override
protected void onDestroy() {
Log.i(TAG, "onDestroy()");
super.onDestroy();
unregisterReceiver(mUnmountReceiver);
}
@ -385,6 +415,9 @@ public class Ankidroid extends Activity implements Runnable
{
Log.i(TAG, "displayProgressDialogAndLoadDeck - Loading deck " + deckFilename);
// Don't open database again in onResume() until we know for sure this attempt to load the deck is finished
deckSelected = true;
if(isSdCardMounted())
{
if (deckFilename != null && new File(deckFilename).exists())
@ -467,6 +500,7 @@ public class Ankidroid extends Activity implements Runnable
case DECK_LOADED:
showControls(true);
deckLoaded = true;
displayCardQuestion();
break;
@ -487,16 +521,23 @@ public class Ankidroid extends Activity implements Runnable
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == PICK_DECK_REQUEST)
{
//Clean the previous card before showing the first of the new loaded deck (so the transition is not so abrupt)
updateCard("");
hideSdError();
hideDeckErrors();
if (resultCode != RESULT_OK)
{
Log.e(TAG, "onActivityResult - Deck browser returned with error");
//Make sure we open the database again in onResume() if user pressed "back"
deckSelected = false;
return;
}
if (intent == null)
{
deckSelected = false;
Log.e(TAG, "onActivityResult - Deck browser returned null intent");
//Make sure we open the database again in onResume()
deckSelected = false;
return;
}
// A deck was picked. Save it in preferences and use it.
@ -504,17 +545,13 @@ public class Ankidroid extends Activity implements Runnable
deckFilename = intent.getExtras().getString(OPT_DB);
savePreferences();
// Don't open database again in onResume(). Load the new one in
// another thread instead.
deckSelected = true;
Log.i(TAG, "onActivityResult - deckSelected = " + deckSelected);
displayProgressDialogAndLoadDeck();
} else if (requestCode == PREFERENCES_UPDATE)
{
restorePreferences();
//If any deck has been selected (usually because there was no sd card attached, and therefore was impossible to select one)
//the controls have not been initialized, so we don't have to try to show or hide them
if(deckSelected && isSdCardMounted())
//If there is no deck loaded the controls have not to be shown
if(deckLoaded)
showOrHideControls();
}
}
@ -545,7 +582,6 @@ public class Ankidroid extends Activity implements Runnable
private void showControls(boolean show)
{
if (show)
{
mCard.setVisibility(View.VISIBLE);
@ -564,7 +600,6 @@ public class Ankidroid extends Activity implements Runnable
mToggleWhiteboard.setVisibility(View.GONE);
mWhiteboard.setVisibility(View.GONE);
}
}
/**
@ -693,7 +728,6 @@ public class Ankidroid extends Activity implements Runnable
timerAndWhiteboard = preferences.getBoolean("timerAndWhiteboard", true);
Log.i(TAG, "restorePreferences - timerAndWhiteboard: " + timerAndWhiteboard);
spacedRepetition = preferences.getBoolean("spacedRepetition", true);
deckPath = preferences.getString("deckPath", "/sdcard");
return preferences;
}
@ -746,6 +780,7 @@ public class Ankidroid extends Activity implements Runnable
private void closeExternalStorageFiles()
{
AnkiDb.closeDatabase();
deckLoaded = false;
displaySdError();
}
@ -823,4 +858,8 @@ public class Ankidroid extends Activity implements Runnable
detail.setVisibility(View.GONE);
}
/*private void checkUpdates()
{
showDialog(DIALOG_UPDATE);
}*/
}

View File

@ -12,6 +12,7 @@ import java.util.concurrent.locks.ReentrantLock;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -45,7 +46,9 @@ public class DeckPicker extends Activity implements Runnable
/**
* Dialogs
*/
public static final int DIALOG_NO_SDCARD = 0;
private static final int DIALOG_NO_SDCARD = 0;
private ProgressDialog dialog;
private DeckPicker mSelf;
@ -146,7 +149,8 @@ public class DeckPicker extends Activity implements Runnable
private void populateDeckList(String location)
{
Log.i(TAG, "DeckPicker - populateDeckList");
Resources res = getResources();
int len = 0;
File[] fileList;
@ -179,12 +183,7 @@ public class DeckPicker extends Activity implements Runnable
data.put("filepath", absPath);
data.put("showProgress", "true");
//Log.i(TAG, data.get("name") + ", due = " + data.get("due") + ", new = " + data.get("new") + ", showProgress = " + data.get("showProgress") + ", filepath = " + data.get("filepath") + ", last modified = " + data.get("mod"));
//Log.i(TAG, "Tree contains data = " + tree.contains(data));
//Log.i(TAG, "Object removed = " + tree.remove(data));
boolean result = tree.add(data);
//Log.i(TAG, "Result tree.add = " + result);
//logTree(tree);
} catch (SQLException e)
{
Log.w(TAG, "DeckPicker - populateDeckList, File " + fileList[i].getName() + " is not a real anki file");
@ -214,8 +213,6 @@ public class DeckPicker extends Activity implements Runnable
tree.add(data);
}
//logTree(tree);
mDeckList.clear();
mDeckList.addAll(tree);
mDeckListView.clearChoices();
@ -259,7 +256,7 @@ public class DeckPicker extends Activity implements Runnable
if (deckFilename != null)
{
Log.i("anki", "Selected " + deckFilename);
Log.i(TAG, "Selected " + deckFilename);
Intent intent = this.getIntent();
intent.putExtra(Ankidroid.OPT_DB, deckFilename);
setResult(RESULT_OK, intent);
@ -319,7 +316,7 @@ public class DeckPicker extends Activity implements Runnable
deck = Deck.openDeck(path);
} catch (SQLException e)
{
Log.w("anki", "Could not open database " + path);
Log.w(TAG, "Could not open database " + path);
continue;
}
int dueCards = deck.failedSoonCount + deck.revCount;
@ -389,25 +386,12 @@ public class DeckPicker extends Activity implements Runnable
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
//saveQueue(true);
//mOneShot = true; // This makes us not save the state again later,
// which would be wrong because the song ids and
// card id might not match.
//closeExternalStorageFiles(intent.getData().getPath());
Log.i(TAG, "DeckPicker - mUnmountReceiver, Action = Media Unmounted");
//closeExternalStorageFiles();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
String deckPath = preferences.getString("deckPath", "/sdcard");
populateDeckList(deckPath);
} else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
///mMediaMountedCount++;
//mCardId = FileUtils.getFatVolumeId(intent.getData().getPath());
//reloadQueue();
//notifyChange(QUEUE_CHANGED);
//notifyChange(META_CHANGED);
Log.i(TAG, "DeckPicker - mUnmountReceiver, Action = Media Mounted");
//hideSdError();
//onResume();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
String deckPath = preferences.getString("deckPath", "/sdcard");
mDeckIsSelected = false;