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

android四大组件之service知识点最强总结

2016-11-01 19:45 344 查看

1.基本概念

Service只能在后台运行,适合那些不需要界面的操作,像是播放音乐或者监听动作等,因为它 的名字就已经提示了:它就是一个服务。

Service同样也是运行在主线程中,所以不能用它来做耗时的请求或者动作,否则就会阻塞住主线程。如果真的要这么做,可以跟Activity一样的做法:新开一个线程。

2.启动方式

Service根据启动方式分为两类:Started和Bound。其中,Started()是通过startService()来启动,主要用于程序内 部使用的Service,而Bound是通过bindService()来启动,允许多个应用程序共享同一个Service。

如果单单只是为了使用Service,两种方式都可以,但正如我们上面所看到 的,Bound启动的Service可以允许多个应用程序绑定到Service,所以,如果该Service是多个程序共享的,必须使用Bound来启动

2.1声明Service:

<application>
<service android:name=".MyService"/>
</application>


2.2共享Service:

如果没有定义Intent Filters,默认下是私有的,无法访问,当然,我们也可以显示的指定该访问权限:android:exported=false。

2.3startService:

服务一旦开启就跟开启者(activity)没有什么关系.activity挂了,

服务还会开心的在后台运行.

创建Service,定义类继承Service,AndroidManifest.xml中定义

开启Service,在其他组件中调用startService方法

停止Service,调用stopService方法

2.4bindService

服务跟activity就有了千丝万缕的联系. 如果调用者activity挂了

服务也跟着挂了. 不求同时生,但求同时死.

服务只能被显示的解除绑定一次,多次的解除绑定服务 应用程序会报异常

创建Service,定义类继承Service,AndroidManifest.xml中定义

开启Service,在其他组件中调用Context.bindService()来启动

绑定Service,onBind()

解绑Service,onUnbind()

停止Service,调用stopService()方法

2.5混合开启服务

需求: 服务长期的后台运行, 又想调用服务里面的方法.

startservice 开启服务 (保证服务长期后台运行)

unbindService 解除绑定服务

//解除绑定,不解除无法直接关闭服务

stopService 停止服务.

3.生命周期



服务常用生命周期回调方法:

Started

Service的生命周期不像Activity那样复杂,当我们通过Context.startService()启动Service的时候,系统就会调 用Service的onCreate(),接着就是onStartCommand(Intent, int, int),过去这个方法是onStart(),但现在onStart()已经不被鼓励使用了,onStartCommand()里面的代码就是我们 Service所要执行的操作,接着就是onDestroy(),关闭Service。

Bound

通过Context.bindService()来启动,系统同样会调用Service的onCreate(),接着并不是 onStartCommand()而是onBind(),它会将多个客户端绑定到同一个服务中。如果我们想要停止Service,必须先对客户端解绑,也 就是调用onUnbind(),然后就是onDestroy()。

混合模式

如果先采用startService()方法启动服务,然后调用bindService()方法绑定到服务,再调用unbindService()方法解除绑定,最后调用bindService()方法再次绑定到服务

注意:

服务一旦被创建,就不会重新创建了,服务的oncreate方法只会执行一次,如果服务已经开启,就不会再去执行oncreate方法,服务在停止的时候,会调用ondestroy方法,每一次开启服务的时候 都会调用 onStartCommand() onStart();

4.Started Service 详细用法

接下来我们就来创建一个简单的Service:MyService,用于在后台播放MP3。这是介绍Service时经常用到的例子。

public class MyService extends Service {
MediaPlayer mediaPlayer = null;

@Override
public IBinder onBind(Intent arg0) {
return null;
}

@Override
public void onCreate() {
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer.create(this, uri); // uri 为要播放的歌曲的路径
super.onCreate();
}
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mediaPlayer.start();
return START_STICKY;
}

@Override
public void onDestroy() {
mediaPlayer.stop();
super.onDestroy();
}
}


