The second article used by WebView -- Interacting with JS

Posted by silvrfoxx on Mon, 24 Jun 2019 20:54:07 +0200

I. Explanation of Basic Knowledge

1. Preface

In the last section, we learned about Android's WebView (Web View), and I believe we have learned the basic usage of WebView.

What we need to learn in this section is to complete the exchange of visits between HTML 5 and Android phones through HTML - > JS - > Java. Okay, let's not say much. Is there any truth? Let's experience this delicate connection by writing code.~

PS: For convenience, the HTML used in this section is placed in the assets directory in the form of a file, and the corresponding HTML can be loaded only through loadUrl ("file://android_asset/").~

2. Explanation of the Core Steps

First, we define a class to expose data, and JS calls Android through the exposed method (Public).

Next, we use the following code on the Web View page Activity:
webview.getSettings().setJavaScriptEnabled(true);
webview.addJavascriptInterface(object,"name");

Then call name.xxx in js or html to call the exposed method in the object:
For example: < input type = "button" value = "Toast prompt" onclick = "name. show Toast ('ha');"/>
Additionally, setJavaScript Enabled was only available on Android 4.4 systems!!! In the next section, we will talk about the changes of WebKit after Android 4.4 and what we should pay attention to!

1. Detailed use of examples (JS calls java)

HTML displays the dialog box between Toast and normal list through JS

1.) First put the written html file under the assert folder

<html>
<head>
    <title>Js call Android</title>
</head>

<body>
<input type="button" value="Toast Tipsʾ" onclick="myObj.showToast('test Js call java Code~');"/>
<input type="button" value="tabbed dialog box" onclick="myObj.showDialog();"/>
</body>
</html>

2.) Customize an Object object, through which js calls Android

/**
 * Created by Jay on 2015/9/11 0011.
 */
public class MyObject {
    private Context context;
    public MyObject(Context context) {
        this.context = context;
    }

    //Exposing methods that display Toast and dialog boxes to JS script calls
    public void showToast(String name) {
        Toast.makeText(context, name, Toast.LENGTH_SHORT).show();
    }

    public void showDialog() {
        new AlertDialog.Builder(context)
                .setTitle("contact list").setIcon(R.mipmap.ic_lion_icon)
                .setItems(new String[]{"Base God", "B god", "Cao Shen", "Street God", "Xiang Shen"}, null)
                .setPositiveButton("Sure?", null).create().show();
    }
}

Finally, MainActivity.java, enabling JavaScript support, and exposing objects through addJavascriptInterface~

public class MainActivity extends AppCompatActivity {
    private WebView wView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        wView = (WebView) findViewById(R.id.wView);
        wView.loadUrl("file:///android_asset/demo1.html");
        WebSettings webSettings = wView.getSettings();
        //(1) Setting up WebView allows js to be invoked
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDefaultTextEncodingName("UTF-8");
        //(2) Exposing object objects to Js and calling add JavaScript Interface
        wView.addJavascriptInterface(new MyObject(MainActivity.this), "myObj");
    }
}

The above method of loading is only suitable for API 17, because the interface of addJavascriptInterface is only visible on API 17.

2) HTML calls three different dialog boxes through JS

First, insert an HTML file under the assets directory: demo2.html:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <title>test Js Three different dialog boxes</title>
    <script language="JavaScript">
        function alertFun()
        {
            alert("Alert alert!");
        }
        function confirmFun()
        {
            if(confirm("Visit Baidu?"))
            {
                location.href = "http://www.baidu.com";
            }
            else alert("Cancel access!");
        }
        function promptFun()
        {
            var word = prompt("Prompt Dialog box","Please enter something...:");
            if(word)
            {
                alert("You entered:"+word)
            }else{
                alert("Ha-ha,You didn't write anything.!");
            }
        }
    </script>
</head>

<body>
<p>Display of three dialog boxes</p>

<p>Alert Dialog box</p>
<p>
    <input type="submit" name = "Submit1" value="Show 1" onclick="alertFun()"/>
</p>
<p>Confirm Dialog box</p>
<p>
    <input type="submit" name = "Submit2" value="Show 2" onclick="confirmFun()"/>
</p>
<p>Prompt Dialog box</p>
<p>
    <input type="submit" name = "Submit3" value="Show 3" onclick="promptFun()"/>
</p>
</body>
</html>

The main layout and prompt layout are not posted here! Go directly to MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private WebView wView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        wView = (WebView) findViewById(R.id.wView);

        //Get WebSetting objects, support js scripts, accessible files, support scaling, and encoding
        WebSettings webSettings = wView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setAllowFileAccess(true);
        webSettings.setBuiltInZoomControls(true);
        webSettings.setDefaultTextEncodingName("UTF-8");
        //Setting up WebChromeClient to handle various js events in Web pages
        wView.setWebChromeClient(new MyWebChromeClient());
        wView.loadUrl("file:///android_asset/demo2.html");
    }

    //Here you need to customize a class to implement the WebChromeClient class and override the handling of three different dialog boxes
    //Rewrite onJsAlert,onJsConfirm,onJsPrompt methods, respectively
    class MyWebChromeClient extends WebChromeClient {
    //Processing Alert dialog box in Js
        @Override
        public boolean onJsAlert(WebView view, String url, String message,
                                 final JsResult result) {
            //Create a Builder to display the dialog box in the Web page
            new Builder(MainActivity.this).setTitle("Alert Dialog box").setMessage(message)
                    .setPositiveButton("Sure?", new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.confirm();
                        }
                    }).setCancelable(false).show();
            return true;
        }
