Enhancing the React Native Webview (Part 1) – Supporting File Uploads in iOS & Android
- February 6, 2018
React Native is a really popular mobile app development framework. However, when running a web application using the React Native Webview, I noticed that it lacked several essential features. To enhance the React Native Webview to support the missing essential features (as of version 0.52), I will be starting a series of blog posts that would ultimately help the React Native developers out there.
In part 1 of this series, we will be looking on how to add support for file uploads for both iOS & Android. This means enabling support for </input type=“file“> (Browse button) to upload a file by selecting from the gallery or by taking a photo using the camera.
Supporting File Uploads in iOS
To enable support for file uploads in iOS you just have to add the NSPhotoLibraryUsageDescription key and a description explaining why your app needs photo library access, into your info.plist file.
Supporting File Uploads in Android
To enable support for file uploads in Android, it’s not easy as for iOS. You will need to write native android code to provide the support.
First we need to create a native UI component which extends the React Native Webview UI component. For more details on creating native UI components please refer the official docs: https://facebook.github.io/react-native/docs/native-components-android.html
To begin create a folder named advancedwebview inside android -> app -> src -> main -> java -> com -> yourpackage (These names are used for this tutorial and you are free to name them however you like). Inside the folder you created create a java file named AdvancedWebView.java and add the following code.
The following permissions should be added to theto allow the app to access camera and the internal storage.
Starting from Android 6.0 (API level 23), we also need to request for permission at run time. The grantPermissions method in the above code is used to acquire the required permission during run time.
Now we need to register the above created View Manager to let android know that it exists. For that first we need to create a class which extends ReactPackage. Inside android -> app -> src -> main -> java -> com -> yourpackage ->advancedwebview create a file namedand add the following code to it.
View manager registrations happens inside the createViewManagers method. Still our main android application is not aware about our newly created package class. To let it know we need to add it to our application’s android -> app -> src -> main -> java -> com -> yourpackage ->file’s getPackages() method as shown below.
After writing the required native code we need to access it from the react native side. For that create a file named AdvancedWebview.android.js outside the android folder (With your other react native JS files) and add the following code to it. This code was taken from https://github.com/facebook/react-native/blob/master/Libraries/Components/WebView/WebView.android.js and was modified according to our need. Added enabledUploadAndroid proptype to it which is required to enable the native code which we discussed above.
The below line in the above code is used to retrieve the native UI component to the react native side. The first parameter of requireNativeComponent is the name of the UI component and it should match the name specified inside the getName() method in the AdvancedWebViewManager class which we discussed above.
We have now arrived to the final step which is to run the created AdvancedWebview UI component. You could run it by importing the AdvancedWebView component and adding it inside the render method of the class as you would do it with the WebView component provided by React Native. Additionally you will have to add the enabledUploadAndroid prop to enable the file upload functionality which we just created. An example code is shown below.
Please note that this AdvancedWebview will work only on Android for now and you will have to use the regular WebView component for iOS. In one of my later blog posts i will cover on how to extend its functionality to use it on iOS as well.