Service Activity的三種交互方式(詳解)
service有兩種類型:
本地服務(wù)(Local Service):用于應(yīng)用程序內(nèi)部
遠(yuǎn)程服務(wù)(Remote Sercie):用于android系統(tǒng)內(nèi)部的應(yīng)用程序之間
前者用于實(shí)現(xiàn)應(yīng)用程序自己的一些耗時(shí)任務(wù),比如查詢升級信息,并不占用應(yīng)用程序比如Activity所屬線程,而是單開線程后臺執(zhí)行,這樣用戶體驗(yàn)比較好。
后者可被其他應(yīng)用程序復(fù)用,比如天氣預(yù)報(bào)服務(wù),其他應(yīng)用程序不需要再寫這樣的服務(wù),調(diào)用已有的即可。
編寫不需和Activity交互的本地服務(wù)示例
本地服務(wù)編寫比較簡單。首先,要?jiǎng)?chuàng)建一個(gè)Service類,該類繼承android的Service類。這里寫了一個(gè)計(jì)數(shù)服務(wù)的類,每秒鐘為計(jì)數(shù)器加一。在服務(wù)類的內(nèi)部,還創(chuàng)建了一個(gè)線程,用于實(shí)現(xiàn)后臺執(zhí)行上述業(yè)務(wù)邏輯。
Service代碼:
import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class CountService extends Service { private boolean threadDisable; private int count; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); new Thread(new Runnable() { public void run() { while (!threadDisable) { try { Thread.sleep(1000); } catch (InterruptedException e) { } count++; System.out.println(" CountService Count is " + count); } } }).start(); } @Override public void onDestroy() { super.onDestroy(); this.threadDisable = true; Log.v(" CountService ", " on destroy "); } } 將該服務(wù)注冊到配置文件AndroidManifest.xml中 <service android:name="CountService" /> 在Activity中啟動(dòng)和關(guān)閉本地服務(wù) import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class LocalServiceDemoActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.startService(new Intent(this, CountService.class)); } @Override protected void onDestroy() { super.onDestroy(); this.stopService(new Intent(this, CountService.class)); } }
編寫本地服務(wù)和Activity交互的示例
上面的示例是通過startService和stopService啟動(dòng)關(guān)閉服務(wù)的。適用于服務(wù)和activity之間沒有調(diào)用交互的情況。如果之間需要傳遞參數(shù)或者方法調(diào)用。需要使用bind和unbind方法。
具體做法是,服務(wù)類需要增加接口,比如ICountService,另外,服務(wù)類需要有一個(gè)內(nèi)部類,這樣可以方便訪問外部類的封裝數(shù)據(jù),這個(gè)內(nèi)部類需要繼承Binder類并實(shí)現(xiàn)ICountService接口。還有,就是要實(shí)現(xiàn)Service的
onBind方法,不能只傳回一個(gè)null了。
新建立的接口代碼:
public interface ICountService { public abstract int getCount(); } CountService代碼: import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class CountService extends Service implements ICountService { private boolean threadDisable; private int count; private ServiceBinder serviceBinder = new ServiceBinder(); public class ServiceBinder extends Binder implements ICountService { // @Override public int getCount() { return count; } } @Override public IBinder onBind(Intent intent) { return serviceBinder; } @Override public void onCreate() { super.onCreate(); new Thread(new Runnable() { // @Override public void run() { while (!threadDisable) { try { Thread.sleep(1000); } catch (InterruptedException e) { } count++; System.out.println("CountService Count is " + count); } } }).start(); } @Override public void onDestroy() { super.onDestroy(); this.threadDisable = true; Log.v(" CountService ", " on destroy "); } // @Override public int getCount() { return count; } }
服務(wù)的注冊也要做改動(dòng),AndroidManifest.xml文件:
<service android:name="CountService" > <intent-filter> <action android:name="com.phone.jiaohuservice.CountService" /> </intent-filter> </service> Acitity代碼不再通過startSerivce和stopService啟動(dòng)關(guān)閉服務(wù),另外,需要通過ServiceConnection的內(nèi)部類實(shí)現(xiàn)來連接Service和Activity。 import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; public class LocalServiceDemoActivity extends Activity { private ServiceConnection serviceConnection = new ServiceConnection() { // @Override public void onServiceConnected(ComponentName name, IBinder service) { countService = (ICountService) service; System.out.println(" CountService on serivce connected, count is " + countService.getCount()); } // @Override public void onServiceDisconnected(ComponentName name) { countService = null; } }; private ICountService countService; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.bindService(new Intent("com.phone.jiaohuservice.CountService"), this.serviceConnection, BIND_AUTO_CREATE); } @Override protected void onDestroy() { this.unbindService(serviceConnection); super.onDestroy(); // 注意先后 } }
編寫傳遞基本型數(shù)據(jù)的遠(yuǎn)程服務(wù)
上面的示例,可以擴(kuò)展為,讓其他應(yīng)用程序復(fù)用該服務(wù)。這樣的服務(wù)叫遠(yuǎn)程(remote)服務(wù),實(shí)際上是進(jìn)程間通信(RPC)。
這時(shí)需要使用android接口描述語言(AIDL)來定義遠(yuǎn)程服務(wù)的接口,而不是上述那樣簡單的java接口。擴(kuò)展名為aidl而不是java??捎蒙厦娴腎CountService改動(dòng)而成ICountSerivde.aidl,eclipse會自動(dòng)生成相關(guān)的java文件。
遠(yuǎn)端代碼:
ICountService.aidl
package com.phone.remoteservice.aidl; interface ICountService { int getCount(); }
CountService.java
import com.phone.remoteservice.aidl.ICountService; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class CountService extends Service { private boolean threadDisable; private int count; private ICountService.Stub serviceBinder = new ICountService.Stub() { // @Override public int getCount() throws RemoteException { return count; } }; // @Override public IBinder onBind(Intent intent) { return serviceBinder; } @Override public void onCreate() { super.onCreate(); new Thread(new Runnable() { // @Override public void run() { while (!threadDisable) { try { Thread.sleep(1000); } catch (InterruptedException e) { } count++; Log.i("aa", "---" + count + "---"); } } }).start(); } // @Override public void onDestroy() { super.onDestroy(); this.threadDisable = true; Log.v(" CountService ", " on destroy "); } }
配置文件AndroidManifest.xml
<service android:name=".CountService" > <intent-filter> <action android:name="com.phone.remoteservice.CountService" /> </intent-filter> </service>
本地代碼:
拷貝遠(yuǎn)端代碼gen:com.phone.remoteservice.aidl包名及內(nèi)部生成的ICountService.java文件到本地,注意包名不要變,java文件名也不要變。
測試代碼
import com.phone.remoteservice.aidl.ICountService; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.view.Menu; public class RemoteServiceTest extends Activity { private ICountService countService; private boolean SreviceDisable; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); bindService(new Intent("com.phone.remoteservice.CountService"), this.serviceConnection, BIND_AUTO_CREATE); } @Override protected void onDestroy() { this.unbindService(serviceConnection); SreviceDisable = true; super.onDestroy(); // 注意先后 } private ServiceConnection serviceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { countService = ICountService.Stub.asInterface(service); new Thread(new Runnable() { // @Override public void run() { while (!SreviceDisable) { try { System.out .println(" CountService on serivce connected, count is " + countService.getCount()); } catch (RemoteException e) { e.printStackTrace(); } try { Thread.sleep(1000); } catch (InterruptedException e) { } } } }).start(); } public void onServiceDisconnected(ComponentName name) { countService = null; } }; }
在Activity中使用服務(wù)的差別不大,只需要對ServiceConnection中的調(diào)用遠(yuǎn)程服務(wù)的方法時(shí),要捕獲RemoteException 異常。
這樣就可以在同一個(gè)應(yīng)用程序中使用遠(yuǎn)程服務(wù)的方式和自己定義的服務(wù)交互了。 如果是另外的應(yīng)用程序使用遠(yuǎn)程服務(wù),需要做的是復(fù)制上面的aidl文件和相應(yīng)的包構(gòu)到應(yīng)用程序中,其他調(diào)用等都一樣。
編寫傳遞復(fù)雜數(shù)據(jù)類型的遠(yuǎn)程服務(wù)
遠(yuǎn)程服務(wù)往往不只是傳遞java基本數(shù)據(jù)類型。這時(shí)需要注意android的一些限制和規(guī)定:
1. android支持String和CharSequence
2. 如果需要在aidl中使用其他aidl接口類型,需要import,即使是在相同包結(jié)構(gòu)下;
3. android允許傳遞實(shí)現(xiàn)Parcelable接口的類,需要import;
4. android支持集合接口類型List和Map,但是有一些限制,元素必須是基本型或者上述三種情況,不需要import集合接口類,但是需要對元素涉及到的類型import;
5. 非基本數(shù)據(jù)類型,也不是String和CharSequence類型的,需要有方向指示,包括in、out和inout,in表示由客戶端設(shè)置,out表示由服務(wù)端設(shè)置,inout是兩者均可設(shè)置。
這里將前面的例子中返回的int數(shù)據(jù)改為復(fù)雜數(shù)據(jù)類型:
import android.os.Parcel; import android.os.Parcelable; public class CountBean implements Parcelable { public static final Parcelable.Creator < CountBean > CREATOR = new Creator < CountBean > () { @Override public CountBean createFromParcel(Parcel source) { CountBean bean = new CountBean(); bean.count = source.readInt(); return bean; } @Override public CountBean[] newArray( int size) { return new CountBean[size]; } }; public int count; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt( this .count); } @Override public int describeContents() { return 0 ; } }
以上就是小編為大家?guī)淼腟ervice Activity的三種交互方式(詳解)的全部內(nèi)容了,希望對大家有所幫助,多多支持腳本之家~
相關(guān)文章
Compose?動(dòng)畫藝術(shù)探索之可見性動(dòng)畫示例詳解
這篇文章主要為大家介紹了Compose?動(dòng)畫藝術(shù)探索之可見性動(dòng)畫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Android取消EditText自動(dòng)獲取焦點(diǎn)默認(rèn)行為
在項(xiàng)目中,一進(jìn)入一個(gè)頁面, EditText默認(rèn)就會自動(dòng)獲取焦點(diǎn),很是郁悶,Android 如何讓EditText不自動(dòng)獲取焦點(diǎn)?于是搜集整理一番,曬出來和大家分享,希望對你們有所幫助2012-12-12Android原生ViewPager控件實(shí)現(xiàn)卡片翻動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android原生ViewPager控件實(shí)現(xiàn)卡片翻動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07Flutter上線項(xiàng)目實(shí)戰(zhàn)記錄之路由篇
這篇文章主要給大家介紹了關(guān)于Flutter上線項(xiàng)目實(shí)戰(zhàn)記錄之路由篇的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Flutter具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Android編程開發(fā)之ScrollView嵌套GridView的方法
這篇文章主要介紹了Android編程開發(fā)之ScrollView嵌套GridView的方法,結(jié)合實(shí)例分析了ScrollView嵌套GridView的相關(guān)注意事項(xiàng)與處理技巧,需要的朋友可以參考下2015-12-12Android json數(shù)據(jù)解析詳解及實(shí)例代碼
這篇文章主要介紹了 Android json數(shù)據(jù)解析詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02Android RadioButton 圖片位置與大小實(shí)例詳解
這篇文章主要介紹了Android RadioButton 圖片位置與大小實(shí)例詳解的相關(guān)資料,這里提供實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-11-11