마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

WebView의 Input file에 javascriptinterface로 파일을 넣을수가 있나요?

0 추천

하이브리드 앱에서 이미지 업로드가 안되는 문제로 4.4.2 버전의 WebView input file문제를 처리하기 위해 

다음과같은 소스를 작성하였습니다.

 

[안드로이드쪽]

  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        accountsArray = new ArrayList<String>();
        wv = (WebView) findViewById(R.id.webview);
        wv.setWebChromeClient(new WebChromeClient());
        wv.setWebViewClient(new WebViewClient());
        WebSettings set = wv.getSettings();
        set.setJavaScriptEnabled(true);
        wv.addJavascriptInterface(new JavaScriptInterface(this), "Android");
        wv.loadUrl(url);        
    }

public class JavaScriptInterface {
        private Context context;

        public JavaScriptInterface(Context context) {
            this.context = context;
        }

        @JavascriptInterface
        public void selectImage() {
            Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            intent.setType("image/*");
            startActivityForResult(intent, PICK_IMAGE_REQ_CODE);
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == PICK_IMAGE_REQ_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                if (data != null) {
                    Uri uri = data.getData();

                    new AsyncTask<Uri, Void, String>() {
                        @Override
                        protected String doInBackground(Uri... params) {
                            String mimeType = getMimeType(params[0]);

                            File file = uriToFile(params[0]);
                            String base64EncodedImage = fileToString(file);

                            return "javascript:updateImage('" + mimeType + "', '" + base64EncodedImage + "');";
                        }

                        @Override
                        protected void onPostExecute(String result) {
                            wv.loadUrl(result);
                        }
                    }.execute(uri);
                }
            }
        }

    public String getMimeType(Uri uri) {
        ContentResolver cR = getContentResolver();
        String type = cR.getType(uri);
        return type;
    }

    private File uriToFile(Uri uri) {

        String filePath = "";

        final String[] imageColumns = {MediaStore.Images.Media.DATA };

        String scheme = uri.getScheme();

        if ( scheme.equalsIgnoreCase("content") ) {
            Cursor imageCursor = 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;
    }

    public String fileToString(File file) {

        String fileString = "";

        try {
            FileInputStream inputStream = new FileInputStream(file);
            ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();

            int len = 0;
            byte[] buf = new byte[1024];
            while ((len = inputStream.read(buf)) != -1) {
                byteOutStream.write(buf, 0, len);
            }

            byte[] fileArray = byteOutStream.toByteArray();
            fileString = new String(Base64.encodeToString(fileArray, 0));

            inputStream.close();
            byteOutStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return fileString;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

onclick메소드로 이미지 셀렉트를 실행하고 이미지추저에서 이미지를 고르면 String으로 변환된 이미지를 jsp로 보내는것 까지는 잘 됩니다.

문제는 그 스트링 형태로 받은 이미지를 input file에 집어넣는 방법이 없는것 같습니다. 인터넷에서 예제를 찾아 겨우 해결한건데 마지막 부분이 없어 이렇게 막히니 정말 미치겠네요.

지금 jsp쪽 스크립트쪽에는 이렇게 되어 있습니다.

function updateImage(mimeType, base64EncodedImage){
  $('#image').val(base64EncodedImage);
}

#image는 input file입니다. 

 

저렇게 스크립트에 String으로 받은 이미지를 인풋파일에 넣을 수 있는 방법이 있나요?

 

없다면 혹시 대체할수 있는 방법이 있는지도 좀 부탁드립니다. 

닭소 (160 포인트) 님이 2016년 12월 7일 질문

1개의 답변

+1 추천
 
채택된 답변
html구조상 인풋태그는 읽기전용입니다.

해당인풋을 하이드시키고 커스텀 인풋박스를 만들어 해당 업로드 파일을 표시해주시고(동기화 방법이 없습니다. 일단 파일은 서버에 업로드된 상태) 뒤로가기나 취소시 해당 파일을 삭제하는 방식으로 구현해야 합니다.
익명사용자 님이 2016년 12월 7일 답변
닭소님이 2017년 1월 17일 채택됨
...