android - Xamarin Android:使用 StartActivityForResult(); OnActivityResult 中的 resultCode 始终为“已取消”
问题描述
我有两个使用 Xamarin.Android 编写的独立应用程序;为了便于讨论,我们称他们为“Tristan”和“Isolde”。Tristan 有一些 Isolde 有时需要知道的状态信息。并发症:特里斯坦可能会也可能不会在伊索尔德开始需要了解他的状态时跑步。
我现在有 kludge 工作,Isolde 向 Tristan 发送一个特殊的发射意图,然后 Tristan 使用广播意图将信息发送回 Isolde。(有关详细信息,请参阅我之前的问题。)
“可是等等!” 我听到你哭了,“这不是一个完美的用例StartActivityForResult()
吗?” 它的确是!代码要简单得多,我读过的所有内容都暗示这就是 Android 希望你做这样的事情的方式。
不幸的是,我无法让它工作(尽管尝试了许多变体并阅读了这个网站上的十几个相关问题)。我的具体问题是,在 Isolde 的OnActivityResult()
回调中,resultCode
is alwaysResult.Canceled
和 the data
is always null
。
这是 Tristan 的代码(其中注释掉的位代表我尝试过的变体):
using Android.App;
using Android.Content;
namespace com.example.Tristan.Android
{
[Activity(Name ="com.example.Tristan.Android.IsoldeQueryActivity")]
public class IsoldeQueryActivity : Activity
{
protected override void OnStart()
{
// base.OnStart();
var rtn = new Intent();
rtn.PutExtra("Test", "test");
//rtn.SetAction("TestAction");
SetResult(Result.Ok, rtn);
Finish();
//FinishActivity(1234);
}
}
}
这是Activity
Isolde 需要询问 Tristan 状态的相关代码:
private TaskCompletionSource<bool> TristanStateCompletion;
public async Task GetTristanState()
{
TristanStateCompletion = new TaskCompletionSource<bool>();
var req = new Intent("com.example.Tristan.Android.IsoldeQueryActivity");
//req.PutExtra(Intent.ExtraReturnResult, true);
StartActivityForResult(req, 1234);
var rtn = await TristanStateCompletion.Task;
if (!rtn) bomb("can't get state");
TristanStateCompletion = null;
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if(requestCode == 1234) {
DoStuffWith(data);
TristanStateCompletion?.TrySetResult(true);
}
}
诊断 - 或者更确切地说,缺乏诊断 - 让我相信 TristanIsoldeQueryActivity.OnStart()
从未真正被调用过。
欢迎提出想法、要求提供更多信息和/或尝试有用的实验。(如果您的想法是“将 <thing> 放入清单中”,请记住这是 Xamarin.Android,我必须通过将 <relatedThing> 放入装饰 . 的属性中来做到这一点Activity
。)
编辑添加:在 Isolde 的代码中,DoStuffWith(data)
因为data
是null
. 当我更改该方法以避免这种情况时,我发现我收到了一个(稍晚一点的)异常StartActivityForResult()
:
Android.Content.ActivityNotFoundException No Activity found to handle Intent { act=com.example.Tristan.Android.IsoldeQueryActivity }
这让我相信我没有Intent
在 Isolde 中正确创建。我需要使用其他Intent
构造函数之一吗?如果有,具体如何?
解决方案
好吧,我想我已经弄清楚了。我最初的问题中的代码存在三个主要问题:
Intent
我在 Isolde中构建错误。- 我没有
IsoldeQueryActivity
在特里斯坦出口。 base.OnStart()
在 Tristan 的覆盖中调用OnStart
是强制性的。
这是特里斯坦的工作版本:
using Android.App;
using Android.Content;
namespace com.example.Tristan.Android
{
[Activity(Name ="com.example.Tristan.Android.IsoldeQueryActivity", Exported=true)]
public class IsoldeQueryActivity : Activity
{
protected override void OnStart()
{
base.OnStart();
var rtn = new Intent();
rtn.PutExtra("Test", "test");
SetResult(Result.Ok, rtn);
Finish();
}
}
}
这是来自 Isolde 的固定代码:
private TaskCompletionSource<bool> TristanStateCompletion;
public async Task GetTristanState()
{
TristanStateCompletion = new TaskCompletionSource<bool>();
var req = new Intent();
req.SetComponent(new ComponentName("com.example.Tristan.Android", "com.example.Tristan.Android.IsoldeQueryActivity"));
StartActivityForResult(req, 1234);
var rtn = await TristanStateCompletion.Task;
if (!rtn) bomb("can't get state");
TristanStateCompletion = null;
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if(requestCode == 1234) {
if(resultCode != Result.Ok) bomb("bad resultCode {0}", resultCode);
if(data == null) bomb("null data from Tristan");
DoStuffWith(data);
TristanStateCompletion?.TrySetResult(true);
}
}
推荐阅读
- c# - 单元测试异步方法在方法完成之前测试断言
- javascript - 创建交错选择框
- asn1 - 无法使用 asn1 编译器生成所需的数据结构
- firebase - * Firebase/BigQuery 中的活跃用户差异*
- c++ - 如何将代码点转换为 utf-8?
- python - 如何使用其 REST API 在 Jupyter Hub 中启动笔记本服务器?
- c# - 如何在 C# 中使用 Selenium 发送密钥“和”?
- java - 如何使导航抽屉中的开关具有功能?
- linux-device-driver - 如何使设备(以太网)使用特定的驱动程序(用户制作的网络驱动程序)
- excel - 为什么分配给单元的宏会失败?