//Processing the Confirm dialog box in Js
        @Override
        public boolean onJsConfirm(WebView view, String url, String message,
                                   final JsResult result) {
            new Builder(MainActivity.this).setTitle("Confirm Dialog box").setMessage(message)
                    .setPositiveButton("Sure?", new OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.confirm();
                        }
                    })
                    .setNegativeButton("cancel", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.cancel();
                        }
                    }).setCancelable(false).show();
            return true;
        }
//Processing the Prompt dialog box in Js
        @Override
        public boolean onJsPrompt(WebView view, String url, String message,
                                  String defaultValue, final JsPromptResult result) {
            //1. Obtain a LayoutInflater object factory and load the specified layout into the corresponding object.
            final LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
            final View myview = inflater.inflate(R.layout.prompt_view, null);
            //Set TextView to the prompt information in the corresponding page, and edit to set the default text from the page
            ((TextView) myview.findViewById(R.id.text)).setText(message);
            ((EditText) myview.findViewById(R.id.edit)).setText(defaultValue);
            //Define the confirmation button on the dialog box
            new Builder(MainActivity.this).setTitle("Prompt Dialog box").setView(myview)
                    .setPositiveButton("Sure?", new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //Click OK to get the input value and pass it to the Web page for processing.
                            String value = ((EditText) myview.findViewById(R.id.edit)).getText().toString();
                            result.confirm(value);
                        }
                    })
                    .setNegativeButton("cancel", new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.cancel();
                        }
                    }).show();
            return true;
        }

    }
}

3.HTML reads Android contacts through JS and displays them

This code reads the contact list in Android mobile phone through js, and then displays it in HTML. When we click on a phone number, we jump directly to the dial-up page to realize the key: using onload() to load the corresponding JS script when the page is loaded, and a function defined in the JS script is to take out the passed object, get the data inside, and use for loop to unit line. Print out the form!

Write the contanct.html file under the assets folder as follows:

Write another business class Contact.java:

public class Contact {
    private String id;
    private String name;
    private String phone;

    public Contact(){}

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return this.id + "~" + this.name + "~" + this.phone;
    }
}
public class MainActivity extends AppCompatActivity {

    private WebView wView;

    @SuppressLint("JavascriptInterface")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Set up the relevant settings of WebView, in turn:
        //Supports js, does not save forms, does not save passwords, does not support scaling
        //Binding Java objects at the same time
        wView = (WebView) findViewById(R.id.wView);
        wView.getSettings().setJavaScriptEnabled(true);
        wView.getSettings().setSaveFormData(false);
        wView.getSettings().setSavePassword(false);
        wView.getSettings().setSupportZoom(false);
        wView.getSettings().setDefaultTextEncodingName("UTF-8");
        wView.addJavascriptInterface(new SharpJS(), "sharp");
        wView.loadUrl("file:///android_asset/demo3.html");
    }

    //Customize a business class of Js, which is the object passed to JS, and call directly javascript:sharp.contactlist()
    public class SharpJS {
        public void contactlist() {
            try {
                System.out.println("contactlist()The method is implemented!");
                String json = buildJson(getContacts());
                wView.loadUrl("javascript:show('" + json + "')");
            } catch (Exception e) {
                System.out.println("Failed to set data" + e);
            }
        }

        public void call(String phone) {
            System.out.println("call()The method is implemented!");
            Intent it = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone));
            startActivity(it);
        }
    }

    //Write the acquired collection of contacts into the JsonObject object and add it to the JsonArray array
    public String buildJson(List<Contact> contacts)throws Exception
    {
        JSONArray array = new JSONArray();
        for(Contact contact:contacts)
        {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", contact.getId());
            jsonObject.put("name", contact.getName());
            jsonObject.put("phone", contact.getPhone());
            array.put(jsonObject);
        }
        return array.toString();
    }

    //Define a method to get contacts, returning List < Contact > Data
    public List<Contact> getContacts()
    {
        List<Contact> Contacts = new ArrayList<Contact>();
        //(1) Query raw_contacts table to get contact id
        ContentResolver resolver = getContentResolver();
        Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        //Query Contact Data
        Cursor cursor = resolver.query(uri, null, null, null, null);
        while(cursor.moveToNext())
        {
            Contact contact = new Contact();
            //Get the contact name, cell phone number
            contact.setId(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)));
            contact.setName(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
            contact.setPhone(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
            Contacts.add(contact);
        }
        cursor.close();
        return Contacts;
    }
}

Topics: Android Java Javascript JSON