Search in sources :

Example 11 with IMPORT

use of com.ichi2.async.CollectionTask.TASK_TYPE.IMPORT in project Anki-Android by ankidroid.

the class Media method maybeUpgrade.

public void maybeUpgrade() {
    String oldpath = dir() + ".db";
    File oldDbFile = new File(oldpath);
    if (oldDbFile.exists()) {
        mDb.execute(String.format(Locale.US, "attach \"%s\" as old", oldpath));
        try {
            String sql = "insert into media\n" + " select m.fname, csum, mod, ifnull((select 1 from log l2 where l2.fname=m.fname), 0) as dirty\n" + " from old.media m\n" + " left outer join old.log l using (fname)\n" + " union\n" + " select fname, null, 0, 1 from old.log where type=" + Consts.CARD_TYPE_LRN + ";";
            mDb.execute(sql);
            mDb.execute("delete from meta");
            mDb.execute("insert into meta select dirMod, usn from old.meta");
            mDb.commit();
        } catch (Exception e) {
            // if we couldn't import the old db for some reason, just start anew
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            mCol.log("failed to import old media db:" + sw.toString());
        }
        mDb.execute("detach old");
        File newDbFile = new File(oldpath + ".old");
        if (newDbFile.exists()) {
            newDbFile.delete();
        }
        oldDbFile.renameTo(newDbFile);
    }
}
Also used : StringWriter(java.io.StringWriter) ZipFile(java.util.zip.ZipFile) File(java.io.File) EmptyMediaException(com.ichi2.libanki.exception.EmptyMediaException) IOException(java.io.IOException) SQLException(android.database.SQLException) FileNotFoundException(java.io.FileNotFoundException) PrintWriter(java.io.PrintWriter)

Example 12 with IMPORT

use of com.ichi2.async.CollectionTask.TASK_TYPE.IMPORT in project Anki-Android by Ramblurr.

the class DeckTask method doInBackgroundImportAdd.

private TaskData doInBackgroundImportAdd(TaskData... params) {
    // Log.i(AnkiDroidApp.TAG, "doInBackgroundImportAdd");
    Resources res = AnkiDroidApp.getInstance().getBaseContext().getResources();
    Collection col = params[0].getCollection();
    String path = params[0].getString();
    boolean sharedDeckImport = params[0].getBoolean();
    ProgressCallback pc = null;
    // don't report progress on shared deck import (or maybe should we?)
    if (!sharedDeckImport) {
        pc = new ProgressCallback(this, res);
    }
    int addedCount = -1;
    try {
        Anki2Importer imp = new Anki2Importer(col, path, pc);
        AnkiDb ankiDB = col.getDb();
        ankiDB.getDatabase().beginTransaction();
        try {
            addedCount = imp.run();
            ankiDB.getDatabase().setTransactionSuccessful();
        } finally {
            ankiDB.getDatabase().endTransaction();
            if (sharedDeckImport) {
                File tmpFile = new File(path);
                tmpFile.delete();
            }
        }
        if (addedCount >= 0) {
            ankiDB.execute("VACUUM");
            ankiDB.execute("ANALYZE");
        }
        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, "doInBackgroundImportAdd - RuntimeException on importing cards: ", e);
        AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundImportAdd");
        return new TaskData(false);
    } catch (IOException e) {
        Log.e(AnkiDroidApp.TAG, "doInBackgroundImportAdd - IOException on importing cards: ", e);
        AnkiDroidApp.saveExceptionReportFile(e, "doInBackgroundImportAdd");
        return new TaskData(false);
    }
}
Also used : Anki2Importer(com.ichi2.libanki.importer.Anki2Importer) AnkiDb(com.ichi2.anki.AnkiDb) IOException(java.io.IOException) Collection(com.ichi2.libanki.Collection) Resources(android.content.res.Resources) ZipFile(java.util.zip.ZipFile) File(java.io.File)

Example 13 with IMPORT

