Xamarin automatic sign-in credentials for Google Play's pre-launch report

别等时光非礼了梦想. 提交于 2021-02-07 03:04:22

问题


I am building an Android application with Xamarin Forms 3 in Visual Studio 2017 and publishing to Google Play. Google Play offers automated testing (pre-launch report) but it cannot get past my sign-in screen.

Google Play has a place to enter the "username resource name", "password resource name", and "sign-in button resource name". I provided the Xamarin x:name for each control (txtEmail, txtPass, and btnSignIn), but apparently that is not correct, because the automated tester still can't get in and isn't even trying.

Here is my SignIn.xaml:

<Entry x:Name="txtEmail" Placeholder="email address" Keyboard="Email" />
<Entry x:Name="txtPass" IsPassword="True" />
<Button x:Name="btnSignIn" Text="Sign In" Clicked="OnSignInClicked" />

I've found these SO questions (here, here, and here) but they do not address my question from within a Xamarin Forms context. The first link seems particularly helpful but I do not know where to put that XML code.

It seems to me that Xamarin/C# is "compiled" into Android code and generates these XML files. How can I work with this process?

I understand an .APK file is just a ZIP file. Renaming the APK file I send to Google Play to .zip I'm able to browse the contents, but I do not see any XML code that makes sense.

For the moment, I added an extra "demo" button that, on click, puts a username and password into the fields and clicks the Sign In button. Google's automated tester likes this and can get in, but it's a terrible idea for human testing and I'd like to remove this workaround.


回答1:


I've faced the same issue recently. I submitted an alpha build, enabled pre-launch report and got a policy violation error saying, that sign-in credentials are not provided. As it's stated in the question, I should have provided resource names along with the test credentials, but it wasn't obvious how to do it in Xamarin.Forms project. Nevertheless, I was able to workaround it using renderers. I know, it's a bit extreme to create a separate renderer and a control just to set id, but I really didn't want to change UI significantly, so, I created 3 empty controls:

public class UsernameEntry : Entry { }
public class PasswordEntry : Entry { }
public class LoginButton : Button { }

And used each of them in corresponding places on the login screen, instead of plain entries and the button.

Then I added ids.xml file into the Android project (Resource/values/ids.xml) and added 3 ids, one for every control:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <item name="username_entry" type="id"/>
  <item name="password_entry" type="id"/>
  <item name="login_button" type="id"/>
</resources>

Finally, I created 3 renderers in the native Android project, one for each control. For example, this is how the UsernameEntryRenderer looks:

[assembly: ExportRenderer(typeof(UsernameEntry), typeof(UsernameEntryRenderer))]
namespace Android.Renderers
{
    public class UsernameEntryRenderer : EntryRenderer
    {
        public UsernameEntryRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                // here I can reference the id created previously in ids.xml file
                // and set the native android id property
                Control.Id = Resource.Id.username_entry;
            }
        }
    }
}

This is not the perfect way, but it worked well in my case. I didn't need to change the UI drastically or to introduce some hidden UI elements. Hopefully, this will be helpful for anyone facing similar problem.




回答2:


Inspired by Yehor's answer, I was able to come up with a solution that uses Xamarin Effects without using custom controls.

First add ids.xml file into the Android project (Resource/values/ids.xml) and add 3 ids, one for every control. Make sure the Build action is set to AndroidResource and the Custom Tool is set to MSBuild:UpdateGeneratedFiles so the C# files can be generated automatically for the styles:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <item name="username_entry" type="id"/>
  <item name="password_entry" type="id"/>
  <item name="login_button" type="id"/>
</resources>

Then define an enum so the effects can be defined easily:

public enum CustomIdType
{
    None,
    Username,
    Password,
    LoginButton
}

For the Android custom renderer, implement the following assign the android ID based on the custom effects.

[assembly: ResolutionGroupName("CustomRendererHandler")]
[assembly: ExportEffect(typeof(AndroidCustomIdEffect), "CustomIdEffect")]
namespace YOUR_ANDROID_NAMESPACE
{
    public class AndroidCustomIdEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            // get autofill effect
            var effect = (CustomIdEffect)Element.Effects
                .FirstOrDefault(e => e is CustomIdEffect);

            // assign android ID if custom ID effect is not null
            if (effect != null) {
                switch (effect.Type) {
                    case CustomIdType.Username:
                        Control.Id = Resource.Id.username_entry;
                        break;
                    case CustomIdType.Password:
                        Control.Id = Resource.Id.password_entry;
                        break;
                    case CustomIdType.LoginButton:
                        Control.Id = Resource.Id.login_button;
                        break;
                }
            }
        }
        
        protected override void OnDetached()
        {
        }
    }
}

Then define a Routing Effect in your shared code to consume the Android custom renderer:

public class CustomIdEffect : RoutingEffect
{
    public CustomIdType Type { get; set; }

    public CustomIdEffect() : base("CustomRendererHandler." + nameof(CustomIdEffect))
    {
    }
}

Finally, to consume the Effects in your login page, simply add the Effects to the controls in XAML:

<Entry PlaceHolder="Enter Username">
    <Entry.Effects>
        <local:CustomIdEffect Type="Username"/>
    </Entry.Effects>
</Entry>

<Entry PlaceHolder="Enter Password">
    <Entry.Effects>
        <local:CustomIdEffect Type="Password"/>
    </Entry.Effects>
</Entry>

<Button Text="Login">
    <Button.Effects>
        <local:CustomIdEffect Type="LoginButton"/>
    </Button.Effects>
</Button>

After that Google Pre-launch Report should be able to get pass the login screen if you provide the right sign-in credentials.



来源:https://stackoverflow.com/questions/51985971/xamarin-automatic-sign-in-credentials-for-google-plays-pre-launch-report

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!