일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
29 | 30 | 31 |
- 230503
- putextra
- querySelector
- 함수 인자
- 안드로이드
- Flutter
- 230508
- ActionBar
- Adapter
- serializable
- fragment
- null-safety
- 생명주기
- 프래그먼트
- C++
- DFS
- javascript
- html
- 230510
- classList
- 인텐트
- textContent
- DOMContentLoaded
- parcelable
- string
- 데이터 타입
- 부가데이터
- ViewPager
- intent
- Class
- Today
- Total
나만의 개발노트
[안드로이드] 권한, 위험권한, permission, RECEIVE_SMS 본문
하라는대로 다 했는데 왜 나만 안될까....
권한 (Permission)
*Android 6.0(API 23/마쉬멜로 버전) 이상에서 일반권한과 위험권한이 나뉨
- 설치 시간 권한
: 최소한 필요한 권한
앱 세부정보에 안내가 되어 있고, 사용자가 앱을 설치할 때 자동으로 앱에 권한을 부여함
- 런타임 권한 (위험 권한)
: 마이크, 카메라 등 민감한 정보 사용할 때
앱을 실행하는 시점에, 권한을 요청
* 권한 요청 메시지는 '시스템'이 띄
(일반권한, 서명권한, 특별권한도 있음)
https://developer.android.com/guide/topics/permissions/overview?hl=ko
[위험 권한 종류]
[위험권한 사용법]
1. Manifest.xml에 권한 선언
uses-permission 태그 사용
<manifest ..>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application ...>
...
</application>
</mainfest>
*일부 하드웨어 및 소프트웨어 기능 상수는 <uses-feature> 시스템을 사용하여
API가 필요하다고 선언하기 전에 API를 사용할 수도 있음
(참고 : https://developer.android.com/guide/topics/manifest/uses-feature-element?hl=ko#permissions-features )
https://developer.android.com/guide/topics/manifest/uses-feature-element?hl=ko
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
2. 권한을 사용할 UI 구성
- SMS를 표시할 SmsActivity.java, activity_sms.xml 작성
https://itnote-for-me.tistory.com/46
3. 앱에 이미 권한이 부여되었는지 확인 (권한이 필요할 때마다)
+ 권한이 없는 경우, 권한을 요청하는 이유 안내
int permissionCheck = ContextCompat.checkSelfPermission(this,Manifest.permission.RECEIVE_SMS);
- shouldShowRequestPermissionRationale() 을 사용하여, 사용자가 권한 설명을 원하는지 확인
- requestPermission() 을 사용하여 시스템이 권한 요청 코드를 관리하도록 허용
1) 시스템이 권한 요청 코드를 관리하도록 허용
*CONTEXT, REQUESTED_PERMISSION는 상황에 맞게 적절히 변경
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(
CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
PackageManager.PERMISSION_GRANTED) {
// You can use the API that requires the permission.
performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected, and what
// features are disabled if it's declined. In this UI, include a
// "cancel" or "no thanks" button that lets the user continue
// using your app without granting the permission.
showInContextUI(...);
} else {
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
requestPermissionLauncher.launch(
Manifest.permission.REQUESTED_PERMISSION);
}
}
private ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(new RequestPermission(), isGranted -> {
if (isGranted) {
//권한이 허용됨. 계속 진행
} else {
//사용자에게 권한 거부로 인해 사용 못하는 기능 안내
}
});
2) 권한 요청 코드 직접 관리
*CONTEXT, REQUESTED_PERMISSION,REQUEST_CODE 는 상황에 맞게 적절히 변경
//MainActivity.java 의 onCreate() 내부에
if (ContextCompat.checkSelfPermission(
CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
PackageManager.PERMISSION_GRANTED) {
performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
showInContextUI(...);
} else {
requestPermissions('CONTEXT',
new String[] { Manifest.permission.REQUESTED_PERMISSION },
REQUEST_CODE);
}
//사용자가 시스템 권한 대화상자에 응답하면, 시스템은 앱의 onRequestPermissionResult()을 호출함
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission is granted. Continue the action or workflow
// in your app.
} else {
// Explain to the user that the feature is unavailable because
// the feature requires a permission that the user has denied.
// At the same time, respect the user's decision. Don't link to
// system settings in an effort to convince the user to change
// their decision.
}
return;
}
// Other 'case' lines to check for other
// permissions this app might request.
}
}
3. 런타임 권한 요청 메시지 표시
4. 런타임 권한 부여에 대한 응답 확인
#최종 Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MySMSReceiver"
tools:targetApi="31">
<activity
android:name=".SmsActivity"
android:exported="false" />
<receiver
android:name=".SmsReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="10000">
<action android:name="android.provier.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
#최종 MainActivity.java
package com.example.mysmsreceiver;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.Manifest;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// BroadcastReceiver br = new SmsReceiver();
// IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
// filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
// this.registerReceiver(br,filter);
int permissionCheck = ContextCompat.checkSelfPermission(this,Manifest.permission.RECEIVE_SMS);
//권한이 이미 있는 경우
if(permissionCheck == PackageManager.PERMISSION_GRANTED){
Toast.makeText(this,"SMS 수신 권한 있음",Toast.LENGTH_LONG).show();
}
//권한이 없는 경우
else{
Toast.makeText(this,"SMS 수신 권한 없음",Toast.LENGTH_LONG).show();
//RECEIVE_SMS에 관한 권한에 대해서 인지
if(shouldShowRequestPermissionRationale(Manifest.permission.RECEIVE_SMS)){
Toast.makeText(this,"SMS 권한 설명 필요함", Toast.LENGTH_LONG).show();
}else{
//사용자에게 교육용 UI가 표시되거나 shouldShowRequestPermissionRationale()의 반환값에서 설명을 표시하지 않아도 된다고 나타나면
//권한 요청하는 대화상자 표시 **시스템에서 하는 것
requestPermissions(new String[]{Manifest.permission.RECEIVE_SMS},1);
}
}
}
//사용자가 권한 대화상자에 응답하면 시스템은 앱의 onRequestPermissionsResult()를 호출
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
//requestCode가 1인 RECEIVE_SMS에 대한 권한인 경우
case 1:
//request가 취소되면, grantResults가 비어있음
//request 응답받았다면
if(grantResults.length>0){
if(grantResults[0] == PERMISSION_GRANTED){
Toast.makeText(this,"SMS 수신 권한을 사용자가 승인함",Toast.LENGTH_LONG).show();
}else if(grantResults[0] == PERMISSION_DENIED){
Toast.makeText(this,"SMS 수신 권한을 사용자가 거부함",Toast.LENGTH_LONG).show();
//권한이 거부된 경우, 거부에 따른 영향을 설명해야함
//Android 11(API수준 30)부터 특정 권한에 관해 2번 이상 거부하면, 그 권한을 다시 묻지 않음
}
}else{
//request 응답 받지 못한 경우
Toast.makeText(this,"SMS 수신 권한을 부여받지 못함",Toast.LENGTH_LONG).show();
}
}
}
}
[참조]
https://www.boostcourse.org/mo316/lecture/22591?isDesc=false
https://developer.android.com/guide/topics/permissions/overview?hl=ko
https://developer.android.com/training/permissions/requesting?hl=ko
'[안드로이드] > [안드로이드] 공부 기록' 카테고리의 다른 글
[안드로이드] 옵션메뉴(OptionMenu), 액션바 (ActionBar) (2) | 2023.11.24 |
---|---|
[안드로이드] 프래그먼트 (Fragment), FragmentManager (0) | 2023.11.22 |
[안드로이드] 브로드캐스트 수신자, onReceiver, SMS메시지 수신 어플 (0) | 2023.11.10 |
[안드로이드] 서비스, startService, onStartCommand (0) | 2023.10.13 |
[안드로이드] 수명주기/생명주기 (LifeCycle), getSharedPreferences() (0) | 2023.10.13 |