본문 바로가기

JAVA/ANDROID

[ 안드로이드 ] 안드로이드 Webview _ FileChooser

참고 URL : https://www.opengeeks.me/2015/08/filechooser-and-android-webview/


FileChooser and Android webview

Today, I want to share with you my solution on how to control a fileChooser HTML input type on Android’s WebView. Let’s start telling that from Android 5.0 to upper, there are a public method defined onShowFileChooser but there is no default methods for lower Android versions. The code bellow handle click events on file chooser button and suggest file choose from android memory, take a photo from cam or select an image from memory. Here’s the full code:


오늘, 안드로이드의 WebView에서 fileChooser HTML 입력 형식을 제어하는 ​​방법에 대한 해결책을 함께 나누고 싶습니다. Android 5.0에서 위쪽으로, ShowFileChooser에 정의 된 public 메소드  가 있지만 Android 버전이 낮은 기본 메소드는 없다는 것을 알기 시작 합니다. 코드 선택기는 파일 선택기 버튼에서 이벤트를 클릭하고 안드로이드 메모리에서 파일을 선택하거나, 캠에서 사진을 찍거나, 메모리에서 이미지를 선택하도록 제안합니다. 

전체 코드는 다음과 같습니다.

 * 버전 별로 onShowFileChooser 혹은 openFileChooser (5.0 버전 밑으로 ) 사용할 수 있다. 

  1. package it.floryn90.webapp;
  2. import android.app.Activity;
  3. import android.app.ProgressDialog;
  4. import android.content.Intent;
  5. import android.graphics.Bitmap;
  6. import android.net.Uri;
  7. import android.os.Build;
  8. import android.os.Bundle;
  9. import android.os.Environment;
  10. import android.os.Parcelable;
  11. import android.provider.MediaStore;
  12. import android.support.v7.app.ActionBarActivity;
  13. import android.util.Log;
  14. import android.view.KeyEvent;
  15. import android.view.View;
  16. import android.webkit.ValueCallback;
  17. import android.webkit.WebChromeClient;
  18. import android.webkit.WebSettings;
  19. import android.webkit.WebView;
  20. import android.webkit.WebViewClient;
  21. import android.widget.Toast;
  22. import java.io.File;
  23. import java.io.IOException;
  24. import java.text.SimpleDateFormat;
  25. import java.util.Date;
  26. public class MainActivity extends ActionBarActivity {
  27. private static final int INPUT_FILE_REQUEST_CODE = 1;
  28. private static final int FILECHOOSER_RESULTCODE = 1;
  29. private static final String TAG = MainActivity.class.getSimpleName();
  30. private WebView webView;
  31. private WebSettings webSettings;
  32. private ValueCallback<Uri> mUploadMessage;
  33. private Uri mCapturedImageURI = null;
  34. private ValueCallback<Uri[]> mFilePathCallback;
  35. private String mCameraPhotoPath;
  36. @Override
  37. public void onActivityResult(int requestCode, int resultCode, Intent data) {
  38. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  39. if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
  40. super.onActivityResult(requestCode, resultCode, data);
  41. return;
  42. }
  43. Uri[] results = null;
  44. // Check that the response is a good one
  45. if (resultCode == Activity.RESULT_OK) {
  46. if (data == null) {
  47. // If there is not data, then we may have taken a photo
  48. if (mCameraPhotoPath != null) {
  49. results = new Uri[]{Uri.parse(mCameraPhotoPath)};
  50. }
  51. } else {
  52. String dataString = data.getDataString();
  53. if (dataString != null) {
  54. results = new Uri[]{Uri.parse(dataString)};
  55. }
  56. }
  57. }
  58. mFilePathCallback.onReceiveValue(results);
  59. mFilePathCallback = null;
  60. } else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
  61. if (requestCode != FILECHOOSER_RESULTCODE || mUploadMessage == null) {
  62. super.onActivityResult(requestCode, resultCode, data);
  63. return;
  64. }
  65. if (requestCode == FILECHOOSER_RESULTCODE) {
  66. if (null == this.mUploadMessage) {
  67. return;
  68. }
  69. Uri result = null;
  70. try {
  71. if (resultCode != RESULT_OK) {
  72. result = null;
  73. } else {
  74. // retrieve from the private variable if the intent is null
  75. result = data == null ? mCapturedImageURI : data.getData();
  76. }
  77. } catch (Exception e) {
  78. Toast.makeText(getApplicationContext(), "activity :" + e,
  79. Toast.LENGTH_LONG).show();
  80. }
  81. mUploadMessage.onReceiveValue(result);
  82. mUploadMessage = null;
  83. }
  84. }
  85. return;
  86. }
  87. @Override
  88. protected void onCreate(Bundle savedInstanceState) {
  89. super.onCreate(savedInstanceState);
  90. setContentView(R.layout.activity_main);
  91. webView = (WebView) findViewById(R.id.webview);
  92. webSettings = webView.getSettings();
  93. webSettings.setJavaScriptEnabled(true);
  94. webSettings.setLoadWithOverviewMode(true);
  95. webSettings.setAllowFileAccess(true);
  96. webView.setWebViewClient(new Client());
  97. webView.setWebChromeClient(new ChromeClient());
  98. if (Build.VERSION.SDK_INT >= 19) {
  99. webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
  100. }
  101. else if(Build.VERSION.SDK_INT >=11 && Build.VERSION.SDK_INT < 19) {
  102. webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
  103. }
  104. webView.loadUrl("http://example.com"); //change with your website
  105. }
  106. private File createImageFile() throws IOException {
  107. // Create an image file name
  108. String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
  109. String imageFileName = "JPEG_" + timeStamp + "_";
  110. File storageDir = Environment.getExternalStoragePublicDirectory(
  111. Environment.DIRECTORY_PICTURES);
  112. File imageFile = File.createTempFile(
  113. imageFileName, /* prefix */
  114. ".jpg", /* suffix */
  115. storageDir /* directory */
  116. );
  117. return imageFile;
  118. }
  119. public class ChromeClient extends WebChromeClient {
  120. // For Android 5.0
  121. public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) {
  122. // Double check that we don't have any existing callbacks
  123. if (mFilePathCallback != null) {
  124. mFilePathCallback.onReceiveValue(null);
  125. }
  126. mFilePathCallback = filePath;
  127. Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  128. if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
  129. // Create the File where the photo should go
  130. File photoFile = null;
  131. try {
  132. photoFile = createImageFile();
  133. takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
  134. } catch (IOException ex) {
  135. // Error occurred while creating the File
  136. Log.e(TAG, "Unable to create Image File", ex);
  137. }
  138. // Continue only if the File was successfully created
  139. if (photoFile != null) {
  140. mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
  141. takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
  142. Uri.fromFile(photoFile));
  143. } else {
  144. takePictureIntent = null;
  145. }
  146. }
  147. Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
  148. contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
  149. contentSelectionIntent.setType("image/*");
  150. Intent[] intentArray;
  151. if (takePictureIntent != null) {
  152. intentArray = new Intent[]{takePictureIntent};
  153. } else {
  154. intentArray = new Intent[0];
  155. }
  156. Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
  157. chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
  158. chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
  159. chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
  160. startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
  161. return true;
  162. }
  163. // openFileChooser for Android 3.0+
  164. public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
  165. mUploadMessage = uploadMsg;
  166. // Create AndroidExampleFolder at sdcard
  167. // Create AndroidExampleFolder at sdcard
  168. File imageStorageDir = new File(
  169. Environment.getExternalStoragePublicDirectory(
  170. Environment.DIRECTORY_PICTURES)
  171. , "AndroidExampleFolder");
  172. if (!imageStorageDir.exists()) {
  173. // Create AndroidExampleFolder at sdcard
  174. imageStorageDir.mkdirs();
  175. }
  176. // Create camera captured image file path and name
  177. File file = new File(
  178. imageStorageDir + File.separator + "IMG_"
  179. + String.valueOf(System.currentTimeMillis())
  180. + ".jpg");
  181. mCapturedImageURI = Uri.fromFile(file);
  182. // Camera capture image intent
  183. final Intent captureIntent = new Intent(
  184. android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
  185. captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
  186. Intent i = new Intent(Intent.ACTION_GET_CONTENT);
  187. i.addCategory(Intent.CATEGORY_OPENABLE);
  188. i.setType("image/*");
  189. // Create file chooser intent
  190. Intent chooserIntent = Intent.createChooser(i, "Image Chooser");
  191. // Set camera intent to file chooser
  192. chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS
  193. , new Parcelable[] { captureIntent });
  194. // On select image call onActivityResult method of activity
  195. startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
  196. }
  197. // openFileChooser for Android < 3.0
  198. public void openFileChooser(ValueCallback<Uri> uploadMsg) {
  199. openFileChooser(uploadMsg, "");
  200. }
  201. //openFileChooser for other Android versions
  202. public void openFileChooser(ValueCallback<Uri> uploadMsg,
  203. String acceptType,
  204. String capture) {
  205. openFileChooser(uploadMsg, acceptType);
  206. }
  207. }
  208. public boolean onKeyDown(int keyCode, KeyEvent event) {
  209. // Check if the key event was the Back button and if there's history
  210. if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
  211. webView.goBack();
  212. return true;
  213. }
  214. // If it wasn't the Back key or there's no web page history, bubble up to the default
  215. // system behavior (probably exit the activity)
  216. return super.onKeyDown(keyCode, event);
  217. }
  218. public class Client extends WebViewClient {
  219. ProgressDialog progressDialog;
  220. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  221. // If url contains mailto link then open Mail Intent
  222. if (url.contains("mailto:")) {
  223. // Could be cleverer and use a regex
  224. //Open links in new browser
  225. view.getContext().startActivity(
  226. new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
  227. // Here we can open new activity
  228. return true;
  229. }else {
  230. // Stay within this webview and load url
  231. view.loadUrl(url);
  232. return true;
  233. }
  234. }
  235. //Show loader on url load
  236. public void onPageStarted(WebView view, String url, Bitmap favicon) {
  237. // Then show progress Dialog
  238. // in standard case YourActivity.this
  239. if (progressDialog == null) {
  240. progressDialog = new ProgressDialog(MainActivity.this);
  241. progressDialog.setMessage("Loading...");
  242. progressDialog.show();
  243. }
  244. }
  245. // Called when all page resources loaded
  246. public void onPageFinished(WebView view, String url) {
  247. try {
  248. // Close progressDialog
  249. if (progressDialog.isShowing()) {
  250. progressDialog.dismiss();
  251. progressDialog = null;
  252. }
  253. } catch (Exception exception) {
  254. exception.printStackTrace();
  255. }
  256. }
  257. }
  258. }