batmaci batmaci - 3 years ago 256
Android Question

How to display Splash screen on OnAppLinkRequestReceived in Xamarin.Forms- Android

I have implemented splash screen as below
I have a splash activity as main launcher which starts MainActivity

[Activity(Theme = "@style/MyTheme.Splash",
MainLauncher = true,
Immersive = true,
ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait,
NoHistory = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class SplashActivity : AppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);

var intent = new Intent(this, typeof(MainActivity));
StartActivity(intent);
}

}


and in my onstart of mainactivity, I register all applinks and having intentfilters as shown below.

[Activity(Label = "myapp",
Icon = "@drawable/icon",
Theme = "@style/MyTheme",
MainLauncher = false,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
[IntentFilter(new[] { Intent.ActionView },
Categories = new[] {
Intent.ActionView,
Intent.CategoryDefault,
Intent.CategoryBrowsable
},
DataScheme = "http",
DataHost = "myapp.azurewebsites.net",
DataPathPrefix = "/app/", AutoVerify = true)
]
[IntentFilter(new[] { Intent.ActionView },
Categories = new[] {
Intent.ActionView,
Intent.CategoryDefault,
Intent.CategoryBrowsable
},
DataScheme = "https",
DataHost = "myapp.azurewebsites.net",
DataPathPrefix = "/app/", AutoVerify = true)
]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{

// TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;

base.OnCreate(bundle);


global::Xamarin.Forms.Forms.Init(this, bundle);
AndroidAppLinks.Init(this);

LoadApplication(new App());


}


So far good, everything works when I click a link, it redirects to my app and hits OnAppLinkRequestReceived in App.Xaml.cs of forms application.

protected override async void OnAppLinkRequestReceived(Uri uri)
{
// read link and redirect to a page
}


Only problem here is that after clicking the link user sees a white screen instead of splash screen. I understand the problem because intentfilters are on mainactivity and splashactivity is never called. I moved intentfilters like below on splash activity,
this time clicking on a link shows splash screen but OnAppLinkRequestReceived function is never called. Does anybody knows how can I achieve this?

[Activity(Theme = "@style/MyTheme.Splash",
MainLauncher = true,
Immersive = true,
ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait,
NoHistory = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
[IntentFilter(new[] { Intent.ActionView },
Categories = new[] {
Intent.ActionView,
Intent.CategoryDefault,
Intent.CategoryBrowsable
},
DataScheme = "http",
DataHost = "myapp.azurewebsites.net",
DataPathPrefix = "/app/", AutoVerify = true)
]
[IntentFilter(new[] { Intent.ActionView },
Categories = new[] {
Intent.ActionView,
Intent.CategoryDefault,
Intent.CategoryBrowsable
},
DataScheme = "https",
DataHost = "myapp.azurewebsites.net",
DataPathPrefix = "/app/", AutoVerify = true)
]
public class SplashActivity : AppCompatActivity

Answer Source

Only problem here is that after clicking the link user sees a white screen instead of splash screen. I understand the problem because intentfilters are on mainactivity and splashactivity is never called. I moved intentfilters like below on splash activity, this time clicking on a link shows splash screen but OnAppLinkRequestReceived function is never called. Does anybody knows how can I achieve this?

Looking into the Xamarin.Forms Source Codes. You can find out that the calling chain of OnAppLinkRequestReceived is like this:

FormsAppCompatActivity.LoadApplication ->
FormsAppCompatActivity.CheckForAppLink(Intent) ->
Xamarin.Forms.Application.SendOnAppLinkRequestReceived(Uri) ->
Xamarin.Forms.Application.OnAppLinkRequestReceived(Uri).

And in CheckForAppLink(Intent), Xamarin.Forms do the following checks:

void CheckForAppLink(Intent intent)
{
    string action = intent.Action;
    string strLink = intent.DataString;
    if (Intent.ActionView != action || string.IsNullOrWhiteSpace(strLink))
            return;

    var link = new Uri(strLink);
    _application?.SendOnAppLinkRequestReceived(link);
}

So, if you pass the Intent from your SplashActivity to MainActivity without Action and Data, SendOnAppLinkRequestReceived will never get called, thus OnAppLinkRequestReceived won't be called.

To fix the problem, you can add Action and Data manually to the intent in SplashActivity's OnCreate:

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

    string action = Intent.Action;
    string strLink = Intent.DataString;
    Intent intent = new Intent(Application.Context, typeof(MainActivity));
    if (Android.Content.Intent.ActionView == action && !string.IsNullOrWhiteSpace(strLink))
    {
        intent.SetAction(Intent.ActionView);
        intent.SetData(Intent.Data);
    }
    StartActivity(intent);
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download