android中的service是android四大组件之一,当你看到学渣的这篇博客时,说明你在艰难前行,学渣的service学习主要参考官网,请养成阅读官方指导的习惯。。。。
1 service是什么?
service是一个没有界面的activity,有自己的生命周期,可以启动,关闭等。而且service有local和remote之分,这里主要讲的是本地的,以后有时间学渣会继续分析。如果想使用service,首先继承Service,其次在mainfest.xml中声明(是不是和activity一样呢),这里学渣声明了一个MyService,代码如下:
public class MyService extends Service{
String TAG = "MyService";
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand() executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() executed");
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
然后在xml中进行注册,如下:
<service
android:name="com.example.servicetest.MyService">
</service>
2 service的声明周期(之一)
生命周期需要从service的启动说起,service是通过Context启动的,在官网里说的是Context.startService(),而activity就是一个Context,大家可以参考一下别的文章,Activity是继承自Context(abstact class)的一个类。用Intent可以选择目的service,Intent可以启动很多组件,如activity,service等。在activity里声明一个Intent,之后启动。学渣用一个例子说明,现在activity定义两个按钮来检测service的生命周期。
效果图如下:
布局文件如下所示:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="@+id/startbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="startService"/>
<Button
android:id="@+id/stopbutton"
android:layout_below="@id/startbutton"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stopService"/>
</RelativeLayout>
activity如下所示:
public class MainActivity extends Activity {
Intent serviceIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serviceIntent = new Intent(this , MyService.class);
Button startButton = (Button)findViewById(R.id.startbutton);
startButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//启动service
startService(serviceIntent);
}
});
Button stopButton = (Button)findViewById(R.id.stopbutton);
stopButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//停止service
stopService(serviceIntent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
在activity中,点击startbutton后输出如下:
点击stopbutton后输出如下:
这其实就是对service的一个完美诠释:
在activity里调用startService()之后在service里onCreate()->onStartCommand()
而在activity里调用stopService()之后在service里onDestroy()
3 service声明周期(之二)
上述的方法中,activity与service没什么联系,如果想让activity与servie有联系,可以采用第二种启动servie的方法。就是采用Context.bindService(),在service中有这么几行代码还没有用到就是关于这个IBinder的。既然service是为了和activity建立联系,就需要一个中介,这个中介就是IBinder,这是一个接口,详情可以看这个页面,这个IBinder是为了远程交互而使用的。在service中使用继承自Binder(实现IBinder接口)的类,之后会有解释的。
ok,从启动service开始,用另一种方法,就是用bindService(),在service中需要实现IBind onBind()函数,返回给activity一个IBinder对象,用来和service交互。这样一个activity就和service绑定在一起,想交互在activity中还需要实现一个ServiceConnection对象,用来监视和service的联系。当联系建立起来后,会调用ServiceConnection中的onServiceConnected()函数,会返回和service交互的IBinder对象。
activity和service交互的流程图如下:
这里有一个例子,activity调用service里的函数进行输出。。。。
mainActivity的代码如下:
public class MainActivity extends Activity {
Intent serviceIntent;
IBinder myBinder;
MyService myService;
boolean mBound = false;//用来检测和service是否绑定
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serviceIntent = new Intent(this , MyService.class);
//绑定activity和service
bindService(serviceIntent , serviceConnection , Context.BIND_AUTO_CREATE);
Button startButton = (Button)findViewById(R.id.startbutton);
startButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if(mBound){
//如果绑定成功,测试一下service里的函数
String out = myService.getServiceString();
System.out.println(out);
}
}
});
}
//定义一个ServiceConnection对象用来和service交互
private ServiceConnection serviceConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName arg0, IBinder binder) {
// TODO Auto-generated method stub
Log.d("Activity", "service connected");
MyBinder myBinder = (MyBinder) binder;
myService = myBinder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
service代码如下:
public class MyService extends Service{
private final IBinder myBinder = new MyBinder();
String TAG = "MyService";
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand() executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() executed");
}
/** method for clients */
public String getServiceString() {
return "getting string from service";
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return myBinder;
}
public class MyBinder extends Binder {
MyService getService() {
// Return this instance of LocalService so clients can call public methods
return MyService.this;
}
}
}