原文地址:http://android.blog.51cto.com/268543/527314
作者:Icansoft
-
本地服務 Local Service 用於應用程序內部。
它可以啓動並運行,直至有人停止了它或它自己停止。在這種方式下,它以調用Context.startService()啓動,而以調用Context.stopService()結束。它可以調用Service.stopSelf() 或 Service.stopSelfResult()來自己停止。不論調用了多少次startService()方法,你只需要調用一次stopService()來停止服務。
用於實現應用程序自己的一些耗時任務,比如查詢升級信息,並不佔用應用程序比如Activity所屬線程,而是單開線程後臺執行,這樣用戶體驗比較好。 -
遠程服務 Remote Service 用於android系統內部的應用程序之間。
它可以通過自己定義並暴露出來的接口進行程序操作。客戶端建立一個到服務對象的連接,並通過那個連接來調用服務。連接以調用Context.bindService()方法建立,以調用 Context.unbindService()關閉。多個客戶端可以綁定至同一個服務。如果服務此時還沒有加載,bindService()會先加載它。
可被其他應用程序複用,比如天氣預報服務,其他應用程序不需要再寫這樣的服務,調用已有的即可。
1. 使用startService()方法啓用服務,調用者與服務之間沒有關連,即使調用者退出了,服務仍然運行。
如果打算採用Context.startService()方法啓動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,接着調用onStart()方法。
如果調用startService()方法前服務已經被創建,多次調用startService()方法並不會導致多次創建服務,但會導致多次調用onStart()方法。
採用startService()方法啓動的服務,只能調用Context.stopService()方法結束服務,服務結束時會調用onDestroy()方法。
2. 使用bindService()方法啓用服務,調用者與服務綁定在了一起,調用者一旦退出,服務也就終止,大有“不求同時生,必須同時死”的特點。
onBind()只有採用Context.bindService()方法啓動服務時纔會回調該方法。該方法在調用者與服務綁定時被調用,當調用者與服務已經綁定,多次調用Context.bindService()方法並不會導致該方法被多次調用。
採用Context.bindService()方法啓動服務時只能調用onUnbind()方法解除調用者與服務解除,服務結束時會調用onDestroy()方法。
2. 如果當前service已經被啓動(start),擁有它的進程則比那些用戶可見的進程優先級低一些,但是比那些不可見的進程更重要,這就意味着service一般不會被killed.
3. 如果客戶端已經連接到service (bindService),那麼擁有Service的進程則擁有最高的優先級,可以認爲service是可見的。
4. 如果service可以使用startForeground(int, Notification)方法來將service設置爲前臺狀態,那麼系統就認爲是對用戶可見的,並不會在內存不足時killed。
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>
/**
* 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);
}
}
/**
* <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;
}
}
};
}
<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>
2.LocalService : onBind
3.Activity: onServiceConnected
-
If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.
- START_STICKY
-
If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand(), but do not redeliver the last intent. Instead, the system calls onStartCommand() with a null intent, unless there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.
- START_REDELIVER_INTENT
- If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand() with the last intent that was delivered to the service. Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as do wnloading a file.