Archives
Recent Posts
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Today
Total
관리 메뉴

안드로이드 개발자의 창고

[33일차 Android] Permission 본문

Computer/Android

[33일차 Android] Permission

Wise-99 2023. 6. 17. 16:55

 

 

 

출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 PPT

 

 

 

📖 Permission

  • 앱의 특정 기능에 부여하는 접근 권한
  • 개인 정보와 관련된 기능을 사용하기 위해서는 권한을 등록해야 한다.
  • 권한 등록의 목적은 사용자에게 애플리케이션이 어떠한 기능을 사용하는지 알려주는 목적으로 사용
  • 모든 권한에 대해서 한번에 요청하고자 한다면 requestPermissions을 사용
  • 권한 확인 후에 처리가 필요하다면 onRequestPermissionsResult 메서드를 overriding하고 권한 별로 분기하여 처리
  • 만약 권한 요청 후 필요한 처리를 권한 별로 나눠서 구현하고 싶다면 ActivityResultCallback을 사용

 

 

 

예제 코드

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="권한 확인하기" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="위치 권한 확인" />

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="연락처 권한 확인" />

    <Button
        android:id="@+id/button4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="저장소 권한 확인" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/textView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="TextView"
                android:textAppearance="@style/TextAppearance.AppCompat.Large" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

 

 

 

MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var activityMainBinding: ActivityMainBinding

    // 확인 받을 권한 목록
    val permissionList = arrayOf(
        Manifest.permission.INTERNET,
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.READ_CONTACTS,
        Manifest.permission.WRITE_CONTACTS,
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(activityMainBinding.root)

        // 위치 정보 권한 확인을 위한 객체들을 생성
        val r1 = ActivityResultContracts.RequestMultiplePermissions()
        val callback1 = LocationPermissionCallback()
        val locationLauncher = registerForActivityResult(r1, callback1)

        val r2 = ActivityResultContracts.RequestMultiplePermissions()
        val callback2 = ContractPermissionCallback()
        val contactLauncher = registerForActivityResult(r2, callback2)

        activityMainBinding.run {
            button.run {
                setOnClickListener {
                    // 권한 확인 요청
                    requestPermissions(permissionList, 0)
                }
            }

            button2.run {
                setOnClickListener {
                    // 권한 요청
                    val a1 = arrayOf(
                        Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_COARSE_LOCATION
                    )
                    locationLauncher.launch(a1)
                }
            }

            button3.run {
                setOnClickListener {
                    val a1 = arrayOf(
                        Manifest.permission.READ_CONTACTS,
                        Manifest.permission.WRITE_CONTACTS
                    )
                    contactLauncher.launch(a1)
                }
            }
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>, // 권한 이름들
        grantResults: IntArray          // 허용 여부 값
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        activityMainBinding.run{
            textView.text = ""

            for(idx in 0 until  permissions.size){
                // 현재 번째의 권한 이름을 가져온다.
                val p1 = permissions[idx]
                // 권한 허용 여부 값을 가져온다.
                val g1 = grantResults[idx]

                when(p1){
                    Manifest.permission.ACCESS_FINE_LOCATION -> {
                        if(g1 == PackageManager.PERMISSION_GRANTED){
                            textView.append("위치 1 : 허용\n")
                        } else {
                            textView.append("위치 1 : 거부\n")
                        }
                    }
                    Manifest.permission.ACCESS_COARSE_LOCATION -> {
                        if(g1 == PackageManager.PERMISSION_GRANTED){
                            textView.append("위치 2 : 허용\n")
                        } else {
                            textView.append("위치 2 : 거부\n")
                        }
                    }
                    Manifest.permission.READ_CONTACTS ->{
                        if(g1 == PackageManager.PERMISSION_GRANTED) {
                            textView.append("연락처 1 : 허용\n")
                        } else {
                            textView.append("연락처 1 : 거부\n")
                        }
                    }
                    Manifest.permission.WRITE_CONTACTS ->{
                        if(g1 == PackageManager.PERMISSION_GRANTED){
                            textView.append("연락처 2 : 허용\n")
                        } else {
                            textView.append("연락처 2 : 거부\n")
                        }
                    }
                    Manifest.permission.READ_EXTERNAL_STORAGE -> {
                        if(g1 == PackageManager.PERMISSION_GRANTED){
                            textView.append("저장소 1 : 허용\n")
                        } else {
                            textView.append("저장소 1 : 거부\n")
                        }
                    }
                    Manifest.permission.WRITE_EXTERNAL_STORAGE ->{
                        if(g1 == PackageManager.PERMISSION_GRANTED){
                            textView.append("저장소 2 : 허용\n")
                        } else {
                            textView.append("저장소 2 : 거용\n")
                        }
                    }
                    Manifest.permission.INTERNET ->{
                        if(g1 == PackageManager.PERMISSION_GRANTED){
                            textView.append("네트워크 : 허용\n")
                        } else {
                            textView.append("네트워크 : 거부\n")
                        }
                    }
                }
            }
        }
    }

    inner class LocationPermissionCallback : ActivityResultCallback<Map<String, Boolean>>{

        override fun onActivityResult(result: Map<String, Boolean>?) {
            activityMainBinding.run{
                textView.text = "위치 권한 확인\n"

                if(result != null) {
                    // 확인한 권한 만큼 반복한다.
                    for (key in result.keys) {
                        // 권한 만큼 반복한다.
                        when(key) {
                            Manifest.permission.ACCESS_FINE_LOCATION -> {
                                if (result[key] == true) {
                                    textView.append("위치1 권한 허용\n")
                                } else {
                                    textView.append("위치1 권한 거부\n")
                                }
                            }
                            Manifest.permission.ACCESS_COARSE_LOCATION ->{
                                if(result[key] == true){
                                    textView.append("위치2 권한 허용\n")
                                } else {
                                    textView.append("위치2 권한 거부\n")
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    inner class ContractPermissionCallback : ActivityResultCallback<Map<String, Boolean>>{
        override fun onActivityResult(result: Map<String, Boolean>?) {
            activityMainBinding.run {
                textView.text = "연락처 권한 확인\n"

                if (result != null){
                    for (permission in result.keys){
                        when(permission){
                            Manifest.permission.READ_CONTACTS -> {
                                if(result[permission] == true){
                                    textView.append("연락처1 권한 허용1\n")
                                } else {
                                    textView.append("연락처1 권한 거부\n")
                                }
                            }
                            Manifest.permission.WRITE_CONTACTS -> {
                                if(result[permission] == true){
                                    textView.append("연락처2 권한 허용\n")
                                } else {
                                    textView.append("연락처2 권한 거부\n")
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

 

 

 

코드 리뷰

    button.run {
        setOnClickListener {
            // 권한 확인 요청
            requestPermissions(permissionList, 0)
        }
    }
  • requestPermissions을 사용하여 권한 확인을 요청한다.
  • 확인이 필요한 권한 중에서 허용되지 않은 권한에 대해 물어본다.
  • 확인이 필요하지 않은 권한은 건너뛴다.

 

    button2.run {
        setOnClickListener {
            // 권한 요청
            val a1 = arrayOf(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION
            )
            locationLauncher.launch(a1)
        }
    }
  • 위치 정보에 대한 권한을 요청한다.
  • ACCESS_FINE_LOCATION : 앱이 정확한 위치에 액세스
  • ACCESS_COARSE_LOCATION : 앱이 대략적인 위치에 액세스

 

    button3.run {
        setOnClickListener {
            val a1 = arrayOf(
                Manifest.permission.READ_CONTACTS,
                Manifest.permission.WRITE_CONTACTS
            )
            contactLauncher.launch(a1)
        }
    }
  • 연락처에 대한 권한을 요청한다.
  • Manifest.permission.READ_CONTACTS : 앱이 연락처 데이터를 읽을 수 있도록 한다.
  • Manifest.permission.WRITE_CONTACTS : 앱이 연락처 데이터를 작성할 수 있도록 한다.

 

override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>, // 권한 이름들
        grantResults: IntArray          // 허용 여부 값
    ) { ... }
  • requestPermission 메서드를 통해 권한을 요청하여 요청 작업이 끝나면 자동으로 호출되는 메서드

 

inner class LocationPermissionCallback : ActivityResultCallback<Map<String, Boolean>>{
    ...
}
  • 권한 요청 후 필요한 처리를 권한 별로 나눠서 구현하기 위한 inner class
  • Map에는 권한의 이름, 권한 허용 여부 값을 들어온다.

'Computer > Android' 카테고리의 다른 글

[34일차 Android] Context Menu  (1) 2023.06.17
[34일차 Android] Option Menu  (0) 2023.06.17
[32일차 Android] RecyclerView  (0) 2023.06.16
[32일차 Android] Spinner  (0) 2023.06.16
[32일차 Android] ListView - CustomAdapter  (0) 2023.06.15