하루 노트 2020
[Do it 개정7판] 서비스와 수신자 이해하기 본문
책: Do it 안드로이드 앱 프로그래밍 (개정 7판)
날짜: 20-04-08
내용: Chapter02-06
도구: 안드로이드 스튜디오
언어: 자바
환경: Windows10
Data parse는
들어온 데이터를 특정한 규칙에 따라 원하는 데이터로 변환하는 과정
06-1. 서비스
[1] 서비스
서비스란 화면 없이 백그라운드에서 실행되는 앱의 구성 요소를 말한다.
서비스는 오래 실행되는 작업을 위한 것으로 화면(앞단)에서 실행되는 것이 아니라 화면 뒤(뒷단)에서 실행된다.
서비스또한 앱의 구성 요소이므로 시스템에서 관리한다.
그래서 서비스를 새로 만들때 매니페스트파일에 등록해야 한다. ( 자동 등록됨 )
카카오톡앱의 경우 실행되어 있지 않거나 화면이 사용자에게 보이지 않는 상태에서도
다른 사람이 보낸 메시지를 받을 수 있다. ( 서비스 )
서비스를 실행하려면 메인 액티비티에서 startService( ) 메소드를 호출하면 된다.
서비스를 종료하고 싶을때는 stopService( ) 메소드를 호출한다.
서비스의 주요 역할 중 하나는 단말이 항상 실행되어 있는 상태로 다른 단말과 데이터를 주고받거나
필요한 기능을 백그라운드에서 실행하는 것이다.
그래서 서비스는 실행된 상태를 계속 유지하기 위해 서비스가 비정상적으로 종료되더라도
시스템이 자동으로 재실행한다.
startService( ) 메소드는 서비스를 시작하는 목적 이외에 인텐트를 전달하는 목적으로도 자주 사용된다.
액티비티에서 서비스로 데이터를 전달할려면 인텐트 객체를 만들고 부가데이터를 넣은 후
startService( ) 메소드를 호출하면서 전달하면 된다.
[2] 서비스 실습
1) 서비스(클래스) 만들기 ( MyService.class )
onBind( ) : 기본으로 있는 메소드 / 서비스가 서버 역할을 하면서 액티비티와 연결될 수 있도록 만드는 것
onCreate( ), onDestroy( ) : 서비스의 수명주기 파악을 위해 추가
onStartCommand( ) : 인텐트 객체를 전달받음 / 서비스의 가장 중요한 메소드
서비스는 시스템에 의해 자동으로 다시 시작될 수 있기 때문에
onStartCommand( ) 메소드로 전달되는 인텐트 객체가 null인 경우도 검사해야 한다.
만약 자동으로 재시작하지 않도록 만들고 싶다면 다른 상수를 사용할 수 있다.
ㅁ 로그 사용하기
로그 출력을 위해서는 첫 번째 파라미터로 로그를 구분할 수 있는 문자열을 전달해야 한다. ( 태그 Tag )
Thread.sleep( 5000 ) : 5초동안 기달림
ㅁ 플래그
서비스에서 startActivity( ) 메소드를 호출할 때는 새로운 태스크를 생성하도록
FLAG_ACTIVITY_TASK 플래그를 인텐트에 추가해야 한다.
서비스는 화면이 없기 때문에 화면이 없는 서비스에서 화면이 있는 액티비티를 띄우려면
새로운 테스크를 만들어야 하기 때문이다.
MainActivity 객체가 이미 메모리에 만들어져 있을 때 재사용하도록
FLAG_ACTIVIT_SINGLE_TOP과 FLAG_ACTIVITY_CLEAR_TOP 플래그도 인텐트에 추가한다.
2) 메인 액티비티 만들기 ( activity_main.xml )
3) 메인 자바 소스코드 작성하기 ( MainActivity.java )
버튼을 클릭하면 인텐트 객체에 command, name 을 부가데이터로 넣어
startService(intent) 서비스를 시작하며 전달한다.
( command는 서비스쪽으로 전달한 인텐트 객체의 데이터가 어떤 목적으로 사용되는지 구별하기 위해 넣은 것이다. )
startService( ) 메소드에 담은 인텐트 객체는 MyService 클래스의 onStartCommand( ) 메소드로 전달된다.
ㅁ 서비스로부터 인텐트 전달받기
getIntent( )메소드를 통해 자신을 호출한 곳으로부터 인텐트 값을 받아
processIntent( ) 메소드를 정의한 후 인텐트 값을 넘겨 처리한다.
ㅁ onNewIntent( intent )
액티비티가 새로 만들어지지 않고 재사용될 경우 메인 액티비티의 OnCreate( ) 메소드가 호출되지 않는다.
이 경우 재사용되는 액티비티에서는 onNewIntent( intent ) 메소드를 사용해 인텐트를 처리한다.
4) 실행화면
06-2. 브로드캐스트 수신자 이해하기
[1] 브로드 캐스트 수신자 이해하기
브로드캐스팅( Broadcasting ) : 메시지를 여러 객체에 전달하는 것
안드로이드는 여러 앱 구성 요소에 메시지를 전달할 때 브로드캐스팅을 사용한다.
( ex 문자를 받았을 때 이 문자를 SMS 수신 앱에 알려줘야 한다면 브로드캐스팅으로 전달하면 된다. )
내가 만든 앱에서 브로드캐스팅 메시지를 받고 싶다면
브로드캐스트 수신자( Broadcast Receiver )를 만들어 앱에등록하면 된다.
A앱으로부터 메시지를 받기 위해 내가 만든 앱에 브로드캐스트 수신자를 등록하면
A앱의 메시지가 내 앱으로 전달된다.
브로드캐스트 수신자도 앱 구성요소이다. ( 화면이 없다 )
따라서 새로운 브로드캐스트 수신자를 만들면 매니페스트 파일에 등록해야 시스템이 알 수 있다.
단, 브로드캐스트 수신자는 매니페스트 등록 방식이 아닌 소스 코드에서 registerReceiver( ) 메소드를
사용해 시스템에 등록할 수 있다. 소스 코드를 이용하여 브로드캐스트 수신자를 등록하면
액티비티 안에서 브로드캐스트 메시지를 전달받아 바로 다른 작업을 수행하도록 만들 수 있는 장점이 있다.
브로드캐스느 수신자에는 onReceive( ) 메소드를 정의해야 한다.
이 메소드는 원하는 브로드캐스트 메시지가 도착하면 자동으로 호출된다.
하지만 시스템의 모든 메시지를 받을 수는 없다. 만약 원하는 메시지만 받으려면
모든 메시지는 인텐트 안에 넣어 전달되므로 원하는 메시지는 인텐트 필터를 사용해 시스템에 등록하면 된다.
* 단말에서는 다른 사람으로부터 SMS 문자를 받았을 때 텔레포니( Telephony ) 모듈이 처리하도록 한다.
이렇게 처리된 정보는 인텐트에 담겨 브로드캐스팅 방식으로 다른 앱에 전달된다.
인텐트를 전달 받으면 onReceive( ) 메소드가 자동으로 호출된다.
( 매니페스트에 브로드캐스트 수신자가 등록되어있기 때문이다. )
* 브로드캐스트 수신자를 포함하고 있는 앱의 메인 액티비티가
적어도 한 번 실행되어야 브로드캐스트 수신자가 메시지를 받을 수 있다.
[2] 브로드 캐스트 수신자 실습
1) 브로드 캐스트 추가하기 ( SmsReceiver.java )
app - New - other - Broadcast Receiver
브로드 캐스트도 앱 구성요소이므로 매니페스트 파일에 자동으로 추가된다.
<intent-filter> : 어떤 인텐트를 받을 것인지를 지정
android.provider.Telephony.SMS_RECEIVED : SMS 메시지가 들어간 인텐트를 구분하기 위한 액션정보
( 단말에서 SMS를 수신했을을 때 해당 정보가 들어간 인텐트를 전달하므로 이 값을 넣어주면 SMS를 받아볼 수 있다. )
SMS를 받으면 onReceive( ) 메소드가 자동으로 호출된다.
그리고 파라미터로 전달되는 Intent 객체 안에 SMS 데이터가 들어있다.
인텐트 객체 안에 들어 있는 Bundle 객체를 getExtras( ) 메소드로 참조한다.
parseSmsMessage( ) 메소드는 SMS 데이터를 확인할 수 있도록
안드로이드 API에 정해둔 코드를 사용하므로 다른 앱에서 재사용할 수 있다.
Build.VERSION.SDK_INT : 단말의 OS 버전을 확인할 때 사용한다.
단말의 OS 버전에 따라 코드가 약간씩 달라져야 할 때 사용한다.
( Build.VERSION_CODES 에는 안드로이드 OS 버전별로 상수가 정의되어 있다. )
브로드캐스트 수신자는 화면이 없으므로 보여주려는 화면은 액티비티로 만든 후 그 화면을 띄워야한다.
따라서 브로드캐스트 수신자에서 인텐트 객체를 만들고
startActivity( ) 메소드를 사용해 액티비티 쪽으로 인텐트 객체를 전달해야 한다.
브로드캐스트 수신자는 화면이 없으므로 인텐트의 플래그로 FLAG_ACTIVITY_NEW_TASK를 추가해야 한다.
그리고 이미 SmsActivity가 있을 때 액티비티를 중복 생성하지 않도록 FLAG_ACTIVITY_SINGLE_TOP 플래그도 추가한다.
수신 시각의 경우 사용자가 알아보기 좋은 날짜 형태로 만들기 위해
SimpleDateFormat 클래스를 사용한다.
intent-filter : 어떤 인텐트가왔을때 우리가 원하는 것말 골라낸다.
리시버가 매니페스트에 등록되어있으면
해당 정보에 맞는 메시지가 날라오면 우리에게 전달해준다.
앱에서 SMS를 수신하려면 RECEIVE_SMS 라는 권한이 있어야 한다.
매니페스트 파일에서 해당 권한을 설정해야 한다. ( 권한 uses-permission )
RECEIVE_SMS 권한은 위험 권한으로 소스 파일에서 앱 실행 후 사용자가
권한을 부여할 수 있도록 별도의 코드가 추가되어야 한다. ( 아래서는 외부 라이브러리 사용 )
* 위험권한은 앱이 실행될때 사용자한테 한번 더 허락받아야 한다.
2) 메인 자바 소스코드 ( MainActivity.java )
위험 권한을 자동으로 부여하는 코드 ( AutoPermissionsListener 구현 )
onRequestPersmissionResult
우리가 위험권한을 요청하고 사용자가 승인 또는 거부를 했는지 알 수 있는 메소드
3) 수신화면 xml ( activity_sms.xml )
4) 수신 액티비티 자바 소스 코드 ( SmsReceiver.java )
onNewIntent( ) 메소드 : 액티비티가 이미 만들어져 있는 상태에서 전달받은 인텐트 처리
5) 실행화면
06-3. 위험 권한 부여하기
[1] 일반 권한 및 위험 권한
일반 권한 ( Normal Permission ) : 앱 설치 시점에 사용자로부터 권한을 부여 받음
위험 권한 ( Dangerous Permission ) : 앱 실행 시점에 사용자로부터 권한을 부여 받음
위험 권한의 예 : 위치, 카메라, 마이크, 연락처, 전화, 문자, 일정, 센서 등
위험 권한을 사용하는 앱은 앱이 실행될 때 권한을 부여해 달라는 대화상자를 사용자에게 띄운다.
위험 권한을 부여하려면 코드를 많이 입력해야 해서 외부 라이브러리를 사용하는 경우가 많다.
위험 권한을 부여하는 것은 앱이 실행 중이라면 언제든 가능하다.
액티비티가 메모리에 만들어지는 시점에 부여되도록 하려면 onCreate( ) 메소드 안에서 권한 부여 요청을 하지만
버튼이 눌렸을 때 권한이 부여되게 할 수도 있다.
[2] 기본 위험 권한 부여하는 방법 알아보기
SD카드를 접근할 때 사용되는 두 가지 위험 권한 부여해보기 ( 읽기, 쓰기 )
기본 권한을 부여할 때는 <uses-permission> 태그를 사용한다.
SD카드를 접근하는 권한은 위험 권한이므로 다음과 같이 코드를 추가로 입력해야 한다.
checkPermissions( ) 메소드는 정해준 권한들에 대해서 그 권한이 부여되어 있는지 확인한다.
그리고 권한이 부여되지 않았다면 ArrayList안에 넣었다가 부여되지 않은 권한들만 권한을 요청하게 된다.
checkSelfPermission( ) 메소드로 이미 권한이 부여되어 있는지 확인하도록 작성되었다.
만약 권한이 부여되지 않았다면 requestPermissions( ) 메소드를 호출하여 권한 부여 요청 대화상자를 띄운다.
이 대화상자는 requestPermissions( ) 메소드를 호출했을 때 시스템에서 띄워주기 때문에
사용자가 수락했는지 아니면 거부했는지의 여부를 콜백 메소드로 받아 확인하는 것이 필요하다.
이렇게 권한을 요청하면 콜백 메소드로 그 결과를 받을 수 있다.
onResultPermissionResult( ) 메소드에는 요청 코드와 함께 사용자가 권한을 수락했는지 여부가 파라미터로 전달된다.
여러 권한을 한 번에 요청할 수도 있으니 grantResults 배열 변수 안에 수락 여부를 넣어 전달한다.
위에서 위험 권한에 대한 수락을 요청할 때 두 개의 권한을 요청했으므로
grantResults 배열의 길이는 2이며 사용자가 권한을 수락했다면
PackageManager.PERMISSION_GRANTED 상수가 결과 값으로 반환된다.
위험권한이라고 하더라도 사용자가 한 번 수락하면 앱에 부여된 권한 정보를
단말에서 알고 있기 떄문에 앱을 다시 실행해도 대화상자는 더 이상 나타나지 않는다.
[3] 외부라이브러리를 사용해 위험권한 부여받기
아래 코드는 위험 권한을 자동으로 부여하는 코드이다.
매니페스트파일 안에 넣은 권한 중에서 위험 권한을 자동으로 체크한 후 권한 부여를 요청하는 방식이다.
onCreate( ) 메소드 안에서 loadAllPermissions( ) 메소드를 호출하면서 자동으로 권한을 부여하도록 요청한다.
그러면 권한 부여 요청 결과가 넘어오게 되는데 그 결과를 onRequestPermissionResult 메소드로 전달 받는다.
이 메소드 안에서는 parsePermissions( ) 메소드를 호출하는데 이 메소드를 호출하면
권한 부여 결과가 승인 또는 거부로 나뉘면서 onGranted( ) 도는 onDenied( ) 메소드가 호출된다.
06-4. 리소스와 매니페스트 이해하기
[1] 매니페스트
매니페스트는 설치된 앱의 구성 요소가 어떤 것인지,
그리고 어떤 권한이 부여되었는지 시스템에 알려주기 때문에 중요하다.
이 정보는 앱이 실행되기 전에 시스템이 알아야 할 내용들을 정의하고 있다.
( 앱이 설치되는 시점에 os에 우리 앱 정보를 알려준다 )
매니페스트의 주요 역할
- 앱의 패키지 이름 지정
- 앱 구성 요소에 대한 정보 등록 ( 액티비티, 서비스, 브로드캐스트 수신자, 내용제공자 )
- 각 구성 요소를 구현하는 클래스 이름 지정
- 앱이 가져야 하는 권한에 대한 정보 등록
- 다른 앱이 접근하기 위해 필요한 권한에 대한 정보 등록
- 앱 개발 과정에서 프로파일링을 위해 필요한 instrumentation 클래스 등록
- 앱에 필요한 안드로이드 API의 레벨 정보 등록
- 앱에서 사용하는 라이브러리 리스트
앱을 의미하는 <application> 태그는 매니페스트 안에 반드시 하나만 있어야 한다.
[2] 리소스
리소스를 자바 코드와 분리하는 이유는 이해하기 쉽고 유지관리가 용이하기 때문이다.
/app/res : 리소스는 빌드되어 설치 파일에 추가되지만 에셋은 빌드되지 않는다.
/app/assets : 에셋은 동영상이나 웹페이지와 같은 용량이 큰 데이터를 의미한다.
리소스가 갱신되면 그 때만다 리소스의 정보가 R.java 파일에 자동으로 기록되며
그 정보는 리소스에 대한 내부적인 포인터 정보가 된다.
리소스는 유형에 따라 정해진 폴더 안에 넣어야 한다.
이렇게 리소스가 유형 별로 서로 다른 폴더에서 관리되면
리소스 별로 구분하기 쉽고 유지관리가 편하다는 장점이 생긴다.
/app/res/values : 문자열이나 기타 기본 데이터 타입에 해당하는 정보들이 저장된다.
/app/res/drawable : 이미지를 저장한다.
ㅁ 스타일과 테마
스타일과 테마는 여러 가지 속성들을 한꺼번에 모아서 정의한 것으로
가장 대표적인 예로 대화상자를 들 수 있다.
06-5. 그래들 이해하기
안드로이드 앱을 실행하거나 앱 스토어에 올릴 때는
소스파일이나 리소스파일을 빌드하거나 배포하는 작업이 필요하다.
이때 사용되는 것이 그래들( Gradle )이다.
그래들은 안드로이드 스튜디오에서 사용하는 빌드 및 배포 도구인 것이다.
한 앱의 빌드 설정은 build.gradle 파일에 넣어 관리한다.
이때 그래들 파일은 프로젝트 수준과 모듈 수준으로 나눠 관리하기 때문에
새로운 프로젝트를 만들면 두 개의 build.gradle 파일이 생긴다.
1) 프로젝트 수준
2) 모듈 수준
applicationId : 앱의 id값 ( 앱은 id 값으로 구분되기 때문에 전 세계에서 유일한 값으로 설정되어야 한다. )
compileSdkVersion : 빌드를 진행할때 어떤 버전의 SDK를 사용할 것인지를 지정 ( 보통 최신 버전의 SDK를 지정 )
minSdkVersion : 이 앱이 어떤 하위 버전까지 지원하도록 할 것인지를 지정
targetSdkVersion : 이 앱이 검증된 버전이 어떤 SDK 버전인지를 지정
dependencies : 외부 라이브러리를 추가할 수 있다.
( 기본 설정을 사용하면 libs 폴더 안에 들어있는 jar 파일을 읽어 들이고 support 패키지를 추가한다. )
( 가장 마지막 줄에 implementation으로 시작하는 한 줄은 직접 추가한 외부 라이브러리를 의미한다. )
settings.gradle : 어떤 모듈을 포함할 것인지에 대한 정보가 들어 있다.
local.properties : 현재 사용하고 있는 PC에 설치된 SDK의 위치가 기록되어 있다.
gradle.properties : 메모리 설정이 들어있다.
gradle-wrapper.properties : 그래들 버전 정보 등이 들어있다.
다음과 같은 정보들은 안드로이드 스튜디오에서 자동 설정하는 경우가 많다.
[ 도전11. 서비스 실행하고 화면에 보여주기 ]
[ 도전12. 서비스에서 수신자로 메시지 보내기 ]
'프로그래밍 > 안드로이드' 카테고리의 다른 글
[Do it 개정7판] 선택 위젯 만들기 (0) | 2020.04.10 |
---|---|
[Do it 개정7판] 프래그먼트 이해하기 (0) | 2020.03.18 |
[Do it 개정7판] 여러 화면 간 전환하기 (1) | 2020.03.12 |
[Do it 개정7판]기본 위젯과 드로어블 사용하기 (0) | 2020.03.11 |
[Do it 개정7판] 레이아웃 익히기 (1) | 2020.03.10 |