Android基础——AIDL

AIDL是什么?

Android Interface Definition Language,安卓接口定义语言

前提阅读:Android基础——Service

AIDL内部实现——存取钱

在java同级目录下new-AIDL-AIDL File
在这里插入图片描述
命名为UserAction,系统自动生成UserAction.aidl
在这里插入图片描述
删除里面的注释和basicTypes(),定义两个方法,如果是自定义数据类型需要序列化,in表示输入

interface UserAction {
   void saveMoney(in int money);
   int getMoney();
}

创建UserActionAIDLImpl类实现UserAction.Stub重写两个方法

  • 这里是extends UserAction.Stub,AS会根据AIDL生成一个class文件
  • 如果报红实现不了则在菜单栏Build-make porject一下
public class UserActionAIDLImpl extends UserAction.Stub {

    @Override
    public void saveMoney(int money) throws RemoteException {
        Log.d("TAG", "saveMoney: " + money);
    }

    @Override
    public int getMoney() throws RemoteException {
        return 100;
    }
}

创建UserService在onBind()方法中返回UserActionAIDLImpl

public class UserService extends Service {

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

在activity_main创建两个按钮

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/saveMoney"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="存钱" />
    <Button
        android:id="@+id/getMoney"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="取钱" />
</LinearLayout>

修改MainActivity绑定服务,在onServiceConnected()中通过UserAction.Stub.asInterface(service)获取UserAction实例,利用多态调用AIDL方法(可能会抛出异常)

public class MainActivity extends AppCompatActivity {

    private Button mSaveBtn;
    private Button mGetBtn;
    private UserConnection mConnection;
    private boolean mIsBind;
    private UserAction mUserAction;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService();
        initView();
        initListener();
    }

    private void initListener() {
        mSaveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    mUserAction.saveMoney(100);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        mGetBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    mUserAction.getMoney();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void initView() {
        mSaveBtn = findViewById(R.id.saveMoney);
        mGetBtn = findViewById(R.id.getMoney);
    }

    private void bindService() {
        Intent intent = new Intent(MainActivity.this, UserService.class);
        mConnection = new UserConnection();
        mIsBind = bindService(intent, mConnection, BIND_AUTO_CREATE);
    }
    private class UserConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mUserAction = UserAction.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mIsBind && mConnection != null) {
            unbindService(mConnection);
            mConnection = null;
            mIsBind = false;
        }
    }
}

AIDL跨应用实现——支付

Pay应用

AIDL接口

在项目Pay中创建回调PayResul.aidl

interface PayResult {
    void onPaySuccsee();
    void onPayFailed(in int errorCode,in String msg);
}

创建Pay.aidl,用到PayResult 需要手动import

import com.example.pay.PayResult;

interface Pay {
   void requestPay(String orderInfo,float payMoney,PayResult callback);
}

Service及其Action

在Manifest中声明action和category

<service
    android:name=".PayService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.pay.PAY" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

创建PayService,内部类PayImpl实现Pay.Stub,PayService跳转到PayActivity

  • 注意Service和Activity不能同一个栈,利用setFlags()创建新栈
  • PayAction类用于与内部的Activity显示绑定
  • PayImpl用于与外部的Activity隐式绑定
public class PayService extends Service {

    private PayImpl mPayImpl;

    @Override
    public IBinder onBind(Intent intent) {
        String action = intent.getAction();
        if (action != null && "com.example.pay.PAY".equals(action)) {
            mPayImpl = new PayImpl();
            return mPayImpl;
        }
        return new PayAction();
    }

    public class PayAction extends Binder {
        public void pay(float money) {
            if (mPayImpl != null) {
                //外部绑定成功后,进行实际支付操作,如开启事务,完事后回调结果
                mPayImpl.paySuccess();
            }
        }

        public void cancel() {
            if (mPayImpl != null) {
                mPayImpl.payFail(1, "cancel");
            }
        }
    }

    private class PayImpl extends Pay.Stub {

        private PayResult mCallback;

        @Override
        public void requestPay(String orderInfo, float payMoney, PayResult callback) throws RemoteException {
            this.mCallback = callback;
            Intent intent = new Intent(PayService.this, PayActivity.class);
            intent.putExtra("orderInfo", orderInfo);
            intent.putExtra("payMoney", payMoney);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }

        public void paySuccess() {
            try {
                if (mCallback != null) {
                    mCallback.onPaySuccsee();
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        public void payFail(int error, String msg) {
            if (mCallback != null) {
                try {
                    mCallback.onPayFailed(error, msg);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

PayActivity及其布局

创建布局文件activity_pay.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".PayActivity">
    <TextView
        android:id="@+id/order_info"
        android:hint="这里显示账单信息"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/pay"
        android:text="确认支付"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

创建PayActivity绑定PayService用于弹出支付界面进行确认支付操作,这里支付成功后直接finish

public class PayActivity extends AppCompatActivity {

    private boolean mIsBind;
    private PayService.PayAction mPayAction;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pay);
        doBindService();
        initView();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        if (mPayAction != null) {
            mPayAction.cancel();
        }
    }

    private void initView() {
        Intent intent = getIntent();
        String orderInfo = intent.getStringExtra("orderInfo");
        final float payMoney = intent.getFloatExtra("payMoney", 0);
        TextView orderInfoTv = findViewById(R.id.order_info);
        orderInfoTv.setText("账单是:" + orderInfo + ",金额是:" + payMoney);
        Button payBtn = findViewById(R.id.pay);
        payBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (payMoney < 100) {
                    Toast.makeText(PayActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                    mPayAction.pay(payMoney);
                    finish();
                } else {
                    Toast.makeText(PayActivity.this, "钱不够", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private void doBindService() {
        Intent intent = new Intent(this, PayService.class);
        mIsBind = bindService(intent, mConnection, BIND_AUTO_CREATE);

    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mPayAction = (PayService.PayAction) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mPayAction = null;
        }
    };

    @Override
    protected void onDestroy() {
        if (mIsBind && mConnection != null) {
            mIsBind = false;
            unbindService(mConnection);
            mConnection = null;
        }
        super.onDestroy();
    }
}

demo0应用

AIDL

将Pay里面的aidl文件拷贝到demo0中并make project
在这里插入图片描述

MainActivity及布局

修改activity_main.xml,TextView用于显示支付结果,另有一支付按钮

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/payResult"
        android:hint="这里返回支付结果"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/userPay"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击支付" />
</LinearLayout>

修改MainActivity,通过隐式意图绑定PayService获取返回的Pay实例,在按钮的点击事件中传入参数调用AIDL的支付操作,在回调中进行支付结果的处理

public class MainActivity extends AppCompatActivity {
    
    private TextView mPayResultTv;
    private Button mPayBtn;
    private payConnection mPayConnection;
    private boolean mIsBind;
    private Pay mPay;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bindPayService();
        initView();
        initListener();
    }

    private void bindPayService() {
        Intent intent = new Intent();
        intent.setAction("com.example.pay.PAY");
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.setPackage("com.example.pay");
        mPayConnection = new payConnection();
        mIsBind = bindService(intent, mPayConnection, BIND_AUTO_CREATE);
        Log.d("TAG", "bindPayService: " + mIsBind);
    }

    private class payConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mPay = Pay.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("TAG", "onServiceDisconnected");
        }
    }

    private void initListener() {
        mPayBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    if (mPay != null) {
                        mPay.requestPay("黄焖鸡米饭", 15, new PayCallback());
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private class PayCallback extends PayResult.Stub {
        @Override
        public void onPaySuccess() throws RemoteException {
            mPayResultTv.setText("支付成功,扣除金额");
            Toast.makeText(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onPayFailed(int errorCode, String msg) throws RemoteException {
            mPayResultTv.setText("支付失败");
            Toast.makeText(MainActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mIsBind && mPayConnection != null) {
            unbindService(mPayConnection);
            mPayConnection = null;
            mIsBind = false;
        }
    }

    private void initView() {
        mPayResultTv = findViewById(R.id.payResult);
        mPayBtn = findViewById(R.id.userPay);
    }
}

注意事项

  • 在API 28/Android 9以前,代码可以运行
  • 在API 29/Android 10以后,在MainActivity中通过隐私意图绑定不了其他应用的服务,且不会报明显错误

可通过在调用端(demo0)中的<manifest>标签下添加<queries>标签解决,package指定服务端(pay)的包名

<queries>
      <package android:name="com.example.pay" />
</queries>

如添加后无法编译,则需要将AS和Gradle更到最新版本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值