Android接入WebView(三)——制作浏览器书签与历史记录与二维码分享

Android接入WebView(一)——基本用法

Android接入WebView(二)——与JavaScript交互

Android接入WebView(三)——浏览器书签与历史记录与二维码分享

Android接入WebView(四)——浏览器书签与历史记录详细处理

Android接入WebView(五)——浏览器制作总结及源码分享

最近写了一个基于webview和zxing,sqlite实现的一款浏览器

主要功能有:扫描二维码以及打开本地二维码加载网页,书签和历史记录管理,无痕浏览,分享网址,分享网址二维码,浏览器出错自定义等功能。

源码地址:此资源解压后用Android可直接打开

 

 

制作浏览器书签与历史记录

我的思路是在本地创建一个sqlite用于保存书签与历史记录(关于sqlite的使用可以参考我的这篇文章

如下:

首先创建一个MyDatabaseHelper类

package mountain_hua.browser;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by dhs on 2018/7/26.
 */

public class MyDatabaseHelper extends SQLiteOpenHelper {
    //书签表
    public static final String CREATE_bookmarkDB = "create table bookmarkDB(" +
            "id integer primary key autoincrement," +
            "title text  key," +
            "url text)";

    //历史记录表
    public static final String CREATE_historyDB = "create table historyDB(" +
            "id integer primary key autoincrement," +
            "title text  key," +
            "url text)";

    private Context mContext;

    //构造方法:
    // 第一个参数Context上下文,
    // 第二个参数数据库名,
    // 第三个参数cursor允许我们在查询数据的时候返回一个自定义的光标位置,一般传入的都是null,
    // 第四个参数表示目前库的版本号(用于对库进行升级)
    public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory , int version){
        super(context,name ,factory,version);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //调用SQLiteDatabase中的execSQL()执行建表语句。
        db.execSQL(CREATE_bookmarkDB);
        db.execSQL(CREATE_historyDB);
        //创建成功
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //更新表
        db.execSQL("drop table if exists bookmarkDB");
        db.execSQL("drop table if exists historyDB");
        onCreate(db);
    }

}

1.添加书签:

获取当前的网址的title和url,添加进数据库,为了用户体验,增加了对话框确认网址信息,如下:

    //数据库添加数据(书签表)
    public void addinfo(String title,String url){
        //第二个参数是数据库名
        dbHelper = new MyDatabaseHelper(MainActivity.this,"usersDataBase",null,1);
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("title", title);
        values.put("url", url);
        //insert()方法中第一个参数是表名,第二个参数是表示给表中未指定数据的自动赋值为NULL。第三个参数是一个ContentValues对象
        db.insert("bookmarkDB",null,values);
        Toast.makeText(this,"添加成功",Toast.LENGTH_SHORT).show();
    }

    //添加书签对话框
    //url详细信息对话框
    public void url_infomation(){
        final Dialog dialog = new Dialog(this, R.style.NormalDialogStyle);
        View view = View.inflate(this, R.layout.bookmark_url_infomation, null);
        text_title = (EditText) view.findViewById(R.id.editText2);
        text_url = (EditText) view.findViewById(R.id.editText4);
        sure=(Button)view.findViewById(R.id.button4);
        dialog.setContentView(view);
        //使得点击对话框外部可消失对话框
        dialog.setCanceledOnTouchOutside(true);
        //设置对话框的大小
        view.setMinimumHeight((int) (ScreenSizeUtils.getInstance(this).getScreenHeight() * 0.23f));
        Window dialogWindow = dialog.getWindow();
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        lp.width = (int) (ScreenSizeUtils.getInstance(this).getScreenWidth() * 0.75f);
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.gravity = Gravity.CENTER;
        dialogWindow.setAttributes(lp);
        //显示详细信息
        text_url.setText(webView.getUrl().toString());
        text_title.setText(webView.getTitle().toString());
        dialog.show();
        //确定修改
        sure.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addinfo(text_title.getText().toString(),text_url.getText().toString());
                dialog.dismiss();
            }
        });

    }

效果如下: 确认添加————————————————查看书签

                                   

现在需要打开书签返回url数据,用的是startActivityForResult()方法.

在MainActivity的打开书签按钮中:

                Intent intent1=new Intent();
                intent1.setClass(MainActivity.this,bookmark.class);
                startActivityForResult(intent1,1);

MainActivity 的信息返回处理:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode){
            case 1:
                //接收书签返回url
                if(resultCode==RESULT_OK){
                    String  dataStringExtra2= data.getStringExtra("2_data_return");
                    webView.loadUrl(dataStringExtra2);
                }
            case 2:
                //接收历史记录返回url
                if(resultCode==RESULT_OK){
                    String  dataStringExtra2= data.getStringExtra("2_data_return");
                    webView.loadUrl(dataStringExtra2);
                }
            case 3:
                //接收扫描二维码返回url
                if(resultCode==RESULT_OK){
                    String  dataStringExtra2= data.getStringExtra("2_data_return");
                    webView.loadUrl(dataStringExtra2);
                }
        }
    }

