You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter应用中调用Android原生BenefitInAppButtonListener

Flutter集成自定义Android SDK问题:BenefitInAppButtonListener监听器无法触发CheckoutListener

问题背景

我需要在Flutter应用中集成一款自定义Android SDK,该SDK包含BenefitInAppButtonListener监听器及相关支付功能,但在Flutter环境下遇到了监听器回调失效的问题。

常规Android原生用法

在Android原生项目中,通常通过给BenefitInAppButton设置监听器来触发支付流程,点击按钮后会自动调用onButtonClicked(),并在该方法中初始化BenefitInAppCheckout,交易结果通过传入的CheckoutListener回调:

checkoutBtn.setListener(object : BenefitInAppButtonListener {
    override fun onButtonClicked() {
        val benefitInAppCheckout = BenefitInAppCheckout.newInstance(
            this@MainActivity,
            ....,
            ....,
            ....,
            (object : CheckoutListener{
                override fun onTransactionSuccess(p0: Transaction?) {
                   Toast.makeText(applicationContext, "Success", Toast.LENGTH_LONG).show()
                }

                override fun onTransactionFail(p0: Transaction?) {
                    Toast.makeText(applicationContext, "Fail", Toast.LENGTH_LONG).show()
                }

            })

        )

    }

    override fun onFail(p0: Int) {
        TODO("Not yet implemented")
    }

})

Flutter集成遇到的问题

在Flutter中没有对应的原生按钮视图可以绑定BenefitInAppButtonListener,我尝试直接调用监听器的onButtonClicked()方法,虽然方法内的日志能正常打印,但内部传入的CheckoutListener完全没有触发回调。看起来必须通过SDK原生的BenefitInAppButtonListener触发完整流程,才能让CheckoutListener生效。

测试代码片段:

var myListener = object : BenefitInAppButtonListener {
            override fun onButtonClicked() {

                Log.i("hamad2", paymentAmount) // 该日志可正常输出

                val benefitInAppCheckout = BenefitInAppCheckout.newInstance(
                    this@MainActivity,
                    ...,
                    ...,
                    ...,
                    (object : CheckoutListener {
                        override fun onTransactionSuccess(p0: Transaction?) {
                            Toast.makeText(applicationContext, "Succ", Toast.LENGTH_LONG).show()
                        }

                        override fun onTransactionFail(p0: Transaction?) {
                            Toast.makeText(applicationContext, "Fail", Toast.LENGTH_LONG).show()
                        }

                    })

                )
            }
            override fun onFail(p0: Int) {
                Toast.makeText(applicationContext, "Fail", Toast.LENGTH_LONG).show()
            }
        }
        
        myListener.onButtonClicked();

完整的MainActivity.kt代码

package com.example.benefit_test

import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import mobi.foo.benefitinapp.data.Transaction
import mobi.foo.benefitinapp.listener.BenefitInAppButtonListener
import mobi.foo.benefitinapp.listener.CheckoutListener
import mobi.foo.benefitinapp.utils.BenefitInAppButton
import mobi.foo.benefitinapp.utils.BenefitInAppCheckout

class MainActivity: FlutterActivity() {

    private val channel = "ummatisoftwares.benefitpay"

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel).setMethodCallHandler {
                call, result ->
            if (call.method == "BenefitPay"){
                val amount = call.argument<String>("amount")
                val status = payBenefitApp(amount.toString())
                if (status == "Success") result.success("Success")
                else result.error("Error", status, null)
            } else {
                result.notImplemented()
            }
        }

    }


    private fun payBenefitApp(paymentAmount: String): String {
        var status = "fail"

        var myListener = object : BenefitInAppButtonListener {
            override fun onButtonClicked() {
                Log.i("hamad2", paymentAmount)
                val benefitInAppCheckout = BenefitInAppCheckout.newInstance(
                    this@MainActivity,
                    ..., ..., ..., // 传入必要的字符串参数
                    (object : CheckoutListener {
                        override fun onTransactionSuccess(p0: Transaction?) {
                            Toast.makeText(applicationContext, "Suc", Toast.LENGTH_LONG).show()
                            status = "Success"
                        }

                        override fun onTransactionFail(p0: Transaction?) {
                            status = " "+p0.toString()
                            Toast.makeText(applicationContext, "Fail", Toast.LENGTH_LONG).show()
                        }

                    })

                )
            }
            override fun onFail(p0: Int) {
                Toast.makeText(applicationContext, "Fail", Toast.LENGTH_LONG).show()
            }
        }

        myListener.onButtonClicked();

        return status
    }
}

