Android--Web Apps

官网简单翻译。。

Web Apps

在安卓平台上, 你可以使用apk安装一个应用或者通过浏览器打开一个web应用。如果选择了后者,你可以通过浏览器或者apk应用内嵌的webView框架为web页面定制viewport和风格属性。
web和android之间可以通过JavaScript进行交互。

相关链接

这里是为设计web页面的同学提供的。。
Pixel-Perfect UI in the WebView
Creating a Mobile-First Responsive Web Design
为不同的像素密度设置HDPI图片

制作支持不同的屏幕web页面

viewport

viewport是一个显示web页面、可拖拽的矩形区域。你可以设置他的一些属性,比如尺寸和比例。最主要的还是width
viewport的长宽和屏幕的长宽是各自独立的。比如设备宽如果为480像素,viewport可以是480,也可以是800(800时会有横条)。

WebView默认是将页面 适应屏幕缩放的。

对page的viewport设置(所有属性请看原文):

<head>
    <title>Example</title>
    <meta name="viewport" content="width=device-width, user-scalable=no" /> 
</head>

屏幕密度

CSS的像素值会在安卓上自动转换成DP单位。要注意
WebView内置了CSS媒体元素来支持DP,如下:

<link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio: 1.5)" href="hdpi.css" />

其中1.5可以为0.75,1.0,1.5。或者可以在样式表中定义。。。

在JS中获取DP值

if (window.devicePixelRatio == 1.5) {
    alert("This is a high-density screen");
} else if (window.devicePixelRatio == 0.75) {
    alert("This is a low-density screen");
}

使用WebView

webView继承自view,没什么多余功能,默认情况下就是单纯显示页面。
常见的使用场景是 用户协议、用户指导等可能经常更新布局(如果布局不变,也可以用activity,个人认为)的页面。
另一个场景是经常要联网检索数据的时候,比如email。

直接使用WebView

布局中添加,代码中find后,直接加载页面:

myWebView.loadUrl("http://www.example.com");

使用JS

启用JS

通过WebSettings

WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

绑定JS和Android代码

//android端WebView,创建名为Android的接口  
webView.addJavascriptInterface(new WebAppInterface(this), "Android");

//调用的WebAppInterface
public class WebAppInterface {
    Context mContext;

    /** Instantiate the interface and set the context */
    WebAppInterface(Context c) {
        mContext = c;
    }

    /** Show a toast from the web page */
    //如果Android4.2及以上,需要加标注
    @JavascriptInterface
    public void showToast(String toast) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }
}

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

<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
}
</script>
  • WebView自动初始化Android接口
  • JS调用的对象运行在另一个线程,而不是在创建的线程。
  • addJavascriptInterface()会使JS可以控制android应用。所以要注意页面来源和相关防范

处理导航

当点击WebView里的链接的时候,默认的方式是打开默认浏览器加载链接。你可以重写该操作,来让你的WebView自身加载链接,并且处理相关的前进和后退操作。
通过WebViewClient

//此时就可以用webView自己处理链接加载了
myWebView.setWebViewClient(new WebViewClient());  
//通过重写获取更多控制
private class MyWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (Uri.parse(url).getHost().equals("www.example.com")) {
            // This is my web site, 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, Uri.parse(url));
        startActivity(intent);
        return true;
    }
}

历史导航

如果你已经重写了shouldOverrideUrlLoading,可以如下控制前进和后退(注意这只是根据浏览记录的前进和后退,不会按层级识别。比如你从1页面进入2页面,再通过按钮“返回”1页面,再进入2页面,则会依次返回,而不是直接返回1后退出。)

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    // Check if the key event was the Back button and if there's history
    if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
        myWebView.goBack();
        return true;
    }
    // If it wasn't the Back key or there's no web page history, bubble up to the default
    // system behavior (probably exit the activity)
    return super.onKeyDown(keyCode, event);
}

在Android4.4集成WebView

4.4的WebView基于Chromium。提升了性能,并且更新HTML5,CSS3和JS标准以匹配最新的浏览器。

如果targetSdkVersion在18及以下,WebView会以quirks mode来禁止一些行为变化,当然它会尽可能的保证性能和web的一些标准。比如在4.4以上的机子运行这个app时,不能完全支持单一狭窄的列布局和默认的缩放等级。所以,尽管targetSdkVersion表示不考虑更新的平台,但是还是需要测试一下。

可以通过setWebContentsDebuggingEnabled()来使用桌面版Chrome调试。更多查看用chrome远程调试android

用户代理改变

