Android Service学习之本地服务
生活随笔
收集整理的這篇文章主要介紹了
Android Service学习之本地服务
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Service是在一段不定的時間運行在后臺,不和用戶交互應(yīng)用組件。每個Service必須在manifest中 通過<service>來聲明。可以通過contect.startservice和contect.bindserverice來啟動。
? ? Service和其他的應(yīng)用組件一樣,運行在進(jìn)程的主線程中。這就是說如果service需要很多耗時或者阻塞的操作,需要在其子線程中實現(xiàn)。 ? ? service的兩種模式(startService()/bindService()不是完全分離的):- 本地服務(wù) Local Service 用于應(yīng)用程序內(nèi)部。
? 它可以啟動并運行,直至有人停止了它或它自己停止。在這種方式下,它以調(diào)用Context.startService()啟動,而以調(diào)用 Context.stopService()結(jié)束。它可以調(diào)用Service.stopSelf() 或 Service.stopSelfResult()來自己停止。不論調(diào)用了多少次startService()方法,你只需要調(diào)用一次 stopService()來停止服務(wù)。
? 用于實現(xiàn)應(yīng)用程序自己的一些耗時任務(wù),比如查詢升級信息,并不占用應(yīng)用程序比如Activity所屬線程,而是單開線程后臺執(zhí)行,這樣用戶體驗比較好。 - 遠(yuǎn)程服務(wù) Remote Service 用于android系統(tǒng)內(nèi)部的應(yīng)用程序之間。
? 它可以通過自己定義并暴露出來的接口進(jìn)行程序操作。客戶端建立一個到服務(wù)對象的連接,并通過那個連接來調(diào)用服務(wù)。連接以調(diào)用 Context.bindService()方法建立,以調(diào)用 Context.unbindService()關(guān)閉。多個客戶端可以綁定至同一個服務(wù)。如果服務(wù)此時還沒有加載,bindService()會先加載 它。
? 可被其他應(yīng)用程序復(fù)用,比如天氣預(yù)報服務(wù),其他應(yīng)用程序不需要再寫這樣的服務(wù),調(diào)用已有的即可。
? ? 1. 使用startService()方法啟用服務(wù),調(diào)用者與服務(wù)之間沒有關(guān)連,即使調(diào)用者退出了,服務(wù)仍然運行。
? ? 如果打算采用Context.startService()方法啟動服務(wù),在服務(wù)未被創(chuàng)建時,系統(tǒng)會先調(diào)用服務(wù)的onCreate()方法,接著調(diào)用onStart()方法。
? ? 如果調(diào)用startService()方法前服務(wù)已經(jīng)被創(chuàng)建,多次調(diào)用startService()方法并不會導(dǎo)致多次創(chuàng)建服務(wù),但會導(dǎo)致多次調(diào)用onStart()方法。
? ? 采用startService()方法啟動的服務(wù),只能調(diào)用Context.stopService()方法結(jié)束服務(wù),服務(wù)結(jié)束時會調(diào)用onDestroy()方法。
? ? 2. 使用bindService()方法啟用服務(wù),調(diào)用者與服務(wù)綁定在了一起,調(diào)用者一旦退出,服務(wù)也就終止,大有“不求同時生,必須同時死”的特點。
? ? onBind()只有采用Context.bindService()方法啟動服務(wù)時才會回調(diào)該方法。該方法在調(diào)用者與服務(wù)綁定時被調(diào)用,當(dāng)調(diào)用者與服務(wù)已經(jīng)綁定,多次調(diào)用Context.bindService()方法并不會導(dǎo)致該方法被多次調(diào)用。
? ? 采用Context.bindService()方法啟動服務(wù)時只能調(diào)用onUnbind()方法解除調(diào)用者與服務(wù)解除,服務(wù)結(jié)束時會調(diào)用onDestroy()方法。 看看官方給出的比較流程示意圖:
? ? 官方文檔告訴我們,一個service可以同時start并且bind,在這樣的情況,系統(tǒng)會一直保持service的運行狀態(tài)如果service已經(jīng) start了或者BIND_AUTO_CREATE標(biāo)志被設(shè)置。如果沒有一個條件滿足,那么系統(tǒng)將會調(diào)用onDestory方法來終止service.所 有的清理工作(終止線程,反注冊接收器)都在onDestory中完成。 擁有service的進(jìn)程具有較高的優(yōu)先級 ? ? 官方文檔告訴我們,Android系統(tǒng)會盡量保持擁有service的進(jìn)程運行,只要在該service已經(jīng)被啟動(start)或者客戶端連接(bindService)到它。當(dāng)內(nèi)存不足時,需要保持,擁有service的進(jìn)程具有較高的優(yōu)先級。
1. 如果service正在調(diào)用onCreate,onStartCommand或者onDestory方法,那么用于當(dāng)前service的進(jìn)程則變?yōu)榍芭_進(jìn)程以避免被killed。
2. 如果當(dāng)前service已經(jīng)被啟動(start),擁有它的進(jìn)程則比那些用戶可見的進(jìn)程優(yōu)先級低一些,但是比那些不可見的進(jìn)程更重要,這就意味著service一般不會被killed.
3. 如果客戶端已經(jīng)連接到service (bindService),那么擁有Service的進(jìn)程則擁有最高的優(yōu)先級,可以認(rèn)為service是可見的。
4. 如果service可以使用startForeground(int, Notification)方法來將service設(shè)置為前臺狀態(tài),那么系統(tǒng)就認(rèn)為是對用戶可見的,并不會在內(nèi)存不足時killed。 如果有其他的應(yīng)用組件作為Service,Activity等運行在相同的進(jìn)程中,那么將會增加該進(jìn)程的重要性。
本地service 1.不需和Activity交互的本地服務(wù) public class LocalService extends Service {
????????private static final String TAG = "LocalService";
????????@Override
????????public IBinder onBind(Intent intent) {
????????????????Log.i(TAG, "onBind");
????????????????return null;
????????}
????????@Override
????????public void onCreate() {
????????????????Log.i(TAG, "onCreate");
????????????????super.onCreate();
????????}
????????@Override
????????public void onDestroy() {
????????????????Log.i(TAG, "onDestroy");
????????????????super.onDestroy();
????????}
????????@Override
????????public void onStart(Intent intent, int startId) {
????????????????Log.i(TAG, "onStart");
????????????????super.onStart(intent, startId);
????????}
} Activity: public class ServiceActivity extends Activity {
????????@Override
????????protected void onCreate(Bundle savedInstanceState) {
????????????????super.onCreate(savedInstanceState);
????????????????setContentView(R.layout.servicedemo);
????????????????((Button) findViewById(R.id.startLocalService)).setOnClickListener(
????????????????????????????????new View.OnClickListener(){
????????????????????????????????????????@Override
????????????????????????????????????????public void onClick(View view) {
????????????????????????????????????????????????// TODO Auto-generated method stub
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?startService(new Intent("com.demo.SERVICE_DEMO"));
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ?
????????????????????????????????});
????????????????((Button) findViewById(R.id.stopLocalService)).setOnClickListener(
????????????????????????????????new View.OnClickListener(){
????????????????????????????????????????@Override
????????????????????????????????????????public void onClick(View view) {
????????????????????????????????????????????????// TODO Auto-generated method stub
????????????????????????????????????????????????stopService(new Intent("com.demo.SERVICE_DEMO"));
????????????????????????????????????????}
????????????????????????????????});
????????}
} 在AndroidManifest.xml添加: <service android:name=".LocalService">
????????<intent-filter>
????????????????<action android:name="com.demo.SERVICE_DEMO" />
????????????????<category android:name="android.intent.category.default" />
????????</intent-filter>
</service> 否則啟動服務(wù)時會提示new Intent找不到"com.demo.SERVICE_DEMO"。 ? ? 對于這類不需和Activity交互的本地服務(wù),是使用startService/stopService的最好例子。 ? ? 運行時可以發(fā)現(xiàn)第一次startService時,會調(diào)用onCreate和onStart,在沒有stopService前,無論點擊多少次 startService,都只會調(diào)用onStart。而stopService時調(diào)用onDestroy。再次點擊stopService,會發(fā)現(xiàn)不會 進(jìn)入service的生命周期的,即不會再調(diào)用onCreate,onStart和onDestroy。 ? ? 而onBind在startService/stopService中沒有調(diào)用。 2.本地服務(wù)和Activity交互 ? ? 對于這種case,官方的sample(APIDemo\app.LocalService)是最好的例子: /**
* This is an example of implementing an application service that runs locally
* in the same process as the application.????The {@link LocalServiceController}
* and {@link LocalServiceBinding} classes show how to interact with the
* service.
*
* <p>Notice the use of the {@link NotificationManager} when interesting things
* happen in the service.????This is generally how background services should
* interact with the user, rather than doing something more disruptive such as
* calling startActivity().
*/
public class LocalService extends Service {
????????private NotificationManager mNM;
????????/**
???????? * Class for clients to access.????Because we know this service always
???????? * runs in the same process as its clients, we don't need to deal with
???????? * IPC.
???????? */
????????public class LocalBinder extends Binder {
????????????????LocalService getService() {
????????????????????????return LocalService.this;
????????????????}
????????}
????????
????????@Override
????????public void onCreate() {
????????????????mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
????????????????// Display a notification about us starting.????We put an icon in the status bar.
????????????????showNotification();
????????}
????????@Override
????????public int onStartCommand(Intent intent, int flags, int startId) {
????????????????Log.i("LocalService", "Received start id " + startId + ": " + intent);
????????????????// We want this service to continue running until it is explicitly
????????????????// stopped, so return sticky.
????????????????return START_STICKY;
????????}
????????@Override
????????public void onDestroy() {
????????????????// Cancel the persistent notification.
????????????????mNM.cancel(R.string.local_service_started);
????????????????// Tell the user we stopped.
????????????????Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();
????????}
????????@Override
????????public IBinder onBind(Intent intent) {
? ? ? ? ? ? ?return mBinder;
????????}
????????// This is the object that receives interactions from clients.????See
????????// RemoteService for a more complete example.
????????private final IBinder mBinder = new LocalBinder();
????????/**
???????? * Show a notification while this service is running.
???????? */
????????private void showNotification() {
????????????????// In this sample, we'll use the same text for the ticker and the expanded notification
????????????????CharSequence text = getText(R.string.local_service_started);
????????????????// Set the icon, scrolling text and timestamp
????????????????Notification notification = new Notification(R.drawable.stat_sample, text,
????????????????????????????????System.currentTimeMillis());
????????????????// The PendingIntent to launch our activity if the user selects this notification
????????????????PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
????????????????????????????????new Intent(this, LocalServiceController.class), 0);
????????????????// Set the info for the views that show in the notification panel.
????????????????notification.setLatestEventInfo(this, getText(R.string.local_service_label),
???????????????????????????????????????????? text, contentIntent);
????????????????// Send the notification.
????????????????// We use a layout id because it is a unique number.????We use it later to cancel.
????????????????mNM.notify(R.string.local_service_started, notification);
????????}
} ? ?這里可以發(fā)現(xiàn)onBind需要返回一個IBinder對象。也就是說和上一例子LocalService不同的是, 1. 添加了一個public內(nèi)部類繼承Binder,并添加getService方法來返回當(dāng)前的Service對象; 2. 新建一個IBinder對象——new那個Binder內(nèi)部類; 3. onBind方法返還那個IBinder對象。 Activity: /**
* <p>Example of binding and unbinding to the {@link LocalService}.
* This demonstrates the implementation of a service which the client will
* bind to, receiving an object through which it can communicate with the service.</p>
*/
public class LocalServiceBinding extends Activity {
????????private boolean mIsBound;
????????private LocalService mBoundService;
????????@Override
?? ? ? ?protected void onCreate(Bundle savedInstanceState) {
????????????????super.onCreate(savedInstanceState);
????????????????setContentView(R.layout.local_service_binding);
????????????????// Watch for button clicks.
????????????????Button button = (Button)findViewById(R.id.bind);
????????????????button.setOnClickListener(mBindListener);
????????????????button = (Button)findViewById(R.id.unbind);
????????????????button.setOnClickListener(mUnbindListener);
????????}
????????private ServiceConnection mConnection = new ServiceConnection() {
? ? ? ? ? ? ? ? public void onServiceConnected(ComponentName className, IBinder service)?{
????????????????????????// This is called when the connection with the service has been
????????????????????????// established, giving us the service object we can use to
????????????????????????// interact with the service.????Because we have bound to a explicit
????????????????????????// service that we know is running in our own process, we can
????????????????????????// cast its IBinder to a concrete class and directly access it.
? ? ? ? ? ? ? ? ? ? ? ? mBoundService = ((LocalService.LocalBinder)service).getService(); ?
????????????????????????
????????????????????????// Tell the user about this for our demo.
????????????????????????Toast.makeText(LocalServiceBinding.this, R.string.local_service_connected,
????????????????????????????????????????Toast.LENGTH_SHORT).show();
????????????????}
? ? ? ? ? ? ? ? public void onServiceDisconnected(ComponentName className) {?
????????????????????????// This is called when the connection with the service has been
????????????????????????// unexpectedly disconnected -- that is, its process crashed.
????????????????????????// Because it is running in our same process, we should never
????????????????????????// see this happen.
????????????????????????mBoundService = null;
????????????????????????Toast.makeText(LocalServiceBinding.this, R.string.local_service_disconnected,
????????????????????????????????????????Toast.LENGTH_SHORT).show();
????????????????}
????????};
????????private OnClickListener mBindListener = new OnClickListener() {
????????????????public void onClick(View v) {
????????????????????????// Establish a connection with the service.????We use an explicit
????????????????????????// class name because we want a specific service implementation that
????????????????????????// we know will be running in our own process (and thus won't be
????????????????????????// supporting component replacement by other applications).
????????????????????????bindService(new Intent(LocalServiceBinding.this,????
????????????????????????????????????????LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
????????????????????????mIsBound = true;
????????????????}
????????};
????????private OnClickListener mUnbindListener = new OnClickListener() {
????????????????public void onClick(View v) {
????????????????????????if (mIsBound) {
????????????????????????????????// Detach our existing connection.
????????????????????????????????unbindService(mConnection);
????????????????????????????????mIsBound = false;
????????????????????????}
????????????????}
????????};
} ? ? 明顯看出這里面添加了一個名為ServiceConnection類,并實現(xiàn)了onServiceConnected(從IBinder獲取Service對象)和onServiceDisconnected(set Service to null)。 ? ? 而bindService和unbindService方法都是操作這個ServiceConnection對象的。 AndroidManifest.xml里添加: <service android:name=".app.LocalService" />
<activity android:name=".app.LocalServiceBinding" android:label="@string/activity_local_service_binding">
? ? ?<intent-filter>
? ? ?? ? ?<action android:name="android.intent.action.MAIN" />
? ? ? ?? ?<category android:name="android.intent.category.SAMPLE_CODE" />
? ? ?</intent-filter>
</activity> 這里沒什么特別的,因為service沒有需要什么特別的action,所以只是聲明service而已,而activity和普通的沒差別。 運行時,發(fā)現(xiàn)調(diào)用次序是這樣的: bindService: 1.LocalService : onCreate
2.LocalService : onBind
3.Activity: onServiceConnected
unbindService: 只是調(diào)用onDestroy 可見,onStart是不會被調(diào)用的,而onServiceDisconnected沒有調(diào)用的原因在上面代碼的注釋有說明。 介紹onStartCommand()需要用到的幾個常量 (引自官方文檔) START_NOT_STICKY
轉(zhuǎn)載于:https://www.cnblogs.com/hnrainll/archive/2011/10/26/2225382.html
總結(jié)
以上是生活随笔為你收集整理的Android Service学习之本地服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL查询月初与月末时间
- 下一篇: JAVA基础之理解JNI原理