티스토리 뷰

하루에 한 번 때 맞춰서 어떤 동작을 실행해야 한다. 근데, Tasker 라는 app 이 MIUI 에서는 동작을 제대로 하지 않는다.  ㅜ.ㅜ 그래서 어쩔 수 없이 AlarmManager 를 건드려 보기로 했다.

일단 기본적으로 android project 를 만드는 법은 아래 링크에서 배우자.

http://i5on9i.tistory.com/687

 

지금부터는 간단하게 start 버튼을 누르면 일정시간마다 특정동작이 작동하도록 하고, cancel 버튼을 누르면 멈추는 간단한 program을 만들어 보자. 이 프로그램에서는 2개의 .java 파일을 만든다.

  1. UI : 버튼 2개가 있는 View (AlarmTestActivity.java)
  2. BroadcastReceiver (AlarmReceiver.java)

 

소스코드 Source code

AlarmTest.zip



UI 만들기

아래 그림처럼 android XML 파일을 추가하자. (추가하지 않고, 기존에 존재하는 mail.xml 을 사용해도 괜찮다.)

res >> layout 를 클릭 >> ctrl+N >> Android XML Layout File

 

xml 을 더블 클릭하면 위와 같은 화면이 나온다. 여기서 Graphical Layout 으로 대충의 UI 를 만들어 놓고, main.xml 에서 편집을 하면 된다. Graphical Layout 을 이용해야 아래 보이는 R.java 의 값들이 자동으로 입력된다. 참고로 수정하고 나서 save 를 해야 R.java 에 적용이 된다.

 

이번 프로그램에서는 버튼 2개를 추가하기만 하면 UI 작업은 끝이다. 이후의 일들은 여타 GUI 프로그래밍처럼 button 을 누를 때의 함수를 listener에 attach 시키면 된다. 이건 보통 아래처럼 OnCreate() 함수에 작성한다.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    setContentView(R.layout.main);
    
    Button button = (Button)findViewById(R.id.setbutton);
    button.setOnClickListener(mRepeatingAlarmListener);
    button = (Button)findViewById(R.id.cancelbutton);
    button.setOnClickListener(mCancelAlarmListener);
    
}

 

Set alarm 시 실행할 함수

여기서 우리는 AlarmManager를 사용할 것이다. Ref. 4 를 참고하면, AlarmManager 이외에도 Handler를 사용할 수 있다는 것을 알 수 있다. 하지만 Handler는 app을 실행 해 놓고 있을 때만 가능한 방법이므로 여기서는 AlarmManager를 사용하는 것이다.

그리고 AlarmManager 가 일정하게 보내는 Message 를 처리하는 방법은 BroadcastReceiver를 사용할 것이다.

 

AlarmManager를 사용하는 방법은

  1. 어떤 녀석을 실행시킬 것인지에 대한 Intent 를 만든다. (왜 Intent 가 필요한 지에 대해서는 Ref. 2를 참고하자.)
  2. 이것을 PendingIntent 에 묶는다.
  3. AlarmManager를 불러온다.
  4. AlarmManager.setRepeating을 이용 해 반복설정을 한다.

 

@Override
public void onClick(View arg0) {
    // TODO Auto-generated method stub
    /**
     * 1. create an offset
     * 2. create your Intent
     * 3. create PendingIntent with made Intent
     * 4. set AlarmManager with pendingIntent and the time
     */
    
    ////////
    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.SECOND, 5);
    
    long firstTime = SystemClock.elapsedRealtime();
    firstTime += 1*1000; // add 1 second
    
    long interval = 10*1000; // 10 seconds //AlarmManager.INTERVAL_DAY;
    
    ////////
    // 2. Make your Intent
    // 
    // {@link:http://developer.android.com/reference/android/content
    // /Intent.html#Intent(android.content.Context, java.lang.Class<?>)}
    // intent to execute a hard-coded class name, e.g. AlarmService
    // make an intent of AlarmTestActivity.this for executing AlarmServcie.class
    
    Intent intent = new Intent(AlarmTestActivity.this, AlarmReceiver.class);
    pendingIntent = PendingIntent.getBroadcast(AlarmTestActivity.this,
            0, intent, 0);
    
    ////////
    AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
    am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    firstTime, interval, pendingIntent);
    
    Toast.makeText(AlarmTestActivity.this, "Start Alarm", Toast.LENGTH_LONG).show();
    

}

 

