解决React-Native的WebView不支持Android选择图片和拍照

解决React-Native的WebView不支持Android选择图片和拍照

目录

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

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

3.怎么重新封装一个Rn组件?

1.新建一个ActivityResultInterface 接口回调

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

 3.ReactWebViewManager 自定义添加配置

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

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

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


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

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

// For Android 4.1
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;
       }
   }

}

 ReactWebViewManager 中间代码有一个包名记的改一下

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> 

4.将写好的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()
     );
   }
......
 };
......
}

5.在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;

 

说明(重点):

1.个人使用的"react-native": "0.55.4"版本,重试过高版本的,不行,如果后面使用高版本不行,就用"react-native": "0.55.4"

2.遇到点击拍照没有反应,可能是没有权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.CAMERA"/>

 

其他方案:有时间可以试试其他方案这个博客

资料:https://www.jianshu.com/p/ceb0634c097c

希望React Native 后面能解决WebView的这个问题

下载地址:https://download.csdn.net/download/pcaxb/10638106

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
React Native的WebView是一个用于在应用程序中显示Web内容的组件。它是通过使用第三方库react-native-web-webview来实现的。您可以使用npm命令来安装这个库,例如: ``` $ npm install react-native-web-webview --save ``` 通过引入这个库,您可以在您的React Native应用程序中使用WebView组件来加载和显示Web页面。您可以使用属性如onLoad、onError、onMessage等来监听WebView的加载、错误和消息事件。例如,您可以通过onLoad来设置页面加载完成后的回调函数,通过onError来设置错误处理函数,通过onMessage来处理从Web页面发送的消息。您可以使用style属性来设置WebView的样式,source属性来指定要加载的Web页面的来源。 以下是一个示例代码,展示了如何使用WebView组件: ```jsx <WebView ref={(view) => (this.webView = view)} useWebKit={false} onLoad={() => { let data = { name: userInfo.usrName }; this.webView.postMessage(JSON.stringify(data)); }} onError={(event) => { console.log(`==webViewError:${JSON.stringify(event.nativeEvent)}`); }} onMessage={(event) => { this._onH5Message(event); }} automaticallyAdjustContentInsets={false} contentInset={{ top: 0, left: 0, bottom: -1, right: 0 }} onScroll={(event) => this._onScroll(event)} style={styles.webview} source={this.html ? { html: this.html } : { uri: this.url }} bounces={false} showsHorizontalScrollIndicator={false} showsVerticalScrollIndicator={false} /> ``` 请注意,这只是一个示例,您可以根据您的实际需求来调整和配置WebView组件。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [react-native-web-webview:React Native用于RN的WebView的Web实现](https://download.csdn.net/download/weixin_42165490/18797652)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [ReactNative进阶(十):WebView 应用详解](https://blog.csdn.net/sunhuaqiang1/article/details/116158130)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值