1.  이전꺼 한번 더 설명

액티비티에서 서비스를 실행하거나,

액티비티에서 서비스로 어떤 데이터를 전달하고 싶다고 하며는

시스템통과한다는 라는 것을 꼭 알고 있어라.

 

왜냐?

둘다 시스템에서 관리하는 "애플리케이션 구성요소"이기때문에 입니다.

 

어쨌든,

액티비티에서 서비스로 전달을 할 수 있구나, 인텐트 안에 데이터를 넣어서,

그래서 넣어서 전달을 할 수 있다는 것을 알았는데,

 

반대의 경우도 있다,

예를 들면,

서비스라고 하는게 "카카오톡이다" 또는 "네이버라인이다", 그러면 채팅앱 같은 경우에는

우리가 화면이 없다라고 하더라도

메시지를 주고 받는 상황들이 생기겠죠!!!,

 

그러면 서비스 쪽에서 다른 사람이 보내온 채팅메시지를 받았다라고 한다면,

화면으로 보내줘야 할 거잖아요!!!?!!

그래야 화면에 보이잖아요!!!

 

(어짜피 서비스는 화면이 없는거니깐...............)

 

그래서

반대로 서비스에서 액티비티로 보내주어야 하는 상황이 생긴다!!!

 

 

 

 

 

 

 

2. 서비스에서 액티비티로 보내주는 방법 ( 설명 + 코드 )

(1) 설명(일부분)

계속 말한 듯이 "서비스"라고 하는 것은 화면이 없거든요.

그런데 화면이 없는 곳(서비스클래스)에서 화면쪽으로 화면을 띄워 달라고 했을 때에는

문제가 생긴다!!!

 

왜냐하면 화면이라는 것은 Task라는 것으로 묶여 있다.

이 Task는 내가 만든 화면도 있고, 다른 사람이 만든 앱의 화면도 있을 거다..

그 앱의 각각의 화면(기본 브라우저,전화걸기 화면 등등)끼리 필요하면 띄워 줄 수 있도록,

인텐트로 띄워 줄 수 있잖아요.

그런 경우에, 각각의 화면이 연속적으로 띄워 줄 수 있도록 만들어 놓은 것이 

Task입니다.

 

그런데 화면이 없는 곳에서 화면을 띄울려고 한다면 

Task라는 정보가 없어서 화면을 띄우는데 문제가 생길 수가 있죠!!

그래서 이것을 띄울려면 옵션을 주어야 합니다.

addFlags() : 사용하면 됩니다!!

 

showIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |   <- 화면이 없는데에서 화면을 띄울 수있게 해준다.
Intent.FLAG_ACTIVITY_SINGLE_TOP |    <- 만들어져 있는 화면을 재활용 해달라
Intent.FLAG_ACTIVITY_CLEAR_TOP) <- 혹시 그 위에 다른 화면이 있으면 그걸을 제거해주는 역할

일반적으로 3가지 옵션을 함께 넣어서 사용해준다고 한다.

이젠, MyService.java에서 MainActivity.java 쪽으로 실행을 할 것이다.

 

 

만약에,

MainActivity.java가 처음만들어지는 시점은 onCreate() 안에서 써져있는 인텐트를 확인(실행)하게 되구요.

그렇지 않으면!!

이미 MainActivity.java가 만들어져 있는 상태에서

onCreate()가 호출 되지 않고

MainActivity.java 안에 onNewIntent()라는 메소드를 오버라이드 해서

onNewIntent()메소드가 호출이 됩니다.!!

 

서비스에서 onCreate() 한번만 호출되고

나중에 onStartCommand()가 호출 되잖아요!! (이런거 하고 같은 개념이라는 말임)

(기억안나면 참고 하셈 -> [Android] 서비스(Service) - (1)사용법(만드는 방법))  

 

 

그래서, MainActivity.java

서비스에서 받은 것을 onNewIntent()메소드에서 확인을 하든지,

onCreate()메소드 안에서 getIntent();로 확인을 하든지,

이렇게 2가지 경우가 생기는 거다.

(1.onNewIntent())

