2016-08-15 5 views
2

У меня есть серьезная проблема с передачей данных от BroadcastReceiver до Activity. Давайте внимательно посмотрим на мою проблему. У меня есть класс PhoneStateReceiver extends BroadcastReceiver, который использовался для приема входящего телефона.Как передавать данные из BroadcastReceiver в Activity без in onCreate()

public class PhoneStateReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     try { 
      System.out.println("Receiver start"); 
      String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 
      String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); 
      if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){ 

      }    
     } 
     catch (Exception e){ 
      e.printStackTrace(); 
     } 
    } 
} 

Входящий телефон будет отправлен в Activity, называется ReceiverActivity. ReceiverActivity принимает входящий телефон и отправляет его на сервер через соединение сокета. Соединение сокета инициализируется в функции onCreate. Я googled и нашел способ сервера передать данные от BroadcastReceiver до Activity. Общим способом является передача данных через putExtra и вызов startActivity. Однако этот способ снова вызовет onCreate, а затем подключит сокет, снова нарисуйте интерфейс. Таким образом, это не полезно в моем случае.

В моей цели Если телефон получает входящий звонок, он отправит входящий вызов на номер ReceiverActivity. ReceiverActivity принимает сообщение и вызывает функцию отправки. Каков наилучший способ сделать это? Спасибо

Распространенный способ передачи данных из BroadcastReceiver в ReceiverActivity, что я использовал следующие

В PhoneStateReceiver класс:

Intent intent_phonenum = new Intent(context, ReceiverActivity.class); 
intent_phonenum.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
intent_phonenum.putExtra("phone_num", incomingNumber); 
context.startActivity(intent_phonenum); 

В ReceiverActivity Класс:

protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     connect_socket(); 
     Intent intent = getIntent(); 
     phone_num = intent.getStringExtra("phone_num"); 
     send(phone_num); 
} 

ответ

4

Существует очень простой шаблон дизайна вы можете использовать здесь, чтобы облегчить связь между вашими классами, а также отвязать ваш код: publisher/subscriber. Моя любимая библиотека это EventBus:

Во-первых, добавить в свой build.gradle файл:

compile 'org.greenrobot:eventbus:3.0.0' 

Затем создайте простой POJO - Plain Old Java Object так:

public class OnReceiverEvent{ 
    private String phoneNumber; 

    public OnReceiverEvent(String phone){ 
     this.phoneNumber = phone; 
    } 

    public String getPhoneNumber(){ 
     return phoneNumber; 
    } 
} 

Далее, по сделав свой Receiver класс a publisher, и ваш Activity a subscriber, вы должны быть в состоянии легко передать информацию своей деятельности, например, является:

//inside your PhoneStateReceiver class when you want to pass info 

EventBus.getDefault().post(new OnReceiverEvent(phoneNumber)); 

Далее в вашей деятельности, просто сделать это:

//onStart 
@Override 
public void onStart(){ 
    super.onStart(); 
    EventBus.getDefault().register(this); 
} 

//onStop 
@Override 
public void onStop(){ 
    super.onStop(); 

    EventBus.getDefault().unregister(this); 
} 

Наконец, ручки размещены данные, то есть значение PHONENUMBER:

@Subscribe 
public void onPhoneNumberReceived(OnReceiverEvent event){ 
    //get the phone number value here and do something with it 

    String phoneNumber = event.getPhoneNumber(); 

    //display or something? 
} 

UPDATE

Если у вас есть еще Событие, на который вы хотите подписаться, это просто создать такой метод, как вы сделали в первом, используя аннотацию @Subscribe.

@Subscribe 
public void onSomeOtherEvent(EventClassName event){ 
    //get the variables here as usual; 
} 

Это самый простой способ передать данные из ресивера к вашей деятельности, не заботясь о начале деятельности снова и снова!

Надеюсь, это поможет и удачи!

+1

Ваш ответ дает краткое руководство по 'pub/sub', используя' EventBus'. –

+1

Я думаю, что это отличный ответ. Я тестировал и работал хорошо. Я просто прошу еще одну вещь о функции onStop. Потому что мое приложение можно запустить в фоновом режиме или в качестве службы. С этой целью PhoneStateReceiver по-прежнему получает входящий телефон. Можно ли принимать входящий телефон в Управлении, когда телефон находится в фоновом режиме или работает в службе? Я хочу спросить об этом, потому что, когда я нажимаю кнопку «Домой», данные не отправляются в Activity – Jame

