6 四大组件之Service
6-1 Servie概述
组件篇——Service
定义:
1.后台运行,不可见,没有界面
2.优先级高于Activity
Service是Android系统的后台服务组件,适用于开发无界面、长时间运行的应用功能。
Service特点如下:
没有用户界面
不会轻易被Android系统终止
在系统资源恢复后Service也将自动恢复
运行状态
可用于进程间通信
用途:
播放音乐,记录地理信息位置的改变,监听某种动作
注意:
-运行在主线程,不能用它来做耗时的请求或者动作
-可以在服务中开一个线程,在线程中做耗时操作
类型:
本地服务(Local Service):
应用程序内部
start方式:startService stopService stopSelf stopSelfResult
启动方式使用Service
通过调用Context.startService()启动Service,通过调用Context.stopService()或Service.stopSefl()停止Service
Bind方式:bindService unbindService
绑定方式使用Service
使用Service的组件通过Context.bindService()建立服务链接,通过Context.unbindService()停止服务链接
如果在绑定过程中Service没有启动,Context.bindService()会自动启动Service
远程服务(Remote Service):
Android系统内部的应用程序间之间
定义IBinder接口
生命周期:

通过startService()方法启动的服务于调用者没有关系,即使调用者关闭了,服务仍然运行想停止服务要调用Context.stopService(),此时系统会调用onDestory(),使用此方法启动时,服务首次启动系统先调用服务的onCreate()-->onStart(),如果服务已经启动再次调用只会触发onStart()方法
onCreate():Service的生命周期开始,完成Service的初始化工作;
onStart():活动生命周期开始;
onDestroy():Service的生命周期结束,释放Service所有占用的资源;
使用bindService()启动的服务与调用者绑定,只要调用者关闭服务就终止,使用此方法启动时,服务首次启动系统先调用服务的onCreate()-->onBind(),如果服务已经启动再次调用不会再触发这2个方法,调用者退出时系统会调用服务的onUnbind()-->onDestory(),想主动解除绑定可使用Contex.unbindService(),系统依次调用onUnbind()-->onDestory();
bindService()绑定Servcie, onCreate()和onBindle()将先后被调用。
unbindService()取消绑定Servcie,onUnbind()将被调用,如果onUnbind()返回true,则表示在调用者绑定新服务时,onRebind()函数将被调用
非绑定式的service的生命周期
startService()--->onCreate()--->onStartCommand()--->ServingRunning--->onStop()--->onDestory()服务停止
绑定式的service的生命周期
bindService()--->onCreate()--->onBind()--->用户与服务绑定 在解绑服务 onUnbind()--->onDestory()服务停止
start方式特点:
-服务跟启动源没有任何联系
-无法得到服务对象
Bind方式特点:
-通过Ibinder接口实例,返回一个ServerConnnection对象给启动源
-通过ServiceConnection对象的相关方法可以得到Service对象
6-2 Start启动
start方式的启动时:
第一次创建Service需要调用onCreate(),而后调用onStartCommand(),不管调用了多少次的onStartCOmmand(),停止的时候只调用一次onDestroy();
StartService
1. 使用方法:
(1)写一个MyStartService继承自Service,重写它的各种方法onCreate()、onStartCommand()、onDestory()
(2)在AndroidManifest.xml中注册这个Service
(3)在主线程Activity中通过startSerice(intent)方式启动
(4)通过stopService(intent)方式停止
2. 关于StartService
(1)启动方式是通过启动intent方式实现
(2)启动之后该Service和启动源没有关系,即使主线程退出了,service还会继续运行
由于Service和Activity类似,属于Android四大组件之一,所以我们需要在AndroidManifest.xml中进行注册。我们的组件都需要在AndroidManifest.xml中进行注册。
3.启动Service
显式启动
Intent中指明Service所在的类,并调用startService(Intent)函数启动Service
final Intent serviceIntent = new Intent(this,RandomService.class); startService(serviceIntent);
隐式启动
需要隐式开启Service,则可以在注册Service时,声明Intent-filter的action属性
<service android:name=".RandomService" > <intent-filter> <action android:name="StartRandomService" /> </intent-filter> </service>
final Intent serviceIntent = new Intent(); serviceIntent.setAction("edu.hrbeu.RandomService");
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start:" /> <Button android:id="@+id/start" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doClick" android:text="StartService" /> <Button android:id="@+id/stop" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doClick" android:text="StopService" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Bind:" /> <Button android:id="@+id/bind" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doClick" android:text="BindService" /> <Button android:id="@+id/play" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doClick" android:text="播放" /> <Button android:id="@+id/pause" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doClick" android:text="暂停" /> <Button android:id="@+id/next" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doClick" android:text="下一首" /> <Button android:id="@+id/pervious" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doClick" android:text="上一首" /> <Button android:id="@+id/unbind" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doClick" android:text="UnBindService" /> </LinearLayout>
MainActivity.java
package com.example.test; import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { Intent intent1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void doClick(View v) { switch (v.getId()) { case R.id.start: intent1 = new Intent(MainActivity.this, MyStartService.class); startService(intent1); break; case R.id.stop: stopService(intent1); break; } } }
MyStartService.java
package com.example.test; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MyStartService extends Service { @Override public void onCreate() { // TODO Auto-generated method stub Log.i("info", "Service--onCreate()"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Log.i("info", "Service--onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { // TODO Auto-generated method stub Log.i("info", "Service--onDestroy()"); super.onDestroy(); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.i("info", "Service--onBind()"); return null; } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.test" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="com.example.servicedemo.MyStartService"></service> </application> </manifest>

6-3 Bind启动
1.通过绑定服务获取回传数据:
通过Ibinder接口实例(继承的类里面返回一个Ibinder对象的抽象方法),返回一个serviceConnection对象给启动源,因为Ibinder里面含有我们要的数据,这里可以定义个内部类继承Binder里面做想返回的参数
2.使用onBind()方法的IBinder返回值给启动源返回信息 但是IBinder不能直接使用 需要通过Ibinder接口实例 返回一个ServiceConnection对象给启动源,通过ServiceConnection对象的相关方法可以得到Service,MyBinder是继承自Binder类的,而Binder类实际上实现了IBinder接口。
public class MyBinder extends Binder{ public MyBindServic getService(){ return MyBindService.this;//返回这个Service的实例 } } public IBunder onBind(Intent intent){ return new MyBinder(); }
3.在启动源定义ServiceConnection 该对象在绑定服务时传输到服务端(bindService(intent,conn,Service.BIND_AUTO_CREATE)) 绑定后 通过onServiceConnected() 方法获取service对象
4.unbindservice执行后,不能重复调用,会报错,并且在destroy的时候必须解绑, stopserveice则不会,
5.服务的两种启动方式:
1).通过startService(Intent intent)启动,stopService(Intent intent)停止,比较简单。服务启动后与启动源无关,也无返回服务本身。需注意要在配置文件中注册服务。
2).通过bindService(Intent intent,ServiceConnection conn,int flags)绑定服务启动,unbindService(ServiceConnection conn)去绑定停止,该方式可以返回服务本身,与启动源相关。
6.通过bindService绑定服务启动的具体步骤:
1)Intent intent = new Intent(上下文, 目标服务名.class);
bindService(intent, conn, Service.BIND_AUTO_CREATE);//绑定
2)在自定义的服务类中通过自定义一个内部类:
public class MyBinder extends Binder {
public MyBindService getService() {
return MyBindService.this;// 获取服务
}
}来返回服务本身
同时在自定义服务类重新父类Service的方法:
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return new MyBinder();
}
该方法可返回服务本身.
3)在启动源的Activity中创建一个ServiceConnection实例,初始化ServiceConnection接口,在接口方法中重写方法
ServiceConnection conn = new ServiceConnection() {
//当启动源跟service的连接意外丢失的时候会调用
//比如service崩溃了,或被强行杀死了
public void onServiceDisconnected(ComponentName name) {
}
//当启动源跟service成功连接之后会调用这个方法
public void onServiceConnected(ComponentName name, IBinder service) {
myBindService = ((MyBinder)service).getService();//大类转化为自身的小类,获取内部类中的方法,从而获得服务本身
}};
4)bindService()中指定ServiceConnection conn参数
bindService(intent2, conn, Service.BIND_AUTO_CREATE);
5)在自定义的继承于Servic类的类中,添加需要的方法,在启动Service的Activity中可以直接调用服务中的方法。
通过bindService()启动的服务是和启动源(Activity)绑定在一起的,如果Activity退出的时候没有调用unbindService()进行解绑定(停止),那么程序会报错。所以我们需要在Activity的onDestroy()方法中调用unbindService()进行解绑定。而且对于已经解绑定的服务再次进行解绑定,那么也会报错,这点和通过startService启动的服务不同,stopService()方法可以调用多次。
7.StartService和BindService
1). StartService启动后启动源和Service没有关系,BindService调用bindService()启动service后启动源和Service相关,在退出activity之前必须要调用unbindService()取消绑定。
2). startService()和bindService()可以混合使用。如果我们想要Activity退出了,但是服务还在继续,那么我们就要选用startService的方式来启动服务,如果我们想要在Activity中获取Service对象,那么我们需要用bindService方法结合ServiceConnection来启动Service,但是这种方法,由于将Service和Activity绑定在了一起,所以当Activity退出的时候,我们需要unbindService()来停掉Service,否则就会报错。
8.BindService
通过bindService()得到的Service是和启动源(Activity)绑定在一起的,在Activity退出的时候需要调用unbindService()进行解绑定(停止)。
调用bindService()时会调用到目标Service的onBind()函数,通过IBinder接口实例,返回一个ServiceConnection对象给启动源。然后启动源可以通过ServiceConnection对象得到启动的Service对象
MyBindService.java
package com.example.test; import android.app.Service; import android.content.Intent; import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class MyBindService extends Service{ @Override public void onCreate() { // TODO Auto-generated method stub Log.i("info", "BindService--onCreate()"); super.onCreate(); } public class MyBinder extends Binder{ public MyBindService getService(){ return MyBindService.this; } } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.i("info", "BindService--onBind()"); return new MyBinder(); } @Override public void unbindService(ServiceConnection conn) { // TODO Auto-generated method stub Log.i("info", "BindService--unbindService()"); super.unbindService(conn); } @Override public void onDestroy() { // TODO Auto-generated method stub Log.i("info", "BindService--onDestroy()"); super.onDestroy(); } public void Play(){ Log.i("info", "播放"); } public void Pause(){ Log.i("info", "暂停"); } public void Pervious(){ Log.i("info", "上一首"); } public void next(){ Log.i("info", "下一首"); } }
MainActivity.java
package com.example.test; import com.example.test.MyBindService.MyBinder; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { Intent intent1; Intent intent2; MyBindService service; ServiceConnection conn = new ServiceConnection() { @Override//当服务跟启动源断开的时候 会自动回调 public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } @Override//当服务跟启动源连接的时候 会自动回调 public void onServiceConnected(ComponentName name, IBinder binder) { // TODO Auto-generated method stub service = ((MyBinder)binder).getService(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void doClick(View v){ switch (v.getId()) { case R.id.start: intent1 = new Intent(MainActivity.this, MyStartService.class); startService(intent1); break; case R.id.stop: stopService(intent1); break; case R.id.play: service.Play(); break; case R.id.pause: service.Pause(); break; case R.id.pervious: service.Pervious(); break; case R.id.next: service.next(); break; case R.id.bind:
//绑定Service:
//bindService()方法绑定服务
//Intent对象传递给bindService(),声明需要启动的Service
//Context.BIND_AUTO_CREATE表明只要绑定存在,就自动建立Service;同时也告知Android系统,这个Service的重要程度与调用者相同
intent2 = new Intent(MainActivity.this, MyBindService.class); startService(intent2); bindService(intent2, conn, Service.BIND_AUTO_CREATE);//绑定了 break; case R.id.unbind: unbindService(conn); break; } } @Override protected void onDestroy() { // TODO Auto-generated method stub stopService(intent2);
//解绑Service:
//取消绑定使用unbindService()方法,并将ServiceConnnection对象传递给unbindService()方法。
//unbindService()方法调用成功后,系统并不会再次调用onServiceDisconnected()方法
//onServiceDisconnected()方法仅在意外断开绑定时才被调用。
unbindService(conn);//解绑定 super.onDestroy(); } @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; } }


浙公网安备 33010602011771号