(2.onCreate() 안에서 getIntent())

 

 

 

(2) 3. 코드 구조 보면 됨..

 

 

 

 

 

 

 

 

3. 코드 구조

(1) (블로그 앞내용) 서비스 만들고 메인에서 서비스로 보내는 구조

 

 

 

(2) 요번에 한거

[코드 구조(1)] + 추가 설명(서비스에서 메인으로 보내는 구조)

- activity_main.xml

(같음)

 

- MyService.java

 

- MainActivity.java

 

- AndroidManifest.xml

(같음)

 

 

 

 

 

 

 

 

4. 

결국,

액티비티와 서비스 간에 "인텐트"를 이용해서

서로 실행 시켜줄 수가 있고,

그리고, 실행 시켜주는게 주 목적이라기 보다는,

대부분에 경우에는 데이터를 전달하는 용도로 많이 사용 한다.

 

주의 할 부분!!!

데이터를 전달 할 때,

이미 서비스가 실행 되어 있는 경우,

이미 액티비티가 떠 있는 경우도

감안을 해야 한다!!!

꼭!!! 생각하고 있어라..

 

 

 

 

 

서비스는 화면이 없는거야!!!

그리고 서비스는 이런구조로 만들어 지는 거야!!

 

 

 

 

 

 

5. -참고 (이것도 중요)-

요즘 앱들은,

웹서버나 서버 쪽하고 데이터를 주고 받는 경우가 많다.

데이터를 주고 받을 때,

그 데이터를 주고 받는 작업 자체는 화면이 필요가 없다.

그리고 기본적으로 

애가 항상(계속) 대기 상태에 있어야지

서버쪽에서 보내온 데이터를 받아서

처리를 할 수 있을 거다.

 

예전에 이야기 한 것처럼

"카톡"이나 "라인", 채팅앱 같은 경우도

만찬가지로 항상(계속) 대기 상태이어야 사용 할 수 있다.

그랴서 이 서비스라는게 

상당히 많이 사용 된다!!!!!!!!

 

 

 

 

 

 

 

 

 

6. 전체 코드

(1) 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"
    android:gravity="center"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="200dp"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/button"
        android:text="서비스 시작!!"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

(2) MainActivity.java

public class MainActivity extends AppCompatActivity {

    EditText editText;

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

        editText = (EditText)findViewById(R.id.editText);

        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = editText.getText().toString();

                Intent intent = new Intent(getApplicationContext(),MyService.class);
                intent.putExtra("command","show");
                intent.putExtra("name",name);
                startService(intent);
            }
        });

        Intent passedIntent = getIntent();
        processCommand(passedIntent);   // 이거 호출
    }

    @Override
    protected void onNewIntent(Intent intent) {
        processCommand(intent);    //이거 호출
        super.onNewIntent(intent);
    }

    private void processCommand(Intent intent){
        if(intent != null){
            String command = intent.getStringExtra("command");
            String name = intent.getStringExtra("name");

            Toast.makeText(this,"서비스로부터 전달받은 데이터 : "+ command+", "+name,Toast.LENGTH_LONG).show();
        }

    }
}

(3) MyService.java

public class MyService extends Service {

    // 이거(생성자)는 메모리에 딱 만들어 지는 시점이고
    public MyService() {
    }

    // 서비스로 동작하기위한 초기 시점
    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if(intent == null){ // 인테트가 null이면,
            return Service.START_STICKY; // 서비스가 종료 되었을 때도 다시 자동으로 실행 함.
        }else{
            processCommand(intent);
        }
        return super.onStartCommand(intent, flags, startId);
    }

    private void processCommand(Intent intent){
        // 이 안에서 Main에서 전달 받은 Extradata를 뽑아 볼 것이다.
        String command = intent.getStringExtra("command");
        String name = intent.getStringExtra("name");

        // 서비스에서 액티비티 보내는 방법////////////////////////////////////////////////////////
        try{
            Thread.sleep(3000);
        }catch (Exception e){}

        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",name + "from service.");
        startActivity(showIntent);

        ////////////////////////////////////////////////////////////////////////////////////////
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

(4) AnroidManifest.xml