Я читал следующий текст на сайте разработчиков Android, в частности, в разделе Темы фреймворка -> Службы -> Запуск службы .
Там говорится следующее:
Если служба также не обеспечивает привязку, намерение, доставленное с помощью startService (), является единственный способ связи между компонентом приложения и службой. Однако, если вы хотите, чтобы служба отправляла результат обратно, то клиент, запускающий службу, может создать PendingIntent для трансляции (с помощью getBroadcast ()) и доставить его службе в намерении, запускающем службу. Затем служба может использовать широковещательную рассылку для доставки результата.
У меня есть пара вопросов по этому поводу:
Service
s и IntentService
s?
; Затем служба может использовать широковещательную рассылку для доставки результата. а также где упомянутая трансляция доставит результат исходному клиенту / действию? Есть ли какой-то метод, который следует перезаписать (например, onActivityResult ()
) или что-то в этом роде?
Вопрос задавался несколько месяцев назад, но, если кто-то все еще ищет ответ, я надеюсь, что смогу помочь.
В приведенном ниже примере у нас есть локальная служба, отвечающая за выполнение некоторых трудоемких операций. Активность делает запросы к службе, но не привязывается к ней - просто отправляет намерение с запросом. Кроме того, 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. Create 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);
}
Ну, самая важная часть в методе 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. Доставка ответа исходному клиенту / деятельности .
Вы можете заниматься абстрактной деятельностью, от которой будут расширяться все ваши действия. Эта абстрактная деятельность может автоматически регистрировать / отменять регистрацию себя в качестве прослушивателя ответа в широковещательном приемнике. На самом деле здесь не так много вариантов, но важно, что если вы сохраняете статические ссылки на свою деятельность, то вы должны удалить ссылку, когда деятельность уничтожена.
С уважением,
Рампы
Как написано здесь
Связь между службой и Activity может быть выполнена с использованием PendingIntent. Для этого мы можем использовать createPendingResult () .createPendingResult () создает новый объект PendingIntent, который вы можете передать службе для использования и отправки данных результатов обратно в вашу деятельность внутри обратного вызова onActivityResult (int, int, Intent). Поскольку PendingIntent имеет значение Parcelable, и поэтому его можно поместить в дополнительный Intent, ваш Activity может передать этот PendingIntent в службу. В свою очередь, служба может вызвать метод PendingIntent в 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); } } } } }