2017/01/18 内容更新しました。
はまったのでメモ
正しくはXamarin.Forms.Init()を呼ぶ前に使ってはいけない。
Init()を呼ばないで使用すると下記の例外が発生する。
System.InvalidOperationException: You MUST call Xamarin.Forms.Init(); prior to using it.
DependencyServiceは上記の初期化処理が呼ばれて初めて使える機能となる。
そしてXamarin.Forms.Init()はMainActivityのOnCreate()で呼ぶので、
本体が落ちた後に起動して動かすようなバックグラウンドサービスでは
MainActivityを利用しないので使えないということになる。
んじゃあInit()呼べばいいと思ったけど引数の1つ目がActivityとなる為、
サービスから呼べなくて困っていろいろ調べましたが、
そもそもサービスからDependencyServiceを使う必要が無いことに気がつきました。
なぜならサービスはXamarin.Android側のコードとなるので、
わざわざDependencyServiceを返さなくても同じ処理が出来るからです。
今回はDependencyServiceの例をだしましたが、
MainActivityを通らないで起動されるバックグラウンド処理では
その他の初期化処理なども通っていない可能性があるので注意が必要です。
2017/01/18 更新 どうしてもバックグラウンドから使いたい場合
上記のように直接DependencyServiceの実装クラスを呼び出すことが可能な場合は問題ないのですが、
PCL側の共通処理として実装している処理内部でDependencyServiceを利用している場合でPCL側からもバックグラウンドサービス側からも呼び出される可能性がある場合は困ってしまいます
その場合はAndroid側のDependencyServiceの実装クラスのインスタンスをAndroid側のサービス等からPCL側に設定してあげることでPCL側からAndroid側の実装クラスを呼び出すことが可能です。
以下サンプルコードです。
Appクラスに使いたいDependencyServiceのインスタンスを公開します。
public partial class App : PrismApplication
{
/// <summary>各プラットフォームのXamarin.Forms.Forms.IsInitialized</summary>
public static bool IsPlatformInitialized { get; set; }
private static IHogeService _hogeService;
public static IHogeService HogeService
{
get
{
if (_hogeService== null)
{
if (IsPlatformInitialized)
{
_hogeService= DependencyService.Get<IHogeService>();
}
}
return _hogeService;
}
set { _hogeService= value; }
}
}
Xamarin.Android側のMainActivityでInitを呼び出した後でフラグを更新します。
global::Xamarin.Forms.Forms.Init(this, bundle);
App.IsPlatformInitialized = Xamarin.Forms.Forms.IsInitialized;
バックグラウンドサービスの初期化コードでAndroid側のクラスのインスタンスを設定します。
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
App.HogeService = new HogeService();
/* 省略 */
}