J'ai lu le texte suivant sur le site des développeurs Android, plus précisément dans les rubriques Framework -> Services -> Démarrer un service .
Il y est indiqué ce qui suit:
Si le service ne fournit pas également de liaison, l'intention fournie avec startService () est le seul mode de communication entre le composant d'application et le service. Toutefois, si vous souhaitez que le service renvoie un résultat, le client qui démarre le service peut créer un PendingIntent pour une diffusion (avec getBroadcast ()) et le remettre au service dans l'intention qui lance le service. Le service peut ensuite utiliser la diffusion pour fournir un résultat.
J'ai quelques questions à ce sujet:
Service
s etIntentService
s?Service
; Le service peut ensuite utiliser la diffusion pour fournir un résultat. et aussi où la diffusion mentionnée fournirait-elle le résultat au client/activité d'origine? Y at-il une méthode qui devrait être écrasée (comme onActivityResult()
) ou quelque chose?
La question a été posée il y a quelques mois, mais si quelqu'un cherche toujours une réponse, j'espère pouvoir vous aider.
Dans l'exemple ci-dessous, nous avons un service local, chargé d'effectuer certaines opérations fastidieuses. Activity envoie les demandes au service, mais ne s'y associe pas - envoie simplement l'intention avec la demande. De plus, Activity inclut les informations de BroadcastReceiver qui doivent être rappelées lorsque le service est terminé avec la tâche demandée. Les informations sont transmises par PendingIntent. Le service gère la tâche en arrière-plan et lorsque la tâche est terminée, il diffuse BroadcastReceiver avec une réponse.
1. Créer une sous-classe BroadcastReceiver:
public class DataBroadcastReceiver extends BroadcastReceiver {
static Logger log = LoggerFactory.getLogger(DataRequestService.class);
@Override
public void onReceive(Context context, Intent intent) {
log.info(" onReceive");
}
}
Ce récepteur de diffusion sera avisé du service une fois la tâche terminée.
2. Créer un service
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);
}
La partie la plus importante est dans la méthode handleMessage (). Le service effectue simplement l'opération de diffusion pour fournir les résultats au récepteur de radiodiffusion.
3. Vous devez également enregistrer votre récepteur de radiodiffusion et votre service dans 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. Et enfin, demandez à votre service de l'activité:
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. Réponse fournie au client/activité d'origine .
Vous pouvez avoir une activité abstraite à partir de laquelle toutes vos activités seront étendues. Cette activité abstraite peut s'inscrire/désenregistrer automatiquement comme écouteur de réponse dans le récepteur de radiodiffusion. En réalité, il n’ya pas beaucoup d’options ici, mais il est important que si vous gardiez des références statiques à votre activité, vous devez supprimer le référent lorsque l’activité est détruite.
Cordialement,
Rampes
Pour effectuer la communication entre service et activité . Vous pouvez également utiliser Binder comme mentionné dans l'exemple Android officiel http://developer.Android.com/reference/Android/app/Service.html#LocalServiceSample
Pour une explication détaillée, voir cette réponse https://stackoverflow.com/a/36983011/4754141
Comme écrit ici
La communication entre service et activité peut être effectuée à l'aide de PendingIntent.For qui peut utiliser createPendingResult () . CreatePendingResult () crée un nouvel objet PendingIntent que vous pouvez remettre au service. à utiliser et à renvoyer les données de résultat à votre activité dans callActivityResult (int, int, Intent) callback. Depuis un PendingIntent est colis, et peut donc être placé dans une Intention extra, votre activité peut transmettre ce PendingIntent au service. Le service, à son tour, peut appeler la méthode send () Du PendingIntent pour notifier l’activité via OnActivityResult of un évènement.
Activité
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); } }
Un service
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); } } } } }