본문 바로가기
My Image
프로그래밍/Android

[Android] startService(시작타입서비스)

by Lim-Ky 2017. 6. 22.
반응형

일전에 서비스에 대해서 전반적인 개념을 숙지했다. 


안보신 분들은 꼭 선행하시길... 클릭-> 서비스전반적인개념


이제 각 서비스에 대한 구체적인 구현방법( startServie, boundService, intentService )에 대해서 알아보자.



1. StartService 타입


우선 StartService부터 구현해보자.

순서는...


1. 서비스시작,종료 버튼 레이아웃 구성하기

2. 매니패스트에 서비스 등록

3. 서비스 상속받아 나만의 서비스 클래스 만들기.

4. 매인액티비티에서 서비스 동작시키기.

5. 동작화면 및 결과



1. 서비스 시작, 종료 버튼 레이아웃 구성하기

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.limky.myservice.MainActivity">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello Service!" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/service_start_button"
android:text="서비스 시작하기"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/service_stop_button"
android:text="서비스 종료하기"/>

</LinearLayout>



</RelativeLayout>


2. 매니패스트.xml 에 Service 등록


.service.StartService라고 한 이윤 StartService.class를 service 폴더 아래 생성해 놓았기 때문에. 즉 service/StartService.class

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.limky.myservice">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service android:name=".service.StartService"></service>

</application>

</manifest>


3. Service 상속받아 StartService.class 만들기


Service를 상속받으면, 아래와 같이 메서드를 override해야합니다.


onBind() : 는 BoundService타입 방식으로 사용합니다. 


onCreate() : service가 구동하면 최초에 한번만 실행됩니다.

onStartCommand() : service가 생성되고 다음으로 실행되는 함수 onstart()함수였으나, onStartCommand()함수를 사용할 것을 권장함.

                           또 서비스가 실행되고 있는 상태에서 또 서비스 시작을 할 경우 onStartCommand()함수를 탑니다.

onDestroy() : 서비스 중지를 하는 경우 실행되는 함수입니다.



Service의 생명주기입니다. start타입과 bind타입이 있습니다. 





그럼 이제 코드 설명을 하겠습니다.


아래 코드에서 보면 onStartCommand()함수에서 서비스 자신을 호출한 쪽에서 전달한 intent를 받을 수 있고 intent 에 담겨진 값을 key,value형태로 해서 파라미터값을 가져올 수 있습니다.


저는 name이라는 키를 통해 값을 출력해보겠습니다. 토스트 창으로ㅎㅎ 

또 각각의 메서드 실행 순서를 알아보기 위해 로그를 찍어봅니다. 

아마 서비스가 최초로 실행될 경우 onCreate() -> onStartCommand()함수 순으로 탈것이며,

서비스 실행되고 있는 상태에서의 재시작을 하면, onStartCommand()함수만 탈 것입니다.

또 서비스 종료를 하면 당연히 onDestroy()함수를 실행하겠죠?


package com.example.limky.myservice.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;

/**
* Created by on 2017-06-22.
*/

public class StartService extends Service{


@Nullable
@Override
public IBinder onBind(Intent intent) {

Log.d("StartService","onBind()");
return null;
}

@Override
public void onCreate() {
Log.d("StartService","onCreate()");
super.onCreate();
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("StartService","onStartCommand()");
String param = intent.getStringExtra("name");
Toast.makeText(this, "received param : "+param, Toast.LENGTH_SHORT).show();

return super.onStartCommand(intent, flags, startId);
}


@Override
public void onDestroy() {
Log.d("StartService","onDestroy()");
super.onDestroy();
}
}



4. 매인 액티비티에서 서비스 동작시켜보기


간단하게 서비스를 시작하면서 intent에 key,value값으로 name과 "임경호" 라는 string을 파라미터로 전달해 보겠습니다.

각 버튼에 리스너를 달아주시고 서비스 시작, 정지 로직을 넣습니다.


인텐트를 제가 액션형태로 기존에 주었는데 안되더라구요....그래서 명시적으로 인텐트를 만들었습니다.

액션이 안된 이유는 이정도로 파악했습니다. 아래 링크

http://developerworrick.blogspot.kr/2015/12/blog-post_3.html


package com.example.limky.myservice;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.example.limky.myservice.service.StartService;

public class MainActivity extends AppCompatActivity {

private Button startServiceButton,stopServiceButton;
private Intent mIntent;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

startServiceButton = (Button) findViewById(R.id.service_start_button);
stopServiceButton= (Button) findViewById(R.id.service_stop_button);


startServiceButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mIntent= new Intent(getApplicationContext(), StartService.class);
mIntent.putExtra("name","임경호");
startService(mIntent);
}
});


stopServiceButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

stopService(mIntent);
}
});



}



}


5. 동작화면 및 결과


서비스 시작하기를 누르면 매인액티비티에서 인텐트를 통해 서비스를 실행시키고 서비스는

매인액티비티에서 넘어온 인텐트를 받아 key를 통해 data값을 출력합니다.




다음은 로그결과입니다.


빨간색 : 서비스 최초 시작할 경우 onCreate() - > onStartCommand()

초록색 : 서비스 실행되고 있는 상태에서 재시작할 경우 onStartCommand() 

//로그창에 3개나 찍힌 이윤 제가 3번 서비스시작 버튼을 눌렀기 때문입니다.

보라색 : 서비스 종료시킬 경우




여기서 주목할 것은 onCreate()함수는 최초에 한번만 실행되는 함수이며,

서비스가 기동되고 있는 상태에서 서비스를 시작하면, onStartCommand()함수만 실행된다는 것입니다.

따라서 비지니스 로직은 onStartCommand()함수 안에서 구현하시면됩니다.


또!!! 나중에 포스팅 할 예정입니다만, startService는 별다른 스레드를 내부적으로 구현하지 않으면, 자동적으로 mainThread 즉 UI 스레드에게 붙습니다. 작업량이 많은 일을 별도스레드를 만들지 않고 실행할 경우 해당 작업을 완료할때까지 UI가 업데이트되지 않을 것이며, 이는 결국 

ANR을 발생시킬 가능성이 큽니다. 그러니 꼭 별도의 스레드를 만들어서 작업하는 습관을 들여야합니다. ㅎㅎㅎ


스크롤 압빡을 피하기위해 여기서 끊겠습니다.


다음은 BoundService타입 구현을 알아보도록 하겠습니다.





반응형

댓글