본문 바로가기

아옳옳의 코딩공부/아옳옳의 안드로이드스튜디오

2021-03-22안드로이드 스튜디오(서비스 )

반응형

서비스란 백그라운드에서 실행되는 어플리케이션의 구성요소 이다 

 

쉽게 내 메인이 실행하는동안에 뒤에서 작업하는 공간이라고 생각하면 된다 

(유튜브 프리미엄 생각하자 ) 

 

서비스에도 따로 자기만의 생명주기가 있다. 

 

사용하는 방법은 2가지 방법이 있다(서비스 , 바인드 서비스 ) 

 

각각의 생명주기

 

(같은색끼리 묶음) 스타트와 스탑으로 실행과 종료한다 

매니패스트 자동으로 추가됨 

 

일단 Context.startSrevice부터 살펴 보도록하자 

메인액티비티

public class MainActivity extends AppCompatActivity {

    EditText editText;
    Intent intent;

    //(태스크 때 배운것 정보불러오기) 서비스에서 작업하고 넘겨준 값을 받아옴 
    @Override
    protected void onNewIntent(Intent intent) {
        if(intent != null){
            String name = intent.getStringExtra("name");
            Toast.makeText(getApplicationContext(),name,Toast.LENGTH_LONG).show();
        }
        super.onNewIntent(intent);
    }

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

        editText = findViewById(R.id.editText);
        Button btn_Start = findViewById(R.id.button);
        Button btn_Stop = findViewById(R.id.button2);

        btn_Start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = editText.getText().toString();
                //인텐트로 에디트 텍스트 정보를 서비스에 정보 전달 해주기 
                intent = new Intent(getApplicationContext(), MyService.class);
                intent.putExtra("name", name);
                startService(intent); //서비스 시작 
            }
        });

        btn_Stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                intent = new Intent(getApplicationContext(), MyService.class);
                stopService(intent); //서비스 종료 
            }
        });


    }
}

일반적인 인텐트처럼 쉽게 생각하자~!

서비스

public class MyService extends Service {
    public MyService() {
    }
    //자동생성 바인드 여기선 안봐도 됨
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    // 서비스가 시작될때 시작점 1번
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("MyService" ,"onCreate 호출");
    }
    //서비스 작동되기전 실행 2번
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("MyService" ,"onStartCommand 호출");
        //메인에서 보내준 정보 꺼내기
        String name = intent.getStringExtra("name");
        Log.i("MyService","name :" +name);
        //정보 보내주기
        intent = new Intent(getApplicationContext(),MainActivity.class);
        //화면이 다시 만들어지는것을 방지 ( 태스크때 배움) 플레그 설정
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_SINGLE_TOP
        |Intent.FLAG_ACTIVITY_CLEAR_TOP);
        //보낼정보 넣어준뒤 메인액티비티로 보내주기
        intent.putExtra("name", name + "from Service");
        startActivity(intent);


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

    }
    //서비스가 끝날때 실행 3번
    @Override
    public void onDestroy() {
        Log.i("MyService" ,"onDestroy 호출");
        super.onDestroy();
    }
}

onCreate : 서비스 시작할때 한번 시작되는 시작점 

onStartCommand : 다른곳에서 실행할때 무조건 실행되는 서비스 생명주기 

onDestory : 서비스가 끝날때 실행되는 생명주기

이런 화면이 있고 kim 이라는 정보를 서비스로 보내주고 로그캣으로 확인 해보자 

여기서 봐야할것은 서비스의 생명주기이다 

처음에 만들어지고 onCreate 가 호출되고 나면 StartCommeand 가 계속 호출되는것을 볼수 있다. 

 

바인드 서비스 

바인드 서비스는 조금더 복잡하고 어렵다... ( 내기준 .. ) 하지만 사용하는 사람들이 있다니 이것도 알아가보도록 하자

위의 코드표를 잘 보면 이해가 될것이다. 

 

메인코드 

