做了一個小的App Demo,利用Webpack 搭建Vue應用框架,vue組件通過js調用android 接口調用相機實現掃一掃功能,最後利用android studio 打包成apk. 整個過程不復雜,但搭建開發環境及fix bug 花了不少時間,記錄下來做個備忘。
Vue組件調用Android 接口:
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的庫來實現的資源很多,稍加研究就可以實現掃碼的功能;
Android Studio打包Apk
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);
}
}
}