앞 게시글에 브로드캐스트 수신자를 만들어 SMS 문자를 받으려면 RECEIVE_SMS
권한이 필요하다는 것을 알고 있습니다.
예를 들어, 인터넷을 사용할 때 부여하는 INTERNET 권한은 일반 권한이므로 앱을 설치할 때 사용자에게 권한이 부여되어야 함을 알려주고 설치할 것인지를 물어봅니다.
사용자가 부여할 권한들에 대한 설명을 보고 수락하면 앱이 설치되고 앱에는 INTERNET 권한이 부여됩니다. 그러나 위험 권한으로 분류되는 RECEIVE_SMS
의 경우에는 설치 시에 부여한 권한은 의미가 없으며 실행시에 사용자에게 권한을 부여할 것인지 물어보게 됩니다.
만약 사용자가 권한을 부여하지 않으면 해당 기능은 동작하지 않습니다.
위험 권한으로 분류된 주요 권한들을 보면 대부분 개인정보가 담겨 있는 정보에 접근하거나 개인정보를 만들어낼 수 있는 단말의 주요 장치에 접근하는 경우에 부여되는 권한이라는 것을 알 수 있습니다.
분류(Permission Group) | 세부 권한 (Permission) |
---|---|
LOCATION(위치) | ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION |
CAMERA | CAMERA |
MICROPHONE | RECORD_AUDIO |
CONTACTS | READ_CONTACTS READ_CONTACTS GET_ACCOUNTS |
PHONE | READ_PHONE_STATE CALL_PHONE READ_CALL_LOG WRITE_CALL_LOG ADD_VOICEMAIL USE_SIP PROCESS_OUTGOING_CALLS |
SMS | SEND_SMS RECEIVE_SMS READ_SMS RECEIVE_WAP_PUSH RECEIVE_MMS |
CALENDAR | READ_CALENDAR WRITE_CALENDAR |
SENSOR | BODY_SENSORS |
STORAGE | READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE |
package com.study.doit; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //권한이 부여되어 있는지 확인함. int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS); if(permissionCheck == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "SMS 수신 권한 있음", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "SMS 수신 권한 없음", Toast.LENGTH_SHORT).show(); if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECEIVE_SMS)) { Toast.makeText(this, "SMS 권한 설정 필요함.", Toast.LENGTH_SHORT).show(); } else { // 사용자가 볼 수 있도록 새로운 권한 부여 요청 대화상자를 띄움. ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.RECEIVE_SMS }, 1); } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch(requestCode) { case 1: //사용자가 권한을 수락했는지 여부를 확인함 if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "SMS 권한을 사용자가 승인함.", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "SMS 권한 거부됨.", Toast.LENGTH_SHORT).show(); } return; } } }
안드리오드 앱은 크게 자바코드와 리소스로 구성됩니다.
설치된 앱의 구성 요소가 어떤 것인지, 그리고 어떤 권한이 부여되었는지 시스템에 알려주기 때문에 매우 중요합니다.
모든 안드로이드 앱은 가장 상위 폴더에 매니페스트 파일이 있어야 하며 이 정보는 앱이 실행되기 전에 시스템이 알아야 할 내용들을 정의하고 있습니다.
<action>
<activity>
<activity_alias>
<application>
<category>
<data>
<grant-uri-permission>
<instrumetation>
<intent-filter>
<manifest>
<meta-data>
<permission>
<permission-group>
<permission-tree>
<provider>
<receiver>
<service>
<uses-configuration>
<uses-library>
<uses-permission>
<uses-sdk>
이 태그들 중에서 <action>, <service>, <receiver>와 같은 태그들은 어플케이션 구성 요소를 등록하기 위해 사용됩니다.
<manifest ...> <application ...> ... <service android:name="com.study.doit" ...> ... </service> ... </applciation> </manifest>
어플리케이션을 의미하는 <application>
태그는 한 개만 있을 수 있습니다.
그 내부에 들어가는 다양한 구성 요소 태그는 여러 번 추가될 수 있습니다.
그중 메인 액티비티는 항상 다음과 같은 형태로 추가되어야 합니다.
인텐트 필터에 들어가는 정보는 <action>
태그의 경우 MAIN이 되어야 하고 <category>
태그의 경우 LAUNCHER가 되어야 합니다.
<activity android:name="com.study.doit" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <catregory android:name="android.intent.category.LAUNCHER" /> </intent-filter> </action>
리소스를 자바 코드와 분리하는 이유는 이해하기 쉽고 유지관리가 용이하기 때문입니다.
/res
폴더 이외에 /asset
폴더를 따로 만들 수 있는데 두 가지 모두 리소스라고 할 수 있으며
대부분은 /res
폴더 밑에서 관리됩니다.
/res/values
폴더에는 문자열이나 기타 기본 데이터 타입에 해당하는 정보들이 저장됩니다.
기본적으로 stings.xml 파일 안에 문자열을 저장합니다.
/res/drawable
폴더에는 이미지를 저장합니다.
저장되 있는 리소스 정보들은 Resources객체를 참조하여 리소스를 읽어들여야합니다.
Resources 객체는 Context.getResources()
메서드를 이용해 액티비티 안에서 언제든지 참조할 수 있습니다.
스타일과 테마는 여러가지 속성들을 한꺼번에 모아서 정의한 것 입니다.
버튼의 모양이나 대화상자의 모양들을 원하는대로 정의할 수 있는데 스타일을 직접 정의하고 싶으면
res/values/styles.xml
파일을 만들어야합니다.
다음은 styles.xml
안에 정의한 <style> 태그를 보여줍니다.
이렇게 각각의 요소별로 정의한 UI속성들을 android:style 속성을 이용하여 레이아웃에 적용할 수 있습니다.
<style name="Alert" parent="android:Theme.Dialog">
<item name="android:whindowBackground">@drawable/alertBackground</item>
</style>