Android Service详解

1、Service的种类

一、本地服务, Local Service 用于应用程序内部。在Service能够调用Context.startService()启动,调用Context.stopService()结束。在内部能够调用Service.stopSelf() 或 Service.stopSelfResult()来本身中止。不管调用了多少次startService(),都只需调用一次stopService()来中止。java

二、远程服务, Remote Service 用于android系统内部的应用程序之间。能够定义接口并把接口暴露出来,以便其余应用进行操做。客户端创建到服务对象的链接,并经过那个链接来调用服务。调用Context.bindService()方法创建链接,并启动,以调用 Context.unbindService()关闭链接。多个客户端能够绑定至同一个服务。若是服务此时尚未加载,bindService()会先加载它。android

提供给可被其余应用复用,好比定义一个天气预报服务,提供与其余应用调用便可。windows

2、生命周期

1). 被启动的服务的生命周期:若是一个Service被某个Activity 调用 Context.startService方法启动,那么无论是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。若是一个Service被startService 方法屡次启动,那么onCreate方法只会调用一次,onStart将会被调用屡次(对应调用startService的次数),而且系统只会建立Service的一个实例(所以你应该知道只须要一次stopService调用)。该Service将会一直在后台运行,而无论对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。固然若是系统资源不足,android系统也可能结束服务。服务器

2). 被绑定的服务的生命周期:若是一个Service被某个Activity 调用 Context.bindService 方法绑定启动,无论调用 bindService调用几回,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当链接创建以后,Service将会一直运行,除非调用Context.unbindService 断开链接或者以前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动中止Service,对应onDestroy将被调用。架构

3).被启动又被绑定的服务的生命周期:若是一个Service又被启动又被绑定,则该Service将会一直在后台运行。而且无论如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会中止Service,而必须调用 stopService 或 Service的 stopSelf 来中止服务。app

4).当服务被中止时清除服务:当一个Service被终止(一、调用stopService;二、调用stopSelf;三、再也不有绑定的链接(没有被启动))时,onDestroy方法将会被调用,在这里你应当作一些清除工做,如中止在Service中建立并运行的线程。异步

特别注意:ide

一、你应当知道在调用 bindService 绑定到Service的时候,你就应当保证在某处调用 unbindService 解除绑定(尽管Activity被finish的时候绑定会自动解除,而且Service会自动中止)。函数

二、你应当注意 使用 startService 启动服务以后,必定要使用 stopService中止服务,无论你是否使用bindService。工具

三、同时使用 startService 与 bindService 要注意到,Service 的终止,须要unbindService与stopService同时调用,才能终止 Service,无论 startService 与 bindService 的调用顺序,若是先调用 unbindService 此时服务不会自动终止,再调用 stopService 以后服务才会中止,若是先调用 stopService 此时服务也不会终止,而再调用 unbindService 或者 以前调用 bindService 的 Context 不存在了(如Activity 被 finish 的时候)以后服务才会自动中止。

四、当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时若是你的 Activity 若是会自动旋转的话,旋转实际上是 Activity 的从新建立,所以旋转以前的使用 bindService 创建的链接便会断开(Context 不存在了),对应服务的生命周期与上述相同。

五、在 sdk 2.0 及其之后的版本中,对应的 onStart 已经被否决变为了 onStartCommand,不过以前的 onStart 任然有效。这意味着,若是你开发的应用程序用的 sdk 为 2.0 及其之后的版本,那么你应当使用 onStartCommand 而不是 onStart。


例子:

public class ServiceDemo extends Service {
    
    public static final String TAG = "ServiceDemo" ;
    public static final String ACTION = "com.demo.SERVICE_DEMO";

    /**
     * onBind 是 Service 的虚方法,所以咱们不得不实现它。
     * 返回 null,表示客服端不能创建到此服务的链接,因此不会调用onServiceConnected。
     */
    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, this.toString() + " ServiceDemo onBind");
        return null;
    }

    @Override
    public void onCreate() {
        Log.i(TAG, this.toString() + " ServiceDemo onCreate");
        super.onCreate();
    }
	
    @Override
    public void onStart(Intent intent, int startId) {
	Log.i(TAG, this.toString() + " ServiceDemo onStart");
	super.onStart(intent, startId);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, this.toString() + " ServiceDemo onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }
	
    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG, this.toString() + " ServiceDemo onUnbind");
        return super.onUnbind(intent);
    }
	
    @Override
    public void onDestroy() {
        Log.i(TAG, this.toString() + " ServiceDemo onDestroy");
        super.onDestroy();
    }

}
<!-- android:exported 这个属性用于指示该服务是否可以被其余应用程序组件调用或跟它交互。
     若是设置为true,则可以被调用或交互,不然不能。设置为false时,
     只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。-->
<service android:name=".ServiceDemo" android:exported="false">
    <intent-filter>
        <action android:name="com.demo.SERVICE_DEMO" />
        <category android:name="android.intent.category.default" />
    </intent-filter>
</service>

经过Context.startService(Intent)方法启动service或者Context.bindService方法来绑定service。

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btn_bindService).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
	        bindService(new Intent(ServiceDemo.ACTION), conn, BIND_AUTO_CREATE);
	    }
	});
        
        findViewById(R.id.btn_unbindService).setOnClickListener(new OnClickListener() {
            @Override
	    public void onClick(View v) {
		unbindService(conn);
	    }
	});
         
        findViewById(R.id.btn_startService).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
        	startService(new Intent(ServiceDemo.ACTION));
            }
        });
        
        findViewById(R.id.btn_stopService).setOnClickListener(new OnClickListener() {
	    @Override
	    public void onClick(View v) {
		stopService(new Intent(ServiceDemo.ACTION));
	    }
	});
    }
	
    ServiceConnection conn = new ServiceConnection() {
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i(ServiceDemo.TAG, service.toString() + " onServiceConnected");
        }
	public void onServiceDisconnected(ComponentName name) {
	    Log.i(ServiceDemo.TAG, "onServiceDisconnected");
	}
    };
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}

日志输出:

上面的截图是点击绑定服务时输出的。能够看出,只调用了onCreate方法和onBind方法,当重复点击绑定服务时,没有再输出任何日志,而且不报错。onCreate方法是在第一次建立Service时调用的,并且只调用一次。另外,在绑定服务时,给定了参数BIND_AUTO_CREATE,即当服务不存在时,自动建立,若是服务已经启动了或者建立了,那么只会掉调用onBind方法。

当解除绑定的时,能够看出,Service调用onUnbind和onDestroy销毁了服务。

上面的截图是在屡次点击启动服务时输出的。能够看出,在第一次点击时,由于Service还未建立,因此调用了onCreate方法,紧接着调用了onStartCommand和onStart方法。当再次点击启动服务时,仍然调用了onStartCommand和onStart方法,因此,在Service中作任务处理时须要注意这点,由于一个Service能够被重复启动。

当点中止服务的时,Service只是执行onDestroy方法,跟绑定仍是有点小区别。

这里说一下,日常使用多的是startService方法,能够把一些耗时的任务放到后台去处理,当处理完成后,能够经过广播来通知前台。

而onBind方法更多的是结合AIDL来使用,这样一个应用能够经过绑定服务得到的IBinder来拿到后台的接口,进而调用AIDL中定义的方法,进行数据交换等。

3、Local 与 Remote 服务绑定

1) Local 服务绑定:Local 服务的绑定较简单,首先在 Service 中咱们须要实现 Service 的抽象方法 onBind,并返回一个实现 IBinder 接口的对象。

Service 中的代码:

public class LocalService extends Service{
	
    public static final String TAG = "LocalService" ;
    public static final String ACTION = "com.demo.LOCAL_SERVICE";
    public SimpleBinder sBinder;

    public class SimpleBinder extends Binder{

        public LocalService getService(){
            return LocalService.this;
        }
         
        public int add(int a, int b){
            return a + b;
        }
    }
	
    @Override
    public void onCreate() {
	super.onCreate();
	// 建立 SimpleBinder
        sBinder = new SimpleBinder();
    }
	
    @Override
    public IBinder onBind(Intent intent) {
	// 返回 SimpleBinder 对象
	Log.i(TAG, "LocalService onBind");
        return sBinder;
    }
	
    @Override
    public boolean onUnbind(Intent intent) {
	Log.i(TAG, "LocalService onUnbind");
	return super.onUnbind(intent);
    }

}
<service android:name=".LocalService" android:exported="false">
    <intent-filter>
	<action android:name="com.demo.LOCAL_SERVICE" />
	<category android:name="android.intent.category.default" />
    </intent-filter>
</service>
public class LocalActivity extends ActionBarActivity {
	
    private ServiceConnection sc;
    private boolean isBind;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_local);
		
	sc = new ServiceConnection() {

            @Override
	    public void onServiceConnected(ComponentName name, IBinder service) {
	        Log.i(LocalService.TAG, "onServiceConnected");
		LocalService.SimpleBinder sBinder = (LocalService.SimpleBinder)service;
                Log.i(LocalService.TAG, "3 + 5 = " + sBinder.add(3, 5));
	    }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i(LocalService.TAG, " onServiceDisconnected");
            }
        };
        
        findViewById(R.id.btn_bindService).setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                bindService(new Intent(LocalService.ACTION), sc, Context.BIND_AUTO_CREATE);
                isBind = true;
            }
        });
        findViewById(R.id.btn_unbindService).setOnClickListener(new OnClickListener() {
             
            @Override
            public void onClick(View v) {
                if(isBind){
                    unbindService(sc);
                    isBind = false;
                }
            }
        });
    }
}

在 Activity 中,咱们经过 ServiceConnection 接口来取得创建链接 与 链接意外丢失的回调。bindService有三个参数,第一个是用于区分 Service 的Intent 与 startService 中的 Intent 一致,第二个是实现了 ServiceConnection 接口的对象,最后一个是 flag 标志位。有两个flag,BIND_DEBUG_UNBIND 与 BIND_AUTO_CREATE,前者用于调试(详细内容能够查看javadoc 上面描述的很清楚),后者默认使用。unbindService 解除绑定,参数则为以前建立的 ServiceConnection 接口对象。另外,屡次调用 unbindService 来释放相同的链接会抛出异常,所以我建立了一个 boolean 变量来判断是否 unbindService 已经被调用过。

运行结果:

在绑定服务的时候,须要一个服务链接对象,ServiceConnection,服务一旦链接,就会调用onServiceConnected方法,咱们能够在这个方法里面返回咱们的本地服务对象,具体看代码;而在服务断开时候会调用onServiceDisconnected方法,咱们能够清理一些服务资源。

2) Remote 服务绑定以前所谈的Service属于Local Service,即Service和Client在同一进程内(即同一application内),Service的生命周期服从进程的生命周期。在实际应用上,有时但愿Service做为后台服务,不只被同一进程内的activity使用,也可被其余进程所使用。

一般每一个应用程序都在它本身的进程内运行,但有时须要在进程之间传递对象(IPC通讯),你能够经过应用程序UI的方式写个运行在一个不一样的进程中的service。在android平台中,一个进程一般不能访问其它进程中的内存区域。因此,他们须要把对象拆分红操做系统能理解的简单形式,以便假装成对象跨越边界访问。编写这种假装代码至关的枯燥乏味,好在android为咱们提供了AIDL工具能够来作这件事。

AIDL(android接口描述语言)是一个IDL语言,它能够生成一段代码,可使在一个android设备上运行的两个进程使用内部通讯进程进行交互。若是你须要在一个进程中(例如在一个Activity中)访问另外一个进程中(例如一个Service)某个对象的方法,你就可使用AIDL来生成这样的代码来假装传递各类参数。

Android提供AIDL(Android Interface Definition Language)工具帮助IPC之间接口的创建,大大地简化了开发者视图。经过下面的步骤实现client和service之间的通讯:

1)定义AIDL接口 ,Eclipse将自动为Service创建接口IService
2)Client链接Service,链接到IService暴露给Client的Stub,得到stub对象;换句话,Service经过接口中的Stub向client提供服务,在IService中对抽象IService.Stub具体实现。 
3)Client和Service链接后,Client可向使用本地方法那样,简单地直接调用IService.Stub里面的方法。

下面的例子给出client从提供定时计数的Remote Service,称为TestRemoteService,中得到服务的例子。

步骤1:经过AIDL文件定义Service向client提供的接口,ITestRemoteService.aidl文件以下

interface ITestRemoteService { 
    int getCounter(); 
}

咱们在src的目录下添加一个ITestRemoteService.aidl文件,语法和java的相同。在这个例子中Service很简单,只提供计数器的值,故在接口中咱们定义了int getCounter( )。

AIDL文件很简单,Eclipse会根据文件自动生成相关的一个java interface文件,不过没有显示出来,若是直接使用命令行工具会帮助生成java文件。

步骤2:Remote Service的编写,经过onBind(),在client链接时,传递stub对象。 TestRemoteService.java文件以下:

//Service提供一个定时计数器,采用Runnable的方式实现。
public class TestRemoteService extends Service{ 
    private Handler serviceHandler = null;
    private int counter = 0; 
    private TestCounterTask myTask = new TestCounterTask();  
     
    public void onCreate() {  
        super.onCreate(); 
        showInfo("remote service onCreate()");
    }  

    public void onDestroy() { 
        super.onDestroy(); 
        serviceHandler.removeCallbacks(myTask); //中止计数器
        serviceHandler = null; 
        showInfo("remote service onDestroy()");
    }  

    public void onStart(Intent intent, int startId) { 
       // 开启计数器 
        super.onStart(intent, startId); 
        serviceHandler=new Handler(); 
        serviceHandler.postDelayed(myTask, 1000); 
        showInfo("remote service onStart()"); 
    } 

   //步骤2.1:具体实现接口中暴露给client的Stub,提供一个stub inner class来具体实现。 
    private ITestRemoteService.Stub stub= new ITestRemoteService.Stub() {
       //步骤2.1:具体实现AIDL文件中接口的定义的各个方法。
        public int getCounter() throws RemoteException {  
            showInfo("getCounter()");
            return counter; 
        } 
    };  
     
//步骤2.2:当client链接时,将触发onBind(),Service向client返回一个stub对象,
//由此client能够经过stub对象来访问Service,本例中经过stub.getCounter()就能够得到计时器的当前计数。
//在这个例子中,咱们向全部的client传递同一stub对象。 
   public IBinder onBind(Intent arg0) {  
   //咱们特别跟踪了stub对象的地址,能够在client链接service中看看经过ServiceConnection传递给client
        showInfo("onBind() " + stub); 
        return stub; 
   }

    //用Runnable使用定时计数器,每10秒计数器加1。
    private class TestCounterTask implements Runnable{
        public void run() {  
            ++ counter; 
            serviceHandler.postDelayed(myTask,10000); 
            showInfo("running " + counter); 
        } 
    }  
    //showInfo() 帮助咱们进行信息跟踪,更好了解Service的运行状况
    private void showInfo(String s){ 
        System.out.println("[" +getClass().getSimpleName()+"@" + Thread.currentThread().getName()+ "] " + s);
    } 
}

步骤3:Client和Service创建链接,得到stub,ServiceTest4.java代码以下

public class ServiceTest4 extends Activity{

    //步骤3.1 定义接口变量 
    private ITestRemoteService remoteService = null;
    private boolean isStarted = false;
    //步骤3.1 定义链接变量,实现ServiceConnection接口
    private CounterServiceConnection conn = null;
      
    protected void onCreate(Bundle savedInstanceState) {
        //5个button分别触发startService( ),stopService( ) ,
        //bindService( ), releaseService( )和invokeService( ),
        //下面两行,一行是显示从Service中得到的计数值,一行显示状态。    
    } 

    private void startService(){ 
        Intent i = new Intent();
        //个人这个包里面还有层次,如*.part一、*.part2,etc
        i.setClassName("com.wei.android.learning", "com.wei.android.learning.part5.TestRemoteService"); 
//和以前的local service同样,经过intent开启Service,触发onCreate()[if Service没有开启]->onStart()
        startService(i); 
        isStarted = true;  
        updateServiceStatus();  
    } 
    private void stopService(){ 
        Intent i = new Intent(); 
        i.setClassName("com.wei.android.learning","com.wei.android.learning.part5.TestRemoteService");
        stopService(i); //触发Service的 onDestroy()[if Service存在]
        isStarted = false;
        updateServiceStatus(); 
    }    
   //步骤3.3:bindService( )经过一个实现ServiceConnection接口的类于Service之间创建链接,
   //注意到里面的参数Context.BIND_AUTO_CREATE,触发onCreate()[if Service不存在] –> onBind().
    private void bindService(){
        if(conn == null){ 
            conn = new CounterServiceConnection();
            Intent i = new Intent();
            i.setClassName("com.wei.android.learning","com.wei.android.learning.part5.TestRemoteService");
           bindService(i, conn,Context.BIND_AUTO_CREATE);
            updateServiceStatus();
        } 
    } 

    private void releaseService(){ 
        if(conn !=null){ 
            unbindService(conn); //断开链接,解除绑定
            conn = null; 
            updateServiceStatus(); 
        } 
    } 
    private void invokeService(){  
        if(conn != null){ 
            try{ 
            //一旦client成功绑定到Service,就能够直接使用stub中的方法。
                Integer counter =remoteService.getCounter(); 
                TextView t = (TextView)findViewById(R.id.st4_notApplicable);
                t.setText("Counter value : " + Integer.toString(counter));
            }catch(RemoteException e){ 
                Log.e(getClass().getSimpleName(),e.toString()); 
            } 
        } 
    } 
    //步骤3.2 class CounterServiceConnection实现ServiceConnection接口,
    //须要具体实现里面两个触发onServiceConnected()和onServiceDisconnected() 
    private class CounterServiceConnection implements ServiceConnection{
        @Override 
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 从链接中得到stub对象,根据咱们的跟踪,remoteService就是service中的stub对象
            remoteService = ITestRemoteService.Stub.asInterface(service);
            showInfo("onServiceConnected()" + remoteService);
        } 

        @Override
        public void onServiceDisconnected(ComponentName name) { 
            remoteService = null;
            updateServiceStatus(); 
            showInfo("onServiceDisconnected");
        } 
    } 
    
    private void updateServiceStatus() {
        TextView t = (TextView)findViewById( R.id.st4_serviceStatus); 
        t.setText( "Service status: "+(conn == null ? "unbound" : "bound")+ ","+ (isStarted ? "started" : "not started"; ));     
      } 
      
    private void showInfo(String s){
        System.out.println("[" +getClass().getSimpleName()+"@" + Thread.currentThread().getName()+ "] " + s);
    }
}

注意:

Service.onBind若是返回null,则调用 bindService 会启动 Service,但不会链接上 Service,所以 ServiceConnection.onServiceConnected 不会被调用,但你任然须要使用 unbindService 函数断开它,这样 Service 才会中止。

其它:

一、在什么状况下使用 startService 或 bindService 或 同时使用startService 和 bindService

若是你只是想要启动一个后台服务长期进行某项任务那么使用 startService 即可以了。若是你想要与正在运行的 Service 取得联系,那么有两种方法,一种是使用 broadcast ,另外是使用 bindService ,前者的缺点是若是交流较为频繁,容易形成性能上的问题,而且 BroadcastReceiver 自己执行代码的时间是很短的(也许执行到一半,后面的代码便不会执行),然后者则没有这些问题,所以咱们确定选择使用 bindService(这个时候你便同时在使用 startService 和 bindService 了,这在 Activity 中更新 Service 的某些运行状态是至关有用的)。另外若是你的服务只是公开一个远程接口,供链接上的客服端(android 的 Service 是C/S架构)远程调用执行方法。这个时候你能够不让服务一开始就运行,而只用 bindService ,这样在第一次 bindService 的时候才会建立服务的实例运行它,这会节约不少系统资源,特别是若是你的服务是Remote Service,那么该效果会越明显(固然在 Service 建立的时候会花去必定时间,你应当注意到这点)。

二、在 AndroidManifest.xml 里 Service 元素的常见选项

android:name,服务类名

android:label服务的名字,若是此项不设置,那么默认显示的服务名则为类名

android:icon服务的图标

android:permission申明此服务的权限,这意味着只有提供了该权限的应用才能控制或链接此服务

android:process表示该服务是否运行在另一个进程,若是设置了此项,那么将会在包名后面加上这段字符串表示另外一进程的名字

android:enabled若是此项设置为 true,那么 Service 将会默认被系统启动,不设置默认此项为 false

android:exported表示该服务是否可以被其余应用程序所控制或链接,不设置默认此项为 false

三、Service 与 Thread 的区别

不少时候,你可能会问,为何要用 Service,而不用 Thread 呢,由于用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下。

1). Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。能够用 Thread 来执行一些异步的操做。

2). Service:Service 是android的一种机制,当它运行的时候若是是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。若是是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。所以请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!

既然这样,那么咱们为何要用 Service 呢?其实这跟 android 的系统机制有关,咱们先拿 Thread 来讲。Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 以后,若是你没有主动中止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。所以这里会出现一个问题:当 Activity 被 finish 以后,你再也不持有该 Thread 的引用。另外一方面,你没有办法在不一样的 Activity 中对同一 Thread 进行控制。

举个例子:若是你的 Thread 须要不停地隔一段时间就要链接服务器作某种同步的话,该 Thread 须要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制以前建立的 Thread。所以你便须要建立并启动一个 Service ,在 Service 里面建立、运行并控制该 Thread,这样便解决了该问题(由于任何 Activity 均可以控制同一 Service,而系统也只会建立一个对应 Service 的实例)。

所以你能够把 Service 想象成一种消息服务,而你能够在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也能够在 Service 里注册 BroadcastReceiver,在其余地方经过发送 broadcast 来控制它,固然这些都是 Thread 作不到的。

四、拥有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等运行在相同的进程中,那么将会增长该进程的重要性。

五、注意事项

Service的onCreate的方法只会被调用一次,就是你不管多少次的startService又 bindService,Service只被建立一次。若是先是bind了,那么start的时候就直接运行Service的onStart方法,若是先是start,那么bind的时候就直接运行onBind方法。若是你先bind上了,就stop不掉了,只能先UnbindService, 再StopService,因此是先start仍是先bind行为是有区别的。 

Android中的服务和windows中的服务是相似的东西,服务通常没有用户操做界面,它运行于系统中不容易被用户发觉,可使用它开发如监控之类的 程序。

服务不能本身运行,须要经过调用Context.startService()或Context.bindService()方法启动服务。

这两个方法均可以启动Service,可是它们的使用场合有所不一样。使用startService()方法启用服务,调用者与服务之间没有关连,即便调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一块儿,调用者一旦退出,服务也就终止,大有“不求同 时生,必须同时死”的特色。

若是打算采用Context.startService()方法启动服务,在服务未被建立时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。若是调用startService()方法前服务已经被建立,屡次调用startService()方法并不会致使屡次 建立服务,但会致使屡次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结 束服务,服务结束时会调用onDestroy()方法。

若是打算采用Context.bindService()方法启动服务,在服务未被建立时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一块儿,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。若是调用bindService()方法前服务已经被绑定,屡次调用bindService()方法并不会致使屡次建立服务及绑定(也就是说onCreate()和onBind()方法并不会被屡次调用)。

若是调用者但愿与正在绑定的服务解除绑定,能够调用unbindService()方法,调用该方法也会致使系统调用服务的 onUnbind()-->onDestroy()方法.   

相关文章
相关标签/搜索