Android 日常开发(46)okhttp与WebView同步cookie(下)

前言

上一篇文章我们讲了okhttp的cookiejar和webview的使用的android cookieManager。这个设计确实不好,为啥三方库就不能基于系统进行扩展呢?
我的分析如下:首先okhttp并不只适用于android开发,java web开发在跨应用也有大量的使用常景。而内置与android.jar包下面的CookieManager跟android系统结合的特殊性,使得okhttp有自己的一套cookie运行,与cookie的本质和机制是差不多的。
Android 日常开发(46)okhttp与WebView同步cookie(下)_第1张图片
Android 日常开发(46)okhttp与WebView同步cookie(下)_第2张图片

问题描述

现实生活我们总能遇到奇奇怪怪,形形色色的需求。最近我就遇到了一个关于pdf的需求,android确实不太友好,webview也没有ios的webview那么功能丰富。绝大多数时候,我们只能通过一点一点的扩展。今天我便遇到了一个大坑!

我们有一个业务场景是接入老旧的OA系统,里面有一个页面上面有pdf等文档文件。要知道android内置的webview根本没有chrome那么强大,所以很多时候在pc上玩的六的东西,到手机全都翘辫子了!哈哈
所以我不得不开发一个pdf的插件来满足这个业务场景。

一开始我把pdf插件规划为以下几步!
1.webview拦截url,校验文件是文档类型,
2.根据url开始执行下载,保存到本地
3.使用地方放pdf查看库进行pdf加载

在不断的试错中,慢慢的把它们细分如下
1.webview拦截url,校验文件是文档类型,

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            String url = String.valueOf(request.getUrl());
            if (url.isEmpty()) {
                return true;
            }
            if (!url.startsWith("http") && !url.startsWith("HTTP")) {
                return true;
            }
             if(url.toLowerCase().endsWith(".pdf")){
                    return true;
                }
            view.loadUrl(url);
            return true;
        }

2.区分pdf和wps等文件

 public static String getMIMETypeStr(String end) {
        String type;
        if (end.equals("pdf")) {
            type = "application/pdf";
        } else if (end.equals("m4a") || end.equals("mp3") || end.equals("mid") ||
                end.equals("xmf") || end.equals("ogg") || end.equals("wav")) {
            type = "audio/*";
        } else if (end.equals("3gp") || end.equals("mp4")) {
            type = "video/*";
        } else if (end.equals("jpg") || end.equals("gif") || end.equals("png") ||
                end.equals("jpeg") || end.equals("bmp")) {
            type = "image/*";
        } else if (end.equals("apk")) {
            type = "application/vnd.android.package-archive";
        } else if (end.equals("pptx") || end.equals("ppt")) {
            type = "application/vnd.ms-powerpoint";
        } else if (end.equals("docx") || end.equals("doc")) {
            type = "application/vnd.ms-word";
        } else if (end.equals("xlsx") || end.equals("xls")) {
            type = "application/vnd.ms-excel";
        }else if(end.equals("txt")){
            type = "text/plain";
        }else if(end.equals("html") || end.equals("htm")){
            type = "text/html";
        } else {
            //如果无法直接打开,就跳出软件列表给用户选择
            type = "*/*";
        }
        return type;
    }

3.使用okhttp并把cookie信息同步到CookieJar接口的实现类中,

public class PersistenceCookieJar implements CookieJar {

    List<Cookie> cache = new ArrayList<>();

    WeakReference<Context> weakReference=null;
    public PersistenceCookieJar(Context mApp) {
        weakReference=new WeakReference<Context>(mApp);
    }

    //Http请求结束,Response中有Cookie时候回调
    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        //内存中缓存Cookie
        cache.addAll(cookies);



        ArrayList<String> cookieList=new ArrayList<>();
        for(Cookie cookie:cookies){
            cookieList.add(cookie.name()+"="+cookie.value());
        }

        url.topPrivateDomain();

        syncCookie(".yourhost.com",cookieList);

    }

    /**
     * 同步cookie
     *
     * @param url        地址
     * @param cookieList 需要添加的Cookie值,以键值对的方式:key=value
     */
    private void syncCookie(String url, ArrayList<String> cookieList) {
        CookieSyncManager.createInstance(weakReference.get());
        android.webkit.CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        cookieManager.removeAllCookie();
        cookieManager.removeSessionCookie();
        if (cookieList != null && cookieList.size() > 0) {
            for (String cookie : cookieList) {
                cookieManager.setCookie(url, cookie);
                cookieManager.setCookie("yourhost.com", cookie);
            }
        }
        String cookies = cookieManager.getCookie(url);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            cookieManager.flush();
        } else {
            CookieSyncManager.getInstance().sync();
        }
    }

    //Http发送请求前回调,Request中设置Cookie
    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        String urlString = url.toString();
        String cookiesString =  CookieManager.getInstance().getCookie(urlString);
        if (cookiesString != null && !cookiesString.isEmpty()) {
            String[] cookieHeaders = cookiesString.split(";");
            List<Cookie> cookies = new ArrayList<>(cookieHeaders.length);
            for (String header : cookieHeaders) {
                cookies.add(Cookie.parse(url, header));
            }
            return cookies;
        }
        return Collections.emptyList();
    }
}

4.获取写权限,根据url开始执行下载,保存到本地

        RxPermissions rxPermissions = null;
        rxPermissions = new RxPermissions(this);

        rxPermissions.request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE).subscribe(new Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean) {
                if (aBoolean) {
                } else {
//                    ToastUtil.showToast("无读写外部存储设备权限");
                }
            }
        });

5.gzip的无法获取到contentlength问题解决

Android 日常开发(46)okhttp与WebView同步cookie(下)_第3张图片

6.使用地方放pdf查看库进行pdf加载,使用pdf阅读库的完整特性

implementation(‘com.github.barteksc:android-pdf-viewer:3.2.0-beta.1’){
exclude group: ‘androidx.legacy’
exclude group: ‘androidx.core’
}

  nightMode=getCurrentTime();
        pdfView.fromFile(file)
                .onPageChange(this)
                .onPageError(this)
                .scrollHandle(new DefaultScrollHandle(getContext()))
                .onLoad(this)
                .enableAnnotationRendering(true)
                .defaultPage(defaultPage)//记住上次读到的页面
                .nightMode(nightMode)//暗黑模式
                .spacing(spacing) // 内部间距
                .password(password)//设置密码
                .fitEachPage(true)
                .swipeHorizontal(swipeHorizontal)//设置水平滚动
                .load();

你可能感兴趣的:(Android 日常开发(46)okhttp与WebView同步cookie(下))