在bookmark Activity中获得url后的处理:

 即结束当前activity,并返回url

Intent mIntent = new Intent();//没有任何参数(意图),只是用来传递数据
                    mIntent.putExtra("2_data_return", url);
                    setResult(RESULT_OK, mIntent);
                    finish();

2.添加历史记录:

需要用这两个方法获取历史记录url和title

webView.copyBackForwardList().getCurrentItem().getTitle()
webView.copyBackForwardList().getCurrentItem().getUrl()

添加进数据库:

 //数据库添加数据(历史记录表)
    public void addinfo_history( String title,String url){
        //第二个参数是数据库名
        dbHelper = new MyDatabaseHelper(this,"usersDataBase",null,1);
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("title", title);
        values.put("url", url);
        //insert()方法中第一个参数是表名,第二个参数是表示给表中未指定数据的自动赋值为NULL。第三个参数是一个ContentValues对象
        db.insert("historyDB",null,values);
    }

 

然后在setWebViewClient里面的 onPageFinished()方法里面执行把历史记录添加进数据库,但要在

shouldOverrideUrlLoading(),onPageStarted(),onPageFinished()这几个方法里设置一个boollean的变量if_load.

避免重定位导致的重复加载,给数据库里面添加两次历史记录

        webView.setWebViewClient(new WebViewClient(){
            boolean if_load;
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if_load=false;
               
            }

           

            //页面完成即加入历史记录
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);

                if(if_load&&!un_footprint) {
                    addinfo_history(view.copyBackForwardList().getCurrentItem().getTitle(), view.copyBackForwardList().getCurrentItem().getUrl());
                    if_load=false;
                }
            }

            //页面开始
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon){
                super.onPageStarted(view, url, favicon);

                if_load=true;
            }
        });

 

然后在在MainActivity的打开历史记录按钮中调用startActivityForResult()方法,和书签按钮一样,此处不再赘述

 

另外我接入了二维码扫描网址与二维码分享的功能,有关zxing二维码的知识可以参考我的这两篇文章

(1)Android利用zxing生成二维码,识别二维码,中间填充图片超详细、超简易教程

(2)Android利用zxing用相机扫描识别二维码(添加闪光灯和本地二维码)超详细教程

 

接下来说说二维码分享

原理就是传入url,转化成二维码,再通过截屏分享,代码如下:

package mountain_hua.browser;

import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;

import android.os.Environment;
import android.os.Message;
import android.os.Handler;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;

import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;


import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Hashtable;


/**
 * Created by dhs on 2018/7/25.
 */

public class be_qrcode extends AppCompatActivity {

