【问题标题】:Xamarin Android: using StartActivityForResult(); resultCode in OnActivityResult is always "Canceled"Xamarin Android:使用 StartActivityForResult(); OnActivityResult 中的 resultCode 始终为“已取消”
【发布时间】:2018-12-26 17:55:19
【问题描述】:

我有两个使用 Xamarin.Android 编写的独立应用程序;为了便于讨论,我们称他们为“Tristan”和“Isolde”。 Tristan 有一些 Isolde 有时需要知道的状态信息。并发症:特里斯坦可能会也可能不会在伊索尔德产生了解自己状态的需要时跑步。

我现在有 kludge 工作,Isolde 向 Tristan 发送一个特殊的发射意图,然后 Tristan 使用广播意图将信息发送回 Isolde。 (详情请见我的earlier question。)

“但是等等!”我听到你哭了,“这不是 StartActivityForResult() 的完美用例吗?”的确是!代码要简单得多,而且我读过的所有内容都暗示这就是 Android 希望你做这样的事情的方式。

不幸的是,我无法让它工作(尽管尝试了许多变体并阅读了这个网站上的十几个相关问题)。我的具体问题是,在 Isolde 的 OnActivityResult() 回调中,resultCode 始终为 Result.Canceleddata 始终为 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);
        }
    }

诊断 - 或者更确切地说,缺乏诊断 - 让我相信 Tristan 的 IsoldeQueryActivity.OnStart() 从未真正被调用过。

欢迎提出想法、要求提供更多信息和/或尝试有用的实验。 (如果您的想法是“将 放入清单中”,请记住这是 Xamarin.Android,我必须通过将 放入装饰 Activity 的属性中来做到这一点。)

编辑添加:在 Isolde 的代码中,DoStuffWith(data) 崩溃了,因为 datanull。当我更改该方法以避免这种情况时,我发现我在StartActivityForResult() 中抛出了一个(稍后)异常:

Android.Content.ActivityNotFoundException No Activity found to handle Intent { act=com.example.Tristan.Android.IsoldeQueryActivity }

这让我相信我没有在 Isolde 中正确创建 Intent。我是否需要使用其他 Intent 构造函数之一?如果有,具体如何?

【问题讨论】:

    标签: android xamarin android-intent xamarin.android


    【解决方案1】:

    好的,我想我已经弄清楚了。我最初问题中的代码存在三个主要问题:

    1. 我在 Isolde 中错误地构建了 Intent
    2. 我没有在特里斯坦导出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);
        }
    }
    

    【讨论】:

    • 非常感谢。经过大约 2 周的搜索和尝试不同的东西,我终于找到了你的问答。我没有在 Activity 属性和 requestCode 中使用 Name ="com.example.Tristan.Android.IsoldeQueryActivity", Exported=true),我也没有在任何地方看到 TaskCompletionSource。我正在使用 Xamarin Forms,因此我需要调整它以使用我的应用程序的共享代码,但我第一次返回 resultCode OK 并返回数据,这是一个很大的突破。
    猜你喜欢
    • 2018-04-08
    • 1970-01-01
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多