반응형

서비스

앱을 실행했을 때 화면이 항상 보이는 것은 아닙니다.

다시 말해 화면을 띄우지 않고도 필요한 기능을 실행할 수 있습니다.

화면 없이 백그라운드에서 실행되는 하나의 단위를 서비스(Service)라고 부릅니다.

서비스는 애플리케이션 구성요소이므로 프로젝트에 추가할 때 반드시 매니페스트 파일에도 추가해야 합니다.

매니페스트에 추가할 때는 <service> 태그를 사용합니다.

다만 New 메뉴를 이용해 새로운 서비스를 만들면 <service> 태그가 자동으로 추가됩니다.

서비스는 startService 메소드를 호출하면 시작됩니다.

서비스도 onCreate와 onDestroy 메소드가 있어서 메모리에 만들어질 때와 메모리에서 없어질 때 자동으로 호출됩니다.

서비스는 항상 실행되어 있을 수 있도록 비정상 종료되는 상황이 벌어지더라도 시스템에 의해 자동으로 재시작됩니다.

자동으로 재시작되는 서비스

startService 메소드를 호출할 때도 인텐트 객체를 파라미터로 전달해야 하며 이 인텐트 객체는 시스템으로 전달된 후 시스템에서 지정한 서비스를 만들고 실행하는 과정을 거치게 됩니다.


서비스로의 명령 전달

서비스가 자동으로 재시작되게 하는 것이 일반적이다 보니 앱이 실행된 후에 startService 메소드를 이용해 서비스를 시작시키기만 하면 더 이상 startService 메소드를 호출할 일이 없지 않을까요?

그렇지 않습니다.

이미 알고 있는 것처럼 인텐트를 이용해 서비스를 시작시키면 인텐트 객체가 서비스로도 전달됩니다.

그리고 그 안에 부가데이터를 넣어 전달할 수 있으므로 서비스로 데이터를 전달하고 싶은 경우에는 startService가 더 자주 호출될 수 있습니다.

그런데 이 때의 startService 메소드는 서비스를 시작시키기 위한 목적이 아니라 명령이나 데이터를 전달하기 위한 용도로 사용됩니다.

이렇게 startService 메소드를 호출하면서 인텐트 안에 넣어 전달한 명령이나 데이터를 잘 처리할 수 있도록 onStartCommand라는 메소드를 사용할 수 있습니다.

새로운 서비스 클래스를 정의할 때는 다음과 같이 onCreate, onStartCommand, onDestroy 메소드를 재정의하는 경우가 많습니다.

public class MyService extends Service {

  @Override
  public void onCreate() {
    super.onCreate();

    Log.d(TAG, "onCreate() 호출됨.");
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStartCommand() 호출됨.");
 
    return super.onStartCommand(intent, flags, startId);
  }

}

 onStartCommand 메소드가 호출되면 인텐트 객체를 파라미터로 전달받을 수 있습니다.

따라서 인텐트 안에 들어있는 명령이나 데이터를 확인하여 필요한 기능을 수행할 수 있습니다.

 

서비스에서 액티비티로 데이터 전달

서비스에는 화면이 없다 보니 사용자에게 무언가를 보여주고 싶다면 액티비티로 데이터를 전달한 후 액티비티에서 보여주어야 합니다.

서비스에서 액티비티로 데이터를 전달할 때는 인텐트를 사용하며 인텐트 안에 부가데이터 넣어 보냅니다.

Intent showIntent = new Intent(getApplicationContext(), MainActivity.class);
showIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

showIntent.putExtra("command", "show");
showIntent.putExtra("name", "mike");

startActivity(showIntent);

 화면이 없는 서비스에서 화면이 있는 액티비티를 띄울 때는 태스크(Task)를 새로 만들어서 연결해야 합니다.

이 때문에 FLAG_ACTIVITY_NEW_TASK 플래그를 추가해주게 되는데 일반적인 경우 세 개의 플래그를 같이 사용합니다.

액티비티가 화면에 보인 상태에서 위와 같이 startActivity를 호출하면 액티비티는 새로 만들어지지 않고 기존 액티비티를 그대로 사용하게 됩니다.

그리고 액티비티의 onNewIntent 메소드가 자동으로 호출됩니다.

@Override
protected void onNewIntent(Intent intent) {
    processIntent(intent);

    super.onNewIntent(intent);
}

Q.어떤 경우에 액티비티가 아닌 서비스에서 기능을 실행하도록 해야 하는 걸까요?

A.사진이나 파일을 전송하거나 다운로드 받을 때 서비스를 이용해서 화면이 보이지 않아도 기능을 수행할 수 있게 할 수 있을 것 같습니다.


Q.인터넷을 통해 데이터를 주고받는 기능을 액티비티에 넣어두는 경우 어떤 문제가 발생할 수 있을까요?

A.OnPause나 OnStop 되었을 때 기능이 중단되는 문제와 UI 스레드에서 이를 처리함으로 인해서 화면이 버벅댈 수도 있을 것 같습니다.

반응형

'안드로이드 개발 > 부스트코스(안드로이드 프로그래밍)' 카테고리의 다른 글

위험권한 부여하기  (0) 2019.03.12
브로드캐스트  (0) 2019.03.10
엑티비티 수명주기  (0) 2019.03.09
부가데이터  (0) 2019.03.08
인텐트(Intent)  (0) 2019.03.08
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기