ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 안드로이드 서비스 (3)
    안드로이드 2020. 5. 21. 21:09
    728x90

    2020/05/21 - [Android & Kotlin] - 안드로이드 서비스(2)

     

    안드로이드 서비스(2)

    2020/05/21 - [Android & Kotlin] - 안드로이드 서비스 안드로이드 서비스 오늘은 서비스에 대해서 알아볼게요. 서비스는 백그라운드 작업을 할 때 사용하는 컴포넌트에요. 지금까지는 우리가 알고 있는

    bubble-dev.tistory.com

    서비스 관련 마지막 글이 될 것 같네요 하하

    이전까지는 스타티드 서비스와 서비스를 LMK로부터 최대한 오래 살아남는 법에 대해서 알아봤어요

     

    이번 글에서는 바운드 서비스에 대해서 알아볼게요

    바운드 서비스는 서버/클라이언트적인 성향이 강해요 그래서 사용하기 전에 연결을 맺고, 다 사용했으면 연결을 끊는 과정들이 필요합니다.

     

    예제

    < layout/activity_main.xml >

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/start_btn"
            android:text="startService"
            android:layout_width="match_parent"
            android:layout_height="100dp"/>
    
        <Button
            android:id="@+id/end_btn"
            android:text="stopService"
            android:layout_width="match_parent"
            android:layout_height="100dp"/>
    
    </LinearLayout>

     

    < MainActivity.java >

    package kr.co.sample;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    public class MainActivity extends AppCompatActivity {
    
        private ServiceConnection connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                // 바운드 서비스가 연결되었음을 확인할 수 있는 메소드
                Log.d("CountService", "onServiceConnected");
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                // unbindService 가 아닌 의도치 않은 상황으로 연결이 끊겼을 때 호출
                Log.d("CountService", "onServiceDisconnected");
            }
        };
    
        Button startBtn, endBtn;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            startBtn = findViewById(R.id.start_btn);
            endBtn = findViewById(R.id.end_btn);
    
            startBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(MainActivity.this, CountService.class);
                    bindService(intent, connection, BIND_AUTO_CREATE);
                }
            });
    
            endBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    unbindService(connection);
                }
            });
        }
    }
    

     

    결과

     

    startService, stopService 버튼을 한 번 씩 눌러보시면 위와 같은 로그가 뜨는데 onServiceConnected(), onServiceDisconnected() 가 안뜨는것을 알 수 있어요

     

    이는 MainActivity와 CountService 간의 통신 매체가 없기 때문이에요

    연결을 맺기는 했는데 어떤 명령을 전달할지는 모르고, 이를 전달하려면 바인더 객체가 필요합니다.

     

    바인더를 생성하려면 AIDL(Android Interface Definition Language)을 작성해야 합니다.

     

    AIDL 만들기

    AIDL 디렉토리 생성

    AIDL 디렉토리 생성

    AIDL 파일 생성

     

    < ICountService.aidl >

    자바처럼 보이지만 자바는 아닙니다.

    // ICountService.aidl
    package kr.co.sample;
    
    // Declare any non-default types here with import statements
    
    interface ICountService {
    
        int getCountNumber();
    
        void startCountDown();
    
        void stopCountDown();
    }
    

     

    이 상태에서 CountService.java 를 수정하실 때 만약 ICountService 클래스가 없다면 Run을 한 번 눌러주세요 그럼 안드로이드가 알아서 클래스를 만들어줄거에요

     

    < CountService.java >

    package kr.co.sample;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    
    public class CountService extends Service {
    
        private int count;
        private Thread thread;
    
        ICountService.Stub binder = new ICountService.Stub() {
            @Override
            public int getCountNumber() throws RemoteException {
                // 현재 카운트 값 리턴
                return count;
            }
    
            @Override
            public void startCountDown() throws RemoteException {
                if (thread == null) {
                    // 카운트 다운 타이머 시작
                    thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            while (true) {
                                count++;
                                Log.d("CountService", String.valueOf(count));
                                try {
                                    Thread.sleep(1000);
                                } catch (InterruptedException e) {
                                    break;
                                }
                            }
                        }
                    });
    
                    thread.start();
                }
            }
    
            @Override
            public void stopCountDown() throws RemoteException {
                // 카운트 다운 타이머 종료
                if (thread != null) {
                    thread.interrupt();
                    thread = null;
                }
            }
        };
    
        public CountService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            Log.d("CountService", "onBind");
            return binder;
        }
    
        @Override
        public boolean onUnbind(Intent intent) {
            Log.d("CountService", "onUnbind");
            if (thread != null) {
                thread.interrupt();
                thread = null;
                count = 0;
            }
            return super.onUnbind(intent);
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            Log.d("CountService", "onCreate");
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d("CountService", "onDestroy");
        }
    }
    

     

    < layout/activity_main.xml >

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/start_btn"
            android:text="startCount"
            android:layout_width="match_parent"
            android:layout_height="100dp"/>
    
        <Button
            android:id="@+id/end_btn"
            android:text="stopCount"
            android:layout_width="match_parent"
            android:layout_height="100dp"/>
    
        <Button
            android:id="@+id/get_btn"
            android:text="getCount"
            android:layout_width="match_parent"
            android:layout_height="100dp"/>
    
        <TextView
            android:id="@+id/count_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
    </LinearLayout>

     

    <MainActivity.java>

    package kr.co.sample;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    public class MainActivity extends AppCompatActivity {
    
        Button startBtn, endBtn, getBtn;
        TextView countText;
        ICountService countBinder;
    
        private ServiceConnection connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                // 바운드 서비스가 연결되었음을 확인할 수 있는 메소드
                Log.d("CountService", "onServiceConnected");
    
                countBinder = (ICountService) service;
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                // unbindService 가 아닌 의도치 않은 상황으로 연결이 끊겼을 때 호출
                Log.d("CountService", "onServiceDisconnected");
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            startBtn = findViewById(R.id.start_btn);
            endBtn = findViewById(R.id.end_btn);
            getBtn = findViewById(R.id.get_btn);
            countText = findViewById(R.id.count_text);
    
            Intent intent = new Intent(MainActivity.this, CountService.class);
            bindService(intent, connection, BIND_AUTO_CREATE);
    
            startBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (countBinder != null) {
                        try {
                            countBinder.startCountDown();
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
    
            endBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (countBinder != null) {
                        try {
                            countBinder.stopCountDown();
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
    
            getBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (countBinder != null) {
                        try {
                            countText.setText(String.valueOf(countBinder.getCountNumber()));
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
    
            unbindService(connection);
        }
    }
    

     

    결과

     

    잘 실행되는걸 볼 수 있습니다.

    '안드로이드' 카테고리의 다른 글

    안드로이드 서비스(2)  (0) 2020.05.21
    안드로이드 서비스  (0) 2020.05.21
    안드로이드 HandlerThread  (0) 2020.05.13
    안드로이드 CountDownTimer  (0) 2020.05.13
    Android AsyncTask  (0) 2020.05.10

    댓글

Designed by Tistory.