Page 37 - MSDN Magazine, October 2017
P. 37
In Solution Explorer, right-click on your app project node and select Add | New Folder. Name the folder myapp. Right-click on the newly added folder node and again select Add | New Folder to create a subfolder named www. Press Ctrl+N, and within the File New dialog, select the General | HTML Page template. Save this file as index.html, under the solution’s MyPackagedPlugin\ MyApp\myapp\www path. Then add this file to the project folder
Figure 4 Adding App Extensions
path, so that it’s included as package content. Right-click on the newly added index.html file node and select Properties. Confirm the default property values of Build Action: Content and Copy to Output Directory: Do not copy.
Now add the markup shown in Figure 5 to the newly created index.html. This page demonstrates several things. First, note that built-in WDP resources, such as the jquery.js and rest.js libraries, are available to packaged plug-ins, as well. This enables a packaged plug-in to combine domain-specific functionality with built-in WDP func- tionality. For more information, please consult the article, “Device Portal API Reference” (bit.ly/2uFTTFD). Second, note the reference to the plug-in’s REST API calls, both the app’s /myapp/API/status and the component’s /mycomponent/API/status. This shows how a plug-in’s static and dynamic content can be easily combined.
Adding a REST API Now I’ll implement a REST API handler. As mentioned earlier, choice of entry point depends on whether a back- ground or foreground AppService is being implemented. Beyond a minor difference in how the incoming AppServiceConnection is obtained, the DevicePortalConnection implementation is identi- cal for both scenarios. I’ll start with the app’s foreground handler.
Open the source file App.xaml.cs and add the following name- spaces, required for every handler:
using Windows.ApplicationModel.AppService; using Windows.ApplicationModel.Background; using Windows.System.Diagnostics.DevicePortal; using Windows.Web.Http;
using Windows.Web.Http.Headers;
Inside the MyApp.App class definition, I’ll add a few members to implement the handler’s state. BackgroundTaskDeferral defers completion of the background task that hosts execution of the han- dler, and DevicePortalConnection implements the connection to the WDP service itself.
sealed partial class App : Application {
private BackgroundTaskDeferral taskDeferral;
private DevicePortalConnection devicePortalConnection;
private static Uri statusUri = new Uri("/myapp/API/status", UriKind.Relative);
Next, override the background activation handler for the app, to instantiate a DevicePortalConnection and subscribe to its events, as shown in Figure 6.
For this handler, I’ll simply look for requests to the URI /myapp/ API/status, and respond with a JSON structure, as shown in Figure 7. A more complex implementation could support sev- eral routes, distinguish between GETs and POSTs, inspect URI parameters, and so on.
Finally, I handle closing of the DevicePortalConnection, either directly with its Closed event, or indirectly by cancellation of the background task, as shown in Figure 8.
Implementation of the component project’s background handler is nearly identical to the foreground example. Open the source file Class1.cs and add the required namespaces, as earlier. Inside the component namespace, replace the generated class definition with a class implementing IBackgroundTask and its required Run method:
public sealed class MyBackgroundHandler : IBackgroundTask {
public void Run(IBackgroundTaskInstance taskInstance) {
// Implement as for foreground handler's OnBackgroundActivated... }
}
<Package ...><Applications><Application ...> <Extensions>
<!--Foreground (in app) packaged plug-in handler app service and WDP provider--> <uap:Extension
Category="windows.appService">
<uap:AppService Name="com.contoso.www.myapp" /> </uap:Extension>
<uap4:Extension
Category="windows.devicePortalProvider"> <uap4:DevicePortalProvider
DisplayName="MyPluginApp" AppServiceName="com.contoso.www.myapp" ContentRoute="/myapp/www/" HandlerRoute="/myapp/API/" />
</uap4:Extension>
<!--Background packaged plug-in handler app service and WDP provider--> <uap:Extension
Category="windows.appService" EntryPoint="MyComponent.MyBackgroundHandler"> <uap:AppService Name="com.contoso.www.mycomponent" />
</uap:Extension> <uap4:Extension
Category="windows.devicePortalProvider"> <uap4:DevicePortalProvider
DisplayName="MyPluginComponent" AppServiceName="com.contoso.www.mycomponent" HandlerRoute="/mycomponent/API/" />
</uap4:Extension> </Extensions>
</Application></Applications></Package>
Figure 5 Status Page Markup
<html> <head>
<title>My Packaged Plug-in Page</title> <script src="/js/rest.js"></script> <script src="/js/jquery.js"></script> <script type="text/javascript">
function InitPage() {
var webb = new WebbRest(); webb.httpGetExpect200("/myapp/API/status")
.done(function (response) { $('#app_status')[0].innerText = response.status;
}); webb.httpGetExpect200("/mycomponent/API/status")
.done(function (response) { $('#comp_status')[0].innerText = response.status;
}); }
</script> </head>
<body onload="InitPage();">
<div style="font-size: x-large;">
My Packaged Plug-in Page
<br/><br/>
App Status: <span id="app_status" style="color:green"></span> <br/>
Component Status: <span id="comp_status" style="color:green"></span>
</div> </body> </html>
msdnmagazine.com
October 2017 33