Search in sources :

Example 1 with PRINT

use of com.ichi2.bd.MainHandlerConstant.PRINT in project AnkiChinaAndroid by ankichinateam.

the class ReviewerTest method assertCounts.

private void assertCounts(Reviewer r, int newCount, int stepCount, int revCount) {
    List<String> countList = new ArrayList<>();
    JavaScriptFunction jsApi = r.javaScriptFunction();
    countList.add(jsApi.ankiGetNewCardCount());
    countList.add(jsApi.ankiGetLrnCardCount());
    countList.add(jsApi.ankiGetRevCardCount());
    List<Integer> expexted = new ArrayList<>();
    expexted.add(newCount);
    expexted.add(stepCount);
    expexted.add(revCount);
    // We use toString as hamcrest does not print the whole array and stops at [0].
    assertThat(countList.toString(), is(expexted.toString()));
}
Also used : JavaScriptFunction(com.ichi2.anki.AbstractFlashcardViewer.JavaScriptFunction) ArrayList(java.util.ArrayList) Matchers.isEmptyString(org.hamcrest.Matchers.isEmptyString)

Example 2 with PRINT

use of com.ichi2.bd.MainHandlerConstant.PRINT 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 3 with PRINT

use of com.ichi2.bd.MainHandlerConstant.PRINT in project AnkiChinaAndroid by ankichinateam.

the class SchedTest method test_cram_resched.

@Test
public void test_cram_resched() throws Exception {
    // add card
    Collection col = getColV1();
    Note note = col.newNote();
    note.setItem("Front", "one");
    col.addNote(note);
    // cram deck
    long did = col.getDecks().newDyn("Cram");
    Deck cram = col.getDecks().get(did);
    cram.put("resched", false);
    col.getDecks().save(cram);
    col.getSched().rebuildDyn(did);
    col.reset();
    // graduate should return it to new
    Card c = col.getSched().getCard();
    assertEquals(60, col.getSched().nextIvl(c, 1));
    assertEquals(600, col.getSched().nextIvl(c, 2));
    assertEquals(0, col.getSched().nextIvl(c, 3));
    assertEquals("(end)", col.getSched().nextIvlStr(getTargetContext(), c, 3));
    col.getSched().answerCard(c, 3);
    assertEquals(CARD_TYPE_NEW, c.getType());
    assertEquals(QUEUE_TYPE_NEW, c.getQueue());
    // undue reviews should also be unaffected
    c.setIvl(100);
    c.setQueue(CARD_TYPE_REV);
    c.setType(QUEUE_TYPE_REV);
    c.setDue(col.getSched().getToday() + 25);
    c.setFactor(STARTING_FACTOR);
    c.flush();
    Card cardcopy = c.clone();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = col.getSched().getCard();
    assertEquals(600, col.getSched().nextIvl(c, 1));
    assertEquals(0, col.getSched().nextIvl(c, 2));
    assertEquals(0, col.getSched().nextIvl(c, 3));
    col.getSched().answerCard(c, 2);
    assertEquals(100, c.getIvl());
    assertEquals(col.getSched().getToday() + 25, c.getDue());
    // check failure too
    c = cardcopy;
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = col.getSched().getCard();
    col.getSched().answerCard(c, 1);
    col.getSched().emptyDyn(did);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(col.getSched().getToday() + 25, c.getDue());
    // fail+grad early
    c = cardcopy;
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = col.getSched().getCard();
    col.getSched().answerCard(c, 1);
    col.getSched().answerCard(c, 3);
    col.getSched().emptyDyn(did);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(col.getSched().getToday() + 25, c.getDue());
    // due cards - pass
    c = cardcopy;
    c.setDue(-25);
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = col.getSched().getCard();
    col.getSched().answerCard(c, 3);
    col.getSched().emptyDyn(did);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(-25, c.getDue());
    // fail
    c = cardcopy;
    c.setDue(-25);
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = col.getSched().getCard();
    col.getSched().answerCard(c, 1);
    col.getSched().emptyDyn(did);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(-25, c.getDue());
    // fail with normal grad
    c = cardcopy;
    c.setDue(-25);
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = col.getSched().getCard();
    col.getSched().answerCard(c, 1);
    col.getSched().answerCard(c, 3);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(-25, c.getDue());
// lapsed card pulled into cram
// col.getSched()._cardConf(c)['lapse']['mult']=0.5
// col.getSched().answerCard(c, 1)
// col.getSched().rebuildDyn(did)
// col.reset()
// c = col.getSched().getCard()
// col.getSched().answerCard(c, 2)
// print c.__dict__
}
Also used : Note(com.ichi2.libanki.Note) Collection(com.ichi2.libanki.Collection) Deck(com.ichi2.libanki.Deck) Card(com.ichi2.libanki.Card) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 4 with PRINT

