6

나는 서비스와 활동 사이에서 의사 소통하는 방법에 대한 질문을 여러 번 해왔다. 그러나 나는 또한 이것을하기 위해 내 자신의 방법을 원한다. 어떻게 처리했는지의 단점은 무엇입니까? 우선 나는 문제의 진술을 가능한 한 자세하게 기술 할 것이다.Firebase Messaging Service와 활동 간의 통신 방법은 무엇입니까? 안드로이드

두 장치간에 통신하기 위해 Firebase Messaging Service를 사용하는 응용 프로그램을 빌드해야합니다. Uber와 같은 시스템을 가정 해 봅시다. 하나의 앱은 서비스 제공 업체 (드라이버) 용이고 하나는 고객 용 (승객 용) 앱입니다. 승객이 자신의 위치로 여행을 요청하면 특정 반경의 운전자는 Firebase를 사용하여 페이로드로 푸시 알림을 받게됩니다. Firebase 서비스가 백그라운드에서 실행 중입니다. 서비스가 밀어 넣기 알림을 받으면 onMessageReceived 메서드가 호출됩니다. 이벤트가 생성됩니다. 여기서는 Firebase를 사용하여 알림을 생성하지 않지만 Firebase 푸시 알림의 data 필드를 사용해야하는 경우 실제로 장치간에 데이터를 전송합니다. 이제 드라이버 앱은 사용자가 Firebase 푸시 알림의 페이로드에서 자동차를 원하는 위치의 좌표를받습니다. 엑스트라에서이 데이터로 활동을 시작하고 요청을 받았다는 사실을 운전자에게 알릴 수 있습니다.

고객 측에서는 고객이 요청을 제출 한 후 드라이버 중 하나가 요청을 수락 할 때까지 기다리는 것을 알리는로드 중 화면이 표시되는 다음 활동으로 이동합니다. 드라이버 중 하나가이 사용자의 요청을 수락하면이 사용자는 지정된 드라이버 정보가있는 푸시 알림의 페이로드에 Firebase 푸시 알림을 받게됩니다. 다시 말하면, 통지는 생성하지 않고 장치간에 데이터를 전송하는 것입니다.

이제 사용 사례를 이해했으며 문제를 해결할 것입니다.

사용자가 요청을 제출하고 드라이버 중 하나가 요청을 기다리는 동안 기다려야한다는로드 화면이 표시된 다음 대기 화면으로 이동하면 문제가 발생합니다. 드라이버가 요청을 수락하면 사용자는 푸시 알림의 페이로드에 드라이버 정보가있는 Firebase 푸시 알림을 받게됩니다. 서비스와 Activity 사이에서 어떻게 통신하여 Loading 화면 표시를 중단하고 푸시 알림의 페이로드에 수신 된 데이터로 TextView를 채우도록 작업에 지시합니다.

어떻게 처리 했는가? TextView가 드라이버의 데이터로 채워지는 이름이 AwaitingDriver 인 활동이 있다고 가정합니다. 하지만 요청이 아직 받아 들여지지 않았기 때문에 현재 로딩 화면이 표시됩니다. 이제 사용자는 어떤 방식 으로든 활동에 연결되지 않은 백그라운드에서 실행중인 서비스의 운전자 정보가 포함 된 푸시 알림을받습니다. 여기 내 onMessageReceived 방법 여기

@Override 
    public void onMessageReceived(RemoteMessage remoteMessage){ 
     SharedPreferences rideInfoPref = getSharedPreferences(getString(R.string.rideInfoPref), MODE_PRIVATE); 
     SharedPreferences.Editor rideInfoPrefEditor = rideInfoPref.edit(); 
     String msgType = remoteMessage.getData().get("MessageType"); 
     if (msgType.equals("RequestAccepted")){     
      rideInfoPrefEditor.putBoolean(getString(R.string.is_request_accepted), true); 
      rideInfoPrefEditor.putString(getString(R.string.driver_phone), remoteMessage.getData().get("DriverPhone")); 
      rideInfoPrefEditor.putString(getString(R.string.driver_lat), remoteMessage.getData().get("DriverLatitude")); 
      rideInfoPrefEditor.putString(getString(R.string.driver_lng), remoteMessage.getData().get("DriverLongitude")); 

      rideInfoPrefEditor.commit(); 
      AwaitingDriver.requestAccepted(); // A static method in AwaitingDriver Activity 
     }    
    } 

입니다 AwaitingDriver.requestAccepted()AwaitingDriver 활동의 정적 방법이다. 기다리는 고객에게 진행 대화 상자가 표시되는 AwaitingDriver 활동 자체에는 AwaitingDriver.requestAccepted()의 작업 방법이 있습니다. 여기 staticActivity

public static void requestAccepted(){ 
    try{ 
     awaitingDriverRequesting.dismiss(); //ProgressDialog for telling user to wait 
    }catch (Exception e){ 
     e.printStackTrace(); 
    }   
    if (staticActivity != null){ 
     staticActivity.new TaskFindSetValues().execute(); 
    } 
} 

