Android 似乎忽略了我对 onActivityResult 的 setResult 调用
Android seems to be ignoring my setResult call for onActivityResult
我有 2 个应用程序,一个是非常简单的玩具应用程序,可以调用另一个:
const val AUTHENTICATE_CODE = 42
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
fab.setOnClickListener {
Intent(Intent.ACTION_VIEW, Uri.parse("testapp://hello.world/")) //2nd app has intent filter to intercept this.
.also { intent -> startActivityForResult(intent, AUTHENTICATE_CODE) }
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val textView = findViewById<TextView>(R.id.hello_text)
if (requestCode == AUTHENTICATE_CODE && resultCode == Activity.RESULT_OK) {
requireNotNull(data) {
textView.text = "Error: Intent was null. Data lost."
return@onActivityResult
}
val dataExtra = data.getStringExtra("com.example.app.DATA")
requireNotNull(dataExtra){
textView.text = "Error: Intent did not contain data."
return@onActivityResult
}
Log.d("TestAppPlsIgnore", "Result Intent received")
textView.text = "Success! $dataExtra"
} else {
textView.text = "Something went wrong. Request = $requestCode; Result = $resultCode"
}
}
//...
}
另一个应用程序涉及更多:
- 玩具应用程序启动的应用程序 2 中的 activity 实现了来自 Jetpack 的导航库。
- activity 的导航图中的大部分片段都实现了相同的 ViewModel。即
private val mainViewModel by activityViewModels<MainActivityViewModel>()
在 MainActivityViewModel
里面是一个 LiveData<String>
,我们称之为 data
。 app 2的MainActivity有一个observer watching 类似这样的数据:
val dataObserver = Observer<String> { data ->
val result = Intent()
result.putExtra("com.example.app.DATA", data)
Log.d("MainActivity.DataObserver", "Sending data $data")
setResult(Activity.RESULT_OK, result)
finish()
}
mainViewModel.data.observe(this, dataObserver)
- 在到达将字符串放入
data
的一般流程中,主 activity 的导航视图可能会在一个或多个片段之间导航。
预期结果:在app 2中data
添加字符串时,观察者会创建结果意图,设置为结果,完成app 2. App 1会收到结果并调用onActivityResult,我们应该显示"Success!"加上一些数据。
我得到的结果:观察者确实有效。日志语句显示观察者收到了正确的数据。应用程序 2 完成。 app 1 的 onActivityResult 显示失败案例,显示正确的请求代码,但响应代码 == Activity.RESULT_CANCELLED。如果 requireNotNull(data)
语句移到 if
语句之外,应用程序 1 将改为显示意图 returned 为空。
我的问题:
- RESULT_CANCELLED 未明确 returned,我正尝试 return 数据意图。所以这应该只会让 activity 崩溃成为 RESULT_CANCELLED 被 returned 的原因。在导航图中导航将不可避免地导致一些片段到达其生命周期的终点。 Android 会将其与 activity 崩溃混淆吗?
- 为什么在调用onActivityResult 时有一个null intent?在大多数情况下,我只是遵循 outlined in the documentation 的内容,如果更冗长的话。
- 这不是在两个特定应用程序之间发送简单字符串的正确方法吗?我不想使用共享意图,因为这意味着特定应用程序之间更直接的通信,而不是我的应用程序与应用程序类别之间的广泛通信。
事实证明,如果您打算使用像我这样的基于观察者的设置通过 startActivityForResult()
发送数据,那么您不应该在应用程序的其他地方调用 finishAfterTransition()
。 finishAfterTransition()
会导致与对 finish()
的任何调用发生冲突,您将发送空结果和 RESULT_CANCELLED.
的 ResultCode
我有 2 个应用程序,一个是非常简单的玩具应用程序,可以调用另一个:
const val AUTHENTICATE_CODE = 42
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
fab.setOnClickListener {
Intent(Intent.ACTION_VIEW, Uri.parse("testapp://hello.world/")) //2nd app has intent filter to intercept this.
.also { intent -> startActivityForResult(intent, AUTHENTICATE_CODE) }
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val textView = findViewById<TextView>(R.id.hello_text)
if (requestCode == AUTHENTICATE_CODE && resultCode == Activity.RESULT_OK) {
requireNotNull(data) {
textView.text = "Error: Intent was null. Data lost."
return@onActivityResult
}
val dataExtra = data.getStringExtra("com.example.app.DATA")
requireNotNull(dataExtra){
textView.text = "Error: Intent did not contain data."
return@onActivityResult
}
Log.d("TestAppPlsIgnore", "Result Intent received")
textView.text = "Success! $dataExtra"
} else {
textView.text = "Something went wrong. Request = $requestCode; Result = $resultCode"
}
}
//...
}
另一个应用程序涉及更多:
- 玩具应用程序启动的应用程序 2 中的 activity 实现了来自 Jetpack 的导航库。
- activity 的导航图中的大部分片段都实现了相同的 ViewModel。即
private val mainViewModel by activityViewModels<MainActivityViewModel>()
在
MainActivityViewModel
里面是一个LiveData<String>
,我们称之为data
。 app 2的MainActivity有一个observer watching 类似这样的数据:val dataObserver = Observer<String> { data -> val result = Intent() result.putExtra("com.example.app.DATA", data) Log.d("MainActivity.DataObserver", "Sending data $data") setResult(Activity.RESULT_OK, result) finish() } mainViewModel.data.observe(this, dataObserver)
- 在到达将字符串放入
data
的一般流程中,主 activity 的导航视图可能会在一个或多个片段之间导航。
预期结果:在app 2中data
添加字符串时,观察者会创建结果意图,设置为结果,完成app 2. App 1会收到结果并调用onActivityResult,我们应该显示"Success!"加上一些数据。
我得到的结果:观察者确实有效。日志语句显示观察者收到了正确的数据。应用程序 2 完成。 app 1 的 onActivityResult 显示失败案例,显示正确的请求代码,但响应代码 == Activity.RESULT_CANCELLED。如果 requireNotNull(data)
语句移到 if
语句之外,应用程序 1 将改为显示意图 returned 为空。
我的问题:
- RESULT_CANCELLED 未明确 returned,我正尝试 return 数据意图。所以这应该只会让 activity 崩溃成为 RESULT_CANCELLED 被 returned 的原因。在导航图中导航将不可避免地导致一些片段到达其生命周期的终点。 Android 会将其与 activity 崩溃混淆吗?
- 为什么在调用onActivityResult 时有一个null intent?在大多数情况下,我只是遵循 outlined in the documentation 的内容,如果更冗长的话。
- 这不是在两个特定应用程序之间发送简单字符串的正确方法吗?我不想使用共享意图,因为这意味着特定应用程序之间更直接的通信,而不是我的应用程序与应用程序类别之间的广泛通信。
事实证明,如果您打算使用像我这样的基于观察者的设置通过 startActivityForResult()
发送数据,那么您不应该在应用程序的其他地方调用 finishAfterTransition()
。 finishAfterTransition()
会导致与对 finish()
的任何调用发生冲突,您将发送空结果和 RESULT_CANCELLED.