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();
}
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();
}
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("");
}
}
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();
}
}
}
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;
}
Aggregations