mirror of
https://github.com/ankidroid/Anki-Android.git
synced 2024-09-20 20:03:05 +02:00
Complete handling of the events of sd card implemented. There is still some bugs regarding with using the app with any deck selected and the "Deck sample" option off.
This commit is contained in:
parent
c46bc02af7
commit
b99052bc39
@ -5,6 +5,9 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/sdcard_error" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/DeckPickerName"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -5,6 +5,9 @@
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<include layout="@layout/sdcard_error" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/card_whiteboard_layout"
|
||||
android:layout_width="fill_parent"
|
||||
|
@ -18,4 +18,6 @@
|
||||
<string name="deckpicker_new">%d new today</string>
|
||||
<string name="deckpicker_loaddeck">Loading deck...</string>
|
||||
<string name="deckpicker_nodeck">No decks found.</string>
|
||||
|
||||
<string name="sdcard_missing_message">SD card is unavailable because it is being used as USB storage. Disconnect USB to access your decks.</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
@ -36,9 +35,9 @@ import android.webkit.WebView;
|
||||
import android.widget.Button;
|
||||
import android.widget.Chronometer;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
/**
|
||||
@ -119,6 +118,7 @@ public class Ankidroid extends Activity implements Runnable
|
||||
|
||||
private Whiteboard mWhiteboard;
|
||||
|
||||
|
||||
//private Hashtable<Integer,String> viewNames = new Hashtable<Integer,String>();
|
||||
|
||||
//private LinearLayout mMainLayout, mRememberedLayout, mChronoButtonsLayout;
|
||||
@ -281,6 +281,7 @@ public class Ankidroid extends Activity implements Runnable
|
||||
|
||||
public void loadDeck(String deckFilename)
|
||||
{
|
||||
Log.i(TAG, "loadDeck - deckFilename = " + deckFilename);
|
||||
this.deckFilename = deckFilename;
|
||||
|
||||
//If I'm not mistaken, the only possibility for deckFilename to be null here is if never existed a deck before
|
||||
@ -295,13 +296,20 @@ public class Ankidroid extends Activity implements Runnable
|
||||
}
|
||||
Log.i(TAG, "loadDeck - SD card mounted and existent file -> Loading deck...");
|
||||
// Open the right deck.
|
||||
AnkiDb.openDatabase(deckFilename);
|
||||
Log.i(TAG, "Deck loaded!");
|
||||
try
|
||||
{
|
||||
AnkiDb.openDatabase(deckFilename);
|
||||
Log.i(TAG, "Deck loaded!");
|
||||
|
||||
// Don't open database in onResume(). Is already opening elsewhere.
|
||||
deckSelected = true;
|
||||
// Start by getting the first card and displaying it.
|
||||
nextCard();
|
||||
} catch (SQLException e)
|
||||
{
|
||||
Log.i(TAG, "The database " + deckFilename + " could not be opened = " + e.getMessage());
|
||||
}
|
||||
|
||||
// Don't open database in onResume(). Is already opening elsewhere.
|
||||
deckSelected = true;
|
||||
// Start by getting the first card and displaying it.
|
||||
nextCard();
|
||||
}
|
||||
}
|
||||
|
||||
@ -418,11 +426,13 @@ public class Ankidroid extends Activity implements Runnable
|
||||
|
||||
public void openDeckPicker()
|
||||
{
|
||||
Log.i(TAG, "openDeckPicker");
|
||||
deckSelected = false; // Make sure we open the database again in
|
||||
// onResume() if user pressed "back".
|
||||
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");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -453,14 +463,21 @@ public class Ankidroid extends Activity implements Runnable
|
||||
{
|
||||
Log.i(TAG, "onResume() - deckFilename = " + deckFilename + ", deckSelected = " + deckSelected);
|
||||
super.onResume();
|
||||
if (!deckSelected && isSdCardMounted())
|
||||
if(isSdCardMounted())
|
||||
{
|
||||
Log.i(TAG, "onResume() - No deck selected before");
|
||||
//AnkiDb.openDatabase(deckFilename);
|
||||
//loadDeck(deckFilename);
|
||||
//deckSelected = true;
|
||||
displayProgressDialogAndLoadDeck();
|
||||
if (!deckSelected)
|
||||
{
|
||||
Log.i(TAG, "onResume() - No deck selected before");
|
||||
//AnkiDb.openDatabase(deckFilename);
|
||||
//loadDeck(deckFilename);
|
||||
//deckSelected = true;
|
||||
displayProgressDialogAndLoadDeck();
|
||||
}
|
||||
} else
|
||||
{
|
||||
deckSelected = false;
|
||||
}
|
||||
|
||||
Log.i(TAG, "onResume() - Ending");
|
||||
}
|
||||
|
||||
@ -495,7 +512,7 @@ public class Ankidroid extends Activity implements Runnable
|
||||
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)
|
||||
if(deckSelected && isSdCardMounted())
|
||||
showOrHideControls();
|
||||
}
|
||||
}
|
||||
@ -532,23 +549,27 @@ public class Ankidroid extends Activity implements Runnable
|
||||
|
||||
private void showControls(boolean show)
|
||||
{
|
||||
if (show)
|
||||
if(layoutInitialized)
|
||||
{
|
||||
mCard.setVisibility(View.VISIBLE);
|
||||
mSelectRemembered.setVisibility(View.VISIBLE);
|
||||
mSelectNotRemembered.setVisibility(View.VISIBLE);
|
||||
mFlipCard.setVisibility(View.VISIBLE);
|
||||
showOrHideControls();
|
||||
} else
|
||||
{
|
||||
mCard.setVisibility(View.GONE);
|
||||
mSelectRemembered.setVisibility(View.GONE);
|
||||
mSelectNotRemembered.setVisibility(View.GONE);
|
||||
mFlipCard.setVisibility(View.GONE);
|
||||
mTimer.setVisibility(View.GONE);
|
||||
mToggleWhiteboard.setVisibility(View.GONE);
|
||||
mWhiteboard.setVisibility(View.GONE);
|
||||
if (show)
|
||||
{
|
||||
mCard.setVisibility(View.VISIBLE);
|
||||
mSelectRemembered.setVisibility(View.VISIBLE);
|
||||
mSelectNotRemembered.setVisibility(View.VISIBLE);
|
||||
mFlipCard.setVisibility(View.VISIBLE);
|
||||
showOrHideControls();
|
||||
} else
|
||||
{
|
||||
mCard.setVisibility(View.GONE);
|
||||
mSelectRemembered.setVisibility(View.GONE);
|
||||
mSelectNotRemembered.setVisibility(View.GONE);
|
||||
mFlipCard.setVisibility(View.GONE);
|
||||
mTimer.setVisibility(View.GONE);
|
||||
mToggleWhiteboard.setVisibility(View.GONE);
|
||||
mWhiteboard.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -692,8 +713,16 @@ public class Ankidroid extends Activity implements Runnable
|
||||
|
||||
public void run()
|
||||
{
|
||||
Log.i(TAG, "Ankidroid loader thread - run");
|
||||
loadDeck(deckFilename);
|
||||
handler.sendEmptyMessage(0);
|
||||
//if(deckSelected)
|
||||
//{
|
||||
handler.sendEmptyMessage(0);
|
||||
//} else
|
||||
//{
|
||||
//Dismiss dialog and show something to indicate to the user that a deck has not been loaded
|
||||
//dialog.dismiss();
|
||||
//}
|
||||
}
|
||||
|
||||
private Handler handler = new Handler()
|
||||
@ -703,7 +732,6 @@ public class Ankidroid extends Activity implements Runnable
|
||||
dialog.dismiss();
|
||||
showControls(true);
|
||||
displayCardQuestion();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@ -717,7 +745,7 @@ public class Ankidroid extends Activity implements Runnable
|
||||
* is going to be ejected, so applications can clean up any files they have open.
|
||||
*/
|
||||
public void registerExternalStorageListener() {
|
||||
/*if (mUnmountReceiver == null) {
|
||||
if (mUnmountReceiver == null) {
|
||||
mUnmountReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@ -728,12 +756,17 @@ public class Ankidroid extends Activity implements Runnable
|
||||
// which would be wrong because the song ids and
|
||||
// card id might not match.
|
||||
//closeExternalStorageFiles(intent.getData().getPath());
|
||||
Log.i(TAG, "mUnmountReceiver - Action = Media Eject");
|
||||
closeExternalStorageFiles();
|
||||
} 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, "mUnmountReceiver - Action = Media Mounted");
|
||||
hideSdError();
|
||||
onResume();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -742,6 +775,46 @@ public class Ankidroid extends Activity implements Runnable
|
||||
iFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
||||
iFilter.addDataScheme("file");
|
||||
registerReceiver(mUnmountReceiver, iFilter);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
private void closeExternalStorageFiles()
|
||||
{
|
||||
AnkiDb.closeDatabase();
|
||||
displaySdError();
|
||||
}
|
||||
|
||||
private void displaySdError()
|
||||
{
|
||||
showControls(false);
|
||||
showSdCardElements(true);
|
||||
}
|
||||
|
||||
private void hideSdError()
|
||||
{
|
||||
showControls(true);
|
||||
showSdCardElements(false);
|
||||
}
|
||||
|
||||
private void showSdCardElements(boolean show)
|
||||
{
|
||||
if(layoutInitialized)
|
||||
{
|
||||
LinearLayout layout = (LinearLayout) findViewById(R.id.sd_layout);
|
||||
TextView tv = (TextView) findViewById(R.id.sd_message);
|
||||
ImageView image = (ImageView) findViewById(R.id.sd_icon);
|
||||
if(show)
|
||||
{
|
||||
layout.setVisibility(View.VISIBLE);
|
||||
tv.setVisibility(View.VISIBLE);
|
||||
image.setVisibility(View.VISIBLE);
|
||||
} else
|
||||
{
|
||||
layout.setVisibility(View.GONE);
|
||||
tv.setVisibility(View.GONE);
|
||||
image.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -5,20 +5,24 @@ import java.io.FileFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.database.SQLException;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
@ -54,6 +58,8 @@ public class DeckPicker extends Activity implements Runnable
|
||||
private boolean mIsFinished = true;
|
||||
|
||||
private boolean mDeckIsSelected = false;
|
||||
|
||||
private BroadcastReceiver mUnmountReceiver = null;
|
||||
|
||||
AdapterView.OnItemClickListener mDeckSelHandler = new AdapterView.OnItemClickListener()
|
||||
{
|
||||
@ -69,8 +75,12 @@ public class DeckPicker extends Activity implements Runnable
|
||||
{
|
||||
Log.i(TAG, "DeckPicker - onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
registerExternalStorageListener();
|
||||
|
||||
mSelf = this;
|
||||
String deckPath = getIntent().getStringExtra("com.ichi2.anki.Ankidroid.DeckPath");
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
|
||||
String deckPath = preferences.getString("deckPath", "/sdcard");
|
||||
setContentView(R.layout.main);
|
||||
|
||||
mDeckList = new ArrayList<HashMap<String, String>>();
|
||||
@ -160,10 +170,13 @@ public class DeckPicker extends Activity implements Runnable
|
||||
thread.start();
|
||||
} else
|
||||
{
|
||||
Log.i(TAG, "populateDeckList - No decks found.");
|
||||
//There is no sd card attached (wrap this code in a function called something like isSdMounted()
|
||||
//and place it in a utils class
|
||||
if(!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
|
||||
{
|
||||
Log.i(TAG, "populateDeckList - No sd card.");
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage("The SD card could not be read. Please, turn off USB storage.");
|
||||
builder.setPositiveButton("OK", null);
|
||||
@ -184,6 +197,7 @@ public class DeckPicker extends Activity implements Runnable
|
||||
mDeckList.clear();
|
||||
mDeckList.addAll(tree);
|
||||
mDeckListView.clearChoices();
|
||||
mDeckListAdapter.notifyDataSetChanged();
|
||||
Log.i(TAG, "DeckPicker - populateDeckList, Ending");
|
||||
}
|
||||
|
||||
@ -235,6 +249,7 @@ public class DeckPicker extends Activity implements Runnable
|
||||
private void waitForDeckLoaderThread()
|
||||
{
|
||||
mDeckIsSelected = true;
|
||||
Log.i(TAG, "DeckPicker - waitForDeckLoaderThread(), mDeckIsSelected set to true");
|
||||
mLock.lock();
|
||||
try
|
||||
{
|
||||
@ -251,6 +266,7 @@ public class DeckPicker extends Activity implements Runnable
|
||||
|
||||
public void run()
|
||||
{
|
||||
Log.i(TAG, "Thread run - Beginning");
|
||||
int len = 0;
|
||||
if (mFileList != null)
|
||||
len = mFileList.length;
|
||||
@ -260,14 +276,18 @@ public class DeckPicker extends Activity implements Runnable
|
||||
mLock.lock();
|
||||
try
|
||||
{
|
||||
Log.i(TAG, "Thread run - Inside lock");
|
||||
|
||||
mIsFinished = false;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
|
||||
// Don't load any more decks if one has already been
|
||||
// selected.
|
||||
Log.i(TAG, "Thread run - Before break mDeckIsSelected = " + mDeckIsSelected);
|
||||
if (mDeckIsSelected)
|
||||
break;
|
||||
|
||||
|
||||
String path = mFileList[i].getAbsolutePath();
|
||||
Deck deck;
|
||||
@ -330,9 +350,56 @@ public class DeckPicker extends Activity implements Runnable
|
||||
}
|
||||
|
||||
mDeckListAdapter.notifyDataSetChanged();
|
||||
Log.i(TAG, "DeckPicker - mDeckList notified of changes");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Registers an intent to listen for ACTION_MEDIA_EJECT notifications.
|
||||
* The intent will call closeExternalStorageFiles() if the external media
|
||||
* is going to be ejected, so applications can clean up any files they have open.
|
||||
*/
|
||||
public void registerExternalStorageListener() {
|
||||
if (mUnmountReceiver == null) {
|
||||
mUnmountReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
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;
|
||||
populateDeckList(deckPath);
|
||||
}
|
||||
}
|
||||
};
|
||||
IntentFilter iFilter = new IntentFilter();
|
||||
iFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
|
||||
iFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
||||
iFilter.addDataScheme("file");
|
||||
registerReceiver(mUnmountReceiver, iFilter);
|
||||
}
|
||||
}
|
||||
/*private void logTree(TreeSet<HashMap<String, String>> tree)
|
||||
{
|
||||
Iterator<HashMap<String, String>> it = tree.iterator();
|
||||
|
Loading…
Reference in New Issue
Block a user