use of com.ichi2.async.CollectionTask.TASK_TYPE.IMPORT 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);
    }
}
Also used : HashMap(java.util.HashMap) FileNotFoundException(java.io.FileNotFoundException) IOException(java.io.IOException) ZipFile(java.util.zip.ZipFile) Collection(com.ichi2.libanki.Collection) JsonReader(com.google.gson.stream.JsonReader) FileReader(java.io.FileReader) Resources(android.content.res.Resources) ZipFile(java.util.zip.ZipFile) File(java.io.File) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap)

Example 14 with IMPORT

use of com.ichi2.async.CollectionTask.TASK_TYPE.IMPORT in project AnkiChinaAndroid by ankichinateam.

the class AnkiActivity method showImportDialog.

@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public void showImportDialog(int id, String message) {
    // On API19+ we only use import dialog to confirm, otherwise we use it the whole time
    if ((CompatHelper.getSdkVersion() < 19) || (id == ImportDialog.DIALOG_IMPORT_ADD_CONFIRM) || (id == ImportDialog.DIALOG_IMPORT_REPLACE_CONFIRM)) {
        Timber.d("showImportDialog() delegating to ImportDialog");
        AsyncDialogFragment newFragment = ImportDialog.newInstance(id, message, this);
        showAsyncDialogFragment(newFragment);
    } else {
        Timber.d("showImportDialog() delegating to file picker intent");
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
        intent.putExtra("android.content.extra.FANCY", true);
        intent.putExtra("android.content.extra.SHOW_FILESIZE", true);
        startActivityForResultWithoutAnimation(intent, PICK_APKG_FILE);
    }
}
Also used : AsyncDialogFragment(com.ichi2.anki.dialogs.AsyncDialogFragment) PendingIntent(android.app.PendingIntent) CustomTabsIntent(androidx.browser.customtabs.CustomTabsIntent) Intent(android.content.Intent) TargetApi(android.annotation.TargetApi)

Example 15 with IMPORT

use of com.ichi2.async.CollectionTask.TASK_TYPE.IMPORT in project AnkiChinaAndroid by ankichinateam.

the class DialogHandler method handleMessage.

