Windowsストアアプリのトリガーとバックグラウンドジョブ









アプリケーションは、非アクティブであっても、システムによって生成されたイベントに応答できます。 これを行うには、SystemTriggerクラスを使用してバックグラウンドジョブを登録する必要があります。



たとえば、インターネットの出現、SMSの受信、タイムゾーンの変更などのイベントを「キャッチ」できます。



これに加えて、デバイス/システムのステータスが特定の条件に準拠しているかどうかのチェックを追加できます。 トリガーのイベントでは、指定されたすべての条件がチェックされます。



システムトリガーに加えて、タイマーで、または特別なイベントの結果として起動できるさまざまなトリガーがあります。



そのため、Windows 8.1アプリケーションで使用されるトリガーの種類をリストします。

SystemTrigger-最も一般的なトリガー。 システムイベントが発生した場合に発生します。

ロック画面への登録を必要としないトリガーは次のとおりです。

InternetAvailable-インターネットが利用可能になると、バックグラウンドタスクが開始されます

NetworkStateChange-ネットワーク状態が変化するとバックグラウンドタスクが開始します

OnlineIdConnectedStateChange-このアカウントに接続されているMicrosoftアカウントが変更されると、バックグラウンドタスクが開始されます

SmsReceived-新しいSMSメッセージを受信するとバックグラウンドタスクが開始します

TimeZoneChange-バックグラウンドタスクは、デバイスのタイムゾーンが変更されたときに開始されます

ServicingComplete-システムがアプリケーションの更新を完了すると、バックグラウンドタスクが開始されます



アプリケーションがロック画面に登録されている場合、次のトリガーも利用できます。

UserPresent-ユーザーが戻るとバックグラウンドタスクが開始します

UserAway-ユーザーがアイドル状態のときにバックグラウンドタスクが開始されます

ControlChannelReset-制御チャネルがリセットされると、バックグラウンドタスクが開始されます

SessionConnected-セッションが接続されるとバックグラウンドタスクが開始されます

BackgroundWorkCostChange-バックグラウンド作業スコアが変更されると、バックグラウンドタスクがアクティブになります



ロック画面に登録せずにこれらのトリガーを使用する場合、バックグラウンドジョブ登録行



BackgroundTaskRegistration task = bgTaskBuilder.Register();
      
      





アクセス拒否の例外をスローします。



ロック画面のアプリケーション登録イベントに応答するために、さらに2つのトリガーがあります。

LockScreenApplicationAdded-ロック画面にタイルが追加されると、バックグラウンドタスクが開始されます

LockScreenApplicationRemoved-タイルがロック画面から削除されると、バックグラウンドタスクが開始されます



Windows 10では、新しいシステムトリガーが導入されました。

PowerStateChange-バッテリーの状態が変化するとバックグラウンドタスクが開始します



システムトリガーが終了しました。他の使用可能なトリガーを検討してください。



MaintenanceTrigger-最も簡単でクールなトリガー。 タイマーのように機能します。 間隔は少なくとも15分に設定する必要があり、PCがAC電源に接続されている場合はトリガーが機能します。 喜ばしいのは、このトリガーがロック画面でのアプリケーションの登録を必要としないという事実です! 必要なことは、PCをプラグインすることだけです。

FreshnessTimeインターバル時間が15分未満に設定されている場合、トリガーを登録しようとすると例外がスローされます。



TimeTriggerMaintenanceTriggerとほぼ同じですが、ネットワークからの電力は必要ありませんが、ロック画面でのアプリケーションの登録が必要です。



PushNotificationTrigger-生の通知を受信するために使用できます。 ロック画面でのアプリケーションの登録が必要です。



ControlChannelTrigger-特殊なネットワーク機能用。 ロック画面でのアプリケーションの登録が必要です。



DeviceUseTrigger-バックグラウンドでセンサーと周辺機器へのアクセスを提供します。 他のトリガーとは異なり、アプリケーションが一時停止した場合にのみ実行されます。 実行条件をサポートしていません。



条件

トリガーが起動すると、次の条件を確認できます。

InternetAvailable / InternetNotAvailable

SessionConnected / SessionDisconnected

UserNotPresent / UserPresent



Windows 10のリリースにより、トリガーが大幅に増加しました。 完全なリストはクラスの中にあります。

Windows.ApplicationModel.Background



Windows UAPアプリケーションで使用可能になった新しいトリガーの一部を次に示します。

ApplicationTrigger-このトリガーを使用して、コードのどこからでもバックグラウンドタスクの実行を開始できます(ボタンを押すなど)

