Xamarin Android:使用StartActivityForResult(); OnActivityResult中的resultCode始终为“Canceled”

3
我有两个使用Xamarin.Android编写的独立应用程序; 为了讨论,我们称它们为“Tristan”和“Isolde”。 Tristan具有一些状态信息,Isolde有时需要了解这些信息。复杂情况:当Isolde开发需要了解其状态时,Tristan可能正在运行,也可能没有运行。
我现在已经有一个解决方法,Isolde向Tristan发送特殊的启动意图,然后Tristan使用广播意图将信息发送回Isolde。(有关详细信息,请参见我的 早期问题。)
“但等等!” 我听到你大声喊道,“这不是StartActivityForResult()的完美用例吗?”确实是这样!代码要简单得多,我读过的所有内容都暗示着这就是Android希望您处理此类问题的方式。
不幸的是,我无法使其工作(尽管尝试了许多变化并阅读了这个网站上与此相关的十几个问题)。我的具体问题是,在Isolde的OnActivityResult()回调中,resultCode始终为Result.Canceled,而data始终为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);
        }
    }
}

以下是与 Isolde 需要查询 Tristan 状态相关的代码,位于 Activity 中:

    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);
        }
    }

诊断 -- 或者更确切地说,缺乏诊断 -- 让我相信 Tristan 的 IsoldeQueryActivity.OnStart() 实际上从未被调用。
欢迎提出想法、要求额外信息和/或有用的实验尝试。(如果你的想法是“在清单中放置<thing>”,请记住这是 Xamarin.Android,我必须通过将 <relatedThing> 放入修饰 Activity 的属性中来执行。)
编辑添加: 在 Isolde 的代码中,DoStuffWith(data) 崩溃了,因为 datanull。当我更改了该方法以避免这种情况时,我发现我在StartActivityForResult() 中抛出了一个(稍后)异常。
Android.Content.ActivityNotFoundException No Activity found to handle Intent { act=com.example.Tristan.Android.IsoldeQueryActivity }

这让我相信我在Isolde中没有正确创建Intent。我需要使用其他Intent构造函数吗?如果需要,具体应该如何操作?
1个回答

4

好的,我想我弄清楚了这个问题。我原始问题中的代码有三个主要问题:

  1. 我在Isolde中不正确地构建了Intent
  2. 我没有在Tristan中导出IsoldeQueryActivity
  3. 在Tristan的OnStart覆盖中调用base.OnStart()是必需的。

这里是Tristan的可工作版本:

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);
    }
}

非常感谢。 我终于在大约两周的搜索和尝试不同的东西后找到了你的问答。 我没有在Activity属性中使用Name ="com.example.Tristan.Android.IsoldeQueryActivity",Exported=true)也没有使用requestCode,也没有看到TaskCompletionSource出现在任何地方。我正在使用Xamarin Forms,所以我需要调整这个来适应我的应用程序的共享代码,但是我第一次收到了resultCode OK和返回的数据,这是一个很大的突破。 - sicko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接