2011-05-23 11 views
25

He estado leyendo el siguiente texto en el sitio de Desarrolladores de Android, específicamente en el Framework Topics -> Services -> Starting a Service.¿Cómo usar PendingIntent para comunicar de un servicio a un cliente/actividad?

Allí se indica lo siguiente:

Si el servicio no hacen también posible la unión, la intención entregado con StartService() es el único medio de comunicación entre el componente de aplicación y el servicio. Sin embargo, si desea que el servicio envíe un resultado, el cliente que inicia el servicio puede crear un PendingIntent para una transmisión (con getBroadcast()) y entregarlo al servicio en el Intent que inicia el servicio. El servicio puede usar la transmisión para entregar un resultado.

Tengo un par de preguntas con respecto a esto:

  1. dice este texto ambas se aplican a Service s y IntentService s?
  2. Cómo (código) debe lograrse esto dentro del Service; El servicio puede usar la transmisión para entregar un resultado. y también ¿dónde la emisión mencionada entregará el resultado al cliente/actividad original? ¿Hay algún método que deba sobrescribirse (como onActivityResult()) o algo así?

Respuesta

45


pregunta fue hecha hace unos meses, pero por si alguien todavía está buscando respuestas espero que pueda ayudar.

En el siguiente ejemplo tenemos el servicio local, responsable de realizar algunas operaciones que requieren mucho tiempo. La actividad realiza las solicitudes al servicio, pero no se vincula a ellas, solo envía el intento con la solicitud. Además, Activity incluye la información de BroadcastReceiver que se debe devolver cuando el servicio se realiza con la tarea solicitada. La información es pasada por PendingIntent. El servicio maneja la tarea en el hilo de fondo y cuando la tarea finaliza, el servicio transmite el BroadcastReceiver con una respuesta.

1. Crear BroadcastReceiver subclase:

public class DataBroadcastReceiver extends BroadcastReceiver { 
    static Logger log = LoggerFactory.getLogger(DataRequestService.class); 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     log.info(" onReceive"); 
    } 
} 

Este receptor de radiodifusión será notificado del servicio, cuando la tarea se realiza.

2. Crear Servicio

public class DataRequestService extends Service { 

    private final class ServiceHandler extends Handler { 
     public ServiceHandler(Looper looper) { 
     super(looper); 
     } 

     @Override 
     public void handleMessage(Message msg) { 
     log.info("handleMessage"); 
     //... performing some time-consuming operation   
     Bundle bundle = msg.getData(); 
     PendingIntent receiver = bundle.getParcelable("receiver"); 
     // Perform the operation associated with PendingIntent 
     try {    
      //you can attach data from the operation in the intent. 
      Intent intent = new Intent(); 
      Bundle b = new Bundle(); 
      //b.putString("key", value); 
      intent.putExtras(b); 
      receiver.send(getApplicationContext(), status, intent); 
     } catch (CanceledException e) {   
     e.printStackTrace(); 
     }   
     } 
    } 

