最近公司项目需要结合Android 加载H5 页面加快工作效率。前端页面采用目前比较流行的React编写,由于React 的特殊性,我们在Android 很难使用常规的
mWebView.evaluateJavascript("xxx()") 方式来找到React 的对象方法来调用。研究了一下React 的编译机制,如果webpack 打包的js生成bundle.js 这个js 中是一个很长的立即执行函数,这就导致我们根本无法去调用,之前写好的类和方法。
解决方法:
将ES6 编写的React 类的实例暴露给window 就可以了。
mport React from 'react';
import {Tabs, Badge,ImagePicker} from "antd-mobile";
import './my.css'
import {Link} from 'react-router-dom';
import Height from '../height'
import $ from 'jquery';
import plus from '../../images/plus.png'
import VConsole from 'vconsole'
window.updateValue = function(url) {
console.log(url);
if(window.callback != undefined) {
window.callback.updateValue(url);
}
};
window.setCallback = function(callback) {
window.callback = callback;
};
export default class MyFeedback extends React.Component {
state = {
files: [],
multiple: false,
value:"我们非常重视你的建议11"
};
onChange = (files, type, index) => {
console.log(files, type, index);
this.setState({
files,
});
};
onSegChange = (e) => {
const index = e.nativeEvent.selectedSegmentIndex;
this.setState({
multiple: index === 1,
});
};
onAddImageClick() {
console.log(navigator.userAgent);
//window.location.assign("?action=uploadimg");
if (window.andpicker != null) {
window.andpicker.test("hello");
}
}
componentWillMount() {
document.title = "反馈";
var vConsole = new VConsole();
window.setCallback(this);
}
updateValue(val) {
this.setState({
files: this.state.files.concat({
url: val,
id: '311',
}),
});
}
render() {
return (
<div style={{minHeight: 'calc(100vh - 43.5px)', backgroundColor: '#fff'}}>
<div>
<div style={{padding:'8px',background:'#ccc'}}>问题和建议</div>
<div style={{margin:'8px'}}><input style={{height:'200px',width:'-webkit-fill-available'}} value={this.state.value} /></div>
<div style={{padding:'8px',background:'#ccc'}}>上传图片</div>
<div>
<ImagePicker
files={this.state.files}
onChange={this.onChange}
onImageClick={(index, fs) => console.log(index, fs)}
onAddImageClick={this.onAddImageClick}
selectable={this.state.files.length < 7}
multiple={this.state.multiple}/>
</div>
<div style={{margin:'8px',background:"#f00",color:'#fff',height:'20px',textAlign:'center',padding:'10px'}}>提交</div>
</div>
<Height></Height>
</div>
)
}
}
window.setCallback(this); 就是重点,这样可以在Java 端调用window.updateValue();来实现和React js 的交互
Java 端代码:
package com.example.jerry.h5project;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.util.HashMap;
import java.util.Map;
public class FeedbackAct extends AppCompatActivity implements AndroidPickerJs.Callback{
private static final String TAG = FeedbackAct.class.getSimpleName();
private static final int CHOOSE_PICTURE = 1;
private WebView mWebView;
private AndroidPickerJs mJsInstance;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feedback);
initViews();
}
private void initViews() {
mJsInstance = new AndroidPickerJs();
mJsInstance.setCallback(this);
mWebView = findViewById(R.id.web_view);
mWebView.setWebViewClient(mWebViewClient);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webSettings.setSupportZoom(true);
mWebView.addJavascriptInterface(mJsInstance,"andpicker");
mWebView.loadUrl("http://10.0.0.24:3000/myfeedback");
}
@Override
public void selectPic() {
choosePictures();
}
private WebChromeClient mWebChromeClient = new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
}
};
private WebViewClient mWebViewClient = new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return super.shouldOverrideUrlLoading(view, request);
}
@Override
public void onPageFinished(WebView view, String url) {
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
Log.d(TAG,"error = " + error.toString());
super.onReceivedError(view, request, error);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
}
};
private void choosePictures() {
Intent intent = new Intent(
Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, CHOOSE_PICTURE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CHOOSE_PICTURE && resultCode == RESULT_OK) {
final Uri uri = data.getData();
Log.d(TAG,"evaluate js script ... uri = " + uri);
Bitmap bitmap = BitmapUtils.getBitmapFromUri(this, uri);
final String base64str = "data:image/png;base64," + Base64Utils.bitmapToBase64(bitmap);
Log.d(TAG,"base64 = " + base64str);
//final String base64 = "https://zos.alipayobjects.com/rmsportal/hqQWgTXdrlmVVYi.jpeg";
mWebView.post(new Runnable() {
@Override
public void run() {
mWebView.evaluateJavascript("window.updateValue('"+base64str+"')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
//此处为 js 返回的结果
}
});
}
});
}
}
}