3

I have a code to speak a text passed from html. Which I was able to make it working using below code.

Here is the code:

    tts = new TextToSpeech(this, this);
    myWebView = (WebView) findViewById(R.id.webviewid);
    //The html text is from the server.
    myWebView.loadDataWithBaseURL(null,
            "<html>" +
            "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">" +
            "</head>" +
            "<body>" +
            "<input class=\"textBox\" id=\"pass\" type=\"text\" maxlength=\"30\" required/>" +
            "<input type=\"button\" value=\"Say hello\" onClick=\"androidSpeak('Hello Android!')\" />" +
            "<script type=\"text/javascript\">" +
            "    function androidSpeak(texttospeak) {" +
            "        Android.textToSpeak(texttospeak);" +
            "    }" +
            "</script>" +
            "</body>" +
            "</html>", "text/html", "UTF-8", null);
    WebSettings webSettings = myWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");

Here is my Java script interface:

    protected class WebAppInterface {
        Context mContext;

        /** Instantiate the interface and set the context */
        WebAppInterface(Context c) {
            mContext = c;
        }

        /** Show a toast from the web page */
        @JavascriptInterface
        public void textToSpeak(String texttospeak) {
            Toast.makeText(mContext, texttospeak, Toast.LENGTH_SHORT).show();
            speakOut(texttospeak);
        }
    }


    private void speakOut(String text) {
        tts.speak(text, TextToSpeech.QUEUE_ADD, null);
    }

The above code works as expected. My question is how can I invoke TTS or any other feature (like alarm or making a call etc) through javascript. That means is it possible to call tts.speak() method from javascript. Or in another way, I wanted to invoke androids TTS through javascript instead of creating Java Script Interface (like above). This way I don't have to give an update to user for every feature that I am going to add.

Example: Please Note: Below is an example, which I know is incorrect. This is to give you an overview what I need to.

    //The html text is from the server.
    myWebView.loadDataWithBaseURL(null,
            "<html>" +
            "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">" +
            "</head>" +
            "<body>" +
            "<input class=\"textBox\" id=\"pass\" type=\"text\" maxlength=\"30\" required/>" +
            "<input type=\"button\" value=\"Say hello\" onClick=\"androidSpeak('Hello Android!')\" />" +
            "<script type=\"text/javascript\">" +
            "    function androidSpeak(texttospeak) {" +
            "        tts = new TextToSpeech(this, this);" +
            "        tts.speak(text, TextToSpeech.QUEUE_ADD, null);" +  <<< directly invoke the android's TTS.
            "    }" +
            "</script>" +
            "</body>" +
            "</html>", "text/html", "UTF-8", null);

Is there any plugin that I need to add. Please let me know. Any help is appreciated.

User12111111
  • 1,179
  • 1
  • 19
  • 41
  • What you are proposing (calling Android code using javascript) is almost impossible. Even if it were possible (using reflection or so), it would be a huge security risk and almost certainly removed from the play store. – Nachi Sep 25 '14 at 11:50
  • OK, I was researching bit more on this.. I came across `cordova`. Do you have idea on this so the above can work with `cordova`? – User12111111 Sep 25 '14 at 12:06
  • You can definitely cross-compile javascript code to Android using cordova, however you cannot update this functionality remotely. You will still have to upload new APKs whenever you add/change features. – Nachi Sep 25 '14 at 12:08

3 Answers3

1

Cordova will allow you to call custom native android code from your javascript or you can use plugins from their library which expose common hardware elements (such as the menu button, native notifications, etc). Cordova creates a complete application environment so you don't have to worry about any of the android application details, and build all of your application logic in html5/javascript. Phonegap is an implementation of Cordova which provides really nice build tools - you don't even need to set up the android build tools on your development machine - simply upload your html site and it will build your android app for you. :P

Allan Nienhuis
  • 3,961
  • 2
  • 23
  • 19
  • Without uploading a new APK, can I update the html site only and trigger the Android feature? for example today I added up `TTS` feature, tomorrow without updating the APK, can I add `Alarm` feature using `Cordova`? – User12111111 Oct 06 '14 at 13:15
  • no, the permissions required are included at the time you build the cordova application. these can't be changed unless you update the app. Of course there's nothing stopping you from just requesting all of the permissions you think you might need, even if you haven't built the features yet. You _will_ need to include the appropriate plugins in the build in addition to requesting required permissions. Your actual html file can be a remote file or it can have an iframe embedded into it, so you can deploy new application logic as easily as updating your website. – Allan Nienhuis Oct 06 '14 at 19:43
  • just to be clear: yes, you can update your site/app as long as the html is stored on a remote server (I usually do this via an iframe but that's not required). The thing that's important is to build the app with the appropriate permissions and plugins. Once that's done you can update your app as much as you like without redeploying. – Allan Nienhuis Oct 06 '14 at 19:45
  • If you store your html app on a remote server, you should also use the appCache html5 features, which ensure that the code/files are cached locally. If you do this right, you can use your app in offline mode really quite well. – Allan Nienhuis Oct 06 '14 at 19:48
  • If we need to put all the plugins before we build the app, then thats what I thought off... but its not the right solution. :) because we don't even know what feature we are going to add or remove. What we are thinking or thought is 'a java script statement should invoke android's feature'. If that is possible, then we can just update the html (at remote location) without even updating the APK. – User12111111 Oct 07 '14 at 07:15
  • There is no way of dynamically adding permissions and plugins to an app at run-time. The whole point of the permissions system in android is to let you know in advance of installation what the app will be capable of, so the user can decide whether to install it. Enabling completely new features after the user has given their permission for a certain set of behaviours isn't possible, and I doubt anyone would want it - too many security issues with that approach. That said, simply updating your app with new plugins and a new list of features requiring user approval would be pretty painless. – Allan Nienhuis Oct 09 '14 at 20:27
0

You may take a look at Intel XDK: https://software.intel.com/en-us/html5/tools and download it from http://xdk-software.intel.com/. It provides a cordova build option which you mentioned in your reply to a previous answer: https://software.intel.com/en-us/html5/articles/using-the-cordova-for-android-ios-etc-build-option

Thanks

0

Yes, Please take a look at addJavascriptInterface method in WebView. See more info here and here

Community
  • 1
  • 1
buddy123
  • 5,679
  • 10
  • 47
  • 73
  • Yes, I used the same, please see original question. But question is how to initiate android feature from Java script. – User12111111 Oct 06 '14 at 13:13
  • You will have to use "Android" object from within js and call a method it implements with parameters as needed, and that will immediately produce a callback in the java side. in this example that would be `Android. textToSpeak("Some text")` – buddy123 Oct 06 '14 at 18:20
  • I guess, you have looked at the code in the original question. What you are suggesting is already posted. – User12111111 Oct 07 '14 at 07:07