2019 安卓混合开发视频精讲

原生语言

苹果手机:iOS 系统,由 Swift 和 C++ / Objective-C 语言编写,后缀名为 ipa (iOS 开发的安装包的后缀名)
Swift 语言是一种开源的语言(半开半闭)

安卓手机:Android 系统,由 Java (Android)语言编写,后缀名为 apk 开源的。

wp手机: Windows Phone 系统,由 C# 语言编写,后缀名分为两类 (wp7 wp8的是 xap wp8.1以后用 8.1 的 SDK 开发的是 appx)一般说到混合开发不考虑这个版本

序号 系统 语言 后缀名
1 iOS OC/C++/Swift ipa
2 Android Java apk
3 wp C# appx

混合开发

原生语言开发 + JavaScript 开发
缘由:
JavaScript 无法调动系统的原生功能(拍照、短信、打电话、通信录),但是原生(iOS、Android、wp)可以,原生有很大的适配问题(特别是 Android),JavaScript 可以很好的解决这个问题。

术语:
Hybrid App —— JavaScript + iOS/Android 写的。
Web App —— m 站,touch 端项目 手机网站 —— 纯 JavaScript 写的。
Native App —— 纯 iOS/Android 编写的程序。

Android + JavaScript 的开发模式

准备工具:
Java JDK
android-studio IntelliJ 编辑器插件扩展而来
android 手机或 android 模拟器
数据线

代码分析

新建项目
配置项目
Android SDK
基础页面

项目目录介绍

项目目录
项目目录
项目目录
项目目录

桥接

涉及的知识点:
1、线性布局
2、WebView 组件应用
3、JSBridge 调用、传值

示例 主要代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tv_title" />

<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/btn1"/>
<WebView
android:id="@+id/wv"
android:layout_width="match_parent"
android:layout_height="match_parent"></WebView>
</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.os.Bundle;

import android.view.KeyEvent;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

private Button Btn1; // var btn1
private WebView WV;
private View.OnClickListener btnonClickHandler = new View.OnClickListener() {
@Override
public void onClick(View view) {
// 业务逻辑 可消失的提示框 Toast
Toast.makeText(MainActivity.this,"测试 android 的 Toast 功能",Toast.LENGTH_SHORT).show();
WV.loadUrl("javascript:getData('我是一个android传递过来的值')");
}
};

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

private void initView(){
// btn1 = document.getElementById("html")
// btn1.addEventLinstenner('click',function(){},false)

Btn1 = findViewById(R.id.btn1);
Btn1.setOnClickListener(btnonClickHandler);

/**
* WV.loadUrl()
* WebView.loadUrl('http://www.google.com') // 远程页面
* WebView.loadUrl('file:///android_asset/test.html') // 本地页面 —— 随着 App 打包
* WebView.loadUrl('content://com android htmlfileprovider/sdcard/test.html') // 手机本地的页面 —— sd卡中的页面
* WebView.loadData() // 加载一段 HTML 代码
*/

/*
* 初次加载显示无网络,需要到项目配置文件添加网络的权限
* <uses-permission android:name="android.permission.INTERNET" />
*/
WV = findViewById(R.id.wv);

// 默认的 WebView 是需要进行配置才能达到我们想要的一些浏览器的特性
WVSetting();

WVClientSetting();

// 加载远程页面
// WV.loadUrl("https://m.jd.com/");
// 加载本地页面
WV.loadUrl("file:///android_asset/index.html");

// 添加JS调用Android(Java)的方法接口
WV.addJavascriptInterface(new MJavascriptInterface(getApplicationContext()), "ToastFunc");
WV.addJavascriptInterface(new PhotoJavascriptInterface(getApplicationContext()), "PhotoFunc");
}

private void WVSetting() {
// 声明 WebSettings 子类
// getSettings() 返回一个WebSettings对象,用来控制WebView的属性设置

WebSettings webSettings = WV.getSettings();
/*
* 如果访问的页面中要与 JavaScript 交互,则 webview 必须设置支持 JavaScript
* 若加载的 html 里有 JavaScript 在执行动画等操作,会造成资源浪费 (CPU、电量)
* 在 onStop 和 onResume 里分别把 setJavaScriptEnadled() 给设置成 false 和 true 即可
* 设置自适应屏幕,两者合用
*/

webSettings.setJavaScriptEnabled(true);

// 将图片调整到适合 webview 的大小

webSettings.setUseWideViewPort(true);

// 缩放至屏幕大小
webSettings.setLoadWithOverviewMode(true);

// 支持缩放,默认为 true
webSettings.setSupportZoom(true);

// 设置内置的缩放控件。若为 false,则该 webview 不可缩放
webSettings.setBuiltInZoomControls(true);

// 隐藏原生的缩放控件
webSettings.setDisplayZoomControls(false);

// 关闭 webview 中缓存
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);

