顯示具有 webview 標籤的文章。 顯示所有文章
顯示具有 webview 標籤的文章。 顯示所有文章

2013/05/02

如何在 2.3.x android OS 呼叫 java 函式 ?

之前提到 WebView 與 javascript 使用,
但卻不適用於 android 2.3.x, 因為會有問題. (App 直接關閉)

下面是我所使用的方式, 讓我們可以在 2.3.x 去調用 java 函式.

稍微修改了一下所使用的 html, 修改 showMsg 所使用的方式
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Example</title>
<meta name="viewport" content="user-scalable=yes,target-densityDpi=device-dpi,width=device-width" />
<script type='text/javascript'>
function showMsg() {
prompt("This is prompt");
}
</script>
</head>
<body>
<input type='button' value='Click Me' onclick='showMsg();' />
</body>
</html>

執行結果如下圖:


透過這個我們可以利用這個方式來非直接的調用 java 函式,
特別注意的是第 10 行, 如果不 cancel, 畫面就會因為這個 prompt 而無法操作喔.
 WebChromeClient mWebChromeClient = new WebChromeClient() {

  @Override
  public boolean onJsPrompt(WebView view, String url, String message,
    String defaultValue, JsPromptResult result) {

   if ((defaultValue != null) && (defaultValue.length() != 0)) {
    if (defaultValue.equalsIgnoreCase("jstesting")) {
     Toast.makeText(MainActivity.this, R.string.msg_js_call_toast, Toast.LENGTH_SHORT).show();
     result.cancel();
     return true;
    }
   }
   
   return super.onJsPrompt(view, url, message, defaultValue, result);
  }
  
 };

再次修改一下 html 檔.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Example</title>
<meta name="viewport" content="user-scalable=yes,target-densityDpi=device-dpi,width=device-width" />
<script type='text/javascript'>
function showMsg() {
prompt("This is prompt", "jstesting");
}
</script>
</head>
<body>
<input type='button' value='Click Me' onclick='showMsg();' />
</body>
</html>

這樣就可以調用 java 函式了.

如果覺得上面方式有點怪異或麻煩, 也可以使用參考資料 [1] 的方式.
不過對我而言以上方式就是最簡單的方式了.

範例原始碼: WebViewExample4_1

參考資料:
[1]. http://fred-zone.blogspot.tw/2011/12/android-23x-javascript-interface.html

WebView 與 javascript 使用


之前講過怎麼簡單的使用 webview,
這邊也稍微紀錄一下如何在 webview 與 javascript 的使用.

預設 webview 是不能使用 javascript 的, 所以在初始時必須開啟 javascript,
除此之外, 還必須設定 web chrome client, 否則在我的範例則會無法達到效果.
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.getSettings().setJavaScriptEnabled(true);

我所使用的 html 檔案, 點擊按鈕會跳出一個訊息視窗
<!DOCTYPE html>
<html>
    <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     <title>Example</title>
        <meta name="viewport" content="user-scalable=yes,target-densityDpi=device-dpi,width=device-width" />
  <script type='text/javascript'> 
   function showMsg() {
    alert('This is alert dialog');
   }
  </script>
    </head>
 <body>
  <input type='button' value='Click Me' onclick='showMsg();'/>
 </body>
</html>

效果如下:


在 Webview 內使用 javascript 就是這麼簡單.

OK ! 接著如果要從 android 呼叫 html 裡的 javascript 呢?
只要使用以下方式就可以呼叫 html 裡的 javscript.
mWebView.loadUrl("javasript:showMsg();");
效果跟上圖一樣, 也是會跳出一個訊息視窗.

反過來, 可以從 html 呼叫 android 的 java 函式嗎 ?
可以, 一樣是透過 javascript 的方式!

2013/04/11

WebView with jsoup html parser

Jsoup 真的非常好用, 尤其搭配 WebView 使用.
以下範例為使用 Jsoup 並且將解悶有漫畫這網站顯示成我所想要的樣子.

Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ProgressBar
        android:id="@+id/progress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:indeterminate="true"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_alignParentBottom="true" 
        android:visibility="gone"/>

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/progress" />

</RelativeLayout>

