做了一个小的App Demo,利用Webpack 搭建Vue应用框架,vue组件通过js调用android 接口调用相机实现扫一扫功能,最后利用android studio 打包成apk. 整个过程不复杂,但搭建开发环境及fix bug 花了不少时间,记录下来做个备忘。
export default {
data: function(){
return {
}
},
mounted: function() {
},
created: function(){
window.androidScanCallBack = this.scanCallBack;
},
methods: {
scan: function() {
window.android.scan();
},
scanCallBack:function (qrcodeUrl) {
this.$nextTick(()=>{
this.$refs.qrcode.value=qrcodeUrl;
});
if(this.$utility.IsURL(qrcodeUrl)){
window.location.href=qrcodeUrl;
}
},
},
components:{
}
}
在组件生命周期创建时给window全局注册js方法 : window.androidScanCallBack = this.scanCallBack;
上面androidScanCallBack 供 Android webview 调用页面js使用:
在Android 的Activity中使用如下:
String jscript = "javascript:androidScanCallBack('www.baidu.com')";
webView.loadUrl(method);
Vue 组件中调用js : window.android.scan();
上面window对象的android对象由android原生创建,代码如下:
webView.addJavascriptInterface(new JavascriptCall(),"android");
JavasciptCall的定义如下:
private class JavascriptCall {
@JavascriptInterface //js接口声明
public void scan() {
}
}
Android 原生实现调用摄像头扫码的逻辑略,利用zxing的库来实现的资源很多,稍加研究就可以实现扫码的功能;
1:首先 npm run build 生成待打包的html资源:
2: 打开Android Studio 新建Android 工程,选择Empty Activity,
拷贝dist目录到Android 工程中,添加到assets文件夹
在MainActivity.java中创建WebView, 并加载本地资源:
webView.loadUrl("file:///android_asset/dist/index.html");
省略图标,权限等的配置。准备完毕:就可以Build 成apk了
完整的Android MaintActivity代码如下:
代码实现了zxing 的扫一扫功能:参考blog:https://www.jianshu.com/p/28c6aa7e1d24
public class MainActivity extends AppCompatActivity {
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
webView= findViewById(R.id.myWebView);
WebSettings ws= webView.getSettings();
ws.setJavaScriptEnabled(true);
ws.setLoadWithOverviewMode(true);
ws.setUseWideViewPort(true);
ws.setDefaultTextEncodingName("utf-8");
ws.setLoadsImagesAutomatically(true);
ws.setSupportZoom(false);
ws.setBuiltInZoomControls(false);
ws.setDomStorageEnabled(true);
ws.setAppCacheEnabled(true);
ws.setAllowFileAccess(true);
ws.setCacheMode(WebSettings.LOAD_NO_CACHE);
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.loadUrl("file:///android_asset/dist/index.html");
webView.addJavascriptInterface(new JavascriptCall(),"android");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode== KeyEvent.KEYCODE_BACK && webView.canGoBack()){
webView.goBack();
return true;
}
AlertDialog dialog=new AlertDialog.Builder(this).create();
dialog.setTitle("提示");
dialog.setMessage("确定退出吗?");
dialog.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK){
return true;
}
return true;
}
});
dialog.show();
return super.onKeyDown(keyCode,event);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 扫描二维码/条码回传
if (requestCode == REQUEST_CODE_SCAN && resultCode == RESULT_OK) {
if (data != null) {
String content = data.getStringExtra(Constant.CODED_CONTENT);
Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();
String method = "javascript:testResult('" + content + "')";
webView.loadUrl(method);
}
}
}
int REQUEST_CODE_SCAN=100;
private class JavascriptCall {
@JavascriptInterface //js接口
public void takePhoto() {
Intent intent = new Intent(MainActivity.this, CaptureActivity.class);
startActivityForResult(intent, REQUEST_CODE_SCAN);
}
}
}