2013-02-27 14 views
11

Sono riuscito a ottenere il mio headset buttons get recognized dalla mia app quando premuto, ma uno dei pulsanti deve chiamare un metodo che è in MyCustomActivity. Il problema è il 1 ° parametro di OnReceive è un contesto che non può essere gettato alle attività e utilizzando classe interna di un MyCustomActivitywon't work in Android 4.1 meno che non sia statica (che ha lo stesso problema di impossibilità di accedere il metodo di MyCustomActivity.Come passare un parametro ad una sottoclasse di BroadcastReceiver?

Quindi l'unica opzione a sinistra per me (al fine di sostenere sia 2.xe 4.1) è quello di passare l'attività come parametro per RemoteControlReceiver

Ma come faccio a farlo, quando l'unico modo per istanziare è via:.

private ComponentName mRemoteControlReceiver = new ComponentName(this, RemoteControlReceiver.class); 

Quale non acc ept eventuali parametri aggiuntivi?

Qualche idea su come aggirare questa limitazione?

Nota: Se provo a definire RemoteControlReceiver come avere un costruttore con un parametro, ricevo la seguente eccezione:

E/AndroidRuntime(2836): java.lang.RuntimeException: Unable to instantiate receiver com.example.RemoteControlReceiver: java.lang.InstantiationException: can't instantiate class com.example.RemoteControlReceiver; no empty constructor 

Caused by: 
E/AndroidRuntime(2836): Caused by: java.lang.InstantiationException: can't instantiate class com.example.RemoteControlReceiver; no empty constructor 
E/AndroidRuntime(2836):  at java.lang.Class.newInstanceImpl(Native Method) 
E/AndroidRuntime(2836):  at java.lang.Class.newInstance(Class.java:1319) 
E/AndroidRuntime(2836):  at android.app.ActivityThread.handleReceiver(ActivityThread.java:2205) 

Quindi è chiaro che questo nuovo requisito registerMediaButtonEventReceiver (introdotto in Android 4.1) si aspetta un costruttore vuoto .

Non c'è modo di aggirare questo problema?

Ad esempio, esiste un modo per ottenere un riferimento all'oggetto RemoteControlReceiver effettivo (istanziato indirettamente tramite mAudioManager.registerMediaButtonEventReceiver())? In modo che possa utilizzare un accessor per impostare un membro di dati di RemoteControlReceiver dopo è stato istanziato?

+1

È possibile creare e registrare BroadcastReceier in onResume/onCreate dell'attività e annullare la registrazione all'interno di onPause/onStop. In questo modo l'attività corrente può occuparsi della sua durata e il ricevitore dovrebbe essere in grado di comunicare al suo contenitore (attività). –

+2

@SudarNimalan L'ho già provato. Questo [funziona solo su Android 2.x] (http://stackoverflow.com/questions/15058743/how-do-i-register-in-manifest-an-inner-media-button-broadcastreciver#comment21174031_15058783). Non funziona in 4.1. Devo essere in grado di sapere in qualche modo "RemoteControlReceiver' (non BroadcastReceiver!) Sapere su MyCustomActivity. Grazie. – an00b

+0

Questo è difficile ma ecco un'idea: puoi controllare [Extra] (http://stackoverflow.com/a/14383023/418055) passato con Intent onReceive? Oppure usa questo [trucco GlobalVariable] (http://stackoverflow.com/a/6980006/418055)? –

risposta

6

registerMediaButtonEventReceiver richiede che BroadcastReceiver sia dichiarato nel manifest dell'applicazione. Ciò significa che il ricevitore deve essere una classe autonoma, il che significa che non sa nulla della tua attuale attività o servizio.

Al fine di ottenere questo messaggio alla vostra attività o servizio, avete un certo numero di opzioni:

  • Utilizzare un globale statico per l'attività o il servizio in modo che il destinatario può inoltrare il messaggio ad esso. Questa non è generalmente una buona idea in quanto conduce a perdite e non è molto adattabile quando si desidera modificare il codice in un secondo momento. La statica è generalmente da evitare.

  • Riscrivere il messaggio a una classe specifica, che risulta essere una classe interna dell'attività o del servizio che si desidera richiamare. Per esempio. nel BroadcastReceiver per registerMediaButtonEventReceiver:

    // Standalone class, declared in the manifest 
    public class ButtonReceiver extends BroadcastReceiver { 
        @Override 
        public void onReceive(final Context context, final Intent intent) { 
         Intent intent = new Intent(); 
         intent.setAction("com.foo.ACTION"); 
    
         // Rebroadcasts to your own receiver. 
         // This receiver is not exported; it'll only be received if the receiver is currently registered. 
         context.sendBroadcast(intent); 
        } 
    } 
    

E nella vostra attività:

class MyActivity extends Activity { 
     private BroadcastReceiver myReceiver = new BroadcastReceiver() { 
      @Override 
      public void onReceive(final Context context, final Intent intent) { 
       MyActivity.this.onMessageReceived(); 
      } 
     } 
     @Override 
     protected void onResume() { 
      registerReceiver(myReceiver, new IntentFilter("com.foo.ACTION")); 
     } 

     @Override 
     protected void onPause() { 
      unregisterReceiver(myReceiver); 
     } 

     private void onMessageReceived() { 
     } 
    } 
  • Simile al metodo di cui sopra, non deve necessariamente essere una trasmissione, potrebbe essere un Intento passato all'attività, a seconda del tuo caso d'uso.Per fare questo invece di usare sendBroadcast, dovresti usare startActivity (o startService se stai usando un servizio).
+2

La tua ricetta di ritrasmissione funziona come un incantesimo. Grazie! – an00b

Problemi correlati