Search in sources :

Example 41 with Media

use of com.ichi2.libanki.Media 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();
    }
}
Also used : Bundle(android.os.Bundle) NonNull(androidx.annotation.NonNull) Uri(android.net.Uri) ImageView(android.widget.ImageView) ColorDrawable(android.graphics.drawable.ColorDrawable) DialogHandler(com.ichi2.anki.dialogs.DialogHandler) NavigationBarItemView(com.google.android.material.navigation.NavigationBarItemView) Manifest(android.Manifest) Decks(com.ichi2.libanki.Decks) Handler(android.os.Handler) JSONException(com.ichi2.utils.JSONException) Fragment(androidx.fragment.app.Fragment) ForegroundColorSpan(android.text.style.ForegroundColorSpan) ContextCompat(androidx.core.content.ContextCompat) DeckPickerBackupNoSpaceLeftDialog(com.ichi2.anki.dialogs.DeckPickerBackupNoSpaceLeftDialog) IntentFilter(android.content.IntentFilter) StringRes(androidx.annotation.StringRes) Nullable(androidx.annotation.Nullable) Message(android.os.Message) HostNumFactory(com.ichi2.anki.web.HostNumFactory) Consts(com.ichi2.libanki.Consts) OKHttpUtil(com.ichi2.utils.OKHttpUtil) MobclickAgent(com.umeng.analytics.MobclickAgent) DeckPickerExportCompleteDialog(com.ichi2.anki.dialogs.DeckPickerExportCompleteDialog) Models(com.ichi2.libanki.Models) SimpleDateFormat(java.text.SimpleDateFormat) Dialog(android.app.Dialog) SdCardReceiver(com.ichi2.anki.receiver.SdCardReceiver) URL_PRIVATE(com.ichi2.libanki.Consts.URL_PRIVATE) ArrayList(java.util.ArrayList) CustomSyncServerUrlException(com.ichi2.libanki.sync.CustomSyncServerUrlException) SpannableStringBuilder(android.text.SpannableStringBuilder) DeckPickerNoSpaceLeftDialog(com.ichi2.anki.dialogs.DeckPickerNoSpaceLeftDialog) Calendar(java.util.Calendar) Toast(android.widget.Toast) Menu(android.view.Menu) Connection(com.ichi2.async.Connection) Response(okhttp3.Response) AnkiPackageImporter(com.ichi2.libanki.importer.AnkiPackageImporter) Call(okhttp3.Call) CHECK_MEDIA(com.ichi2.async.CollectionTask.TASK_TYPE.CHECK_MEDIA) FragmentManager(androidx.fragment.app.FragmentManager) Beta(com.tencent.bugly.beta.Beta) SpannableString(android.text.SpannableString) ALL_DECKS_ID(com.ichi2.anki.SelfStudyActivity.ALL_DECKS_ID) URL_USER_PROTOCOL(com.ichi2.libanki.Consts.URL_USER_PROTOCOL) TextUtils(android.text.TextUtils) IOException(java.io.IOException) File(java.io.File) Gravity(android.view.Gravity) SharedPreferences(android.content.SharedPreferences) TypedValue(android.util.TypedValue) ActivityTransitionAnimation(com.ichi2.anim.ActivityTransitionAnimation) EditText(android.widget.EditText) AsyncDialogFragment(com.ichi2.anki.dialogs.AsyncDialogFragment) PackageManager(android.content.pm.PackageManager) Date(java.util.Date) WindowManager(android.view.WindowManager) UnderlineSpan(android.text.style.UnderlineSpan) UsageAnalytics(com.ichi2.anki.analytics.UsageAnalytics) ClickableSpan(android.text.style.ClickableSpan) ExportDialog(com.ichi2.anki.dialogs.ExportDialog) DeviceID(com.ichi2.libanki.DeviceID) ConfirmationDialog(com.ichi2.anki.dialogs.ConfirmationDialog) Permissions(com.ichi2.utils.Permissions) AnkiChinaSyncer(com.ichi2.libanki.sync.AnkiChinaSyncer) JSONObject(org.json.JSONObject) NOT_LOGIN_ANKI_CHINA(com.ichi2.anki.MyAccount.NOT_LOGIN_ANKI_CHINA) View(android.view.View) TaskData(com.ichi2.async.TaskData) SyncStatus(com.ichi2.utils.SyncStatus) FIND_EMPTY_CARDS(com.ichi2.async.CollectionTask.TASK_TYPE.FIND_EMPTY_CARDS) ParseException(java.text.ParseException) BottomNavigationView(com.google.android.material.bottomnavigation.BottomNavigationView) BroadcastReceiver(android.content.BroadcastReceiver) DatabaseErrorDialog(com.ichi2.anki.dialogs.DatabaseErrorDialog) DisplayMetrics(android.util.DisplayMetrics) ViewGroup(android.view.ViewGroup) Timber(timber.log.Timber) List(java.util.List) TextView(android.widget.TextView) RelativeLayout(android.widget.RelativeLayout) TaskListenerWithContext(com.ichi2.async.TaskListenerWithContext) ViewPropertyAnimator(android.view.ViewPropertyAnimator) MaterialDialog(com.afollestad.materialdialogs.MaterialDialog) Window(android.view.Window) VersionUtils(com.ichi2.utils.VersionUtils) Context(android.content.Context) TaskListener(com.ichi2.async.TaskListener) Spanned(android.text.Spanned) KeyEvent(android.view.KeyEvent) GravityEnum(com.afollestad.materialdialogs.GravityEnum) DeckPickerAnalyticsOptInDialog(com.ichi2.anki.dialogs.DeckPickerAnalyticsOptInDialog) Intent(android.content.Intent) ViewPager2(androidx.viewpager2.widget.ViewPager2) Collection(com.ichi2.libanki.Collection) StyledProgressDialog(com.ichi2.themes.StyledProgressDialog) MenuItem(android.view.MenuItem) FragmentStateAdapter(androidx.viewpager2.adapter.FragmentStateAdapter) CHECK_DATABASE(com.ichi2.async.CollectionTask.TASK_TYPE.CHECK_DATABASE) Lifecycle(androidx.lifecycle.Lifecycle) REPAIR_COLLECTION(com.ichi2.async.CollectionTask.TASK_TYPE.REPAIR_COLLECTION) WidgetStatus(com.ichi2.widget.WidgetStatus) MotionEvent(android.view.MotionEvent) SyncErrorDialog(com.ichi2.anki.dialogs.SyncErrorDialog) Model(com.ichi2.libanki.Model) ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) Bugly(com.tencent.bugly.Bugly) LOAD_COLLECTION_COMPLETE(com.ichi2.async.CollectionTask.TASK_TYPE.LOAD_COLLECTION_COMPLETE) UMConfigure(com.umeng.commonsdk.UMConfigure) PlatformConfig(com.umeng.socialize.PlatformConfig) ActivityCompat(androidx.core.app.ActivityCompat) CollectionTask(com.ichi2.async.CollectionTask) BottomNavigationMenuView(com.google.android.material.bottomnavigation.BottomNavigationMenuView) Color(android.graphics.Color) MediaCheckDialog(com.ichi2.anki.dialogs.MediaCheckDialog) LOAD_DECK_COUNTS(com.ichi2.async.CollectionTask.TASK_TYPE.LOAD_DECK_COUNTS) VisibleForTesting(androidx.annotation.VisibleForTesting) CustomStyleDialog(com.ichi2.ui.CustomStyleDialog) Resources(android.content.res.Resources) SpannableStringBuilder(android.text.SpannableStringBuilder) Model(com.ichi2.libanki.Model) JSONException(com.ichi2.utils.JSONException) Models(com.ichi2.libanki.Models) SpannableString(android.text.SpannableString) File(java.io.File)

