2014년 8월 6일 수요일

[Android] 안드로이드 위젯 만들기

Application Widget이란 화면에 직접 올릴 수 있는 작은 Application을 말합니다..

다른 것들은 presentaion logic을 activity가 담당하지만,
application Widget의 최상위 클래스는 broadcast reciever입니다..

application Widget을 만들기 위해 아래와 같은 순서를 거쳐야 합니다..

0. Manifest 파일에 Widget을 등록
1. Widget의 메타 데이터 기술
   - layout, update 주기, provider class에 대한 정보를 xml로 기술
2. View layout
   - widget의 화면 구성을 xml로 구성
3. AppWidgetProvider
   - Widget의 Update, Delete, Enable, Disable 등 실제 Action을 처리

widget의 update는 매우 중요합니다..
widget의 update는 broadcast receiver가 주기적으로 호출해줍니다..
바탕화면 widget이 한 화면에 16개가 들어갈 수 있는데, 그런 바탕화면을 7개까지 만들 수가 있습니다..
즉, 최대 16*7 = 112개까지 만들 수 있기 때문에
100개가 넘는 widget이 refresh가 된다면 폰이 감당하지 못할 것입니다..
따라서, 2.대 버전이 되면서 바탕화면의 refresh 주기를 30분으로 하였습니다..
(1.대에서는 1초까지 가능)
update 주기는 최소 30분으로 해야하며, 그 이하의 시간은 시스템에서 무시를 합니다..
그래서 개발자들은 보통 refresh 주기를 최대로 늘린 다음에,
그 안에서 thread를 생성하여 임의로 update 주기를 조절합니다.. ^^;;

자, 그럼 자세한 설명은 다른 데서 다시 확인하시고~ ^^;;
예제를 보여드리도록 하겠습니다..

예제는 바탕화면에 텍스트 시계를 띄우는 것이며,  예제 순서는 아래와 같습니다..
1. Activity 없는 project 생성
2. AndroidManifest.xml 파일에 widget 등록
3. Widget xml 생성
4. layout 구성
5. 시계 설정

그럼, 아래와 같이 Activity가 없는 Project를 생성합니다..


그리고 AndroidManifest.xml파일을 열어서 Widget을 등록합니다..
AndroidManifest.xml 파일을 열면 아래와 같은 뭔가 허전한(?) 것을 보시게 됩니다..


여기에 아래와 같이 입력합니다..


이건 제가 다 코딩후 캡쳐한 것이라서 에러가 나타나지 않는데
MyWidget class가 없다는 에러와 xml 폴더에 mywidget_provider 없다는 에러가 나타날 것입니다..
이건 아래에서 만들 것이기 때문에, 여기서는 그냥 넘어갑니다..

자, 그럼 res 폴더 아래에 xml 폴더 신규 생성 후, mywidget_provider.xml 파일을 만들겠습니다..
- res 오른쪽 클릭 -> new -> folder 하여 xml 폴더 생성
- xml 폴더 오른쪽 클릭 -> new -> Other



이제 mywidget_provider.xml 파일을 아래와 같이 작성합니다..
여기서도 layout에 mywidget이 없다는 에러가 나타나지만, 아래에서 만들 것이기에 그냥 넘어갑니다..
그럼, layout에 자동적으로 만들어져 있는 main.xml 파일의 이름을 mywidget.xml로 수정하겠습니다..
main.xml 오른쪽 클릭 -> refactor -> rename
파일 이름을 수정한 후에, 아래와 같이 작성합니다..


widget의 바탕화면(android:background)과 글자색(textColor)를 설정하고
시간을 나타낼 textView를 선언합니다..

자, 이젠 MyWidget class를 만들겠습니다..
MyWidget Class는 아래와 같이 android.appwidget.AppWidgetProvider를 상속해서 생성합니다..
Superclass는 직접 입력하셔도 되고, browser를 클릭하셔서 찾으셔도 됩니다..

아래와 같이 코딩을 합니다..



package com.djship.blog.My_Widget;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.widget.RemoteViews;
public class MyWidget extends AppWidgetProvider {
 Timer timer;
 MyTime myTime;
 RemoteViews remoteViews;
 
 @Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager,
   int[] appWidgetIds) {
  // TODO Auto-generated method stub
  
  remoteViews = new RemoteViews(context.getPackageName(), R.layout.mywidget) ;
  
  myTime = new MyTime(appWidgetManager, appWidgetIds) ;
  timer = new Timer();
  timer.scheduleAtFixedRate(myTime, 1, 10000) ;
  super.onUpdate(context, appWidgetManager, appWidgetIds);
 }
 private class MyTime extends TimerTask
 {
  AppWidgetManager appWidgetManager;
  int[] appWidgetIds;
  
  Calendar cal;
  String now;
  
  public MyTime(AppWidgetManager awm, int[] appids)
  {
   this.appWidgetManager = awm;
   this.appWidgetIds = appids;
  }
  @Override
  public void run() 
  {
   // TODO Auto-generated method stub
   cal = Calendar.getInstance() ;
   now = String.valueOf(cal.get(Calendar.HOUR_OF_DAY)) + ":" +
      String.valueOf(cal.get(Calendar.MINUTE));
   remoteViews.setTextViewText(R.id.textView, now) ;
   appWidgetManager.updateAppWidget(appWidgetIds, remoteViews) ;
  }  
 }
}

자, 이제 모든 작업은 끝났습니다..
이제 AVD를 실행시키신 후, Run As -> Android application을 하시기 바랍니다..
그럼, 아래와 같이 log가 생성되며, Done이 나타났다면 AVD에 정상적으로 올라간 것입니다..
이제 AVD 바탕화면에서 클릭을 길게 하면 아래와 같은 창이 뜨고,

여기서 Widget 선택 후, MyWidget을 선택하면




위와 같이 바탕화면에 Widget이 나타납니다.. ^^

댓글 없음:

댓글 쓰기