use of com.ichi2.bd.MainHandlerConstant.PRINT in project Anki-Android by ankidroid.

the class SchedTest method test_cram_resched.

@Test
public void test_cram_resched() throws Exception {
    // add card
    Collection col = getColV1();
    Note note = col.newNote();
    note.setItem("Front", "one");
    col.addNote(note);
    // cram deck
    long did = addDynamicDeck("Cram");
    Deck cram = col.getDecks().get(did);
    cram.put("resched", false);
    col.getDecks().save(cram);
    col.getSched().rebuildDyn(did);
    col.reset();
    // graduate should return it to new
    Card c = getCard();
    assertEquals(60, col.getSched().nextIvl(c, BUTTON_ONE));
    assertEquals(600, col.getSched().nextIvl(c, BUTTON_TWO));
    assertEquals(0, col.getSched().nextIvl(c, BUTTON_THREE));
    assertEquals("(end)", col.getSched().nextIvlStr(getTargetContext(), c, BUTTON_THREE));
    col.getSched().answerCard(c, BUTTON_THREE);
    assertEquals(CARD_TYPE_NEW, c.getType());
    assertEquals(QUEUE_TYPE_NEW, c.getQueue());
    // undue reviews should also be unaffected
    c.setIvl(100);
    c.setQueue(QUEUE_TYPE_REV);
    c.setType(CARD_TYPE_REV);
    c.setDue(col.getSched().getToday() + 25);
    c.setFactor(STARTING_FACTOR);
    c.flush();
    Card cardcopy = c.clone();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = getCard();
    assertEquals(600, col.getSched().nextIvl(c, BUTTON_ONE));
    assertEquals(0, col.getSched().nextIvl(c, BUTTON_TWO));
    assertEquals(0, col.getSched().nextIvl(c, BUTTON_THREE));
    col.getSched().answerCard(c, BUTTON_TWO);
    assertEquals(100, c.getIvl());
    assertEquals(col.getSched().getToday() + 25, c.getDue());
    // check failure too
    c = cardcopy;
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = getCard();
    col.getSched().answerCard(c, BUTTON_ONE);
    col.getSched().emptyDyn(did);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(col.getSched().getToday() + 25, c.getDue());
    // fail+grad early
    c = cardcopy;
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = getCard();
    col.getSched().answerCard(c, BUTTON_ONE);
    col.getSched().answerCard(c, BUTTON_THREE);
    col.getSched().emptyDyn(did);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(col.getSched().getToday() + 25, c.getDue());
    // due cards - pass
    c = cardcopy;
    c.setDue(-25);
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = getCard();
    col.getSched().answerCard(c, BUTTON_THREE);
    col.getSched().emptyDyn(did);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(-25, c.getDue());
    // fail
    c = cardcopy;
    c.setDue(-25);
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = getCard();
    col.getSched().answerCard(c, BUTTON_ONE);
    col.getSched().emptyDyn(did);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(-25, c.getDue());
    // fail with normal grad
    c = cardcopy;
    c.setDue(-25);
    c.flush();
    col.getSched().rebuildDyn(did);
    col.reset();
    c = getCard();
    col.getSched().answerCard(c, BUTTON_ONE);
    col.getSched().answerCard(c, BUTTON_THREE);
    c.load();
    assertEquals(100, c.getIvl());
    assertEquals(-25, c.getDue());
// lapsed card pulled into cram
// col.getSched()._cardConf(c)['lapse']['mult']=0.5
// col.getSched().answerCard(c, 1)
// col.getSched().rebuildDyn(did)
// col.reset()
// c = getCard()
// col.getSched().answerCard(c, 2)
// print c.__dict__
}
Also used : Note(com.ichi2.libanki.Note) Collection(com.ichi2.libanki.Collection) Deck(com.ichi2.libanki.Deck) Card(com.ichi2.libanki.Card) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 5 with PRINT

use of com.ichi2.bd.MainHandlerConstant.PRINT in project Anki-Android by ankidroid.

the class Connection method doInBackgroundSync.

/**
 * In the payload, success means that the sync did occur correctly and that a change did occur.
 * So success can be false without error, if no change occurred at all.
 */
