http://duzi077.tistory.com/12
목차
1. Service에 대해 알아보기
2. BroadcastReciever에 대해 알아보기
3. 개발 방법
결과물
1. Service와 Broadcast 에 대한 이해 및 적용 방법
2. 프로젝트 코드
1. Service
서비스는 쉽게 말하면 메인스레드에서 동작하는 UI가 없는 액티비티이다.
UI가 없으므로 라이프사이클은 다음과 같이 동작한다.
onCreate() -> onStart() -> onDestory()
메인스레드에서 관리하기 때문에 UI가 종료되어도 살아서 서비스를 계속한다.
2. BroadcastReceiver
핸드폰에서 발생하는 특정 intent 신호를 받아주는 클래스이다.
// registerReceiver 메소드를 호출해 동적으로 리시버를 등록할 수 있고, AndroidManifest에 receiver를 정적으로 등록할 수 있다.
You can either dynamically register an instance of this class with Context.registerReceiver()
or statically publish an implementation through the <receiver>
tag in your AndroidManifest.xml
.
// onResume 하면서 리시버를 등록하려면 onPause에서 레지스트를 해제해야 불필요한 시스템 오버헤드를 없앨 수 있다.
Note: If registering a receiver in your Activity.onResume()
implementation, you should unregister it in Activity.onPause()
. (You won't receive intents when paused, and this will cut down on unnecessary system overhead). Do not unregister in Activity.onSaveInstanceState()
, because this won't be called if the user moves back in the history stack.
3. 개발방법
프로젝트 기능 :
1) 재부팅 시 부팅 완료 메시지 받기 ( 정적으로 Manifest에 등록)
2) 화면 켤 때 화면 켜짐 메시지 받기 ( 동적으로 리시버 등록)
1. Manifest의 receiver 컴포넌트에 BOOT_COMPLETED 필터 정적으로 등록
1 2 3 4 5 6 7 8 9 10 | <receiver android:name=".OnLock_BroadcastReceiver" android:enabled="true" android:exported="false" android:label="OnLock_BroadcastReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> | cs |
apk 파일이 설치되면서 자동으로 운영체제 브로드캐스트 관리하는 곳에
내 앱은 부팅 완료 메세지를 받겠다고 알려놓기 때문에
재부팅후에 내 앱의 OnLock_BroadcastReceiver의 onReceive() 에서 부팅 완료 인텐트를 받게된다.
2. 재부팅 후 OS는 부팅 완료 메세지를 브로드캐스팅으로 보내주고
내 앱은 Activty를 실행 안하고도 내 앱 내의 브로드캐스트 클래스의 OnReceive 메소드를 호출시키면서 인텐트를 받는다
인텐트의 종류가 Intent.ACTION_BOOT_COMPLETED 이므로 그 아래 서비스를 실행 시킨다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class OnLock_BroadcastReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { Toast.makeText(context, "SCREEN_ON", Toast.LENGTH_SHORT).show(); } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { Toast.makeText(context, "SCREEN_OFF", Toast.LENGTH_SHORT).show(); } else if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { Toast.makeText(context, "BOOT_COMPLETED", Toast.LENGTH_SHORT).show(); Intent i = new Intent(context, OnLock_Service.class); context.startService(i); } } } | cs |
단말기 환경 설정에서 다음과 같이 서비스가 켜짐을 확인 할 수 있다.
3. 서비스에서 인텐트 필터를 만들고 스크린 ON, OFF 를 추가한 후
동적으로 리시버를 등록한다.
순서는 onCreate -> onStartCommand 로 진행되고 onStartCommand의 리턴값은 종류는 다음과 같다
메모리 공간 부족으로 서비스가 종료되었을 때, 다음 세가지 플래그에 따라 서비스는 재 실행 또는 생성을 결정 한다.
1) START_STICKY : 재생성과 onStartCommand() 호출(with null intent)
2) START_NOT_STICKY : 서비스 재 실행하지 않음
3) START_REDELIVER_INTENT : 재생성과 onStartCommand() 호출(with same intent)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class OnLock_Service extends Service{ private BroadcastReceiver mReceiver; @Override public void onCreate() { super.onCreate(); IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); mReceiver = new OnLock_BroadcastReceiver(); registerReceiver(mReceiver, filter); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if( intent == null) { IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); mReceiver = new OnLock_BroadcastReceiver(); registerReceiver(mReceiver, filter); } return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(mReceiver); } @Override public IBinder onBind(Intent intent) { return null; } } | cs |
4. 서비스가 중단 되기 전 까지 동적으로 만들어진 스크린 ON,OFF 리시버는 계속 동작하게 된다.
5. 메니페스트에 다음과 같은 태그도 추가 해야한다
1 | <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> | cs |
1 2 3 4 5 6 7 8 9 10 11 | <service android:name=".OnLock_Service" ></service> <receiver android:name=".OnLock_BroadcastReceiver" android:enabled="true" android:exported="false" android:label="OnLock_BroadcastReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> | cs |
6. 처음 앱을 설치하고 앱이 실행될 때와 사용자가 별도로 앱을 실행 할 때
액티비티화면 없이 실행시키는 방법
1 2 3 4 5 | <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.Black.NoTitleBar" > | cs |
android:theme="@android:style/Theme.Black.NoTitleBar" 테마를 변경해준다
1 2 3 4 5 6 7 8 9 | @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Toast.makeText(MainActivity.this, "APK install Success.. ", Toast.LENGTH_SHORT).show(); finish(); } | cs |
메인 액티비티에서 Toast를 하나 띄워주고 finish()로 앱을 종료시킨다.
정적으로 리시버를 설정해놓았기 때문에 메인 액티비티에 별도의 코드를 안 넣어도
재부팅 후 정상적으로 브로드캐스트 리시버가 동작한다.