Florianschmidtwelzow has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/270557

Change subject: WIP: Implement Text to speech functionality for pages
......................................................................

WIP: Implement Text to speech functionality for pages

This is an early status of the change, but works for most cases.

ToDo:
 * Don't add a huge text variable to tts.speak(), the limit is somewhere
   at 4000 chars.

Upstreamed from: http://gerrit.go2tech.de/r/1374

Bug: T126889
Change-Id: Idc13fc334320a0dd9ab436183161b338fc72d9a2
---
M app/src/main/java/org/wikipedia/page/PageActivity.java
M app/src/main/java/org/wikipedia/page/PageFragment.java
M app/src/main/res/menu/menu_page_actions.xml
M app/src/main/res/values/strings.xml
4 files changed, 121 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia 
refs/changes/57/270557/1

diff --git a/app/src/main/java/org/wikipedia/page/PageActivity.java 
b/app/src/main/java/org/wikipedia/page/PageActivity.java
index 9a03014..64b5dab 100644
--- a/app/src/main/java/org/wikipedia/page/PageActivity.java
+++ b/app/src/main/java/org/wikipedia/page/PageActivity.java
@@ -52,6 +52,9 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.preference.PreferenceManager;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.TextToSpeech.OnInitListener;
+import android.speech.tts.UtteranceProgressListener;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.design.widget.NavigationView;
@@ -75,11 +78,13 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import java.util.Locale;
+
 import static org.wikipedia.util.DeviceUtil.isBackKeyUp;
 import static org.wikipedia.util.DeviceUtil.hideSoftKeyboard;
 import static org.wikipedia.util.UriUtil.visitInExternalBrowser;
 
-public class PageActivity extends ThemedActionBarActivity {
+public class PageActivity extends ThemedActionBarActivity implements 
OnInitListener {
 
     public enum TabPosition {
         CURRENT_TAB,
@@ -90,6 +95,7 @@
     public static final int ACTIVITY_REQUEST_LANGLINKS = 0;
     public static final int ACTIVITY_REQUEST_EDIT_SECTION = 1;
     public static final int ACTIVITY_REQUEST_GALLERY = 2;
+    public static final int ACTIVITY_TTS_DATA_CHECK = 3;
 
     public static final int PROGRESS_BAR_MAX_VALUE = 10000;
 
@@ -124,6 +130,7 @@
     private RandomHandler randomHandler;
     private NavDrawerHelper navDrawerHelper;
     private boolean navItemSelected;
+    private TextToSpeech TTS;
 
     public View getContentView() {
         return fragmentContainerView;
@@ -276,6 +283,11 @@
 
         // Conditionally execute all recurring tasks
         new RecurringTasksExecutor(app).run();
+
+        Intent checkTTSIntent = new Intent();
+        checkTTSIntent
+            .setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
+        startActivityForResult(checkTTSIntent, ACTIVITY_TTS_DATA_CHECK);
     }
 
     private void finishActionMode() {
@@ -861,6 +873,16 @@
             handleLoginActivityResult(resultCode);
         } else if (newArticleLanguageSelected(requestCode, resultCode) || 
galleryFilePageSelected(requestCode, resultCode)) {
             handleLangLinkOrFilePageResult(data);
+        } else if (requestCode == ACTIVITY_TTS_DATA_CHECK) {
+            if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
+                TTS = new TextToSpeech(this, this);
+            } else {
+                Intent installTTSIntent = new Intent();
+                installTTSIntent
+                        
.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
+                startActivity(installTTSIntent);
+            }
+
         } else {
             super.onActivityResult(requestCode, resultCode, data);
         }
@@ -881,6 +903,11 @@
             themeChooser.dismiss();
         }
         app.getSessionFunnel().persistSession();
+
+        if (TTS.isSpeaking()) {
+           getCurPageFragment().stopSpeechArticle(TTS);
+        }
+
 
         super.onStop();
         unregisterBus();
@@ -1004,4 +1031,40 @@
         widgetIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
         sendBroadcast(widgetIntent);
     }
+
+    public void onInit(int initStatus) {
+        final PageActivity activity = this;
+
+        switch (initStatus) {
+            case TextToSpeech.ERROR:
+                FeedbackUtil.showMessage(this, R.string.tts_failed_unknown);
+                break;
+            case TextToSpeech.SUCCESS:
+                TTS.setOnUtteranceProgressListener(new 
UtteranceProgressListener() {
+                    @Override
+                    public void onDone(String utteranceId) {
+                        getCurPageFragment().stopSpeechArticle(TTS);
+                    }
+
+                    @Override
+                    public void onStop(String utteranceId, boolean 
interrupted) {
+                        getCurPageFragment().stopSpeechArticle(TTS);
+                    }
+
+                    @Override
+                    public void onError(String utteranceId) {
+                        getCurPageFragment().stopSpeechArticle(TTS);
+                    }
+
+                    @Override
+                    public void onStart(String utteranceId) {
+                    }
+                });
+                break;
+        }
+    }
+
+    public TextToSpeech getTTSEngine() {
+        return TTS;
+    }
 }
diff --git a/app/src/main/java/org/wikipedia/page/PageFragment.java 
b/app/src/main/java/org/wikipedia/page/PageFragment.java
index 0571bba..411d0d7 100755
--- a/app/src/main/java/org/wikipedia/page/PageFragment.java
+++ b/app/src/main/java/org/wikipedia/page/PageFragment.java
@@ -5,6 +5,8 @@
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Bundle;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.UtteranceProgressListener;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
@@ -73,6 +75,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
 import static butterknife.ButterKnife.findById;
