studio - notificaciones push android firebase
¿Cómo usar PendingIntent para comunicarse desde un servicio a un cliente/actividad? (3)
He estado leyendo el siguiente texto en el sitio de desarrolladores de Android, específicamente en los temas del marco -> Servicios -> Iniciar un servicio .
Allí dice lo siguiente:
Si el servicio no proporciona también enlace, la intención entregada con startService () es el único modo de comunicación entre el componente de la aplicación y el servicio. Sin embargo, si desea que el servicio devuelva un resultado, entonces el cliente que inicia el servicio puede crear un PendingIntent para una transmisión (con getBroadcast ()) y entregarlo al servicio en la Intención que inicia el servicio. El servicio puede usar la transmisión para entregar un resultado.
Tengo un par de preguntas sobre esto:
- ¿Este texto se aplica a los
Service
eIntentService
? - ¿Cómo (en forma de código) se debe lograr esto dentro del
Service
? El servicio puede usar la transmisión para entregar un resultado. y también, ¿dónde la transmisión mencionada entregaría el resultado al cliente / actividad original? ¿Hay algún método que deba sobrescribirse (comoonActivityResult()
) o algo así?
Como esta escrito here
La comunicación entre el servicio y la Actividad se puede hacer usando PendingIntent. Para que podamos usar createPendingResult () .createPendingResult () crea un nuevo objeto PendingIntent que puede entregar al servicio para usar y enviar datos de resultados a su actividad en onActivityResult (int, int, Intent) devolución de llamada. Dado que un PendingIntent es Parcelable y, por lo tanto, se puede poner en un Intent extra, su actividad puede pasar este PendingIntent al servicio. El servicio, a su vez, puede llamar al método send () en el PendingIntent para notificar al Actividad a través de onActivityResult 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); } } } } }
Para realizar comunicación entre servicio y actividad . También puede usar Binder como se menciona en el Ejemplo oficial de Android http://developer.android.com/reference/android/app/Service.html#LocalServiceSample
Para una explicación detallada, consulte estas respuestas https://.com/a/36983011/4754141
La pregunta se hizo hace unos meses, pero en caso de que alguien todavía esté buscando una respuesta, espero poder ayudar.
En el siguiente ejemplo tenemos servicio local, responsable de realizar algunas operaciones que requieren mucho tiempo. La actividad realiza las solicitudes al servicio, pero no se enlaza con él, solo envía el intento con la solicitud. Además, Actividad incluye la información de BroadcastReceiver que debe devolverse cuando se realiza el servicio con la tarea solicitada. La información es pasada por PendingIntent. El servicio maneja la tarea en un subproceso en segundo plano y cuando la tarea finaliza, el servicio transmite BroadcastReceiver con una respuesta.
1. Crear la subclase BroadcastReceiver:
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 difusión será notificado desde el 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 está en el método handleMessage (). El servicio simplemente hace la operación de transmisión para entregar resultados a Broadcast Receiver.
3. También debe registrar su receptor y servicio de difusión 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, realizar solicitud a su servicio de 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. Dar respuesta al cliente / actividad original .
Puede tener actividad abstracta desde la cual se extenderán todas sus actividades. Esta actividad abstracta puede registrarse / anularse automáticamente como 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, debe eliminar la referencia cuando se destruya la actividad.
Saludos,
Rampas