Search code examples
javascriptandroidwebviewresponsivevoice

ResponsiveVoice doesn't work when page is loaded in Android webview


It works well when i click the button:

<!DOCTYPE html>
<html>
<head>


    <script src="https://code.responsivevoice.org/responsivevoice.js"></script>

    </head >

<body>

<button onclick="responsiveVoice.speak('Welcome to the Responsive Voice website');">Click</button>

</body>
</html>

but doesn't work when i want to play speech when page is loaded in a webview:

<!DOCTYPE html>
<html>
<head>

    <script src="https://code.responsivevoice.org/responsivevoice.js"></script>

    </head >

<body>

<script>

   setTimeout(responsiveVoice.speak("Welcome to the Responsive Voice  website"),500);

</script>
</body>
</html>

Android code:

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        WebView webView = (WebView) findViewById(R.id.myWebview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.loadUrl("file:///android_asset/index.html");


    }

Manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.abdallah.test">

    <WebView  xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission  android:name="android.permission.ACCESS_NETWORK_STATE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

This is system's log when i click the button:

I/chromium: [INFO:CONSOLE(62)] "Voice support NOT ready", source: https://code.responsivevoice.org/responsivevoice.js (62)
I/chromium: [INFO:CONSOLE(62)] "Voice support NOT ready", source: https://code.responsivevoice.org/responsivevoice.js (62)
I/chromium: [INFO:CONSOLE(62)] "Voice support NOT ready", source: https://code.responsivevoice.org/responsivevoice.js (62)
I/chromium: [INFO:CONSOLE(63)] "RV: speechSynthesis present but no system voices found", source: https://code.responsivevoice.org/responsivevoice.js (63)
I/chromium: [INFO:CONSOLE(64)] "RV: Enabling fallback mode", source: https://code.responsivevoice.org/responsivevoice.js (64)
D/MediaResourceGetter: ethernet/wifi connection detected
D/MediaHTTPConnection: filterOutInternalHeaders: key=User-Agent, val= SonyD5803 Build/23.4.A.1.232 stagefright/1.2 (Linux;Android 5.1.1)
D/MediaHTTPConnection: proxy null port 0
D/MediaResourceGetter: resource doesn't have video
D/MediaResourceGetter: extracted valid metadata: MediaMetadata[durationInMilliseconds=0, width=0, height=0, success=true]
E/MediaPlayer-JNI: QCMediaPlayer mediaplayer NOT present
D/MediaPlayer: Couldn't open file on client side, trying server side
D/MediaHTTPConnection: filterOutInternalHeaders: key=User-Agent, val= SonyD5803 Build/23.4.A.1.232 stagefright/1.2 (Linux;Android 5.1.1)
D/MediaHTTPConnection: filterOutInternalHeaders: key=allow-cross-domain-redirect, val= false
D/MediaHTTPConnection: filterOutInternalHeaders: key=x-wap-profile, val= http://uaprof.sonymobile.com/D5803R2321.xml
D/MediaHTTPConnection: proxy null port 0
E/MediaPlayer: Should have subtitle controller already set
D/MediaPlayer: getMetadata

This is when i want to play speech when page is loaded:

I/chromium: [INFO:CONSOLE(62)] "Voice support NOT ready", source: https://code.responsivevoice.org/responsivevoice.js (62)
I/chromium: [INFO:CONSOLE(62)] "Voice support NOT ready", source: https://code.responsivevoice.org/responsivevoice.js (62)
I/chromium: [INFO:CONSOLE(62)] "Voice support NOT ready", source: https://code.responsivevoice.org/responsivevoice.js (62)
I/chromium: [INFO:CONSOLE(62)] "Voice support NOT ready", source: https://code.responsivevoice.org/responsivevoice.js (62)
I/chromium: [INFO:CONSOLE(62)] "Voice support NOT ready", source: https://code.responsivevoice.org/responsivevoice.js (62)
I/chromium: [INFO:CONSOLE(63)] "RV: speechSynthesis present but no system voices found", source: https://code.responsivevoice.org/responsivevoice.js (63)
I/chromium: [INFO:CONSOLE(64)] "RV: Enabling fallback mode", source: https://code.responsivevoice.org/responsivevoice.js (64)
D/MediaResourceGetter: ethernet/wifi connection detected
D/MediaHTTPConnection: filterOutInternalHeaders: key=User-Agent, val= SonyD5803 Build/23.4.A.1.232 stagefright/1.2 (Linux;Android 5.1.1)
D/MediaHTTPConnection: proxy null port 0
D/MediaResourceGetter: resource doesn't have video
D/MediaResourceGetter: extracted valid metadata: MediaMetadata[durationInMilliseconds=0, width=0, height=0, success=true]

Solution

  • ResponsiveVoice says:

    On iOS, some events such as Speech Synthesis, need to be triggered from a user action (i.e. a click). That causes ResponsiveVoice speak calls not to work on page load, for example.

    With Speech Synthesis, that user triggered action only needs to be done once. Further direct calls after the first one will work as expected.

    So, the recommended best practice is to add a “Start” button to the experience for the user to click, and use that as a initialization call to responsiveVoice.speak(). That call, if desired, can have a blank space as text, so there’s no impact to the user.

    I think android is the same, but i have found a solution to my problem:

    First i will load the html page containing the javascript function for text to speech. Then load the function itself only like the following code:

    final Handler handler=new Handler();
    handler.postDelayed(new Runnable() {
    
                            public void run() {
                                WebView webView = (WebView) findViewById(R.id.myWebview);
                                webView.loadUrl("javascript:speak('" + s + "');");
    
                            }
                        }, 5000 );