Android的Service總結
參考鏈接:http://www.cnblogs.com/lwbqqyumidi/p/4181185.html
Android上經常會碰到Service,用到的都比較零散,今天比較全面的了解了下。
Service也是組件之一,如需使用,需要在清單文件中注冊。代碼如下:
<service
android:exported=["true" | "false"]
android:icon="drawable resource"
android:name="string"
android:process="string" >
. . .
</service>
上面是用到較多的幾個屬性,name為服務類,process為進程名。exported是否允許遠程調用。
下面是簡單的實現service類:
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service {
public static final int MSG_SEND_TO_SERVER = 1;
public static final int MSG_SEND_TO_CLIENT = 2;
private Messenger mClientMessenger;
private Messenger mServerMessenger = new Messenger(new ServerHandler());
private static int mark =1;
@Override
public IBinder onBind(Intent intent) {
return mServerMessenger.getBinder();
}
class ServerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SEND_TO_SERVER:
mClientMessenger = msg.replyTo;
Message toClientMsg = Message.obtain(null, MSG_SEND_TO_CLIENT);
toClientMsg.obj = "來自Service:" + mark;
try {
mClientMessenger.send(toClientMsg);
} catch (RemoteException e) {
e.printStackTrace();
}
mark++;
break;
default:
super.handleMessage(msg);
}
}
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.e("123","onDestroy");
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
Activity調用service簡單代碼如下:
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView tvRecord;
private Button btnBindService;
private Button btnStartService;
private Button btnSend;
private Button btnUnBindService;
private Button btnStopService;
private ServiceConnection sc = new MyServiceConnnect();
private boolean isConnnect =false;
private Messenger mServerMessenger;
private Handler mClientHandler = new MyClientHandler();
private Messenger mClientMessenger = new Messenger(mClientHandler);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findView();
setListener();
}
private void setListener(){
btnBindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyService.class);
bindService(intent, sc, Context.BIND_AUTO_CREATE);
}
});
btnStartService.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
}
});
btnSend.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
send();
}
});
btnStopService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyService.class);
stopService(intent);
}
});
btnUnBindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isConnnect) {
unbindService(sc);
isConnnect = false;
}
}
});
}
private void send(){
if (!isConnnect){
return;
}
Message msg = Message.obtain(null, MyService.MSG_SEND_TO_SERVER);
msg.replyTo = mClientMessenger;
try {
mServerMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private void findView(){
tvRecord = (TextView)findViewById(R.id.tv_record);
btnBindService = (Button) findViewById(R.id.btn_bind);
btnStartService = (Button)findViewById(R.id.btn_start);
btnSend = (Button)findViewById(R.id.btn_send);
btnStopService = (Button)findViewById(R.id.btn_stop);
btnUnBindService = (Button)findViewById(R.id.btn_unbind);
}
class MyClientHandler extends Handler{
@Override
public void handleMessage(Message msg) {
if (msg.what == MyService.MSG_SEND_TO_CLIENT) {
String obj = (String)msg.obj;
tvRecord.setText(obj);
}
}
}
class MyServiceConnnect implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mServerMessenger = new Messenger(service);
isConnnect =true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
isConnnect =false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
一般啟動服務有兩方法:startService和bindService。
startService比較簡單,通過stopService結束。當服務已經啟動,則不會調用oncreate方法,直接調用onStartCommand。startCommand的返回值意義如下:
START_NOT_STICKY:當Service因為內存不足而被系統kill後,接下來未來的某個時間內,即使系統內存足夠可用,系統也不會嘗試重新創建此Service。除非程序中Client明確再次調用startService(...)啟動此Service。
START_STICKY:當Service因為內存不足而被系統kill後,接下來未來的某個時間內,當系統內存足夠可用的情況下,系統將會嘗試重新創建此Service,一旦創建成功後將回調onStartCommand(...)方法,但其中的Intent將是null,pendingintent除外。
START_REDELIVER_INTENT:與START_STICKY唯一不同的是,回調onStartCommand(...)方法時,其中的Intent將是非空,將是最後一次調用startService(...)中的intent。
START_STICKY_COMPATIBILITY:compatibility version of [email protected] #START_STICKY} that does not guarantee that [email protected] #onStartCommand} will be called again after being killed。此值一般不會使用,所以注意前面三種情形就好。
bindService也可啟動服務,可通過unbindService結束,此方法可通過接口,通過信使通信。具體代碼如上。如通過bindservice啟動的服務,需關閉所有的依賴才可結束服務。