@@ -143,6 +146,7 @@
     private ActionMode findInPageActionMode;
     @NonNull private ShareHandler shareHandler;
     private TabsProvider tabsProvider;
+    @NonNull private Menu mOptionsMenu;
 
     private WikipediaApp app;
 
@@ -633,6 +637,7 @@
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
+        mOptionsMenu = menu;
         if (!isAdded() || getPageActivity().isSearching()) {
             return;
         }
@@ -695,8 +700,45 @@
             case R.id.menu_page_show_tabs:
                 tabsProvider.enterTabMode();
                 return true;
+            case R.id.menu_page_tts:
+                speechArticle();
+                return true;
             default:
                 return super.onOptionsItemSelected(item);
+        }
+    }
+
+    public void stopSpeechArticle(TextToSpeech tts) {
+        MenuItem speechArticle = mOptionsMenu.findItem(R.id.menu_page_tts);
+        tts.stop();
+        speechArticle.setTitle(R.string.tts_read_aloud);
+    }
+
+    private void speechArticle() {
+        TextToSpeech tts = getPageActivity().getTTSEngine();
+        MenuItem speechArticle = mOptionsMenu.findItem(R.id.menu_page_tts);
+        if (tts.isSpeaking()) {
+            stopSpeechArticle(tts);
+        } else {
+            speechArticle.setTitle(R.string.tts_stop_read_aloud);
+            Locale lang = 
Locale.forLanguageTag(getTitle().getSite().getLanguageCode());
+            if (tts.isLanguageAvailable(lang) == TextToSpeech.LANG_AVAILABLE) {
+                tts.setLanguage(lang);
+                L.d("Set TTS language to: " + lang.getDisplayLanguage());
+            } else {
+                FeedbackUtil.showMessage(getActivity(), 
R.string.tts_lang_not_available);
+                return;
+            }
+
+            String text = 
Html.fromHtml(getPage().getDisplayTitle()).toString();
+            List<Section> sections = getPage().getSections();
+            for (Section section : sections) {
+                text += ". " + Html.fromHtml(section.getHeading() + " " + 
section.getContent()).toString();
+            }
+
+            Bundle params = new Bundle();
+            params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, 
getPage().getDisplayTitle());
+            tts.speak(text, TextToSpeech.QUEUE_ADD, params, 
getPage().getDisplayTitle());
         }
     }
 
@@ -919,10 +961,14 @@
     private void updateMenuPageInfo(@NonNull Menu menu) {
         MenuItem contentIssues = menu.findItem(R.id.menu_page_content_issues);
         MenuItem similarTitles = menu.findItem(R.id.menu_page_similar_titles);
+        MenuItem speechArticle = menu.findItem(R.id.menu_page_tts);
         contentIssues.setVisible(pageInfo != null && 
pageInfo.hasContentIssues());
         contentIssues.setEnabled(true);
         similarTitles.setVisible(pageInfo != null && 
pageInfo.hasSimilarTitles());
         similarTitles.setEnabled(true);
+        Locale lang = 
Locale.forLanguageTag(getTitle().getSite().getLanguageCode());
+        
speechArticle.setVisible(getPageActivity().getTTSEngine().isLanguageAvailable(lang)
 == TextToSpeech.LANG_AVAILABLE);
+        speechArticle.setEnabled(true);
     }
 
     private void showContentIssues() {
diff --git a/app/src/main/res/menu/menu_page_actions.xml 
b/app/src/main/res/menu/menu_page_actions.xml
index 62238e9..cb23af3 100644
--- a/app/src/main/res/menu/menu_page_actions.xml
+++ b/app/src/main/res/menu/menu_page_actions.xml
@@ -23,6 +23,10 @@
           android:title="@string/menu_page_similar_titles"
           app:showAsAction="never"
           android:enabled="false" />
+    <item android:id="@+id/menu_page_tts"
+          android:title="@string/tts_read_aloud"
+          app:showAsAction="never"
+          android:enabled="false" />
     <item android:id="@+id/menu_page_font_and_theme"
           android:title="@string/menu_page_font_and_theme"
           app:showAsAction="never"
diff --git a/app/src/main/res/values/strings.xml 
b/app/src/main/res/values/strings.xml
index 6f03757..1291ae7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -305,4 +305,11 @@
     <string name="article_menu_bar_share">Share the article link</string>
     <string name="article_menu_bar_navigate">Navigate to the location of the 
article</string>
     <!-- /Article menu bar -->
+
+    <!-- Text-to-Speech -->
+    <string name="tts_failed_unknown">The initialization of the Text-to-Speech 
engine failed.</string>
+    <string name="tts_lang_not_available">The Text-to-Speech engine does not 
provide the language the article is written in.</string>
+    <string name="tts_read_aloud">Read aloud (Text-to-Speech)</string>
+    <string name="tts_stop_read_aloud">Stop reading aloud...</string>
+    <!-- /Text-to-Speech -->
 </resources>

-- 
To view, visit https://gerrit.wikimedia.org/r/270557
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Idc13fc334320a0dd9ab436183161b338fc72d9a2
Gerrit-PatchSet: 1
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Florianschmidtwelzow <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to