kotlinでAndroid端末内の画像を含むフォルダを検知する



画像系のアプリを作ってる時に端末内の画像を含むフォルダを表示させたかったので作成



##ストレージの許可
端末の設定からアプリのストレージ設定を弄らないと内部ストレージにアクセスできない？らしい
詳しくはhttps://direct.fujixerox.co.jp/ap1/sc/beat/ja/support/020211.html


## 内部ストレージのパスを渡す
内部ストレージのパスをImgFileconクラスのextract()に渡す



```ruby:MainActivity.kt
package com.example.myapplication

import android.os.Bundle
import android.support.design.widget.BottomNavigationView
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File
import com.example.myapplication.R.attr.content
import android.content.Context
import android.os.Environment

class MainActivity : AppCompatActivity() {

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

        /*内部ストレージのパス取得*/
        val path = Environment.getExternalStorageDirectory().getPath()
        val dir  = File(path)

      /*内部ストレージのファイルオブジェクトを渡す*/
      val imgserch=ImgFilecon()
      imgserch.extract(dir)
    }
}
```

## 画像を含むフォルダを探す（class ImgFilecon）
渡されたパス内のディレクトを再帰的に探索してファイルを探す。見つけたファイルが画像の拡張子(.jpgなど)を持っていたらそのファイルのあるディレクトリのパスを出力


```ruby:ImgFilecon.kt

/*フォルダ・ファイル探索クラス*/
class ImgFilecon() {

    /*メソッド一覧
    in_storagepath_serch():内部ストレージのパスを取得
    out_storagepath_serch():外部ストレージのパスを取得（今回は不要）
    extract():ストレージのファイルオブジェクトを受け取り探索
    imgserch():extract()から呼び出されて再帰的にフォルダを探索
    dirurllist():画像を含むフォルダのリストを返す
    dircount():画像を含むフォルダ数を返す
     */

    /*パス格納配列*/
    var imgdirurl: MutableList<RowData>  = mutableListOf()
    var filecount:Int =0


    /*内部ストレージのパス取得*/
    fun in_storagepath_serch(): File {
        val path = Environment.getExternalStorageDirectory().getPath()
        val in_strage_dir = File(path)
        return in_strage_dir
    }

    /*外部ストレージのパス取得*/
    fun out_storagepath_serch(){}


    /*フォルダ・ファイルリストを探索*/
    fun extract(dir:File): Unit {
        /*内部ストレージ下のフォルダ・ファイルリスト*/
        for (i in dir.listFiles()) {
            if (i.listFiles() != null) imgserch(0, i.listFiles().reversed(), false, i)
            else println("ファイルもフォルダもなし")
            }
    }


    /*ファイルの再帰探索*/
    tailrec fun imgserch(i:Int, filelist:List<File>, flag: Boolean, dir:File):Boolean {

        if (flag && !dir.isDirectory) return true

        /*ファイル時の処理*/
        if (filelist[i].isFile && !flag) {
            /*画像ファイル判定*/
            when (Extension().extensionsplit(i.toString(), ".")) {
                "jpeg", "JPEG", "jpg", "JPG", "png", "PNG", "gif", "GIF", "MP4", "mp4" -> {
                    val rowData: RowData = RowData().also {
                        it.dirurl = dir.toString()
                        it.imgurl = i.toString()
                    }
                    imgdirurl.add(rowData)
                    filecount = +1
                    return imgserch(i + 1, filelist, true, dir)
                }
                else -> { return imgserch(i+1,filelist,false,dir)}
            }
        }

        if(filelist[i].isFile && flag) return imgserch(i+1,filelist,true,dir)

        /*ディレクトリの時の処理*/
        if (filelist[i].isDirectory && flag) return imgserch(0, filelist[i].listFiles().reversed(), false, filelist[i])
        if (filelist[i].isDirectory && !flag) return imgserch(i+1, filelist,false,filelist[i])

        return true
    }

    /*画像を含むフォルダのリストを返す*/
    fun dirurllist(): MutableList<RowData>{
        return imgdirurl
    }

    /*画像を含むフォルダ数を返す*/
    fun dircount(): Int{
        return filecount
    }

}
```
```ruby:RowData.kt
package com.example.viewkotlintest

class RowData {
    var dirurl: String=""
    var imgurl: String=""
}

```


## 画像ファイルを判断するために拡張子切り出し(class Extension)
パスと区切り文字を渡すと区切り文字より下の文字列を返すメソッド。今回はファイルパスと区切り文字"."を渡して拡張子を取得した。

```ruby:Extension.kt
package com.example.myapplication

import android.os.Parcel
import android.os.Parcelable

class Extension {

    /*区切り文字で分割するメソッド*/
     fun extensionsplit(filename: String, splitps: String): String {

        /*splitpsで指定した文字のindex*/
         val point = filename.lastIndexOf(splitps)

         if (point != -1) {
             /*pointより下の部分を切り出す*/
             /* 例 xxxx.jpg→jpg*/
             return filename.substring(startIndex = point + 1)
         }
         else return null.toString()
     }
}
```



## デモ
<img width="774" alt="スクリーンショット 2019-02-11 7.04.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/296022/9794f632-2d5a-1658-d8b3-7871da576c68.png">
こんな感じで端末内の画像を含むフォルダ一覧がAndroidStudioのRunに表示される



##参考
ストレージへのアクセス許可:[https://direct.fujixerox.co.jp/ap1/sc/beat/ja/support/020211.html](https://direct.fujixerox.co.jp/ap1/sc/beat/ja/support/020211.html)