// 设置可以访问文件
webSettings.setAllowFileAccess(true);

// 支持通过 JavaScript 打开新窗口
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

// 支持自动加载图片
webSettings.setLoadsImagesAutomatically(true);

// 设置编码格式
webSettings.setDefaultTextEncodingName("utf-8");
}

private void WVClientSetting() {
//处理页面加载各个阶段
MWebViewClient mWebViewClient = new MWebViewClient(WV,getApplicationContext());
WV.setWebViewClient(mWebViewClient);
//提供网页加载过程中提供的数据内容
MWebChromeClient mWebChromeClient = new MWebChromeClient( getApplicationContext());
WV.setWebChromeClient(mWebChromeClient);
}

class MJavascriptInterface {
private Context context;

public MJavascriptInterface(Context context) {
this.context = context;
}

// andorid版本升级时必须加上@JavascriptInterface
@JavascriptInterface
public void showToast() { // 可以由前端调用 window.ToastFunc.showToast()
Toast.makeText(MainActivity.this, "js调起了android的Toast功能", Toast.LENGTH_SHORT).show();
}

@JavascriptInterface
public void showToastParams(String str) { // 可以由前端调用 window.ToastFunc.showToast()
Toast.makeText(MainActivity.this, "js调起了android的Toast功能" + str, Toast.LENGTH_SHORT).show();
}
}

class PhotoJavascriptInterface {
private Context context;

public PhotoJavascriptInterface(Context context) {
this.context = context;
}

// andorid版本升级时必须加上@JavascriptInterface
@JavascriptInterface
public void takePhoto() { // 拍照
Toast.makeText(MainActivity.this, "拍照", Toast.LENGTH_SHORT).show();
// 拍照流程
}

@JavascriptInterface
public void getPhoto() { // 相册选取
Toast.makeText(MainActivity.this, "相册选取", Toast.LENGTH_SHORT).show();
// 相册选取流程
}
}


//点击返回上一页面而不是退出浏览器
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && WV.canGoBack()) {
WV.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link href="https://cdn.bootcss.com/mui/3.7.1/css/mui.min.css" rel="stylesheet">
</head>
<body>
<button type="button" id="btn" class="mui-btn mui-btn-royal">js按钮,调用android的Toast功能</button>
<button type="button" id="takePhoto" class="mui-btn mui-btn-royal">拍照</button>
<button type="button" id="getPhoto" class="mui-btn mui-btn-royal">相册</button>
<div id="msg"></div>
</body>
<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
<script>
$('#btn').on('click', function () {
console.log('我是js按钮,想要调用android的Toast功能')
window.ToastFunc.showToast()
// js 可以调用android的功能
window.ToastFunc.showToastParams('是真的吗')
})
$('#takePhoto').on('click', function () {
window.PhotoFunc.takePhoto()
})
$('#getPhoto').on('click', function () {
window.PhotoFunc.getPhoto()
})

function getData (str) {
$('#msg').html(str)
}
/**
只需要按照项目需求编写也买你,假设你的一个按钮需要调用系统的功能(部分功能需要添加权限),
在你的按钮事件中调用由android工程师提供的相对应的对象和其方法即可,
同时前端也会定义一些方法,但是前端自己不调用,android会根据webview的loadUrl方法进行调用,
并且传参(根据需求看)

如果把这些对象封装起来(plus),结合特定的环境(hbuilder),那么前端人员也就可以自己做混合开发的项目了
*/
</script>
</html>

相关资料
2019 安卓混合开发视频精讲

相关代码

作者

Fallen-down

发布于

2020-03-06

更新于

2021-04-02

许可协议

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

评论

You forgot to set the shortname for Disqus. Please set it in _config.yml.
You need to set client_id and slot_id to show this AD unit. Please set it in _config.yml.