private Payload doInBackgroundSync(Payload data) {
    sIsCancellable = true;
    Timber.d("doInBackgroundSync()");
    // Block execution until any previous background task finishes, or timeout after 5s
    boolean ok = TaskManager.waitToFinish(5);
    // Unique key allowing to identify the user to AnkiWeb without password
    String hkey = (String) data.data[0];
    // Whether media should be synced too
    boolean media = (Boolean) data.data[1];
    // If normal sync can't occur, what to do
    ConflictResolution conflictResolution = (ConflictResolution) data.data[2];
    // A number AnkiWeb told us to send back. Probably to choose the best server for the user
    HostNum hostNum = (HostNum) data.data[3];
    // 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 (FULL_DOWNLOAD == conflictResolution) {
            colCorruptFullSync = true;
        } else {
            return returnGenericError(data);
        }
    }
    try {
        CollectionHelper.getInstance().lockCollection();
        RemoteServer remoteServer = new RemoteServer(this, hkey, hostNum);
        Syncer client = new Syncer(col, remoteServer, hostNum);
        // run sync and check state
        boolean noChanges = false;
        if (conflictResolution == null) {
            Timber.i("Sync - starting sync");
            publishProgress(R.string.sync_prepare_syncing);
            Pair<ConnectionResultType, Object> ret = client.sync(this);
            data.message = client.getSyncMsg();
            if (ret == null) {
                return returnGenericError(data);
            }
            if (NO_CHANGES != ret.first && SUCCESS != ret.first) {
                data.success = false;
                data.resultType = ret.first;
                data.result = new Object[] { ret.second };
                // Check if there was a sanity check error
                if (SANITY_CHECK_ERROR == ret.first) {
                    // Force full sync next time
                    col.modSchemaNoCheck();
                    col.save();
                }
                return data;
            }
            // save and note success state
            if (NO_CHANGES == ret.first) {
                // publishProgress(R.string.sync_no_changes_message);
                noChanges = true;
            }
        } else {
            try {
                // Disable sync cancellation for full-sync
                sIsCancellable = false;
                FullSyncer fullSyncServer = new FullSyncer(col, hkey, this, hostNum);
                switch(conflictResolution) {
                    case FULL_UPLOAD:
                        {
                            Timber.i("Sync - fullsync - upload collection");
                            publishProgress(R.string.sync_preparing_full_sync_message);
                            Pair<ConnectionResultType, Object[]> ret = fullSyncServer.upload();
                            col.reopen();
                            if (ret == null) {
                                return returnGenericError(data);
                            }
                            if (ret.first == ARBITRARY_STRING && !ret.second[0].equals(HttpSyncer.ANKIWEB_STATUS_OK)) {
                                data.success = false;
                                data.resultType = ret.first;
                                data.result = ret.second;
                                return data;
                            }
                            break;
                        }
                    case FULL_DOWNLOAD:
                        {
                            Timber.i("Sync - fullsync - download collection");
                            publishProgress(R.string.sync_downloading_message);
                            ConnectionResultType ret = fullSyncServer.download();
                            if (ret == null) {
                                Timber.w("Sync - fullsync - unknown error");
                                return returnGenericError(data);
                            }
                            if (SUCCESS == ret) {
                                data.success = true;
                                col.reopen();
                            }
                            if (SUCCESS != ret) {
                                Timber.w("Sync - fullsync - download failed");
                                data.success = false;
                                data.resultType = ret;
                                if (!colCorruptFullSync) {
                                    col.reopen();
                                }
                                return data;
                            }
                            break;
                        }
                    default:
                }
            } catch (OutOfMemoryError e) {
                Timber.w(e);
                AnkiDroidApp.sendExceptionReport(e, "doInBackgroundSync-fullSync");
                data.success = false;
                data.resultType = OUT_OF_MEMORY_ERROR;
                data.result = new Object[0];
                return data;
            } catch (RuntimeException e) {
                Timber.w(e);
                if (timeoutOccurred(e)) {
                    data.resultType = CONNECTION_ERROR;
                } else if (USER_ABORTED_SYNC.toString().equals(e.getMessage())) {
                    data.resultType = USER_ABORTED_SYNC;
                } else {
                    AnkiDroidApp.sendExceptionReport(e, "doInBackgroundSync-fullSync");
                    data.resultType = IO_EXCEPTION;
                }
                data.result = new Object[] { 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;
        String mediaError = null;
        if (media) {
            RemoteMediaServer mediaServer = new RemoteMediaServer(col, hkey, this, hostNum);
            MediaSyncer mediaClient = new MediaSyncer(col, mediaServer, this);
            Pair<ConnectionResultType, String> ret;
            try {
                Timber.i("Sync - Performing media sync");
                ret = mediaClient.sync();
                if (ret == null || ret.first == null) {
                    mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_error);
                } else {
                    if (CORRUPT == ret.first) {
                        mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_db_error);
                        noMediaChanges = true;
                    }
                    if (NO_CHANGES == ret.first) {
                        publishProgress(R.string.sync_media_no_changes);
                        noMediaChanges = true;
                    }
                    if (MEDIA_SANITY_FAILED == ret.first) {
                        mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_sanity_failed);
                    } else {
                        publishProgress(R.string.sync_media_success);
                    }
                }
            } catch (RuntimeException e) {
                Timber.w(e);
                if (timeoutOccurred(e)) {
                    data.resultType = CONNECTION_ERROR;
                    data.result = new Object[] { e };
                } else if (USER_ABORTED_SYNC.toString().equals(e.getMessage())) {
                    data.resultType = USER_ABORTED_SYNC;
                    data.result = new Object[] { e };
                }
                int downloadedCount = mediaClient.getDownloadCount();
                int uploadedCount = mediaClient.getUploadCount();
                if (downloadedCount == 0 && uploadedCount == 0) {
                    mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_error) + "\n\n" + e.getLocalizedMessage();
                } else {
                    mediaError = AnkiDroidApp.getAppResources().getString(R.string.sync_media_partial_updated, downloadedCount, uploadedCount) + "\n\n" + e.getLocalizedMessage();
                }
            }
        }
        if (noChanges && (!media || noMediaChanges)) {
            // This means that there is no change at all, neither media nor collection. Not that there was an error.
            data.success = false;
            data.resultType = NO_CHANGES;
            data.result = new Object[0];
        } 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.resultType = MEDIA_SYNC_SERVER_ERROR;
        data.result = new Object[] { 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.resultType = ERROR;
        data.result = new Object[] { code, msg };
        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.resultType = CONNECTION_ERROR;
            data.result = new Object[] { e };
        } else if (USER_ABORTED_SYNC.toString().equals(e.getMessage())) {
            data.resultType = USER_ABORTED_SYNC;
            data.result = new Object[] { e };
        } else {
            AnkiDroidApp.sendExceptionReport(e, "doInBackgroundSync");
            data.resultType = ARBITRARY_STRING;
            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 : ConnectionResultType(com.ichi2.libanki.sync.Syncer.ConnectionResultType) HostNum(com.ichi2.libanki.sync.HostNum) FullSyncer(com.ichi2.libanki.sync.FullSyncer) UnknownHttpResponseException(com.ichi2.anki.exception.UnknownHttpResponseException) CustomSyncServerUrlException(com.ichi2.libanki.sync.CustomSyncServerUrlException) JSONException(com.ichi2.utils.JSONException) 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) ConflictResolution(com.ichi2.async.Connection.ConflictResolution) RemoteServer(com.ichi2.libanki.sync.RemoteServer) RemoteMediaServer(com.ichi2.libanki.sync.RemoteMediaServer) Pair(android.util.Pair)

