您的位置:首页 > 移动开发 > Android开发

Android之Service例程

2015-08-10 18:22 344 查看
转载/article/2781421.html

一个服务是一个应用程序组合,在后台运行,可以执行一个长时间的操作,但是并不提供用户界面。

应用程序终止,Service也不会终止。。。。每个Service必须在manifest中
通过<service>来声明。可以通过contect.startservice和contect.bindserverice来启动。。Service和其他的应用组件一样,运行在进程的主线程中。这就是说如果service需要很多耗时或者阻塞的操作,需要在其子线程中实现。

service的两种模式(startService()/bindService()不是完全分离的):

本地服务LocalService用于应用程序内部。


它可以启动并运行,直至有人停止了它或它自己停止。在这种方式下,它以调用Context.startService()启动,而以调用Context.stopService()结束。它可以调用Service.stopSelf()或Service.stopSelfResult()来自己停止。不论调用了多少次startService()方法,你只需要调用一次stopService()来停止服。用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。

远程服务RemoteService用于android系统内部的应用程序之间。

它可以通过自己定义并暴露出来的接口进行程序操作。客户端建立一个到服务对象的连接,并通过那个连接来调用服务。连接以调用Context.bindService()方法建立,以调用Context.unbindService()关闭。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。

两种Service方式启动服务的主要区别

1、startService()方式启动。

使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。

如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法(在2.0之后已经改变onStartCommond()方法)。

如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。

采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。或者自己停止。

2、bindService()方式启动;(异步)

调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用

采用Context.bindService()方法启动服务时只能调用onUnbind()方法解除调用者与服务解除,服务结束时会调用onDestroy()方法

Service生命周期:(如图,不做介绍)






拥有service的进程具有较高的优先级

官方文档告诉我们,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级

1、如果service正在调用onCreate,onStartCommand或者onDestory方法,那么用于当前service的进程则变为前台进程以避免被killed。

2、如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.

