AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似。 您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。 在 Android 上,一个进程通常无法访问另一个进程的内存。 尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。 编写执行这一编组操作的代码是一项繁琐的工作,因此 Android 会使用 AIDL 来处理。

反正我的理解就是用来跨进程访问的接口,AIDL文件创建后会生成.java的。

 

这次测试的是一个相当于玩游戏充值的模式,比如一个小游戏要充值,点击充值的时候会跳转到支付宝的支付界面,然后再输入密码支付,接着回到游戏中,学之前以为只是搞了个类似支付宝的界面,原来是需要和支付宝的程序进行连接,支付宝接收到充值信息然后打包SDK发送到这个游戏的服务器,服务器里的数据库的数据改变,然后更新到游戏中,就充值成功,但我们测试只是两个程序之间,充值的程序点击充值按钮跳转到模拟的支付宝程序的支付界面,然后充值后结束支付宝程序,回到充值的程序更新充值的内容。

 

 

 

 

 首先开始写类似支付宝支付界面的程序,

刚开始写AIDL文件

创建的方式就是跟创建活动差不多,在活动上面

Android跨进程修改sp android跨进程点击_支付宝

 

 

Android跨进程修改sp android跨进程点击_支付宝_02

 

 

这里的两个AIDL文件的作用,两个程序交互时使用,比如第一个就是支付时的信息和金额数量(这只是模仿,一小部分而已参数),然后回调第二个AIDL文件,第二个文件里面的方法是判断支付成功与否。

 

Android跨进程修改sp android跨进程点击_xml_03

 

 

Android跨进程修改sp android跨进程点击_android_04

 

 

 

 

再写支付的服务:

package com.example.zhifubao;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.Nullable;

import static android.content.ContentValues.TAG;

public class PayService extends Service {