由于我们是通过Started启动Service,所以onBind()返回的是NULL。

其实,onStartCommand()中的代码是我们Service主要的操作,它会在每次Service运行的时候被调用,而onCreate()是 当Service第一次被创建的时候才会被调用,当Service已经在运行的时候,不会调用该方法,可以将一些初始化的操作放在这里。 定义好Service后,我们就可以在Activity中启动该Service:

Intent intent = new Intent(this, MyService.class);
startService(intent);


这就像是在Activity中跳转到另一个Activity一样。

看上去Service就好像是在Activity中新开一个Thread一样,事实上,这两者也是挺像的,那么,我们是如何确定我们需要的是Thread还是Service?

如果是当用户使用我们的应用程序,像是点击按钮的时候,才执行一个在主线程外面的操作,我们需要的就是一个Thread而不是Service。

还是我们上面的例子,如果我们想要播放音乐是在我们应用程序运行的时候,那么我们可以再onCreate()中新建一个Thread, 然后在onStartCommand()中开始该Thread,接着是在onStop()中停止该Thread。这样的做法非常自然,是一般的新手都会想 到的,但是android鼓励我们使用AsyncTask或者HandlerThread来处理这个过程。关于这个话题,我们还是放在其他文章里讲吧,毕 竟这是一个不小的话题。

当我们开启了一个Service,我们就有义务去决定什么时候关闭该Service。可以通过stopSelf()让Service自己关闭自己或者调用stopService()来关闭该Service。

当内存不够的时候,系统也会自动关闭Service。这时系统是如何选择哪些Service应该被关闭呢?如果一个Service被绑定到 Activity并且得到用户的焦点,那么它就很少可能会被关闭,但如果它是被声明运行在前台,它就永远也不可能会被关闭。

知道这个事实对我们有什么用呢?当然是考虑如果内存足够的时候我们如何重启Service,解决这个问题的关键就在于onStartCommand()的返回值。

onStartCommand()指定要求返回一个整数值,这个整数值描述的就是系统应该以何种方式来重启该Service,一共有下面三种方式:

1.START_NOT_STICKY:系统在关闭Service后,不需要重新创建该Service,除非我们传递Intent要求创建Service。这是避免不必要的Service运行的最安全的方式,因为我们可以自己指定什么时候重新启动该Service。

2.START_STICKY:要求重新创建Service并且系统会通过一个空的Intent来调用onStartCommand()除非我们传递Intent。我们看到,上面的例子就使用了该返回值,这样当音乐播放被停止后,重新启动的时候就会重新播放音乐。

3.START_REDELIVER_INTENT:这种方式会通过关闭前的Intent来调用onStartCommand()。它非常适合像是下载文件这类的操作,这样当重新启动的时候,就会继续之前的下载而不会丢失之前的下载进度。

关闭Service有两种方式:stopSelf()和stopService(),它们是有区别的,而且区别非常大。如果我们在一个应用程序中开启了多 个Service,那么我们就不能贸然的使用stopService()来关闭Service,因为前一个Service的关闭可能会影响到后面 Service的使用。这时我们就需要使用stopSelf(int startId)来决定关闭哪个Service。关闭Service是非常重要的,这对于减少内存消耗和电量消耗来说,都是一件好事。

要想使用Started Service,我们除了继承自Service之外,还可以继承自另一个类:IntentService。IntentService是Service的子类。我们一般都是一个Intent就开启一个Service,但是 IntentService是专门有一个线程来处理所有的开启请求,每次处理一个。这是我们需要在应用程序中开启多个Service但又想避免多线程的最佳选择。

public class MyService extends IntentService {
MediaPlayer mediaPlayer = null;

public MyService() {
super("MyService");
}

@Override
protected void onHandleIntent(Intent intent) {
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer.create(this, uri);
}// uri 为要播放的歌曲的路径        mediaPlayer.start();
}
}


