rokkonet

PC・Androidソフトウェア・アプリの開発・使い方に関するメモ

android端末内のファイルのパスをファイラーを利用して選択し取得する android開発

2020 May 04.
2020 May 03.


参照元
https://yyyank.blogspot.com/2015/03/androidintent.html
https://alasixosaka.hatenablog.com/entry/2019/06/23/210006


端末内のファイルを一覧表示して選択
Intent.ACTION_GET_CONTENT へ startActivityForResult() すれば端末内のファイラが起動し、選択したファイルパスを取得できる。

すべてのファイルの表示
Intentに type = "*/*" とセットする。
前方のアスタリスクMIME-Typeにすべてのタイプを、後方のアスタリスクMIME-SubTypeにすべてのタイプを指定している。

デコード
取得したファイルパスを URLDecoder.decode(FILE_PATH, "utf-8") でデコードし、端末のパスに合ったものに再構成する。

class MainActivity : AppCompatActivity() {
    private lateinit var strSdParentDir: String
    private lateinit var strSdFullDir: String
    private val GET_FILE_CODE: Int = 1100
    private val REQUEST_PERMISSION_EX_STORAGE = 2100

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // レイアウト上のボタンに、ファイル選択を行うメソッドを起動するリスナをセット
        buttonGetFile.setOnClickListener {  
            onClick(buttonGetFile)
        }

        // 外部記憶装置へのパーミッション要求
        ActivityCompat.requestPermissions(this,
            arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
            REQUEST_PERMISSION_EX_STORAGE)

        // 外部記憶装置パーミッション取得後
        override fun onRequestPermissionsResult(
                requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
            if (requestCode == REQUEST_PERMISSION_EX_STORAGE) {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(applicationContext, "ex-storage-permission true", Toast.LENGTH_LONG).show()

                    // 外部記憶装置のパスを取得
                    strSdFullDir = getFullPathExtStorage(this)
                    strSdParentDir = getFullPathExtStorage(this).replace("^.+/".toRegex(),"")
                }
            }
        }
    }

    fun onClick(view: View?) {
        if ( buttonGetFile == view ) {  // レイアウト上のボタンへのクリック
            val getFileIntent = Intent(Intent.ACTION_GET_CONTENT)
            getFileIntent.type = "*/*"
            startActivityForResult(getFileIntent, GET_FILE_CODE)
        }    
    }

    override fun onActivityResult(requestCode: Int , resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data )
        try {
            if (requestCode == GET_FILE_CODE && resultCode == RESULT_OK) {

                // ファイラでファイルパスを取得した時
                val filePath: String = data!!.getDataString()

                // ファイルパス文字列をプログラム扱える正しいものにする
                //     ・URLDecoder.decodeで文字列をデコードする
                //     ・パスを再構成する
                //             ファイラから取得したファイルパス(decodedFilePath) /aaa/bbb/ccc/ddd
                //             外部記憶装置のパス(strSdFullDir) /xxx/ccc
                //             共通に含まれるccc(strSdParentDir)をキーに正しいファイルパス(/xxx/ccc/ddd)を取得する
                val decodedFilePath: String = URLDecoder.decode(filePath, "utf-8").
                    replace("^.*${strSdParentDir}".toRegex(), "${strSdFullDir}").
                    replace(":", "/")

                // File型インスタンス取得
                val myFile = File(decodedFilePath)

                // インプットストリーム型インスタンス取得
                val myFileInStream = FileInputStream(myFile)
            }
        } catch (e: UnsupportedEncodingException) {
            // 例外処理
        }
    }


    // 外部記憶装置のパスを取得する
    protected fun getFullPathExtStorage(appContext: Context?): String {
        // android端末内の外部ストーリッジ確認
        val sdCardFilesDirPaths =
            SdCardDirPaths.getSdCardFilesDirPathListForLollipop(appContext)
        // sort sdCardFilesDirPaths order by shorter length of path
        Collections.sort(sdCardFilesDirPaths, CompStringLength())
        // get top path in array-sdCardFilesDirPaths
        val externalPath = sdCardFilesDirPaths[0]
        // get complete full path
        return externalPath.replace("/Android.*$".toRegex(), "")
    }
}


SdCardDirPaths.java

public class SdCardDirPaths {
    /**
     * SDカードのfilesディレクトリパスのリストを取得する。
     * Android5.0以上対応。
     *
     * @param Context
     * @return List<String>: SDカードのfilesディレクトリパスのリスト
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static List<String> getSdCardFilesDirPathListForLollipop(Context context) {
        List<String> sdCardFilesDirPathList = new ArrayList<>();
        // 外部ストーリッジのディレクトリのFile型配列を取得
        // getExternalFilesDirs()はAndroid4.4から利用可能
        File[] dirArr = context.getExternalFilesDirs(null);
        for (File dir : dirArr) {
            if (dir != null) {
                String path = dir.getAbsolutePath();
                // isExternalStorageRemovableはAndroid5.0から利用できるAPI。
                // 取り外し可能かどうか(SDカードかどうか)を判定している。
                if (Environment.isExternalStorageRemovable(dir)) {
                    // 取り外し可能であればSDカード。
                    // このパスをパスリストに加える
                    if (!sdCardFilesDirPathList.contains(path)) {
                        sdCardFilesDirPathList.add(path);
                    }
                }
            }
        }
        return sdCardFilesDirPathList;
    }
}