stopservice servicio saber notification intent implement how example esta ejemplo corriendo como android android-activity android-service

android - saber - Ejemplo: comunicación entre actividad y servicio mediante mensajería.



service android ejemplo (9)

No pude encontrar ningún ejemplo de cómo enviar mensajes entre una actividad y un servicio, y he pasado demasiadas horas resolviendo esto. Aquí hay un proyecto de ejemplo para que otros puedan consultar.

Este ejemplo le permite iniciar o detener un servicio directamente, y vincular / desvincular por separado del servicio. Cuando el servicio está en ejecución, incrementa un número a 10 Hz. Si la actividad está vinculada al Service , mostrará el valor actual. Los datos se transfieren como un entero y como una cadena para que pueda ver cómo hacerlo de dos maneras diferentes. También hay botones en la actividad para enviar mensajes al servicio (cambia el valor de incremento por).

Captura de pantalla:

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.exampleservice" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyService"></service> </application> <uses-sdk android:minSdkVersion="8" /> </manifest>

res / values ​​/ strings.xml:

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">ExampleService</string> <string name="service_started">Example Service started</string> <string name="service_label">Example Service Label</string> </resources>

res / layout / main.xml:

<RelativeLayout android:id="@+id/RelativeLayout01" android:layout_width="fill_parent" android:layout_height="wrap_content" > <Button android:id="@+id/btnStart" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start Service" > </Button> <Button android:id="@+id/btnStop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="Stop Service" > </Button> </RelativeLayout> <RelativeLayout android:id="@+id/RelativeLayout02" android:layout_width="fill_parent" android:layout_height="wrap_content" > <Button android:id="@+id/btnBind" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Bind to Service" > </Button> <Button android:id="@+id/btnUnbind" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="Unbind from Service" > </Button> </RelativeLayout> <TextView android:id="@+id/textStatus" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Status Goes Here" android:textSize="24sp" /> <TextView android:id="@+id/textIntValue" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Integer Value Goes Here" android:textSize="24sp" /> <TextView android:id="@+id/textStrValue" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="String Value Goes Here" android:textSize="24sp" /> <RelativeLayout android:id="@+id/RelativeLayout03" android:layout_width="fill_parent" android:layout_height="wrap_content" > <Button android:id="@+id/btnUpby1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Increment by 1" > </Button> <Button android:id="@+id/btnUpby10" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="Increment by 10" > </Button> </RelativeLayout>

src / com.exampleservice / MainActivity.java:

