Android over kitkat doesn’t work WebChromeClient openFileChoose
- Input type file click event call android method that start file select (ex : gallery)
- Get Selected file path
- Upload file to server return file path that uploaded server
- Submit Form with File Upload Sucess message (ex : server uploaded path)
Call Android Method openFileChoose JavascriptInterface
JavascriptInterface.java
public class JavaScriptInterface { private final static String TAG = "JavaScriptInterface"; private Handler mHandler; @JavascriptInterface public void openFileChoose() { Logger.debug(this, "openFileChoose"); Message msg = new Message(); msg.what = HandlerOwner.MSG_FILE_CHOOSE; mHandler.sendMessage(msg); } @JavascriptInterface public void uploadFileCall() { Logger.debug(this, "uploadFileCall"); Message msg = new Message(); msg.what = HandlerOwner.MSG_UPLOAD_FILE_CALL; mHandler.sendMessage(msg); } }
Receive JavascriptInterface Message on Activity
WebActivity.java
@EActivity(R.layout.activity_web) public class WebActivity extends BaseActivity implements View.OnClickListener, HandlerOwner, TaskObserver{ @ViewById(R.id.webView) WebView webView; File uploadFile; private JavaScriptInterface jsInterface; private Handler mHandler; private String title, webViewUrl; private WebChromeClient webChromeClient; private WebClient webClient; @AfterViews void initView() { webClient = new WebClient(this); webView.setWebViewClient(webClient); webChromeClient = new WebChromeClient(this); webView.setWebChromeClient(webChromeClient); WebSettings set = webView.getSettings(); set.setJavaScriptEnabled(true); set.setBuiltInZoomControls(true); set.setDomStorageEnabled(true); Intent intent = getIntent(); title = intent.getStringExtra("title"); webViewUrl = intent.getStringExtra("url"); if(!webViewUrl.equals("")) { webView.loadUrl(webViewUrl); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_web); Logger.debug(this, ON_CREATE_START); Logger.debug(this, ON_CREATE_END); } @Override protected void onResume() { super.onResume(); Logger.debug(this, ON_RESUME_START); if(mHandler == null) { mHandler = new Handler(this); } jsInterface = new JavaScriptInterface(mHandler); webView.addJavascriptInterface(jsInterface, "Android"); Logger.debug(this, ON_RESUME_END); } @Override protected void onPause() { super.onPause(); Logger.debug(this, ON_PAUSE_START); Logger.debug(this, ON_PAUSE_END); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { Logger.debug(this, "keyCode : "+keyCode); switch (keyCode) { case KeyEvent.KEYCODE_BACK: if(webView.canGoBack()) { webView.goBack(); return true; } } return super.onKeyDown(keyCode, event); } @Override public void onMessage(Message message) { Logger.debug(this, ON_MESSAGE_START); Logger.debug(this, "message.what : "+ message.what); switch (message.what) { case MSG_FILE_CHOOSE: Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); startActivityForResult(Intent.createChooser(i, "File Chooser"), WebChromeClient.FILECHOOSER_RESULTCODE); break; case MSG_UPLOAD_FILE_CALL: FileUploadAsyncTask fileUploadAsyncTask = new FileUploadAsyncTask(this, null); fileUploadAsyncTask.execute(uploadFile.getAbsolutePath()); break; } Logger.debug(this, ON_MESSAGE_END); } //Select File onActivityResult getFilePath @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { // super.onActivityResult(requestCode, resultCode, data); if(requestCode== WebChromeClient.FILECHOOSER_RESULTCODE) { //if (null == webChromeClient.getmUploadMessage()) return; if(resultCode == RESULT_OK) { Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData(); Logger.debug(this, "image Uri : " +result.toString()); Logger.debug(this, "file name : " +uriToFile(result).getName()); webView.loadUrl("javascript:getFileName('"+uriToFile(result).getName()+"')"); uploadFile = uriToFile(result); } } } @TargetApi(19) private File uriToFile ( Uri uri ) { String filePath = ""; if ( uri.getPath().contains(":") ) { String wholeID = DocumentsContract.getDocumentId(uri); // Split at colon, use second item in the array String id = wholeID.split(":")[1]; String[] column = { MediaStore.Images.Media.DATA }; // where id is equal to String sel = MediaStore.Images.Media._ID + "=?"; Cursor cursor = this.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null); int columnIndex = cursor.getColumnIndex(column[0]); if (cursor.moveToFirst()) { filePath = cursor.getString(columnIndex); } cursor.close(); } else { String id = uri.getLastPathSegment(); final String[] imageColumns = {MediaStore.Images.Media.DATA }; final String imageOrderBy = null; String selectedImagePath = "path"; String scheme = uri.getScheme(); if ( scheme.equalsIgnoreCase("content") ) { Cursor imageCursor = this.getContentResolver().query(uri, imageColumns, null, null, null); if (imageCursor.moveToFirst()) { filePath = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA)); } } else { filePath = uri.getPath(); } } File file = new File( filePath ); return file; } @Override public void update(Class cls, Object returnObj) { Logger.debug(this, TASK_OBSERVER_UPDATE_START); Logger.debug(this, cls.getSimpleName()); if(cls.equals(FileUploadAsyncTask.class)) { FileUploadRes uploadRes = (FileUploadRes)returnObj; if(uploadRes != null) { String atchFilePth = uploadRes.getAtchFilePth(); String atchFileMg = uploadRes.getAtchFileMg(); Logger.debug(this, "atchFilePth : "+ atchFilePth+ " / atchFileMg : "+atchFileMg); // Receive AsynTaskResult Ok webView.loadUrl("javascript:getUploadFilePath('"+atchFilePth+"', '"+atchFileMg+"')"); } } Logger.debug(this, TASK_OBSERVER_UPDATE_END); } public class WebClient extends WebViewClient { Context context; public WebClient(Context context) { this.context = context; } public boolean shouldOverrideUrlLoading(WebView view, String url) { Logger.debug(WebActivity.this, "shouldOverrideUrlLoading : "+ url); view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); Logger.debug(this, "onPageFinished : "+url); } } }
Get File Upload to Server
FileUploadAsyncTask.java
public class FileUploadAsyncTask extends BaseAsyncTask implements UrlConstant { private static AsyncTaskResult asyncTaskResult = null; public FileUploadAsyncTask(TaskObserver caller, String progressMsg) { super(caller, progressMsg); } @Override protected AsyncTaskResult doInBackground(Object... params) { try { String path = (String)params[0]; AsyncHttpPost post = new AsyncHttpPost(HTTP_URL+CONTEXT+FILE_UPLOAD); MultipartFormDataBody body = new MultipartFormDataBody(); // parameters are name, value body.addFilePart("atchFile", new File(path)); post.setBody(body); AsyncHttpClient.getDefaultInstance().executeJSONObject(post, new AsyncHttpClient.JSONObjectCallback(){ @Override public void onCompleted(Exception e, AsyncHttpResponse asyncHttpResponse, JSONObject result) { if (e != null) { e.printStackTrace(); asyncTaskResult = new AsyncTaskResult(AsyncTaskResultType.RESULT_TIMEOUT, e); return; } if (result != null) { try { Logger.debug(this, "result\n" + result.toString()); Gson gsonResult = new Gson(); FileUploadRes fileUploadRes = gsonResult.fromJson(result.toString(), FileUploadRes.class); asyncTaskResult = new AsyncTaskResult(AsyncTaskResultType.RESULT_SUCCESS, fileUploadRes); } catch (Exception e1) { e1.printStackTrace(); asyncTaskResult = new AsyncTaskResult(AsyncTaskResultType.RESULT_FAIL); } } else { asyncTaskResult = new AsyncTaskResult(AsyncTaskResultType.RESULT_FAIL); } } }); while (asyncTaskResult == null) { Thread.sleep(100); } } catch (Exception e) { Logger.error(this, e.getLocalizedMessage()); asyncTaskResult = new AsyncTaskResult(AsyncTaskResultType.RESULT_FAIL, e); } return asyncTaskResult; } }
File upload Sucess call webview javascript method upload success
// Receive AsynTaskResult Ok webView.loadUrl("javascript:getUploadFilePath('"+atchFilePth+"', '"+atchFileMg+"')");
Submit Form with Server UploadFilePath that after AsyncTask success
Conclusion
Android
- Call Image Pick Activity
- Get File Url
- File upload to server
Server
- input type file click call andorid javascript method that file pick
- fill the file path input type file
- Receive File upload
- submit with get uploaded file path
Reference
Android WebView File Upload
File Upload in WebView (Android)
[Android, Hybrid]openFileChooser 킷캣에서 동작하지 않는 문제( openFileChooser Kitkat bug )
Leave a Reply