BroadcastReceiver 와 Service 의 차이

Ref 5, 6 을 통해 알 수 있지만, BroadcastReceiver 와 Service 는 약간의 차이가 있다. 간단하게 이야기하면, BroadcastReceiver 는 5초 이내의 짧은 동작을 실행할 때 좋다. 이 녀석은 짧지만 대신에 10초 이내의 동작을 실행하고 있는 도중에는 절대(?) 죽지 않는다. 하지만 Service 는 좀 더 장시간을 요하는 동작에 쓰이며, 이 녀석은 memory 가 부족한 경우에 죽었다가 다시 살려서 실행될 수도 있다. 그러니 여기서는 BroadcastReceiver 를 사용하도록 하자.

참고로, BroadcastReceiver 에서 Intent 를 만들고 startService() 를 해서 다른 서비스를 실행시킬 수 있다. 여기서 5초의 제한은 OnReceive() 의 실행시간을 5초 이내로 끝내야 하는 것이라서 startService() 같은 함수의 사용은 괜찮다고 한다. 아래 코드를 참고하자.

@Override public void onReceive(Context context, Intent intent) { // Get the lifeform details from the intent. Uri data = intent.getData(); String type = intent.getStringExtra("extra string data"); double lat = intent.getDoubleExtra("EXTRA_LAT", 0); double lng = intent.getDoubleExtra("EXTRA_LNG", 0); Location loc = new Location(“gps”); loc.setLatitude(lat); loc.setLongitude(lng); if (type.equals(“facehugger”)) { Intent startIntent = new Intent("com.pc.test", data); startIntent.putExtra("EXTRA_LAT", lat); startIntent.putExtra("EXTRA_LNG", lng); context.startService(startIntent); } }


 

BroadcastReceiver 를 사용하기 때문에 Intent를 보낼 때(PendingIntent)는 getBroadcast() 를 사용해서 instance 를 만들어야 한다.

 

Intent intent = new Intent(AlarmTestActivity.this, AlarmReceiver.class);
            
PendingIntent sender = PendingIntent.getBroadcast(AlarmTestActivity.this,
                    0, intent, 0);
 
 

AndroidManifest.xml 에 등록

그리고 중요한 것은 모든 Service 나 Receiver 는 반드시 AndroidManifest.xml 에 등록해야 한다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.alarmtest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />
    

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AlarmTestActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
<!--here is –->        
        <receiver android:name=".AlarmReceiver" android:process=":remote" />    
    </application>
    
    

</manifest>

 

Emulator에서 BroadcastReceiver 를 debugging 하고 싶다면 아래를 참고하자.

 

 

Cancel 버튼 클릭시 실행될 함수

이 부분은 간단하다. 단순히 소스코드만 봐도 쉽게 이해가 갈 듯 하다.

  1. AlarmManager를 불러오고,
  2. 해당 pendignIntent 를 cancel 시킨다.

 

@Override
public void onClick(View arg0) {
    // TODO Auto-generated method stub
    AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
    alarmManager.cancel(pendingIntent);

    //Tell the user about what we did.
    Toast.makeText(AlarmTestActivity.this, "Cancel!", Toast.LENGTH_LONG).show();

    
}

 

 

References

  1. http://android-er.blogspot.kr/2011/05/using-alarmmanager-to-start-scheduled.html
  2. android 에서 context 의 의미
    http://jungminjupiter.blogspot.kr/2011/02/android-context.html
  3. Android Service Tutorial, 2. Defining Services
    http://www.vogella.com/articles/AndroidServices/article.html
  4. Handler와 AlarmManager - 열 두번째 시간
    http://www.androidside.com/bbs/board.php?bo_table=B46&wr_id=301
  5. Broadcast Receiver와 Service의 차이
    http://jinsemin119.tistory.com/201
  6. Multitasking the Android Way
    http://android-developers.blogspot.kr/2010/04/multitasking-android-way.html
  7. 서비스 디버깅 하기(Attach debugger for service in Android)
    http://honorstudent.tistory.com/14


댓글
댓글쓰기 폼