ToastNotificationActionTrigger-ユーザートースト通知で何らかのアクションを実行すると発生します

ToastNotificationHistoryChangedTrigger-通知履歴の変更を追跡できます。 たとえば、通知センターでメッセージを消去する瞬間を「キャッチ」するために使用できます。

LocationTrigger-バックグラウンドタスクを開始する場所変更イベント(ジオフェンシング機能で使用)

DeviceServicingTrigger-デバイスの長時間の更新操作(ファームウェアまたはパラメーター)中にトリガーされるイベント

DeviceWatcherTrigger-接続されたデバイスのリストで変更が発生すると発生します



さらに、残りの新しいトリガーのリストのみ(それらはたくさんありますよね?):

AppointmentStoreNotificationTrigger

ActivitySensorTrigger

BluetoothLEAdvertisementPublisherTrigger

BluetoothLEAdvertisementWatcherTrigger

CachedFileUpdaterTrigger

ChatMessageNotificationTrigger

ChatMessageReceivedNotificationTrigger

CommunicationBlockingAppSetAsActiveTrigger

ContactStoreNotificationTrigger

ContentPrefetchTrigger

DeviceConnectionChangeTrigger

DeviceManufacturerNotificationTrigger

EmailStoreNotificationTrigger

GattCharacteristicNotificationTrigger

MediaProcessingTrigger

MobileBroadbandDeviceServiceNotificationTrigger

MobileBroadbandPinLockStateChangeTrigger

MobileBroadbandRadioStateChangeTrigger

MobileBroadbandRegistrationStateChangeTrigger

NetworkOperatorNotificationTrigger

NetworkOperatorHotspotAuthenticationTrigger

PhoneTrigger

RcsEndUserMessageAvailableTrigger

Rfcommconnectiontrigger

SmartCardTrigger

SmsMessageReceivedTrigger

StorageLibraryContentChangedTrigger

SocketActivityTrigger



明らかに、一部のトリガーは特定の条件下では機能しませんが、特定の目的でバックグラウンドタスクを実行するように設計されています。 たとえば、 MediaProcessingTriggerトリガーを取り上げます。説明により、アプリケーションはバックグラウンドタスクの一部としてマルチメディアをトランスコードできます。 これにより、フォアグラウンドアプリケーションが作業を完了した場合でも、トランスコーディングを続行できます。



アプリケーションがバックグラウンドジョブを登録する場合、この機能をマニフェストに文書化する必要があります。 これは、マニフェストのグラフィカルエディターを使用して簡単に実行できます。











複数のバックグラウンドタスクを登録する必要がある場合は、マニフェストのグラフィカルエディターで必要な数のタスクを追加します。







または、任意のXMLエディターでマニフェストを手動で開き、Applicationタグ内に同様の構成を追加できます。



  <Extensions> <Extension Category="windows.backgroundTasks" EntryPoint="BGTaskMD.ExampleBackgroundTask"> <BackgroundTasks> <Task Type="timer" /> </BackgroundTasks> </Extension> <Extension Category="windows.backgroundTasks" EntryPoint="BGTaskMD.AppUpdateServicingCompleteTask"> <BackgroundTasks> <Task Type="systemEvent" /> </BackgroundTasks> </Extension>
      
      





Windows 8.1は、次を使用して自動的にロック画面に登録できます。



  BackgroundAccessStatus accessresult = await BackgroundExecutionManager.RequestAccessAsync();
      
      





その結果、ユーザーはアプリをロック画面に追加するように求められます。

このメソッドは、 BackgroundAccessStatus列挙を返します。



Windows 10およびWindows Phone 8.1アプリケーションでは、ロック画面に登録する必要はありませんが、タスクを登録する前にRequestAccessAsyncを呼び出すことは必須です。



ロック画面にアプリケーションを登録するための2つのオプションがあります-バッジとbadgeAndTileText。 バッジとテキスト付きバッジのみ。 このオプションは、マニフェストのグラフィカルエディターとXMLコードの編集の両方で選択できます。 オプションを選択することに加えて、バッジの画像を設定する必要があります-BadgeLogo:



 <uap:VisualElements DisplayName="Background Task example" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="BGTaskExample" BackgroundColor="transparent"> <uap:LockScreen Notification="badgeAndTileText" BadgeLogo="Assets\BadgeLogo.png" /> <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" ShortName="Background Task example"> </uap:DefaultTile> <uap:SplashScreen Image="Assets\SplashScreen.png" /> </uap:VisualElements>
      
      





もちろん、マニフェストのグラフィカルエディターを使用すると、より便利です。











アプリケーションをbadgeAndTileTextモードのロック画面に登録するには、ワイドタイル(WideLogo)の画像も含まれていることを確認する必要があります。



アプリケーションは、バッジ、最後のタイル通知のテキスト、トースト通知などのさまざまな情報をロック画面に表示できます。 これには特別なアクションは必要ありません。

ロック画面には最大7つのアプリケーションを登録できます。 そして、そのうちの1つだけが広いタイルを表示できます。



ロック画面に登録されているアプリケーションは、他のアプリケーションと比べてより多くの特権を持っています。 より多くのリソースを使用できます。

ユーザーのデバイスがバックグラウンドで常に実行中のタスクから「ブレーキをキャッチ」せず、バッテリーを着陸させないように、リソースの使用に制限が必要です。



例:

アプリケーションがロック画面に登録されている場合、15分ごとに2秒のCPU時間を使用できます。

アプリケーションがロック画面に登録されていない場合は、2時間ごとに1秒のCPU時間しか使用できません。

このアプリケーションがWindows Phone用の場合、15分ごとに2秒使用できます。



デバイスがAC電源に接続されておらず、バッテリーで駆動されている場合、ネットワークデータを使用するためのクォータが自動的にオンになります(ネットワークインターフェイスで消費されるエネルギー量を節約するため)。



Windows Phoneでは、バッテリーセーバー機能がオンの場合、デバイスが外部電源に接続されておらず、バッテリーの充電が特定のレベルよりも少ない場合、バックグラウンドタスクは開始されません。

リンクで詳細を読む: バックグラウンドタスクを使用したアプリケーションのサポート(XAML)



アプリケーションの更新後、バックグラウンドタスクの更新(登録解除および再登録)が必要になります。 前述のServicingCompleteトリガーは、アプリケーションの更新の瞬間を「キャッチ」するのに役立ちます。 このトリガーを使用すると、良好なトーンのルールに準拠します(ほとんど使用する必要があります)。

次のように登録解除できます。



  foreach (var _task in BackgroundTaskRegistration.AllTasks) { if (_task.Value.Name == "My demo task") { _task.Value.Unregister(true); } }
      
      





Unregisterメソッドの値がtrueに設定されている場合、バックグラウンドタスクの現在実行中のすべてのインスタンスがキャンセルされます。 falseが設定されている場合、タスクには作業を完了する機会が与えられます。

ところで、コンピューターを再起動した後でも、トリガーは機能します。



トリガーが2番目のパラメーターで初期化されると、いわゆるOneShotパラメーターが設定されます。これは、トリガーが1回だけ実行されるか、複数回実行されるかを示します。 例:



  SystemTrigger taskTrigger = new SystemTrigger(SystemTriggerType.ServicingComplete,false);
      
      







アクションの小さなガイド

Blank App(Universal Windows)のようなプロジェクトを作成します

作成したソリューションに、Windowsランタイムコンポーネント(ユニバーサルWindows)などのプロジェクトをもう1つ追加します

最初のプロジェクトで、2番目のプロジェクトにリンクを追加します。 次の方法で実行できます。

ソリューションエクスプローラーのプロジェクト名で、コンテキストメニューを呼び出し、[追加] / [追加]-[参照...] / [リンク]を選択し、ウィンドウでメニューから[プロジェクト]を選択し、2番目のプロジェクトの前に