public class MainActivity extends AppCompatActivity {
    //어디서든 마이서비스를 사용하기위하여 전역으로 빼줌
    MyService myService;
    //계속해서 생성이나 종료를 누를시 오류가 나기때문에 만들어준 블린
    boolean isService = false;
    // 직접 컨트롤 가능하다는게 바인더 서비스에 장점이다.

    // 1. 서비스 커넥션만들어줌
    ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 이너 클래스로 정의 해놔서 바로 사용 불가능 하여 다운캐스팅
            MyService.MyBinder myBinder = (MyService.MyBinder)service;
            myService = myBinder.getService();
            isService = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isService = false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn_Start = findViewById(R.id.button1);
        Button btn_End = findViewById(R.id.button2);
        Button btn_Confirm = findViewById(R.id.button3);

        // 서비스 시작버튼
        btn_Start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), MyService.class);
                //인텐트 , 위에 만든 커넥션 (상수 이거 주로 사용)
                //2. 바인드 서비스를 통해서 서비스로 간다
                bindService(intent, connection , BIND_AUTO_CREATE);
            }
        });
        //서비스 종료 버튼
        btn_End.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               if (isService){
                   unbindService(connection);
                   isService = false;
               }else {
                   Toast.makeText(getApplicationContext(), "연결된 서비스 없음 ", Toast.LENGTH_LONG).show();
               }
            }
        });
        //받아온 정보 확인 버튼
        btn_Confirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(isService){
                    int num = myService.getRandom();
                    Toast.makeText(getApplicationContext(), "받아온 데이터 : " + num , Toast.LENGTH_LONG).show();
                }else {
                    Toast.makeText(getApplicationContext(), "서비스중이 아이다 아이가 , 데이터 못받는다 아이가 " , Toast.LENGTH_LONG).show();
                }
            }
        });
    }
}

서비스 코드

public class MyService extends Service {
    //4. 마이 바인더 객체 생성
    private final  IBinder mBider = new MyBinder();
    //5. 마이바인더 리턴 (결과적으로 서비스 주소값 던져준다 )
    @Override
    public IBinder onBind(Intent intent) {

       return mBider;
    }
    //3. 마이 바인더 만들어주고 주소값을 가진놈
    class MyBinder extends Binder{
        MyService getService(){
            return MyService.this;
        }
    }

    int getRandom(){
        return new Random().nextInt(100);
    }
    //서비스 생성시
    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(getApplicationContext(),"Service Create", Toast.LENGTH_LONG).show();
    }
    //서비스 종료시
    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(getApplicationContext(),"Service End", Toast.LENGTH_LONG).show();
    }

}

 

 

인텐트 서비스

위에서 본 내용들은 따로 서비스를 종료해주거나 어플리케이션이 완전히 종료 되어야 서비스가 종료되는걸 알수 있는데 이에 반해 인텐트 서비스는 일회성으로 시작이되고 자기가 주어진일이 끝나면 자동으로 종료를 해주는 기능이 들어있다

코드로 살펴보자 

 

메인액티비티

public class MainActivity extends AppCompatActivity {


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

        Button button = findViewById(R.id.button);
        editText = findViewById(R.id.editText);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!editText.getText().toString().isEmpty()){
                    Long sleepSconds = Long.parseLong(editText.getText().toString());
                    Intent intent = new Intent(MainActivity.this , MyIntentService.class);
                intent.putExtra("seconds" , sleepSconds);
                startService(intent);
                }else {
                    Toast.makeText(getApplicationContext(),"시간을 입력해", Toast.LENGTH_LONG).show();
                }

            }
        });
    }
}

에디트 텍스트로 숫자를 받으면 그 시간만큼 서비스를 작동하고 종료하게 만들것이다 . 

코드에 보이는것처럼 에디트텍스트로 받은것을 Long에 담아주었고 인텐트로 보내주었다 

그게 아니라면 시간을 입력하라는 메시지를 보여준다

 

서비스

//인텐트 서비스
public class MyIntentService extends IntentService {

    long seconds;

