-
[Android] Storage Access Framework(SAF) ์ด๋?Android 2022. 3. 13. 17:54๋ฐ์ํ
Storage Access Framework(SAF)
Android 4.4(API 19)์ดํ๋ถํฐ ๋ฌธ์, ์ด๋ฏธ์ง(์ฌ์ง) ๋ฐ ๊ฐ์ข ๋ค๋ฅธ ํ์ผ์ ํ์ํ๊ณ ์ฌ๋ ์์ ์ ๊ฐํธํ๊ฒ ํด์ฃผ๋ Strorage Access Framework(SAF)๊ฐ ๋์ ์ด ๋์์ต๋๋ค. Selector๋ฅผ ํตํด ์ฌ์ฉ์๊ฐ ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ํ์ผ์ ํ์ํ๊ณ ์ต๊ทผ ๊ธฐ๋ก์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
SAF ๊ตฌ์ฑ ์์
Document Provider
๋ฌธ์๋ฅผ ์ ๊ณตํ๋ ์ฃผ์ฒด๋ก DocumentProvider ํด๋์ค๋ฅผ ์์๋ฐ๊ณ ์์ผ๋ฉฐ, Android์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ด์ฅ๋ ๋ค์ด๋ก๋, ์ด๋ฏธ์ง, ๋์์๊ณผ ๊ฐ์ ์ฑ๋ค์ด DocumentProvider ํด๋์ค๋ฅผ ์์๋ฐ์ ๋ฌธ์๋ฅผ ์ ๊ณตํด์ค๋๋ค.
Client App
Document Provider์์ ์ ๊ณต๋ ๋ฌธ์, ํ์ผ๋ค์ ์ฌ์ฉํ๋ ํด๋ผ์ด์ธํธ ์ฑ
Selector
์ผ์ข ์ ์์คํ UI๋ก, ์ฌ์ฉ์๊ฐ ํ์ํ ํ์ผ์ ์ ํํ ๋ ์ฌ์ฉ๋๋ UI์ ๋๋ค.
SAF์ ํน์ง
- SAF๋ ๋ฌธ์๋ฅผ ์ ๊ณตํ๋ Provider์ ์ ๊ณต๋ ๋ฌธ์๋ค์ ์ฌ์ฉํ๋ Client ๊ตฌ์กฐ๋ก ๋๋๊ฒ ๋ฉ๋๋ค.
์๋ํํฐ ์ฑ์ด ๋ฌธ์๋ฅผ ์ ๊ณตํ๋ Provider ์ญํ ์ ํจ๊ณผ ๋์์ ๋ค๋ฅธ Provider๋ฅผ ์ฌ์ฉํ๋ Client ์ญํ ์ ํ ์๋ ์์ต๋๋ค. - ์ฌ์ฉ์๋ Selector๋ฅผ ํตํด์ ํ๋์ ์ฑ์ด ์๋ ๋ชจ๋ Document Provider๋ก๋ถํฐ ๋ฌธ์, ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค.
- ํด๋ผ์ด์ธํธ ์ฑ์ Document Provider์์ ์ ๊ณตํ ๋ฌธ์์ ์ก์ธ์ค ๊ถํ์ ๊ฐ์ง๋ฉฐ ์ฌ์ฉ์๊ฐ ์ ๊ณต์์ ํ์ผ์ ์ถ๊ฐ, ์ญ์ , ๋ณ๊ฒฝ ๋ฐ ์ ์ฅ์ ํ ์ ์์ต๋๋ค.
- USB๊ฐ ์ฐ๊ฒฐ์ด ๋๋ฉด USB ์ ์ฅ์ Provider๋ ์ง์ํฉ๋๋ค.
SAF ํ๋ฆ
์์ ๊ทธ๋ฆผ์ ์ฌ์ง ์ฑ(com.example.photos) ์์ SAF๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ๋ค์ ์ก์ธ์ค ํ ์ ์๋ flow๋ฅผ ๋ํ๋ ๋๋ค. PhotoViewer๋ ACTION_OPEN_DOCUMENT ๋ฅผ ์ฌ์ฉํ์ฌ Selector์์ ์ํ๋ Provider๋ฅผ ์ ํํ ํ ํ์ผ์ ์ฝ์ต๋๋ค. PhotoEditor๋ ACTION_CREATE_DOCUMENT๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ์ ์ ์ฅํฉ๋๋ค.
ํด๋ผ์ด์ธํธ ์ฑ ์์ฑ
private fun bindViews() = with(binding){ actionPickButton.setOnClickListener { startActivityForResult( Intent(Intent.ACTION_PICK).apply { type = "image/*" }, READ_REQUEST_CODE ) } actionGetContentButton.setOnClickListener { startActivityForResult( Intent(Intent.ACTION_GET_CONTENT).apply { type = "image/*" }, READ_REQUEST_CODE ) } actionOpenDocumentButton.setOnClickListener { startActivityForResult( Intent(Intent.ACTION_OPEN_DOCUMENT).apply { type = "image/*" }, READ_REQUEST_CODE ) } actionOpenDocumentTreeButton.setOnClickListener { startActivityForResult( Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), READ_REQUEST_CODE ) } }
4๊ฐ์ ๋ฒํผ์ ๋์ด ๊ฐ ๋ฒํผ๋ณ๋ก Intent Action์ ๋ค๋ฅด๊ฒ ์ค์ ํ์์ต๋๋ค.
Android 4.3 ์ดํ์์๋ ์ฑ์ด ๋ค๋ฅธ ์ฑ์ ํ์ผ์ ๊ฒ์ํ๊ธฐ ์ํด์๋ ACTION_PICK ๋๋ ACTION_GET_CONTENT์ ๊ฐ์ ์ก์ ์ ํธ์ถํด์ผ ํฉ๋๋ค. ๊ทธ ์ดํ ์ฌ์ฉ์๋ ํ์ผ์ ์ ํํ ์ฑ์ ํ๋ ์ ํํฉ๋๋ค. ACTION_PICK๊ณผ ACTION_GET_CONTENT์๋ ์ฐจ์ด์ ์ด ์กด์ฌํ๋๋ฐ ACTION_PICK์ ์ฌ์ง, ์จ๋ฒ์์๋ง ํ์ผ์ ๊ฐ์ ธ์ค๊ธฐ์ ๋ชจ๋ ํ์ผ์ URI์ Authority๊ฐ ๋์ผํ๊ณ ID๋ง ๋ค๋ฅด์ง๋ง, ACTION_GET_CONTENT ์ฌ์ง, ์จ๋ฒ ์ด์ธ์ ๊ตฌ๊ธ ํฌํ , download Provider๋ก๋ถํฐ๋ ํ์ผ์ ๊ฐ์ ธ์ฌ ์ ์์ด URI๋ ๋ค์ํฉ๋๋ค.
Android 4.4(API 19) ์ด์์์๋ ACTION_OPEN_DOCUMENT ์ธํ ํธ ์ก์ ์ ์ฌ์ฉํ๋ฉฐ, ACTION_GET_CONTENT์ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ๊ตฌ๊ธ ๊ณต์๋ฌธ์์์๋ ACTION_OPEN_DOCUMENT๊ฐ ACTION_GET_CONTENT๋ฅผ ๋์ฒดํ ๋ชฉ์ ์ผ๋ก ๋ง๋ค์ด์ง ๊ฒ์ด ์๋๋ฉฐ, ์ด๋ ๊ฒ์ ์ฌ์ฉํ ์ง๋ ๊ฐ ์ฑ์ ํ์์ฑ์ ๋ฐ๋ผ ์ข์ฐ๋๋ค๊ณ ํฉ๋๋ค.
- ACTION_GET_CONTENT : ๋จ์ํ ๋ฐ์ดํฐ ์ฝ๋๋ฐ ์ ํฉ, ์ด ๋ฐฉ์ ์ฌ์ฉ ์ ๋ฐ์ดํฐ ์ฌ๋ณธ์ ๊ฐ์ ธ์ด
- ACTION_OPEN_DOCUMENT : ๋ฐ์ดํฐ์ ์ฅ๊ธฐ์ , ์ง์์ ์ก์ธ์ค ๊ถํ์ ๊ฐ์ ธ์ผ ํ ๊ฒฝ์ฐ ์ฌ์ฉ
Android 5.0(API 21) ์ด์์์๋ ACTION_OPEN_DOCUMENT_TREE ์ธํ ํธ ์ก์ ์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์ด ์ธํ ํธ๋ก ์ฌ์ฉ์๋ ์ฑ์์ ํ์ํ๊ณ ์ ํ๋ ๋๋ ํฐ๋ฆฌ๋ฅผ ์ง์ ํ์ฌ ๊ถํ์ ๋ถ์ฌํ ์ ์์ต๋๋ค.
์ฐธ๊ณ
SAF๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ ์ฝ๋ ๋ฐฉ๋ฒ๋ง ์์ ํ์์ง๋ง, ๊ทธ์ธ์๋ ํ์ผ ์์ฑ, ์์ , ์ญ์ ๋ฑ SAF๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์๋ ์ฐธ๊ณ ๋ธ๋ก๊ทธ์ ๊ณต์๋ฌธ์๋ฅผ ๋ณด์๋ฉด ๋์์ด ๋ง์ด ๋ ๊ฒ์ ๋๋ค. ๐
๋ฐ์ํ'Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] RecyclerView ViewHolder ํจํด, DiffUtil ํด๋์ค (1) 2022.03.22 [Android] ViewBinding์ด๋? (0) 2022.03.20 [Android] findViewById ์๋ฆฌ (0) 2022.03.13 [Android] Native Application(C/C++), NDK build ๋ฐ CMake ๊ตฌ์ฑ (0) 2022.02.14 [Android] ContentProvider ๊ตฌํ ๋ฐ ์ฌ์ฉ๋ฒ (0) 2022.02.05 - SAF๋ ๋ฌธ์๋ฅผ ์ ๊ณตํ๋ Provider์ ์ ๊ณต๋ ๋ฌธ์๋ค์ ์ฌ์ฉํ๋ Client ๊ตฌ์กฐ๋ก ๋๋๊ฒ ๋ฉ๋๋ค.