• android AIDL 语言用法


    跨进程通信可以用AIDL语言

    这里讲述下如何使用AIDL语言进行跨进程通信

    文章参考 《设计模式》一书

    demo结构参考

    主要的文件类有:IBankAidl.aidl

    java文件:AidlBankBinder,BackActivity(应该是BankActivity写错了),BankService(继承自Service,服务类)

    IBankAidl.aidl文件 这里AIdl的使用对包位置有要求,所以我就把包名放出来了

    package finishdemo.arcturis.binderandserviceandaidl.binder;
    
    // Declare any non-default types here with import statements
    
    interface IBankAidl {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
                double aDouble, String aString);
       /**
         * 开户
         * @param name 户主名
         * @param password 密码
         * @return 开户信息
         */
        String openAccount(String name,String password);
    
        /**
         * 存钱
         * @param money
         * @param account
         * @return
         */
        String saveMoney(int money,String account);
    
        /**
         * 取钱
         * @param money
         * @param account
         * @param password
         * @return
         */
        String takeMoney(int money,String account,String password);
    
        /**
         * 销户
         * @param account
         * @param password
         * @return
         */
        String closeAccount(String account,String password);
    
    }

    AidlBankBinder文件 继承自IBankAidl的Stub类,然后重写并实现Aidl内的方法,这里是模拟一个银行的操作

    public class AidlBankBinder extends IBankAidl.Stub {
    
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
        }
    
        @Override
        public String openAccount(String name, String password) {
            return name+"开户成功!账号为:"+ UUID.randomUUID().toString();
        }
    
        @Override
        public String saveMoney(int money, String account) {
            return "账户:"+account + "存入"+ money + "单位:人民币";
        }
    
        @Override
        public String takeMoney(int money, String account, String password) {
            return "账户:"+account + "支取"+ money + "单位:人民币";
        }
    
        @Override
        public String closeAccount(String account, String password) {
            return account + "销户成功";
        }
    }

    BankService文件 返回一个AidlBankBinder 

    public class BankService extends Service {
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            //单进程写法
    //        return new BankBinder();
            //不同进程AIDL 通信写法
            return new AidlBankBinder();
        }
    }

    接下来在Activity中使用 BackActivity方法

    public class BackActivity extends AppCompatActivity implements View.OnClickListener {
    
    //    private BankBinder mBankBinder;
        private IBankAidl mBankBinder;
    
        private TextView tvMsg;
    
        private Context context;
    
    
        private ServiceConnection conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //同一进程写法
    //            mBankBinder = (BankBinder) service;
                //不同进程写法
                mBankBinder = IBankAidl.Stub.asInterface(service);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        };
    
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            context = this;
            tvMsg = (TextView) findViewById(R.id.tv_msg);
    
            Intent intent = new Intent();
            intent.setAction("actionname.aidl.bank.BankService");
    
            //这里遇到一个问题,如果你直接使用intent 这个意图去开启服务的话就会报
            //Android Service Intent must be explicit 意思是服务必须要显示的调用,这个是5.0之后新的规定
            //这个 createExplicitFromImplicitIntent 可以将隐性调用变成显性调用
            Intent intent1  = new Intent(createExplicitFromImplicitIntent(context,intent));
    
            bindService(intent1,conn,BIND_AUTO_CREATE);
    
            initBtn(R.id.btn_aidl_bank_close);
            initBtn(R.id.btn_aidl_bank_open);
            initBtn(R.id.btn_aidl_bank_save);
            initBtn(R.id.btn_aidl_bank_take);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(conn);
        }
    
        private void initBtn(int resID){
            Button b = (Button) findViewById(resID);
            b.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.btn_aidl_bank_open:
                    //这个RemoteException 是 AIDL跨进程通信的用法必须加上的异常捕获
                    try {
                        tvMsg.setText(mBankBinder.openAccount("BigAss","123456"));
                    }catch (RemoteException e){
                        e.printStackTrace();
                    }
                    break;
    
                case R.id.btn_aidl_bank_save:
                    try {
                        tvMsg.setText(mBankBinder.saveMoney(8888888,"bigAss123"));
                    }catch (RemoteException e){
                        e.printStackTrace();
                    }
                    break;
    
                case R.id.btn_aidl_bank_take:
                    try {
                        tvMsg.setText(mBankBinder.takeMoney(520,"bigAss123","123456"));
                    }catch (RemoteException e){
                        e.printStackTrace();
                    }
                    break;
    
                case R.id.btn_aidl_bank_close:
                    try {
                        tvMsg.setText(mBankBinder.closeAccount("bigAss123","123456"));
                    }catch (RemoteException e){
                        e.printStackTrace();
                    }
                    break;
    
            }
        }
    
    
        /***
         * Android L (lollipop, API 21) introduced a new problem when trying to invoke implicit intent,
         * "java.lang.IllegalArgumentException: Service Intent must be explicit"
         *
         * If you are using an implicit intent, and know only 1 target would answer this intent,
         * This method will help you turn the implicit intent into the explicit form.
         *
         * Inspired from SO answer: http://stackoverflow.com/a/26318757/1446466
         * @param context
         * @param implicitIntent - The original implicit intent
         * @return Explicit Intent created from the implicit original intent
         */
        public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
            // Retrieve all services that can match the given intent
            PackageManager pm = context.getPackageManager();
            List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
    
            // Make sure only one match was found
            if (resolveInfo == null || resolveInfo.size() != 1) {
                return null;
            }
    
            // Get component info and create ComponentName
            ResolveInfo serviceInfo = resolveInfo.get(0);
            String packageName = serviceInfo.serviceInfo.packageName;
            String className = serviceInfo.serviceInfo.name;
            ComponentName component = new ComponentName(packageName, className);
    
            // Create a new intent. Use the old one for extras and such reuse
            Intent explicitIntent = new Intent(implicitIntent);
    
            // Set the component to be explicit
            explicitIntent.setComponent(component);
    
            return explicitIntent;
        }
    }

    主要思路是用隐式的方法启动一个服务,然后调用Aidl实例类的方法即可,具体的Aidl语言在BuildApp之后在

    这里即可查看 内部是他实现进程间数据传输所做的转化代码,有兴趣可以看下

  • 相关阅读:
    关于sizeof表达式作为数组元素个数的编译
    【deque】滑动窗口、双端队列解决数组问题
    【二叉树】重建二叉树
    字符数组与字符串指针
    【STL】C中的qsort与C++中的sort
    对C++不是类型安全语言的理解
    【vector】创建一个二维vector当作二维数组用
    批量处理改变文件名、文件后缀名
    位运算
    关于sqlserver帐号被禁用问题
  • 原文地址:https://www.cnblogs.com/fengfenghuifei/p/8418965.html
Copyright © 2020-2023  润新知