0

I am trying to allow the users of my Xamarin.Android application to pick an image from their gallery and upload it to the server. The image, once picked, should first be shown in the upload form, and then converted into base64 and sent to the remote web application.

My app uses only one activity containing a FrameLayout, which gets filled with Fragments. The fragment that should handle the module (which is dynamic and depends on a schema it receives from the server) is instantiating the selection control like this:

private View BuildImageUploader()
{
    LinearLayout lay = new LinearLayout(Context);
    lay.Orientation = Orientation.Horizontal;
    lay.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
    (lay.LayoutParameters as LinearLayout.LayoutParams).SetMargins(0, 30, 0, 0);

    ImageView img = new ImageView(Context);
    var par = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent, 0.8f);
    par.Gravity = GravityFlags.Center;
    par.TopMargin = 5;          
    img.LayoutParameters = par;

    Button btn = new Button(Context);
    btn.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent, 0.2f);
    btn.Text = "Scegli";

    btn.Click += (s, e) =>
    {
        Intent intent = new Intent();
        intent.SetType("image/*");
        intent.SetAction(Intent.ActionGetContent);
        StartActivityForResult(Intent.CreateChooser(intent, "Scegli un'immagine"), 0);
    };

    lay.AddView(img);
    lay.AddView(btn);

    return lay;
}

I put the same override of OnActivityCreated in both my fragment and MainActivity:

protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
}

Yes, it does absolutely nothing and there is currently no way to get the image back, but I plan to handle that with events. The overrides are still empty because I'm testing them by putting breakpoints in them, to check which one gets called. And guess what? None. OnActivityResult is never called neither in the activity nor in the fragment. What am I doing wrong?

Extra info - what I tried so far (none worked):

  • Changing the request code (the second parameter of StartActivityForResult) to something different - I tried 1, -1 and some random 4 digits numbers as well
  • Moving the call to StartActivityForResult inside a method in class MainActivity
  • Changing the event handler lambda into an actual method

Finally, I would like to emphasize that the image picking phase works like a charm; I can see the gallery and select an image. The problem is that nothing happens after that: OnActivityResult isn't called, and I verified this with breakpoints. Thanks to whoever is willing to help, I need this for work and I'm quite desperate now, so I guess any solution will do.

EDIT: I was asked to include the code that handles the control drawing. I can't include it all (it's more than 1000 lines long and all the other controls work anyway), so I will show the part concerning this specific control:

private void ShowItem(LinearLayout container, DynamicFieldSchemaItem item)
{
    GuiControlType type = GuiControlType.GetGuiControlTypeById(item.SystemGuiControlId);
    List<View> toAdd = new List<View>();

    switch(type.Enum)
    {
        // Various cases for other controls...
        case GuiControlTypeEnum.UploadImage:
            toAdd.Add(BuildImageUploader());
            break;
    }

    foreach (View view in toAdd)
        container.AddView(view);
}

Here, container is used because the controls are divided in tabs, thus the application creates a separate LinearLayout for each of those tabs and then adds controls to it via ShowItem, called on every item received from the server.

UPDATE: while I was testing an unrelated functionality on a different device, I accidentally tapped on the uploader button, closed it, and the Activity's OnActivityResult breakpoint was toggled. This means that the problem is with my device. I have a OnePlus One with the stock LineageOS file browser and gallery. Could I solve this problem for my device somehow, in case anybody else is running the app with this setup?

neos7m
  • 11
  • 5
  • Does this android-java question answer your question? https://stackoverflow.com/questions/6147884/onactivityresult-is-not-being-called-in-fragment?s=1|262.7094 – k3b Jan 22 '18 at 15:16

1 Answers1

1

1) Start in Fragment, receive results in Activity: use Activity.StartActivityForResult()

2) Start in Fragment, receive results in Fragment: use StartActivityForResult(), and in the Activity's OnActivityResult() call base.OnActivityResult(requestCode, resultCode, data);


Base on the codes you provided, looks like you want to use 2), receive results in Fragment, so, please add OnActivityResult() in your fragment.

Robbit
  • 4,300
  • 1
  • 13
  • 29
  • I already have OnActivityResult() in my fragment. Like I said, it isn't called, nor is the activity's OnActivityResult (and thus there is no way it can forward the call to base, since it doesn't receive it in the first place). – neos7m Jan 23 '18 at 09:55
  • Can you show more codes? Because I am using axml file to get the layout in the fragment, not dynamic, and it works well. I think there is no different between dynamic and static, but I want to reproduce it, so, please show more codes. – Robbit Jan 23 '18 at 10:00
  • You can provide a demo, if it is possible, – Robbit Jan 23 '18 at 10:02
  • I edited my question to show the function calling the one I originally posted. Hope it's useful. – neos7m Jan 23 '18 at 15:16
  • Hi, you have said, it is your device problem, and by `I have a OnePlus One with the stock LineageOS file browser and gallery.`, can you explain it? What is OnePlus One? – Robbit Jan 24 '18 at 13:57
  • Seriously? What would you expect me to be talking about, washing machines? – neos7m Feb 05 '18 at 11:59