要將網頁顯示成我們所要的格式, 最要下苦工的就是查看網頁的 html 原始檔, 幸好現在大部分網站的 html 都很有規格,
所以要解析也變得相當容易.
如果透過 WebView 載入畫面, 那麼資料將無法處理, 所以改成透過 HttpURLConnection 來連結網站, 並且處理資料.

 class LoadTask extends AsyncTask<String, Void, String> {

@Override
protected String doInBackground(String... params) {
StringBuilder sb = new StringBuilder();

String url = params[0];

try {

Document doc = HttpConnection
.connect(url)
.followRedirects(true)
.get();
if (doc == null) {
return null;
}

Element el = doc.select("ul#framemain_1").first();
if (el == null) {
return null;
}

Elements lis = el.select("li");

/** parse html data and create our own html file **/
sb.append("<html>");
sb.append("<title>WebViewExample Test</title>");
sb.append("<head></head>");
sb.append("<body style='margin: 0px; padding: 0px;'>");
sb.append("<table width='100%' border='1' cellspacing='0' cellpadding='5'><tbody>");
for (Element li: lis) {
Element cover = li.select("a > img").first();
if (cover != null) {
cover.parent().remove();
cover.attr("width", "100px");
cover.attr("height", "136px");
}
sb.append("<tr>");
if (cover == null) {
sb.append("<td colspan='2'>"+li.html()+"</td>");
} else {
sb.append("<td width='100px' height='136px'>"+cover.outerHtml()+"</td>");
sb.append("<td>"+li.html()+"</td>");
}
sb.append("</tr>");
}
sb.append("</body></html>");
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}

@Override
protected void onPostExecute(String result) {
if (result == null) {
Toast.makeText(MainActivity.this, R.string.msg_fail, Toast.LENGTH_SHORT).show();
} else {
mWebView.loadDataWithBaseURL(null, result, "text/html", "UTF-8", null);
}
}
}

主要工作就這麼簡單, 讀取 html, parse 出想要的, 然後寫一份所想要顯示的 html. 完成 !
結果如下:




原始碼: WebViewExample_3

參考 :
[1] Jsoup
[2] 怎麼使用 android 的 webview
[3] WebView with Progressbar

WebView with Progressbar

在 WebView 加上 progressbar 讓使用者知道目前載入進度,

主要利用 WebViewClient 和 WebChromeClient

WebViewClient 可以知道載入開始和載入結束, 可用來判斷是否該顯示 ProgressBar 或者該隱藏
WebChromeClient 可用來知道載入進度

Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<ProgressBar
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:indeterminate="true"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_alignParentBottom="true" 
android:visibility="gone"/>

<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/progress" />

</RelativeLayout>

主程式碼
package tw.clotai.webviewexample;

import tw.clotai.webviewexample.R;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;

public class MainActivity extends Activity {

WebView mWebView = null;
ProgressBar mBar = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mWebView = (WebView)findViewById(R.id.webview);
mBar = (ProgressBar)findViewById(R.id.progress);

mWebView.setWebViewClient(mWebViewClient);
mWebView.setWebChromeClient(mWebChromeClient);
mWebView.loadUrl("http://tw.yahoo.com");
//mWebView.loadUrl("file:///android_asset/example.html");
}

WebViewClient mWebViewClient = new WebViewClient() {

@Override
public void onPageFinished(WebView view, String url) {
mBar.setVisibility(View.GONE);
}

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
mBar.setVisibility(View.VISIBLE);
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
};

WebChromeClient mWebChromeClient = new WebChromeClient() {

@Override
public void onProgressChanged(WebView view, int newProgress) {
mBar.setIndeterminate(false);
mBar.setProgress(newProgress);
}

@Override
public void onReceivedTitle(WebView view, String title) {
if ((title != null) && (title.trim().length() != 0)) {
setTitle(title);
}
}
};
}




原始碼: WebViewExample_2

參考:
[1] 基本使用 webview

怎麼使用 android 的 webview

怎麼使用 android 的 webview, 很簡單, 不過這邊我一樣紀錄一下如何使用.


模擬器: android os 版本 2.3.3
SDK: android-17

以下是我的 Layout 檔案.
且記得在 AndroidManifest.xml 裡面加上網路權限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <WebView 
        android:id="@+id/webview"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_alignParentTop="true" />

</RelativeLayout>


我的 MainActivity 裡面內容如下:
public class MainActivity extends Activity {

 WebView mWebView = null;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  mWebView = (WebView)findViewById(R.id.webview);
  
  mWebView.loadUrl("http://tw.yahoo.com");
 }
}

這樣基本上就會載入畫面了, 可是如果實際測試, 會發現會使用外部的瀏覽器開啟.
原因是因為當載入時, yahoo 判斷是 Mobile 所以轉址, 而這轉址的動作我們並沒有處理, 所以就會開啟預設的瀏覽器瀏覽.
解決方式如下 :
public class MainActivity extends Activity {

 WebView mWebView = null;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  mWebView = (WebView)findViewById(R.id.webview);
  
  mWebView.setWebViewClient(mWebViewClient);
  mWebView.loadUrl("http://tw.yahoo.com");
 }
 
 
 WebViewClient mWebViewClient = new WebViewClient() {
  @Override
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
   view.loadUrl(url);
   return true;
  }
 };
}
顯示結果如下 :



2013/03/08

Sync cookie 到 webview

Webview 可以用來呈現網頁畫面, 其中最簡單的使用方式就是 loadUrl 這個 function. 一般網站可以不考慮到 cookie, 但如果牽扯到需要登入時, cookie 就很重要了. 如果單純使用 webview, 那 cookie 就不是問題, 但如果想要用 HttpURLConnection 這類別, 並且透過此類別做動作, 那麼要如何把所得到的 cookies 分享給 webview 使用 ? 以下就是 sync cookie 的方式.
android.webkit.CookieManager cookieManager = android.webkit.CookieManager.getInstance();

/** remove all cookies **/
cookieManager.removeAllCookie();
cookieManager.removeSessionCookie();
cookieManager.removeExpiredCookie();
/** Yes, we accept cookies **/
cookieManager.setAcceptCookie(true); 

StringBuilder sb = null;

for (HttpCookie cookie: cookies) {
 sb = new StringBuilder();
 if (cookie.getDomain() == null) {
  continue;
 }
 sb.append(cookie.getName() + "=" + cookie.getValue());
 sb.append("; domain=" + cookie.getDomain());
 cookieManager.setCookie(cookie.getDomain(), sb.toString());
}
cookieSyncManager.getInstance().sync();