Android Kotlin集成Stripe Terminal时initTerminal运行时错误修复
解决Stripe Terminal初始化错误:
java.lang.IllegalStateException: initTerminal must be called before attempting to get the instance 这个错误的核心原因是你在调用Terminal的任何功能方法前,未完成SDK的初始化流程。Stripe Terminal SDK强制要求:必须先调用initTerminal()完成初始化,才能通过Terminal.getInstance()获取实例并调用如discoverReaders()这类方法。
修复步骤
- 优先完成Terminal初始化,建议在
Activity的onCreate()中、调用onDiscoverReaders()之前执行初始化逻辑。 - 初始化需传入包含Stripe可发布密钥、设备位置ID等参数的
TerminalConfiguration。 - 仅在初始化成功的回调中,再调用
onDiscoverReaders()方法。
完整修复代码示例
import com.stripe.stripeterminal.Terminal import com.stripe.stripeterminal.external.models.TerminalConfiguration import com.stripe.stripeterminal.external.models.ConnectionTokenProvider import com.stripe.stripeterminal.external.callbacks.InitCallback import com.stripe.stripeterminal.external.callbacks.Callback import com.stripe.stripeterminal.external.models.DiscoveryConfiguration import com.stripe.stripeterminal.external.models.DiscoveryMethod import com.stripe.stripeterminal.external.models.Reader import com.stripe.stripeterminal.external.callbacks.DiscoveryListener import com.stripe.stripeterminal.external.models.Cancelable class PayScreenActivity : AppCompatActivity() { private var discoveryCancelable: Cancelable? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_pay_screen) // 先执行Terminal初始化 initStripeTerminal() } private fun initStripeTerminal() { val terminalConfig = TerminalConfiguration.Builder() .setPublishableKey("你的Stripe可发布密钥") .setLocationId("xxxxxxxxxxxxxxx") // 你原代码中使用的location ID .build() Terminal.initTerminal( applicationContext, terminalConfig, object : ConnectionTokenProvider { override fun fetchConnectionToken(callback: ConnectionTokenCallback) { // 此处需调用你的后端接口获取Stripe Connection Token // 示例伪代码: // apiService.getStripeConnectionToken() // .enqueue(object : Callback<ConnectionTokenResp> { // override fun onResponse(call: Call<ConnectionTokenResp>, resp: Response<ConnectionTokenResp>) { // resp.body()?.token?.let { callback.onSuccess(it) } // ?: callback.onFailure(Exception("获取Token失败")) // } // override fun onFailure(call: Call<ConnectionTokenResp>, t: Throwable) { // callback.onFailure(t) // } // }) } }, object : InitCallback { override fun onSuccess() { // 初始化成功后再启动设备发现 onDiscoverReaders() } override fun onFailure(e: TerminalException) { e.printStackTrace() // 处理初始化失败逻辑 } } ) } fun onDiscoverReaders() { val config = DiscoveryConfiguration( timeout = 0, discoveryMethod = DiscoveryMethod.LOCAL_MOBILE, isSimulated = false, location = "xxxxxxxxxxxxxxx" ) discoveryCancelable = Terminal.getInstance().discoverReaders(config, discoveryListener = object : DiscoveryListener { override fun onUpdateDiscoveredReaders(readers: List<Reader>) { // 处理发现的设备列表 } }, object : Callback { override fun onSuccess() { println("Finished discovering readers") } override fun onFailure(e: TerminalException) { e.printStackTrace() } } ) } override fun onDestroy() { super.onDestroy() // 取消发现任务,避免内存泄漏 discoveryCancelable?.cancel() } }
关键注意事项
- Connection Token获取:必须通过后端服务获取,不能在客户端直接生成或硬编码,这是Stripe的安全要求。
- 初始化时机:若多个页面需使用Terminal,建议在Application类的
onCreate()中完成全局初始化,避免重复操作。 - 权限配置:确保应用已添加Terminal所需权限(如蓝牙、位置权限等,根据使用的发现方法调整)。
内容的提问来源于stack exchange,提问作者Ajith
相关产品推荐
相关产品推荐