Aggregations

Collection (com.ichi2.libanki.Collection)4 RobolectricTest (com.ichi2.anki.RobolectricTest)2 MediaSyncException (com.ichi2.anki.exception.MediaSyncException)2 UnknownHttpResponseException (com.ichi2.anki.exception.UnknownHttpResponseException)2 Card (com.ichi2.libanki.Card)2 Deck (com.ichi2.libanki.Deck)2 Note (com.ichi2.libanki.Note)2 FullSyncer (com.ichi2.libanki.sync.FullSyncer)2 HostNum (com.ichi2.libanki.sync.HostNum)2 HttpSyncer (com.ichi2.libanki.sync.HttpSyncer)2 MediaSyncer (com.ichi2.libanki.sync.MediaSyncer)2 RemoteMediaServer (com.ichi2.libanki.sync.RemoteMediaServer)2 RemoteServer (com.ichi2.libanki.sync.RemoteServer)2 Syncer (com.ichi2.libanki.sync.Syncer)2 JSONException (com.ichi2.utils.JSONException)2 JSONObject (com.ichi2.utils.JSONObject)2 IOException (java.io.IOException)2 Test (org.junit.Test)2 Pair (android.util.Pair)1 JavaScriptFunction (com.ichi2.anki.AbstractFlashcardViewer.JavaScriptFunction)1