基于Android应用开发的跨进程通信实现(IPC)

  本文是基于上一文 Android Binder机制----创建自定义的系统服务 讲解的Binder机制,实现开发第三方应用跨进程通信。
  所谓跨进程调用,在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文件定义的接口限定的数据类型要求的)
   本文相关的Demo代码下载地址如下:http://download.csdn.net/detail/stevenhu_223/5197679

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值