和继承自Service不一样,我们需要一个构造器,该构造器的主要作用就是为工作线程命名,我们仅需要覆写onHandleIntent()一个方法,因为该方法会为我们处理所有的Intent,并且会在处理完毕后关闭该Service,IntentService就像是一个封装好的Service,方便我们处理多个Intent的情况,但如果我们想要覆写其他方法,也是可以的,但要确保每个方法最后都有调用super的实现。

5. Bound Service 详细用法

5.1本地服务

绑定本地服务调用服务里面方法的流程:

在activity 采用bindService方式开启服务…

写一个实现类 MyConn implements ServiceConnection

接口里面有一个方法onServiceConnected 在服务成功绑定的时候调用的方法

在service代码 实现 onBind方法 返回一个IBinder接口的实现( 里面必须一个调用服务方法的api)

在服务成功绑定的时候 服务里面返回的IBinder对象会传给 activity里面onServiceConnected 方法

获取IBinder对象 中间人, 调用中间人的方法. 间接调用了服务里面的方法

我们先从简单的本地服务开始:

public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();

/**
* Class used for the client Binder.  Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}

@Override
public IBinder onBind(Intent intent) {
return mBinder;
}

/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}


这个例子非常简单,就是为每个绑定到该服务的客户产生一个0-100的随机数。

我们首先必须提供一个IBinder的实现类,该类返回的是我们Service的一个实例,这是为了方便客户调用Service的公共方法,接着我们在onBind()方法中返回这个IBinder的实现类,这种做法适合Service只在应用程序内部共享,我们可以这样使用这个Service:

public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;

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

@Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}

/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}

@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}


我们通过bindService()将Activity和Service绑定到一起,接着必须定义一个 ServiceConnection,为的就是通过绑定的IBinder的getService()方法来获得Service,然后我们再调用 Service的getRandomNumber()。使用完后,我们需要通过unbindService()来解除绑定,这里充分利用了回调的价值,这种方式仅仅适合客户和服务都在同一个应用程序和一个进程内,像是音乐程序的后台播放。

混合调用:

结合我们上面有关Started Service的讨论,我们知道,可以用两种方式来开启服务,StartedService完全可以变成Bound Service,这样我们就不用显式的关闭服务,当没有任何客户和该Service绑定的时候,系统会自动的关闭该Service。但如果我们在一个 Started Service中也同样使用了onBind()呢?像是这样的情况:我们在一个音乐播放程序中利用Started Service开启音乐播放,然后用户离开程序后,音乐会在后台播放,当用户重新返回到程序中时,Activity可以绑定到Service上以便对音乐 进行控制。我们可以使用onRebind()方法来做到这点。



这就是既是Started Service又是Bound Service的整个生命周期。

5.2 远程服务

5.2.1 通过Messenger实现进程间通信

但我们有时候需要和远程的进程进行通信,这时就需要使用Messenger,这是为了实现进程间通信但又不想使用AIDL的唯一方式。

我们还是先来个简单例子:

public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;

/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}

/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());

/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}


可以看到,我们必须先在Service里面实现一个Handler,然后将这个Handler传递给Messenger,然后在onBind()中返回的是该Messenger的getBinder()的返回值。

public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;

/** Flag indicating whether we have called bind on the service. */
boolean mBound;

/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service.  We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}

public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};

public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}

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

@Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}


Activity所要做的就是创建一个Messenger,该Messenger拥有Service返回的IBinder,接着就是发送消息给 Service,然后Service中的Handler根据消息进行处理。我们可以看到,Messenger之所以能够实现进程间的通信,靠的还是 Handler。

5.2.2 通过AIDL实现进程间通信

在Android中, 每个应用程序都有自己的进程,当需要在不同的进程之间传递对象时,该如何实现呢? 显然, Java中是不支持跨进程内存共享的。因此要传递对象, 需要把对象解析成操作系统能够理解的数据格式, 以达到跨界对象访问的目的。在JavaEE中,采用RMI通过序列化传递对象。在Android中, 则采用AIDL(Android Interface Definition Language:接口定义语言)方式实现。

AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC)。AIDL的IPC机制和EJB (Enterprise Java Bean JAVA中的商业应用组件技术) 所采用的CORBA (Common Object Request Broker Architecture 是一组用来定义“分布式对象系统”的标准) 很类似,进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后再转换成相应的对象。由于进程之间的通信信息需要双向转换,所以android采用代理类在背后实现了信息的双向转换,代理类由android编译器生成,对开发人员来说是透明的。

假设A应用需要与B应用进行通信,调用B应用中的download(String path)方法,B应用以Service方式向A应用提供服务。需要下面四个步骤:

1>>在B应用中创建*.aidl文件,aidl文件的定义和接口的定义很相类,

如:在cn.itcast.aidl包下创建IDownloadService.aidl文件,内容如下:

package cn.itcast.aidl;
interface IDownloadService {
void download(String path);
}


当完成aidl文件创建后,eclipse会自动在项目的gen目录中同步生成IDownloadService.java接口文件。接口文件中生成一个Stub的抽象类,里面包括aidl定义的方法,还包括一些其它辅助方法。值得关注的是asInterface(IBinder iBinder),它返回接口类型的实例,对于远程服务调用,远程服务返回给客户端的对象为代理对象,客户端在onServiceConnected(ComponentName name, IBinder service)方法引用该对象时不能直接强转成接口类型的实例,而应该使用asInterface(IBinder iBinder)进行类型转换。

编写Aidl文件时,需要注意下面几点:
1.接口名和aidl文件名相同。
2.接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static。
3.Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),使用这些类型时不需要import声明。对于List和Map中的元素类型必须是Aidl支持的类型。如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口。
4.自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。
5.在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数。
6.Java原始类型默认的标记为in,不能为其它标记。


2>>在B应用中实现aidl文件生成的接口(本例是IDownloadService),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口方法的代码。内容如下:

public class ServiceBinder extends IDownloadService.Stub {
@Override
public void download(String path) throws RemoteException {
Log.i("DownloadService", path);
}
}


3>>在B应用中创建一个Service(服务),在服务的onBind(Intent intent)方法中返回实现了aidl接口的对象(本例是ServiceBinder)。内容如下:

public class DownloadService extends Service {
private ServiceBinder serviceBinder = new ServiceBinder();
@Override
public IBinder onBind(Intent intent) {
return serviceBinder;
}
public class ServiceBinder extends IDownloadService.Stub { @Override public void download(String path) throws RemoteException { Log.i("DownloadService", path); } }
}


其他应用可以通过隐式意图访问服务,意图的动作可以自定义,AndroidManifest.xml配置代码如下:

<service android:name=".DownloadService" >
<intent-filter>
<action android:name="cn.itcast.process.aidl.DownloadService" />
</intent-filter>
</service>


4>>把B应用中aidl文件所在package连同aidl文件一起拷贝到客户端A应用,eclipse会自动在A应用的gen目录中为aidl文件同步生成IDownloadService.java接口文件,接下来就可以在A应用中实现与B应用通信,代码如下:

public class ClientActivity extends Activity {
private IDownloadService downloadService;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.bindService(new Intent("cn.itcast.process.aidl.DownloadService"), this.serviceConnection, BIND_AUTO_CREATE);//绑定到服务
}

@Override
protected void onDestroy() {
super.onDestroy();
this.unbindService(serviceConnection);//解除服务
}

private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadService = IDownloadService.Stub.asInterface(service);
try {
downloadService.download("http://www.itcast.cn");
} catch (RemoteException e) {
Log.e("ClientActivity", e.toString());
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
downloadService = null;
}
};
}


5.2.3 通过Parcelable实现在AIDL间传递自定义类型参数

Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),如果要传递自定义的类型该如何实现呢?

Parcelable接口

要传递自定义类型,首先要让自定义类型支持parcelable协议,实现步骤如下:

