항상 네트워크에 연결되어있지 않다는 가정으로, 앱의 아키텍처를 변경합니다.
앱을 실행시 로컬 DB의 데이터를 읽으며, 백그라운드 서비스에서 주기적으로 데이터를 긁어옵니다. (추후 gcm push로 변경합니다.)
데이터 삽입시 화면을 자동 갱신할려면? 어떠한 구조를 가져야 할까요?
그리고 view holder 패턴도 다룹니다.
27. Android Service
Service는 백그라운드에서 긴 기간동안 수행해야하는 연산을 하는 컴포넌트
사용자와 상호작용을 제공하지 않는 컴포넌트를 구현할때 사용
예) 네트워크 연산, 음악 재생, I/O 연산 수행, content provider와 상호작용 과 같은 모든 백그라운드 연산
28. Service의 두가지 형태
STARTED BOUND
Activity같은 Component에서
startService() 메서드를 통해 시작할때
Component에서 bindService()메서드를
통해 시작할때
• 백그라운드에서 실행되기 때문에 호출한
컴포넌트가 사라져도 실행됨
• caller에게 결과값을 리턴하지 않음
• 보통 한개의 연산을 수행할때 사용
• Client - Serivce 인터페이스 제공(send
request, get results, IPC)
• Bind 되어있을 동안 서비스가 계속 살아
있음. Bind 되어있는 서비스가 0개가 되
었을때 서비스가 죽음
29. Service의 두가지 형태
STARTED BOUND
Activity같은 Component에서
startService() 메서드를 통해 시작할때
우리는 STARTED만 다룸
Component에서 bindService()메서드를
통해 시작할때
• 백그라운드에서 실행되기 때문에 호출한
컴포넌트가 사라져도 실행됨
• caller에게 결과값을 리턴하지 않음
• 보통 한개의 연산을 수행할때 사용
• Client - Serivce 인터페이스 제공(send
request, get results, IPC)
• Bind 되어있을 동안 서비스가 계속 살아
있음. Bind 되어있는 서비스가 0개가 되
었을때 서비스가 죽음
30. Android Service 구현하기
1. Service를 상속받는 SyncDataService 클래스를 하나 생성합니다.
2. Service를 사용하기 위해 AndroidManifest.xml에 코드를 추가합니다.
3. Service를 위해 필요한 메서드를 구현합니다
33. Android Manifest 파일 수정
구조 예시
Service 클래스를 상속받은 SyncDataService를 등록
• Android에서 Service를 사용하기 위해선 AndroidManifest.xml 파일에 등록을 해주어야 합니다.
• application 태그 안에 넣어야 합니다.
35. 구현해야할 메서드 추가
SyncDataService에서 코드를 Override 합니다
• onCreate() : Service가 생성되었을 때 실행.
• onDestroy() : Service가 종료되었을 때 실행.
• onStartCommand() : 다른 컴포넌트에서
startService를 통해 시작했을때 실행.
36. 구현해야할 메서드 추가
SyncDataService에서 코드를 Override 합니다
• onCreate() : Service가 생성되었을 때 실행.
• onDestroy() : Service가 종료되었을 때 실행.
• onStartCommand() : 다른 컴포넌트에서
startService를 통해 시작했을때 실행.
앞으로 이 3개의 메서드를 구현함으로써 기능을 완성시키겠습니다.
42. Article을 주기적으로 가져오자(2)
Timer의 메서드
…http://developer.android.com/reference/java/util/Timer.html
• schedule 메서드는 TimerTask (원하는 작업), 시작하기 원하는 때, 주기를 인자로 받아
작업을 수행합니다.
• 본 예제에선 schedule(TimerTask task, long delay, long period)를 활용하겠습니다.
49. Service에서 Article 저장하기(3)
SyncDataService.java
Proxy와 Dao에게 Application Context를 넘겨주고 생성합니다.
Proxy와 Dao 클래스 내부에서 Application Context가 필요한 메서드가 있었습니다.
50. Service에서 Article 저장하기(3)
SyncDataService.java
Proxy.getJson()
TimerTask의 run() 메서드 안에 를 추가해 줍니다.
Dao.insertJsonD
ata()
65. Activity
Dao
database
다른앱에 우리의
데이터를 제공하고 싶다면?
데이터가 저장되었을때 화면을
자동으로 재갱신하고 싶다면?
데이터를 핸들링하는
템플릿을 유지하고 싶다면?
66. Content Provider의 역할
• 데이터 집합에 접근
• Data를 캡슐화 하고, Data의 보안을 위한 메커니즘을 제공
• 한 프로세스안의 데이터에 다른 프로세스가 접근하기 위한 표준 인터페이스
67. Content Provider
Content Provider를 사용하기 위해 알아야할 클래스들
(1). ContentProvider
(2). ContentResolver
(3). Cursor
(4). Uri
Database에 접근
ContentProvider에 접근 Application이 데이터를 쉽게 핸들링
Resolver를 통해 얻어온 데이터를 조회
컨텐츠를 구분할 수 있는 식별자
전화번호부, DB.. 등등
68. Content Provider
동작 방식
Application ContentResolver
ContentProvider
DataBase
Application
1
URI
Application이 자신의 Resolver에게 데이터를 요청
69. Content Provider
Application ContentResolver
ContentProvider
DataBase
Application
ContentResolver가 URI에 적합한 어플리케이션의
ContentProvider를 찾아 데이터 요청
2
URI
동작 방식
70. Content Provider
Application ContentResolver
ContentProvider
DataBase
Application
ContentProvider는 Resolver가 요청한 데이터를
Database에서 찾음
3
URI
동작 방식
71. Content Provider
Application ContentResolver
ContentProvider
DataBase
Application
Cursor
4
ContentProvider가 Resolver에게 데이터를 반환하고
Resolver는 데이터를 요청한 Application에게 Cursor 객체로
데이터를 반환
동작 방식
72. Content Provider 특징
URI
Application ContentResolver
ContentProvider
DataBase
Application
Cursor
1. ContentResolver 객체는 Provider 객체와 동일한 메서드를 갖는다.
ContentResolver.query() 메서드는 ContentProvider.query()의 메서드를 호출
2. ContentResolver 객체는 Create, Retrieve, Update, Delete (CRUD)를 제공함
73. Content Provider 학습순서
URI
Application ContentResolver
ContentProvider
DataBase
Application
Cursor
1. Application에서 Content Resolver를 사용하는방법
ContentResolver를 통해 ContentProvider에 접근할 수 있어야 한다
74. Content Provider 학습순서
URI
Application ContentResolver
ContentProvider
DataBase
Application
Cursor
2. Content Provider를 제작하는 방법
Custom Content Provider를 만들어 다른 어플리케이션에 인터페이스를 제공할 수 있어야 한다
76. ContentResolver의 메서드
ContentProvider
query() Provider를 통해 데이터를 전달받기 위한 함수 (Cursor 반환)
insert() Provider를 통해 데이터를 삽입함. (새로 삽입된 row의 URI를 반환)
update() Provider를 통해 데이터를 업데이트함. (업데이트된 로우의 개수를 반환)
delete() Provider를 통해 데이터를 삭제함. (삭제된 로우의 개수를 반환)
…. (더 있지만 우선 위의것이 기본)
77. ContentResolver의 메서드
ContentProvider
query() Provider를 통해 데이터를 전달받기 위한 함수 (Cursor 반환)
insert() Provider를 통해 데이터를 삽입함. (새로 삽입된 row의 URI를 반환)
update() Provider를 통해 데이터를 업데이트함. (업데이트된 로우의 개수를 반
환)
query()를 먼저 알아봄으로써
Content URI, Cursor 등 필요한
개념에 대해서 알아 봅시다.
delete() Provider를 통해 데이터를 삭제함. (삭제된 로우의 개수를 반환)
…. (더 있지만 우선 위의것이 기본)
78. 百聞不如一見
연락처를 받아오는 App을 만들자
Android 는 사용자 핸드폰에 저장된 연락처에 접근할 수 있는
Content Provider 를 이미 제공하고 있습니다.
따라서 우리는 그 연락처 Provider에 접근하는 Resolver 를 만들어
1. Application에서 Content Resolver를 사용하는방법
ContentResolver를 통해 ContentProvider에 접근할 수 있어야 한다
위의 퀘스트를 달성하겠습니다.
연락처 Provider : http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html
80. 만들 메서드 2개!
1. Cursor getContactCursor ()
ContentResolver를 통해 연락처 Provider에 데이터를 요청한 후
데이터 Cursor를 반환하는 메서드
2. void printLogContactData (Cursor contactData)
contentProvider로 부터 Cursor형태로 넘어온 데이터를 Log에 출력하는 메서드
81. 만들 메서드 2개!
1. Cursor getContactCursor ()
ContentResolver를 통해 연락처 Provider에 데이터를 요청한 후
데이터 Cursor를 반환하는 메서드
2. void printLogContactData (Cursor contactData)
contentProvider로 부터 Cursor형태로 넘어온 데이터를 Log에 출력하는 메서드 Cursor는 뭔데?
93. Cursor란 무엇일까요?
DB
Application
Cursor
Data
Cursor 객체를 통해
데이터를 사용하자
Cursor에 대한 더 자세한 정보 : http://developer.android.com/reference/android/database/Cursor.html
95. getContactCursor 구현(1)
ContentResolver를 통해 연락처 Provider에 데이터를 요청한 후, 데이터 Cursor를 반환하는 메서드
함수를 작성합니다.
Mac기준 : command + shift + o 를 눌러 Import하지 않은 클래스를 Import
96. getContactCursor 구현(2)
ContentResolver를 통해 연락처 Provider에 데이터를 요청한 후, 데이터 Cursor를 반환하는 메서드
Uri contactURI 는 Provider의 데이터를 식별하기 위한 URI 입니다.
ContactsContract.Contacts.CONTENT_URI 는 연락처 정보 테이블의 위치를 의미합니다.
99. getContactCursor 구현(4)
ContentResolver를 통해 연락처 Provider에 데이터를 요청한 후, 데이터 Cursor를 반환하는 메서드
getContentResolver() 를 통해 Resolver 객체를 획득한 후
query() 메서드를 사용합니다.
SQL query 와 비교해서 좀 더 자세히 설명하겠습니다.
100. getContactCursor 구현(4)
ContentResolver를 통해 연락처 Provider에 데이터를 요청한 후, 데이터 Cursor를 반환하는 메서드
query() 인자값 SELECT 비고
Uri FROM table_name Uri 는 provider의 테이블에 접근하는 정보
projection col, col, col, … 반환받길 원하는 col을 서술한다.
selection
WHERE col = value
WHERE 뒤에 오는 문장을 표현한다.
변수는 ? 로서 표현
selectionArgs selection의 ?에 매칭되어 값이 전달된다
sortOrder Order By col, col… sortOrder 에 따라서 Cursor가 정렬되어
반환됨
101. getContactCursor 구현(5)
ContentResolver를 통해 연락처 Provider에 데이터를 요청한 후, 데이터 Cursor를 반환하는 메서드
null일 경우 연결 실패
.query(contactURI, projection, null, null, Contacts.DISPLAY_NAME+” asc”);
SELECT _ID, display_name FROM contacts ORDER BY display_name ASC;
102. 만들 메서드 2개!
1. Cursor getContactCursor ()
ContentResolver를 통해 연락처 Provider에 데이터를 요청한 후
데이터 Cursor를 반환하는 메서드
2. void printLogContactData (Cursor contactData)
contentProvider로 부터 Cursor형태로 넘어온 데이터를 Log에 출력하는 메서드
111. 1. Cursor getContactCursor ()
2. void printLogContactData (Cursor contactData)
메서드를 만들어 봄으로써
1. Application에서 Content Resolver를 사용하는방법
ContentResolver를 통해 ContentProvider에 접근할 수 있어야 한다
을 학습했습니다
112. Content Provider 만들어 보기
Custom Content Provider를 만들어 다른 어플리케이션에 인터페이스를 제공할 수 있어야 한다
113. Content Provider를 만들기 전에
• Content Provider가 정말 필요한지 생각해보자
필요한 경우
1. 다른 어플리케이션에게 복잡한 데이터, file을 제공하길 원한다면.
2. 사용자가 당신의 앱에서 다른 앱으로 복잡한 데이터를 복사하길 원한다면.
3. Search Framework를 사용해서 custom search를 제공하길 원한다면.
• 이미 제공하는 Provider가 있을경우 굳이 만들지 말자
Calendar, Contacts 같이 이미 제공하는 Provider들을 찾아보자
114. Content Provider 만들기 순서
• NextgramProvider를 만들자.
• Dao를 분리하기
• Contract Class 만들기
• Content Provider 상속구현하기
115. • Dao를 분리하기
현재 있는 Dao.java를 복사해 ProviderDao.java를 만듭니다.
121. • Dao를 분리하기
NextgramProvider 에게 필요한 기능을 ProviderDao로부터 복사해옵니다.
Database와 통신하기 위한
• sqLiteInitialize
• tableCreate
• isTableExist
NextgramProvider.java
122. • Dao를 분리하기
NextgramProvider.java
NextgramProvider 에게 필요한 변수를 생성해 줍니다.
124. • Contract Class 만들기
• Contract class는 Content Provider에서 필요한 상수값을 지정해두는 클래스입니다.
• 외부의 어플리케이션에서 Provider를 사용하기 위해 필요한 값들이 지정되어 있습니다.
연락처 Provider의 Contract class 사용 예제
125. • Contract Class 만들기
NextgramContract 라는 public final class 를 만들어 줍시다
126. • Contract Class 만들기
NextgramContract.java
NextgramContract 에 AUTHORITY, CONTENT_URI에 대한 정보를 입력합니다.
128. Content URI를 디자인하자
• Content URI는 provider안의 데이터를 식별하는 URI이다.
• Provider의 이름을 의미하는 Authority와 테이블이나 파일을 의미하는
Path로 구성되어 있다.
Content URI
Authority + Path
129. Content URI를 디자인하자
Authority는 다른 프로바이더와 충돌을 피하기 위해 “Android 패키지 이름 + 앱이름” 을 추천한다
Content URI
Authority + Path
org.nhnnext.nextgram.provider/table1
예시 :
130. Content URI를 디자인하자
Content URI 패턴
content://org.nhnnext.nextgram.provider/table1
content://org.nhnnext.nextgram.provider/table2/dataset1
content://org.nhnnext.nextgram.provider/table2/dataset2
content://org.nhnnext.nextgram.provider/table3
table1을 요청.
dataset1이라 불리는 table을 요청
dataset2라 불리는 table을 요청
table3을 요청함.
URI를 통해 테이블에 접근
URI를 통해 각 열에 접근
content://org.nhnnext.nextgram.provider/table1/1 table1을 요청.
테이블 URI : content://authority/path
한 열의 URI : content://authority/path/id
#은 모든 숫자에 매칭
*은 모든 숫자, 문자에 매칭
131. • Contract Class 만들기
NextgramContract.java
Inner class로 BaseColumns를 상속받은 Articles 클래스를 작성합니다.
132. • Contract Class 만들기
NextgramContract.java
테이블의 컬럼속성인 _ID, TITLE, WRITER, ID, CONTENT, WRITER_DATE, IMAGE_NAME와
매치되는 변수를 선언합니다.
133. • Contract Class 만들기
NextgramContract.java
Articles 테이블의 아이템에 연결되는 CONTENT_URI를 작성합니다.
134. • Contract Class 만들기
NextgramContract.java
PROJECTION_ALL에 대한 정보를 작성해 둡니다.
135. • Contract Class 만들기
NextgramContract.java
기본적인 정렬은 _ID를 기준으로 하도록 합니다.
136. • Contract Class 만들기
이렇게 만들어진 Contract Class는 Provider에 접근하기 위한 API라고
생각하면 편합니다.
다음으론 NextgramProvider의
onCreate
query
getType
insert
delete
update
137. • Contract Class 만들기
이렇게 만들어진 Contract Class는 Provider에 접근하기 위한 API라고
생각하면 편합니다.
다음으론 NextgramProvider의
onCreate
query
getType
insert
delete
update
MIME TYPE을 지원하지 않음.
아직 기능이 없음
아직 기능이 없음
138. • Contract Class 만들기
이렇게 만들어진 Contract Class는 Provider에 접근하기 위한 API라고
생각하면 편합니다.
다음으론 NextgramProvider의
onCreate
query
insert
를 구현하겠습니다.
139. • Content Provider 상속구현하기
Android Manifest 파일안에
manifest 안에 위의 퍼미션과
Provider가 지정되어야 합니다.
140. • Content Provider 상속구현하기
NextgramProvider.java
query, insert에서 사용할 URI정보를 관리할 Uri Matcher 객체를 생성합니다.
141. • Content Provider 상속구현하기
NextgramContract.java
Resolver를 통해 요청이 들어올때
“org.nhnnext.nextgram.provider/Articles”는 1 (ARTICLE_LIST) 처리
“org.nhnnext.nextgram.provider/Articles/#”는 2 (ARTICLE_ID) 처리
160. • Content Provider 상속구현하기
기존 Dao.java에서는 database에 직접 insert하는 쿼리에
컬럼의 값들을 직접 붙여 날리는 방법을 사용했습니다.
하지만 ContentResolver를 이용하면 database에 직접 접근할
수 없으므로 컬럼 값들을 ContentValues에 담아 전달해야 합니다.
200. ViewHolder Pattern
기존의 HomeViewAdapter.java의 getView()
Adapter를 갱신할때마다 findViewById()를 사용해 성능이 저하되는것을
막기 위해 ViewHolder Pattern을 사용하도록 하겠습니다.
View객체를 재사용하기 위한 목적