이 클래스 내에 선언 AwaitingDriver 활동 클래스의 정적 오브젝트이다. 나는 그 값을 onResume과 방법으로 설정하고있다. 즉, 액티비티가 화면에 표시되고 화면에 표시되면 staticActivity의 값은 null이 아닙니다. 다음은 onResume 및 방법입니다.여기

@Override 
public void onResume(){ 
    super.onResume(); 
    staticActivity = this; 
    Boolean accepted = rideInfoPref.getBoolean(getString(R.string.is_request_accepted), false); 
    if (accepted){   
     new TaskFindSetValues().execute();    
    } 
} 
@Override 
protected void onPause(){ 
    super.onPause(); 
    staticActivity = null; 
} 

TaskFindSetValuesAwaitingDriver는 활동 클래스 내에 정의 된 AsyncTask를이다. 다음은이 코드를 검토하고 대신 다른 솔루션이 일의 단점에 대해 말해 당신이 같은 예에 제안 방법을 설명 할 수 있다면 정말 감사하게 될 거라고하십시오 TaskFindSetValues

public class TaskFindSetValues extends AsyncTask<String, Void, String>{ 
    String phone; 
    String lat; 
    String lng; 
    @Override 
    protected void onPreExecute(){ 
     SharedPreferences pref = getSharedPreferences(getString(R.string.rideInfoPref), MODE_PRIVATE);    
     phone = pref.getString(getString(R.string.driver_phone), ""); 
     lat = pref.getString(getString(R.string.driver_lat), ""); 
     lng = pref.getString(getString(R.string.driver_lng), ""); 
    } 
    @Override 
    protected String doInBackground(String... arg0){ 
     return null; 
    } 

    @Override 
    protected void onPostExecute(String returnValue){    
     awaitingDriverPhone.setText(phone); //setting values to the TextViews 
     awaitingDriverLat.setText(lat); 
     awaitingDriverLng.setText(lng); 
    } 
} 

의 코드는 .

답변

18

왜 AsyncTask를 사용하고 있습니까? 말이되지 않습니다. 어쨌든, 당신이 활동과 통신하고 싶다면 BroadcastReceiver으로 할 수 있습니다.

public class MyFirebaseMessagingService extends FirebaseMessagingService{ 
    private LocalBroadcastManager broadcaster; 

    @Override 
    public void onCreate() { 
     broadcaster = LocalBroadcastManager.getInstance(this); 
    } 

    @Override 
    public void onMessageReceived(RemoteMessage remoteMessage) { 
     Intent intent = new Intent("MyData"); 
     intent.putExtra("phone", remoteMessage.getData().get("DriverPhone")); 
     intent.putExtra("lat", remoteMessage.getData().get("DriverLatitude")); 
     intent.putExtra("lng", remoteMessage.getData().get("DriverLongitude")); 
     broadcaster.sendBroadcast(intent); 
    } 
} 

하고 활동에

@Override 
    protected void onStart() { 
     super.onStart(); 
     LocalBroadcastManager.getInstance(this).registerReceiver((mMessageReceiver), 
       new IntentFilter("MyData") 
     ); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); 
    } 

    private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      awaitingDriverRequesting.dismiss(); 
      awaitingDriverPhone.setText(intent.getExtras().getString("phone")); //setting values to the TextViews 
      awaitingDriverLat.setText(intent.getExtras().getDouble("lat")); 
      awaitingDriverLng.setText(intent.getExtras().getDouble("lng")); 
     } 
    }; 
+0

등록 취소의 필요성은 무엇입니까? 일명, 당신이 등록 취소하지 않으면 어떻게됩니까? –

+0

FirebaseMessagingService의 onCreate 메소드가 호출되지 않습니다. 왜 그런가? – eskalera

+0

당신은'onCreate' 메소드를 오버라이드 했습니까? 그리고 오타가 있는지 확인하십시오. 메소드의 이름은'OnCreate()'가 아니고'OnCreate()'입니다. –

2

onMessageReceived 메서드에서 응용 프로그램 브로드 캐스트를 보내고 드라이버 세부 정보를 전송할 수 있습니다. 그런 다음 요청을 수락 한 메서드는 브로드 캐스트 수신기 onReceive 메서드로 대체됩니다. 그런 식으로 공유 환경 설정에 쓸 필요가 없으며 doinbackground 메소드가 null을 반환하기 때문에 기본적으로 아무 것도하지 않는 aSyncTask를 사용할 수 있습니다. onPreExecute 및 onPostExecute 메서드 만 사용합니다.이 메서드는 모두 주 스레드에서 실행됩니다.

+0

나는'정적 메서드를 통해'requestAccepted을() 활동의 멤버 변수와 TextViews에 액세스 할 수 없습니다하지만 난 AsyncTask를 통해에서 실행할 수 있기 때문에 내가 AsyncTask를 사용 static method –

0

단순히 onMessageReceived 메서드 내에 인 텐트를 만들고 활동을 다시 시작한 다음 추가로 드라이버 데이터를 전달하지 않는 이유는 무엇입니까?

+0

고객이 다시 시작하는 활동을 보지 않기를 원하기 때문입니다. 유스 케이스에서는 고객이 대기중인 로딩 화면을 실제로보고 있습니다. –

+0

좋습니다. – Cuculus