package com.exampleservice; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { Button btnStart, btnStop, btnBind, btnUnbind, btnUpby1, btnUpby10; TextView textStatus, textIntValue, textStrValue; Messenger mService = null; boolean mIsBound; final Messenger mMessenger = new Messenger(new IncomingHandler()); class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MyService.MSG_SET_INT_VALUE: textIntValue.setText("Int Message: " + msg.arg1); break; case MyService.MSG_SET_STRING_VALUE: String str1 = msg.getData().getString("str1"); textStrValue.setText("Str Message: " + str1); break; default: super.handleMessage(msg); } } } private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = new Messenger(service); textStatus.setText("Attached."); try { Message msg = Message.obtain(null, MyService.MSG_REGISTER_CLIENT); msg.replyTo = mMessenger; mService.send(msg); } catch (RemoteException e) { // In this case the service has crashed before we could even do anything with it } } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been unexpectedly disconnected - process crashed. mService = null; textStatus.setText("Disconnected."); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnStart = (Button)findViewById(R.id.btnStart); btnStop = (Button)findViewById(R.id.btnStop); btnBind = (Button)findViewById(R.id.btnBind); btnUnbind = (Button)findViewById(R.id.btnUnbind); textStatus = (TextView)findViewById(R.id.textStatus); textIntValue = (TextView)findViewById(R.id.textIntValue); textStrValue = (TextView)findViewById(R.id.textStrValue); btnUpby1 = (Button)findViewById(R.id.btnUpby1); btnUpby10 = (Button)findViewById(R.id.btnUpby10); btnStart.setOnClickListener(btnStartListener); btnStop.setOnClickListener(btnStopListener); btnBind.setOnClickListener(btnBindListener); btnUnbind.setOnClickListener(btnUnbindListener); btnUpby1.setOnClickListener(btnUpby1Listener); btnUpby10.setOnClickListener(btnUpby10Listener); restoreMe(savedInstanceState); CheckIfServiceIsRunning(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("textStatus", textStatus.getText().toString()); outState.putString("textIntValue", textIntValue.getText().toString()); outState.putString("textStrValue", textStrValue.getText().toString()); } private void restoreMe(Bundle state) { if (state!=null) { textStatus.setText(state.getString("textStatus")); textIntValue.setText(state.getString("textIntValue")); textStrValue.setText(state.getString("textStrValue")); } } private void CheckIfServiceIsRunning() { //If the service is running when the activity starts, we want to automatically bind to it. if (MyService.isRunning()) { doBindService(); } } private OnClickListener btnStartListener = new OnClickListener() { public void onClick(View v){ startService(new Intent(MainActivity.this, MyService.class)); } }; private OnClickListener btnStopListener = new OnClickListener() { public void onClick(View v){ doUnbindService(); stopService(new Intent(MainActivity.this, MyService.class)); } }; private OnClickListener btnBindListener = new OnClickListener() { public void onClick(View v){ doBindService(); } }; private OnClickListener btnUnbindListener = new OnClickListener() { public void onClick(View v){ doUnbindService(); } }; private OnClickListener btnUpby1Listener = new OnClickListener() { public void onClick(View v){ sendMessageToService(1); } }; private OnClickListener btnUpby10Listener = new OnClickListener() { public void onClick(View v){ sendMessageToService(10); } }; private void sendMessageToService(int intvaluetosend) { if (mIsBound) { if (mService != null) { try { Message msg = Message.obtain(null, MyService.MSG_SET_INT_VALUE, intvaluetosend, 0); msg.replyTo = mMessenger; mService.send(msg); } catch (RemoteException e) { } } } } void doBindService() { bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE); mIsBound = true; textStatus.setText("Binding."); } void doUnbindService() { if (mIsBound) { // If we have received the service, and hence registered with it, then now is the time to unregister. if (mService != null) { try { Message msg = Message.obtain(null, MyService.MSG_UNREGISTER_CLIENT); msg.replyTo = mMessenger; mService.send(msg); } catch (RemoteException e) { // There is nothing special we need to do if the service has crashed. } } // Detach our existing connection. unbindService(mConnection); mIsBound = false; textStatus.setText("Unbinding."); } } @Override protected void onDestroy() { super.onDestroy(); try { doUnbindService(); } catch (Throwable t) { Log.e("MainActivity", "Failed to unbind from the service", t); } } }

src / com.exampleservice / MyService.java:

package com.exampleservice; import java.util.ArrayList; import java.util.Timer; import java.util.TimerTask; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; public class MyService extends Service { private NotificationManager nm; private Timer timer = new Timer(); private int counter = 0, incrementby = 1; private static boolean isRunning = false; ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients. int mValue = 0; // Holds last value set by a client. static final int MSG_REGISTER_CLIENT = 1; static final int MSG_UNREGISTER_CLIENT = 2; static final int MSG_SET_INT_VALUE = 3; static final int MSG_SET_STRING_VALUE = 4; final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler. @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } class IncomingHandler extends Handler { // Handler of incoming messages from clients. @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_REGISTER_CLIENT: mClients.add(msg.replyTo); break; case MSG_UNREGISTER_CLIENT: mClients.remove(msg.replyTo); break; case MSG_SET_INT_VALUE: incrementby = msg.arg1; break; default: super.handleMessage(msg); } } } private void sendMessageToUI(int intvaluetosend) { for (int i=mClients.size()-1; i>=0; i--) { try { // Send data as an Integer mClients.get(i).send(Message.obtain(null, MSG_SET_INT_VALUE, intvaluetosend, 0)); //Send data as a String Bundle b = new Bundle(); b.putString("str1", "ab" + intvaluetosend + "cd"); Message msg = Message.obtain(null, MSG_SET_STRING_VALUE); msg.setData(b); mClients.get(i).send(msg); } catch (RemoteException e) { // The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop. mClients.remove(i); } } } @Override public void onCreate() { super.onCreate(); Log.i("MyService", "Service Started."); showNotification(); timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 0, 100L); isRunning = true; } private void showNotification() { nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); // In this sample, we''ll use the same text for the ticker and the expanded notification CharSequence text = getText(R.string.service_started); // Set the icon, scrolling text and timestamp Notification notification = new Notification(R.drawable.icon, text, System.currentTimeMillis()); // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0); // Set the info for the views that show in the notification panel. notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent); // Send the notification. // We use a layout id because it is a unique number. We use it later to cancel. nm.notify(R.string.service_started, notification); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("MyService", "Received start id " + startId + ": " + intent); return START_STICKY; // run until explicitly stopped. } public static boolean isRunning() { return isRunning; } private void onTimerTick() { Log.i("TimerTick", "Timer doing work." + counter); try { counter += incrementby; sendMessageToUI(counter); } catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks. Log.e("TimerTick", "Timer Tick Failed.", t); } } @Override public void onDestroy() { super.onDestroy(); if (timer != null) {timer.cancel();} counter=0; nm.cancel(R.string.service_started); // Cancel the persistent notification. Log.i("MyService", "Service Stopped."); isRunning = false; } }


Así es como implementé Activity-> Service Communication: en mi actividad tuve

private static class MyResultReciever extends ResultReceiver { /** * Create a new ResultReceive to receive results. Your * {@link #onReceiveResult} method will be called from the thread running * <var>handler</var> if given, or from an arbitrary thread if null. * * @param handler */ public MyResultReciever(Handler handler) { super(handler); } @Override protected void onReceiveResult(int resultCode, Bundle resultData) { if (resultCode == 100) { //dostuff } }

Y luego usé esto para iniciar mi servicio

protected void onCreate(Bundle savedInstanceState) { MyResultReciever resultReciever = new MyResultReciever(handler); service = new Intent(this, MyService.class); service.putExtra("receiver", resultReciever); startService(service); }

En mi servicio tuve

public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) resultReceiver = intent.getParcelableExtra("receiver"); return Service.START_STICKY; }

Espero que esto ayude


Gran tutorial, fantástica presentación. Limpio, simple, corto y muy explicativo. Aunque, notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent); El método ya no existe. Como trante dijo here , un buen enfoque sería:

private static final int NOTIFICATION_ID = 45349; private void showNotification() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("My Notification Title") .setContentText("Something interesting happened"); Intent targetIntent = new Intent(this, MainActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, targetIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(contentIntent); _nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); _nManager.notify(NOTIFICATION_ID, builder.build()); } @Override public void onDestroy() { super.onDestroy(); if (_timer != null) {_timer.cancel();} _counter=0; _nManager.cancel(NOTIFICATION_ID); // Cancel the persistent notification. Log.i("PlaybackService", "Service Stopped."); _isRunning = false; }

Comprobado por mí mismo, todo funciona como un encanto (los nombres de actividades y servicios pueden diferir de los originales).


He visto todas las respuestas. Quiero decir de manera más robusta ahora un día . Eso te hará comunicarte entre Activity - Service - Dialog - Fragments (Todo).

EventBus

Esta biblioteca que estoy usando en mis proyectos tiene excelentes funciones relacionadas con la mensajería.

EventBus en 3 pasos

  1. Definir eventos:

    public static class MessageEvent { /* Additional fields if needed */ }

  2. Preparar suscriptores:

Declare y anote su método de suscripción, opcionalmente especifique un modo de hilo :

@Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) {/* Do something */};

Regístrese y anule el registro de su suscriptor. Por ejemplo, en Android, las actividades y los fragmentos deben registrarse de acuerdo con su ciclo de vida:

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

  1. Publicar eventos:

    EventBus.getDefault().post(new MessageEvent());

Solo agrega esta dependencia en tu nivel de aplicación gradle

compile ''org.greenrobot:eventbus:3.1.1''


Me parece que podrías haber guardado algo de memoria declarando tu actividad con "implementa Handler.Callback"


Mira el ejemplo de LocalService .

Su Service devuelve una instancia de sí mismo a los consumidores que llaman a onBind . Luego puede interactuar directamente con el servicio, por ejemplo, registrando su propia interfaz de escucha con el servicio, para que pueda obtener devoluciones de llamada.


Nota: no necesita verificar si su servicio se está ejecutando, CheckIfServiceIsRunning() , porque bindService() lo iniciará si no se está ejecutando.

Además: si gira el teléfono, no quiere que bindService() a bindService() , porque se onCreate() a bindService() a bindService() . Asegúrese de definir onConfigurationChanged() para evitar esto.


Para enviar datos a un servicio puede utilizar:

Intent intent = new Intent(getApplicationContext(), YourService.class); intent.putExtra("SomeData","ItValue"); startService(intent);

Y después de estar en servicio en onStartCommand (), obtenga datos de la intención.

Para enviar datos o eventos desde un servicio a una aplicación (para una o más actividades):

private void sendBroadcastMessage(String intentFilterName, int arg1, String extraKey) { Intent intent = new Intent(intentFilterName); if (arg1 != -1 && extraKey != null) { intent.putExtra(extraKey, arg1); } sendBroadcast(intent); }

Este método está llamando desde su servicio. Simplemente puede enviar datos para su actividad.

private void someTaskInYourService(){ //For example you downloading from server 1000 files for(int i = 0; i < 1000; i++) { Thread.sleep(5000) // 5 seconds. Catch in try-catch block sendBroadCastMessage(Events.UPDATE_DOWNLOADING_PROGRESSBAR, i,0,"up_download_progress"); }

Para recibir un evento con datos, cree y registre el método registerBroadcastReceivers () en su actividad:

private void registerBroadcastReceivers(){ broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int arg1 = intent.getIntExtra("up_download_progress",0); progressBar.setProgress(arg1); } }; IntentFilter progressfilter = new IntentFilter(Events.UPDATE_DOWNLOADING_PROGRESS); registerReceiver(broadcastReceiver,progressfilter);

Para enviar más datos, puede modificar el método sendBroadcastMessage(); . Recuerde: debe registrar transmisiones en onResume () y anular el registro en métodos onStop ().

ACTUALIZAR

Por favor, no use mi tipo de comunicación entre Actividad y Servicio. Esta es la manera incorrecta Para una mejor experiencia por favor use libs especiales, como nosotros:

1) EventBus de greenrobot

2) Otto de Square Inc

PD Solo uso EventBus de greenrobot en mis proyectos,


Todo está bien. Buen ejemplo de comunicación de activity/service utilizando Messenger .

Un comentario: el método MyService.isRunning() no es obligatorio .. bindService() se puede hacer cualquier número de veces. no hay daño en eso

Si MyService se ejecuta en un proceso diferente, la función estática MyService.isRunning() siempre devolverá false. Así que no hay necesidad de esta función.


Message msg = Message.obtain(null, 2, 0, 0); Bundle bundle = new Bundle(); bundle.putString("url", url); bundle.putString("names", names); bundle.putString("captions",captions); msg.setData(bundle);

Así que lo envías al servicio. Después de recibir.