woong's
Android 죽지 않는 서비스 사용하기 본문
Android 죽지 않는 서비스 사용하기
이번에 사용할 기회가 생겨서 android 죽지 않는 서비스 를 구성해 보았습니다.
하루 꼬박 걸려서 구성했네요 .ㅜ
여러 블로그 살펴보니 많은 시행착오를 겪는 분들이 많으신 것 같습니다.
중간에 2% 부족하게 완성하신 분도 계신것 같습니다.
저 또하 많은 시행착오를 겪고 마무리를 지었습니다.
이 방법이 사용자에 악용되지 않았으면 합니다.
서비스가 죽지 말아야 할 경우
1. 앱을 종료 했을 때
2. 폰을 재시작 했을 때
3. Task Kill 을 했을 때
이 세 가지 부분을 막아야 이모탈 서비스를 구성 할 수 있습니다.
1. 앱을 종료 했을 때
- 기본 서비스를 사용 하면 막을 수 있습니다.
2. 폰을 재시작 했을 때
- 폰 재시작시 이벤트를 받아서 서비스 재시작
3. Task Kill 을 했을 때
- startForeground 를 통해서 서비스를 죽지 않게 함.
기본 구성
서비스를 실행 시키고 , 서비스가 종료 될 시 알람 매니져를 통해서 서비스를 예약 합니다.
이와 같이 하면 서비스를 종료 해도 알람매니져에서 이벤트를 발생 시켜서 서비스가 다시 살아 나게 됩니다.
시행착오 및 문제점
1. 앱을 종료후에 Task kill 을 하면 onDestroy 가 타서 다시 알람 매니져를 등록해서 서비스를 실행
-onDestroy 가 호출되는 시점이 불분명 합니다. 빠를때도 있고 10분이 걸릴때도 있습니다.
이렇게 구성이 되면 카카오톡으로 예를 들면 메세지를 앱을 키기 전까지는
onDestroy가 타기 전까지는 받을수 없게 될것 입니다.
2. startForeground 를 사용합니다.
-startForeground 를 이용하면 task kill 을 해도 서비스가 죽지 않고 잘 작동되지만 , 아이스크림 버전 이상 부터
notification 을 보여 주어야 한다.
아이스크림 이하버전 에서는 Notification 을 안나타나게 할 수 있습니다.
4.3 버전에서는 항시 명시 될수 있도록 구성이 되어 있습니다.
구성을 하지 않으면 서비스가 실행이 되지 않거나 에러가 나타 나는 경우 입니다.
notification을 보여주자니 한구석이 찜찜합니다.
저도 계속 시도 해보고 자료를 찾아보았지만 해결을 하지 못했었습니다. 카카오톡을 살펴보니 카카오톡은
위 조건을 다 만족하면서 notification 이 나타나지 않습니다. 무엇인가 방법은 있는데 찾지 못하고 있다는 생각이
들어 좀더 찾아보다가 해결 방법을 찾게 되었습니다.
해결 방법
startForeground 를 이용하여 Task kill 을 하더라고 서비스를 죽이 않게 구성 합니다.
이제 문제점은 notification을 보여주어야 되는 문제점이 있습니다.
startForeground 를 실행하는 동시에 notification 이 생겨 납니다.
이 notification 을 가져와서 cancel 시키는 방법 입니다.
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 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(1,new Notification()); NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); Notification notification; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ notification = new Notification.Builder(getApplicationContext()) .setContentTitle("") .setContentText("") .build(); }else{ notification = new Notification(0, "", System.currentTimeMillis()); notification.setLatestEventInfo(getApplicationContext(), "", "", null); } nm.notify(startId, notification); nm.cancel(startId); return super.onStartCommand(intent, flags, startId); } | cs |
핵심 코드 입니다.
startForeground 를 실행하고 NotificationManager 를 통해서 notification 을 등록 합니다. notification 을
startForeground 시 등록했던 아이디와 동일하게 등록후 cancel 을 하면 startForeground 를 사용하면서
notification 을 보여주지 않을 수 있습니다.
전체 구성 코드
mainActivity.java
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | package com.woong.beaconbackgroundservice; import android.content.Intent; import android.content.IntentFilter; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import com.woong.service.PersistentService; import com.woong.service.RestartService; public class MainActivity extends ActionBarActivity { private Intent intent; private RestartService restartService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); } @Override protected void onDestroy() { super.onDestroy(); Log.i("MainActivity","onDestroy"); //브로드 캐스트 해제 unregisterReceiver(restartService); } /** * 데이터 초기화 */ private void initData(){ //리스타트 서비스 생성 restartService = new RestartService(); intent = new Intent(MainActivity.this, PersistentService.class); IntentFilter intentFilter = new IntentFilter("com.woong.service.PersistentService"); //브로드 캐스트에 등록 registerReceiver(restartService,intentFilter); // 서비스 시작 startService(intent); } } | cs |
메인 화면 에서는 서비스 등록 , 해제 , 브로드캐스트 등록 해제 관련 코드가 있습니다.
여기는 특별한 코드는 없습니다.
RestartService.java
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 38 39 40 41 42 43 44 | package com.woong.service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; /** * Created by woong on 2015. 1. 28.. */ public class RestartService extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.i("000 RestartService" , "RestartService called : " + intent.getAction()); /** * 서비스 죽일때 알람으로 다시 서비스 등록 */ if(intent.getAction().equals("ACTION.RESTART.PersistentService")){ Log.i("000 RestartService" ,"ACTION.RESTART.PersistentService " ); Intent i = new Intent(context,PersistentService.class); context.startService(i); } /** * 폰 재시작 할때 서비스 등록 */ if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){ Log.i("RestartService" , "ACTION_BOOT_COMPLETED" ); Intent i = new Intent(context,PersistentService.class); context.startService(i); } } } | cs |
재시작 , 서비스가 죽었을 때 다시 시작해주는 BroadcastReceiver 입니다.
PersistentService.java
PersistentService 에서 많은 처리를 해주고 있습니다.
서비스 가 죽을 시 알람 등록/해제 , startForeground 실행 등
코드 설명은 주석을 토해 부연설명을 해 놓았습니다.
Manifast.xml
퍼미션 등록
서비스 등록
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <service android:name="com.woong.service.PersistentService" android:enabled="true" android:process=":remote" > </service> <receiver android:name="com.woong.service.RestartService" android:enabled="true" android:exported="false" android:label="RestartService" android:process=":remote" > <intent-filter> <action android:name="ACTION.RESTART.PersistentService" /> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> | cs |
이와 같이 구성하면 이모탈 서비스를 구성 할 수 있습니다.
프로젝트 첨부파일에 첨부 하겠습니다.
'Develop > Android' 카테고리의 다른 글
Android Launcher 만들기(1) (1) | 2016.02.14 |
---|---|
Android Log 배포시 안보이게 하기 (0) | 2016.02.14 |
Android ClipBoard 텍스트 복사 하기 (0) | 2016.02.14 |
Android 화면 회전시 onCreate 실행 안되도록 하기 (0) | 2016.02.14 |
Android 앱내 언어 변경 하기 (0) | 2016.02.14 |