1>自定义类型必须实现Parcelable接口,并且实现Parcelable接口的public void writeToParcel(Parcel dest, int flags)方法 。

2>自定义类型中必须含有一个名称为CREATOR的静态成员,该成员对象要求实现Parcelable.Creator接口及其方法。

3> 创建一个aidl文件声明你的自定义类型。

Parcelable接口的作用:实现了Parcelable接口的实例可以将自身的状态信息(状态信息通常指的是各成员变量的值)写入Parcel,也可以从Parcel中恢复其状态。 Parcel用来完成数据的序列化传递。

进程间传递自定义类型的实现过程:

1>>创建自定义类型,并实现Parcelable接口,使其支持parcelable协议。如:在cn.itcast.domain包下创建Person.java:

package cn.itcast.domain;
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable
private Integer id;
private String name;

public Person(){}
public Person(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {//把javanbean中的数据写到Parcel
dest.writeInt(this.id);
dest.writeString(this.name);
}
//添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>(){
@Override
public Person createFromParcel(Parcel source) {//从Parcel中读取数据,返回person对象
return new Person(source.readInt(), source.readString());     //*按write入的顺序读取
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
}


2>>在自定义类型所在包下创建一个aidl文件对自定义类型进行声明,文件的名称与自定义类型同名。

package cn.itcast.domain;
parcelable Person;


3>>在接口aidl文件中使用自定义类型,需要使用import显式导入,本例在cn.itcast.aidl包下创建IPersonService.aidl文件,内容如下:

package cn.itcast.aidl;
import cn.itcast.domain.Person;
interface IPersonService {
void save(in Person person);
}


4>>在实现aidl文件生成的接口(本例是IPersonService),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口方法的代码。内容如下:

public class ServiceBinder extends IPersonService.Stub {
@Override
public void save(Person person) throws RemoteException {
Log.i("PersonService", person.getId()+"="+ person.getName());
}
}


5>>创建一个Service(服务),在服务的onBind(Intent intent)方法中返回实现了aidl接口的对象(本例是ServiceBinder)。内容如下:

public class PersonService extends Service {
private ServiceBinder serviceBinder = new ServiceBinder();
@Override
public IBinder onBind(Intent intent) {
return serviceBinder;
}
public class ServiceBinder extends IPersonService.Stub { @Override public void save(Person person) throws RemoteException { Log.i("PersonService", person.getId()+"="+ person.getName()); } }
}


6> 把应用中的aidl文件和所在package一起拷贝到客户端应用的src目录下,eclipse会自动在客户端应用的gen目录中为aidl文件同步生成IPersonService.java接口文件,接下来再把自定义类型文件和类型声明aidl文件及所在package一起拷贝到客户端应用的src目录下。

最后就可以在客户端应用中实现与远程服务的通信,代码如下:

public class ClientActivity extends Activity {
private IPersonService personService;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.bindService(new Intent("cn.itcast.process.aidl.PersonService"), this.serviceConnection, BIND_AUTO_CREATE);//绑定到服务
}

@Override
protected void onDestroy() {
super.onDestroy();
this.unbindService(serviceConnection);//解除服务
}

private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
personService = IPersonService.Stub.asInterface(service);
try {
personService.save(new Person(56,"liming"));
} catch (RemoteException e) {
Log.e("ClientActivity", e.toString());
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
personService = null;
}
};
}


5.3 绑定远程服务和本地服务的区别

本地服务 直接定义IService.java的接口

远程服务 定义一个IService.adil文件 更改扩展名 删除public

本地服务 extend Binder implement IServcie

远程服务 extend IService.Stub

本地服务 绑定成功 直接强制类型转换 IServcie

远程服务 绑定成功 IService.Stub.asInterface(service)

小结

本篇对service进行了一个比较深层的总结,更是介绍了远程服务、本地服务、进程间通信的方面,也是平时面试经常会问到但是大部分人打不好的点,所以大家可以多看下理解理解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android