解决react-native 的 webview 组件不支持android客户端上传图片文件问题

上图说明

1.为什么Rn的android端webview不支持选择图片?

    android原生的webview,本身就需要配置一个方法来配合上传图片,RN封装的webView没有配置这个方法

public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { 
if (mUploadMessage != null) 
{ 
mUploadMessage.onReceiveValue(null); 
} 
mUploadMessage = uploadMsg; showPopSelectPic();
}
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { 
if (mUploadMessage != null) {
 mUploadMessage.onReceiveValue(null); 
} 
mUploadMessage = filePathCallback; 
showPopSelectPic(); 
return true; 
}

2.如何给RN的webview配置上这个方法?

在js代码中暂时没办法处理,那只好改原生的方法,原生的webview封装在react native 包里,没办法改,只好重新封装一个webview.

3.怎么重新封装一个Rn组件?
https://reactnative.cn/docs/0.45/native-component-android.html#content

首先把/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/webview中的ReactWebViewManager的复制到自己的src的java包目录里,然后根据自己的需求进行更改,比如现在的需求事添加选择图片的配置

1.新建一个ActivityResultInterface 接口回调

interface ActivityResultInterface {
   void callback(int requestCode, int resultCode, Intent data);
}

2.PickerActivityEventListener onActivityResult回调和自定义回调链接

 

public class PickerActivityEventListener extends BaseActivityEventListener { 
private ActivityResultInterface mCallback;
public PickerActivityEventListener(ReactApplicationContext reactContext, ActivityResultInterface callback) {
 reactContext.addActivityEventListener(this); mCallback = callback; 
} 
// < RN 0.33.0 
public void onActivityResult(int requestCode, int resultCode, Intent data) { mCallback.callback(requestCode, resultCode, data);
 } 
// >= RN 0.33.0 public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
 mCallback.callback(requestCode, resultCode, data);
 } 
}

3.ReactWebViewManager 自定义添加配置

public class ReactWebViewManager extends SimpleViewManager<WebView> implements ActivityResultInterface { //一些初始化变量 private ReactApplicationContext reactApplicationContext; private ValueCallback mUploadMessage; private Uri imageUri; private static final int TAKE_PHOTO = 10001; private static final int CHOOSE_PHOTO = 10002; protected static final String REACT_CLASS = "RCTWebView2"; ...... //修改构造方法 public ReactWebViewManager(ReactApplicationContext reactApplicationContext) { this.reactApplicationContext = reactApplicationContext; new PickerActivityEventListener(reactApplicationContext, this); mWebViewConfig = new WebViewConfig() { public void configWebView(WebView webView) { } }; } ...... protected WebView createViewInstance(final ThemedReactContext reactContext) { ReactWebView webView = createReactWebViewInstance(reactContext); webView.setWebChromeClient(new WebChromeClient() { ...... // For Android 4.1 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { if (mUploadMessage != null) { mUploadMessage.onReceiveValue(null); } mUploadMessage = uploadMsg; showPopSelectPic(reactContext); } public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { if (mUploadMessage != null) { mUploadMessage.onReceiveValue(null); } mUploadMessage = filePathCallback; showPopSelectPic(reactContext); return true; } }); ...... } private void showPopSelectPic(final ThemedReactContext Context) { String[] items = new String[]{"相机", "相册"}; AlertDialog.Builder builder = new AlertDialog.Builder(Context); builder.setTitle("提示") .setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); if (which == 0) { //openCamera File outputImage = new File(Context.getExternalCacheDir(), "output_image.jpg"); try { if (outputImage.exists()) { outputImage.delete(); } outputImage.createNewFile(); } catch (IOException e) { e.printStackTrace(); } if (Build.VERSION.SDK_INT < 24) { imageUri = Uri.fromFile(outputImage); } else { imageUri = FileProvider.getUriForFile(Context, "com.rnpro.fileprovider", outputImage); } // 启动相机程序 if (ContextCompat.checkSelfPermission(Context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { //ActivityCompat.requestPermissions(Context, new String[]{Manifest.permission.CAMERA}, 2); } else { openCamera(); } } else if (which == 1) { //openAlbum if (ContextCompat.checkSelfPermission(Context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //ActivityCompat.requestPermissions(Context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } else { openAlbum(); } } } }) .setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { if (mUploadMessage != null) { mUploadMessage.onReceiveValue(null); mUploadMessage = null; } } }); builder.create().show(); } void openCamera() { Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); Activity currentActivity = reactApplicationContext.getCurrentActivity(); currentActivity.startActivityForResult(intent, TAKE_PHOTO); } void openAlbum() { Intent intent = new Intent("android.intent.action.GET_CONTENT"); intent.setType("image/*"); Activity currentActivity = reactApplicationContext.getCurrentActivity(); currentActivity.startActivityForResult(intent, CHOOSE_PHOTO); // 打开相册 } @Override public void callback(int requestCode, int resultCode, Intent data) { switch (requestCode) { case TAKE_PHOTO: if (resultCode == RESULT_OK) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mUploadMessage.onReceiveValue(new Uri[]{imageUri}); } else { mUploadMessage.onReceiveValue(imageUri); } mUploadMessage = null; } else { mUploadMessage.onReceiveValue(null); mUploadMessage = null; return; } break; case CHOOSE_PHOTO: if (resultCode == RESULT_OK) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mUploadMessage.onReceiveValue(new Uri[]{data.getData()}); } else { mUploadMessage.onReceiveValue(data.getData()); } mUploadMessage = null; } else { mUploadMessage.onReceiveValue(null); mUploadMessage = null; return; } break; default: break; } } }

4.注意 需要注册FileProvider和设置xml path

 //清单文件中注册 <provider
           android:name="android.support.v4.content.FileProvider"
           android:authorities="com.rnpro.fileprovider"
           android:exported="false"
           android:grantUriPermissions="true"> <meta-data
               android:name="android.support.FILE_PROVIDER_PATHS"
               android:resource="@xml/file_paths" /> </provider> //res资源文件中新建xml文件夹新建文件file_paths.xml <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="my_images" path="" /> </paths>

5.将写好的ReactWebViewManager写入到ReactPackage中,将ReactPackage写入Application中

public class WebViewReactPackage implements ReactPackage {
public List<Class<? extends JavaScriptModule>> createJSModules() {
       return Collections.emptyList();
   }

@Override 
public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) { 
return Arrays.<ViewManager>asList( new ReactWebViewManager(reactApplicationContext) 
); 
} 

@Override
 public List<NativeModule> createNativeModules( ReactApplicationContext reactApplicationContext) { 
return Collections.emptyList(); 
 }
}




public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
 @Override
   protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
     new MainReactPackage(),
     new WebViewReactPackage()
);
}
};
}

6.在js文件中,把/node_modules/react-native/Libraries/Components/WebView中的webview.android.js,复制到自己的js文件夹中,做一定的修改

webview.ios.js   

import { WebView } from 'react-native';
export default WebView;

webview.android.js

var RCT_WEBVIEW_REF = 'webview2';
 ......
 class WebView2 extends React.Component { 
...... 
var
RCTWebView = requireNativeComponent('RCTWebView2', WebView2, WebView2.extraNativeComponentConfig);
//RCTWebView2与ReactWebViewManager的REACT_CLASS对应 
//WebView2与上面的WebView2对应
 module.exports = WebView2;

资源下载地址

https://download.csdn.net/download/xiaozhuang__/10811136

原文:https://blog.csdn.net/caoyangyang123/article/details/79669374 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值