Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android--Web Apps

Android--Web Apps

編輯:關於Android編程

官網簡單翻譯。。

Web Apps

在安卓平台上, 你可以使用apk安裝一個應用或者通過浏覽器打開一個web應用。如果選擇了後者,你可以通過浏覽器或者apk應用內嵌的webView框架為web頁面定制viewport和風格屬性。
web和android之間可以通過JavaScript進行交互。

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

viewport

viewport是一個顯示web頁面、可拖拽的矩形區域。你可以設置他的一些屬性,比如尺寸和比例。最主要的還是width
viewport的長寬和屏幕的長寬是各自獨立的。比如設備寬如果為480像素,viewport可以是480,也可以是800(800時會有橫條)。

WebView默認是將頁面 適應屏幕縮放的。

對page的viewport設置(所有屬性請看原文):




屏幕密度

CSS的像素值會在安卓上自動轉換成DP單位。要注意
WebView內置了CSS媒體元素來支持DP,如下:



其中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端


<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(),
Show Profile

用戶點擊的時候會有不同的結果:

如果你使用非合法或者空的base Url來loadData()或loadDataWithBaseURL(),以加載頁面。那麼你在這個頁面的這一類鏈接都不會回調shouldOverrideUrlLoading()

注意如果loadDataWithBaseURL()時,baseUrl是非合法的或者空的,那麼內容裡的鏈接必須是絕對路徑。

如果加載頁面通過loadUrl,或者使用合法的baseUrl來loadDataWithBaseURL(),那麼你就會收到回調。但是你獲取的url是 “http://www.example.com/http://blog.csdn.net/u013867301/article/details/showProfile“(相對於你baseUrl的絕對路徑),而不只是http://blog.csdn.net/u013867301/article/details/showProfile

你可以在頁面這麼自定義主題:

Show Profile

然後處理:

// 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 = "You scored <b>192</b> points.";
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/");
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved