对于Service的定义及使用场合等请详见官方定义:http://developer.android.com/guide/components/services.html
Service有两种类型:
1. 本地服务(Local Service):用于应用程序内部2. 远程服务(Remote Service):用于android系统内部的应用程序之间
本文讲解远程Service服务的使用。
远程Service通常用于Android内部应用程序之间通信,既然是两个应用程序,所以可以将其理解为一个是服务器提供Service服务,一个是客户端使用Service服务。通常远程Service使用AIDL(Android Interface Define Language)接口定义语言进行进程间通信。
下面编写服务器Service应用的实例代码(三步即可完成):
1)创建一个应用之后,新建一个接口文件,后缀*.adil结尾。如图:
文件中的使用Java语言编写一个接口:
package com.example.aidl;
interface CountInterface {
int getCount();
//可以继续定义更多方法提供给客户端使用
}
该文件定义好之后,系统会自动生成其对应的*.java 文件。如图:
package com.example.a_bindservice_a;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import com.example.aidl.CountInterface;
import com.example.aidl.CountInterface.Stub;
public class MyBindService extends Service {
Thread t;
int i = 0;
/**
* 创建一个CountInterface.Stub类型的binder,binder将返回给客户端作为客户端的代理,从而可以调用当前服务的方<span style="white-space:pre"> </span> *法。
* Stub是CountInterface接口的一个静态内部类
* */
CountInterface.Stub binder = new Stub() {
@Override
public int getCount() throws RemoteException {
return i;//在这里实现CountInterface计数的方法
}
};
@Override
public IBinder onBind(Intent intent) {
// 如果使用远程Service 必须返回一个binder对象。
return binder;
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("bind Oncreate");
// 通过启动线程在Service中实现一个计数的功能。
t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread run");
while (true) {
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
System.out.println("onDestroy");
t.interrupt();// 当远程调用unbindService()方法时,当前Service一起被销毁,同时终止子线程。
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("onUnbind");
return super.onUnbind(intent);
}
}
需要注意的是:远程Service的onBind()方法中必须返回一个binder对象。binder对象使用CountInterface的内部类Stub 创建。
3)在AndroidManifest.xml文件中注册当前Service并添加Action(不然其他应用找不到这个Service)
注册代码如下:
<service android:name="MyBindService">
<intent-filter >
<action android:name="com.example.a_bindservice_a.MyBindService"/>
</intent-filter>
</service>
下面创建客户端使用Service服务的实例代码(两步即可完成):
1)首先将服务器Service创建的接口文件连同报名一同拷贝到客户端应用中。如图:
2)编写客户端使用远程Service的实例代码:
package com.example.a_bindservice_b;
import com.example.aidl.CountInterface;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
* 远程服务在客户端:首先将服务器端的AIDL包及文件拷贝到当前项目中。
* 在客户端创建AIDL接口类型的引用对象cInterface,用来作为服务器再本地的代理。
* 在本地创建ServiceConnection类型的对象sConnection,
* 并且重写onServiceConnected和onServiceDisconnected两个方法。
* onServiceConnected方法会在bindService时被回调。
* 在onServiceConnected方法里面对AIDL接口对象赋值,cInterface =
* CountInterface.Stub.asInterface(binder);。 在unbindService时清空cInterface对象的引用。
* bindService(intent, sConnection, BIND_AUTO_CREATE);
* unbindService(sConnection); Intent对象通过new Intent("Action")方法创建。
* sConnection对象就是ServiceConnection的对象。
*
* */
public class MainActivity extends Activity implements OnClickListener {
Intent intent; //通过Intent找到服务器端的Service
CountInterface cInterface; // 创建一个接口对象,实现本地代理?
private Button bind;//绑定Service的按钮
private Button unbind;//解绑的按钮
private Button getNum;//调用远程Service中接口方法的按钮
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent("com.example.a_bindservice_a.MyBindService");
bind = (Button) findViewById(R.id.btnbind);
unbind = (Button) findViewById(R.id.btnUnbind);
getNum = (Button) findViewById(R.id.btngetCount);
getNum.setOnClickListener(this);
bind.setOnClickListener(this);
unbind.setOnClickListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (cInterface != null) {
unbindService(sConnection);
cInterface = null;
}
};
ServiceConnection sConnection = new ServiceConnection() {
/**
* onServiceDisconnected() 在连接正常关闭的情况下是不会被调用的, 该方法只在Service
* 被破坏了或者被杀死的时候调用. 例如, 系统资源不足, 要关闭一些Services, 刚好连接绑定的 Service 是<span style="white-space:pre"> </span> *被关闭者之一,
* 这个时候onServiceDisconnected() 就会被调用。
* */
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("onServiceDisconnected");
cInterface = null;
}
/**
* 在调用bindService方法时会回调此方法。
* 远程Service在onBind()方法必须返回一个binder对象,否则当前方法不会被调用。
* */
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
System.out.println("onServiceConnected");
// 通过asInterface()方法获得接口CountInterface对象的引用实例。binder就是服务器Service返回的<span style="white-space:pre"> </span>//binder对象。
cInterface = CountInterface.Stub.asInterface(binder);
}
};
// 为按钮添加监听
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnbind:
bindService(intent, sConnection, BIND_AUTO_CREATE);
break;
case R.id.btnUnbind:
if (cInterface != null) {
unbindService(sConnection);
cInterface = null;
}
break;
case R.id.btngetCount:
try {
if (cInterface != null) {
int i =cInterface.getCount();// 通过cInterface对象调用应用A的getCount()方法
System.out.println("--------------->" + i);
}
} catch (RemoteException e) {
System.out.println("RemoteException");
e.printStackTrace();
}
break;
default:
break;
}
}
}
需要注意的是:1.客户端使用服务器Service的接口方法时通过CountInterface接口的变量cInterface来实现的。
2.客户端在bindService时需要使用ServiceConnection类型的变量,创建sConnection变量时使用匿名 内部类,并实现其中的两个方法。
到此运行程序。然后就可以在客户端程序B中使用服务器A中定义的接口方法了。
真正纯自己写的第一个Blog,参考了许多其他大神的博客。如有错误,欢迎探讨~~好开森~

本文介绍如何使用AIDL实现Android应用程序间的远程Service通信。包括创建远程Service的步骤和客户端如何绑定及调用Service的方法。
1053

被折叠的 条评论
为什么被折叠?



