...더보기

간단설명...

다음의 (1), (2) 코드를 모두 작성하게 되면,

액티비티 내의 특정 버튼을 누름으로써 서비스를 실행시키고,

이렇게 실행된 서비스는 5초간 sleep() 했다가 액티비티를 호출하여 액티비티에 Toast메세지가 뜨게된다.

 

 


 

우선! 새로운 Service 클래스 작성하기

 

app오른쪽클릭>New>Service>Service 선택

(생성하게되면, AndroidManifest.xml에 서비스관련 태그가 자동으로 등록된 것을 확인할 수 있다)

 

생성시 다음과 같은 코드가 작성되어 있다.

package x.x.x;
import ...;

public class MyService extends Service{

	public MyService(){
	
	}
    
	@Override
	public IBinder onBind(Intent intent){
		throw new UnsupportedOperationException("Not yet Implemented"); //자동으로 작성되는 코드
	}
}
       

여기서 오른쪽클릭>generate>override method 에서 onCreate(), onDestroy(), onStartCommand() 를 선택하여 세 가지 메소드를 오버라이딩합니다. (에러가 뜨는 파라미터는 삭제하면 된다)

 


 

* (1) 액티비티 -> Service (액티비티에서 Intent를 보내고, Service에서 처리하는 경우 예시코드)

 

우선, 액티비티에서 서비스를 호출하는 코드는 다음과 같다.(간단)

(startService() 메소드를 사용하면 된다.)

// 액티비티의 화면안에서 특정 버튼을 눌러 서비스를 실행시키는 경우

button.setOnClickListener(new View.OnClickListener(){
	@Override
    public void onClick(View v){
    	Intent intent = new Intent(getApplicationContext(), MyService.class); // 실행시키고픈 서비스클래스 이름
        // intent.putExtra("", ""); 필요시 인텐트에 필요한 데이터를 담아준다
        
        startService(intent); // 서비스 실행!
        
	}
});

이제 서비스의 코드를 작성해본다.

액티비티의 인텐트를 통해 전달받은 데이터를 로그에 찍는 간단한 코드이다.

(Service.START_STICKY 상수값을 사용하여 혹시 서비스가 종료되더라도 다시 자동으로 실행되도록 할 수 있다.)

/** MyService.java - 서비스 코드!! **/

package x.x.x;
import ...;

public class MyService extends Service{

	private static final String TAG = "MyService";

	public MyService(){
	
	}
    
    @Override
    public void onCreate(){
    	super.onCreate();
        // 서비스는 한번 실행되면 계속 실행된 상태로 있는다.
        // 따라서 서비스 특성상 intent를 받아서 처리하기에 적합하지않다.
        // intent에 대한 처리는 onStartCommand()에서 처리해준다.
        Log.d(TAG, "onCreate() called");
    }
    
    /** 요놈이 중요 **/
    @Override
    public void onStartCommand(Intent intent, int flags, int startId){
        Log.d(TAG, "onStartCommand() called");
        
        if (intent == null) { 
        	return Service.START_STICKY; //서비스가 종료되어도 자동으로 다시 실행시켜줘!
        } else {
        	// intent가 null이 아니다.
            // 액티비티에서 intent를 통해 전달한 내용을 뽑아낸다.(if exists)
            String command = intent.getStringExtra("command");
            String name = intent.getStringExtra("name");
            // etc..
            
            Log.d(TAG, "전달받은 데이터: " + command+ ", " +name);
        }
        
        return super.onStartCommand(intent, flags, startId);
    }
    
    @Override
    public void onDestroy(){
    	super.onDestroy();
        
        Log.d(TAG, "onDestroy() called");
    }
    
	@Override
	public IBinder onBind(Intent intent){
		throw new UnsupportedOperationException("Not yet Implemented"); //자동으로 작성되는 코드
	}
}
       

 


 

* (2) 반대로 Service -> 액티비티 에게 정보를 전달하는 경우 예시코드

(ex 백그라운드에서 실행중인 카카오톡의 새메시지 알림)

 

* 서비스 코드. startActivity()메소드를 활용하여 서비스가 액티비티를 호출한다.
(플래그 사용, startActivity() 메소드를 사용한다는 것이 포인트)

/** MyService.java - onStartCommand() 메소드 내용만 변경 **/

    /* ... */
    
    @Override
    public void onStartCommand(Intent intent, int flags, int startId){
        Log.d(TAG, "onStartCommand() called");
        
        if (intent == null) { 
        	return Service.START_STICKY; //서비스가 종료되어도 자동으로 다시 실행시켜줘!
        } else {
            String command = intent.getStringExtra("command");
            String name = intent.getStringExtra("name");
            
            //Log.d(TAG, "전달받은 데이터: " + command+ ", " +name);
            
            try{
            	Thread.sleep(5000); //5초동안 정지
            } catch(Exception e) {}
            
            Intent showIntent = new Intent(getApplicationContext(), MainActivity.class);
            
            /**
               	화면이 띄워진 상황에서 다른 액티비티를 호출하는 것은 문제가없으나,
               	지금은 따로 띄워진 화면이 없는 상태에서 백그라운드에서 실행중인 서비스가 액티비티를 호출하는 상황이다.
               	이러한 경우에는 FLAG_ACTIVITY_NEW_TASK 옵션(플래그)을 사용해줘야 한다.
            **/
            showIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            
            showIntent.putExtra("command", "show");
            showIntent.putExtra("name", name + " from service.");
            
            // *** 이제 완성된 인텐트와 startActivity()메소드를 사용하여 MainActivity 액티비티를 호출한다. ***
            startActivity(showIntent);
        }
        
        return super.onStartCommand(intent, flags, startId);
    }
    
    
    /*  ...  */

* 인텐트를 받게될 MainActivity.java 액티비티 코드

(주의: intent를 받아서 MainActivity가 처음으로 만들어지는 상황이라면 onCreate() 메소드 안에서 인텐트를 처리할 것이다. 하지만 해당 액티비티가 이미 만들어져있는, onPause()등을 통해 잠시 실행중지 된 상태였다면, onCreate()를 거치지 않을 것이다. 이러한 경우를 위하여, onNewIntent()를 override해주어 이와같은 상황에도 인텐트가 처리될 수 있도록 해주어야한다.)

// MainActivity.java 코드 일부

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
    /*.. 생략 ..*/
    
    Intent passedIntent = getIntent();
    processCommand(passedIntent);
}

@Override
protected void onNewIntent(Intent intent) {
	processCommand(passedIntent);
    
    super.onNewIntent(intent);
}

// 이와 같이 모든 경우에 서비스로부터 받은 인텐트가 처리 될 수 있도록한다.
// 이제 processCommand() 메서드 정의.

private void processCommand(Intent intent) {
	if(intent != null) {
    	String command = intent.getStringExtra("command");
        String name = intent.getStringExtra("name");
        
        Toast.makeText(this, "서비스로부터 전달받은 데이터: "+ command + ", " + name, Toast.LENGHT_LONG).show();
}

 


 

서비스 특성 상 화면이 없는 상태로 작동하기 때문에 헷갈리는 것일 뿐, 간단하다.

상당히 많이 사용되는 개념이므로 잘 숙지하는게 중요해보인다.

+ Recent posts