+1

Ну, если вы хотите передать информацию из вашего ресивера на ваш сервис (когда приложение закрыто и работает в фоновом режиме) вы можете просто сделать то же самое в своем фоновом сервисе, что и в своей деятельности. Хорошая вещь о EventBus, вы можете использовать его с услугами, действиями, фрагментами и т. Д. – Eenvincible

1

Итак, я понимаю вас не хотите каждый раз воссоздавать свою деятельность.

В ваших Intent изменение этого флага поможет:

intent_phonenum.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 

В Intent класса, если вы сводка метод из FLAG_ACTIVITY_CLEAR_TOP:

  • Если установлены, и активность запускаются уже запущен в текущей задаче
  • , а затем вместо запуска нового экземпляра этого действия
  • все остальные действия на нем будут закрыты, и это намерение
  • будет доставлено на прежнюю деятельность (теперь сверху) как новое намерение. (Вы можете читать далее ...)

В этом случае: Если ваше приложение работает, и у вас есть экземпляр Activity, то Intent не воссоздаст вашу активность. Но предположим, что ваше приложение находится в закрытом состоянии, и когда BroadcastReceiver запускается, Intent создаст новую активность, потому что у вас нет экземпляра этой активности.

@Edit:

Вы можете указать специальный Intent подобное в вашем BroadcastReceiver:

public void onReceive(Context context, Intent intent) { 
    Bundle extras = intent.getExtras(); 
    Intent i = new Intent("mycustombroadcast"); 
    i.putExtra("phone_num", incomingNumber); 
    context.sendBroadcast(i); 
} 

Тогда в вашей деятельности внутри onCreate() регистра приемника так:

BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 

     Bundle bundle = intent.getExtras(); 

     int incoming_number= bundle.getInt("phone_num"); 

     Log.e("incoming number", "" + incoming_number); 
    } 
}; 
//then register receiver like that : 
registerReceiver(broadcastReceiver, new IntentFilter("mycustombroadcast")); 

Вы может отменить регистрацию Получателя в onDestroy(): unregisterReceiver(broadcastReceiver);

Также другой путь перекрывая onNewIntent() в вашей деятельности:

@Override 
protected void onNewIntent(Intent intent) { 
//your intent is here, you can do sth. 
super.onNewIntent(intent); 
} 
+0

Итак, как я могу знать, что событие данных посылает ReceiverActivity. Потому что мне нужно перенаправить данные на сервер через сокет – Jame

+0

@ user8430 Вы хотите получить входящий номер в своей «ReceiverActivity»? –

+0

Да. Но он не должен в функции onCreate(), потому что функция создает сокет и пользовательский интерфейс, поэтому я не хочу вызывать полученные данные в функции – Jame

3

Простой без каких-либо сторонних библиотек.

Удостоверьтесь, что BroadcastReceiver должен быть зарегистрирован, а также незарегистрирован на OnPause().

Вы должны сделать две вещи

зарегистрировать приемник в вас активности, как показано ниже.

public class MainActivity extends Activity { 

    Context context; 
    BroadcastReceiver updateUIReciver; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     context = this; 

     IntentFilter filter = new IntentFilter(); 
     filter.addAction("service.to.activity.transfer"); 
     updateUIReciver = new BroadcastReceiver() { 
      @Override 
      public void onReceive(Context context, Intent intent) { 
       //UI update here 
       if (intent != null) 
        Toast.makeText(context, intent.getStringExtra("number").toString(), Toast.LENGTH_LONG).show(); 
      } 
     }; 
     registerReceiver(updateUIReciver, filter); 
    } 
} 

Сейчас в вас обслуживать

public class PhoneStateReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     try { 
      System.out.println("Receiver start"); 
      String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 
      String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); 
      if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { 
       Intent local = new Intent(); 
       local.setAction("service.to.activity.transfer"); 
       local.putExtra("number", incomingNumber); 
       context.sendBroadcast(local); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

Спасибо, что дали мне решение – Jame

 Смежные вопросы

  • Нет связанных вопросов^_^