App打包那点事

最近团队有需求将一个移动端网站打包成Android App,最初尝试过使用一些在线打包工具,但打包出来即难看又难用,所以还是撸起袖子自己干吧。需求无非是增加几个Tab栏,接入微博微信分享等社交功能,再用webview把网页加载进来,花了一点时间完成了,对常用的一些知识点做个总结。

webview的一些细节

处理页面导航

一般来说,在webview中点击一个链接之后,Android会打开一个能处理URL事件的APP,例如你默认的浏览器,如果我们想要自己去处理webview中网页的前进后退甚至更多的事情,就可以利用WebviewClient.

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient());

竟然敢叫Native App,我们自然就不会只有一个页面,所以我们需要在用户点击某些链接时跳转到新的Activity,以及在页面开始加载时显示加载动画,页面结束加载时让动画结束,此时我们可以重载WebViewClient中的方法。

private WebViewClient mClient = new WebViewClient() {
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            mRefreshLayout.setRefreshing(true);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if (mRefreshLayout.isRefreshing()) {
                mRefreshLayout.setRefreshing(false);
            }
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Intent intent = new Intent(getActivity(), DetailsActivity.class);
            intent.putExtra(AppUtil.KEY_URL, url);
            startActivity(intent);
            return true;
        }
    };
}

除此之外,当然可以通过重载webviewclient做更多的事情,如自定义网页出错界面等等。

获取页面标题

我们通常可以通过实现WebChromeClient中的接口去获取与显示网页标题:

mWebView.setWebChromeClient(new WebChromeClient() {
            public void onReceivedTitle(WebView view, String title){
                mTitle.setText(title);
            }
        });

但是当你在一个webview中有不同链接跳转,再通过webview.goback()返回的时候,标题并不会更新,其实我们可以在WebviewClient中实现onPageFinish接口时通过view.getTitle去获取标题,此时goback时也是能获取到标题更新的。

UserAgent

网页的移动端通常有自己的导航栏设计,我们在native中增加了导航栏,如果此时继续让网页的导航栏加载出来,界面就会出现两个导航栏,所以我们需要告诉网页,访问并非来源于一个真正的浏览器,而是一个App,当网页识别到该访问时,即将自己的导航栏隐藏掉。我们可以通过下面这段代码获取并定制专属App的UserAgent.

        WebSettings webSettings = mWebView.getSettings();
        String userAgent = webSettings.getUserAgentString();
        userAgent = userAgent.concat(" app和网页约定的字串");
        webSettings.setUserAgentString(userAgent);

缓存

大多数需要访问网页的App,假设你已经成功访问了网页,那么下一次你断掉网络之后再访问,还是可以看到上次访问的页面,所以我们可以在有网络时去获取新数据,而没有网络时即从webview的缓存中去加载数据。webview有四种缓存模式,根据需要灵活使用。

if (AppUtil.isNetworkConnected(getActivity())) {
            webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        } else {
            webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        }

js交互

有时候我们需要在客户端与js代码做交互,在我的项目中,加载网页时,执行一段Js代码,返回用户是否登录的信息,在这里就简单的使用js让客户端弹toast作演示。
首先,定义一个类,用于让js代码调用:

public 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 showToast(String toast) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }
}

调用下面这段代码,将WebAppInterface与webview绑定起来:

WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");

至此,js代码就可以和客户端通信了。

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }
</script>

上面这段代码,是写在网页端的,如果我们想客户端主动插入js代码也是可以的,非常简单:

String js = "Android.showToast(\"Hello Android\")"
webview.loadurl(“javascript:”+js);

代码混淆

兴高采烈的打开混淆准备发布应用的时候发现,所有的js调用不生效了!打开proguard-rules.pro可以发现显著的提示:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

所以,我们必须将有webviwe和js交互的类作声明,且必须使用完整的包名路径:

-keepclassmembers class com.google.test.TestActivity {
   public *;
}

同时4.2以上版本中我们需要对js调用接口作@javascriptinterface,声明,为了声明不丢失,我们还需要加上:

-keepattributes *Annotation*
-keepattributes *JavascriptInterface*

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值