Bagaimana agar Layanan Android berkomunikasi dengan Activity

251

Saya sedang menulis aplikasi Android pertama saya dan mencoba untuk berkomunikasi antara layanan dan kegiatan. Saya memiliki Layanan yang akan berjalan di latar belakang dan melakukan beberapa gps dan pencatatan berdasarkan waktu. Saya akan memiliki Kegiatan yang akan digunakan untuk memulai dan menghentikan Layanan.

Jadi pertama-tama, saya harus dapat mengetahui apakah Layanan berjalan saat Kegiatan dimulai. Ada beberapa pertanyaan lain di sini tentang itu, jadi saya pikir saya bisa mengetahuinya (tapi jangan ragu untuk memberikan saran).

Masalah saya yang sebenarnya: jika Aktivitas berjalan dan Layanan dimulai, saya perlu cara agar Layanan mengirim pesan ke Aktivitas. String dan bilangan bulat sederhana pada titik ini - sebagian besar pesan status. Pesan-pesan tidak akan terjadi secara teratur, jadi saya tidak berpikir polling layanan adalah cara yang baik untuk pergi jika ada cara lain. Saya hanya ingin komunikasi ini ketika Aktivitas telah dimulai oleh pengguna - Saya tidak ingin memulai Kegiatan dari Layanan. Dengan kata lain, jika Anda memulai aktivitas dan layanan berjalan, Anda akan melihat beberapa pesan status di UI aktivitas ketika sesuatu yang menarik terjadi. Jika Anda tidak memulai Kegiatan, Anda tidak akan melihat pesan-pesan ini (mereka tidak begitu menarik).

Sepertinya saya harus dapat menentukan apakah Layanan berjalan, dan jika demikian, tambahkan Kegiatan sebagai pendengar. Kemudian hapus Aktivitas sebagai pendengar saat Aktivitas berhenti atau berhenti. Apakah itu benar-benar mungkin? Satu-satunya cara saya bisa melakukannya adalah dengan memiliki Activity mengimplementasikan Parcelable dan membangun file AIDL sehingga saya bisa meneruskannya melalui antarmuka jarak jauh Layanan. Namun itu kelihatannya berlebihan, dan saya tidak tahu bagaimana Activity seharusnya mengimplementasikan writeToParcel () / readFromParcel ().

Apakah ada cara yang lebih mudah atau lebih baik? Terima kasih atas bantuannya.

EDIT:

Bagi siapa pun yang tertarik dengan ini nanti, ada kode sampel dari Google untuk menangani ini melalui AIDL di direktori sampel: /apis/app/RemoteService.java

Scott Saunders
sumber

Jawaban:

94

Ada tiga cara yang jelas untuk berkomunikasi dengan layanan:

  1. Menggunakan Intents
  2. Menggunakan AIDL
  3. Menggunakan objek layanan itu sendiri (sebagai singleton)

Dalam kasus Anda, saya akan menggunakan opsi 3. Buat referensi statis ke layanan itu sendiri dan isi di onCreate ():

void onCreate(Intent i) {
  sInstance = this;
}

Buat fungsi statis MyService getInstance(), yang mengembalikan statis sInstance.

Kemudian di dalam Activity.onCreate()Anda memulai layanan, tunggu secara tidak sinkron sampai layanan benar-benar dimulai (Anda bisa meminta layanan Anda memberi tahu aplikasi Anda bahwa ia siap dengan mengirimkan maksud ke aktivitas tersebut.) Dan mendapatkan instansnya. Ketika Anda memiliki instance, daftarkan objek pendengar layanan Anda ke layanan Anda dan Anda ditetapkan. CATATAN: saat mengedit Tampilan di dalam Aktivitas Anda harus memodifikasinya di utas UI, layanan mungkin akan menjalankan Utasnya sendiri, jadi Anda perlu menelepon Activity.runOnUiThread().

Hal terakhir yang perlu Anda lakukan adalah menghapus referensi untuk objek pendengar Anda Activity.onPause(), jika tidak, contoh konteks aktivitas Anda akan bocor, tidak baik.

CATATAN: Metode ini hanya berguna ketika aplikasi / Aktivitas / tugas Anda adalah satu-satunya proses yang akan mengakses layanan Anda. Jika tidak, Anda harus menggunakan opsi 1. atau 2.