    private ImageView im1;  //imageview图片
    private int w,h;        //图片宽度w,高度h
    private ProgressDialog dlog;//对话框
    String filePath;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.be_qrcode);
        final String url=getIntent().getStringExtra("url");
        final String title=getIntent().getStringExtra("title");

        TextView textView=(TextView)findViewById(R.id.textView);
        textView.setText(title);

        //显示对话框,绘制二维码
        dodialog(url);

        Button bt=(Button)findViewById(R.id.button);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popShotSrceenDialog(url);
            }
        });

        //返回上一页
        Button bt2=(Button)findViewById(R.id.button2);
        bt2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

    }

    //转化为二维码:
    public void createQRcodeImage(String url)
    {
        im1=(ImageView)findViewById(R.id.imageView1);
        w=300;
        h=300;

        try
        {
            //判断URL合法性
            if (url == null || "".equals(url) || url.length() < 1)
            {
                return;
            }
            Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            //图像数据转换,使用了矩阵转换
            BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, w, h, hints);
            int[] pixels = new int[w * h];
            //下面这里按照二维码的算法,逐个生成二维码的图片,
            //两个for循环是图片横列扫描的结果
            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    if (bitMatrix.get(x, y))
                    {
                        pixels[y * w + x] = 0xff000000;
                    }
                    else
                    {
                        pixels[y * w + x] = 0xffffffff;
                    }
                }
            }
            //生成二维码图片的格式,使用ARGB_8888
            Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
            //显示到我们的ImageView上面
            im1.setImageBitmap(bitmap);
        }
        catch (WriterException e)
        {
            e.printStackTrace();

        }

    }

    //进度条对话框
    private void dodialog(final String url){
        dlog=ProgressDialog.show(be_qrcode.this,"正在生成二维码","请稍等。。。");
        new Thread(){
            @Override
            public void run(){
                super.run();
                try {
                    createQRcodeImage(url);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Message message=Message.obtain();
                message.arg1=0;
                message.what=2;
                myHandler.sendMessage(message);
            }
        }.start();

    }

    //Handler
    Handler myHandler = new Handler(){
        /**
         * handleMessage接收消息后进行相应的处理
         */
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
           if(msg.what==2){
                //使对话框消失
                //Toast.makeText(be_qrcode.this,"二维码生成成功",Toast.LENGTH_SHORT).show();
                dlog.dismiss();
            }
        }
    };

    //截屏功能
    private void popShotSrceenDialog(String url){
        final AlertDialog cutDialog = new AlertDialog.Builder(this).create();
        View dialogView = View.inflate(this, R.layout.show_cut_screen_layout, null);
        ImageView showImg = (ImageView) dialogView.findViewById(R.id.show_cut_screen_img);
        dialogView.findViewById(R.id.share_cancel).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cutDialog.dismiss();
            }
        });
        dialogView.findViewById(R.id.share_img).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //分享
                Uri pa=Uri.fromFile(new File(filePath));//根据路径转化为uri
                Intent imageIntent = new Intent(Intent.ACTION_SEND);//调用系统的ACTION_SEND
                imageIntent.setType("image/png");
                imageIntent.putExtra(Intent.EXTRA_STREAM, pa);//EXTRA_STREAM对应转化为uri的path
                startActivity(Intent.createChooser(imageIntent, "分享"));
            }
        });
        //获取当前屏幕的大小
        int width = getWindow().getDecorView().getRootView().getWidth();
        int height = getWindow().getDecorView().getRootView().getHeight();
        //生成相同大小的图片
        Bitmap temBitmap = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888 );
        //找到当前页面的跟布局
        View view = getWindow().getDecorView().getRootView();
        //设置缓存
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        //从缓存中获取当前屏幕的图片
        temBitmap = view.getDrawingCache();
        //保存图片
        if (temBitmap != null)
        {
            try {
                // 获取内置SD卡路径
                String sdCardPath = Environment.getExternalStorageDirectory().getPath();
                // 图片文件路径,获取系统时间
                long time=System.currentTimeMillis();
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
                java.util.Date date=new java.util.Date(time);
                String str=sdf.format(date);
                filePath = sdCardPath + File.separator +str+"screenshot.png";

                File file = new File(filePath);
                FileOutputStream os = new FileOutputStream(file);
                temBitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
                os.flush();
                os.close();
            } catch (Exception e) {
                Toast.makeText(be_qrcode.this,"保存失败",Toast.LENGTH_SHORT).show();
            }
        }

        showImg.setImageBitmap(temBitmap);

        cutDialog.setView(dialogView);
        Window window = cutDialog.getWindow();
        window.setBackgroundDrawableResource(android.R.color.transparent);
        WindowManager m = window.getWindowManager();
        Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
        WindowManager.LayoutParams p = window.getAttributes(); // 获取对话框当前的参数值
        p.height = (int) (d.getHeight() * 0.8); // 高度设置为屏幕的0.6
        p.gravity = Gravity.CENTER;//设置弹出框位置
        window.setAttributes(p);
        window.setWindowAnimations(R.style.dialogWindowAnim);
        cutDialog.show();
    }

}

 

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Android中,WebView是用于显示网页内容的组件,而且它还具有加载HTML页面的功能。通常情况下,WebView会将网页内容在应用内部显示,但是我们也可以通过设置WebView的方式,使其在外部浏览器中打开网页。 要在外部浏览器中打开网页,我们可以通过重写WebViewWebViewClient类中的shouldOverrideUrlLoading方法来实现。该方法会在WebView加载URL之前被调用,并返回一个boolean值,该值表示是否由WebView处理URL。 代码示例如下: webView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // 使用外部浏览器打开网页 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; // 返回true表示由外部浏览器处理URL } }); 在上述代码中,我们首先创建了一个WebViewClient对象,并重写了其中的shouldOverrideUrlLoading方法。在该方法中,我们创建了一个Intent对象,使用ACTION_VIEW action,将URL转换为Uri,并通过该Intent启动外部浏览器来打开网页。然后我们返回true,表示由外部浏览器处理URL。 最后,我们将创建的WebViewClient对象设置给WebView,这样在加载网页时,WebView会先调用shouldOverrideUrlLoading方法来判断是否在外部浏览器中打开。若返回true,则会在外部浏览器中打开网页;若返回false,则会在WebView中显示网页内容。 通过上述方法,我们可以实现在Android中使用WebView加载H5页面时,使用外部浏览器打开网页。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值