Mengikat layanan ke aktivitas di Android

90

Saya mencoba menulis pemutar media sederhana yang memutar audio streaming menggunakan RTSP. Saya memiliki aktivitas GUI dan layanan yang melakukan pemutaran. Pertanyaan saya adalah bagaimana cara terbaik untuk berkomunikasi antara aktivitas dan layanan (mis. Memperbarui GUI berdasarkan status pemain).

Saya tahu bahwa saya bisa mengikat layanan ke aktivitas menggunakan onBind (), tetapi jika saya mengerti dengan benar, ini akan menghentikan layanan jika aktivitas dimatikan. Saya ingin melanjutkan pemutaran bahkan jika pengguna keluar dari aktivitas. Apakah ada cara standar atau yang lebih disukai untuk mengatasi masalah ini?

aspartam
sumber

Jawaban:

154

"Jika Anda memulai Layanan android dengan startService(..)Layanan itu akan tetap berjalan sampai Anda secara eksplisit memanggil stopService(..). Ada dua alasan mengapa layanan dapat dijalankan oleh sistem. Jika seseorang memanggil Context.startService()maka sistem akan mengambil layanan (membuatnya dan memanggil onCreate()metodenya jika diperlukan) dan kemudian memanggil onStartCommand(Intent, int, int)metodenya dengan argumen yang diberikan oleh klien. Layanan pada saat ini akan terus berjalan hingga Context.stopService()atau stopSelf()dipanggil. Perhatikan bahwa beberapa panggilan ke Context.startService()tidak bersarang (meskipun mereka menghasilkan beberapa panggilan yang sesuai ke onStartCommand()), jadi tidak ada peduli berapa kali dimulai, layanan akan dihentikan satu kali Context.stopService()atau stopSelf()dipanggil; namun, layanan dapat menggunakanstopSelf(int) metode untuk memastikan layanan tidak dihentikan sampai maksud yang dimulai telah diproses.

Klien juga dapat menggunakan Context.bindService()untuk mendapatkan koneksi tetap ke layanan. Ini juga membuat layanan jika belum berjalan (memanggil onCreate()sambil melakukannya), tetapi tidak memanggil onStartCommand(). Klien akan menerima IBinderobjek yang dikembalikan layanan dari onBind(Intent)metodenya, memungkinkan klien untuk kemudian melakukan panggilan kembali ke layanan. Layanan akan tetap berjalan selama koneksi dibuat (apakah klien mempertahankan referensi pada Layanan atau tidak IBinder). Biasanya yang IBinderdikembalikan adalah untuk antarmuka kompleks yang telah ditulis dalam AIDL.

Sebuah layanan dapat dimulai dan memiliki koneksi yang terikat padanya. Dalam kasus seperti itu, sistem akan menjaga layanan tetap berjalan selama layanan tersebut dimulai atau ada satu atau beberapa koneksi dengannya dengan Context.BIND_AUTO_CREATEflag. Setelah tidak satu pun dari situasi ini berlaku, metode Layanan onDestroy()dipanggil dan layanan dihentikan secara efektif. Semua pembersihan (menghentikan utas, membatalkan pendaftaran penerima) harus selesai setelah kembali dari onDestroy(). "

Schildmeijer
sumber
1
sedikit kebingungan: Benarkah jika aktivitas dimusnahkan layanan juga akan dimusnahkan? Atau apakah layanan itu tidak dihancurkan hanya jika saya menerapkan AIDL saya sendiri? Saya bertanya karena ketika saya menggunakan startService (esp di IntentService) layanan berhenti ketika pekerjaannya selesai, bukan ketika aktivitas mati. Lantas apakah benar jika aktivitas tersebut mati, maka layanan yang diikat (eksklusif) juga mati?
Katedral Pillon
1
jika Anda menggunakan server sederhana dengan memanggil startService maka layanan tidak akan berhenti sampai Anda memanggil stopSelf () atau stopService (). Dan selanjutnya jika menggunakan bindService maka layanan yes akan mati jika semua komponen yang terhubung / bind rusak.
Asif Mushtaq
1
@UnKnown Jika layanan dimulai menggunakan startService () maka tidak masalah jika Anda mengikat atau melepaskannya, itu akan terus berjalan dan hanya dapat dimusnahkan dengan memanggil stopService () atau stopSelf (). Jadi, meskipun aktivitas yang terikat ke layanan dimusnahkan, layanan tidak akan dimusnahkan.
CopsOnRoad
Bisakah Anda membantu saya dengan pertanyaan ini stackoverflow.com/questions/51508046/…
Rajesh K
25

