zoukankan      html  css  js  c++  java
  • 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之后在

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

  • 相关阅读:
    SharePoint 2013 APP 开发示例 (六)服务端跨域访问 Web Service (REST API)
    麦咖啡导致电脑不能上网
    SharePoint 2013 Central Admin 不能打开
    SharePoint 2013 APP 开发示例 (五)跨域访问 Web Service (REST API)
    SharePoint 2013 APP 开发示例 系列
    synthesize(合成) keyword in IOS
    Git Cmd
    简单的正则匹配
    Dropbox
    SQL Server Replication
  • 原文地址:https://www.cnblogs.com/fengfenghuifei/p/8418965.html
Copyright © 2011-2022 走看看