服务Service介绍
运行于后台,没有图形界面。
做耗时操作,实际使用中要开子线程来实现耗时操作。
包含有服务的进程,进程级别会被提高。
分启动服务和绑定服务两类。
服务的创建和注册
定义一个继承Service的子类,并重写相关方法。
public class MyService extends Service{ }
在清单文件中配置Service类
<service android: name=”com.example.test.Service”></service>
服务的启动与终止
//启动服务
Intent intent=new Intent();
//显示意图启动服务
intent.setClass(MainActivity.this,MyService.class);
//隐式意图启动服务
Intent.setAction(“com.fs.service.MyService”);
//该方法声明于context中
startService(intent);
停止服务
//该方法声明于Context中 被动停
StopService(intent);
//stopSelf是Service的实例方法 自停
StopSelf();
服务的生命周期
- Service与Activity一样都时Context派生出来的,也有自己的生命周期
Service生命周期方法解释
- 必须实现的方法,返回Ibinder对象,应用程序可以通过该对象与Service组件通信,使用StartService启动的服务该方法不会被回调。
Public IBinder onBind(Intent intent)
//当该Service第一次被创建后将立即回调该方法
Public void onCreate()
//该方法早期版本为public void onStart(Intent intent,int startid),
//当每次调用StartService(intent)启动服务时,都会回调该方法。
Public int onStartCommand(Intent intent ,int flags,int startId)
启动服务(非绑定的服务)
*普通方式启动服务时,启动服务的组件只负责启动停止,其它没有什么关系
代码演示:
MainActivity.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends Activity implements OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button1).setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);
findViewById(R.id.button3).setOnClickListener(this);
findViewById(R.id.button4).setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id=v.getId();
Intent intent=new Intent();
if(id==R.id.button1){
//启动服务1
intent.setClass(this, MyService1.class);
startService(intent);
}else if(id==R.id.button2){
//启动服务2
intent.setClass(this, MyService2.class);
startService(intent);
}else if(id==R.id.button3){
//关闭服务1
stopService(new Intent(this, MyService1.class));
}else if(id==R.id.button4){
//关闭服务2
stopService(new Intent("com.example.android_906_service.MyService2"));
}
}
}
MyService1.java
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyService1 extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d("Tag", "onCreate1");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.d("Tag", "onStartCommand1");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("Tag", "onDestroy1");
} }
MyService2.java
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyService2 extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d("Tag", "onCreate2");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.d("Tag", "onStartCommand2");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("Tag", "onDestroy2");
}
}
Activity_main.xml
<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="com.example.android_906_service.MainActivity" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="77dp"
android:text="启动服务1" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="33dp"
android:text="启动服务2" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button2"
android:layout_below="@+id/button2"
android:layout_marginTop="24dp"
android:text="关闭服务1" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/button3"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp"
android:text="关闭服务2" />
</RelativeLayout>
绑定服务
绑定服务可以解决服务的组件与服务进行通信,绑定服务职能是在同一个项目中。
底层是Binder驱动进行进程间通信。
具体在Service中创建一个内部类(IBinder接口实现类),在Service的onBinder返回该内部类对象,该对象会传回到客户端,客户端通过该对象调用该对象的方法实现与Service的通信。
客户端通过 ServiceConnection得到Service中onBinder返回的对象。
绑定服务使用bindService方法
解绑使用unBindService方法或者启动服务的组件被销毁
服务中int onStartCommand(Intent intent,int flag,int startID)有三种返回值;当Service被异常kill掉后
- Service.STARTSTICKY(默认值)
当Service因为内存不足而被系统Kill后,接下来未来的某个时间内,当系统内存足够的情况下,系统将会尝试重新创建此Service,一旦创建成功后将回调onStartCommand(…)方法,但其中的Intent僵尸null,pendingIntent除外。
如果service和访问者之间需要进行方法调用或者数据传递时应当使用bindService()和unbindService()方法开启关闭服务。
BindService(Intent service,ServiceConnection conn,int flags)
- Service:通过intent指定需要启动的服务。
- Conn:ServiceConnection对象,用于监听Service与 之间的连接情况。
- Flag: 指定绑定服务时是否自动创建Service(如果服务还没有创建就自动创建)该参数一般为BINDAUTOCREATE。
绑定服务注意事项
- 组件绑定服务后,一旦组件被销毁,会自动解除与服务的绑定 不能跨项目实现绑定(AIDL可以跨项目)
- ServiceConnection中onServiceDisconnected
方法只能在异常情况下被调用。绑定服务也是服务,所以一定要配置
启动服务和绑定服务混合使用
服务既被绑定又被启动的情况下的生命周期
操作示例:
- 1服务启动后在绑定服务onCreate onStartCommand onBind
- 2绑定服务后在启动服务onCreate onBind onStartCommand