3、如果客户端已经连接到service(bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。

4、如果service可以使用startForeground(int,Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。

如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。

分析onStartCommand方法参数的作用和返回值的作用:

1、根据这个方法的返回值不同可以有两种启动模式START_NOT_STICKY,START_STICKY,(当进行被杀死的时候,是否重新启动。如果是参数:START_REDELIVER_INTENT表示当服务所在进程被杀死后,重新启动,并且重新传递Intent内容,其它两个参数不会重新传递intent,都为null)

2、返回START_REDELIVER_INTENT的时候,如果不论启动多少次,当重新启动的时候,也会启动多少次。

3、是当前服务的标记

4、第三个参数startId表示当前启动的Service的次数。

下面看一下测试源码:

HelloSerivce.java

[java]
viewplaincopyprint?

publicclassHelloServiceextendsService{
Handlerhandler=newHandler();
privatefinalIBindermBinder=newHelloBinder();
@Override
publicvoidonCreate(){
Log.v("verbose","onCreate");
super.onCreate();
}

/**
*用这种方式,从Activity启动服务之后,在后台运行的,之后就没有与Activity联系了如果有bind方法
*,在整个过程中与Activity进行通信
*
*根据这个方法的返回值不同可以有两种启动模式START_NOT_STICKY,START_STICKY,
*START_REDELIVER_INTENT服务被系统杀死后是否自动重启,和是否重新传递intent。
*如果被杀死之后重新启动服务,会重新调用onCreate,和onStartCommand方法
*,但是重新调用onStartCommand的时候,不会再次传递参数。。
*返回START_REDELIVER_INTENT的时候,如果不论启动多少次,当重新启动的时候,也会启动多少次。
*/
@Override
publicintonStartCommand(Intentintent,intflags,intstartId){
Log.v("verbose","onStartComand");
handler.post(newRunnable(){//用通常用Handler线程跟UI线程打交到
@Override
publicvoidrun(){
Toast.makeText(getApplicationContext(),"启动服务",
Toast.LENGTH_LONG).show();

}
});
//returnsuper.onStartCommand(intent,flags,startId);
returnSTART_REDELIVER_INTENT;
}

@Override
publicvoidonDestroy(){
Log.v("verbose","onDestory");
handler.post(newRunnable(){//用通常用Handler线程跟UI线程打交到
@Override
publicvoidrun(){
Toast.makeText(getApplicationContext(),"停止服务",
Toast.LENGTH_LONG).show();
}
});
super.onDestroy();
}

/**
*这个方法是必须执行的,当用bind方法启动Service的时候,是有用的。
*/
@Override
publicIBinderonBind(Intentintent){
//TODOAuto-generatedmethodstub
returnmBinder;
}

/**
*ClassusedfortheclientBinder.Becauseweknowthisservicealways
*runsinthesameprocessasitsclients,wedon'tneedtodealwithIPC.
*/
publicclassHelloBinderextendsBinder{
HelloServicegetService(){
returnHelloService.this;
}
}

publicvoidshowNumber(){
newThread(newRunnable(){
inti=1;
@Override
publicvoidrun(){
while(true){
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println(i++);
}
}
}).start();
}
}

HelloServiceActivity.java

[java]
viewplaincopyprint?

packagehb.android.service;

importhb.android.service.HelloService.HelloBinder;
importandroid.app.Activity;
importandroid.content.ComponentName;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.ServiceConnection;
importandroid.os.Bundle;
importandroid.os.IBinder;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
importandroid.widget.TextView;

publicclassHelloServiceActivityextendsActivity{
Intentintent;
booleanflag=true;
HelloServicemService;;
booleanmBound=false;
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
intent=newIntent();
initMyWidget();
setMyWidgetListener();
}

publicvoidsetMyWidgetListener(){
MyWidget.btn_bind.setOnClickListener(newWidgetOnClickListener());
MyWidget.btn_start.setOnClickListener(newWidgetOnClickListener());
MyWidget.btn_stop.setOnClickListener(newWidgetOnClickListener());
MyWidget.btn_unbind.setOnClickListener(newWidgetOnClickListener());
MyWidget.btn_kill.setOnClickListener(newWidgetOnClickListener());
}

classWidgetOnClickListenerimplementsOnClickListener{

@Override
publicvoidonClick(Viewv){
switch(v.getId()){
caseR.id.btn_start:
intent.setClass(getApplicationContext(),HelloService.class);
intent.putExtra("test","start");
startService(intent);
flag=true;
MyWidget.btn_stop.setEnabled(flag);
break;
caseR.id.btn_stop:
intent.putExtra("test","stop");
stopService(intent);
flag=false;
MyWidget.btn_stop.setEnabled(flag);
break;
caseR.id.btn_kill:
android.os.Process.killProcess(android.os.Process.myPid());
break;
caseR.id.btn_bind:
Intentintent=newIntent(getApplicationContext(),HelloService.class);
bindService(intent,mConnection,Context.BIND_AUTO_CREATE);//自动调用Service里的onCreate方法
System.out.println("bind:"+mService);
opeService();
break;
caseR.id.btn_unbind:
if(mBound){
unbindService(mConnection);//自动调用Service的onDestory方法
mBound=false;
}
break;
default:
break;
}
}

publicvoidopeService(){
System.out.println("opeService:"+mService);
//mService.showNumber();

}
}

publicvoidinitMyWidget(){
MyWidget.btn_bind=(Button)findViewById(R.id.btn_bind);
MyWidget.btn_start=(Button)findViewById(R.id.btn_start);
MyWidget.btn_stop=(Button)findViewById(R.id.btn_stop);
MyWidget.btn_unbind=(Button)findViewById(R.id.btn_unbind);
MyWidget.tv_test=(TextView)findViewById(R.id.tv_test);
MyWidget.btn_kill=(Button)findViewById(R.id.btn_kill);
}

privatestaticclassMyWidget{
staticButtonbtn_start;
staticButtonbtn_stop;
staticButtonbtn_bind;
staticButtonbtn_unbind;
staticButtonbtn_kill;
@SuppressWarnings("unused")
staticTextViewtv_test;
}

@Override
protectedvoidonDestroy(){
super.onDestroy();
stopService(intent);
}

/**Definescallbacksforservicebinding,passedtobindService()*/
privateServiceConnectionmConnection=newServiceConnection(){
publicvoidonServiceConnected(ComponentNameclassName,
IBinderservice){
//We'veboundtoLocalService,casttheIBinderandgetLocalServiceinstance
HelloBinderbinder=(HelloBinder)service;
mService=binder.getService();
System.out.println("ServiceConnection:"+mService);
mBound=true;
mService.showNumber();
}

@Override
publicvoidonServiceDisconnected(ComponentNamearg0){
mBound=false;
}
};
@Override
protectedvoidonStop(){
super.onStop();
if(mBound){
unbindService(mConnection);
mBound=false;
}
};
}

注意:当服务创建之后由,onServiceConnected这个方法负责建立与Servicer的连接

意思当Activit用BindService启动服务之后,由:

[java]
viewplaincopyprint?

publicServiceConnectionmConnection=newServiceConnection(){

@Override
publicvoidonServiceDisconnected(ComponentNamename){
System.out.println("onServiceConnected");
mBound=false;
}
/**
*服务创建之后收些方法建立Serivce与Activity的连接
*/
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
System.out.println("onServiceDisconnected");
mBound=true;
LocalBindermyBinder=(LocalBinder)service;
myService=myBinder.getService();//在下面就可以对service进行操作了。
myService.showNumber();
}
};

对所绑定的Service进行控制(连接与销毁)
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: