Android WebView专题

WebView 专题

第一个WebView程序:加载远程网址

  1. Layout添加WebView组件;

    
    
  2. 初始化组件,加载Url;

    public class FirstWebViewActivity extends AppCompatActivity{
    
        private WebView webView_first;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_first_web_view);
            webView_first=findViewById(R.id.webView_first);
            webView_first.loadUrl("https://www.baidu.com/");
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            webView_first.removeAllViews();
            webView_first.destroy();
        }
    }
    
  3. Manifest文件添加网络访问权限

    <uses-permission android:name="android.permission.INTERNET" />
    
  4. 出现错误:

    NetworkSecurityConfig   com.hymy.webviewstarter              D  No Network Security Config specified, using platform default
    Denied starting an intent without a user gesture, URI
    

    解决方法:

    res/xml下添加 network_security_config.xml 文件:

    
    <network-security-config> //默认配置:允许明文通信
        <base-config cleartextTrafficPermitted="true" />
    network-security-config>
    

    在AndroidManifest.xml中引用

  5. 出现错误:

    访问bing.com无法加载封面图片:

    The resource xxx was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally.
    

    解决方法:

    webView_first=findViewById(R.id.webView_first);
    //启用JavaScript
    WebSettings webSettings = webView_first.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webView_first.loadUrl("https://cn.bing.com/?mkt=zh-CN");
    
  6. 下载:在bing搜索网站首页,好看的壁纸,点击可以下载图片,将图片下载到 SD 卡下的Downloader目录下

    参考:https://cloud.tencent.com/developer/article/1742327

  7. 将 JavaScript代码绑定到Android代码

    js调用Android代码中的方法

    新建 WebAppInterface 类

    /**
     * @Author : alex
     * @Date : on 2023/11/14 09:21.
     * @Description :描述
     */
    public class WebAppInterface {
        Context mContext;
    
        /**
         * 初始化接口,并设置context
         * @param c
         */
        WebAppInterface(Context c){
            mContext=c;
        }
    
        /**
         * 在Web页面显示消息提示
         * @param toast
         */
        @JavascriptInterface
        public void showToast(String toast){
            Toast.makeText(mContext,toast,Toast.LENGTH_SHORT).show();
        }
    }
    

    webview 绑定接口:

     webView_first.addJavascriptInterface(new WebAppInterface(this),"Android");
    

    html代码示例:

    
    
      
        
        
        Bootstrap demo
        
      
      
        

    Hello, world!

  8. webview中的跳转连接

    参考:https://www.digitalocean.com/community/tutorials/android-webview-example-tutorial

    当 html 中有跳转链接的时候,可以直接阻止、选择性阻止在我们的App跳转、或者可以打开系统浏览器,加载外部链接。

    webView_first.setWebViewClient(new MyWebViewClient());
    
    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            Log.i("FirstWebViewActivity",request.getUrl().getHost());
            if ("192.168.96.108".equals(request.getUrl().getHost())) {
                // This is my website, so do not override; let my WebView load the page
                return false;
            }
            // Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
            Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
            startActivity(intent);
            return true;
        }
    }
    
  9. webview加载本地网页,实现 sqlite 数据库增删改查

    使用的库 gson:

    implementation 'com.google.code.gson:gson:2.8.5'
    

    首先新建assets文件夹,android默认工程没有创建。

    Android WebView专题_第1张图片

    编写 DBHelper ,定义数据库名,在 onCreate 中初始化数据库:

    public class MyDatabaseHelper extends SQLiteOpenHelper {
        public static final String DATABASE_NAME = "student.db";
        public static final int DATABASE_VERSION =1;
    
        public MyDatabaseHelper(Context context){
            super(context,DATABASE_NAME,null,DATABASE_VERSION);
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            // 数据库首次创建时调用,执行创建表等语句
            // 创建student表
            db.execSQL("CREATE TABLE student (" +
                    "id INTEGER PRIMARY KEY AUTOINCREMENT," +
                    "name TEXT," +
                    "age INTEGER," +
                    "birth TEXT)");
            // 如果需要初始化数据可以在这里插入:
            db.execSQL("INSERT INTO student (name, age, birth) " +
                    "VALUES ('张三', 18, '1980-01-01')");
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // 数据库版本更新时调用
    
        }
    }
    

    然后定义 MyApplication,在程序启动的时候初始化数据库:

    public class MyApplication extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            //检测数据库是否存在,不存在则创建数据库
            Context context = getApplicationContext();
            MyDatabaseHelper dbHelper = new MyDatabaseHelper(context);
            SQLiteDatabase db = dbHelper.getWritableDatabase();
        }
    }
    

    定义数据增、查接口类,供H5中调用:

    public class JsDBInterface {
        private SQLiteDatabase db;
        public JsDBInterface(Context context){
            // 在构造函数中打开数据库
            MyDatabaseHelper helper = new MyDatabaseHelper(context);
            db = helper.getWritableDatabase();
        }
    
        /**
         * 插入数据
         * @param name
         * @param age
         * @param birth
         */
        @JavascriptInterface
        public void insertData(String name,int age,String birth){
            //检查参数
            if(name==null||name.isEmpty()){
                return;
            }
            //插入数据
            ContentValues values = new ContentValues();
            values.put("name",name);
            values.put("age",age);
            values.put("birth",birth);
            db.insert("student",null,values);
            Log.i("插入数据",name);
        }
    
        /**
         * 查询数据
         * @return
         */
        @JavascriptInterface
        public String getAllStudents(){
            List<Student> students = new ArrayList<>();
            //查询数据库中的所有学生
            Cursor cursor = db.query("student",null,null,null,null,null,null);
            //获取所有列
    //        String[] cols = cursor.getColumnNames();
    //        int nameIndex=-1;
            while (cursor.moveToNext()){
                int columnIndex1=cursor.getColumnIndex("id");
                int columnIndex2=cursor.getColumnIndex("name");
                int columnIndex3=cursor.getColumnIndex("age");
                int columnIndex4=cursor.getColumnIndex("birth");
                int id=0;String name="null";int age=0;String birth="0000-00-00";
                if(columnIndex1>=0){
                    id = cursor.getInt(columnIndex1);
                }
                if(columnIndex2>=0){
                    name=cursor.getString(columnIndex2);
                }
                if(columnIndex3>=0){
                    age = cursor.getInt(columnIndex3);
                }
                if(columnIndex4>=0){
                    birth=cursor.getString(columnIndex4);
                }
    
                Student stu = new Student(id,name,age,birth);
                students.add(stu);
            }
            cursor.close();
            Gson gson = new Gson();
            String json = gson.toJson(students);
            return json;
        }
    }
    

    数据实体类:

    public class Student {
        private int id;
        private String name;
        private int age;
        private String birth;
    
        public int getId() {
            return id;
        }
    
        public Student(int id,String name, int age, String birth) {
            this.id=id;
            this.name = name;
            this.age = age;
            this.birth = birth;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getBirth() {
            return birth;
        }
    
        public void setBirth(String birth) {
            this.birth = birth;
        }
    }
    

    在 Activity 中注册接口:

    webView.addJavascriptInterface(new JsDBInterface(MainActivity.this),"JsDBInterface");
    
    加载本地网页:
    private String localUrl="file:///android_asset/index.html";
    webView_first.loadUrl(localUrl);
    

    HTML 使用了vue,调用代码如下:

    
    
    
        
        
        Document
        
    
    
        

    {{message}}

    • {{user.name}}

      结果:
      Android WebView专题_第2张图片

    • webview h5 alert 不运行

      参考:https://copyprogramming.com/howto/modify-alert-title-javascript-in-android-webview

      最简单的处理方法是:添加下面的代码

      webView_first.setWebChromeClient(new WebChromeClient());
      

      Android WebView专题_第3张图片

    但是上面的标题会显示网址,可以用下面的方法进行修改:

    webView_first.setWebChromeClient(new WebChromeClient(){
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            AlertDialog dialog = new AlertDialog.Builder(view.getContext())
                .setTitle("提示")
                .setMessage(message)
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // do nothing
                    }
                }).create();
            dialog.show();
            result.confirm();
            return true;
        }
    });
    

    修改后:

    Android WebView专题_第4张图片

    此外如果对 alert, prompt, confirm统一进行修改,可以使用下面代码:

    webView_first.setWebChromeClient(new WebChromeClient(){
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            new AlertDialog.Builder(view.getContext())
                .setTitle("alert")
                .setMessage(message)
                .setPositiveButton("确定", (DialogInterface dialog, int which) -> result.confirm())
                .setOnDismissListener((DialogInterface dialog) -> result.confirm())
                .create()
                .show();
            return true;
        }
    
        @Override
        public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
            new AlertDialog.Builder(view.getContext())
                .setTitle("confirm")
                .setMessage(message)
                .setPositiveButton("确定", (DialogInterface dialog, int which) -> result.confirm())
                .setNegativeButton("取消", (DialogInterface dialog, int which) -> result.cancel())
                .setOnDismissListener((DialogInterface dialog) -> result.cancel())
                .create()
                .show();
            return true;
        }
    
        @Override
        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
            final EditText input = new EditText(view.getContext());
            input.setInputType(InputType.TYPE_CLASS_TEXT);
            input.setText(defaultValue);
            new AlertDialog.Builder(view.getContext())
                .setTitle("prompt")
                .setMessage(message)
                .setView(input)
                .setPositiveButton("确定", (DialogInterface dialog, int which) -> result.confirm(input.getText().toString()))
                .setNegativeButton("取消", (DialogInterface dialog, int which) -> result.cancel())
                .setOnDismissListener((DialogInterface dialog) -> result.cancel())
                .create()
                .show();
            return true;
        }
    });
    

    你可能感兴趣的:(android)