原生app的开发成本和网页相比相对较高,所以越来越多的app使用网页来作为界面,甚至完全将一个网站封装成app,可以提高开发速度,还能基本实现跨平台。@H_616_9@
下面以Android为例,在ubuntu-14.04.4-desktop-amd64环境实现一个简单的WebView封装网站成app的过程。
环境准备
开发环境需要Java SDK(官网下载),Android SDK(官网下载)。
Java SDK安装
wget@H_616_9@ http://@H_616_9@download.Oracle.com/otn-pub/java/jdk/8u91-b14/jdk-8u91-linux-x64.tar.gz
tar -x -f @H_616_9@jdk-8u91-linux-x64.tar.gz
然后配置PATH路径及JAVA_HOME
在最后添加
export JAVA_HOME=JDK解压目录
export CLASSPATH@H_616_9@=.:$CLASSPATH:$JAVA_HOME/lib
export PATH@H_616_9@=$PATH:$JAVA_HOME/bin
保存退出vi,刷新配置
Android SDK安装
wget@H_616_9@ https://@H_616_9@dl.google.com/android/android-sdk_r24.4.1-linux.tgz@H_616_9@
tar@H_616_9@ -x -f android-sdk_r24.4.1@H_616_9@-linux.tgz
cd android@H_616_9@-sdk-linux/tools
先看一下有哪些sdk版本可以安装
./android list sdk
然后安装需要的sdk版本
@H_616_9@
项目建立及代码编写
在任意地方新建一个目录,保存这个项目,然后新建一个src目录,用于存放源文件。因为Java有包的概念,所以进入src目录后,根据包名的层次,依次建立相应目录,然后新建Java源程序文件,比如:
1@H_616_9@ package@H_616_9@ test.android;
@H_616_9@ 2@H_616_9@
3@H_616_9@ import@H_616_9@ android.app.Activity;
@H_616_9@ 4@H_616_9@ import@H_616_9@ android.os.bundle;
@H_616_9@ 5@H_616_9@ //@H_616_9@ import android.app.AlertDialog;@H_616_9@
6@H_616_9@ import@H_616_9@ android.view.Window;
@H_616_9@ 7@H_616_9@ //@H_616_9@ import android.view.WindowManager;@H_616_9@
8@H_616_9@ import@H_616_9@ android.view.KeyEvent;
@H_616_9@ 9@H_616_9@ import@H_616_9@ android.webkit.WebView;
@H_616_9@10@H_616_9@ import@H_616_9@ android.webkit.WebViewClient;
@H_616_9@11@H_616_9@ //@H_616_9@import android.webkit.WebChromeClient;
@H_616_9@12@H_616_9@ //@H_616_9@ import android.webkit.JsResult;
@H_616_9@13@H_616_9@ //@H_616_9@ import android.content.DialogInterface;
@H_616_9@14@H_616_9@ //@H_616_9@ import android.content.DialogInterface.onClickListener;@H_616_9@
15@H_616_9@
16@H_616_9@ public@H_616_9@ class@H_616_9@ Main extends@H_616_9@ Activity {
@H_616_9@17@H_616_9@ public@H_616_9@ static@H_616_9@ final@H_616_9@ String LOAD_URL = "http://www.baidu.com/";
@H_616_9@18@H_616_9@
19@H_616_9@ private@H_616_9@ WebView webView = null@H_616_9@;
@H_616_9@20@H_616_9@
21@H_616_9@ public@H_616_9@ void@H_616_9@ onCreate(Bundle savedInstanceStatE) {
@H_616_9@22@H_616_9@ super@H_616_9@.onCreate(savedInstanceStatE);
@H_616_9@23@H_616_9@
24@H_616_9@ //@H_616_9@this.requestWindowFeature(Window.FEATURE_NO_titlE);
@H_616_9@25@H_616_9@ //@H_616_9@this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);@H_616_9@
26@H_616_9@
27@H_616_9@ webView = new@H_616_9@ WebView(this@H_616_9@);
@H_616_9@28@H_616_9@ this@H_616_9@.setContentView(webView);
@H_616_9@29@H_616_9@ webView.setWebViewClient(new@H_616_9@ WebViewClient() {
@H_616_9@30@H_616_9@ public@H_616_9@ void@H_616_9@ onPageFinished(WebView view,String url) {
@H_616_9@31@H_616_9@ //@H_616_9@webView.evaluateJavascript("test();",null);@H_616_9@
32@H_616_9@ }
@H_616_9@33@H_616_9@ });
@H_616_9@34@H_616_9@ /*@H_616_9@
35@H_616_9@ webView.setWebChromeClient(new WebChromeClient() {
@H_616_9@36@H_616_9@ public Boolean onJSALErt(WebView view,String url,String message,JsResult result) {
@H_616_9@37@H_616_9@
38@H_616_9@ new AlertDialog.builder(_this)
@H_616_9@39@H_616_9@ .setmessage(messagE)
@H_616_9@40@H_616_9@ .setPositiveButton("OK",new DialogInterface.onClickListener() {
@H_616_9@41@H_616_9@ public void onClick(DialogInterface dialog,int which) {}
@H_616_9@42@H_616_9@ }).show();
@H_616_9@43@H_616_9@
44@H_616_9@ return true;
@H_616_9@45@H_616_9@ }
@H_616_9@46@H_616_9@ });
@H_616_9@47@H_616_9@ */@H_616_9@
48@H_616_9@ webView.getSetTings().setJavaScriptEnabled(true@H_616_9@);
@H_616_9@49@H_616_9@ webView.addJavascripTinterface(this@H_616_9@,"native");
@H_616_9@50@H_616_9@ webView.loadUrl(LOAD_URL);
@H_616_9@51@H_616_9@ }
@H_616_9@52@H_616_9@
53@H_616_9@ //@H_616_9@ overwrite BACk button@H_616_9@
54@H_616_9@ public@H_616_9@ Boolean@H_616_9@ onKeyDown(int@H_616_9@ keyCode,KeyEvent event) {
@H_616_9@55@H_616_9@ if@H_616_9@ (KeyEvent.KEYCODE_BACK == keyCode && webView.canGoBACk()) {
@H_616_9@56@H_616_9@ webView.goBACk();
@H_616_9@57@H_616_9@ return@H_616_9@ true@H_616_9@;
@H_616_9@58@H_616_9@ }
@H_616_9@59@H_616_9@
60@H_616_9@ return@H_616_9@ super@H_616_9@.onKeyDown(keyCode,event);
@H_616_9@61@H_616_9@ }
@H_616_9@62@H_616_9@
63@H_616_9@ }
将文件保存为Main.java
回到项目根目录,新建另一个文件,保存为AndroidManifest.xml,内容如下:
1@H_616_9@ <?@H_616_9@xml version="1.0" encoding="utf-8"@H_616_9@?>@H_616_9@
2@H_616_9@ <@H_616_9@@H_742_450@manifest @H_616_9@xmlns:android@H_616_9@="http://scheR_559_11845@as.android.com/apk/res/android"@H_616_9@ package@H_616_9@="test.android"@H_616_9@>@H_616_9@
3@H_616_9@ <@H_616_9@@H_742_450@application @H_616_9@android:icon@H_616_9@="@drawable/icon"@H_616_9@
4@H_616_9@ android:label@H_616_9@="@String/app_name"@H_616_9@>@H_616_9@
5@H_616_9@ <@H_616_9@@H_742_450@activity @H_616_9@android:name@H_616_9@=".Main"@H_616_9@>@H_616_9@
6@H_616_9@ <@H_616_9@@H_742_450@intent-filter@H_616_9@>@H_616_9@
7@H_616_9@ <@H_616_9@@H_742_450@action @H_616_9@android:name@H_616_9@="android.intent.action.MAIN"@H_616_9@ />@H_616_9@
8@H_616_9@ <@H_616_9@@H_742_450@category @H_616_9@android:name@H_616_9@="android.intent.category.LAUNCHER"@H_616_9@ />@H_616_9@
9@H_616_9@ </@H_616_9@@H_742_450@intent-filter@H_616_9@>@H_616_9@
10@H_616_9@ </@H_616_9@@H_742_450@activity@H_616_9@>@H_616_9@
11@H_616_9@ </@H_616_9@@H_742_450@application@H_616_9@>@H_616_9@
12@H_616_9@
13@H_616_9@ <@H_616_9@@H_742_450@uses-permission @H_616_9@android:name@H_616_9@="android.permission.INTERNET"@H_616_9@ />@H_616_9@
14@H_616_9@
15@H_616_9@ </@H_616_9@@H_742_450@manifest@H_616_9@>@H_616_9@
在项目根目录新建res目录,在res内新建drawable和values目录。
在values内新建xml文件Strings.xml,内容如下:
<?@H_616_9@xml version="1.0" encoding="utf-8"@H_616_9@?>@H_616_9@
<@H_616_9@@H_742_450@resources@H_616_9@>@H_616_9@
<@H_616_9@@H_742_450@String @H_616_9@name@H_616_9@="app_name"@H_616_9@>网页打包@H_616_9@</@H_616_9@@H_742_450@String@H_616_9@>@H_616_9@
<@H_616_9@@H_742_450@String @H_616_9@name@H_616_9@="web_url"@H_616_9@>@H_616_9@http://www.baidu.com</@H_616_9@@H_742_450@String@H_616_9@>@H_616_9@
</@H_616_9@@H_742_450@resources@H_616_9@>@H_616_9@
然后将需要的程序图标拷入drawable目录,文件名为icon.png
演示示例可以从这里下载
编译
先切换到项目目录。
首先要编译资源,在项目根目录创建gen目录,保存生成的R.java资源编号,在控制台输入以下命令:
/opt/android-sdk-linux/build-tools/24.0@H_616_9@.0@H_616_9@/aapt package -f -m -J gen -S res -I /opt/android-sdk-linux/platforms/android-24@H_616_9@/android.jar -M AndroidManifest.xml
javac -encoding utf-8 -source 1.6 -target 1.6 -bootclasspath /opt/android-sdk-linux/platforms/android-24/android.jar -d bin/classes src/test/android/Main.java gen/test/android/R.java
将编译好的文件打包成dex格式
/opt/android-sdk-linux/build-tools/24.0.0/dx --dex --output=bin/classes.dex bin/classes
将资源文件打包
/opt/android-sdk-linux/build-tools/24.0.0/aapt package -f -M AndroidManifest.xml -S res -I /opt/android-sdk-linux/platforms/android-24/android.jar -F bin/main.ap_
将所有文件打包成apk
java -classpath /opt/android-sdk-linux/tools/lib/sdklib.jar com.android.sdklib.build.ApkBuilderMain main_unsigned.apk -v -u -z bin/main.ap_ -f bin/classes.dex -rf src
1 keytool -genkey -alias my.keystore -keyalg RSA -validity 20000 -keypass 123456 -storepass 123456 -keystore my.keystore
生成签名文件时,提示输入姓名单位之类都可以直接回车忽略,最后输入y确认即可
对apk文件签名
jarsigner -verbose -keystore my.keystore -keypass 123456 -storepass 123456 -signedjar main.apk main_unsigned.apk my.keystore
接下来就可以安装测试了