zoukankan      html  css  js  c++  java
  • Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用

    在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法。可是我们能发现Messenger是以串行的方式来处理client发来的信息,假设有大量的消息发到服务端,服务端仍然一个一个的处理再响应client显然是不合适的。另外,Messenger用来进程间进行数据传递可是却不能满足跨进程的方法调用。接下来我们来使用AIDL来实现跨进程方法调用,此前我们都是用Eclipse来实现的,这次我们看看在Android Studio中使用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文件里支持的数据类型包含:

    • 基本数据类型
    • String和CharSequence
    • List:仅仅支持ArrayList,里面的元素都必须被AIDL支持
    • Map:仅仅支持HashMap,里面的元素必须被AIDL 支持
    • 实现Parcelable接口的对象
    • 全部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. client调用
    最后我们在clientonCreate方法中调用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方法将新游戏加入进去,然后调用循环将远端服务中的全部的游戏在打印出来。我们执行程序

    这里写图片描写叙述

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

    github源代码下载

  • 相关阅读:
    【总结】st表
    【luogu】p2024 食物链
    【总结】stl(以后还会慢慢补上
    【总结】二叉堆
    【luogu】p1631 序列合并
    才子们博客地址
    Lemon测评软件使用说明 (对比cena)
    Cena编译器的使用 及任大佬和禚大佬解释(O2优化、C++11特性、开栈)值得大家学习
    编程求100内的素数
    【关于德育和道德方面】
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7346755.html
Copyright © 2011-2022 走看看