Pertama-tama, 2 hal yang perlu kita pahami

Klien

  • itu membuat permintaan ke server tertentu

    bindService(new 
        Intent("com.android.vending.billing.InAppBillingService.BIND"),
            mServiceConn, Context.BIND_AUTO_CREATE);`
    

Berikut mServiceConnadalah contoh ServiceConnectionclass (inbuilt) sebenarnya adalah antarmuka yang perlu kita implementasikan dengan dua metode (pertama untuk jaringan yang terhubung dan jaringan kedua tidak terhubung) untuk memantau status koneksi jaringan.

Server

  • Ini menangani permintaan klien dan membuat replikanya sendiri yang bersifat pribadi hanya untuk klien yang mengirim permintaan dan replika server ini berjalan di utas yang berbeda.

Sekarang di sisi klien, bagaimana cara mengakses semua metode server?

  • Server mengirimkan respon dengan IBind Object. jadi IBind object adalah handler kita yang mengakses semua metode service dengan menggunakan operator (.).

    MyService myService;
    public ServiceConnection myConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder binder) {
            Log.d("ServiceConnection","connected");
            myService = binder;
        }
        //binder comes from server to communicate with method's of 
    
        public void onServiceDisconnected(ComponentName className) {
            Log.d("ServiceConnection","disconnected");
            myService = null;
        }
    }
    

sekarang bagaimana memanggil metode yang terletak pada layanan

myservice.serviceMethod();

di sini myServiceadalah objek dan serviceMethodemetode dalam pelayanan. Dan dengan cara ini komunikasi terjalin antara klien dan server.

Hardik Gajera
sumber
10

Saya mencoba menelepon

startService(oIntent);
bindService(oIntent, mConnection, Context.BIND_AUTO_CREATE);

akibatnya dan saya dapat membuat layanan lengket dan mengikatnya. Tutorial terperinci untuk Contoh Layanan Terikat .

M.Hefny
sumber
5

Ada metode yang disebut unbindService yang akan mengambil ServiceConnection yang akan Anda buat saat memanggil bindService. Ini akan memungkinkan Anda untuk memutuskan sambungan dari layanan sambil tetap membiarkannya berjalan.

Ini dapat menimbulkan masalah saat Anda menyambungkannya lagi, karena Anda mungkin tidak tahu apakah aktivitas itu berjalan atau tidak saat Anda memulai aktivitas lagi, jadi Anda harus mempertimbangkannya di kode aktivitas.

Semoga berhasil!

vrutberg.dll
sumber
-1

Ini adalah jawaban yang bias, tetapi saya menulis pustaka yang dapat menyederhanakan penggunaan Layanan Android, jika berjalan secara lokal dalam proses yang sama dengan aplikasi: https://github.com/germnix/acacia

Pada dasarnya Anda mendefinisikan antarmuka yang dianotasi dengan @Service dan kelas implementasinya, dan perpustakaan membuat dan mengikat layanan, menangani koneksi dan thread pekerja latar belakang:

@Service(ServiceImpl.class)
public interface MyService {
    void doProcessing(Foo aComplexParam);
}

public class ServiceImpl implements MyService {
    // your implementation
}

MyService service = Acacia.createService(context, MyService.class);
service.doProcessing(foo);

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    ...
    <service android:name="com.gmr.acacia.AcaciaService"/>
    ...
</application>

Anda bisa mendapatkan instance android.app.Service terkait untuk menyembunyikan / menampilkan notifikasi tetap, menggunakan android.app.Service Anda sendiri dan secara manual menangani threading jika Anda mau.

Jerman
sumber
-5

Jika pengguna mundur, onDestroy()metode ini akan dipanggil. Metode ini untuk menghentikan layanan apa pun yang digunakan dalam aplikasi. Jadi, jika Anda ingin melanjutkan layanan meskipun pengguna mundur dari aplikasi, hapus saja onDestroy(). Semoga bantuan ini.

Mira Febriani
sumber
Anda harus mengganti fungsi dan menghapus panggilan default ke onDestroy () superclass jika IDE Anda secara otomatis membuatnya. tetapi mengapa Anda ingin melakukan ini?
Riptyde4