2013-02-15 7 views
25

Es gibt einen Dienst, der nach einer Stimme lauscht. Wenn Sprache mit einer Zeichenfolge übereinstimmt, wird eine bestimmte Methode im Dienstobjekt aufgerufen. DieseSo rufen Sie eine Methode in Aktivität von einem Dienst auf

public class SpeechActivationService extends Service { 

    public static Intent makeStartServiceIntent(Context pContext){  

     return new Intent(pContext, SpeechActivationService.class); 
    } 

    //... 

    public void onMatch(){ 
     Log.d(TAG, "voice matches word"); 
    } 

    //... 
} 

ist, wie ich den Dienst in meiner Tätigkeit beginnen:

Intent i = SpeechActivationService.makeStartServiceIntent(this); 
startService(i); 

Von diesem Service-Methode, wie kann ich eine Methode aufrufen, die in der Tätigkeit Objekt befindet? Ich möchte keinen Zugriff von Aktivität zu Service, sondern von Service zu Aktivität. Ich habe bereits über Handler und Sender gelesen, konnte aber kein Beispiel finden. Irgendwelche Ideen?

+0

Hat das Verfahren haben in der Aktivitätsklasse sein, oder können Sie es in eine Utility-Klasse bewegen? –

+0

Ich möchte die Benutzeroberfläche aktualisieren, so denke ich, dass es in der Aktivitätsklasse sein muss –

Antwort

2

Es gibt viele verschiedene Wege, dies zu achive. Einer von ihnen zu verwenden Handler und Messanger Klassen. Die Idee der Methode besteht darin, Handler Objekt von Activity zu Service zu übergeben. Jedes Mal, Service will eine Methode der Activity anrufen, sendet es einfach eine Message und Activity behandelt es irgendwie.

Aktivität:

public class MyActivity extends Activity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     final Handler handler = new Handler() { 
      @Override 
      public void handleMessage(Message msg) { 
       showToast(msg.what); 
      } 
     }; 

     final Intent intent = new Intent(this, MyService.class); 
     final Messenger messenger = new Messenger(handler); 

     intent.putExtra("messenger", messenger); 
     startService(intent); 
    } 

    private void showToast(int messageId) { 
     Toast.makeText(this, "Message " + messageId, Toast.LENGTH_SHORT).show(); 
    } 
} 

Service:

public class MyService extends Service { 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     if (intent != null) { 
      final Messenger messenger = (Messenger) intent.getParcelableExtra("messenger"); 
      final Message message = Message.obtain(null, 1234); 

      try { 
       messenger.send(message); 
      } catch (RemoteException exception) { 
       exception.printStackTrace(); 
      } 
     } 

     return START_NOT_STICKY; 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 
} 
+0

Mein Service erstreckt sich vom Service und nicht IntentService –

+0

Sie können 'Service' auch verwenden. Dieser Code zeigt nur die Idee. Ich habe meine Antwort aktualisiert und benutze nun 'Service' anstelle von' IntentService' –

+0

+1 Danke, ich habe es bereits mit dem Broadcast-Empfänger http://inchoo.net/mobile-development/android-development/broadcast-receiver-from geschafft -activity/ –

54

der Service und Aktivität Unter der Annahme, sind im selben Paket (dh die gleiche App) können Sie LocalBroadcastManager wie folgt verwenden:

In Ihrem Service:

// Send an Intent with an action named "my-event". 
private void sendMessage() { 
    Intent intent = new Intent("my-event"); 
    // add data 
    intent.putExtra("message", "data"); 
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent); 
} 

In Ihrer Aktivität:

@Override 
public void onResume() { 
    super.onResume(); 

    // Register mMessageReceiver to receive messages. 
    LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, 
     new IntentFilter("my-event")); 
} 

// handler for received Intents for the "my-event" event 
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
    // Extract data included in the Intent 
    String message = intent.getStringExtra("message"); 
    Log.d("receiver", "Got message: " + message); 
    } 
}; 

@Override 
protected void onPause() { 
    // Unregister since the activity is not visible 
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); 
    super.onPause(); 
} 

Aus Abschnitt 7.3 Verbindung des @ Ascorbin: http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html#ownreceiver_localbroadcastmanager

+3

Es funktioniert wie ein Charme, TY! –

+1

Das ist absolut großartig, danke Mann, du hast mich gerettet – Ale

+1

Danke Tony! Große Antwort – Nickmccomb

0

Nach einigen Recherchen habe ich die folgenden Timings in meinem Fall für das Senden und Empfangen der Sendung gefunden. Ich habe Dienst im selben Prozess.

sendBroadcast (nicht empfehlenswert, wenn beide Komponenten in gleichen Prozess sind) 34 sec

LocalBroadcastManager.getInstance (this).sendBroadcast (Absicht); der Nähe von 30 sec

mit AIDL Implementierung und RemoteCallbackList Wird für denselben Prozess oder anderen Prozess vom Dienst

In Ihrem Service

public final RemoteCallbackList<ICallBackAidl> mDMCallbacks = new RemoteCallbackList<ICallBackAidl>(); 

public void registerDMCallback(ICallBackAidl cb) { 
    Logger.d(LOG_TAG, "registerDMCallback " + cb); 
    if (cb != null) 
     mDMCallbacks.register(cb); 
} 

Wenn Sie anrufen müssen Methoden in Anwendung/Acitvity arbeiten

public void callMehodsInApplication() { 
    final int N = mDMCallbacks.beginBroadcast(); 
    for (int i = 0; i < N; i++) { 
     try { 
      mDMCallbacks.getBroadcastItem(i).method1(); 
     } catch (RemoteException e) { 
      e.printStackTrace(); 
     } 
    } 
    mDMCallbacks.finishBroadcast(); 
} 

In Ihrer Klasse ex Pflege von Anwendungen oder Aktivitäten.

private ISyncmlServiceDMCallback mCallback = new ISyncmlServiceDMCallback.Stub() { 
// Implement callback methods here 
    public void method1() { 
     // Service can call this method 
    } 
} 

public void onServiceConnected(ComponentName name, IBinder service) { 
     svc.LocalBinder binder = (svc.LocalBinder) service; 
     mSvc = binder.getService(); 
     mSvc.registerDMCallback(mCallback); 
} 

auf diese Weise aufrufen ist fast augenblicklich vom Rundfunk und Empfangen von demselben Prozess