Search in sources :

Example 11 with AbstractFlashcardViewer

use of com.ichi2.anki.AbstractFlashcardViewer in project Anki-Android by ankidroid.

the class OnRenderProcessGoneDelegateTest method unrecoverableCrashDoesNotRecreateWebView.

@SuppressWarnings("ResultOfMethodCallIgnored")
@Test
public void unrecoverableCrashDoesNotRecreateWebView() {
    AbstractFlashcardViewer mock = getViewer();
    OnRenderProcessGoneDelegateImpl delegate = getInstance(mock);
    doReturn(null).when(mock).getCurrentCard();
    callOnRenderProcessGone(delegate);
    verify(mock, times(1)).destroyWebViewFrame();
    verify(mock, never()).recreateWebViewFrame();
    assertThat("A toast should be displayed", delegate.mDisplayedToast, is(true));
    verify(mock, times(1).description("screen should be closed")).finishWithoutAnimation();
}
Also used : AbstractFlashcardViewer(com.ichi2.anki.AbstractFlashcardViewer) Test(org.junit.Test)

Example 12 with AbstractFlashcardViewer

use of com.ichi2.anki.AbstractFlashcardViewer in project AnkiChinaAndroid by ankichinateam.

the class ReadText method initializeTts.

public static String initializeTts(Context context, boolean vipSpeak, boolean showToast, ReadTextListener listener) {
    // Store weak reference to Activity to prevent memory leak
    mReviewer = new WeakReference<>(context);
    // Create new TTS object and setup its onInit Listener
    mTts = new TextToSpeech(context, status -> {
        if (status == TextToSpeech.SUCCESS) {
            // build list of available languages
            buildAvailableLanguages(TextToSpeech.LANG_AVAILABLE);
            if (availableTtsLocales.size() > 0) {
                // notify the reviewer that TTS has been initialized
                Timber.d("TTS initialized and available languages found");
                if (listener != null) {
                    listener.ttsInitialized();
                }
            // ((AbstractFlashcardViewer) mReviewer.get()).ttsInitialized();
            } else {
                if (showToast) {
                    Toast.makeText(mReviewer.get(), mReviewer.get().getString(R.string.no_tts_available_message), Toast.LENGTH_LONG).show();
                }
                Timber.w("TTS initialized but no available languages found");
            }
            mTts.setOnUtteranceProgressListener(new UtteranceProgressListener() {

                @Override
                public void onDone(String arg0) {
                    if (ReadText.sTextQueue.size() > 0) {
                        String[] text = ReadText.sTextQueue.remove(0);
                        ReadText.speak(text[0], text[1], TextToSpeech.QUEUE_FLUSH);
                    }
                    if (listener != null) {
                        listener.onDone();
                    }
                }

                @Override
                @Deprecated
                public void onError(String utteranceId) {
                    Timber.v("Andoid TTS failed. Check logcat for error. Indicates a problem with Android TTS engine.");
                    final Uri helpUrl = Uri.parse(mReviewer.get().getString(R.string.link_faq_tts));
                    final AnkiActivity ankiActivity = (AnkiActivity) mReviewer.get();
                    ankiActivity.mayOpenUrl(helpUrl);
                    if (showToast) {
                        UIUtils.showSnackbar(ankiActivity, R.string.no_tts_available_message, false, R.string.help, v -> openTtsHelpUrl(helpUrl), ankiActivity.findViewById(R.id.root_layout), new Snackbar.Callback());
                    }
                }

                @Override
                public void onStart(String arg0) {
                // no nothing
                }
            });
        } else {
            if (showToast) {
                Toast.makeText(mReviewer.get(), mReviewer.get().getString(R.string.no_tts_available_message), Toast.LENGTH_LONG).show();
            }
            Timber.w("TTS not successfully initialized");
        }
    });
    // Show toast that it's getting initialized, as it can take a while before the sound plays the first time
    if (showToast) {
        Toast.makeText(context, context.getString(R.string.initializing_tts), Toast.LENGTH_LONG).show();
    }
    return mTts.getDefaultEngine();
}
Also used : Context(android.content.Context) NonNull(androidx.annotation.NonNull) Uri(android.net.Uri) WindowManager(android.view.WindowManager) UtteranceProgressListener(android.speech.tts.UtteranceProgressListener) Compat(com.ichi2.compat.Compat) Timber(timber.log.Timber) ArrayList(java.util.ArrayList) TextToSpeech(android.speech.tts.TextToSpeech) Nullable(androidx.annotation.Nullable) Locale(java.util.Locale) Handler(android.os.Handler) Toast(android.widget.Toast) CompatHelper(com.ichi2.compat.CompatHelper) View(android.view.View) MaterialDialog(com.afollestad.materialdialogs.MaterialDialog) WeakReference(java.lang.ref.WeakReference) Snackbar(com.google.android.material.snackbar.Snackbar) VisibleForTesting(androidx.annotation.VisibleForTesting) Sound(com.ichi2.libanki.Sound) CustomStyleDialog(com.ichi2.ui.CustomStyleDialog) Resources(android.content.res.Resources) UtteranceProgressListener(android.speech.tts.UtteranceProgressListener) TextToSpeech(android.speech.tts.TextToSpeech) Uri(android.net.Uri) Snackbar(com.google.android.material.snackbar.Snackbar)