このファイルでは、バックグラウンドジョブクラスコードは次のようになります。



  public sealed class ExampleBackgroundTask : IBackgroundTask { public void Run(IBackgroundTaskInstance taskInstance) { // - ,      } }
      
      





名前空間を追加します。



 using Windows.ApplicationModel.Background;
      
      





登録する前に、トリガーが既に登録されているかどうかを確認する必要があります。そうでない場合、同じトリガーの多くの登録を取得します。



  foreach (var _task in BackgroundTaskRegistration.AllTasks) { if (_task.Value.Name == "My demo task") { return; } }
      
      





トリガーの初期画面での登録が必要な場合、トリガーを登録する前に、同様のスニペットも挿入する必要があります。



  //      BackgroundAccessStatus accessresult = await BackgroundExecutionManager.RequestAccessAsync(); if ((accessresult == BackgroundAccessStatus.Denied)||(accessresult == BackgroundAccessStatus.Unspecified)) { return; }
      
      





次のようなトリガーを登録できます。



  TimeTrigger taskTrigger = new TimeTrigger(15, false); var bgTaskBuilder = new BackgroundTaskBuilder(); bgTaskBuilder.Name = "My demo task"; bgTaskBuilder.TaskEntryPoint = "BGTaskMD.ExampleBackgroundTask"; bgTaskBuilder.SetTrigger(taskTrigger); // ,          SystemCondition internetCondition = new SystemCondition(SystemConditionType.InternetAvailable); bgTaskBuilder.AddCondition(internetCondition); BackgroundTaskRegistration task = bgTaskBuilder.Register(); task.Completed += task_Completed; // -   void task_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args) { // -    }
      
      





Completedイベントは、アプリケーションが現在実行中の場合に発生します。 アプリケーションが中断(中断)されてから終了(終了)された場合、イベントは発生しません。 アプリケーションを一時停止してから再開すると、再開後に完了がトリガーされます。



完了に加えて、バックグラウンドタスクのキャンセル(キャンセル済み)も処理する必要があります。 ただし、タスクの登録時にではなく、その実装、つまりWinMDファイルのクラスで処理されます。



  public sealed class ExampleBackgroundTask : IBackgroundTask { volatile bool _cancelRequested = false; public void Run(IBackgroundTaskInstance taskInstance) { taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled); //        } private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) { //      sender.Task.Name _cancelRequested = true; } }
      
      





バックグラウンドタスク中に非同期コードが実行される場合、アプリケーションが中断された場合にコードを正しく完了するには、defferalを使用します。 この場合、Runメソッドは次のようになります。



  public void Run(IBackgroundTaskInstance taskInstance) { BackgroundTaskDeferral _deferral = taskInstance.GetDeferral(); await someAsyncTask(); _deferral.Complete(); }
      
      





システムに干渉しない短いタスクを作成することをお勧めします。



バックグラウンドタスクの実行中に、プロセスステータス値を設定(Windows.Storage.ApplicationData.Current.LocalSettings)に書き込み、必要に応じて読み取ることができます。



ユーザーの操作はバックグラウンドタスクでは使用されません。 バックグラウンドタスクコードからの通知、タイル、およびイベントインジケーターの更新を除き、ユーザーインターフェイス要素を更新することはお勧めしません。



バックグラウンドタスクのデバッグは、トリガーによってトリガーされたイベントにコミットしたり、トレースしたり、MaintenanceTriggerやTimeTriggerが機能するまで15分以上待機したりすると、退屈なタスクになるリスクがあります(開発者の中には、そのようなデバッグを夢見ている人もいるでしょう)。

VSがトリガーを呼び出すことができるようにするには、バックグラウンドジョブのコードをメタデータファイルWinMDに移動する必要があります。 そのため、デバッグ時には、アプリケーションライフサイクルイベントでバックグラウンドタスクを確認できます。



これが機能するには、バックグラウンドタスクが既に登録されており、起動を待機している必要があります。

OneShotパラメーターを使用してバックグラウンドタスクを登録すると、動作後、Visual Studioを介したタスクのデバッグは利用できなくなります。

Visual Studioを介したデバッグは、ControlChannelTrigger、PushNotificationTriggerなどのトリガー、およびSystemTriggerをトリガータイプSmsReceivedで使用するバックグラウンドタスクでは使用できません。



GitHubでTimeTriggerとServicingCompleteのサンプル実装を見つけることができます



インターネットでの作業に関しては、バックグラウンドジョブは大規模なデータダウンロード操作用ではありません。 ただし、ニュースの更新やイベントの監視などには便利です。 大きなファイルをダウンロードする場合は、 BackgroundDownloaderクラスを使用する必要があります。

単純なデータ読み込みの例を考えてみましょう。



 using Windows.Networking.BackgroundTransfer; using Windows.Storage; // -  ... Uri source = new Uri("https://habrastorage.org/files/f0a/5ea/caf/f0a5eacaf8c44f82a92748124c470f91.jpg"); StorageFile destinationFile = await KnownFolders.PicturesLibrary.CreateFileAsync( "imagefromhabr.jpg", CreationCollisionOption.GenerateUniqueName); BackgroundDownloader downloader = new BackgroundDownloader(); DownloadOperation download = downloader.CreateDownload(source, destinationFile); await download.StartAsync();
      
      





最後に、トピックからこれまで削除されていたとしても、小さなリソースのダウンロードを含む短期的な操作には、 Windows.Web.Http名前空間を使用できるか、使用する必要があることを追加します。



  var uri = new Uri("http://habrahabr.ru/post/264199/"); var httpClient = new HttpClient(); try //   exceptions   async  { var result = await httpClient.GetStringAsync(uri); } catch { } httpClient.Dispose();
      
      






All Articles