Skip to content

Commit

Permalink
Merge pull request #77 from gree/experimental/android_input_type_file
Browse files Browse the repository at this point in the history
[Experimental] WebChromeClient for <input type="file">
  • Loading branch information
KojiNakamaru committed Apr 12, 2020
2 parents f7a59cf + 21c39ad commit a1a2a89
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 3 deletions.
12 changes: 12 additions & 0 deletions plugins/Android/project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "ant.properties", and override values to adapt the script to your
# project structure.
android.library=true

# Project target.
target=android-23
162 changes: 160 additions & 2 deletions plugins/Android/src/net/gree/unitywebview/CWebViewPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
package net.gree.unitywebview;

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
Expand All @@ -31,6 +32,9 @@
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
Expand All @@ -49,12 +53,16 @@
import android.webkit.CookieSyncManager;
import android.widget.FrameLayout;
import android.webkit.PermissionRequest;
import android.webkit.ValueCallback;
// import android.support.v4.app.ActivityCompat;
// import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
Expand Down Expand Up @@ -89,7 +97,7 @@ public void call(final String method, final String message) {
}
}

public class CWebViewPlugin {
public class CWebViewPlugin extends Fragment {
private static FrameLayout layout = null;
private WebView mWebView;
private OnGlobalLayoutListener mGlobalLayoutListener;
Expand All @@ -103,7 +111,69 @@ public class CWebViewPlugin {
private Pattern mAllowRegex;
private Pattern mDenyRegex;

private static final int INPUT_FILE_REQUEST_CODE = 1;
private ValueCallback<Uri> mUploadMessage;
private ValueCallback<Uri[]> mFilePathCallback;
private String mCameraPhotoPath;

public CWebViewPlugin() {
final Activity a = UnityPlayer.currentActivity;
final CWebViewPlugin self = this;
a.runOnUiThread(new Runnable() {public void run() {
a
.getFragmentManager()
.beginTransaction()
.add(0, self, "CWebViewPlugin")
.commit();
}});
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != INPUT_FILE_REQUEST_CODE) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mFilePathCallback == null) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
Uri[] results = null;
// Check that the response is a good one
if (resultCode == Activity.RESULT_OK) {
if (data == null) {
if (mCameraPhotoPath != null) {
results = new Uri[] { Uri.parse(mCameraPhotoPath) };
}
} else {
String dataString = data.getDataString();
// cf. https://www.petitmonte.com/java/android_webview_camera.html
if (dataString == null) {
if (mCameraPhotoPath != null) {
results = new Uri[] { Uri.parse(mCameraPhotoPath) };
}
} else {
results = new Uri[] { Uri.parse(dataString) };
}
}
}
mFilePathCallback.onReceiveValue(results);
mFilePathCallback = null;
} else {
if (mUploadMessage == null) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
Uri result = null;
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
result = data.getData();
}
}
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}

public static boolean IsWebViewAvailable() {
Expand Down Expand Up @@ -245,6 +315,93 @@ public boolean onJsPrompt(WebView view, String url, String message, String defau
public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
callback.invoke(origin, true, false);
}

// For Android < 3.0 (won't work because we cannot utilize FragmentActivity)
// public void openFileChooser(ValueCallback<Uri> uploadFile) {
// openFileChooser(uploadFile, "");
// }

// For 3.0 <= Android < 4.1
public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType) {
openFileChooser(uploadFile, acceptType, "");
}

// For 4.1 <= Android < 5.0
public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture) {
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(null);
}
mUploadMessage = uploadFile;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, INPUT_FILE_REQUEST_CODE);
}

// For Android 5.0+
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
// cf. https://github.com/googlearchive/chromium-webview-samples/blob/master/input-file-example/app/src/main/java/inputfilesample/android/chrome/google/com/inputfilesample/MainFragment.java
if (mFilePathCallback != null) {
mFilePathCallback.onReceiveValue(null);
}
mFilePathCallback = filePathCallback;

mCameraPhotoPath = null;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
} catch (IOException ex) {
// Error occurred while creating the File
Log.e("CWebViewPlugin", "Unable to create Image File", ex);
}
// Continue only if the File was successfully created
if (photoFile != null) {
mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}


Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("*/*");

Intent[] intentArray;
if(takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}

Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
// chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);

startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);

return true;
}

private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File imageFile = File.createTempFile(imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
return imageFile;
}
});

mWebViewPlugin = new CWebViewPluginInterface(self, gameObject);
Expand Down Expand Up @@ -328,6 +485,7 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) {
}
if (url.startsWith("http://") || url.startsWith("https://")
|| url.startsWith("file://") || url.startsWith("javascript:")) {
mWebViewPlugin.call("CallOnStarted", url);
// Let webview handle the URL
return false;
} else if (url.startsWith("unity:")) {
Expand Down
3 changes: 2 additions & 1 deletion sample/Assets/StreamingAssets/sample.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ <h1>Hello Unity WebView!</h1>
<p><a href="javascript:void(0)" onclick="Unity.call('anchor');">[Send Message!]</a></p>
<form method="get" action="form">
<input id="input1" type="text" value="hoge" name="msg"/>
<input type="submit" value="Send Message!" onclick="Unity.call('form?msg=' + document.getElementById('input1').value); return false;"/>
<input type="submit" value="Send Message!" onclick="Unity.call('form?msg=' + document.getElementById('input1').value); return false;"/><br/>
<input type="file" name="datafile"/>
</form>
</body>
</html>

0 comments on commit a1a2a89

Please sign in to comment.