The new obsolete warning in Xamarin.Forms 2.5 really puzzled me. What context should I be using in Dependency Services, for example, to call GetSystemService()?
Shou
I was having the same issue with several Dependency Services
In a lot of cases for Single Activity Applications
Xamarin.Forms.Forms.Context
Can be replaced with
Android.App.Application.Context
Android.App.Application.Context
returns the global Application Context of the current process tied to the lifecycle of the Application, as apposed to an Activity context.
A typical example of using the Application context is for starting an Activity e.g.
Android.App.Application.Context.StartActivity(myIntent);
The general rule of thumb is to use the current Activity Context, unless you need to save a reference to a context from an object that lives beyond your Activity. In which case use the Application context
Xmarin.Forms 2.5 introduced a new "Forms embedding" feature, which can embed Forms pages into Xamarin.iOS / Xamarin.Android apps. However, since Xamarin.Android apps can use multiple Activities, seemingly there was a danger of Xamarin.Android
users calling Forms.Context
and in turn getting a reference to the MainActivity
, which has the potential cause problems.
Inside a Renderer you now get a reference to the view’s context which is passed into the constructor.
With any other class you are faced with the issue of how to get the Activity Context. In a single Activity application (in most cases) the Application.Context
will work just fine.
However to get the current Activity Context in a Multiple Activity Application you will need to hold a reference to it. The easiest and most reliable way to do this is via a class
that implements the Application.IActivityLifecycleCallbacks
Interface.
The main idea is to keep a reference of the Context when an Activity is created, started, or resumed.
[Application]
public partial class MainApplication : Application, Application.IActivityLifecycleCallbacks
{
internal static Context ActivityContext { get; private set; }
public MainApplication(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) { }
public override void OnCreate()
{
base.OnCreate();
RegisterActivityLifecycleCallbacks(this);
}
public override void OnTerminate()
{
base.OnTerminate();
UnregisterActivityLifecycleCallbacks(this);
}
public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
{
ActivityContext = activity;
}
public void OnActivityResumed(Activity activity)
{
ActivityContext = activity;
}
public void OnActivityStarted(Activity activity)
{
ActivityContext = activity;
}
public void OnActivityDestroyed(Activity activity) { }
public void OnActivityPaused(Activity activity) { }
public void OnActivitySaveInstanceState(Activity activity, Bundle outState) { }
public void OnActivityStopped(Activity activity) { }
}
With the above approach, single Activity Applications and multiple Activity Applications can now always have access to the Current/Local Activity Context. e.g instead of relying on the global context
Android.App.Application.Context
// or previously
Xamarin.Forms.Forms.Context
Can now be replaced with
MainApplication.ActivityContext
if (MainApplication.ActivityContext!= null)
{
versionNumber = MainApplication.ActivityContext
.PackageManager
.GetPackageInfo(MainApplication.ActivityContext.PackageName, 0)
.VersionName;
}
Android.App.Application.IActivityLifecycleCallbacks
registerActivityLifecycleCallbacks
In the latest scaffold of a new Xamarin Forms solution the CrossActivityPlugin (https://github.com/jamesmontemagno/CurrentActivityPlugin) is referenced in the Android project. So you can use
CrossCurrentActivity.Current.Activity.StartActivity(myIntent)