参考链接:http://www.cnblogs.com/lwbqqyumidi/p/4181185.html
Android上经常会碰到Service,用到的都比较零散,今天比较全面的了解了下。
Service也是组件之一,如需使用,需要在清单文件中注册。代码如下:
android:exported=["true" | "false"]
android:icon="drawable resource"
android:name="string"
android:process="string" >
. . .
上面是用到较多的几个属性,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 {@link #START_STICKY} that does not guarantee that {@link #onStartCommand} will be called again after being killed。此值一般不会使用,所以注意前面三种情形就好。
bindService也可启动服务,可通过unbindService结束,此方法可通过接口,通过信使通信。具体代码如上。如通过bindservice启动的服务,需关闭所有的依赖才可结束服务。