Service一直后台运行,它没有用户界面;一旦启动,就与Activity一样,完全具有自己的生命周期
开发Service组件需要
- 先开发一个Service的子类
- 然后再AndroidManifest.xml文件中配置该Service,配置时可通过<intent-filter.../>元素指定它可以被那些Intent启动
Android系统提供了大量的Service组件,开发者可通过这些系统Service来操作Android系统本身
Service与Activity都从Context派生,因此可调用getResources()、getContentResolver()等;
生命周期
IBinder onBind(Intent intent)
|
必须实现的方法,返回一个IBinder对象,应用通过该对象与Service组件通信
|
void onCreate()
|
|
void onDestroy()
|
|
void onStartCommand(Intent intent, int flags, int startId)
|
每次客户端调用startService(Intent)方法启动该Service时都会回调该方法
|
boolean onUnbind(Intent intent)
|
当该Service上绑定的所有客户端都断开连接时会回调该方法
|
示例代码
public
class
FirstService
extends
Service
{
@Override
public IBinder onBind ( Intent arg0 )
{
return null ;
}
@Override
public void onCreate ()
{
super . onCreate ();
System . out .println( "Service is created" );
}
@Override
public int onStartCommand ( Intent intent , int flags , int startId )
{
System . out .println( "Service is started" );
return START_STICKY ;
}
@Override
public void onDestroy ()
{
super . onDestroy ();
System . out .println( "Service is destroyed" );
}
@Override
public IBinder onBind ( Intent arg0 )
{
return null ;
}
@Override
public void onCreate ()
{
super . onCreate ();
System . out .println( "Service is created" );
}
@Override
public int onStartCommand ( Intent intent , int flags , int startId )
{
System . out .println( "Service is started" );
return START_STICKY ;
}
@Override
public void onDestroy ()
{
super . onDestroy ();
System . out .println( "Service is destroyed" );
}
}
<
service
android:name
=
".FirstService"
>
< intent-filter >
< action android:name = "com.example.service.FIRST_SERVICE" />
</ intent-filter >
< intent-filter >
< action android:name = "com.example.service.FIRST_SERVICE" />
</ intent-filter >
</
service
>
Service开发完成后,接下来就可在程序中运行该Service了,Android系统中运行Service
- 通过Context的startService()方法:访问者与Service之间没有关联,即使访问者退出,Service任然运行
- 通过Context的bindService()方法:访问者与Service绑定在一起,访问者一旦退出,Service也终止
示例代码(使用Activity作为Service的访问者,一个启动Service按钮,一个关闭Service按钮)
如果Service和访问者之间需要进行方法调用或数据交换,则应该使用bindService()和unbindService()方法启动、关闭Service
bindService(Intent service, ServiceConnection conn, int flags)
- service:该参数通过Intent指定要启动的Service
- conn:ServiceConnection对象,监听访问者与Service之间的连接情况;当连接成功时回调ServiceConnection对象的onServiceConnected(ComponentName name, IBinder service)方法,断开时onServiceDisconnected(ComponentName name)方法
- flags:指绑定时是否自动创建Service(可指定为0或者BIND_AUTO_CREATE)
实际开发时通常会采用继承Binder(IBinder的实现类)的方式实现自己的IBinder对象。
示例代码
(示范了如何在Activity中绑定本地Service,并获取Service的运行状态。该程序的Service类需要“真正”实现onBind()方法,并让该方法放回一个有效的IBinder对象)
BindService
public
class
BindService
extends
Service
{
private int count ;
private boolean quit ;
private MyBinder binder = new MyBinder();
public class MyBinder extends Binder
{
public int getCount ()
{
return count ;
}
}
@Override
public IBinder onBind ( Intent intent )
{
System . out .println( "Service is Binded" );
return binder ;
}
@Override
public void onCreate ()
{
super . onCreate ();
System . out .println( "Service is Created" );
new Thread()
{
@Override
public void run ()
{
while (! quit )
{
try {
Thread . sleep ( 1000 );
}
catch ( InterruptedException e )
{}
count ++;
}
}
}.start();
}
@Override
public boolean onUnbind ( Intent intent )
{
System . out .println( "Service is Unbinded" );
return true ;
}
@Override
public void onDestroy ()
{
super . onDestroy ();
this . quit = true ;
System . out .println( "Service is Destroyed" );
}
private int count ;
private boolean quit ;
private MyBinder binder = new MyBinder();
public class MyBinder extends Binder
{
public int getCount ()
{
return count ;
}
}
@Override
public IBinder onBind ( Intent intent )
{
System . out .println( "Service is Binded" );
return binder ;
}
@Override
public void onCreate ()
{
super . onCreate ();
System . out .println( "Service is Created" );
new Thread()
{
@Override
public void run ()
{
while (! quit )
{
try {
Thread . sleep ( 1000 );
}
catch ( InterruptedException e )
{}
count ++;
}
}
}.start();
}
@Override
public boolean onUnbind ( Intent intent )
{
System . out .println( "Service is Unbinded" );
return true ;
}
@Override
public void onDestroy ()
{
super . onDestroy ();
this . quit = true ;
System . out .println( "Service is Destroyed" );
}
}
BindServiceTest
public
class
BindServiceTest
extends
Activity
{
Button bind , unbind , getServiceStatus ;
BindService . MyBinder binder ;
private ServiceConnection conn = new ServiceConnection()
{
@Override
public void onServiceConnected ( ComponentName name
, IBinder service )
{
System . out .println( "---Service Connected---" );
binder = ( BindService . MyBinder ) service ;
}
@Override
public void onServiceDisconnected ( ComponentName name )
{
System . out .println( "---Service Disconnected---" );
}
};
@Override
public void onCreate ( Bundle savedInstanceState )
{
super . onCreate ( savedInstanceState );
setContentView ( R . layout . main );
bind = ( Button ) findViewById ( R . id . bind );
unbind = ( Button ) findViewById ( R . id . unbind );
getServiceStatus = ( Button ) findViewById ( R . id . getServiceStatus );
final Intent intent = new Intent();
intent .setAction( "com.example.service.BIND_SERVICE" );
bind .setOnClickListener( new OnClickListener()
{
@Override
public void onClick ( View source )
{
bindService( intent , conn , Service . BIND_AUTO_CREATE );
}
});
unbind .setOnClickListener( new OnClickListener()
{
@Override
public void onClick ( View source )
{
unbindService( conn );
}
});
getServiceStatus .setOnClickListener( new OnClickListener()
{
@Override
public void onClick ( View source )
{
Toast . makeText ( BindServiceTest . this , "Service count value:"
+ binder .getCount(), Toast . LENGTH_SHORT ).show();
}
});
}
Button bind , unbind , getServiceStatus ;
BindService . MyBinder binder ;
private ServiceConnection conn = new ServiceConnection()
{
@Override
public void onServiceConnected ( ComponentName name
, IBinder service )
{
System . out .println( "---Service Connected---" );
binder = ( BindService . MyBinder ) service ;
}
@Override
public void onServiceDisconnected ( ComponentName name )
{
System . out .println( "---Service Disconnected---" );
}
};
@Override
public void onCreate ( Bundle savedInstanceState )
{
super . onCreate ( savedInstanceState );
setContentView ( R . layout . main );
bind = ( Button ) findViewById ( R . id . bind );
unbind = ( Button ) findViewById ( R . id . unbind );
getServiceStatus = ( Button ) findViewById ( R . id . getServiceStatus );
final Intent intent = new Intent();
intent .setAction( "com.example.service.BIND_SERVICE" );
bind .setOnClickListener( new OnClickListener()
{
@Override
public void onClick ( View source )
{
bindService( intent , conn , Service . BIND_AUTO_CREATE );
}
});
unbind .setOnClickListener( new OnClickListener()
{
@Override
public void onClick ( View source )
{
unbindService( conn );
}
});
getServiceStatus .setOnClickListener( new OnClickListener()
{
@Override
public void onClick ( View source )
{
Toast . makeText ( BindServiceTest . this , "Service count value:"
+ binder .getCount(), Toast . LENGTH_SHORT ).show();
}
});
}
}
Service配置代码
<
service
android:name
=
".BindService"
>
<
intent-filter
>
< action android:name = "com.example.service.BIND_SERVICE" />
</ intent-filter >
< action android:name = "com.example.service.BIND_SERVICE" />
</ intent-filter >
</
service
>
与多次调用startService()方法启动Service不同的是,多次调用bindService()方法并不会执行重复绑定
IntentService
Service本身存在的两个问题
- Service不会专门启动一条单独的进程,Service与它所在应用位于同一个进程中
- Service也不是专门一条新的线程,因此不该在Service中直接处理耗时任务
而IntentService正好可以弥补Service的上述两个不足
IntentService使用队列来管理请求Intent,每次使用新的worker线程处理Intent请求,因此IntentService不会阻塞主线程,它自己就可以处理耗时任务,IntentService有如下特征
- IntentService会创建单独的worker线程来处理所有的Intent请求
- IntentService会创建单独的worker线程来处理onHandleIntent()方法处理代码,开发者无需处理多线程
- 当所有请求处理完成后,IntentService会自动停止,因此无需调用stopSelf()来停止
- 为Service的onBind()方法提供了默认的实现,默认实现的onBind()方法返回null
- 为Service的onStartCommand()方法提供了默认实现,该实现会将请求Intent添加到队列中
扩展IntentService无须重写onBind()、onStartCommand()方法,只要重写onHandleIntent()方法
示例
IntentServiceTest.java
public
class
IntentServiceTest
extends
ActionBarActivity
{
@Override
protected void onCreate ( Bundle savedInstanceState ) {
super . onCreate ( savedInstanceState );
setContentView ( R . layout . main );
}
public void startService ( View source )
{
Intent intent = new Intent( this , MyService . class );
startService ( intent );
}
public void startIntentService ( View source )
{
Intent intent = new Intent( this , MyIntentService . class );
startService ( intent );
@Override
protected void onCreate ( Bundle savedInstanceState ) {
super . onCreate ( savedInstanceState );
setContentView ( R . layout . main );
}
public void startService ( View source )
{
Intent intent = new Intent( this , MyService . class );
startService ( intent );
}
public void startIntentService ( View source )
{
Intent intent = new Intent( this , MyIntentService . class );
startService ( intent );
}
}
MyService.java
public
class
MyService
extends
Service
{
@Override
public IBinder onBind ( Intent intent )
{
return null ;
}
@Override
public int onStartCommand ( Intent intent , int flags , int startId )
{
long endTime = System . currentTimeMillis () + 20 * 1000 ;
System . out .println( "onStart" );
while ( System . currentTimeMillis () < endTime )
{
synchronized ( this )
{
try {
wait ( endTime - System . currentTimeMillis ());
}
catch ( Exception e )
{
}
}
}
System . out .println( "----time consuming task running---" );
return START_STICKY ;
}
@Override
public IBinder onBind ( Intent intent )
{
return null ;
}
@Override
public int onStartCommand ( Intent intent , int flags , int startId )
{
long endTime = System . currentTimeMillis () + 20 * 1000 ;
System . out .println( "onStart" );
while ( System . currentTimeMillis () < endTime )
{
synchronized ( this )
{
try {
wait ( endTime - System . currentTimeMillis ());
}
catch ( Exception e )
{
}
}
}
System . out .println( "----time consuming task running---" );
return START_STICKY ;
}
}
MyIntentService.java
public
class
MyIntentService
extends
IntentService
{
public MyIntentService ()
{
super ( "MyIntentService" );
}
@Override
protected void onHandleIntent ( Intent intent )
{
long endTime = System . currentTimeMillis () + 20 * 1000 ;
System . out .println( "onStart" );
while ( System . currentTimeMillis () < endTime )
{
synchronized ( this )
{
try {
wait ( endTime - System . currentTimeMillis ());
} catch ( Exception e ){}
}
}
}
public MyIntentService ()
{
super ( "MyIntentService" );
}
@Override
protected void onHandleIntent ( Intent intent )
{
long endTime = System . currentTimeMillis () + 20 * 1000 ;
System . out .println( "onStart" );
while ( System . currentTimeMillis () < endTime )
{
synchronized ( this )
{
try {
wait ( endTime - System . currentTimeMillis ());
} catch ( Exception e ){}
}
}
}
}