Backgrounded jobs not working with Shiny library in a simple Xamarin Forms project [duplicate] - xamarin

This question already has answers here:
How to extend application class in xamarin android
(2 answers)
Closed 3 years ago.
I am trying to implement the very promising Shiny library (for background jobs) from Allan Ritchie. I have only tried this in a simple File/New Project for Android thus far (haven't implemented the code for iOS or UWP), but I am not able to get it to run.
I am following the article https://allancritchie.net/posts/shinyjobs. However, when I run I get the following exception...
And I never hit this breakpoint...
My code can be cloned from https://github.com/JohnLivermore/SampleXamarinApp.git
But here it is inline as well...
App.xaml.cs
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
protected override async void OnStart()
{
var job = new JobInfo
{
Identifier = "YourFirstJob",
Type = typeof(YourFirstJob),
// these are criteria that must be met in order for your job to run
BatteryNotLow = false,
DeviceCharging = false,
RequiredInternetAccess = InternetAccess.Any,
Repeat = true //defaults to true, set to false to run once OR set it inside a job to cancel further execution
};
// lastly, schedule it to go - don't worry about scheduling something more than once, we just update if your job name matches an existing one
await ShinyHost.Resolve<Shiny.Jobs.IJobManager>().Schedule(job);
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
}
Startup.cs
public class Startup : ShinyStartup
{
public override void ConfigureServices(IServiceCollection services)
{
}
}
YourFirstJob.cs
public class YourFirstJob : IJob
{
public YourFirstJob()
{
}
public async Task<bool> Run(JobInfo jobInfo, CancellationToken cancelToken)
{
//await this.dependency.SomeAsyncMethod(id);
return true; // this is for iOS - try not to lie about this - return true when you actually do receive new data from the remote method
}
}
MainActivity.cs
[Activity(Label = "SampleApp", Icon = "#mipmap/icon", Theme = "#style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
Shiny.AndroidShinyHost.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
MainApplication.cs
[Application]
public class MainApplication : Application
{
public override void OnCreate()
{
base.OnCreate();
Shiny.AndroidShinyHost.Init(this, new SampleApp.Startup());
}
}
Any help would be greatly appreciated!

You might want to add following constructor to your MainApplication class.
public MainApplication(IntPtr handle, JniHandleOwnership ownerShip) : base(handle, ownerShip)
{
}

Related

Playing a standard/system sound on phone xamarin forms

Is there a standard cross platform way of playing a 250 ms or so 'ding' on Xamarin Forms iOS and Android?
Mark Wardell
You can use DependencyService to play default system notification sound in each platform .
Create IPlaySoundService Interface :
public interface IPlaySoundService
{
void PlaySystemSound();
}
Implement the PlaySystemSound method in iOS as follow:
[assembly: Xamarin.Forms.Dependency(typeof(PlaySoundService))]
namespace AppCarouselViewSample.iOS
{
public class PlaySoundService : IPlaySoundService
{
public void PlaySystemSound()
{
var sound = new SystemSound(1000);
sound.PlaySystemSound();
}
}
}
Implement the PlaySystemSound method in Android as follow :
[assembly:Xamarin.Forms.Dependency(typeof(PlaySoundService))]
namespace AppCarouselViewSample.Droid
{
public class PlaySoundService : IPlaySoundService
{
public void PlaySystemSound()
{
Android.Net.Uri uri = RingtoneManager.GetDefaultUri(RingtoneType.Ringtone);
Ringtone rt = RingtoneManager.GetRingtone(MainActivity.instance.ApplicationContext, uri);
rt.Play();
}
}
}
This is the definition of instance from MainActivity :
namespace xxx.Droid
{
[Activity(Label = "AppCarouselViewSample", Icon = "#mipmap/icon", Theme = "#style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static MainActivity instance { set; get; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
instance = this;
Xamarin.Forms.Forms.SetFlags(new string[] { "CarouselView_Experimental", "SwipeView_Experimental", "IndicatorView_Experimental" });
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
...
}
Then it they will play the default notification Sound in each platform . You can modify SystemSoundID in iOS to fit your wants .Here is the Sound ID list .
here is my now compiling yet crashing Droid implementation
using Android.Media;
using TripCalculator.Droid.Services;
[assembly: Xamarin.Forms.Dependency(typeof(PlaySoundService))]
// Crashes
namespace TripCalculator.Droid.Services
{
public class PlaySoundService : IPlaySoundService
{
public void PlaySystemSound()
{
var currentContext = Android.App.Application.Context;
Android.Net.Uri uri = RingtoneManager.GetDefaultUri(RingtoneType.Ringtone);
Ringtone rt = RingtoneManager.GetRingtone(currentContext.ApplicationContext, uri);
rt.Play();
}
}
}

How to migrate MVVMCross based Xamarin.android project into Intune managed one

I have a android project running smoothly, it uses MVVMCross at its core.
The problem came when I was asked manage the app protection policies with Intune.
Now Intune is forcing me to use their managed activity and all other managed namespaces provided by Intune SDK.
In that case, how I can proceed with it?
I tried changing activities base class to Intune's one, in hope to use general things provided by Mvvmcross, such as IOC, dependency injections.
I customised App startup as Intune wants that means there will not be any setup/app.cs class calls involvement.
So I launch Splash activity -> and it launches MainActivity, in MainActivity I am manually injecting all the Dependencies which I require.
Because all these syntaxes are throwing exception under Intune managed activities
example: Mvx.RegisterType<IDeviceInformation, DeviceInformation>();
Above throws exception.
How do I proceed with this migration keeping MVVMcross basic functionality intact?
There is a couple of solutions to that matter that I can think of.
If you only need the DI you can add another DI manager package and handle it from there which will be simpler than configuring Mvx to do that only.
If you need other capabilities of Mvx then you will have to do what Mvx does in its base classes and implement them taking into consideration setting the appropiate interfaces to your base classes.
In Android, in order to get the Setup and Activities working you'll have to:
Register your setup in your android Application file as done here
this.RegisterSetupType<TMvxAndroidSetup>();
Implement your own base activity that takes into consideration the implementation of IMvxEventSourceActivity such as here and also the MvxActivity like here in order to have the events and the data context / viewmodel handling
[Register("mvvmcross.platforms.android.views.base.MvxEventSourceActivity")]
public abstract class MvxEventSourceActivity
: Activity, IMvxEventSourceActivity
{
protected MvxEventSourceActivity()
{
}
protected MvxEventSourceActivity(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
protected override void OnCreate(Bundle bundle)
{
CreateWillBeCalled.Raise(this, bundle);
base.OnCreate(bundle);
CreateCalled.Raise(this, bundle);
}
protected override void OnDestroy()
{
DestroyCalled.Raise(this);
base.OnDestroy();
}
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
NewIntentCalled.Raise(this, intent);
}
protected override void OnResume()
{
base.OnResume();
ResumeCalled.Raise(this);
}
protected override void OnPause()
{
PauseCalled.Raise(this);
base.OnPause();
}
protected override void OnStart()
{
base.OnStart();
StartCalled.Raise(this);
}
protected override void OnRestart()
{
base.OnRestart();
RestartCalled.Raise(this);
}
protected override void OnStop()
{
StopCalled.Raise(this);
base.OnStop();
}
public override void StartActivityForResult(Intent intent, int requestCode)
{
StartActivityForResultCalled.Raise(this, new MvxStartActivityForResultParameters(intent, requestCode));
base.StartActivityForResult(intent, requestCode);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
ActivityResultCalled.Raise(this, new MvxActivityResultParameters(requestCode, resultCode, data));
base.OnActivityResult(requestCode, resultCode, data);
}
protected override void OnSaveInstanceState(Bundle outState)
{
SaveInstanceStateCalled.Raise(this, outState);
base.OnSaveInstanceState(outState);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
DisposeCalled.Raise(this);
}
base.Dispose(disposing);
}
public event EventHandler DisposeCalled;
public event EventHandler<MvxValueEventArgs<Bundle>> CreateWillBeCalled;
public event EventHandler<MvxValueEventArgs<Bundle>> CreateCalled;
public event EventHandler DestroyCalled;
public event EventHandler<MvxValueEventArgs<Intent>> NewIntentCalled;
public event EventHandler ResumeCalled;
public event EventHandler PauseCalled;
public event EventHandler StartCalled;
public event EventHandler RestartCalled;
public event EventHandler StopCalled;
public event EventHandler<MvxValueEventArgs<Bundle>> SaveInstanceStateCalled;
public event EventHandler<MvxValueEventArgs<MvxStartActivityForResultParameters>> StartActivityForResultCalled;
public event EventHandler<MvxValueEventArgs<MvxActivityResultParameters>> ActivityResultCalled;
}
[Register("mvvmcross.platforms.android.views.MvxActivity")]
public abstract class MvxActivity
: MvxEventSourceActivity
, IMvxAndroidView
{
protected View _view;
protected MvxActivity(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
protected MvxActivity()
{
BindingContext = new MvxAndroidBindingContext(this, this);
this.AddEventListeners();
}
public object DataContext
{
get { return BindingContext.DataContext; }
set { BindingContext.DataContext = value; }
}
public IMvxViewModel ViewModel
{
get
{
return DataContext as IMvxViewModel;
}
set
{
DataContext = value;
OnViewModelSet();
}
}
public void MvxInternalStartActivityForResult(Intent intent, int requestCode)
{
StartActivityForResult(intent, requestCode);
}
public IMvxBindingContext BindingContext { get; set; }
public override void SetContentView(int layoutResId)
{
_view = this.BindingInflate(layoutResId, null);
SetContentView(_view);
}
protected virtual void OnViewModelSet()
{
}
protected override void AttachBaseContext(Context #base)
{
if (this is IMvxSetupMonitor)
{
// Do not attach our inflater to splash screens.
base.AttachBaseContext(#base);
return;
}
base.AttachBaseContext(MvxContextWrapper.Wrap(#base, this));
}
private readonly List<WeakReference<Fragment>> _fragList = new List<WeakReference<Fragment>>();
public override void OnAttachFragment(Fragment fragment)
{
base.OnAttachFragment(fragment);
_fragList.Add(new WeakReference<Fragment>(fragment));
}
public List<Fragment> Fragments
{
get
{
var fragments = new List<Fragment>();
foreach (var weakReference in _fragList)
{
if (weakReference.TryGetTarget(out Fragment f))
{
if (f.IsVisible)
fragments.Add(f);
}
}
return fragments;
}
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
ViewModel?.ViewCreated();
}
protected override void OnDestroy()
{
base.OnDestroy();
ViewModel?.ViewDestroy(IsFinishing);
}
protected override void OnStart()
{
base.OnStart();
ViewModel?.ViewAppearing();
}
protected override void OnResume()
{
base.OnResume();
ViewModel?.ViewAppeared();
}
protected override void OnPause()
{
base.OnPause();
ViewModel?.ViewDisappearing();
}
protected override void OnStop()
{
base.OnStop();
ViewModel?.ViewDisappeared();
}
}
public abstract class MvxActivity<TViewModel>
: MvxActivity
, IMvxAndroidView<TViewModel> where TViewModel : class, IMvxViewModel
{
public new TViewModel ViewModel
{
get { return (TViewModel)base.ViewModel; }
set { base.ViewModel = value; }
}
}
Also you'll have to implement your own splash activity like here which implements the IMvxSetupMonitor and is the one who ends up calling the setup here by calling MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext); and initializing a monitor.
[Register("mvvmcross.platforms.android.views.MvxSplashScreenActivity")]
public abstract class MvxSplashScreenActivity
: MvxActivity, IMvxSetupMonitor
{
protected const int NoContent = 0;
private readonly int _resourceId;
private Bundle _bundle;
public new MvxNullViewModel ViewModel
{
get { return base.ViewModel as MvxNullViewModel; }
set { base.ViewModel = value; }
}
protected MvxSplashScreenActivity(int resourceId = NoContent)
{
RegisterSetup();
_resourceId = resourceId;
}
protected MvxSplashScreenActivity(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
protected virtual void RequestWindowFeatures()
{
RequestWindowFeature(WindowFeatures.NoTitle);
}
protected override void OnCreate(Bundle bundle)
{
RequestWindowFeatures();
_bundle = bundle;
var setup = MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext);
setup.InitializeAndMonitor(this);
base.OnCreate(bundle);
if (_resourceId != NoContent)
{
// Set our view from the "splash" layout resource
// Be careful to use non-binding inflation
var content = LayoutInflater.Inflate(_resourceId, null);
SetContentView(content);
}
}
private bool _isResumed;
protected override void OnResume()
{
base.OnResume();
_isResumed = true;
var setup = MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext);
setup.InitializeAndMonitor(this);
}
protected override void OnPause()
{
_isResumed = false;
var setup = MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext);
setup.CancelMonitor(this);
base.OnPause();
}
public virtual async Task InitializationComplete()
{
if (!_isResumed)
return;
await RunAppStartAsync(_bundle);
}
protected virtual async Task RunAppStartAsync(Bundle bundle)
{
if (Mvx.IoCProvider.TryResolve(out IMvxAppStart startup))
{
if(!startup.IsStarted)
{
await startup.StartAsync(GetAppStartHint(bundle));
}
else
{
Finish();
}
}
}
protected virtual object GetAppStartHint(object hint = null)
{
return hint;
}
protected virtual void RegisterSetup()
{
}
}
public abstract class MvxSplashScreenActivity<TMvxAndroidSetup, TApplication> : MvxSplashScreenActivity
where TMvxAndroidSetup : MvxAndroidSetup<TApplication>, new()
where TApplication : class, IMvxApplication, new()
{
protected MvxSplashScreenActivity(int resourceId = NoContent) : base(resourceId)
{
}
protected override void RegisterSetup()
{
this.RegisterSetupType<TMvxAndroidSetup>();
}
}
This will cover the basics I think.
Hope it helps you to get you to the right direction

Xamarin android - Attempt to invoke virtual method sendBroadcast() on a null object reference

I'm building a crossplatform application using Xamarin,my application will download videos from internet, I've done the download and save functions, but after saved videos to DCIM(in android) the videos do not appear in gallery.After hafl of a day searching for solutions on internet I comeup with two solutions:
1.after download finished: send broadcast with action "Intent.ActionMediaMounted".
2.after download finished Call "MediaScannerConnection.ScanFile".
With solution 1 I got:
"{Java.Lang.NullPointerException: Attempt to invoke virtual method 'void android.content.Context.sendBroadcast(android.content.Intent)' on a null object reference}
With solution 2, I got:
"{Java.Lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Context.bindService(android.content.Intent, android.content.ServiceConnection, int)' on a null object reference}
This is my Interface which I used to handle downloadfinished placed in PLC project:
namespace VideoDownloader
{
public interface IDownloadState
{
void OnDownloadStarted();
void OnDownloadError();
void OnDownloadFinished(string path);
}
}
This is my MainPage.xaml.cs in PLC project:
namespace VideoDownloader
{
public partial class MainPage : TabbedPage
{
public MainPage()
{
InitializeComponent();
}
public void downloadVideo(VideoInfor video, bool isRetried)
{
//download code here...
DependencyService.Get<IDownloadState()
.OnDownloadFinished(video.path);
}
}
}
And This is my MainActivity in Android project which implement IDownloadState and send broadcast when OnDownloadFinished fired:
[assembly: Xamarin.Forms.Dependency(typeof(MainActivity))]
namespace VideoDownloader.Droid
{
[Activity(Label = "VideoDownloader", Icon = "#mipmap/icon", Theme =
"#style/MainTheme", MainLauncher = true, ConfigurationChanges =
ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity :
global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,
IDownloadState
{
readonly string[] StoragePermissions =
{
Manifest.Permission.WriteExternalStorage,
Manifest.Permission.ReadExternalStorage
};
const int RequestStorageId = 0;
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
int sdkBuildVersion = (int)Build.VERSION.SdkInt;
Console.WriteLine("SDK build version = " + sdkBuildVersion);
if (sdkBuildVersion >= 23)
{
RequestStoragePermission();
}
}
public override void OnRequestPermissionsResult(int requestCode,
string[] permissions, Permission[] grantResults)
{
switch (requestCode)
{
case RequestStorageId:
{
if (grantResults[0] == Permission.Granted)
{
}
else
{
}
}
break;
default:
break;
}
}
public void OnDownloadStarted()
{
throw new NotImplementedException();
}
public void OnDownloadError()
{
throw new NotImplementedException();
}
public void OnDownloadFinished(string path)
{
//Intent intent = new Intent(Intent.ActionMediaMounted);
//SendBroadcast(intent);
//throw new NotImplementedException();
MediaScannerConnection.ScanFile(this, new String[] {
Android.OS.Environment
.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim)
.AbsolutePath }, null, null);
}
}
}
I know there are many many similar questions for android on stackoverflow that have ansered but they seem to not like my situation at all. So is there anyone know what am I doing wrong? Why this is happening?
With solution 2, I got:
"{Java.Lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Context.bindService(android.content.Intent, android.content.ServiceConnection, int)' on a null object reference}
Please try to use Forms.Context instead of this in OnDownloadFinished().
For example:
public void OnDownloadFinished(string path)
{
//Intent intent = new Intent(Intent.ActionMediaMounted);
//SendBroadcast(intent);
//throw new NotImplementedException();
MediaScannerConnection.ScanFile(Forms.Context, new String[] {
Android.OS.Environment
.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim)
.AbsolutePath }, null, null);
}

Xamarin, how to clear intentExtra after use

My app showing notification on specific time. Notification has got pending intent with note id. When user tapped on notification, this note id is use to launch app and load note with id that come from notification.
Basically it works fine but problem starts when user leave app using "back button". On next application start that note id is still in memory and app takes user to that note again.
How can I clear that intent from memory after first use.
MainActivity.cs
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static Context AndroidContext { get; private set; }
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
//noteId is a id of Note thet notification was dispaly and tapped by user
//Id is pass to xamarin PCL and proper note basic on this id is displayed
int noteId = Intent.GetIntExtra("noteId", 0);
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
CalligraphyConfig.InitDefault(new CalligraphyConfig.Builder()
.SetDefaultFontPath("Dosis-Regular.ttf")
.SetFontAttrId(Resource.Attribute.fontPath)
.Build()
);
AndroidContext = this;
global::Xamarin.Forms.Forms.Init(this, bundle);
Xamarin.FormsGoogleMaps.Init(this, bundle);
LoadApplication(new App(noteId));
}
protected override void AttachBaseContext(Context context)
{
base.AttachBaseContext(CalligraphyContextWrapper.Wrap(context));
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
BroadcastReciver
class AlamReciver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
int noteId = intent.GetIntExtra("id",0);
var noteTitle = intent.GetStringExtra("title");
var noteContent = intent.GetStringExtra("content");
var resultIntent = new Intent(context, typeof(MainActivity));
resultIntent.PutExtra("noteId", noteId);
resultIntent.SetFlags(ActivityFlags.ClearTop | ActivityFlags.ClearTask);
var PI = PendingIntent.GetActivity(context, noteId, resultIntent, PendingIntentFlags.OneShot);
var builder = new Notification.Builder(context)
.SetContentTitle(noteTitle)
.SetContentText(noteContent)
.SetSmallIcon(Resource.Drawable.ic_gnote_logo)
.SetPriority(1)
.SetAutoCancel(true)
.SetDefaults(NotificationDefaults.All)
.SetContentIntent(PI);
var notification = builder.Build();
var manager = NotificationManager.FromContext(context);
manager.Notify(noteId, notification);
}
}
Thank you.

Xamarin forms splash screen issue

A black screen with app title is showing when minimizing the app while loading splash screen , also the first screen will display after some time. Here is my splash activity and main activity classes.
[Activity(Theme = "#style/Theme.Splash", Icon = "#drawable/icon", MainLauncher = true, NoHistory = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
ScreenOrientation = ScreenOrientation.Behind)]
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var dpWidth = Resources.DisplayMetrics.WidthPixels/Resources.DisplayMetrics.Density;
RequestedOrientation = dpWidth > 700 ? ScreenOrientation.Unspecified : ScreenOrientation.Portrait;
ThreadPool.QueueUserWorkItem(o => LoadActivity());
}
private void LoadActivity()
{
RunOnUiThread(() => StartActivity(typeof(MainActivity)));
}
public override void OnBackPressed()
{
Environment.Exit(0);
}
}
[Activity(Label = "HACCP", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : FormsApplicationActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
ActionBar.SetIcon(Android.Resource.Color.Transparent);
Forms.Init(this, bundle);
// some function //
LoadApplication(new App());
}
}
You tagged Xamarin.Forms so it should be as simple as..
class App : Application
{
public App()
{
MainPage = new MySplashPage();
}
}
class MySplashPage : ContentPage
{
public MySplashPage()
{
Task.Delay(3000); //show my pretty splash for 3 seconds
Application.Current.MainPage = new MyOtherSpiffyPage();
}
}
Not certain if the activity attribute ScreenOrientation = ScreenOrientation.Behind) is causing any issues, we don't use that in our apps.
Here is a "standard" splash activity we do use, letting Xamarin.Android take care of timing etc:
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Start main.
StartActivity(typeof(MainActivity));
}
}
You might try simplifying your app in similar fashion.

Resources