Android IPC机制(三)使用AIDL实现跨进程方法调用

news/2024/7/4 10:57:42

  上一篇文章中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messenger是以串行的方式来处理客户端发来的信息,如果有大量的消息发到服务端,服务端仍然一个一个的处理再响应客户端显然是不合适的。另外,Messenger用来进程间进行数据传递但是却不能满足跨进程的方法调用,接下来我们来使用AIDL来实现跨进程方法调用

1. 创建AIDL文件 
我们将项目的目录结构调为Android模式,在java同级目录创建aidl文件夹,在文件夹中创建一个包名和应用包名一致的包 
这里写图片描述

我们先创建一个IGameManager.aidl的文件,这里面有两个方法分别是addGame和getGameList。(IGameManager.aidl)

package com.example.liuwangshu.moonaidl;
import com.example.liuwangshu.moonaidl.Game;
interface IGameManager {
  List<Game>getGameList();
  void addGame(in Game game);
}

在AIDL文件中支持的数据类型包括:

  1. 基本数据类型
  2. String和CharSequence
  3. List:只支持ArrayList,里面的元素都必须被AIDL支持
  4. Map:只支持HashMap,里面的元素必须被AIDL 支持
  5. 实现Parcelable接口的对象
  6. 所有AIDL接口

在IGameManager.aidl中我们用到了Game这个类,这个类实现了Parcelable,在AIDL 文件中我们要import 进来,来看看Game类。(Game.java)

package com.example.liuwangshu.moonaidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Game implements Parcelable {
    public String gameName;
    public String gameDescribe;
    public Game(String gameName,String gameDescribe){
        this.gameName=gameName;
        this.gameDescribe=gameDescribe;
    }

    protected Game(Parcel in) {
        gameName=in.readString();
        gameDescribe=in.readString();
    }

    public static final Creator<Game> CREATOR = new Creator<Game>() {
        @Override
        public Game createFromParcel(Parcel in) {
            return new Game(in);
        }

        @Override
        public Game[] newArray(int size) {
            return new Game[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(gameName);
        dest.writeString(gameDescribe);
    }
}

在这里不去讲怎么去实现Parcelable 接口,在上面的IGameManager.aidl文件中我们用到了Game这个类,所以我们也要创建Game.aidl,来申明Game实现了parcelable 接口。(Game.aidl)

package com.example.liuwangshu.moonaidl;
parcelable Game;

这个时候我们重新编译程序,工程就会自动生成IGameManager.aidl对应的接口文件,这个文件生成的位置和Eclipse的位置不同,我们将项目的目录结构调整为project模式,在app–>build–>generated–>soure–>aidl–>debug目录下我们找到自己的包名文件,在文件中有一个接口文件IGameManager。 
这里写图片描述

IGameManager接口文件的代码这里就不说了,有兴趣的可以下载本项目的源码去了解下。

2. 创建服务端 
服务端我们在onCreate方法中创建了两个游戏的信息并创建Binder对象实现了AIDL的接口文件中的方法,并在onBind方法中将Binder对象返回。(AIDLService.java)

package com.example.liuwangshu.moonaidl;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class AIDLService extends Service{
    private CopyOnWriteArrayList<Game> mGameList=new CopyOnWriteArrayList<Game>();
    private Binder mBinder= new IGameManager.Stub() {
        @Override
        public List<Game> getGameList() throws RemoteException {
            return mGameList;
        }

        @Override
        public void addGame(Game game) throws RemoteException {
            mGameList.add(game);
        }
    };

    @Override
    public void onCreate() {
       super.onCreate();
        mGameList.add(new Game("九阴真经ol", "最好玩的武侠网游"));
        mGameList.add(new Game("大航海时代ol","最好玩的航海网游"));

    }
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

当然我们不要忘了这个服务端应该运行在另一个进程,在AndroidManifest.xml文件中配置service:

<service android:name=".AIDLService" android:process=":remote"></service>

3. 客户端调用 
最后我们在客户端onCreate方法中调用bindService方法绑定远程服务端,绑定成功后将返回的Binder对象转换为AIDL接口,这样我们就可以通过这个接口来调用远程服务端的方法了。(AIDLActivity.java)

package com.example.liuwangshu.moonaidl;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.List;
public class AIDLActivity extends AppCompatActivity {
    private final static String TAG="AIDLActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aidl);
        Intent mIntent=new Intent(AIDLActivity.this,AIDLService.class);
        bindService(mIntent,mServiceConnection, Context.BIND_AUTO_CREATE);
    }

   private ServiceConnection mServiceConnection=new ServiceConnection() {
       @Override
       public void onServiceConnected(ComponentName name, IBinder service) {
           IGameManager iGameManager=IGameManager.Stub.asInterface(service);
           Game game=new Game("月影传说","最好玩的武侠单机游戏");
           try {
               iGameManager.addGame(game);
               List<Game> mList=iGameManager.getGameList();
               for(int i=0;i<mList.size();i++){
                   Game mGame=mList.get(i);
                   Log.i(TAG,mGame.gameName+"---"+mGame.gameDescribe);
               }
           } catch (RemoteException e) {
               e.printStackTrace();
           }
       }

       @Override
       public void onServiceDisconnected(ComponentName name) {

       }
   };
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);

    }
}

