개발하는 두더지

[Android/안드로이드] Service와 BroadcastReceiver로 스크린 화면 감지하기 본문

Java,Android

[Android/안드로이드] Service와 BroadcastReceiver로 스크린 화면 감지하기

덜지 2016. 7. 22. 03:00

목차

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()로 앱을 종료시킨다.

정적으로 리시버를 설정해놓았기 때문에 메인 액티비티에 별도의 코드를 안 넣어도 

재부팅 후 정상적으로 브로드캐스트 리시버가 동작한다.



Comments