    public MyIntentService() {
        //앱의 이름 적어주면 된다
        super(MyIntentService.class.getName());
    }
    //인텐트 서비스는 일회성 서비스이다 !!
    //onHandleIntent 여기에 일을 하고 끝나면 자동으로 종료된다
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
    seconds = intent.getLongExtra("seconds", 0);
        long milis = seconds*1000; //몇초동안 잠들게 하는지 볼려면
        try {
            Thread.sleep(milis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(getApplicationContext(),String.format("Sleep %d sconds", seconds),Toast.LENGTH_LONG).show();
    }
}

여기서 받아온 숫자로 코드를 작성해주었는데 처음보는 코드가 있는데 저건 나중에 배울것이라 그냥 흐름만 보고 파악하면 된다 . 

중요한건 받아온 숫자를 밀리세컨드로 바꿔주고 그 시간이 지나면 즉 할당된 일이 끝나면 생명주기에 따라서 끝나게 되는데 끝나면서 토스트메시지로 우리가 알수 있게 확인을 해줄것이다. 

그럼 결과값을 보자~!! 

 

 이렇게3이라는 숫자를 임력하고 인텐트서비스에 따라서 힐당된 일이 끝나고 종료가 되면서 토스트 메시지가 나온것을 볼수 있다. 


다음 예제를 보면 서비스가 어떻게 작동되는지 알기쉽다 (멜론이나 유튜브 프리미엄같음) 

게임이나 어떤 어플리케이션을 들어가면 배경음악등이 나오는 경우가 있는데 보통 그럴때 많이 사용된다고 한다 

메인액티비티

public class MainActivity extends AppCompatActivity {

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

        Button btn_Start = findViewById(R.id.button);
        Button btn_Stop = findViewById(R.id.button2);

        btn_Start.setOnClickListener(new View.OnClickListener() {
            @Override
            //서비스 시작
            public void onClick(View v) {
                startService(new Intent(getApplicationContext(),MusicService.class));
            }
        });
            //서비스 종료
        btn_Stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(new Intent(getApplicationContext(),MusicService.class));
            }
        });
    }
}

서비스

public class MusicService extends Service {
    //미디어 플레이어 클래스 
    MediaPlayer mediaPlayer;

    public MusicService() {
    }
    // 서비스의 생명주기
    @Override
    public void onCreate() {
        super.onCreate();
        //미디어 클래스에 음악파일 셋팅해주기 
        mediaPlayer = MediaPlayer.create(this , R.raw.sample);
        mediaPlayer.setLooping(false);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(getApplicationContext(),"Music Service가 시작됨", Toast.LENGTH_LONG).show();
        //음악재생  
        mediaPlayer.start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(getApplicationContext(),"Music Service가 중지됨", Toast.LENGTH_LONG).show();
        //서비스가 종료되면 음악도 종료 
        mediaPlayer.stop();

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");

    }
}

코드는 위의 서비스랑 다른게 없고 , 미디어플레이어 사용한 부분만 보면될거 같다 . ( 나중에 배운다 ) 

raw에 파일을 넣어준다 !!  

위의 코드를 실행하면 이렇게 나오게 된다 

 

 서비스 시작을 누르게 되면 음악이 재생되고 보이는것처럼 앱을 종료하더라도 음악은 계속 나오는걸 볼수 있다.

딱 음악 재생 어플같은 느낌이다~!! 

고로 액티비티생명주기와 서비스 생명주기는 완전히 다르다는걸 볼수 있다. 

 

 

오늘배운 내용은 안드로이드 4대 컨포넌트 정말 중요한 부분이라 잘 알고 넘어가야 하는데 

간단하게 서비스는 보여지는 화면에서 작동하는것이 아니라 보이지않는 곳에서 일처리를 해주는 것이라고 생각하면된다 .. 

 

 

시간이 지남에 따라서 알아야 할 것들도 많아지고 어려워 지는데 그만큼 나의 실력도 늘어가는거라고 생각하자~~!!! 

반응형