android java层进程间通信实例

本文介绍了如何在Android中实现跨进程音乐播放服务,通过定义aidl接口、服务类及客户端代码来完成服务的远程调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、定义aidl接口。

为服务定义aidl接口,所有拥有服务的客户端都可使用该接口中的函数。

package com.service;

interface IMusicPlayerService {
	boolean start();
	void stop();
}

该接口elipse会自动生成IMusicPlayerService.java文件。该文件不需要修改。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: /home/zhangfang/workspace_eclipse/RemoteService/src/com/service/IMusicPlayerService.aidl
 */
package com.service;
public interface IMusicPlayerService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.service.IMusicPlayerService
{
private static final java.lang.String DESCRIPTOR = "com.service.IMusicPlayerService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.service.IMusicPlayerService interface,
 * generating a proxy if needed.
 */
public static com.service.IMusicPlayerService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.service.IMusicPlayerService))) {
return ((com.service.IMusicPlayerService)iin);
}
return new com.service.IMusicPlayerService.Stub.Proxy(obj);
}
public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_start:
{
data.enforceInterface(DESCRIPTOR);
boolean _result = this.start();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_stop:
{
data.enforceInterface(DESCRIPTOR);
this.stop();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.service.IMusicPlayerService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public boolean start() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_start, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public void stop() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_stop, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_start = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_stop = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public boolean start() throws android.os.RemoteException;
public void stop() throws android.os.RemoteException;
}

注意该生成的接口文件:

IMusicPlayerService继承了android.os.IInterface,并实现了抽象的Stub类,该Stub继承android.os.Binder。该Stub是一个庄,它继承Binder,那么它的对象就可以被远程的进程使用了。本例中,在MusicPlayerServer中的类MyMusicPlayer继承了IMusicPlayerService.Stub,则该Stub中的函数可以在其他进程中使用。本例在另外Activity中调用。

public class MyMusicPlayer extends IMusicPlayerService.Stub


2、定义一个服务,实现IMusicPlayerService中定义的函数。该MusicPlayerServer相当与服务端,可以和client在同一个进程中,也可在不同进程中。

package com.service;

import com.remoteservice.R;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class MusicPlayerServer extends Service {
	private static final String Tag = "com.remote.service.MusicPlayerServer";
	MediaPlayer player=null;
	public class MyMusicPlayer extends IMusicPlayerService.Stub
	{
		public void stop() throws RemoteException {
			// TODO Auto-generated method stub
			Log.v(Tag,"stop is called.");
			player.stop();
		}

		public boolean start() throws RemoteException {
			// TODO Auto-generated method stub
			Log.v(Tag,"start is called.");
			player=MediaPlayer.create(MusicPlayerServer.this,R.raw.dream);
			player.setLooping(true);
			player.start();
			return true;
		}
	}
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		Log.v(Tag,"in oncreate");
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		Log.v(Tag,"in onDestroy");
		super.onDestroy();
	}

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		Log.v(Tag,"in onBind");
		return new MyMusicPlayer();
	}

}
该MusicPlayerServer相当与服务端,可以和client在同一个进程中,也可在不同进程中。如果希望客户端和服务端在不同进程中,则在AndroidManifest.xml中指定服务在不同的进程。

<service android:name="com.service.MusicPlayerServer"
		    android:process=":zhang"></service>

3、Client端代码

package com.remoteservice;

import com.service.IMusicPlayerService;
import com.service.MusicPlayerServer;
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.Menu;
import android.view.MenuItem;

public class RemoteServiceActivity extends Activity {
    /** Called when the activity is first created. */
	private static final String Tag="com.android.remote.service.RemoteServiceActivity";
	IMusicPlayerService iPlayer=null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        initService();
    }
    /**
     * 开启服务
     * 绑定服务
     */
    private void initService()
    {
    	Intent intent=new Intent();
    	intent.setClass(RemoteServiceActivity.this, MusicPlayerServer.class);
    	bindService(intent,conn,Context.BIND_AUTO_CREATE);
    }
    
    private ServiceConnection conn=new ServiceConnection(){

		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub			
			iPlayer=IMusicPlayerService.Stub.asInterface(service);
			Log.v(Tag,"in onServiceConnected");
		}

		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			Log.v(Tag,"in onServiceDisConnected");
		}
    	
    };
    /**
     * 设置菜单按钮
     */
    public boolean onCreateOptionsMenu(Menu menu)
    {
    	menu.add(0, 0, 0, "start");
    	menu.add(0, 1, 1, "stop");
    	return true;
    }
   
	public boolean onOptionsItemSelected(MenuItem item)
    {
    	int item_id=item.getItemId();
    	switch(item_id){
    	case 0:{  	
    		try {
				iPlayer.start();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		    	break;
    		}
    	case 1:{
    		try {
				iPlayer.stop();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    		break;
    	}		
    	}
    	return true;
    }
	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		
		RemoteServiceActivity.this.unbindService(conn);
	}
	
}

使用bindservice函数。onServiceConnected函数第二个参数是MusicPlayerServer服务中onBinder返回的值。

该Activity用下面函数获得service中的Stub对象,这样就可以在activity中使用Stub对象中定义的方法了,即使该Stub对象在另一个进程中。底层的进程间通信android已经帮我们做好了。

iPlayer=IMusicPlayerService.Stub.asInterface(service);

4、AndroidManifest.xml文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.remoteservice"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".RemoteServiceActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
		<service android:name="com.service.MusicPlayerServer"
		    android:process=":zhang"></service>
    </application>
</manifest>


5、下载运行,可以看到Client和Server在不同的进程中。

 3170 10037      0:00 {m.remoteservice} com.remoteservice
 3178 10037      0:00 {teservice:zhang} com.remoteservice:zhang


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值