绑定成功后我们创建了一个新的Game然后调用远程服务端的addGame方法将新游戏添加进去,然后调用循环将远端服务中的所有的游戏在打印出来,我们运行程序

这里写图片描述

打印出了远程服务端的所有的游戏,这样我们就成功的在客户端通过AIDL来调用远程服务端的方法了。

  

https://github.com/henrymorgen/MoonAIDL2  

  

  


http://www.niftyadmin.cn/n/2642658.html

相关文章

骁龙 820A芯片机器学习方案介绍

高通公司推出了多项计划以进一步推动智能互联汽车领域的发展&#xff0c;包括使用高通Snapdragon 820A为下一代大众信息娱乐系统提供动力&#xff0c;宣布在德国进行Cellular V2X试验&#xff0c;揭示出一种新的高端带宽千兆LTE用于车辆&#xff0c;并演示Snapdragon 820A如何为…

cocosc++怎么打印_VS2010-win32下cocos2dx控制台打印的方法

在xcode中 直接使用printf 或者 cout<但是在VS2010 却死活不好用 真郁闷-----------------10-9更新----------------下面的代码在 自己建立的项目里都已经存在啦AllocConsole(); freopen("CONIN$", "r", stdin); freopen("CONOUT$", "…

复联4里用到的方法论

引子 为了不剧透&#xff0c;我忍了很久才写这篇文章。直到现在复联4的免费在线观看版在网上都可以搜到了。所以介于漫威系列电影里很多方面和互联网的共性&#xff0c;今天说说自己的看法。 漫威系列得到了很多工程师的喜爱&#xff0c;除了编剧选演员日久弥新的审美观这个必…

Maven the definitive guide.pdf

http://vdisk.weibo.com/s/yW8b4aInnvTwk

git tag本地删除以及远程删除

假设存在tag:12345 git tag -d 12345 #删除本地记录 git push origin :refs/tags/12345 #删除远程记录PS: 如果您觉得我的文章对您有帮助&#xff0c;请关注我的微信公众号&#xff0c;谢谢!

pytorch训练lstm_Pytorch-RNNBASE-LSTM python+c源码理解

实验室要做一个语义相似度判别的项目&#xff0c;分给了我这个本科菜鸡&#xff0c;目前准备使用LSTM做一个Baseline来评价其它的方法&#xff0c;但是卡在了pytorch的LSTM模块使用上&#xff0c;一是感觉这个模块的抽象程度太高&#xff0c;完全封装了所有内部结构的情况下使得…

骁龙820A USB音频分享方案

USB虚拟双声卡的基本思路就是依据USB驱动中的复合描述符&#xff0c;根据驱动的配置&#xff0c;在驱动中用声音子系统创建出了两个声卡。 USB 驱动中的复合描述符 如 USB 规范所述&#xff0c;每个 USB 设备都会提供一组分层描述符来定义其功能。在顶层&#xff0c;每个设备具…

gitbook 入门教程之前置知识

markdown 基本知识 markdown 是一种简化的 html 语法,相比于 txt 无格式文本更强大. 你可以用专门的软件去编辑 markdown 文件,就像需要使用软件编辑 txt 文件一样,当然也可以什么软件也不用,甚至直接在记事本或命令行书写,只不过这样的缺点就是无法实时预览输出效果,安全依赖…