編輯:初級開發
android Service Note
1、 概述
每個服務都繼承Service基類。
可以連接到(或者bind to)一個正在運行的服務(如果沒有在運行則啟動它)。當連接成功後,你可以通過服務提供的接口來與它通信。服務通常產生另外的線程來進行占用時間長的任務。
Service是沒有用戶可見的界面,不與用戶交互,而是在後台運行一段不確定的時間的應用程序組件。每個Service class 都必須在androidManifest.XML文件中有相應的< service>聲明。Service可以通過 Context.startService()和Context.bindService()來啟動。
注意,與其他程序中的對象一樣,Service運行他們的主進程中。這意味著,如果服務要進行消耗CPU或者阻塞的操作,它應該產生新的線程,在新線程裡進行這些工作。
2、Service 的生命周期
系統有兩種啟動Service的方法。如果調用Context.startService(),那麼系統將會retrIEve這個Service(如果必要則創建它並調用它的onCreate()方法),然後使用客戶端傳遞的參數調用它的onStart(Intent,int)方法。這是Service開始運行直到Context.stopService()或者stopSelf()方法被調用。注意,多次調用 Context.startservice()不會嵌套(即使會有相應的onStart()方法被調用),所以無論同一個服務被啟動了多少次,一旦調用 Context.stopService()或者stopSelf(),他都會被停止。
客戶端也可以使用context.bindservice()來得到一個Service的永久鏈接。這個方法也會在服務沒有運行的條件下創建服務(調用 onCreate()),但是不調用onStart()。客戶端會得到服務的onBind(Intent)方法返回的IBinder對象,用來允許客戶端回調服務的方法。只要連接已經建立服務會一直運行下去(無論客戶端是否保留服務的IBinder對象的引用)。通常返回的IBinder對象是aidl中定義的復雜接口。
A service can be both started and have connections bound to it.這種情況下,系統會為之Service運行只要它被啟動或者有一個或者多個對它的使用Context.BIND_AUTO_CREATE flag的鏈接。一旦沒有著這一個的情況發生,Service的哦呢Destroy()會被調用,Service會被有效的結束。所有的 cleanup(停止線程,反注冊receiver等)在onDestroy()返回的時候完成。
使用Service的兩種方法:
1、It can be started and allowed to run until someone stops it or it stops itself. In this mode, it's started by calling Context.startService() and stopped by calling Context.stopService(). It can stop itself by calling Service.stopSelf() or Service.stopSelfResult(). Only one stopService() call is needed to stop the service, no matter how many times startService() was called.
2、It can be Operated programmatically using an interface that it defines and exports. Clients establish a connection to the Service object and use that connection to call into the service. The connection is established by calling Context.bindService(), and is closed by calling Context.unbindService(). Multiple clIEnts can bind to the same service. If the service has not already been launched, bindService() can optionally launch it.
也可以在startService()後bindService()。
你應該實現Service的方法( they are public):
void onCreate()
void onStart(Intent intent)
void onDestroy()
通過實現這些方法,你可以監視Service生命周期中的兩個嵌套循環:
1、Service的完全生命時間(entire lifetime)是指從調用onCreate()開始到onDestroy()返回的這段時間。Service在onCreate()中進行初始化,在onDestroy()中釋放資源。
2、Service的活動生命時間(active lifetime)從onStart()開始,onStart()會處理從startService()方法傳遞過來的Intent對象。
Service不存在onStop()方法。
注意:只有通過startService()啟動Service才會調用它的onStart()方法,通過onBind()啟動的Service不會調用。
The onCreate() and onDestroy() methods are called for all services, whether they're started by Context.startService() or Context.bindService(). However, onStart() is called only for services started by startService().
如果Service運氣其他程序bind到它,你需要實現其他的回調方法。
IBinder onBind(Intent intent)
boolean onUnbind(Intent intent)
void onRebind(Intent intent)
傳遞給bindService()的Intent對象會傳遞給onBind(),傳遞給unbindService()的Intent對象會傳遞給 onUnbind()方法。如果這個Service允許連接,onBind()返回客戶端和Service交互的通信頻道(the communications channel that clIEnts use to interact with the service)。如果有新的客戶端鏈接到Service,onUnbind()方法可以請求調用onRebind()。
3、權限(Permissions)
在manifest 文件中聲明的Service可以被全局訪問(所有的應用程序都可以訪問這個Service)。為了可以訪問這個Service,其他的程序需要在他們的 manifest文件中聲明相應的< uses-permission> 來使用啟動、停止或者綁定到這個Service。
另外,Service可以通過權限(通過在執行那個調用的實現之前調用checkCallingPermission(String))保護自己的IPC調用。
4、進程生命周期(Process LIfecycle)
android系統會盡量保持使用Service的進程盡可能長(Service被啟動或者有客戶端綁定到Service)。當系統內存變低,系統需要kill現存的進程時,Service的hosting進程的優先級將會在下列的可能中保持更高。
If the service is currently executing code in its onCreate(), onStart(), or onDestroy() methods, then the hosting process will be a foreground process to ensure this code can execute without being killed.
If the service has been started, then its hosting process is considered to be less important than any processes that are currently visible to the user on-screen, but more important than any process not visible. Because only a few processes are generally visible to the user, this means that the service should not be killed except in extreme low memory conditions.
If there are clients bound to the service, then the service's hosting process is never less important than the most important client. That is, if one of its clIEnts is visible to the user, then the service itself is considered to be visible.
注意:大多數時間你的Service是運行的,但在嚴重的內存壓力下它也可能被系統kill。如果是這樣,系統會在稍後嘗試重新啟動這個Service。 An important consequence of this is that if you implement onStart() to schedule work to be done asynchronously or in another thread, then you may want to write
-information about that work into persistent storage during the onStart() call so that it does not get lost if the service later gets killed.
Other application components running in the same process as the service (such as an Activity) can, of course, increase the importance of the overall process beyond just the importance of the service itself.
package test.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyTestService extends Service {
private static final String TAG = "MyTestService";
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG, "onBind(Intent intent) called");
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d(TAG, "onCreate() called");
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d(TAG, "onDestroy() called");
}
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Log.d(TAG, "onStart(Intent intent, int startId) called");
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG, "onUnbind(Intent intent) called");
return super.onUnbind(intent);
}
public class LocalBinder extends Binder {
public MyTestService getService() {
return MyTestService.this;
}
}
}
package test.service;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.VIEw;
import android.widget.Button;
public class ServiceDemo extends Activity {
private static final String TAG = "ServiceDemo";
private Button mBtnStart, mBtnStop, mBtnBind, mBtnUnbind;
private MyTestService mService;
private boolean isBinded;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentVIEw(R.layout.main);
mBtnStart = (Button) findVIEwById(R.id.btnStartService);
mBtnStop = (Button) findVIEwById(R.id.btnStopService);
mBtnBind = (Button) findVIEwById(R.id.btnBindService);
mBtnUnbind = (Button) findVIEwById(R.id.btnUbindService);
mBtnStart.setOnClickListener(new VIEw.OnClickListener() {
@Override
public void onClick(VIEw v) {
startService();
}
});
mBtnStop.setOnClickListener(new VIEw.OnClickListener() {
@Override
public void onClick(VIEw v) {
stopService();
}
});
mBtnBind.setOnClickListener(new VIEw.OnClickListener() {
@Override
public void onClick(VIEw v) {
bindService();
}
});
mBtnUnbind.setOnClickListener(new VIEw.OnClickListener() {
@Override
public void onClick(VIEw v) {
unbindService();
}
});
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = ((MyTestService.LocalBinder)(service)).getService();
Log.i(TAG, "in onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
Log.i(TAG, "in onServiceDisconnected");
}
};
private void startService() {
Intent i = new Intent(this, MyTestService.class);
startService(i);
}
private void stopService() {
Intent i = new Intent(this, MyTestService.class);
stopService(i);
}
private void bindService() {
Intent i = new Intent(this, MyTestService.class);
bindService(i, mServiceConnection, Context.BIND_AUTO_CREATE);
isBinded = true;
}
private void unbindService() {
if(isBinded) {
unbindService(mServiceConnection);
isBinded = false;
}
}
}
< ?XML version="1.0" encoding="utf-8"?>
< TableLayout XMLns:android="http://schemas.android.com/apk/res/android"
android:orIEntation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
< TableRow android:layout_width="fill_parent" android:gravity="center"
android:layout_height="wrap_content">
< TextVIEw android:id="@+id/text" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:minLines="2" />
< /TableRow>
< TableRow android:layout_width="fill_parent" android:gravity="center"
android:layout_height="wrap_content" android:paddingTop="24px">
< Button android:id="@+id/btnStartService" android:text="StartService"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
< Button android:id="@+id/btnStopService" android:text="StopService"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
< /TableRow>
< TableRow android:layout_width="fill_parent" android:gravity="center"
android:layout_height="wrap_content" android:paddingTop="24px">
< Button android:id="@+id/btnBindService" android:text="BindService"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
< Button android:id="@+id/btnUbindService" android:text="UbindService"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
< /TableRow>
< /TableLayout>
< ?XML version="1.0" encoding="utf-8"?>
< manifest XMLns:android="http://schemas.android.com/apk/res/android"
package="test.service" android:versionCode="1" android:versionName="1.0">
< application android:icon="@drawable/icon" android:label="@string/app_name">
< activity android:name=".ServiceDemo" android:label="@string/app_name">
< intent-filter>
< action android:name="android.intent.action.MAIN" />
< category android:name="android.intent.category.LAUNCHER" />
< /intent-filter>
< /activity>
< service android:name=".MyTestService" android:enabled="true"
android:process=":local" >
< /service>
< /application>
< uses-sdk android:minSdkVersion="4" />
< /manifest>
android是一個針對觸摸屏專門設計的操作系統,當點擊編輯框,系統自動為用戶彈出軟鍵盤,以便用戶進行輸入。 那麼,彈出軟鍵盤後必然
HTC Hero作為一款硬件配置強悍的智能手機,對不同版本的android系統兼容性非常好,曾有用戶將HTC新機Espresso內的2.1版android系統和最新的S
很多開發者考慮使自己的Android程序兼容多國語言,其實Google在設計Android時已經考慮了本地化問題,通過定義相關的資源可以自適應當前手機的語言來加載響應的
眾所周知,在寫 android 程序的時候,很容易出現 OOM ,而出現的時機大多數是由 Bitmap decode 引發的: &