Android中的服务(service)详解(三)--远程服务(remote)
1. 引言:
(1)AIDL的作用
在Android平台,每个应用程序都是一个单独的JVM,都运行在自己的进程空间里, 通常,一个进程不允许访问另一个进程的内存空间(一个应用不能访问另一个应用)。当用户(程序开发人员)想在一个App中访问另一个App的进程空间的时候,就需要进程间通信。在Android中,远程服务为我们提供了实现进程间通信的方式,其中,AIDL是应用程序开发人员常的一种方式。
AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参 数。换句比较浅显的话来说,就是我这个App应用的activity,需要调用其他App应用的Service.当然同一App应用的activity 与service也可以在不同进程间,这可以设置Service配置中,android:process=":remote"。
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" >
</service>
2. 本篇主要实例:
应用服务之远程(remote)服务的开启和运用,也就是AIDL的创建和使用过程:
例子说明:
(1). 功能: 创建remote service,在service中计算出指定路径下有多少个文件,并在UI显示。
(2). 您将学到: a. remote service的定义和使用;
b. Aidl文件的定义和使用。
创建过程:
(1)在工程的src下,新建立一个文本文件,将要实现的函数放在这个文件中,后缀为.aidl。
(2)刷新工程后,就会发现在gen包下,有一个同名的java文件,这是aidl工具自动生成的,里面,就有我们要实现的函数。
(3)Aidl定义好后,我们就要实现我们的remote service了。它也是继承自service的。
(4)Service实现后,要将它在mainfest.xml设置为remote.注意,客户端服务端在同个App中,android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。
(5)最后,来实现我们的客户端,也就是Activity,来调用service。
3. 例子代码:
(1).aidl文件:IFileCountService.aidl:
package com.example.remoteservicetest;
interface IFileCountService{
int getFileCnt(String path);
}
(2). remote service的实现:MyRemoteService.java:
package com.example.remoteservicetest;
import java.io.File;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MyRemoteService extends Service {
static final String TAG="MyService";
private int fileCnt = 0;
//定义内部类MyRemoteServiceImpl,继承我们的AIDL文件自动生成的内部类,
//并且实现我们AIDL文件定义的接口方法
private class MyRemoteServiceImpl extends IFileCountService.Stub{
@Override
public int getFileCnt(String path) throws RemoteException {
Log.e(TAG, "path");
File file = new File(path);
if (file.exists()) {
if (file.isDirectory()) {
File files[] = file.listFiles();
if (files == null ) {
return 0;
}
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
fileCnt++;
}
}
}
}
return fileCnt;
}
}
@Override
public IBinder onBind(Intent arg0) {
//返回AIDL实现
return new MyRemoteServiceImpl();
}
@Override
public void onDestroy(){
Log.e(TAG, "Release MyService");
super.onDestroy();
}
}
(3). 客户端Activity:AndroidRemoteActivity.java:
package com.example.androidservicetest;
import com.example.remoteservicetest.IFileCountService;
import com.example.remoteservicetest.MyRemoteService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class AndroidRemoteActivity extends Activity {
static final String TAG="AndroidRemoteActivity";
int fileCnt = 0;
private TextView textView;
Button btn1;
Button btn2;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.textview);
btn1 = (Button)findViewById(R.id.button1);
btn2 = (Button)findViewById(R.id.button2);
btn2.setVisibility(View.GONE);
btn1.setText("Get File Count:");
if(btn1!=null)
btn1.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
//绑定一个服务
fileCnt = 0;
bindService();
}
});
}
IFileCountService iService=null;
private ServiceConnection conn=new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//返回AIDL接口对象,然后可以调用AIDL方法
iService=IFileCountService.Stub.asInterface(service);
try {
fileCnt=iService.getFileCnt("/sdcard");
}
catch (RemoteException e) {
Log.e(TAG,"error 000");
e.printStackTrace();
}
Log.e(TAG, "file count:"+fileCnt);
textView.setText("file count:"+fileCnt);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected");
}
};
private void bindService(){
Intent intent=new Intent(this,MyRemoteService.class);
startService(intent);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
}
(4). AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidservicetest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidservicetest.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>
<activity
android:name="com.example.androidservicetest.AndroidLocalServiceActivity" >
</activity>
<activity
android:name="com.example.androidservicetest.AndroidRemoteActivity" >
</activity>
<service android:name="com.example.androidservicetest.PackageFindService" >
<intent-filter>
<action android:name="com.test.service"/>
</intent-filter>
</service>
<service android:name="com.example.remoteservicetest.MyRemoteService"
android:process=":remote"
>
<intent-filter>
<action android:name="com.example.remoteservicetest.IFileCountService"/>
</intent-filter>
</service>
</application>
</manifest>
4. 测试结果:
运行程序后,会显示两个button,第一个是测试locel service的,第二个是测试remote service的,点第二个,再点,就会在屏幕上显示sdcard根目录的文件个数了。
5. 代码下载:
http://download.csdn.net/detail/liranke/8401933
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。