Android and HTML5 开发手机应用

作为一个WEB开发者,HTML5让我兴奋,因为它可以将桌面应用程序功能带入浏览器中。但在国内,看着到处横行的IE8版本以下的浏览器,觉得到能大规模使用HTML5技术的那天,还遥遥无期。但面对iOS及Android等平台的手机用户越来越多,基于Webkit内核的移动浏览器一定能让HTML5先大规模应用起来。这将对对移动 Web 应用程序开发具有重大影响。

作为非常看好未来手机网络的我,也在一直研究Android平台的应用的开发,也许是因为自己更熟悉HTML及CSS、JS,并受到之前使用HTML和VC开发程序的影响,我也更愿意使用HTML来做Android程序的UI….

09年,在开发《华夏风云》游戏的时候,使用了基于Google Gear插件来做了很多离线应用,可惜Gear已经不在更新开发,被HTML5取代。下面介绍基于HTML 5 的Web 应用程序的本地存储,不再废话,例子说明一切。

 

一、离线应用缓存 HTML 5 Offline Application Cache

    • 在服务器上添加MIME TYPE支:text/cache-manifest

如果在Apache下添加:

 
1 AddType text/cache-manifest manifest

如果为Nginx,在添加:

 
1 text/cache-manifest manifest;

或者通过动态程序生成:

 
1 header('Content-type: text/cache-manifest; charset=UTF-8');
    • 创建 NAME.manifest:

新建清单文件 manifest

 
01 CACHE MANIFEST
02 # This is a comment.
03 # Cache manifest version 0.0.1
04 # If you change the version number in this comment,
05 # the cache manifest is no longer byte-for-byte
06 # identical.
07  
08 /app/static/default/js/models/prototype.js
09 /app/static/default/js/controllers/init.js
10  
11 NETWORK:
12 # All URLs that start with the following lines
13 # are whitelisted.
14  
15 http://a.com/
16  
17 CACHE:
18 # Additional items to cache.
19 /app/static/default/images/main/bg.png
20  
21 FALLBACK:
22 demoimages/ images/
    • 给 <html> 标签加 manifest 属性

建立manifest文件之后,需要在HTML文档中声明:
声明清单文件 manifest

<!doctype html>  <html manifest="notebook.manifest">  <head>  <meta charset="UTF-8" />  <meta name = "viewport" content = "width = device-width, user-scalable = no">  <title>NoteBook</title>  </head>  <body>  </body>  </html>

二、Key-Value Storage

三、Using the JavaScript Database

四、Android下使用WebView来做基于HTML5的App

见如下AndroidManifest.xml

 
01 < ?xml version="1.0" encoding="utf-8"?>
02 <manifest android:versionName="1.0" android:versionCode="1" package="com.xinze.joke"xmlns:android="http://schemas.android.com/apk/res/android">
03 <application android:label="@string/app_name" android:icon="@drawable/icon">
04 <activity android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar"android:configChanges="orientation|keyboardHidden|navigation" android:name=".Joke">
05 <intent -filter="">
06 <action android:name="android.intent.action.MAIN">
07 <category android:name="android.intent.category.LAUNCHER">
08 </category></action></intent>
09 </activity>
10 </application>
11 <uses android:name="android.permission.INTERNET" -permission="">
12 </uses></manifest>

注意:

 
1 <uses android:name="android.permission.INTERNET" -permission=""></uses>

, 允许网络应用,必须!!

