Flutter 集成 Revolut Payment 出现未解析引用
结论
这两个错误通常来自以下问题:
MainActivity.kt缺少对应的 Kotlin imports。- Revolut SDK 依赖写在了错误的 Gradle 文件中,或者 Gradle 尚未成功解析依赖。
题目中的 SDK API 通常需要导入:
import com.revolut.revolutpayments.RevolutPayments
import com.revolut.revolutpay.api.RevolutPayEnvironment
依赖应添加到 Flutter 项目的 android/app/build.gradle,而不是项目级的 android/build.gradle。
正确配置 Gradle 依赖
打开 Flutter 项目中的模块级 Gradle 文件:
android/app/build.gradle
在 dependencies 中添加:
dependencies {
implementation "com.revolut:revolutpayments:1.0.0"
implementation "com.revolut:revolutpay:2.2"
}
不要把 implementation 直接写进项目级的 android/build.gradle。依赖只有添加到 Android 应用模块,才能进入 MainActivity.kt 的编译 classpath。
如果项目使用 Kotlin DSL,对应文件可能是 android/app/build.gradle.kts,语法需要改成:
dependencies {
implementation("com.revolut:revolutpayments:1.0.0")
implementation("com.revolut:revolutpay:2.2")
}
同时确认项目已经配置 SDK 所在的 Maven 仓库。通常至少应包含:
repositories {
google()
mavenCentral()
}
较新的 Flutter 和 Gradle 项目一般会在 android/settings.gradle 的 dependencyResolutionManagement 中统一配置仓库,不需要在 app/build.gradle 中重复添加。
添加 Kotlin imports
在 MainActivity.kt 顶部加入:
import com.revolut.revolutpayments.RevolutPayments
import com.revolut.revolutpay.api.RevolutPayEnvironment
完整的 import 区域可以写成:
package com.example.foodbourge_mobile_app
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import androidx.annotation.NonNull
import com.revolut.revolutpay.api.RevolutPayEnvironment
import com.revolut.revolutpayments.RevolutPayments
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
如果还需要传递 Customer,请根据当前 SDK 版本中该类型的实际包路径添加 import。Revolut SDK 不同版本的包结构可能会变化,不要直接照搬旧版示例。可以使用 Android Studio 的自动导入功能确认正确路径。
调整后的 MainActivity.kt
下面的代码保留了现有 MethodChannel 结构,并添加了实际调用支付初始化方法的分支:
package com.example.foodbourge_mobile_app
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import androidx.annotation.NonNull
import com.revolut.revolutpay.api.RevolutPayEnvironment
import com.revolut.revolutpayments.RevolutPayments
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/revolut_pay"
override fun configureFlutterEngine(
@NonNull flutterEngine: FlutterEngine
) {
super.configureFlutterEngine(flutterEngine)
fun getBatteryLevel(): Int {
return if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
val batteryManager =
getSystemService(Context.BATTERY_SERVICE) as BatteryManager
batteryManager.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY
)
} else {
val intent = ContextWrapper(applicationContext).registerReceiver(
null,
IntentFilter(Intent.ACTION_BATTERY_CHANGED)
)
if (intent == null) {
-1
} else {
val level = intent.getIntExtra(
BatteryManager.EXTRA_LEVEL,
-1
)
val scale = intent.getIntExtra(
BatteryManager.EXTRA_SCALE,
-1
)
if (level < 0 || scale <= 0) -1 else level * 100 / scale
}
}
}
fun initializeRevolutPay() {
RevolutPayments.revolutPay.init(
environment = RevolutPayEnvironment.SANDBOX,
merchantPublicKey = "YOUR_MERCHANT_PUBLIC_KEY",
requestShipping = false
)
}
MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
CHANNEL
).setMethodCallHandler { call, result ->
when (call.method) {
"getBatteryLevel" -> {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error(
"UNAVAILABLE",
"Battery level not available.",
null
)
}
}
"initializeRevolutPay" -> {
try {
initializeRevolutPay()
result.success(null)
} catch (exception: Exception) {
result.error(
"REVOLUT_INITIALIZATION_FAILED",
exception.message,
null
)
}
}
else -> result.notImplemented()
}
}
}
}
原代码中的 payByRevolut() 只是局部函数,没有在 MethodChannel 的处理逻辑中调用。即使解决了编译错误,Flutter 端调用其他方法时也不会触发 Revolut 初始化。
重新同步依赖
修改 Gradle 文件后,可以在项目根目录执行:
flutter clean
flutter pub get
cd android
./gradlew clean
cd ..
flutter run
Windows 环境使用:
cd android
gradlew.bat clean
cd ..
flutter run
如果 Android Studio 仍然显示红色的未解析引用,可以执行 Gradle Sync,然后重新打开项目的 android 目录,让 IDE 重建依赖索引。
如何判断是 import 问题还是依赖问题
如果依赖已经成功下载,只是遗漏了 import,Android Studio 通常能在类名上提供自动导入,并显示类似下面的候选项:
com.revolut.revolutpayments.RevolutPayments
com.revolut.revolutpay.api.RevolutPayEnvironment
如果没有任何自动导入候选项,问题通常不只是缺少 import,而是 SDK 没有进入应用模块的 classpath。此时应检查:
- 依赖是否写在
android/app/build.gradle中。 - Gradle Sync 是否成功。
- 是否已经配置
mavenCentral()等仓库。 - Gradle 输出中是否出现 “Could not find” 或 “Could not resolve”。
- 文档示例与实际使用的 SDK 版本是否一致。
- 两个 Revolut artifact 的版本是否兼容。
Revolut SDK 的 artifact、版本号和包路径可能随版本升级而变化。上面的 imports 对应题目中 RevolutPayments.revolutPay 和 RevolutPayEnvironment 这套 API。如果 Gradle 已经成功解析依赖,但这些包仍然不存在,说明当前依赖版本与参考文档的版本不一致。此时应以该 SDK 版本实际导出的类和官方版本说明为准。
生产环境注意事项
开发阶段可以使用:
environment = RevolutPayEnvironment.SANDBOX
切换到生产环境时,除了修改枚举值,还需要确认:
- 使用生产环境对应的 merchant public key。
- 后端订单和支付接口也已切换到生产环境。
- Android 应用签名、包名和商户后台配置正确。
- 初始化操作不会在每次 MethodChannel 调用时重复执行。
题目中展示的 merchant public key 已经公开出现在代码片段中。即使它是公钥,也建议将其替换为商户后台当前有效且与目标环境匹配的配置值,不要继续使用示例值。
备注:内容仅供参考。