Example 42 with Media

use of com.ichi2.libanki.Media 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)

Example 43 with Media

use of com.ichi2.libanki.Media in project AnkiChinaAndroid by ankichinateam.

the class Connection method doInBackgroundSync.

private Payload doInBackgroundSync(Payload data) {
    sIsCancellable = true;
    Timber.d("doInBackgroundSync()");
    // Block execution until any previous background task finishes, or timeout after 5s
    boolean ok = CollectionTask.waitToFinish(5);
    String hkey = (String) data.data[0];
    boolean media = (Boolean) data.data[1];
    String conflictResolution = (String) data.data[2];
    HostNum hostNum = (HostNum) data.data[3];
    long restServerSpace = (long) data.data[4];
    // Use safe version that catches exceptions so that full sync is still possible
    Collection col = CollectionHelper.getInstance().getColSafe(AnkiDroidApp.getInstance());
    boolean colCorruptFullSync = false;
    if (!CollectionHelper.getInstance().colIsOpen() || !ok) {
        if (conflictResolution != null && "download".equals(conflictResolution)) {
            colCorruptFullSync = true;
        } else {
            data.success = false;
            data.result = new Object[] { "genericError" };
            return data;
        }
    }
    try {
        CollectionHelper.getInstance().lockCollection();
        HttpSyncer server = new RemoteServer(this, hkey, hostNum);
        Syncer client = new Syncer(col, server, hostNum);
        // run sync and check state
        boolean noChanges = false;
        if (conflictResolution == null) {
            Timber.i("Sync - starting sync");
            publishProgress(R.string.sync_prepare_syncing);
            Object[] ret = client.sync(this, restServerSpace);
            data.message = client.getSyncMsg();
            if (ret == null) {
                data.success = false;
                data.result = new Object[] { "genericError" };
                return data;
            }
            String retCode = (String) ret[0];
            if (!"noChanges".equals(retCode) && !"success".equals(retCode)) {
                data.success = false;
                data.result = ret;
                // Check if there was a sanity check error
                if ("sanityCheckError".equals(retCode)) {
                    // Force full sync next time
                    col.modSchemaNoCheck();
                    col.save();
                }
                return data;
            }
            // save and note success state
            if ("noChanges".equals(retCode)) {
                // publishProgress(R.string.sync_no_changes_message);
                noChanges = true;
            }
            restServerSpace = client.getRestSpace();
        } else {
            try {
                // Disable sync cancellation for full-sync
                sIsCancellable = false;
                server = new FullSyncer(col, hkey, this, hostNum);
                if ("upload".equals(conflictResolution)) {
                    Timber.i("Sync - fullsync - upload collection");
                    publishProgress(R.string.sync_preparing_full_sync_message);
                    Object[] ret = server.upload(restServerSpace);
                    col.reopen();
                    if (ret == null) {
                        data.success = false;
                        data.result = new Object[] { "genericError" };
                        return data;
                    }
                    if (!ret[0].equals(HttpSyncer.ANKIWEB_STATUS_OK)) {
                        data.success = false;
                        data.result = ret;
                        return data;
                    }
                } else if ("download".equals(conflictResolution)) {
                    Timber.i("Sync - fullsync - download collection");
                    publishProgress(R.string.sync_downloading_message);
                    Object[] ret = server.download();
                    if (ret == null) {
                        Timber.w("Sync - fullsync - unknown error");
                        data.success = false;
                        data.result = new Object[] { "genericError" };
                        return data;
                    }
                    if ("success".equals(ret[0])) {
                        data.success = true;
                        col.reopen();
                    }
                    if (!"success".equals(ret[0])) {
                        Timber.w("Sync - fullsync - download failed");
                        data.success = false;
                        data.result = ret;
                        if (!colCorruptFullSync) {
                            col.reopen();
                        }
                        return data;
                    }
                }
            } catch (OutOfMemoryError e) {
                AnkiDroidApp.sendExceptionReport(e, "doInBackgroundSync-fullSync");
                data.success = false;
                data.result = new Object[] { "OutOfMemoryError" };
                return data;
            } catch (RuntimeException e) {
                if (timeoutOccurred(e)) {
                    data.result = new Object[] { "connectionError", e };
                } else if ("UserAbortedSync".equals(e.getMessage())) {
                    data.result = new Object[] { "UserAbortedSync", e };
                } else {
                    AnkiDroidApp.sendExceptionReport(e, "doInBackgroundSync-fullSync");
                    data.result = new Object[] { "IOException", e };
                }
                data.success = false;
                return data;
            }
        }
        // clear undo to avoid non syncing orphans (because undo resets usn too
        if (!noChanges) {
            col.clearUndo();
        }
        // then move on to media sync
        sIsCancellable = true;
        boolean noMediaChanges = false;
        boolean enoughServerSpace = true;
        String mediaError = null;
        if (media) {
            server = new RemoteMediaServer(col, hkey, this, hostNum);
            MediaSyncer mediaClient = new MediaSyncer(col, (RemoteMediaServer) server, this);
            String ret;
            try {
                // ������ܻ���Ϊ�ϴ��ļ������ռ��С���׳��쳣���ڴ�֮ǰ��Ҫ����ʣ��ռ��С
                ret = mediaClient.sync(restServerSpace);
                Timber.e("sync media ret is null");
                if (ret == null) {
                    mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_error);
                } else {
                    if ("corruptMediaDB".equals(ret)) {
                        mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_db_error);
                        noMediaChanges = true;
                    }
                    if ("noChanges".equals(ret)) {
                        publishProgress(R.string.sync_media_no_changes);
                        noMediaChanges = true;
                    }
                    if ("sanityFailed".equals(ret)) {
                        mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_sanity_failed);
                    } else {
                        publishProgress(R.string.sync_media_success);
                    }
                }
            } catch (RuntimeException e) {
                if (timeoutOccurred(e)) {
                    data.result = new Object[] { "connectionError", e };
                } else if ("UserAbortedSync".equals(e.getMessage())) {
                    data.result = new Object[] { "UserAbortedSync", e };
                }
                mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_error) + "\n\n" + e.getLocalizedMessage();
            }
        }
        if (noChanges && (!media || noMediaChanges)) {
            data.success = false;
            data.result = new Object[] { "noChanges" };
            return data;
        } else {
            data.success = true;
            data.data = new Object[] { conflictResolution, col, mediaError };
            return data;
        }
    } catch (MediaSyncException e) {
        Timber.e("Media sync rejected by server");
        data.success = false;
        data.result = new Object[] { "mediaSyncServerError", e };
        AnkiDroidApp.sendExceptionReport(e, "doInBackgroundSync");
        return data;
    } catch (UnknownHttpResponseException e) {
        Timber.e(e, "doInBackgroundSync -- unknown response code error");
        data.success = false;
        int code = e.getResponseCode();
        String msg = e.getLocalizedMessage();
        data.result = new Object[] { "error", code, msg };
        return data;
    } catch (NoEnoughServerSpaceException e) {
        Timber.e("NoEnoughServerSpaceException ");
        e.printStackTrace();
        data.success = false;
        data.result = new Object[] { "noServerSpace", e.rest, e.need };
        return data;
    } catch (Exception e) {
        // Global error catcher.
        // Try to give a human readable error, otherwise print the raw error message
        Timber.e(e, "doInBackgroundSync error");
        data.success = false;
        if (timeoutOccurred(e)) {
            data.result = new Object[] { "connectionError", e };
        } else if ("UserAbortedSync".equals(e.getMessage())) {
            data.result = new Object[] { "UserAbortedSync", e };
        } else {
            AnkiDroidApp.sendExceptionReport(e, "doInBackgroundSync");
            data.result = new Object[] { e.getLocalizedMessage(), e };
        }
        return data;
    } finally {
        Timber.i("Sync Finished - Closing Collection");
        // don't bump mod time unless we explicitly save
        if (col != null) {
            col.close(false);
        }
        CollectionHelper.getInstance().unlockCollection();
    }
}
Also used : HostNum(com.ichi2.libanki.sync.HostNum) FullSyncer(com.ichi2.libanki.sync.FullSyncer) UnknownHttpResponseException(com.ichi2.anki.exception.UnknownHttpResponseException) JSONException(com.ichi2.utils.JSONException) NoEnoughServerSpaceException(com.ichi2.anki.exception.NoEnoughServerSpaceException) MediaSyncException(com.ichi2.anki.exception.MediaSyncException) IOException(java.io.IOException) UnknownHttpResponseException(com.ichi2.anki.exception.UnknownHttpResponseException) HttpSyncer(com.ichi2.libanki.sync.HttpSyncer) FullSyncer(com.ichi2.libanki.sync.FullSyncer) Syncer(com.ichi2.libanki.sync.Syncer) MediaSyncer(com.ichi2.libanki.sync.MediaSyncer) MediaSyncException(com.ichi2.anki.exception.MediaSyncException) Collection(com.ichi2.libanki.Collection) MediaSyncer(com.ichi2.libanki.sync.MediaSyncer) JSONObject(com.ichi2.utils.JSONObject) HttpSyncer(com.ichi2.libanki.sync.HttpSyncer) RemoteServer(com.ichi2.libanki.sync.RemoteServer) RemoteMediaServer(com.ichi2.libanki.sync.RemoteMediaServer) NoEnoughServerSpaceException(com.ichi2.anki.exception.NoEnoughServerSpaceException)

