Recently the company projects require a combination of Android H5 page load speed up productivity. The front page using the more popular writing React, due to the special nature of React, it is difficult to use conventional in the Android
mWebView.evaluateJavascript ( "xxx ()") to find a way to call the object methods React. Study a little compilation mechanism React if webpack packed js js generated bundle.js this is a very long immediately execute the function, which can not lead us to call, classes and methods previously written.
Solution:
React instance of the class to write ES6 exposed to the window on it.
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); that is the focus, so you can call window.updateValue in Java end (); to achieve interaction and React js
Java-side code:
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 返回的结果
}
});
}
});
}
}
}