外部应用调用第三方服务采用AIDL(Android Interface Definition Language)
AIDL即是用来跟外部第三方用来进行通信的接口(创建AIDL项目,在里面申明接口),要想使用内部接口,应先build project产生.java文件。
然后通过实现该接口调用内部方法,产生的.java文件中的Stub继承自android.os.Binder实现了AIDL中的接口。
定义的接口方法通过产生的.java文件的抽象类Stub实现,因此实现AIDL中的接口方法即继承自该接口下的.Stub类实现。
private class ThirdPartPlay extends ThirdPartPay.Stub
//ThirdPartPay即是AIDL中的接口
public static abstract class Stub extends android.os.Binder implements com.alibaba.alipay.ThirdPartPay{ }
将父类强转为接口类型采用asInterface();
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "ComponentName:" + name);
Log.d(TAG, "service:" + service);
thirdPartPay = ThirdPartPay.Stub.asInterface(service);
}
不同应用之间进行通信时,AIDL必须相同,否则不能产生相同的.java文件
找到该AIDL的文件夹,
将com文件夹复制带另一个项目中去,保证双方产生相同的.java文件。
小栗子
通过模拟支付宝支付界面通过服务发起调转至第三方进行支付。
服务方:
源码:(PayActivity.java)
package com.alibaba.alipay;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
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.annotation.Nullable;
public class PayActivity extends Activity implements View.OnClickListener {
private static final String TAG = PayActivity.class.getName();
private boolean mBindService;
private mConnection connection;
private ThirdPartPay thirdPartPay;
private EditText pass;
private Button payBtn;
private PayService.PayAction payAction;
private float payMoney;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pay);
//3.绑定第三方服务
doBindService();
InitView();
}
private void InitView() {
Intent intent = getIntent();
String info = intent.getStringExtra(Constants.KEY_BILL_INFO);
payMoney = intent.getFloatExtra(Constants.KEY_PAY_MONEY, 0);
TextView infoTV = this.findViewById(R.id.order_info_tv);
TextView payMoney = this.findViewById(R.id.pay_money);
infoTV.setText("支付信息为:" + info);
payMoney.setText("支付金额为:" + this.payMoney + "元");
pass = this.findViewById(R.id.password);
payBtn = this.findViewById(R.id.pay_btn);
//5.通过用户支付的密码正确与否,是否进行支付
payBtn.setOnClickListener(this);
}
private void doBindService() {
Intent intent = new Intent();
intent.setClass(PayActivity.this, PayService.class);
connection = new mConnection();
mBindService = bindService(intent, connection, BIND_AUTO_CREATE);
}
@Override
public void onClick(View v) {
String password = pass.getText().toString().trim();
if (password.equals("123") && payAction != null) {
//6.密码正确,进行支付(payAction.Pay()是内部类方法,该方法调用AIDL接口方法传值回第三方)
payAction.Pay(payMoney);
Toast.makeText(this, "支付成功!!!!", Toast.LENGTH_SHORT).show();
//关闭页面
finish();
Log.d(TAG,"pay finish!");
}else {
Toast.makeText(this, "password inCorrect!!!!", Toast.LENGTH_SHORT).show();
return;
}
}
private class mConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//内部类的支付方法
payAction = (PayService.PayAction) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
//销毁服务
@Override
protected void onDestroy() {
super.onDestroy();
if (mBindService && connection != null) {
unbindService(connection);
mBindService = false;
connection = null;
thirdPartPay = null;
}
}
}
服务(PayService.java)
package com.alibaba.alipay;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import androidx.annotation.Nullable;
public class PayService extends Service {
private static final String TAG = "PayService";
private ThirdPartPlay thirdPartPlay;
@Nullable
@Override
public IBinder onBind(Intent intent) {
String action = intent.getAction();
Log.d(TAG,"onBind--action-->"+action);
if (action != null&&"com.alibaba.alipay.THIRD_PART_PAY".equals(action)) {
//1.第三方应用拉起服务
thirdPartPlay = new ThirdPartPlay();
return thirdPartPlay;
}
PayAction payAction = new PayAction();
return payAction;
}
//4.绑定服务后,服务将该支付类返回给支付页面
public class PayAction extends Binder{
public void Pay(Float payMoney){
Log.d(TAG,"支付金额:"+payMoney);
if (thirdPartPlay!=null) {
//7.将支付结果回调给第三方
thirdPartPlay.PaySuccess();
}
}
public void UserCancelPay(){
if (thirdPartPlay!=null) {
thirdPartPlay.PayFailed(1,"用户取消支付");
}
}
}
//2.处理第三方应用的信息,拉起支付页面
private class ThirdPartPlay extends ThirdPartPay.Stub{
private ThirdPartResult mCallback;
@Override
public void requstPay(String orderInfo, float payMoney, ThirdPartResult callback) {
this.mCallback = callback;
//第三方发起支付请求,打开支付界面
Intent intent = new Intent();
intent.setClass(PayService.this,PayActivity.class);
intent.putExtra(Constants.KEY_BILL_INFO,orderInfo);
Log.d(TAG,"orderInfo:----->"+orderInfo);
Log.d(TAG,"payMoney:----->"+payMoney);
intent.putExtra(Constants.KEY_PAY_MONEY,payMoney);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
public void PaySuccess(){
if (mCallback != null) {
try {
//返回给第三方应用,支付成功(该方法在第三方实现,直接调用第三方的接口即可)
mCallback.onPaySuccess();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void PayFailed(int ErrorCode,String msg){
if (mCallback != null) {
try {
//返回给第三方应用,支付失败
mCallback.onPayFailed(ErrorCode,msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.alibaba.alipay">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Alipay">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--exported="true"表示可以被第三方调用服务内部方法-->
<service android:name=".PayService" android:exported="true">
<intent-filter >
<action android:name="com.alibaba.alipay.THIRD_PART_PAY"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</service>
<activity android:name=".PayActivity"/>
</application>
</manifest>
activity_pay.xml(支付界面)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/order_info_tv"
android:textSize="20sp"
/>
<TextView
android:layout_width="match_parent"
android:textSize="20sp"
android:layout_height="wrap_content"
android:id="@+id/pay_money"
android:layout_marginTop="10dp"
/>
<EditText
android:layout_width="match_parent"
android:textSize="20sp"
android:layout_height="wrap_content"
android:id="@+id/password"
android:hint="请输入支付密码"
/>
<Button
android:layout_width="match_parent"
android:textSize="20sp"
android:layout_height="wrap_content"
android:text="确认支付"
android:id="@+id/pay_btn"
/>
</LinearLayout>
客户端:
源码:
(MainActivity.java)第三方逻辑层
package com.alibaba.client;
import androidx.appcompat.app.AppCompatActivity;
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 com.alibaba.alipay.ThirdPartPay;
import com.alibaba.alipay.ThirdPartResult;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = MainActivity.class.getName();
private TextView count;
private Button buyBtn;
private Connection connection;
private boolean isBindService;
private ThirdPartPay thirdPartPay;
private String sCount;
private float fCount;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindAliPayService();
InitVeiw();
buyBtn.setOnClickListener(this);
}
private void InitVeiw() {
count = this.findViewById(R.id.count);
buyBtn = this.findViewById(R.id.buy_btn);
}
/**
* 绑定支付宝服务
*/
public void bindAliPayService() {
Intent intent = new Intent();
intent.setAction("com.alibaba.alipay.THIRD_PART_PAY");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setPackage("com.alibaba.alipay");
connection = new Connection();
isBindService = bindService(intent, connection, BIND_AUTO_CREATE);
}
private class Connection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "ComponentName:" + name);
Log.d(TAG, "service:" + service);
thirdPartPay = ThirdPartPay.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
@Override
public void onClick(View v) {
//点击按钮进行充值
try {
if (thirdPartPay != null) {
//调用服务方的方法,开启服务调转至第三方界面,new PayCallPay()将结果传回
thirdPartPay.requstPay("充值100块钱", 100f, new PayCallPay());
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
//复写AIDL接口下的父类方法
private class PayCallPay extends ThirdPartResult.Stub {
//此方法由服务方调用,用以确保支付是否成功,成功则调用onPaySuccess()
@Override
public void onPaySuccess() throws RemoteException {
//支付成功,我们就去修改UI上面的内容
sCount = count.getText().toString();
fCount = Float.valueOf(sCount)+100.0f;
String sText =String.valueOf(fCount);
count.setText(sText);
Toast.makeText(MainActivity.this, "充值成功!!!", Toast.LENGTH_SHORT).show();
}
@Override
public void onPayFailed(int errorCode, String msg) throws RemoteException {
Toast.makeText(MainActivity.this, "充值失败!!!", Toast.LENGTH_SHORT).show();
}
}
//销毁服务
@Override
protected void onDestroy() {
super.onDestroy();
if (isBindService == true && connection != null) {
if (isBindService) {
Log.d(TAG, "销毁第三方服务");
unbindService(connection);
connection = null;
isBindService = false;
}
}
}
}
点击充值界面(main_activity.xml)
<?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="10dp"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="积分"
android:textSize="30sp"
android:gravity="center"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="0"
android:textSize="30sp"
android:gravity="center"
android:layout_marginTop="20dp"
android:textColor="#ff0000"
android:id="@+id/count"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textSize="30sp"
android:text="充值100块"
android:id="@+id/buy_btn"
/>
</LinearLayout>
效果图:
AIDL接口(build project)
ThirdPartPay:
// ThirdPartPay.aidl
package com.alibaba.alipay;
import com.alibaba.alipay.ThirdPartResult;
interface ThirdPartPay {
//发起支付
void requstPay(String orderInfo,float payMoney,ThirdPartResult callback);
}
ThirdPartResult:
// ThirdPartResult.aidl
package com.alibaba.alipay;
interface ThirdPartResult {
//支付成功
void onPaySuccess();
//支付失败
void onPayFailed(in int erroeCode,in String msg);
}
效果显示:
注意:1.绑定服务之后为了防止泄露,必须同时写解绑服务。
2.服务方传递结果给第三方应用采用回传方式,在AIDL定义接口实现。调用第三方方法即可。
3.注意四大组件均是通过Intent通信,且在xml文件中进行配置。
4.Activity返回结果给第三方时:①调用服务内部类方法②内部类调用实现接口的内部类方法③该内部类中方法将调用回传对象的方法,该回传对象通过AIDL形式传给第三方
============================================================================
学习整理自b站up主程序猿拉大锯的视频