use of com.ichi2.libanki.DB in project Anki-Android by Ramblurr.
the class DeckTask method doInBackgroundOpenCollection.
private TaskData doInBackgroundOpenCollection(TaskData... params) {
// Log.i(AnkiDroidApp.TAG, "doInBackgroundOpenCollection");
long time = Utils.intNow(1000);
Resources res = AnkiDroidApp.getInstance().getBaseContext().getResources();
String collectionFile = params[0].getString();
SharedPreferences prefs = AnkiDroidApp.getSharedPrefs(AnkiDroidApp.getInstance().getBaseContext());
// see, if a collection is still opened
Collection oldCol = AnkiDroidApp.getCol();
Collection col = null;
publishProgress(new TaskData(res.getString(R.string.open_collection)));
if (!(AnkiDroidApp.colIsOpen() && oldCol.getPath().equals(collectionFile))) {
// android's delete db bug
if (BackupManager.safetyBackupNeeded(collectionFile)) {
publishProgress(new TaskData(res.getString(R.string.backup_collection)));
BackupManager.performBackup(collectionFile);
}
publishProgress(new TaskData(res.getString(R.string.open_collection)));
// load collection
try {
col = AnkiDroidApp.openCollection(collectionFile);
} catch (RuntimeException e) {
BackupManager.restoreCollectionIfMissing(collectionFile);
Log.e(AnkiDroidApp.TAG, "doInBackgroundOpenCollection - RuntimeException on opening collection: " + e);
AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundOpenCollection");
return new TaskData(false);
}
// create tutorial deck if needed
if (prefs.contains("createTutorial") && prefs.getBoolean("createTutorial", false)) {
prefs.edit().remove("createTutorial").commit();
publishProgress(new TaskData(res.getString(R.string.tutorial_load)));
doInBackgroundLoadTutorial(new TaskData(col));
}
} else {
// Log.i(AnkiDroidApp.TAG, "doInBackgroundOpenCollection: collection still open - reusing it");
col = oldCol;
}
Object[] counts = null;
DeckTask.TaskData result = doInBackgroundLoadDeckCounts(new TaskData(col));
if (result != null) {
counts = result.getObjArray();
}
if (prefs.getBoolean("splashScreen", false)) {
long millies = Utils.intNow(1000) - time;
if (millies < 1000) {
try {
Thread.sleep(1200 - millies);
} catch (InterruptedException e) {
}
}
}
return new TaskData(col, counts);
}
use of com.ichi2.libanki.DB in project Anki-Android by Ramblurr.
the class DeckTask method doInBackgroundImportReplace.
private TaskData doInBackgroundImportReplace(TaskData... params) {
// Log.i(AnkiDroidApp.TAG, "doInBackgroundImportReplace");
Collection col = params[0].getCollection();
String path = params[0].getString();
Resources res = AnkiDroidApp.getInstance().getBaseContext().getResources();
// extract the deck from the zip file
String fileDir = AnkiDroidApp.getCurrentAnkiDroidDirectory() + "/tmpzip";
File dir = new File(fileDir);
if (dir.exists()) {
BackupManager.removeDir(dir);
}
publishProgress(new TaskData(res.getString(R.string.import_unpacking)));
// from anki2.py
String colFile = fileDir + "/collection.anki2";
ZipFile zip;
try {
zip = new ZipFile(new File(path), ZipFile.OPEN_READ);
} catch (IOException e) {
Log.e(AnkiDroidApp.TAG, "doInBackgroundImportReplace - Error while unzipping: ", e);
AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundImportReplace0");
return new TaskData(false);
}
if (!Utils.unzipFiles(zip, fileDir, new String[] { "collection.anki2", "media" }, null) || !(new File(colFile)).exists()) {
return new TaskData(-2, null, false);
}
Collection tmpCol = null;
try {
tmpCol = Storage.Collection(colFile);
if (!tmpCol.validCollection()) {
tmpCol.close();
return new TaskData(-2, null, false);
}
} finally {
if (tmpCol != null) {
tmpCol.close();
}
}
publishProgress(new TaskData(res.getString(R.string.importing_collection)));
String colPath;
if (col != null) {
// unload collection and trigger a backup
colPath = col.getPath();
AnkiDroidApp.closeCollection(true);
BackupManager.performBackup(colPath, true);
}
// overwrite collection
colPath = AnkiDroidApp.getCollectionPath();
File f = new File(colFile);
f.renameTo(new File(colPath));
int addedCount = -1;
try {
col = AnkiDroidApp.openCollection(colPath);
// because users don't have a backup of media, it's safer to import new
// data and rely on them running a media db check to get rid of any
// unwanted media. in the future we might also want to duplicate this step
// import media
HashMap<String, String> nameToNum = new HashMap<String, String>();
HashMap<String, String> numToName = new HashMap<String, String>();
File mediaMapFile = new File(fileDir, "media");
if (mediaMapFile.exists()) {
JsonReader jr = new JsonReader(new FileReader(mediaMapFile));
jr.beginObject();
String name;
String num;
while (jr.hasNext()) {
num = jr.nextName();
name = jr.nextString();
nameToNum.put(name, num);
numToName.put(num, name);
}
jr.endObject();
jr.close();
}
String mediaDir = col.getMedia().getDir();
int total = nameToNum.size();
int i = 0;
for (Map.Entry<String, String> entry : nameToNum.entrySet()) {
String file = entry.getKey();
String c = entry.getValue();
File of = new File(mediaDir, file);
if (!of.exists()) {
Utils.unzipFiles(zip, mediaDir, new String[] { c }, numToName);
}
++i;
publishProgress(new TaskData(res.getString(R.string.import_media_count, (i + 1) * 100 / total)));
}
zip.close();
// delete tmp dir
BackupManager.removeDir(dir);
publishProgress(new TaskData(res.getString(R.string.import_update_counts)));
// Update the counts
DeckTask.TaskData result = doInBackgroundLoadDeckCounts(new TaskData(col));
if (result == null) {
return null;
}
return new TaskData(addedCount, result.getObjArray(), true);
} catch (RuntimeException e) {
Log.e(AnkiDroidApp.TAG, "doInBackgroundImportReplace - RuntimeException: ", e);
AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundImportReplace1");
return new TaskData(false);
} catch (FileNotFoundException e) {
Log.e(AnkiDroidApp.TAG, "doInBackgroundImportReplace - FileNotFoundException: ", e);
AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundImportReplace2");
return new TaskData(false);
} catch (IOException e) {
Log.e(AnkiDroidApp.TAG, "doInBackgroundImportReplace - IOException: ", e);
AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundImportReplace3");
return new TaskData(false);
}
}
use of com.ichi2.libanki.DB in project AnkiChinaAndroid by ankichinateam.
the class DeckPicker method showStartupScreensAndDialogs.
public void showStartupScreensAndDialogs(SharedPreferences preferences, int skip) {
if (!BackupManager.enoughDiscSpace(CollectionHelper.getCurrentAnkiDroidDirectory(this))) {
Timber.i("Not enough space to do backup");
showDialogFragment(DeckPickerNoSpaceLeftDialog.newInstance());
} else if (preferences.getBoolean("noSpaceLeft", false)) {
Timber.i("No space left");
showDialogFragment(DeckPickerBackupNoSpaceLeftDialog.newInstance());
preferences.edit().remove("noSpaceLeft").apply();
} else if ("".equals(preferences.getString("lastVersion", ""))) {
Timber.i("Fresh install");
preferences.edit().putString("lastVersion", VersionUtils.getPkgVersionName()).apply();
onFinishedStartup();
} else if (skip < 2 && !preferences.getString("lastVersion", "").equals(VersionUtils.getPkgVersionName())) {
Timber.i("AnkiDroid is being updated and a collection already exists.");
// The user might appreciate us now, see if they will help us get better?
if (!preferences.contains(UsageAnalytics.ANALYTICS_OPTIN_KEY)) {
showDialogFragment(DeckPickerAnalyticsOptInDialog.newInstance());
}
// For upgrades, we check if we are upgrading
// to a version that contains additions to the database integrity check routine that we would
// like to run on all collections. A missing version number is assumed to be a fresh
// installation of AnkiDroid and we don't run the check.
long current = VersionUtils.getPkgVersionCode();
Timber.i("Current AnkiDroid version: %s", current);
long previous;
if (preferences.contains(UPGRADE_VERSION_KEY)) {
// Upgrading currently installed app
previous = getPreviousVersion(preferences, current);
} else {
// Fresh install
previous = current;
}
preferences.edit().putLong(UPGRADE_VERSION_KEY, current).apply();
// It is rebuilt on the next sync or media check
if (previous < 20300200) {
Timber.i("Deleting media database");
File mediaDb = new File(CollectionHelper.getCurrentAnkiDroidDirectory(this), "collection.media.ad.db2");
if (mediaDb.exists()) {
mediaDb.delete();
}
}
// Recommend the user to do a full-sync if they're upgrading from before 2.3.1beta8
if (previous < 20301208) {
Timber.i("Recommend the user to do a full-sync");
mRecommendFullSync = true;
}
// Fix "font-family" definition in templates created by AnkiDroid before 2.6alhpa23
if (previous < 20600123) {
Timber.i("Fixing font-family definition in templates");
try {
Models models = getCol().getModels();
for (Model m : models.all()) {
String css = m.getString("css");
if (css.contains("font-familiy")) {
m.put("css", css.replace("font-familiy", "font-family"));
models.save(m);
}
}
models.flush();
} catch (JSONException e) {
Timber.e(e, "Failed to upgrade css definitions.");
}
}
// Check if preference upgrade or database check required, otherwise go to new feature screen
int upgradePrefsVersion = AnkiDroidApp.CHECK_PREFERENCES_AT_VERSION;
int upgradeDbVersion = AnkiDroidApp.CHECK_DB_AT_VERSION;
// Specifying a checkpoint in the future is not supported, please don't do it!
if (current < upgradePrefsVersion) {
Timber.e("Checkpoint in future produced.");
UIUtils.showSimpleSnackbar(this, "Invalid value for CHECK_PREFERENCES_AT_VERSION", false);
onFinishedStartup();
return;
}
if (current < upgradeDbVersion) {
Timber.e("Invalid value for CHECK_DB_AT_VERSION");
UIUtils.showSimpleSnackbar(this, "Invalid value for CHECK_DB_AT_VERSION", false);
onFinishedStartup();
return;
}
// Skip full DB check if the basic check is OK
// TODO: remove this variable if we really want to do the full db check on every user
boolean skipDbCheck = false;
// noinspection ConstantConditions
if ((!skipDbCheck && previous < upgradeDbVersion) || previous < upgradePrefsVersion) {
if (previous < upgradePrefsVersion) {
Timber.i("showStartupScreensAndDialogs() running upgradePreferences()");
upgradePreferences(previous);
}
// noinspection ConstantConditions
if (!skipDbCheck && previous < upgradeDbVersion) {
Timber.i("showStartupScreensAndDialogs() running integrityCheck()");
// #5852 - since we may have a warning about disk space, we don't want to force a check database
// and show a warning before the user knows what is happening.
new MaterialDialog.Builder(this).title(R.string.integrity_check_startup_title).content(R.string.integrity_check_startup_content).positiveText(R.string.integrity_check_positive).negativeText(R.string.close).onPositive((materialDialog, dialogAction) -> integrityCheck()).onNeutral((materialDialog, dialogAction) -> this.restartActivity()).onNegative((materialDialog, dialogAction) -> this.restartActivity()).canceledOnTouchOutside(false).cancelable(false).build().show();
} else if (previous < upgradePrefsVersion) {
Timber.i("Updated preferences with no integrity check - restarting activity");
// If integrityCheck() doesn't occur, but we did update preferences we should restart DeckPicker to
// proceed
this.restartActivity();
}
} else {
// If no changes are required we go to the new features activity
// There the "lastVersion" is set, so that this code is not reached again
// if (VersionUtils.isReleaseVersion()) {
// Timber.i("Displaying new features");
// Intent infoIntent = new Intent(this, Info.class);
// infoIntent.putExtra(Info.TYPE_EXTRA, Info.TYPE_NEW_VERSION);
//
// if (skip != 0) {
// startActivityForResultWithAnimation(infoIntent, SHOW_INFO_NEW_VERSION,
// ActivityTransitionAnimation.LEFT);
// } else {
// startActivityForResultWithoutAnimation(infoIntent, SHOW_INFO_NEW_VERSION);
// }
// } else {
Timber.i("Dev Build - not showing 'new features'");
// Don't show new features dialog for development builds
preferences.edit().putString("lastVersion", VersionUtils.getPkgVersionName()).apply();
String ver = getResources().getString(R.string.updated_version, VersionUtils.getPkgVersionName());
UIUtils.showSnackbar(this, ver, true, -1, null, findViewById(R.id.root_layout), null);
showStartupScreensAndDialogs(preferences, 2);
// }
}
} else {
// this is the main call when there is nothing special required
Timber.i("No startup screens required");
onFinishedStartup();
}
}
use of com.ichi2.libanki.DB in project AnkiChinaAndroid by ankichinateam.
the class CollectionTask method doInBackgroundAddNote.
private TaskData doInBackgroundAddNote(TaskData param) {
Timber.d("doInBackgroundAddNote");
Note note = param.getNote();
Collection col = getCol();
try {
DB db = col.getDb();
db.getDatabase().beginTransaction();
try {
publishProgress(new TaskData(col.addNote(note)));
db.getDatabase().setTransactionSuccessful();
} finally {
db.getDatabase().endTransaction();
}
} catch (RuntimeException e) {
Timber.e(e, "doInBackgroundAddNote - RuntimeException on adding note");
AnkiDroidApp.sendExceptionReport(e, "doInBackgroundAddNote");
return new TaskData(false);
}
return new TaskData(true);
}
use of com.ichi2.libanki.DB in project AnkiChinaAndroid by ankichinateam.
the class DeckPickerCheckDatabaseListenerTest method validResultWithLockedDatabaseWillShowLockedDialog.
@Test
public void validResultWithLockedDatabaseWillShowLockedDialog() {
CheckDatabaseResult lockedDb = lockedDatabase();
TaskData result = validResultWithData(lockedDb);
execute(result);
assertThat("Load Failed dialog should not be shown if invalid data is supplied", !impl.didDisplayDialogLoadFailed());
assertThat("Locked Database dialog should be shown if Db was locked", impl.didDisplayLockedDialog());
assertThat("Dialog should not be displayed", !impl.didDisplayMessage());
}
Aggregations