Android主程序代码:

 
001 package com.xinze.joke;
002  
003 import android.app.Activity;
004 import android.app.AlertDialog;
005 import android.app.AlertDialog.Builder;
006  
007 import android.content.DialogInterface;
008  
009 import android.os.Bundle;
010 import android.view.KeyEvent;
011 import android.view.View;
012 import android.view.Window;
013 import android.view.WindowManager;
014 import android.webkit.JsPromptResult;
015 import android.webkit.JsResult;
016 import android.webkit.WebChromeClient;
017 import android.webkit.WebView;
018 import android.webkit.WebViewClient;
019  
020 import android.webkit.WebStorage ;
021  
022 public class Joke extends Activity {
023  
024 /** Called when the activity is first created. */
025 @Override
026 public void onCreate(Bundle savedInstanceState) {
027 super.onCreate(savedInstanceState);
028  
029 final WebView wv = new WebView(this);
030  
031 // 覆盖默认后退按钮的作用,替换成WebView里的查看历史页面
032 wv.setOnKeyListener(new View.OnKeyListener() {
033  
034 @Override
035 public boolean onKey(View v, int keyCode, KeyEvent event) {
036 if (event.getAction() == KeyEvent.ACTION_DOWN) {
037 if ((keyCode == KeyEvent.KEYCODE_BACK) && wv.canGoBack()) {
038 wv.goBack();
039 return true;
040 }
041 }
042 return false;
043 }
044 });
045  
046 // 设置支持Javascript
047 wv.getSettings().setJavaScriptEnabled(true);
048  
049 wv.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
050 wv.getSettings().setDatabaseEnabled(true);
051 wv.getSettings().setDatabasePath("/data/data/com.xinze.joke/databases");
052  
053 // 创建WebViewClient对象
054 WebViewClient wvc = new WebViewClient() {
055  
056 @Override
057 public boolean shouldOverrideUrlLoading(WebView view, String url) {
058 wv.loadUrl(url);
059 // 记得消耗掉这个事件。给不知道的朋友再解释一下,Android中返回True的意思就是到此为止吧,事件就会不会冒泡传递了,我们称之为消耗掉
060 return true;
061 }
062 };
063  
064 // 设置WebViewClient对象
065 wv.setWebViewClient(wvc);
066  
067 // 创建WebViewChromeClient
068 WebChromeClient wvcc = new WebChromeClient() {
069  
070 // 处理Alert事件
071 @Override
072 public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
073 // 构建一个Builder来显示网页中的alert对话框
074 Builder builder = new Builder(Joke.this);
075 builder.setTitle("笑死不偿命");
076 builder.setMessage(message);
077 builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
078 @Override
079 public void onClick(DialogInterface dialog, int which) {
080 result.confirm();
081 }
082 });
083 builder.setCancelable(false);
084 builder.create();
085 builder.show();
086 return true;
087 }
088  
089 // 处理Confirm事件
090 @Override
091 public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
092 Builder builder = new Builder(Joke.this);
093 builder.setTitle("删除确认");
094 builder.setMessage(message);
095 builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
096  
097 @Override
098 public void onClick(DialogInterface dialog, int which) {
099 result.confirm();
100 }
101  
102 });
103 builder.setNeutralButton(android.R.string.cancel, new AlertDialog.OnClickListener() {
104  
105 @Override
106 public void onClick(DialogInterface dialog, int which) {
107 result.cancel();
108 }
109  
110 });
111 builder.setCancelable(false);
112 builder.create();
113 builder.show();
114 return true;
115 }
116  
117 // 处理提示事件
118 @Override
119 public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
120 JsPromptResult result) {
121 // 看看默认的效果
122 return super.onJsPrompt(view, url, message, defaultValue, result);
123 }
124  
125 @Override
126 public void onExceededDatabaseQuota(String url, String
127 databaseIdentifier, long currentQuota, long estimatedSize, long
128 totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
129 quotaUpdater.updateQuota(204801);
130 }
131  
132 };
133  
134 wv.loadUrl("http://192.168.1.14/index.html");
135  
136 // 设置setWebChromeClient对象
137 wv.setWebChromeClient(wvcc);
138 setContentView(wv);
139 }
140 }

使用 JavaScript Database 的时候,需要特别注意:setDatabaseEnabled 以及 onExceededDatabaseQuota!


在Android上做HTML5应用用到了Webkit这个浏览器内核,这里具体不讨论Webkit for Android。

HTML5如何在安卓上开发HTML5应用

