App-Callback-Mark
App 之间回调是常有的事, 特别是一些提供第三方登录/第三方支付的 App, 更是需要提供调起, 登录/支付, 回调原 App 的功能. 在实现的过程中遇到一些问题, 所以记录一下.
接下来调起界面称为 CallActivity
, 调起 App 称为 Call App
, 被调起页面称为 PayActivity
. 被调起 App 称为 Pay App
.
常见方案: startActivityForResult
最常见的当然是 通过 startActivityForResult()
使用隐式 Intent 调起, 然后在 onActivityResult()
中捕捉回调并处理成功失败逻辑了. 这种方法大部分人都会, 说点遇到的问题吧:
问题来了
- 问题一:
- 打开
Pay Activity
后可以切到后台, 再切回来, 这样做一方面安全性不够, 另一方面不符合支付工具的特性. 第三方应用调起支付应用后, 对用户的感觉不应该是完整的打开了一个应用, 而应该是仅仅启动了支付的一个功能, 切到后台后应该无法再切回该支付页面, 最近打开的应用页面也不该展示 Pay App. - 在
AndroidManifest.xml
中加上android:excludeFromRecents="true"
- 打开
- 问题二:
- 支付成功后, 按 Home 键切到后台, 再切回
Call App
, 这时候没有触发onActivityResult()
- 这是系统问题, 正常逻辑, 只能在
onResume()
里面查询后台是否成功.
- 支付成功后, 按 Home 键切到后台, 再切回
- 问题三:
- 如果已经打开了
Pay App
, 然后切到后台, 打开到Call App
, 调起Pay Activity
后按返回键, 返回到Pay App
的界面了. - 需要指定
PayActivity
的 luanchMode 为singleInstance
- 如果已经打开了
- 问题一:
大坑来了
坑就在于这个
singleInstance
, 在 Android 5.0 上一切正常, 但是在 Android 4.4 及以下版本,Call Activity
调用startActivityForResult()
后, 直接回调了onActivityResult()
, 然后才打开Pay Activity
.为此我记录了一下不同 luanchMode 对 Android 4.4 及以下版本回调的影响.
正常回调 -> Y
直接回调 -> N
| Call Activity | Standard | SingleTop | SingleTask | SingleInstance :---: | :---: | :---: | :---: | :---: | :---: Pay Activity | Standard | | Y | Y | Y | N SingleTop | | Y | Y | Y | N SingleTask | | N | N | N | N SingleInstance | | N | N | N | N
startActivityForResult 方案不可行
对于
startActivityForResult()
来说, 想实现对 singleInstance 的回调是不可能了, 同时还有问题二也需要优化, 所以最好还是换个方案来执行.
透明中间页 + 广播方案
之前版本由于已经发布, 需要兼容旧版本, 同时为了优化问题二, 考虑在接入 sdk 中提供一个中间页面 Entry Activity
. 另外对于 singleInstance 的问题, 考虑用广播来替代.
Call Activity
-> Entry Activity
-> Pay Activity
各页面功能如下:
Call Activity
依旧执行 startActivityForResult 方法, sdk 内部直接调起
Pay Activity
改为调起透明Entry Activity
.在 onActivityResult 中处理回调逻辑.
Entry Activity
设置 theme 为透明, 同时取消进入和退出的动画. 设置 luanchMode 为 singleTop
注册广播, 监听
Pay Activity
发来的支付成功的广播直接通过
startActivity
调起PayActivity
在第二次进入
onResume()
时判断是否收到了支付成功的广播, 否则当做支付失败处理.成功及支付都通过
setResult()
的方式回调Pay Activity
支付成功使用广播通知.