Example 13 with AbstractFlashcardViewer

use of com.ichi2.anki.AbstractFlashcardViewer in project AnkiChinaAndroid by ankichinateam.

the class AbstractFlashcardViewer method onActivityResult.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Timber.i("onActivityResult:" + requestCode);
    if (requestCode == BE_VIP || requestCode == REFRESH_LOGIN_STATE_AND_TURN_TO_VIP_HTML) {
        mRefreshVipStateOnResume = true;
        mTurnToVipHtml = requestCode == REFRESH_LOGIN_STATE_AND_TURN_TO_VIP_HTML;
    } else if (requestCode == REFRESH_VOICE_INFO) {
        mRefreshVoiceInfoStateOnResume = true;
    } else if (resultCode == DeckPicker.RESULT_DB_ERROR) {
        closeReviewer(DeckPicker.RESULT_DB_ERROR, false);
    } else if (resultCode == DeckPicker.RESULT_MEDIA_EJECTED) {
        finishNoStorageAvailable();
    } else if (requestCode == REFRESH_TOP_BUTTONS) {
        restorePreferences();
        supportInvalidateOptionsMenu();
        invalidateOptionsMenu();
    } else if (requestCode == REQUEST_CODE_SPEAK_SETTING) {
        restorePreferences();
        mReInitBDVoice = true;
    } else if (requestCode == REFRESH_GESTURE) {
        restorePreferences();
    } else if (requestCode == REFRESH_CONTROLLER) {
        restorePreferences();
    }
    /* Reset the schedule and reload the latest card off the top of the stack if required.
           The card could have been rescheduled, the deck could have changed, or a change of
           note type could have lead to the card being deleted */
    if (data != null && data.hasExtra("reloadRequired")) {
        performReload();
    }
    if (requestCode == EDIT_CURRENT_CARD) {
        if (resultCode == RESULT_OK) {
            // content of note was changed so update the note and current card
            Timber.i("AbstractFlashcardViewer:: Saving card...");
            CollectionTask.launchCollectionTask(UPDATE_NOTE, mUpdateCardHandler, new TaskData(sEditorCard, true));
            onEditedNoteChanged();
        } else if (resultCode == RESULT_CANCELED && !(data != null && data.hasExtra("reloadRequired"))) {
            // nothing was changed by the note editor so just redraw the card
            redrawCard();
        }
    } else if (requestCode == DECK_OPTIONS && resultCode == RESULT_OK) {
        performReload();
    }
    if (!mDisableClipboard) {
        clipboardSetText("");
    }
}
Also used : TaskData(com.ichi2.async.TaskData)

Example 14 with AbstractFlashcardViewer

use of com.ichi2.anki.AbstractFlashcardViewer in project AnkiChinaAndroid by ankichinateam.

the class Sound method playSoundInternal.

/**
 * Plays a sound without ensuring that the playAllListener will release the audio
 */