解决方案建议

1. 模拟原生按钮触发流程

直接调用onButtonClicked()会跳过SDK内部的绑定逻辑,建议创建一个隐藏的BenefitInAppButton实例,绑定监听器后模拟点击,触发完整流程:

import android.view.View
import android.view.ViewGroup

private fun payBenefitApp(paymentAmount: String) {
    // 创建隐藏按钮并添加到视图树
    val checkoutBtn = BenefitInAppButton(this)
    checkoutBtn.visibility = View.GONE
    val rootView = window.decorView.findViewById(android.R.id.content) as ViewGroup
    rootView.addView(checkoutBtn)

    checkoutBtn.setListener(object : BenefitInAppButtonListener {
        override fun onButtonClicked() {
            Log.i("hamad2", paymentAmount)
            val benefitInAppCheckout = BenefitInAppCheckout.newInstance(
                this@MainActivity,
                ..., ..., ...,
                object : CheckoutListener {
                    override fun onTransactionSuccess(p0: Transaction?) {
                        Toast.makeText(applicationContext, "Success", Toast.LENGTH_LONG).show()
                        // 异步回调给Flutter
                        flutterEngine?.let {
                            MethodChannel(it.dartExecutor.binaryMessenger, channel)
                                .invokeMethod("onPaymentResult", "Success")
                        }
                        rootView.removeView(checkoutBtn)
                    }

                    override fun onTransactionFail(p0: Transaction?) {
                        val errorMsg = p0?.toString() ?: "Unknown error"
                        Toast.makeText(applicationContext, "Fail", Toast.LENGTH_LONG).show()
                        flutterEngine?.let {
                            MethodChannel(it.dartExecutor.binaryMessenger, channel)
                                .invokeMethod("onPaymentResult", errorMsg)
                        }
                        rootView.removeView(checkoutBtn)
                    }
                }
            )
        }

        override fun onFail(p0: Int) {
            val errorMsg = "Button init fail: $p0"
            Toast.makeText(applicationContext, errorMsg, Toast.LENGTH_LONG).show()
            flutterEngine?.let {
                MethodChannel(it.dartExecutor.binaryMessenger, channel)
                    .invokeMethod("onPaymentResult", errorMsg)
            }
            rootView.removeView(checkoutBtn)
        }
    })

    // 模拟按钮点击
    checkoutBtn.performClick()
}

2. 修改Flutter端回调逻辑

支付是异步流程,不能同步返回结果,需要在Flutter端监听MethodChannel回调:

import 'package:flutter/services.dart';
import 'package:flutter/material.dart';

class _PaymentPageState extends State<PaymentPage> {
  static const platform = MethodChannel('ummatisoftwares.benefitpay');
  String _paymentResult = "等待支付...";

  @override
  void initState() {
    super.initState();
    // 监听Android端的回调
    platform.setMethodCallHandler((call) async {
      if (call.method == "onPaymentResult") {
        setState(() {
          _paymentResult = call.arguments.toString();
        });
      }
    });
  }

  Future<void> startPayment() async {
    try {
      await platform.invokeMethod("BenefitPay", {"amount": "100"});
    } on PlatformException catch (e) {
      setState(() {
        _paymentResult = "支付错误: ${e.message}";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(_paymentResult),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: startPayment,
              child: const Text("发起Benefit支付"),
            ),
          ],
        ),
      ),
    );
  }
}

3. 检查SDK初始化要求

确认SDK是否需要提前初始化全局配置、权限申请,或者必须在特定Activity生命周期中执行操作,可参考SDK官方文档补充必要步骤。

内容的提问来源于stack exchange,提问作者Ummati Softwares

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 04:35:24