MrSnowflake
sumber
2
Bagaimana saya bisa busy-waitberaktifitas? Bisakah Anda jelaskan?
iTurki
1
Jadi, baik setelah onCreate atau setelah onStartCommand di kelas layanan Anda, tetapkan variabel statis publik, sebut saja itu terkoneksi atau sesuatu yang benar. Kemudian di Aktivitas Anda lakukan ini: Intent intent = new Intent (act, YourService.class); startService (niat); while (! YourService.isConnected) {sleep (300); } Setelah loop itu, layanan Anda berjalan dan Anda dapat melakukan komunikasi dengannya .. Dalam pengalaman saya pasti ada beberapa batasan untuk berinteraksi dengan layanan seperti ini.
Matt Wolfe
Mengapa hanya bisa dimulai di Activity.onCreate()?
skywall
Ada alasan mengapa Anda tidak ingin menggunakan Intentsdengan mengirimkan data melalui Parcellablepesan di antara mereka?
Aman Alam
2
Ini berfungsi, tetapi jawaban @ MaximumGoat jauh lebih bersih dan tidak melibatkan kesibukan apa pun.
Matt
262

Penanya mungkin sudah lama pindah melewati ini, tetapi kalau-kalau ada orang lain yang mencari ini ...

Ada cara lain untuk menangani ini, yang saya pikir mungkin yang paling sederhana.

Tambahkan BroadcastReceiverke aktivitas Anda. Daftarkan untuk menerima beberapa maksud khusus onResumedan batalkan pendaftarannya onPause. Kemudian kirimkan niat itu dari layanan Anda ketika Anda ingin mengirimkan pembaruan status Anda atau apa pun yang Anda miliki.

Pastikan Anda tidak akan bahagia jika beberapa aplikasi lain mendengarkan Anda Intent(adakah yang bisa melakukan sesuatu yang jahat?), Tetapi di luar itu, Anda seharusnya baik-baik saja.

Sampel kode diminta:

Dalam layanan saya, saya punya ini:

// Do stuff that alters the content of my local SQLite Database
sendBroadcast(new Intent(RefreshTask.REFRESH_DATA_INTENT));

( RefreshTask.REFRESH_DATA_INTENThanya string konstan.)

Dalam kegiatan mendengarkan saya, saya mendefinisikan BroadcastReceiver:

private class DataUpdateReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(RefreshTask.REFRESH_DATA_INTENT)) {
          // Do stuff - maybe update my view based on the changed DB contents
        }
    }
}

Saya menyatakan penerima saya di bagian atas kelas:

private DataUpdateReceiver dataUpdateReceiver;

Saya mengganti onResumeuntuk menambahkan ini:

if (dataUpdateReceiver == null) dataUpdateReceiver = new DataUpdateReceiver();
IntentFilter intentFilter = new IntentFilter(RefreshTask.REFRESH_DATA_INTENT);
registerReceiver(dataUpdateReceiver, intentFilter);

Dan saya mengganti onPauseuntuk menambahkan:

if (dataUpdateReceiver != null) unregisterReceiver(dataUpdateReceiver);

Sekarang aktivitas saya mendengarkan layanan saya untuk mengatakan "Hei, perbarui sendiri." Saya bisa meneruskan data di Intentalih - alih memperbarui tabel database dan kemudian kembali untuk menemukan perubahan dalam aktivitas saya, tetapi karena saya ingin perubahan tetap ada, masuk akal untuk meneruskan data melalui DB.

MaximumGoat
sumber
5
Bagaimana? Apa yang Anda gambarkan adalah persis apa yang saya butuhkan. Tetapi lebih dari itu, saya perlu kode sampel lengkap. Terima kasih sebelumnya. FYI, terakhir kali saya mencoba menulis widget, bagian pengiriman pesan memakan waktu 2 bulan. Tertawa jika Anda mau, tetapi Anda para ahli perlu menerbitkan lebih banyak karena IMHO Android lebih rumit daripada iOS!
1
aaaaaaa, The Busy Coder's Guide to Advanced Android Development memiliki bab hebat tentang widget. Ini satu-satunya sumber yang membuat saya melalui kekacauan itu. CommonsWare, penulis, memiliki reputasi 115k di StackOverflow, dan saya sangat merekomendasikan buku ini. commonsware.com/AdvAndroid
MaximumGoat
64
Broadcastsfantastis dan sebagai tambahan jika Anda tidak ingin siaran Anda melampaui proses Anda sendiri maka pertimbangkan untuk menggunakan LocalBroadcast: developer.android.com/reference/android/support/v4/content/…
Cody Caughlan
2
Terima kasih Cody, saya belum pernah melihat itu sebelumnya.
MaximumGoat
3
Ini cara komunikasi yang sangat baik. Tetapi apa yang harus dilakukan jika hasil dikirim, ketika aktivitas dalam keadaan jeda? Jadi setelah aktivitas onResume bisa menunggu lama untuk hasil. Dan tidak ada data yang akan diterima, karena data terlewatkan.
Anton-M
20

Saya terkejut bahwa tidak ada yang memberikan referensi ke perpustakaan Bus acara Otto

http://square.github.io/otto/

Saya telah menggunakan ini di aplikasi android saya dan berfungsi dengan lancar.