//现在多了个chrome版本
Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16H) AppleWebKit/537.36
(KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36

获取代理:
- getDefaultUserAgent(),检索代理并且可以不保存、不实例化WebView
- getUserAgentString(),重写代理字符串

多线程和锁死线程

  • 请确保在主线程调用WebView的方法,否则会有预期之外的结果。
  • 确保不要锁死UI线程。比如等待JS回调时,可以用evaluateJavascript()异步运行JS

自定义URL处理

新的WebView在用自定义URL主题,进行资源请求和链接处理的时候添加了很多限制,比如只在url合法的时候调用shouldOverrideUrlLoading() or shouldInterceptRequest(),
如果在4.4上回调的数量很少或者加载资源失败,请确认下url是否符合RFC3986。
比如:

//WebView不会在点击这个链接时调用shouldOverrideUrlLoading(),
<a href="showProfile">Show Profile</a>

用户点击的时候会有不同的结果:

  • 如果你使用非合法或者空的base Url来loadData()或loadDataWithBaseURL(),以加载页面。那么你在这个页面的这一类链接都不会回调shouldOverrideUrlLoading()

    注意如果loadDataWithBaseURL()时,baseUrl是非合法的或者空的,那么内容里的链接必须是绝对路径。

  • 如果加载页面通过loadUrl,或者使用合法的baseUrl来loadDataWithBaseURL(),那么你就会收到回调。但是你获取的url是 “http://www.example.com/showProfile“(相对于你baseUrl的绝对路径),而不只是showProfile

你可以在页面这么自定义主题:

<a href="example-app:showProfile">Show Profile</a>

然后处理:

// The URL scheme should be non-hierarchical (no trailing slashes)
private static final String APP_SCHEME = "example-app:";

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith(APP_SCHEME)) {
        urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8");
        respondToData(urlData);
        return true;
    }
    return false;
}

如果没法改变HTML,可以自己加一个baseUrl以组成合法的地址

webView.loadDataWithBaseURL("example-app://example.co.uk/", HTML_DATA,
    null, "UTF-8", null);

Viewport改变

  • target-densitydpi属性不再支持,请参照相关链接里的 Pixel-Perfect UI in the WebView 文章。
  • 之前的viewport宽如果小于320,高如果小于WebView的高,会默认改成设备的宽高。现在viewport不变,WebView会放大它到适应屏幕宽度。
  • 不再支持多个tags。现在只承认最后定义的tag
  • 默认缩放已经过时。不再支持 getDefaultZoom() and setDefaultZoom() 。

4.4及以上的API已不支持,所以。。。

如果你不能在html设置viewport的宽度,那么调用setUseWideViewPort()来保证为page配置了个更大的viewport

WebSettings settings = webView.getSettings();
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);

风格改变

background CSS shorthand 覆盖 background-size

如果你设置了background style,那么这样写的话,background-size会被重置成默认值。

.some-class {
    background-size: contain;
    background: url('images/image.png') no-repeat;
}

修正方法是将background-size写在下面。

大小使用CSS像素,而不是屏幕像素

如果你设置缩放不可用并且初始化比例为1.0,那么可以使用window.devicePixelRatio获取缩放比例,然后乘以CSS像素值。否则就使用和JS交互的方式获取像素大小。更多查看quirksmode.org

单一或狭窄的列不再支持

不再支持NARROW_COLUMNS value for WebSettings.LayoutAlgorithm
你可以做如下处理:

  • 最好是修改HTML或者CSS,…

注:…处都是页面修改什么的,不懂,忽略了。下同。如有需要,可查看原文

用JS处理触摸事件

调试WebApps

在Android浏览器中使用Console APIs

在WebView中使用Console APIs

android2.1以上,你必须提供实现 onConsoleMessage() 的 WebChromeClient,这样才可以获取logcat。
支持API 7,则使用 onConsoleMessage(String, int, String) ,8及以上使用:

myWebView.setWebChromeClient(new WebChromeClient() {
    public boolean onConsoleMessage(ConsoleMessage cm) {
        Log.d("MyApplication", cm.message() + " -- From line "
                     + cm.lineNumber() + " of "
                     + cm.sourceId() );
        return true;
    }
});

ConsoleMessage包含了一个MessageLevel对象,可以通过messageLevel()方法获取消息等级以做出相应的处理。
消息示例:

Hello World -- From line 82 of http://www.example.com/hello.html

WebApps最佳实践

WebView

api文档中,上面没提到的代码部分

//= = 一般性起码加个ProgressBar吧。。
WebView webview = new WebView(this);
setContentView(webview);
// 加载HTML字符串,
String summary = "<html><body>You scored <b>192</b> points.</body></html>";
webview.loadData(summary, "text/html", null);
//配合title bar设置进度
getWindow().requestFeature(Window.FEATURE_PROGRESS);

webview.getSettings().setJavaScriptEnabled(true);

final Activity activity = this;
webview.setWebChromeClient(new WebChromeClient() {
    public void onProgressChanged(WebView view, int progress) {
    // Activities and WebViews measure progress with different scales.
    // The progress meter will automatically disappear when we reach 100%
    activity.setProgress(progress * 1000);
    }
});
webview.setWebViewClient(new WebViewClient() {
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show();
    }
});

webview.loadUrl("http://developer.android.com/");

猜你喜欢

转载自blog.csdn.net/u013867301/article/details/53163958