@Override
public void handleMessage(Message msg) {
    Bundle msgData = msg.getData();
    String messageName = sMessageNameList[msg.what];
    UsageAnalytics.sendAnalyticsScreenView(messageName);
    Timber.i("Handling Message: %s", messageName);
    if (msg.what == MSG_SHOW_COLLECTION_LOADING_ERROR_DIALOG) {
        // Collection could not be opened
        mActivity.get().showDatabaseErrorDialog(DatabaseErrorDialog.DIALOG_LOAD_FAILED);
    } else if (msg.what == MSG_SHOW_COLLECTION_IMPORT_REPLACE_DIALOG) {
        // Handle import of collection package APKG
        mActivity.get().showImportDialog(ImportDialog.DIALOG_IMPORT_REPLACE_CONFIRM, msgData.getString("importPath"));
    } else if (msg.what == MSG_SHOW_COLLECTION_IMPORT_ADD_DIALOG) {
        // Handle import of deck package APKG
        mActivity.get().showImportDialog(ImportDialog.DIALOG_IMPORT_ADD_CONFIRM, msgData.getString("importPath"));
    } else if (msg.what == MSG_SHOW_SYNC_ERROR_DIALOG) {
        if (mActivity.get() instanceof DeckPicker) {
            int id = msgData.getInt("dialogType");
            String message = msgData.getString("dialogMessage");
            ((DeckPicker) mActivity.get()).showSyncErrorDialog(id, message);
        }
    } else if (msg.what == MSG_SHOW_EXPORT_COMPLETE_DIALOG) {
        // Export complete
        AsyncDialogFragment f = DeckPickerExportCompleteDialog.newInstance(msgData.getString("exportPath"));
        mActivity.get().showAsyncDialogFragment(f);
    } else if (msg.what == MSG_SHOW_MEDIA_CHECK_COMPLETE_DIALOG) {
        if (mActivity.get() instanceof DeckPicker) {
            // Media check results
            int id = msgData.getInt("dialogType");
            if (id != MediaCheckDialog.DIALOG_CONFIRM_MEDIA_CHECK) {
                List<List<String>> checkList = new ArrayList<>();
                checkList.add(msgData.getStringArrayList("nohave"));
                checkList.add(msgData.getStringArrayList("unused"));
                checkList.add(msgData.getStringArrayList("invalid"));
                ((DeckPicker) mActivity.get()).showMediaCheckDialog(id, checkList);
            }
        }
    } else if (msg.what == MSG_SHOW_DATABASE_ERROR_DIALOG) {
        // Database error dialog
        mActivity.get().showDatabaseErrorDialog(msgData.getInt("dialogType"));
    } else if (msg.what == MSG_SHOW_FORCE_FULL_SYNC_DIALOG) {
        // Confirmation dialog for forcing full sync
        ConfirmationDialog dialog = new ConfirmationDialog();
        Runnable confirm = new Runnable() {

            @Override
            public void run() {
                // Bypass the check once the user confirms
                CollectionHelper.getInstance().getCol(AnkiDroidApp.getInstance()).modSchemaNoCheck();
            }
        };
        dialog.setConfirm(confirm);
        dialog.setArgs(msgData.getString("message"));
        (mActivity.get()).showDialogFragment(dialog);
    } else if (msg.what == MSG_DO_SYNC) {
        if (mActivity.get() instanceof DeckPicker) {
            SharedPreferences preferences = AnkiDroidApp.getSharedPrefs(mActivity.get());
            Resources res = mActivity.get().getResources();
            Collection col = mActivity.get().getCol();
            String hkey = preferences.getString("hkey", "");
            long millisecondsSinceLastSync = col.getTime().intTimeMS() - preferences.getLong("lastSyncTime", 0);
            boolean limited = millisecondsSinceLastSync < INTENT_SYNC_MIN_INTERVAL;
            if (!limited && hkey.length() > 0 && Connection.isOnline()) {
                ((DeckPicker) mActivity.get()).sync();
            } else {
                String err = res.getString(R.string.sync_error);
                if (limited) {
                    long remainingTimeInSeconds = Math.max((INTENT_SYNC_MIN_INTERVAL - millisecondsSinceLastSync) / 1000, 1);
                    // getQuantityString needs an int
                    int remaining = (int) Math.min(Integer.MAX_VALUE, remainingTimeInSeconds);
                    String message = res.getQuantityString(R.plurals.sync_automatic_sync_needs_more_time, remaining, remaining);
                    mActivity.get().showSimpleNotification(err, message, NotificationChannels.Channel.SYNC);
                } else {
                    mActivity.get().showSimpleNotification(err, res.getString(R.string.youre_offline), NotificationChannels.Channel.SYNC);
                }
            }
            mActivity.get().finishWithoutAnimation();
        }
    }
}
Also used : SharedPreferences(android.content.SharedPreferences) Bundle(android.os.Bundle) Collection(com.ichi2.libanki.Collection) ArrayList(java.util.ArrayList) List(java.util.List) Resources(android.content.res.Resources) DeckPicker(com.ichi2.anki.DeckPicker)

Aggregations

File (java.io.File)11 Test (org.junit.Test)9 Collection (com.ichi2.libanki.Collection)8 AnkiPackageImporter (com.ichi2.libanki.importer.AnkiPackageImporter)7 IOException (java.io.IOException)7 Note (com.ichi2.libanki.Note)6 TextImporter (com.ichi2.libanki.importer.TextImporter)6 FileNotFoundException (java.io.FileNotFoundException)6 HashMap (java.util.HashMap)6 Resources (android.content.res.Resources)5 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)5 Anki2Importer (com.ichi2.libanki.importer.Anki2Importer)5 ArrayList (java.util.ArrayList)5 Cursor (android.database.Cursor)4 InstrumentedTest (com.ichi2.anki.tests.InstrumentedTest)4 Importer (com.ichi2.libanki.importer.Importer)4 NoteImporter (com.ichi2.libanki.importer.NoteImporter)4 FileOutputStream (java.io.FileOutputStream)4 ImportExportException (com.ichi2.anki.exception.ImportExportException)3 List (java.util.List)3