Madhur Ahuja
sumber
7
Atau, ada perpustakaan EventBus greenrobot .
Jazzer
15
Tapi ingat bahwa EventBus dan otto selalu dalam satu proses. Saat Anda menggunakan layanan yang sedang dalam prosesnya sendiri (dimulai dengan pengaturan, android:process=":my_service"mereka tidak dapat berkomunikasi.
Ron
20

Menggunakan Messenger adalah cara sederhana lain untuk berkomunikasi antara Layanan dan Aktivitas.

Dalam Aktivitas, buat Handler dengan Messenger yang sesuai. Ini akan menangani pesan dari Layanan Anda.

class ResponseHandler extends Handler {
    @Override public void handleMessage(Message message) {
            Toast.makeText(this, "message from service",
                    Toast.LENGTH_SHORT).show();
    }
}
Messenger messenger = new Messenger(new ResponseHandler());

Messenger dapat diteruskan ke layanan dengan melampirkannya ke Pesan:

Message message = Message.obtain(null, MyService.ADD_RESPONSE_HANDLER);
message.replyTo = messenger;
try {
    myService.send(message);
catch (RemoteException e) {
    e.printStackTrace();
}

Contoh lengkap dapat ditemukan di demo API: MessengerService dan MessengerServiceActivity . Lihat contoh lengkap tentang cara kerja MyService.

Kjetil
sumber
1
Sangat dihargai! Bekerja dengan sempurna. Hanya detail dalam kode: myService.send(message);seharusnya messenger.send(message);.
Federico Cristina
9

Metode lain yang tidak disebutkan dalam komentar lain adalah untuk mengikat ke layanan dari aktivitas menggunakan bindService () dan mendapatkan turunan dari layanan di callback ServiceConnection. Seperti dijelaskan di sini http://developer.android.com/guide/components/bound-services.html

miguel
sumber
4
Ini adalah cara yang tepat untuk mendapatkan referensi instance layanan.
김준호
9

Anda juga dapat menggunakan LiveDatayang berfungsi seperti EventBus.

class MyService : LifecycleService() {
    companion object {
        var BUS = MutableLiveData<Object>()
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        super.onStartCommand(intent, flags, startId)

        val testItem : Object

        // expose your data
        if (BUS.hasActiveObservers()) {
            BUS.postValue(testItem)
        }

        return START_NOT_STICKY
    }
}

Kemudian tambahkan pengamat dari Anda Activity.

MyService.BUS.observe(this, Observer {
    it?.let {
        // Do what you need to do here
    }
})

Anda dapat membaca lebih banyak dari blog ini .

Zeenosaurus
sumber
2

Cara lain bisa menggunakan pengamat dengan kelas model palsu melalui aktivitas dan layanan itu sendiri, menerapkan variasi pola MVC. Saya tidak tahu apakah ini cara terbaik untuk mencapai ini, tapi itu cara yang bekerja untuk saya. Jika Anda memerlukan beberapa contoh, minta dan saya akan mengirim sesuatu.

ReDirEct__
sumber
Saya berjuang dengan pemikiran yang sama. Saya memiliki aktivitas dan 2 layanan yang memiliki Model yang sama. Model dapat diperbarui baik dalam aktivitas atau layanan apa pun sehingga saya berpikir tentang menggunakan Pengamat entah bagaimana, tetapi tidak dapat menemukannya. Bisakah Anda memposting contoh untuk menunjukkan ide Anda?
pzo
2

Metode saya:

Kelas untuk mengelola mengirim dan menerima pesan dari / ke layanan / aktivitas:

import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class MessageManager {

    public interface IOnHandleMessage{
        // Messages
        int MSG_HANDSHAKE = 0x1;

        void onHandleMessage(Message msg);
    }

    private static final String LOGCAT = MessageManager.class.getSimpleName();

    private Messenger mMsgSender;
    private Messenger mMsgReceiver;
    private List<Message> mMessages;

    public MessageManager(IOnHandleMessage callback, IBinder target){
        mMsgReceiver = new Messenger(new MessageHandler(callback, MessageHandler.TYPE_ACTIVITY));
        mMsgSender = new Messenger(target);
        mMessages = new ArrayList<>();
    }

    public MessageManager(IOnHandleMessage callback){
        mMsgReceiver = new Messenger(new MessageHandler(callback, MessageHandler.TYPE_SERVICE));
        mMsgSender = null;
        mMessages = new ArrayList<>();
    }

    /* START Getter & Setter Methods */
    public Messenger getMsgSender() {
        return mMsgSender;
    }

    public void setMsgSender(Messenger sender) {
        this.mMsgSender = sender;
    }

    public Messenger getMsgReceiver() {
        return mMsgReceiver;
    }

    public void setMsgReceiver(Messenger receiver) {
        this.mMsgReceiver = receiver;
    }

    public List<Message> getLastMessages() {
        return mMessages;
    }

    public void addMessage(Message message) {
        this.mMessages.add(message);
    }
    /* END Getter & Setter Methods */

    /* START Public Methods */
    public void sendMessage(int what, int arg1, int arg2, Bundle msgData){
        if(mMsgSender != null && mMsgReceiver != null) {
            try {
                Message msg = Message.obtain(null, what, arg1, arg2);
                msg.replyTo = mMsgReceiver;
                if(msgData != null){
                    msg.setData(msgData);
                }
                mMsgSender.send(msg);
            } catch (RemoteException rE) {
                onException(rE);
            }
        }
    }

    public void sendHandshake(){
        if(mMsgSender != null && mMsgReceiver != null){
            sendMessage(IOnHandleMessage.MSG_HANDSHAKE, 0, 0, null);
        }
    }
    /* END Public Methods */

    /* START Private Methods */
    private void onException(Exception e){
        Log.e(LOGCAT, e.getMessage());
        e.printStackTrace();
    }
    /* END Private Methods */

    /** START Private Classes **/
    private class MessageHandler extends Handler {

        // Types
        final static int TYPE_SERVICE = 0x1;
        final static int TYPE_ACTIVITY = 0x2;

        private IOnHandleMessage mCallback;
        private int mType;

        public MessageHandler(IOnHandleMessage callback, int type){
            mCallback = callback;
            mType = type;
        }

        @Override
        public void handleMessage(Message msg){
            addMessage(msg);
            switch(msg.what){
                case IOnHandleMessage.MSG_HANDSHAKE:
                    switch(mType){
                        case TYPE_SERVICE:
                            setMsgSender(msg.replyTo);
                            sendHandshake();
                            break;
                        case TYPE_ACTIVITY:
                            Log.v(LOGCAT, "HERE");
                            break;
                    }
                    break;
                default:
                    if(mCallback != null){
                        mCallback.onHandleMessage(msg);
                    }
                    break;
            }
        }

    }
    /** END Private Classes **/

}

Dalam Contoh Kegiatan:

public class activity extends AppCompatActivity
      implements     ServiceConnection,
                     MessageManager.IOnHandleMessage { 

    [....]

    private MessageManager mMessenger;

    private void initMyMessenger(IBinder iBinder){
        mMessenger = new MessageManager(this, iBinder);
        mMessenger.sendHandshake();
    }

    private void bindToService(){
        Intent intent = new Intent(this, TagScanService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        /* START THE SERVICE IF NEEDED */
    }

    private void unbindToService(){
    /* UNBIND when you want (onDestroy, after operation...)
        if(mBound) {
            unbindService(mServiceConnection);
            mBound = false;
        }
    }

    /* START Override MessageManager.IOnHandleMessage Methods */
    @Override
    public void onHandleMessage(Message msg) {
        switch(msg.what){
            case Constants.MSG_SYNC_PROGRESS:
                Bundle data = msg.getData();
                String text = data.getString(Constants.KEY_MSG_TEXT);
                setMessageProgress(text);
                break;
            case Constants.MSG_START_SYNC:
                onStartSync();
                break;
            case Constants.MSG_END_SYNC:
                onEndSync(msg.arg1 == Constants.ARG1_SUCCESS);
                mBound = false;
                break;
        }
    }
    /* END Override MessageManager.IOnHandleMessage Methods */

    /** START Override ServiceConnection Methods **/
    private class BLEScanServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            initMyMessenger(iBinder);
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mMessenger = null;
            mBound = false;
        }
    }
    /** END Override ServiceConnection Methods **/

Dalam Contoh Layanan:

public class Blablabla extends Service
    implements     MessageManager.IOnHandleMessage {

    [...]

    private MessageManager mMessenger;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        super.onBind(intent);
        initMessageManager();
        return mMessenger.getMsgReceiver().getBinder();
    }

    private void initMessageManager(){
        mMessenger = new MessageManager(this);
    }

    /* START Override IOnHandleMessage Methods */
    @Override
    public void onHandleMessage(Message msg) {
    /* Do what you want when u get a message looking the "what" attribute */
    }
    /* END Override IOnHandleMessage Methods */

Kirim pesan dari Aktivitas / Layanan:

mMessenger.sendMessage(what, arg1, arg2, dataBundle);

Bagaimana ini bekerja:

pada aktivitas Anda memulai atau mengikat layanan. Layanan "OnBind" metode mengembalikan Binder ke MessageManager-nya, dalam Aktivitas melalui implementasi metode antarmuka "Koneksi Layanan" "OnServiceConnected" Anda mendapatkan IBinder ini dan init Anda MessageManager menggunakannya. Setelah Kegiatan init MessageManager-nya MessageHandler mengirim dan jabat tangan ke layanan sehingga dapat mengatur pengirim "MessageHandler" ("private Messenger mMsgSender;" di MessageManager). Melakukan ini layanan tahu siapa yang mengirim pesannya.

Anda juga dapat menerapkan ini menggunakan Daftar / Antrian Messenger "pengirim" di MessageManager sehingga Anda dapat mengirim beberapa pesan ke berbagai Kegiatan / Layanan atau Anda dapat menggunakan Daftar / Antrian Messenger "penerima" di MessageManager sehingga Anda dapat menerima beberapa pesan dari berbagai Kegiatan / Layanan.

Dalam contoh "MessageManager" Anda memiliki daftar semua pesan yang diterima.

Karena Anda dapat melihat hubungan antara "Activity's Messenger" dan "Service Messenger" menggunakan instance "MessageManager" ini otomatis, hal itu dilakukan melalui metode "OnServiceConnected" dan melalui penggunaan "Handshake".

Semoga ini bisa membantu Anda :) Terima kasih banyak! Sampai jumpa: D

Z3R0
sumber
2

Untuk menindaklanjuti jawaban @MrSnowflake dengan contoh kode. Ini adalah XABBER sekarang open source Applicationkelas . The Applicationkelas sentralisasi dan koordinasi Listenersdan ManagerInterfaces dan banyak lagi. Manajer dari segala jenis dimuat secara dinamis. Activity´sdimulai di Xabber akan melaporkan dalam jenis apa Listenermereka. Dan ketika Servicemulai, laporkan ke Applicationkelas seperti yang dimulai. Sekarang untuk mengirim pesan ke Activitysemua yang harus Anda lakukan adalah membuat Anda Activitymenjadi listenertipe yang Anda butuhkan. Di OnStart() OnPause()register / batalkan registrasi. Mereka Servicedapat meminta Applicationkelas untuk hanya listenerperlu berbicara dengannya dan jika ada di sana maka Kegiatan siap untuk menerima.

Melewati Applicationkelas Anda akan melihat ada banyak jarahan yang terjadi kemudian.

Erik
sumber
Tautan yang disediakan sekarang menghasilkan github 404. Apakah itu bergerak?
JE Carter II
Yap, sepertinya berhasil sekarang. Pasti masalah sementara di github.
JE Carter II
1

Mengikat adalah cara lain untuk berkomunikasi

Buat panggilan balik

public interface MyCallBack{

   public void getResult(String result);

}

Sisi kegiatan:

  1. Terapkan antarmuka dalam Aktivitas

  2. Berikan implementasi untuk metode ini

  3. Bind Aktivitas ke Layanan

  4. Daftarkan dan Batalkan Pendaftaran Callback ketika Layanan terikat dan tidak terikat dengan Activity.

    public class YourActivity extends AppCompatActivity implements MyCallBack{
    
          private Intent notifyMeIntent;
          private GPSService gpsService;
          private boolean bound = false;
    
          @Override
          public void onCreate(Bundle sis){
    
              // activity code ...
    
              startGPSService();
    
          }
    
          @Override
          public void getResult(String result){
           // show in textView textView.setText(result);
          }
    
          @Override
          protected void onStart()
          {
              super.onStart();
              bindService();
          }
    
          @Override
          protected void onStop() {
              super.onStop();
              unbindService();
          }
    
          private ServiceConnection serviceConnection = new ServiceConnection() {
    
                @Override
                public void onServiceConnected(ComponentName className, IBinder service) {
    
                      GPSService.GPSBinder binder = (GPSService.GPSBinder) service;
                      gpsService= binder.getService();
                      bound = true;
                      gpsService.registerCallBack(YourActivity.this); // register
    
               }
    
               @Override
               public void onServiceDisconnected(ComponentName arg0) {
                      bound = false;
               }
          };
    
          private void bindService() {
    
               bindService(notifyMeIntent, serviceConnection, Context.BIND_AUTO_CREATE);
          }
    
          private void unbindService(){
               if (bound) {
                     gpsService.registerCallBack(null); // unregister            
                     unbindService(serviceConnection);
                     bound = false;
                }
          }
    
          // Call this method somewhere to start Your GPSService
          private void startGPSService(){
               notifyMeIntent = new Intent(this, GPSService.class);
               startService(myIntent );
          }
    
     }

Sisi Layanan:

  1. Inisialisasi panggilan balik

  2. Meminta metode panggilan balik kapan pun diperlukan

     public class GPSService extends Service{
    
         private MyCallBack myCallback;
         private IBinder serviceBinder = new GPSBinder();
    
         public void registerCallBack(MyCallBack myCallback){
              this.myCallback= myCallback;
         }
    
         public class GPSBinder extends Binder{
    
             public GPSService getService(){
                  return GPSService.this;
             }
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent){
             return serviceBinder;
        }
     }
Rohit Singh
sumber
Anda serviceConnectionkehabisan onCreate. Harap edit.
Adeel Zafar
Tidak harus di dalam onCreate
Rohit Singh
0

Selain LocalBroadcastManager, Event Bus dan Messenger sudah menjawab dalam pertanyaan ini, kita dapat menggunakan Pending Intent untuk berkomunikasi dari layanan.

Seperti yang disebutkan di sini di posting blog saya

Komunikasi antara layanan dan Aktivitas dapat dilakukan menggunakan PendingIntent. Untuk itu kita dapat menggunakan createPendingResult () .createPendingResult () membuat objek PendingIntent baru yang dapat Anda serahkan ke layanan untuk digunakan dan mengirim data hasil kembali ke aktivitas Anda di dalamActivityResult (int, int, Intent) callback. Karena PendingIntent adalah Parcelable, dan karenanya dapat dimasukkan ke dalam Intent extra, aktivitas Anda dapat meneruskan PendingIntent ini ke layanan. Layanan ini, pada gilirannya, dapat memanggil metode send () pada PendingIntent untuk memberi tahu aktivitas melalui onActivityResult dari suatu acara.

Aktivitas

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

Layanan

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

                }
            }
        }
    }
}
Pengembang Android
sumber