Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Experimental] WebChromeClient for <input type="file"> #77

Merged
merged 42 commits into from
Apr 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
8aa12b9
implemented WebChromeClient for '<input type="file">'.
KojiNakamaru May 31, 2016
c784a4b
adjusted build settings.
KojiNakamaru May 31, 2016
2f92ec2
modified sample.html to add '<input type="file">'.
KojiNakamaru May 31, 2016
4532900
updated binaries.
KojiNakamaru Jun 6, 2016
5b9e4e6
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Mar 8, 2018
7faf62d
added <input type="file"/> in sample.html.
KojiNakamaru Mar 8, 2018
0640ba5
updated binaries.
KojiNakamaru Mar 8, 2018
1228353
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Oct 16, 2018
b51d0ee
removed redundant log outputs.
KojiNakamaru Oct 16, 2018
e23e9b2
updated binaries.
KojiNakamaru Oct 16, 2018
f4c8057
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Dec 11, 2018
650c6a8
updated binaries.
KojiNakamaru Dec 11, 2018
3a3c7eb
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Dec 12, 2018
1e128de
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Dec 12, 2018
5dfff85
updated CWebViewPlugin.java to support camera input (works only for L…
KojiNakamaru Dec 12, 2018
d873ecb
updated binaries.
KojiNakamaru Dec 12, 2018
1985400
modified to grant camera access in Android WebView.
KojiNakamaru Sep 27, 2018
a91bad3
updated binaries.
KojiNakamaru Dec 12, 2018
59fd857
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Mar 17, 2019
c57c71e
updated binaries.
KojiNakamaru Mar 17, 2019
bdbf2bf
modified setType argument image/* -> */*.
KojiNakamaru Mar 24, 2019
7f38afe
updated binaries.
KojiNakamaru Mar 24, 2019
a671e29
fixed to remove Intent.EXTRA_TITLE.
KojiNakamaru Mar 29, 2019
8a22986
updated binaries.
KojiNakamaru Mar 29, 2019
658072b
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Apr 10, 2019
b6efa15
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Apr 10, 2019
8454209
updated binaries.
KojiNakamaru Apr 10, 2019
ae1a373
added CallOnStarted in shouldOverrideUrlLoading.
KojiNakamaru Jun 14, 2019
b463c98
updated binaries.
KojiNakamaru Jun 14, 2019
d98bb9a
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Jun 23, 2019
b3f97ee
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Jun 23, 2019
f32b560
updated binaries.
KojiNakamaru Jun 23, 2019
3fbe684
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Jun 27, 2019
147b102
updated binaries.
KojiNakamaru Jun 27, 2019
762875b
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Aug 29, 2019
2586417
updated binaries.
KojiNakamaru Aug 29, 2019
b73176e
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Sep 5, 2019
f9c8da2
updated binaries.
KojiNakamaru Sep 5, 2019
b6fa5c0
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Sep 10, 2019
292bb11
updated binaries.
KojiNakamaru Sep 10, 2019
8a1cdd9
Merge branch 'master' into experimental/android_input_type_file
KojiNakamaru Apr 12, 2020
21c39ad
adjusted sample.html.
KojiNakamaru Apr 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>