도전과제 11,12
서비스에서 보낸 메시지를 액티비티 안에서 등록한 브로드캐스트 수신자를 이용해 받도록 만들어 보세요
- 화면에 버튼 하나와 입력상자 그리고 텍스트뷰를 배치합니다.
- 버튼을 누르면 입력상자의 글자를 가져와 서비스를 실행하면서 보내줍니다.
- 서비스에는 다시 브로드캐스팅을 이용해 글자를 보내줍니다.
- MainActivity 화면에서는 브로드캐스트 수신자를 통해 글자를 전달받습니다.
- 수신자를 통해 전달받은 글자를 화면에 있는 텍스트뷰에 표시합니다.
참고할점
액티비티 안에서 브로드캐스트 수신자를 등록할 수 있습니다.
액티비티 안의 수신자에서 메시지를 수신하면 그 메시지를 액티비티 안의 텍스트뷰에 표시할 수 있습니다.
풀이
레이아웃은 단순하게 EditText로 메세지를 보내면, 밑에 TextView에 각각의 서비스와 수신자를 거치는게 기록되면서 표시되게 구성하였다.
메인 액티비티에서 버튼을 누르면 인텐트에 메세지를 담아 서비스를 시작한다. 그럼 인텐트는 MyService.class를 실행하며 전달된다.
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String text = editText.getText().toString();
Intent intent = new Intent(getApplicationContext(), MyService.class);
intent.putExtra("text", text);
intent.putExtra("name", "메인 출발\n");
startService(intent);
}
});
실행된 서비스인 MyService.class에서는 onStartCommand()로 시작할 때의 동작을 정의한다. 이때 인텐트 객체가 null이 아니면 processCommand를 실행하는데, 이 processCommand에서는 액션을 정의한 후 브로드캐스트로 뿌린다.
public class MyService extends Service {
private static final String TAG = "MyService";
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate Called");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStratCommand Called");
if(intent == null){
return Service.START_STICKY;
}else{
processCommand(intent);//인텐트 객체가 null이 아니면 실행
}
return super.onStartCommand(intent, flags, startId);
}
private void processCommand(Intent intent){
String text = intent.getStringExtra("text");
String name = intent.getStringExtra("name"); //인텐트 안에서 데이터 따와서
//com.example.doitmission12.myAction의 액션으로 정의 후
Intent sendIntent = new Intent("com.example.doitmission12.myAction");
sendIntent.putExtra("text", text);
sendIntent.putExtra("name", name + "서비스 거침\n");
sendBroadcast(sendIntent); //브로드캐스트로 뿌림
Log.d(TAG, "서비스에서 받은 문자 : " + text);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy Called");
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
다시 메인 액티비티로 돌아와서, BoradcastReceiver를 상속받는 MyReceiver를 정의하는데, onReceive 함수로 원하는 액션을 받았을때 할 행동을 정의한다. 여기선 textView를 갱신하게 하였다. 이제 이 myRecevier 객체를 선언한 후, registerReceiver()메소드로 이 액티비티에 등록시킨다.
MyReceiver 자체를 메인 액티비티 내부에서 선언하여 바로 textView를 갱신하거나 받은 인텐트 값을 사용할 수 있지만, 다른 액티비티로 인텐트를 넘겨 사용해야 할 경우가 있다. 위 문제에서는 브로드캐스트 수신자에서 인텐트 값을 다시 넣은 뒤, 다시 메인 액티비티를 호출하는 방법 sendToActivity를 통해 사용하였다.
public class MyReceiver extends BroadcastReceiver {
public static final String TAG = "MyReceiver";
public Intent BroadcastIntent;
@Override
public void onReceive(Context context, Intent intent) {
String text = intent.getStringExtra("text");
String name = intent.getStringExtra("name") + "브로드캐스트 거침\n";
Log.d(TAG, "BroadCast에서 받은 문자 : " + text);
//textView.setText("내용 : " + text+ "\n" + "경로 : " + name + "다시 메인으로");
sendToActivity(context, text, name);
}
//아래 메소드를 사용하면 새 액티비티 창켜서 인텐트내용 전송 가능.
public void sendToActivity(Context context, String text, String name){
BroadcastIntent = new Intent(context.getApplicationContext(), MainActivity.class);
BroadcastIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
BroadcastIntent.putExtra("text" , text);
BroadcastIntent.putExtra("name", name);
context.getApplicationContext().startActivity(BroadcastIntent);
}
}
그렇게 되면 onCreate함수의 getIntent()가 발동하면서 NewActivity 메소드가 실행되고, 새 메인 액티비티 창이 켜지면서 텍스트뷰에 지금까지의 경로가 표시된다.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = findViewById(R.id.editText);
textView = findViewById(R.id.textView);
button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
//중략..
});
myReceiver = new MyReceiver();
IntentFilter filter = new IntentFilter("com.example.doitmission12.myAction");
this.registerReceiver(myReceiver, filter);
NewActivity(getIntent());
}
public void NewActivity(Intent intent){
String text = intent.getStringExtra("text");
String name = intent.getStringExtra("name");
if(text != null){
textView.setText("내용 : " + text+ "\n" + "경로 : " + name + "다시 메인으로");
}
}
결과
전체 소스코드 : https://github.com/howtolivelikehuman/DoitAndroid/tree/master/DoitMission_12
'코딩 > Do it Android [JAVA]' 카테고리의 다른 글
도전과제 14 : 쇼핑 상품 화면 구성하기(Do it 안드로이드 앱 프로그래밍) [JAVA] (0) | 2020.08.17 |
---|---|
도전과제 13 : 리사이클러뷰에 고객 정보 추가하기 (Do it 안드로이드 앱 프로그래밍) [JAVA] (0) | 2020.08.17 |
도전과제 10 : 기본 앱 화면 구성 (Do it 안드로이드 앱 프로그래밍) [JAVA] (0) | 2020.08.15 |
도전과제 09 :고객 정보 입력화면의 구성 (Do it 안드로이드 앱 프로그래밍) [JAVA] (0) | 2020.08.10 |
도전과제 07,08 : 세 개 이상의 화면 만들어 전환하기 (Do it 안드로이드 앱 프로그래밍) [JAVA] (0) | 2020.08.09 |
Comment