    @Override 
    public void onStart(Intent intent, int startId) { 
     Bundle bundle = intent.getExtras(); 
     msg.setData(bundle); 
     mServiceHandler.sendMessage(msg); 
    } 

Bueno, la parte más importante es en el método handleMessage(). El servicio simplemente realiza la operación de difusión para entregar resultados a Broadcast Receiver.

3. También es necesario registrar su receptor de radiodifusión y el servicio en Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.ramps.servicetest" 
    android:versionCode="1" 
    android:versionName="1.0" > 
    .... 
     <service android:name=".service.DataRequestService" android:exported="false"/> 
     <receiver android:name=".service.DataBroadcastReceiver"></receiver> 
    </application> 
</manifest><br> 

4.Y, por último, hacer una petición al servicio de la actividad:

Intent serviceIntent = new Intent(context, DataRequestService.class); 
    @Override 
    public void onClick(View v) { 
     //this is the intent that will be broadcasted by service. 
     Intent broadcastReceiverIntent = new Intent(context, DataBroadcastReceiver.class);  
     //create pending intent for broadcasting the DataBroadcastReceiver 
     PendingIntent pi = PendingIntent.getBroadcast(context, 0, broadcastReceiverIntent, 0);  
     Bundle bundle = new Bundle();    
     bundle.putParcelable("receiver", pi); 
     //we want to start our service (for handling our time-consuming operation) 
     Intent serviceIntent = new Intent(context, DataRequestService.class); 
     serviceIntent.putExtras(bundle); 
     context.startService(serviceIntent); 
    } 



5. La entrega de respuesta a cliente original/actividad.

Puede tener una actividad abstracta a partir de la cual se extenderán todas sus actividades. Esta actividad absoluta puede registrarse/anularse automáticamente como un oyente de respuesta en el receptor de difusión. No hay muchas opciones aquí en realidad, pero es importante que si mantiene referencias estáticas a su actividad, entonces debe eliminar la referencia cuando se destruye la actividad.

Regards,
Rampas

+1

Por qué no simplemente invocar el BroadcastReceiver de servicio. ¿Todo esto se hace para ocultar el nombre de BroadcastReceiver del servicio? – Kiran

+0

¿Cuál es la necesidad de crear controlador aquí? .Podemos poner enviar transmisión en onStart() también. –

+1

@RohitBandil 'Service's se ejecuta en el subproceso de la interfaz de usuario, por lo que hacer la operación de fondo allí y enviar el resultado después sería frustrante el propósito de tener un servicio en segundo plano. 'IntentService' fue diseñado para ocultar esta complejidad de Handler de usted; no estoy seguro de por qué @Ramps no usó eso. – TWiStErRob

0

Como está escrito here

La comunicación entre el servicio y la actividad se puede realizar usando PendingIntent.Para eso podemos usar createPendingResult() .createPendi ngResult() crea un nuevo objeto PendingIntent que puede entregar al servicio para usar y enviar los datos de resultado a su actividad dentro de la retroligencia de activación de actividad (int, int, ). Como un PendingIntent es Parcelable, y puede ponerse en un Intent adicional, su actividad puede pasar este PendingIntent al servicio. El servicio, a su vez, puede llamar al método send() en PendingIntent para notificar a la actividad a través del sobre el resultado de la actividad de un evento.

Actividad

public class PendingIntentActivity extends AppCompatActivity 
{ 
@Override 
protected void onCreate(@Nullable Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 

PendingIntent pendingResult = createPendingResult(
100, new Intent(), 0); 
Intent intent = new Intent(getApplicationContext(), PendingIntentService.class); 
intent.putExtra("pendingIntent", pendingResult); 
startService(intent); 

} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
if (requestCode == 100 && resultCode==200) { 
Toast.makeText(this,data.getStringExtra("name"),Toast.LENGTH_LONG).show(); 
} 
super.onActivityResult(requestCode, resultCode, data); 
} 
} 

Servicio

public class PendingIntentService extends Service { 

    private static final String[] items= { "lorem", "ipsum", "dolor", 
      "sit", "amet", "consectetuer", "adipiscing", "elit", "morbi", 
      "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam", 
      "vel", "erat", "placerat", "ante", "porttitor", "sodales", 
      "pellentesque", "augue", "purus" }; 
    private PendingIntent data; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 

     data = intent.getParcelableExtra("pendingIntent"); 

     new LoadWordsThread().start(); 
     return START_NOT_STICKY; 
    } 

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

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
    } 

    class LoadWordsThread extends Thread { 
     @Override 
     public void run() { 
      for (String item : items) { 
       if (!isInterrupted()) { 

        Intent result = new Intent(); 
        result.putExtra("name", item); 
        try { 
         data.send(PendingIntentService.this,200,result); 
        } catch (PendingIntent.CanceledException e) { 

         e.printStackTrace(); 
        } 
        SystemClock.sleep(400); 

       } 
      } 
     } 
    } 
} 
Cuestiones relacionadas