Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit a02b4ca

Browse files
committed
[[ Bug 23087 ]] Implement onShowFileChooser in android browser
This patch implements the `onShowFileChooser` callback in the android browser implementation to support picking files in web forms.
1 parent 8f1ab59 commit a02b4ca

File tree

2 files changed

+134
-6
lines changed

2 files changed

+134
-6
lines changed

docs/notes/bugfix-23087.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Support file input in Android browser forms

engine/src/java/com/runrev/android/libraries/LibBrowser.java

Lines changed: 133 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.runrev.android.libraries;
1818

19-
import com.runrev.android.Engine;
19+
import com.runrev.android.*;
2020
import com.runrev.android.nativecontrol.NativeControlModule;
2121

2222
import android.app.AlertDialog;
@@ -29,12 +29,17 @@
2929
import android.view.*;
3030
import android.webkit.*;
3131
import android.widget.*;
32+
import android.net.*;
33+
import android.os.*;;
34+
import android.media.*;
35+
import android.provider.*;
3236

3337
import java.lang.reflect.*;
3438
import java.net.*;
3539
import java.security.*;
3640
import java.util.*;
3741
import java.util.regex.*;
42+
import java.io.*;
3843

3944
import org.json.JSONArray;
4045
import org.json.JSONException;
@@ -236,8 +241,129 @@ public boolean onTouch(View v, MotionEvent event)
236241
return !m_allow_user_interaction;
237242
}
238243
});
239-
240-
m_chrome_client = new WebChromeClient() {
244+
245+
class MCWebChromeClient extends WebChromeClient implements LiveCodeActivity.OnActivityResultListener
246+
{
247+
private static final int WEBVIEW_INPUT_FILE_RESULT = 9999;
248+
private ValueCallback<Uri[]> m_browser_file_path_callback = null;
249+
private File m_temp_image_file = null;
250+
251+
public void onActivityResult (int p_request_code, int p_result_code, Intent p_data)
252+
{
253+
LiveCodeActivity t_activity = (LiveCodeActivity)getContext();
254+
t_activity.removeOnActivityResultListener(p_request_code);
255+
256+
switch (p_request_code)
257+
{
258+
case WEBVIEW_INPUT_FILE_RESULT:
259+
Uri[] t_uris = null;
260+
if (p_result_code == Activity.RESULT_OK)
261+
{
262+
if (p_data.getData() != null)
263+
{
264+
t_uris = WebChromeClient.FileChooserParams.parseResult(p_result_code, p_data);
265+
}
266+
else if (m_temp_image_file != null)
267+
{
268+
t_uris = new Uri[] {Uri.fromFile(m_temp_image_file)};
269+
}
270+
}
271+
272+
m_browser_file_path_callback.onReceiveValue(t_uris);
273+
m_browser_file_path_callback = null;
274+
275+
if (m_temp_image_file != null)
276+
{
277+
FileProvider.getProvider(getContext()).removePath(m_temp_image_file.getPath());
278+
m_temp_image_file = null;
279+
}
280+
default:
281+
break;
282+
}
283+
}
284+
285+
@Override
286+
public boolean onShowFileChooser(WebView p_webview, ValueCallback<Uri[]> p_file_path_callback, WebChromeClient.FileChooserParams p_file_chooser_params)
287+
{
288+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
289+
{
290+
try {
291+
LiveCodeActivity t_activity = (LiveCodeActivity)getContext();
292+
293+
Intent t_intent = p_file_chooser_params.createIntent();
294+
295+
List<Intent> t_extra_intents = new ArrayList<Intent>();
296+
297+
Intent t_gallery_intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
298+
t_gallery_intent.setType("image/*");
299+
t_extra_intents.add(t_gallery_intent);
300+
301+
boolean t_have_temp_file = false;
302+
try
303+
{
304+
// try external cache first
305+
m_temp_image_file = File.createTempFile("img", ".jpg", t_activity.getExternalCacheDir());
306+
m_temp_image_file.setWritable(true, false);
307+
t_have_temp_file = true;
308+
}
309+
catch (IOException e)
310+
{
311+
m_temp_image_file = null;
312+
t_have_temp_file = false;
313+
}
314+
315+
if (!t_have_temp_file)
316+
{
317+
try
318+
{
319+
// now try internal cache - should succeed but may not have enough space on the device for large image files
320+
m_temp_image_file = File.createTempFile("img", ".jpg", t_activity.getCacheDir());
321+
m_temp_image_file.setWritable(true, false);
322+
t_have_temp_file = true;
323+
}
324+
catch (IOException e)
325+
{
326+
m_temp_image_file = null;
327+
t_have_temp_file = false;
328+
}
329+
}
330+
331+
if (t_have_temp_file)
332+
{
333+
String t_path = m_temp_image_file.getPath();
334+
335+
Uri t_uri;
336+
t_uri = FileProvider.getProvider(getContext()).addPath(t_path, t_path, "image/jpeg", false, ParcelFileDescriptor.MODE_READ_WRITE);
337+
338+
Intent t_image_capture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
339+
340+
t_image_capture.putExtra(MediaStore.EXTRA_OUTPUT, t_uri);
341+
t_image_capture.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
342+
t_extra_intents.add(t_image_capture);
343+
}
344+
345+
Intent t_chooser_intent = Intent.createChooser(t_intent, "Select a file");;
346+
t_chooser_intent.putExtra(Intent.EXTRA_INITIAL_INTENTS, t_extra_intents.toArray(new Parcelable[] {}));
347+
348+
if (t_chooser_intent.resolveActivity(t_activity.getPackageManager()) == null)
349+
{
350+
return false;
351+
}
352+
353+
m_browser_file_path_callback = p_file_path_callback;
354+
t_activity.setOnActivityResultListener(this, WEBVIEW_INPUT_FILE_RESULT);
355+
t_activity.startActivityForResult(t_chooser_intent, WEBVIEW_INPUT_FILE_RESULT);
356+
357+
return true;
358+
}
359+
catch (Exception e)
360+
{
361+
362+
}
363+
}
364+
return false;
365+
}
366+
241367
@Override
242368
public void onShowCustomView(View view, CustomViewCallback callback)
243369
{
@@ -362,9 +488,10 @@ public void onProgressChanged(WebView p_view, int p_progress)
362488
doProgressChanged(p_view.getUrl(), p_progress);
363489
wakeEngineThread();
364490
}
365-
366-
};
367-
491+
}
492+
493+
m_chrome_client = new MCWebChromeClient();
494+
368495
setWebChromeClient(m_chrome_client);
369496
getSettings().setJavaScriptEnabled(true);
370497
getSettings().setAllowFileAccessFromFileURLs(true);

0 commit comments

Comments
 (0)