// audio API deprecation tracked on github as #5022
@SuppressWarnings({ "PMD.EmptyIfStmt", "PMD.CollapsibleIfStatements", "deprecation" })
private void playSoundInternal(String soundPath, OnCompletionListener playAllListener, VideoView videoView) {
    Timber.d("Playing %s has listener? %b", soundPath, playAllListener != null);
    Uri soundUri = Uri.parse(soundPath);
    if ("tts".equals(soundPath.substring(0, 3))) {
    // TODO: give information about did
    // ReadText.textToSpeech(soundPath.substring(4, soundPath.length()),
    // Integer.parseInt(soundPath.substring(3, 4)));
    } else {
        // Check if the file extension is that of a known video format
        final String extension = soundPath.substring(soundPath.lastIndexOf(".") + 1).toLowerCase();
        boolean isVideo = Arrays.asList(VIDEO_WHITELIST).contains(extension);
        if (!isVideo) {
            final String guessedType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
            isVideo = (guessedType != null) && guessedType.startsWith("video/");
        }
        // Also check that there is a video thumbnail, as some formats like mp4 can be audio only
        isVideo = isVideo && ThumbnailUtils.createVideoThumbnail(soundUri.getPath(), MediaStore.Images.Thumbnails.MINI_KIND) != null;
        // holder
        if (isVideo && videoView == null && mCallingActivity != null && mCallingActivity.get() != null) {
            Timber.d("Requesting AbstractFlashcardViewer play video - no SurfaceHolder");
            mPlayAllListener = playAllListener;
            ((AbstractFlashcardViewer) mCallingActivity.get()).playVideo(soundPath);
            return;
        }
        // Play media
        try {
            // Create media player
            if (mMediaPlayer == null) {
                Timber.d("Creating media player for playback");
                mMediaPlayer = new MediaPlayer();
            } else {
                Timber.d("Resetting media for playback");
                mMediaPlayer.reset();
            }
            if (mAudioManager == null) {
                mAudioManager = (AudioManager) AnkiDroidApp.getInstance().getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
            }
            // Provide a VideoView to the MediaPlayer if valid video file
            if (isVideo && videoView != null) {
                mMediaPlayer.setDisplay(videoView.getHolder());
                mMediaPlayer.setOnVideoSizeChangedListener((mp, width, height) -> configureVideo(videoView, width, height));
            }
            mMediaPlayer.setOnErrorListener((mp, what, extra) -> {
                Timber.w("Media Error: (%d, %d). Calling OnCompletionListener", what, extra);
                return false;
            });
            // Setup the MediaPlayer
            mMediaPlayer.setDataSource(AnkiDroidApp.getInstance().getApplicationContext(), soundUri);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setOnPreparedListener(mp -> {
                Timber.d("Starting media player");
                mMediaPlayer.start();
            });
            if (playAllListener != null) {
                mMediaPlayer.setOnCompletionListener(playAllListener);
            }
            mMediaPlayer.prepareAsync();
            Timber.d("Requesting audio focus");
            mAudioManager.requestAudioFocus(afChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
        } catch (Exception e) {
            Timber.e(e, "playSounds - Error reproducing sound %s", soundPath);
            releaseSound();
        }
    }
}
Also used : AbstractFlashcardViewer(com.ichi2.anki.AbstractFlashcardViewer) Uri(android.net.Uri) MediaPlayer(android.media.MediaPlayer)

Example 15 with AbstractFlashcardViewer

use of com.ichi2.anki.AbstractFlashcardViewer in project Anki-Android by ankidroid.

the class OnRenderProcessGoneDelegateTest method getViewer.

@SuppressWarnings("ResultOfMethodCallIgnored")
private AbstractFlashcardViewer getViewer(Lifecycle.State state) {
    WebView mockWebView = mock(WebView.class);
    AbstractFlashcardViewer mock = strictMock(AbstractFlashcardViewer.class);
    doReturn(mock(Lock.class)).when(mock).getWriteLock();
    doReturn(mock(Resources.class)).when(mock).getResources();
    doReturn(mockWebView).when(mock).getWebView();
    doReturn(mock(Card.class)).when(mock).getCurrentCard();
    doReturn(lifecycleOf(state)).when(mock).getLifecycle();
    doNothing().when(mock).destroyWebViewFrame();
    doNothing().when(mock).recreateWebViewFrame();
    doNothing().when(mock).displayCardQuestion();
    doNothing().when(mock).finishWithoutAnimation();
    return mock;
}
Also used : AbstractFlashcardViewer(com.ichi2.anki.AbstractFlashcardViewer) Resources(android.content.res.Resources) WebView(android.webkit.WebView) Lock(java.util.concurrent.locks.Lock) Card(com.ichi2.libanki.Card)

Aggregations

AbstractFlashcardViewer (com.ichi2.anki.AbstractFlashcardViewer)9 Test (org.junit.Test)6 Resources (android.content.res.Resources)4 WebView (android.webkit.WebView)4 Uri (android.net.Uri)3 View (android.view.View)3 Context (android.content.Context)2 MediaPlayer (android.media.MediaPlayer)2 ImageView (android.widget.ImageView)2 TextView (android.widget.TextView)2 AudioView (com.ichi2.anki.multimediacard.AudioView)2 TaskData (com.ichi2.async.TaskData)2 SharedPreferences (android.content.SharedPreferences)1 AudioAttributes (android.media.AudioAttributes)1 AudioFocusRequest (android.media.AudioFocusRequest)1 Handler (android.os.Handler)1 TextToSpeech (android.speech.tts.TextToSpeech)1 UtteranceProgressListener (android.speech.tts.UtteranceProgressListener)1 OnClickListener (android.view.View.OnClickListener)1 ViewGroup (android.view.ViewGroup)1