Blog スタッフブログ

Android システム開発

[Android][Kotlin]WebViewのinputフォームのfile対応

システム開発担当のTFです。

※Android10対応(他バージョンの場合、細かい部分等が異なる事があります)

やり方

  • 画像アクセスの為のpermissionを設定する
  • WebChromeClient の onShowFileChooser を override し、画像を取得するIntentを発行する
  • onActivityResult で画像パスを受け取る

参考

  WebChromeClient
  — チャットの画像アップロードに対応する

サンプル

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
	
	<!-- ネット接続の為のpermissionを設定する -->
	<uses-permission android:name="android.permission.INTERNET"/>
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	
	<!-- 画像アクセスの為のpermissionを設定する -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
	
	<!-- 省略 -->

</manifest>
class SampleActivity : AppCompatActivity() {
	
	final val FILE_PATH_CALLBACK_RESULT_CODE = 1234
	
	// ファイルパスを受け取るコールバック変数
	var mFilePathCallback:ValueCallback<Array<Uri>>? = null;
	
	override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
		
		// 省略
		
		// WebChromeClientの設定
		binding.webView.webChromeClient = object :WebChromeClient(){
            // 省略
			
			// input type=file で発火
            override fun onShowFileChooser(webView: WebView?, filePathCallback: ValueCallback<Array<Uri>>?, fileChooserParams: FileChooserParams?): Boolean {
                if(mFilePathCallback != null){
                    // 前のにnullを返す
					mFilePathCallback?.onReceiveValue(null);
                }
				// ファイルパスのコールバックの保存
                mFilePathCallback = filePathCallback;

				// 画像取得のインテントを発行する
                var intent:Intent = Intent(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("image/*");
                startActivityForResult(intent, FILE_PATH_CALLBACK_RESULT_CODE);

                return true;
            }

        }
	}
	
	override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        // 画像取得からの戻りで リザルトOK
		if( requestCode == FILE_PATH_CALLBACK_RESULT_CODE && resultCode == Activity.RESULT_OK ){
            if(mFilePathCallback == null){
                super.onActivityResult(requestCode, resultCode, data);
                return;
            }
            var results:Array<Uri>? = null;

            var dataString = data?.dataString;
            if( dataString != null ){
                results = arrayOf(Uri.parse(dataString));
            }
			
			// 画像パスをコールバックに返し、コールバックをnullに
            mFilePathCallback?.onReceiveValue(results);
            mFilePathCallback = null;

            return;
        }
		// 画像取得からの戻りで リザルトNG
        else if(requestCode == FILE_PATH_CALLBACK_RESULT_CODE){
            mFilePathCallback?.onReceiveValue(null);
            mFilePathCallback = null;
            return;
        }

        super.onActivityResult(requestCode, resultCode, data);
    }
}