본문 바로가기

안드로이드

라이브 폴더

라이브 폴더는 안드로이드 1.5(API 레벨3)에서 소개 되었고 어플리케이션을 실행하지 않고도 홈스크린에 데이터 소스를 디스플레이할수 있게 해준다. 라이브 폴더는 단순히 ContentProvider 의 실시간 view 이다. 라이브 폴더는 사용자 주소록이나 북마크, 이메일, 플레이리스트, RSS feed 등과 같은 것을 디스플레이하는데 사용될수 있다. 그 가능성은 끝이 없다!

플랫폼은 주소록을 디스플레이 하기 위한 몇개의 표준 폴더를 포함한다. 예를 들어 아래의 화면은 전화번호를 가지는 모든 주소록을 디스플레이하는 라이브 폴더의 내용이다.

사용자가 라이브 폴더를 브라우징하는 동안 백그라운드에서 주소록 동기화가 발생한다면 실시간으로 변경을 볼수 있을 것이다. 라이브 폴더는 유용할뿐 아니라 어플리케이션과 데이터에 추가하기도 쉽다. 본 글은 어떻게 라이브 폴더를 Shelves 샘플 어플리케이션에 추가하는 지를 보여준다. 어떻게 라이브 폴더가 동작하는지를 더 잘 이해하기 위해 어플리케이션의 소스 코드를 다운로드 해서 볼수 있고 아래의 내용에 따라 변경해 볼수 있다.

어플리케이션의 새로운 라이브 폴더를 작성하기 위해 옵션을 사용자에게 주기 위해 먼저 액션이 android.intent.action.CREATE_LIVE_FOLDER 인 intent filter를 갖는 새로운 activity를 작성할 필요가 있다. 단순히 AndroidManifest.xml파일을 열고 아래와 같은 내용을 추가한다.

<activity
android:name=".activity.BookShelfLiveFolder"
android:label="BookShelf">
<intent-filter>
<action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

이 activity의 라벨과 아이콘은 사용자가 생성하기 위한 라이브 폴더를 선택했을때 홈스크린에서 보게 되는 것이다.

intent filter가 필요하므로 기존의 activity를 재사용하는 것이 가능하며 그렇게 하는 것이 좋다. Shelves의 경우 새로운 activity인 org.curiouscreature.android.shelves.activity.BookShelfLiveFolder를 작성할 것이다. 이 activity의 역활은 intent 결과를 라이브 폴더의 내용(이름, 아이콘, 디스플레이 모드, content URI)을 가지고 있는 홈에 전달하는 것이다. content URI는 어떤 ContentProvider가 라이브 폴더를 표현하기 위해 사용될지를 기술하므로 매우 중요하다. activity의 코드는 아래와 같이 매우 단순하다.

public class BookShelfLiveFolder extends Activity {
public static final Uri CONTENT_URI = Uri.parse("content://shelves/live_folders/books");

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

final Intent intent = getIntent();
final String action = intent.getAction();

if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI,
"Books", R.drawable.ic_live_folder));
} else {
setResult(RESULT_CANCELED);
}

finish();
}

private static Intent createLiveFolder(Context context, Uri uri, String name, int icon) {
final Intent intent = new Intent();

intent.setData(uri);
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
Intent.ShortcutIconResource.fromContext(context, icon));
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);

return intent;
}
}

이 activity는 ACTION_CREATE_LIVE_FOLDER intent가 호출될때 content://shelves/live_folders/books URI의 intent와 라이브 폴더를 기술하는 3개의 extras를 리턴한다. 다른 extra와 상수값을 사용할수 있고 더 자세한 내용은 android.provider.LiveFolders의 문서를 참조할수 있다.  홈이 이 intent를 수신했을때 제공된 이름과 아이콘을 갖는 새로운 라이브 폴더가 사용자 데스크탑에 생성된다. 그리고 사용자가 라이브 폴더를 열기 위해 클릭했을 경우 홈은 제공된 URI를 참조로 content provider에게 쿼리를 던진다.

라이브 폴더의 content provider는 특정 이름 규칙을 반드시 준수해야한다. query()메서드에 의해 리턴되는 Cursor는 반드시 최소한 2개의 컬럼(_ID, LiveFolders.NAME)을 가져야 한다. _ID는 각 아이템을 구별하기 위한 유일한 식별자이고 LiveFolders.NAME은 아이템의 이름이다.  아이콘, 설명, 아이템과 관련된 intent(사용자가 아이템을 클릭할 경우 발생)등을 명시하기 위해 사용할수 있는 다른 컬럼 이름들이 있다. 더 자세한 내용은 android.provider.LiveFolders 문서를 참고하면 된다.

아래 예에서 구현해야할 것은 Shelves의 기존 org.curiouscreature.android.shelves.provider.BooksProvider 프로바이더를 변경하는 것이 전부다. 먼저 content://shelves/live_folders/books content URI를 식별하기 위해 URI_MATCHER를 변경할 필요가 있다.

private static final int LIVE_FOLDER_BOOKS = 4;
// ...
URI_MATCHER.addURI(AUTHORITY, "live_folders/books", LIVE_FOLDER_BOOKS);

그런 다음 커서를 위한 새로운 projection map을 작성할 필요가 있다. projection map은 컬럼이름을 변경하기 위해 사용될수 있다. BooksStore.Book._ID, BooksStore.Book.TITLE and BooksStore.Book.AUTHORS을 LiveFolders._ID, LiveFolders.TITLE, LiveFolders.DESCRIPTION로 변경할 것이다.

private static final HashMap<string, string=""> LIVE_FOLDER_PROJECTION_MAP;
static {
LIVE_FOLDER_PROJECTION_MAP = new HashMap<string, string="">();
LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders._ID, BooksStore.Book._ID +
" AS " + LiveFolders._ID);
LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.NAME, BooksStore.Book.TITLE +
" AS " + LiveFolders.NAME);
LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.DESCRIPTION, BooksStore.Book.AUTHORS +
" AS " + LiveFolders.DESCRIPTION);
}

각 열에 대한 제목과 설명을 제공하기 때문에 홈은 자동적으로 두줄의 텍스트를 갖는 라이브 폴더의 각 아이템을 디스플레이할 것이다. 마지막으로 projection map을 SQL쿼리 빌더에 제공하므로서 query()메서드를 구현한다.

public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {

SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

switch (URI_MATCHER.match(uri)) {
// ...
case LIVE_FOLDER_BOOKS:
qb.setTables("books");
qb.setProjectionMap(LIVE_FOLDER_PROJECTION_MAP);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}

SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, BooksStore.Book.DEFAULT_SORT_ORDER);
c.setNotificationUri(getContext().getContentResolver(), uri);

return c;
}

이제 컴파일하고 어플리케이션을 배포하고 홈 스크린에서 라이브 폴더를 추가해보자. books 라이브 폴더를 열어 보유하고 있는 모든 책(제목, 저자)의 목록이 여러줄 보일 것이다.

라이브 폴더 API는 매우 단순하고 intent와 content URI에만 의존한다. 라이브 폴더 구현의 더 많은 에제를 원한다면Contacts 어플리케이션 과 Contacts provider 의 소스코드를 보면 되고 

라이브 폴더가 있는 Shelves를 다운 받아 볼수도 있다.