Android开发HTML5应用实际项目面临的问题1:

Android的HTML5应用程序概述 如何适配多分辨率的Android设备?

如何在Android中构建HTML5应用程序?

如何在Android中调试HTML5应用程序?

如何在Android中使用HTML5的本地储存?

如何在Android中使用HTML5的本地数据库?

如何在Android中使用HTML5的地理定位?

如何在Android中构建HTML5离线应用?

如何使用Canvas进行绘图?

上述问题这里提供一个ppt和参考代码

  
  
  
  
  1. package com.example.androidwebview; 
  2.  
  3. import android.os.Bundle; 
  4. import android.annotation.SuppressLint; 
  5. import android.app.Activity; 
  6. import android.content.Context; 
  7. import android.graphics.Bitmap; 
  8.  
  9. import android.view.KeyEvent; 
  10. import android.view.View; 
  11. import android.view.ViewGroup; 
  12. import android.view.Window; 
  13. import android.view.WindowManager; 
  14.  
  15. import android.webkit.GeolocationPermissions; 
  16. import android.webkit.WebChromeClient; 
  17. import android.webkit.WebSettings; 
  18. import android.webkit.WebStorage; 
  19. import android.webkit.WebView; 
  20. import android.webkit.WebSettings.RenderPriority; 
  21. import android.webkit.WebViewClient; 
  22.  
  23. public class MainActivity extends Activity { 
  24.  
  25.     private WebView mWebView; 
  26.  
  27.     private WebViewClient mWebViewClient = new WebViewClient() { 
  28.         // 处理页面导航 
  29.         @Override 
  30.         public boolean shouldOverrideUrlLoading(WebView view, String url) { 
  31.             mWebView.loadUrl(url); 
  32.             // 记得消耗掉这个事件。给不知道的朋友再解释一下, 
  33.             // Android中返回True的意思就是到此为止吧,事件就会不会冒泡传递了,我们称之为消耗掉 
  34.             return true
  35.         } 
  36.  
  37.         @Override 
  38.         public void onPageFinished(WebView view, String url) { 
  39.             super.onPageFinished(view, url); 
  40.         } 
  41.  
  42.         @Override 
  43.         public void onPageStarted(WebView view, String url, Bitmap favicon) { 
  44.             super.onPageStarted(view, url, favicon); 
  45.         } 
  46.     }; 
  47.  
  48.     // 浏览网页历史记录 
  49.     // goBack()和goForward() 
  50.     @Override 
  51.     public boolean onKeyDown(int keyCode, KeyEvent event) { 
  52.         if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) { 
  53.             mWebView.goBack(); 
  54.             return true
  55.         } 
  56.  
  57.         return super.onKeyDown(keyCode, event); 
  58.     } 
  59.  
  60.     private WebChromeClient mChromeClient = new WebChromeClient() { 
  61.  
  62.         private View myView = null
  63.         private CustomViewCallback myCallback = null
  64.  
  65.         // 配置权限 (在WebChromeClinet中实现) 
  66.         @Override 
  67.         public void onGeolocationPermissionsShowPrompt(String origin, 
  68.                 GeolocationPermissions.Callback callback) { 
  69.             callback.invoke(origin, truefalse); 
  70.             super.onGeolocationPermissionsShowPrompt(origin, callback); 
  71.         } 
  72.  
  73.         // 扩充数据库的容量(在WebChromeClinet中实现) 
  74.         @Override 
  75.         public void onExceededDatabaseQuota(String url, 
  76.                 String databaseIdentifier, long currentQuota, 
  77.                 long estimatedSize, long totalUsedQuota, 
  78.                 WebStorage.QuotaUpdater quotaUpdater) { 
  79.  
  80.             quotaUpdater.updateQuota(estimatedSize * 2); 
  81.         } 
  82.  
  83.         // 扩充缓存的容量 
  84.         @Override 
  85.         public void onReachedMaxAppCacheSize(long spaceNeeded, 
  86.                 long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) { 
  87.  
  88.             quotaUpdater.updateQuota(spaceNeeded * 2); 
  89.         } 
  90.  
  91.         // Android 使WebView支持HTML5 Video(全屏)播放的方法 
  92.         @Override 
  93.         public void onShowCustomView(View view, CustomViewCallback callback) { 
  94.             if (myCallback != null) { 
  95.                 myCallback.onCustomViewHidden(); 
  96.                 myCallback = null
  97.                 return
  98.             } 
  99.  
  100.             ViewGroup parent = (ViewGroup) mWebView.getParent(); 
  101.             parent.removeView(mWebView); 
  102.             parent.addView(view); 
  103.             myView = view; 
  104.             myCallback = callback; 
  105.             mChromeClient = this
  106.         } 
  107.  
  108.         @Override 
  109.         public void onHideCustomView() { 
  110.             if (myView != null) { 
  111.                 if (myCallback != null) { 
  112.                     myCallback.onCustomViewHidden(); 
  113.                     myCallback = null
  114.                 } 
  115.  
  116.                 ViewGroup parent = (ViewGroup) myView.getParent(); 
  117.                 parent.removeView(myView); 
  118.                 parent.addView(mWebView); 
  119.                 myView = null
  120.             } 
  121.         } 
  122.     }; 
  123.  
  124.     @SuppressLint("SetJavaScriptEnabled"
  125.     @SuppressWarnings("deprecation"
  126.     private void initSettings() { 
  127.  
  128.         requestWindowFeature(Window.FEATURE_NO_TITLE); //设置标题栏样式 
  129.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //全屏 
  130.          
  131.         setContentView(R.layout.activity_main); 
  132.         mWebView = (WebView) findViewById(R.id.webview); 
  133.  
  134.         WebSettings webSettings = mWebView.getSettings(); 
  135.         // 开启Javascript脚本 
  136.         webSettings.setJavaScriptEnabled(true); 
  137.  
  138.         // 启用localStorage 和 essionStorage 
  139.         webSettings.setDomStorageEnabled(true); 
  140.  
  141.         // 开启应用程序缓存 
  142.         webSettings.setAppCacheEnabled(true); 
  143.         String appCacheDir = this.getApplicationContext() 
  144.                 .getDir("cache", Context.MODE_PRIVATE).getPath(); 
  145.         webSettings.setAppCachePath(appCacheDir); 
  146.         webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); 
  147.         webSettings.setAppCacheMaxSize(1024 * 1024 * 10);// 设置缓冲大小,我设的是10M 
  148.         webSettings.setAllowFileAccess(true); 
  149.  
  150.         // 启用Webdatabase数据库 
  151.         webSettings.setDatabaseEnabled(true); 
  152.         String databaseDir = this.getApplicationContext() 
  153.                 .getDir("database", Context.MODE_PRIVATE).getPath(); 
  154.         webSettings.setDatabasePath(databaseDir);// 设置数据库路径 
  155.  
  156.         // 启用地理定位 
  157.         webSettings.setGeolocationEnabled(true); 
  158.         // 设置定位的数据库路径 
  159.         webSettings.setGeolocationDatabasePath(databaseDir); 
  160.  
  161.         // 开启插件(对flash的支持) 
  162.         webSettings.setPluginsEnabled(true); 
  163.         webSettings.setRenderPriority(RenderPriority.HIGH); 
  164.         webSettings.setJavaScriptCanOpenWindowsAutomatically(true); 
  165.  
  166.         mWebView.setWebChromeClient(mChromeClient); 
  167.         mWebView.setWebViewClient(mWebViewClient); 
  168.     } 
  169.  
  170.     @Override 
  171.     protected void onCreate(Bundle savedInstanceState) { 
  172.         super.onCreate(savedInstanceState); 
  173.  
  174.         this.initSettings(); 
  175.  
  176.         mWebView.loadUrl("http://192.168.1.14/Heaven"); 
  177.     } 

你可能感兴趣的:(android,html5,应用)