    private ThirdPartPayImpl thirdPartPay;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        String action = intent.getAction();
        Log.d(TAG, "onBind --> action -->" + action);
        if (action != null && "com.example.zhifubao.THIRD_PART_PAY".equals(action)) {
//        第三方软件要求支付宝进行支付
            thirdPartPay = new ThirdPartPayImpl();
            return thirdPartPay;
        }
        return new PlayAction();
    }
    public class PlayAction extends Binder{
        public void Play(float payMoney){
            Log.d(TAG,"Pay money is -->"+payMoney);
//          实际的支付还需要加密,比如向服务器发送请求,等待服务器的结果。
            if (thirdPartPay!=null) {
                thirdPartPay.paySuccess();
            }
        }
        public  void onUserCancel(){
            if (thirdPartPay!=null) {
                thirdPartPay.payFailed(1,"user cancel pay.");
            }
        }
    }
    private class ThirdPartPayImpl extends ThirdPartPay.Stub {
        private ThirdPartPayResult mCallback;
        @Override
        public void requestPay(String orderInfo, float payMoney, ThirdPartPayResult callback) {
            this.mCallback=callback;
            //      第三方应用发起请求打开一个支付的界面
            Intent intent =new Intent(PayService.this,PayActivity.class);
            intent.putExtra(Const.KEY_BILL_INFO,orderInfo);
            intent.putExtra(Const.KEY_PAY_MONEY,payMoney);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
        public void paySuccess(){
            if (mCallback!=null) {
                try {
                    mCallback.onPaySuccess();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

        }
        public void payFailed(int errorCode,String errorMsg){
            if (mCallback!=null) {
                try {
                    mCallback.onPayFailed(errorCode, errorMsg);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
在这个支付服务里面的Const是常量集,所以还得创建一个常量类Const
package com.example.zhifubao;

public class Const {
    public static final String KEY_BILL_INFO="key_bill_info";
    public static final String KEY_PAY_MONEY="key_pay_money";

}
接着给它在AndroidManifest.xml里注册服务并给他action-name,
<service
    android:name=".PayService"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.zhifubao.THIRD_PART_PAY" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>


然后我们就创建一个活动来显示支付界面并绑定服务
package com.example.zhifubao;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

public class PayActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG =PayActivity.class.getName();
    private boolean isBind;
    private TextView order_info_tv;
    private TextView pay_money;
    private EditText pay_password_input;
    private Button pay_commit;
    private PayService.PlayAction playAction;
    private float floatExtra;
    private String stringExtra;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pay);
//        因为Activity也要和服务进行通讯,告诉服务支付结果,所以要绑定服务
        doService();
        initView();

    }

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

    private void initView() {
        Intent intent = getIntent();
        stringExtra = intent.getStringExtra(Const.KEY_BILL_INFO);
        floatExtra = intent.getFloatExtra(Const.KEY_PAY_MONEY, 0f);

        order_info_tv = (TextView) findViewById(R.id.order_info_tv);
        order_info_tv.setText("支付信息:"+ stringExtra);
        order_info_tv.setOnClickListener(this);
        pay_money = (TextView) findViewById(R.id.pay_money);
        pay_money.setText("支付金额:"+ floatExtra);
        pay_money.setOnClickListener(this);
        pay_password_input = (EditText) findViewById(R.id.pay_password_input);
        pay_password_input.setOnClickListener(this);
        pay_commit = (Button) findViewById(R.id.pay_commit);
        pay_commit.setOnClickListener(this);
    }

    private void doService() {
        Intent intent = new Intent(this, PayService.class);
        isBind = bindService(intent, MConnection, BIND_AUTO_CREATE);
    }

    private ServiceConnection MConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            playAction = (PayService.PlayAction) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (isBind && MConnection != null) {
            unbindService(MConnection);
            MConnection = null;
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.pay_commit:
//                提交点击了
                Toast.makeText(this, "点击提交", Toast.LENGTH_SHORT).show();
                String trim = pay_password_input.getText().toString().trim();
                if ("123456".equals(trim)&&playAction!=null) {
                    Log.d(TAG,"pay finished...");
                    Toast.makeText(this, "支付成功", Toast.LENGTH_SHORT).show();
                    playAction.Play(floatExtra);
                    finish();
                }
                else {
                    Toast.makeText(this, "密码错误", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

    private void submit() {
        // validate
        String input = pay_password_input.getText().toString().trim();
        if (TextUtils.isEmpty(input)) {
            Toast.makeText(this, "请输入支付密码", Toast.LENGTH_SHORT).show();
            return;
        }

        // TODO validate success, do something


    }
}
然后布局就比较简洁了
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="15dp"
    tools:context=".PayActivity">

    <TextView
        android:id="@+id/order_info_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="账单:充值6480点券"
        android:textSize="22sp" />

    <TextView
        android:id="@+id/pay_money"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="支付金额:648元"
        android:textSize="20sp" />

    <EditText
        android:id="@+id/pay_password_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入支付密码"
        android:inputType="numberPassword" />

    <Button
        android:id="@+id/pay_commit"
        android:text="支付"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

Android跨进程修改sp android跨进程点击_支付宝_05

 

 

然后调试下,没问题就可以了,

 

开始下一个程序

在下一个程序中,我们做一个充值648元的操作,但是比例是1:10,充值648获得6480点券

 

这里最关键的就是那个AIDL的转接,我用死方法的,首先AIDL要进行跨程序操作:主程序(游戏)需要调用支付宝(充值界面)充值,那么在支付宝(充值界面)写的AIDL就得原封不动(文件名,文件内部包名,都得是支付宝里的)

下面可以看到,这个程序是Pokemon,调用的AIDL文件夹里的文件夹名还是属于zhifubao里的,

Android跨进程修改sp android跨进程点击_android_06

 

 

 

Android跨进程修改sp android跨进程点击_支付宝_07

 

 

Android跨进程修改sp android跨进程点击_xml_08

 

 

可以看出,文件里的包名还是zhifubao里的,这个需要注意,
然后给他Make Project一下

Android跨进程修改sp android跨进程点击_Android跨进程修改sp_09

 

这样就能让它产生.java的文件

 

然后在主活动写绑定服务,写布局

 

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

  <LinearLayout
      android:gravity="right"
      android:layout_gravity="right"
      android:orientation="horizontal"
      android:layout_width="wrap_content"
      android:layout_marginRight="20dp"
      android:layout_height="wrap_content">
      <TextView
          android:id="@+id/tv1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="点劵: "
          android:textSize="20dp"
          android:textStyle="bold" />
      <TextView
          android:id="@+id/money"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="120"
          android:textSize="20dp"
          android:textStyle="bold" />


  </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/sq1"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:background="@android:color/white"
            android:text="充值6480点券"
            android:textSize="30dp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/bt"
            android:layout_width="205dp"
            android:layout_height="184dp"
            android:background="@drawable/sq6"
            android:text="648元"
            android:textColor="@android:color/white"
            android:textSize="22dp"
            android:textStyle="bold" />
    </LinearLayout>

</LinearLayout>
一些图片之类的是我导入的

Android跨进程修改sp android跨进程点击_支付宝_10

 

 

 

然后这个雷电狮这个是一个按钮,背景改成雷电狮了

点击它就进行充值交互

 

 

活动里的就是绑定服务,调用AIDL的接口和方法,

package com.example.pokemon;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.zhifubao.ThirdPartPay;
import com.example.zhifubao.ThirdPartPayResult;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = MainActivity.class.getName();
    private TextView tv;
    private Button bt;
    private TextView tv1;
    private TextView money;
    private TextView tv2;
    private AliPayConnection aliPayConnection;
    private boolean isbind;
    private ThirdPartPay thirdPartPay;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//       绑定 支付宝的服务,在现实开发中,绑定服务是由支付宝的SDK完成的
        bindAliService();


        //找到控件
        initView();
    }

    private void bindAliService() {
        Intent intent = new Intent();
        intent.setAction("com.example.zhifubao.THIRD_PART_PAY");
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.setPackage("com.example.zhifubao");
        aliPayConnection = new AliPayConnection();
        isbind = bindService(intent, aliPayConnection, BIND_AUTO_CREATE);
    }

    private class AliPayConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "连接服务。。。");
            thirdPartPay = ThirdPartPay.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "未连接服务。。。");

        }
    }

    private void initView() {
        bt = (Button) findViewById(R.id.bt);

        bt.setOnClickListener(this);
        tv1 = (TextView) findViewById(R.id.tv1);
        tv1.setOnClickListener(this);
        money = (TextView) findViewById(R.id.money);
        money.setOnClickListener(this);
        tv2 = (TextView) findViewById(R.id.tv2);
        tv2.setOnClickListener(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (isbind && aliPayConnection != null) {
            unbindService(aliPayConnection);
            Log.d(TAG, "解绑服务。。");
            aliPayConnection = null;
        }
    }

    private class PayCallback extends ThirdPartPayResult.Stub {

        @Override
        public void onPaySuccess() {
//支付成功就修改布局的内容,不过真正的是修改服务器的数据,实际上支付宝是通过回调的URL地址通知服务器,
// 不会到客户端,不然被拦截就很容易开挂了


                //the activity provides this method to be able to run code in the UI Thread
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        if (money.getText().toString() != null) {
                            int t = Integer.parseInt(money.getText().toString()) + 6480;

                            money.setText("" + t);
                        } else {
                            money.setText("0");
                        }

                        Toast.makeText(MainActivity.this, "充值成功!", Toast.LENGTH_SHORT).show();
                    }
            });

        }

        @Override
        public void onPayFailed(int errorCode, String msg) {
            Log.d(TAG, "失败 code-->" + errorCode + "信息" + msg);
            Toast.makeText(MainActivity.this, "充值失败!", Toast.LENGTH_SHORT).show();

        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt:
//                点击充值,进行跨进程操作
                try {
                    if (thirdPartPay != null) {

                        thirdPartPay.requestPay("充值点券6480", 648.00f, new PayCallback());
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
//                TODO:一个标签,跟书签一样,下面的按钮中TODO就可以查看这些书签

                break;
        }
    }
}
然后运行测试
初始的点券120

Android跨进程修改sp android跨进程点击_支付宝_11

 

这里的支付密码当时是内定的123456

然后输入

 

Android跨进程修改sp android跨进程点击_android_12

 

支付完成,然后点券是6480+120=6600 

Android跨进程修改sp android跨进程点击_xml_13

 

 

再来一次

Android跨进程修改sp android跨进程点击_android_14

 

 

 

不过像我这种口袋空空的学生,怎么可能充648呢,只能做做软件过过瘾了。。。

加油,努力,勤能补拙。

 

 

牛崽成为大牛的发展路途将成为历史的里程碑