所谓跨进程调用,在Android应用开发中,就是不同了两个应用程序进程之间的通信实现。
我们姑且将这个两个通信的应用程序进程区分为客户端和服务端。
下面就以两个简单的应用程序来了解如何实现Android应用开发的跨进程通信。
这两个应用的实现很简单,就是实现在客户端点击“设置用户名”按钮往服务端输入用户名,然后又在客户端点击“获取用户名”按钮,获取服务端保存的用户名。
服务端:一个继承Service的类,以及一个aidl文件。(关于aidl文件还是用上一篇文章的IMyService.aidl)
IMyService.aidl的定义如下:
interface IMyService
{
String getName();
void setName(String name);
}
针对创建的IMyService.aidl,eclipse会自动在工程的gen目录中生成IMyService.java文件,这时候可以将这个java文件移到工程的src目录。然后删掉之前在src目录创建的IMyService.aidl就可以了。(注意,别忘了在IMyService.java文件代码中添加你自己创建的工程包名)
继承Service类的远程服务类代码package com.feixun.hu.ipc.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class IpcService extends Service
{
//用于保存客户端输入的用户名
private String userName;
private ServiceBinder mServiceBinder;
@Override
public void onCreate()
{
// TODO Auto-generated method stub
super.onCreate();
//创建ServiceBinder对象(Binder类型对象)
mServiceBinder = new ServiceBinder();
}
/*定义一个继承IMyService接口内部类Stub的实现与客户端通信的Binder类型的类,
* IMyService.Stub是Binder类型
*/
public class ServiceBinder extends IMyService.Stub
{
@Override
public String getName() throws RemoteException
{
// TODO Auto-generated method stub
return userName;
}
@Override
public void setName(String name) throws RemoteException
{
// TODO Auto-generated method stub
userName = name;
}
}
@Override
public IBinder onBind(Intent arg0)
{
// TODO Auto-generated method stub
/*与客户端连接时,返回该Binder对象.
* 1.如果连接的客户端和该服务端属于同一个进程,则此处直接返回mServiceBinder本身
* 2.如果连接的客户端和该服务不属于同一个进程,则返回的是mServiceBinder对象的代理
*/
return mServiceBinder;
}
}
AndroidManifest.xml文件代码如下: (注:文件中添加的action>”com.feixun.hu.action.IPC_SERVICE”对应的是在客户端中绑定该服务设置添加的action)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.feixun.hu.ipc.service"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<service android:name=".IpcService">
<intent-filter >
<action android:name="com.feixun.hu.action.IPC_SERVICE"/>
</intent-filter>
</service>
</application>
</manifest>
本文所谓的服务端,也就是创建一个应用程序工程,该应用程序包含一个Service。所以,该服务端应用程序运行时是不可见的。
客户端:一个继承Activity的类,和服务端一摸一样的IMyService.aidl文件(这个文件是实现两者之间进行通信必不可少的。可以直接把服务端自动生成的IMyService.java复制过去客服端)。
继承Activity的可视化类的代码如下:
package com.feixun.hu.ipc.client;
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.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class IpcClient extends Activity
{
private IMyService mIMyService;
private Button setName, getName;
private TextView show;
private EditText input;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//获取各组件
setName = (Button)findViewById(R.id.set);
getName = (Button)findViewById(R.id.get);
show = (TextView)findViewById(R.id.show);
input = (EditText)findViewById(R.id.input);
//创建Intent,对应服务端注册的Intent
Intent intent = new Intent();
intent.setAction("com.feixun.hu.action.IPC_SERVICE");
//绑定连接远程服务
bindService(intent, conn, Service.BIND_AUTO_CREATE);
//为设置按钮绑定监听
setName.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if(input.getText() != null)
{
try
{
//将输入的信息保存到远程服务端
mIMyService.setName(input.getText().toString());
}
catch (RemoteException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
//获取按钮绑定监听
getName.setOnClickListener(new OnClickListener()
{
//String name = mIMyService.getName();
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
try {
if(mIMyService.getName() != null)
{
show.setText(mIMyService.getName().toString());
}
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
//实现客户端与服务端绑定的关键部分
private ServiceConnection conn = new ServiceConnection()
{
//解除连接服务端
@Override
public void onServiceDisconnected(ComponentName name)
{
// TODO Auto-generated method stub
mIMyService = null;
}
//连接服务端
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
// TODO Auto-generated method stub
/*此处实现获取通过IpcService的onBind方法返回的mServiceBinder对象的代理。
* 参数service为绑定获得的远程服务IpcService的mServiceBinder对象,
* 而调用IMyService.Stub的函数asInterface获取的是mServiceBinder对象的代理。
*/
mIMyService = IMyService.Stub.asInterface(service);
}
};
@Override
protected void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
//解除绑定
unbindService(conn);
}
}
main.xml文件的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/set"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/setName"/>
<EditText
android:id="@+id/input"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/info"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/get"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/getName"/>
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
本文所谓的客户端,也是创建一个应用程序工程,该工程包含一个Activity,用户通过操作该Activity所提供的可视化组件界面,向远处服务端(也就是在另一个应用程序进程中运行的Service服务)保存数据、获取数据。
以上两个简单的应用程序例子,可以实现两个应用程序之间的最基本的跨进程通信了。当然,有需要时,我们还可以创建传输和处理更复杂的数据远程服务,而不单单是本文所创建的例子那么简单。比如,以一个类的形式(类似JavaBean)为数据,而此时,这个数据类是要求要实现Parcelable接口的。(根据AIDL文件定义的接口限定的数据类型要求的)
原文地址:http://blog.csdn.net/stevenhu_223/article/details/8738682