Example 44 with Media

use of com.ichi2.libanki.Media in project AnkiChinaAndroid by ankichinateam.

the class SdCardReceiver method onReceive.

@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(Intent.ACTION_MEDIA_EJECT)) {
        Timber.i("media eject detected - closing collection and sending broadcast");
        Intent i = new Intent();
        i.setAction(MEDIA_EJECT);
        context.sendBroadcast(i);
        try {
            Collection col = CollectionHelper.getInstance().getCol(context);
            if (col != null) {
                col.close();
            }
        } catch (Exception e) {
            Timber.w(e, "Exception while trying to close collection likely because it was already unmounted");
        }
    } else if (intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED)) {
        Timber.i("media mount detected - sending broadcast");
        Intent i = new Intent();
        i.setAction(MEDIA_MOUNT);
        context.sendBroadcast(i);
    }
}
Also used : Collection(com.ichi2.libanki.Collection) Intent(android.content.Intent)

Example 45 with Media

use of com.ichi2.libanki.Media in project AnkiChinaAndroid by ankichinateam.

the class ImageFieldTest method testNoImagePathIsNothing.

@Test
public void testNoImagePathIsNothing() {
    String knownBadImage = "<br />";
    Collection col = collectionWithMediaFolder("media");
    String imageSrc = ImageField.getImageFullPath(col, knownBadImage);
    assertThat("no media should return no paths", imageSrc, equalTo(""));
}
Also used : Collection(com.ichi2.libanki.Collection) Test(org.junit.Test)

Aggregations

File (java.io.File)43 IOException (java.io.IOException)26 Collection (com.ichi2.libanki.Collection)25 JSONObject (com.ichi2.utils.JSONObject)19 ArrayList (java.util.ArrayList)17 Test (org.junit.Test)17 ZipFile (java.util.zip.ZipFile)14 JSONException (com.ichi2.utils.JSONException)10 FileOutputStream (java.io.FileOutputStream)10 List (java.util.List)10 JSONArray (com.ichi2.utils.JSONArray)9 FileInputStream (java.io.FileInputStream)9 FileNotFoundException (java.io.FileNotFoundException)9 SharedPreferences (android.content.SharedPreferences)8 JSONObject (org.json.JSONObject)8 Resources (android.content.res.Resources)7 Uri (android.net.Uri)7 RobolectricTest (com.ichi2.anki.RobolectricTest)7 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)7 AnkiPackageImporter (com.ichi2.libanki.importer.AnkiPackageImporter)7