Как использовать PendingIntent для связи между Сервисом и клиентом / Activity? - PullRequest
25 голосов
/ 23 мая 2011

Я читал следующий текст на сайте разработчиков Android, в частности в разделе Framework Framework -> Службы -> Запуск службы .

Там говорится следующее:

Если служба также не обеспечивает привязку, намерение, поставляемое с startService (), является единственным способом связи между компонентом приложения и службой. Однако если вы хотите, чтобы служба отправляла результат обратно, то клиент, запускающий службу, может создать PendingIntent для широковещательной передачи (с помощью getBroadcast ()) и доставить его службе в Intent, который запускает службу. Затем служба может использовать трансляцию для доставки результата.

У меня есть пара вопросов по этому поводу:

  1. Относится ли этот текст к Service s и IntentService s?
  2. Как (по кодам) это должно быть достигнуто из Service; Служба может затем использовать широковещательную передачу для доставки результата. а также где упомянутая широковещательная рассылка доставит результат исходному клиенту / деятельности? Есть какой-то метод, который должен быть перезаписан (например, onActivityResult()) или что-то еще?

Ответы [ 3 ]

45 голосов
/ 06 ноября 2011


Вопрос был задан несколько месяцев назад, но, если кто-то все еще ищет ответ, я надеюсь, что смогу помочь.

В приведенном ниже примере у нас есть местная служба, отвечающая за выполнение некоторых трудоемких операций. Активность делает запросы к службе, но не привязывается к ней - просто отправляет намерение с запросом. Кроме того, Activity включает в себя информацию BroadcastReceiver, которая должна быть отозвана, когда обслуживание выполняется с запрошенной задачей. Информация передана PendingIntent. Служба обрабатывает задачу в фоновом потоке, и когда задача завершается, служба передает BroadcastReceiver с ответом.

1. Создать подкласс BroadcastReceiver:

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

Этот приемник вещания будет уведомлен службой, когда задание выполнено.

2. Создать сервис

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);
   }

Ну, самая важная часть в методе handleMessage (). Сервис просто выполняет операцию широковещания для доставки результатов в Broadcast Receiver.

3. Вам также необходимо зарегистрировать свой вещательный приемник и сервис в 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. И, наконец, сделайте запрос к вашему сервису из Activity:

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. Доставка ответа оригинальному клиенту / деятельности .

Вы можете заниматься абстрактной деятельностью, от которой будут расширяться все ваши действия. Эта абстрактная деятельность может автоматически регистрировать / отменять регистрацию себя в качестве прослушивателя ответа в широковещательном приемнике. На самом деле здесь не так много вариантов, но важно, что если вы сохраняете статические ссылки на свою деятельность, вы должны удалить ссылку, когда деятельность уничтожена.

С уважением,
Рампы

0 голосов
/ 06 марта 2018

Как написано здесь

Связь между сервисом и активностью может быть выполнена с помощью PendingIntent. Для этого мы можем использовать createPendingResult () .createPendingResult () создает новый объект PendingIntent, который вы можете передать службе для использования и отправки возвращать данные к вашей деятельности внутри onActivityResult (int, int, Намерение) обратный вызов. Так как PendingIntent является Parcelable, и может поэтому вы должны быть включены в намерение дополнительно, ваша деятельность может пройти это PendingIntent к сервису. Сервис, в свою очередь, может вызвать send () метод на PendingIntent, чтобы уведомить активность через onActivityResult события.

активность

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);
}
}

Услуги

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);

                }
            }
        }
    }
}
0 голосов
/ 02 мая 2016

Для осуществления связи между услугой и деятельностью .Вы также можете использовать Binder, как упомянуто в официальном примере Android http://developer.android.com/reference/android/app/Service.html#LocalServiceSample

Для подробного объяснения см. Ответы https://stackoverflow.com/a/36983011/4754141

...