【问题标题】:UWP AppService Send cancelled SystemPolicyUWP AppService 发送取消的 SystemPolicy
【发布时间】:2018-06-06 21:53:21
【问题描述】:

过去 3 天,我一直在尝试远程创建和使用 Windows 10 UWP AppService。当 AppService 在一台笔记本电脑上运行而客户端在另一台笔记本电脑上运行(桌面到桌面)时,我得到了这一切。但是,当我在手机上安装客户端时,IBackgroundTaskInstance 会取消,原因是:SystemPolicy。 我不知道为什么在电话到桌面的情况下它不起作用。 有人知道从哪里开始寻找吗?

下面是我的服务类

using Newtonsoft.Json;
using SharedObjects;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.AppService;
using Windows.ApplicationModel.Background;
using Windows.ApplicationModel.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Management.Deployment;
using Windows.Storage.Streams;

namespace AppStarterService
{
    public sealed class AppStarterTask : IBackgroundTask
    {
        BackgroundTaskDeferral serviceDeferral;
        AppServiceConnection connection;

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            try
            {
                serviceDeferral = taskInstance.GetDeferral();
                taskInstance.Canceled += OnTaskCanceled;
                var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
                if (details.Name == "com.poctools.appstarter")
                {
                    connection = details.AppServiceConnection;
                    connection.RequestReceived += OnRequestReceived;
                    connection.ServiceClosed += Connection_ServiceClosed;
                }
                else
                {
                    serviceDeferral.Complete();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
        }

        async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            var messageDeferral = args.GetDeferral();
            try
            {
                var input = args.Request.Message;
                var packageList = await GetPackageListInfo();
                var json = JsonConvert.SerializeObject(packageList, Formatting.None);
                var result = new ValueSet();
                result.Add("result", json);
                Debug.WriteLine(json);
                var response = await args.Request.SendResponseAsync(result); //returns Success, even on the phone-to-desktop scenario
                Debug.WriteLine($"Send result: {response}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            finally
            {
                messageDeferral.Complete();
            }
        }

        private void Connection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
        {
            Debug.WriteLine($"Service closed: {args.Status}");
        }

        private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            Debug.WriteLine($"Task cancelled: {reason}");
            if (serviceDeferral != null)
            {
                serviceDeferral.Complete();
                serviceDeferral = null;
            }

            if (connection != null)
            {
                connection.Dispose();
                connection = null;
            }
        }



        private async Task<List<PackageInfo>> GetPackageListInfo()
        {
            try
            {
                List<PackageInfo> PackageInfoList = new List<PackageInfo>();

                PackageManager packageManager = new PackageManager();
                var Packages = packageManager.FindPackagesForUser("");

                foreach (var package in Packages.Where(p => p.SignatureKind == PackageSignatureKind.Store && !p.IsFramework))
                {
                    IReadOnlyList<AppListEntry> entryList = await package.GetAppListEntriesAsync();
                    if (entryList != null)
                    {
                        foreach (var entry in entryList)
                        {
                            if (entry != null)
                            {
                                Debug.WriteLine(entry.DisplayInfo.DisplayName);
                                var name = entry.DisplayInfo.DisplayName;
                                RandomAccessStreamReference stream = entry.DisplayInfo.GetLogo(new Size(150, 150));
                                if (stream != null)
                                {
                                    var streamContent = await stream.OpenReadAsync();
                                    if (streamContent != null)
                                    {
                                        byte[] buffer = new byte[streamContent.Size];
                                        await streamContent.ReadAsync(buffer.AsBuffer(), (uint)streamContent.Size, InputStreamOptions.None);
                                        string logo = Convert.ToBase64String(buffer);
                                        PackageInfoList.Add(new PackageInfo(name, package.Id.FamilyName, logo));
                                    }
                                }
                            }
                        }
                    }
                    Debug.WriteLine($"{package.Id.Name} - {package.SignatureKind}");
                }
                return PackageInfoList;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
        }

    }
}

【问题讨论】:

  • 你的手机中部署服务商成功了吗?
  • 提供程序部署在笔记本电脑上。电话将充当客户端。 SendResponseAsync() 确实返回了一个 AppServiceResponseStatus.Success,但在一秒钟左右后它仍然返回到 OnTaskCanceled() 中。 (它在调试模式下运行)
  • 您需要将服务和客户端部署在同一台设备上,并为本地应用提供服务。根据您的要求,您可以为多个设备创建一个网络服务。
  • 但它适用于桌面到桌面的场景。即使电话连接到服务,我也可以在主机的输出窗口中看到它(json 被创建得很好)。电话连接到主机,主机完成它,然后执行 SendResponseAsync() 给出“成功”响应。但是电话端什么也没有发生,一两秒后调用 OnTaskCanceled()。我能想到的只是秋季创作者更新功能,但找不到任何文档。已经在考虑 WCF,但看到“通用”不起作用,这令人沮丧。
  • 回到绘图板并做了一个只返回一个小字符串的服务。我在github.com/POC-Tools/RemoteAppServiceExample 上发布了一个工作示例。也许有一个可以发送的大小限制,并且 json 很大。需要进行更多测试。

标签: uwp


【解决方案1】:

主机和客户端之间可以发送的数据包大小有一个限制,显然对于我的手机来说它只有几 KB。 GetPackageListInfo() 方法获取主机上所有已安装应用程序的列表,包括名称和徽标。一些应用程序有很大的标志(Minecraft 有一个 9 KB 的标志,而且很大,Paint 3D 的标志是 27 KB)。 最后,我让服务一次返回 1 个 PackageInfo,让客户端调用服务,直到服务返回最后一个 PackageInfo,并减少任何大于 8KB 的徽标。

https://docs.microsoft.com/en-us/windows/uwp/launch-resume/how-to-create-and-consume-an-app-service 上的另一个兴趣点

应用服务的生命周期取决于调用者:

  1. 如果调用者在前台,应用服务生命周期是一样的 作为调用者。
  2. 如果调用者在后台,应用服务会获取 运行 30 秒。取出延期提供额外的 时间 5 秒。

代码:

    async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
    {
        var messageDeferral = args.GetDeferral();
        try
        {
            var inputs = args.Request.Message;
            if (Singleton.Instance.PackageList == null)
                Singleton.Instance.PackageList = await GetPackageListInfo();

            var itemsSend = inputs["items"] as string[]; //keep track of items already send
            inputs["items"] = null; //clear to keep response data small (it will be filled again when a new request comes in)
            var package = Singleton.Instance.PackageList.FirstOrDefault(p => !itemsSend.Contains(p.Id));
            if (package == null)
            {
                inputs["status"] = "stop"; //let the client know it's time to stop requesting
                inputs["package"] = null;
            }
            else
            {
                var json = JsonConvert.SerializeObject(package);
                inputs["package"] = json;
            }
            var response = await args.Request.SendResponseAsync(inputs);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
        finally
        {
            messageDeferral?.Complete();
        }
    }

调整图片大小

    async Task<byte[]> ResizeImage(byte[] imageData, int reqWidth, int reqHeight)
    {
        var memStream = new MemoryStream(imageData);

        using (IRandomAccessStream imageStream = memStream.AsRandomAccessStream())
        {
            //Get BitmapDecoder based on the original image
            var decoder = await BitmapDecoder.CreateAsync(imageStream);
            if (decoder.PixelHeight > reqHeight || decoder.PixelWidth > reqWidth)
            {
                //BitmapTransform defines a set of transformation to be applied to the original image (we're just interessted in scaling down)
                BitmapTransform transform = new BitmapTransform()
                {
                    ScaledHeight = (uint)reqHeight,
                    ScaledWidth = (uint)reqWidth,
                    InterpolationMode = BitmapInterpolationMode.Linear
                };

                PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
                    BitmapPixelFormat.Rgba8,
                    BitmapAlphaMode.Straight,
                    transform,
                    ExifOrientationMode.IgnoreExifOrientation,
                    ColorManagementMode.ColorManageToSRgb);

                var resizedStream = new InMemoryRandomAccessStream();
                BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, resizedStream);
                var pixels = pixelData.DetachPixelData();
                encoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, (uint)reqWidth, (uint)reqHeight, 96, 96, pixels);
                await encoder.FlushAsync();
                var outBuffer = new byte[resizedStream.Size];
                await resizedStream.ReadAsync(outBuffer.AsBuffer(), (uint)resizedStream.Size, InputStreamOptions.None);

                return outBuffer;

            }
        }
        return imageData;
    }

GetPackageListInfo

    private async Task<List<PackageInfo>> GetPackageListInfo()
    {
        try
        {
            List<PackageInfo> PackageInfoList = new List<PackageInfo>();

            PackageManager packageManager = new PackageManager();
            IEnumerable<Package> Packages = packageManager.FindPackagesForUser("");

            foreach (var package in Packages.Where(p => p.SignatureKind == PackageSignatureKind.Store && !p.IsFramework))
            {
                IReadOnlyList<AppListEntry> entryList = await package.GetAppListEntriesAsync();
                if (entryList != null)
                {
                    foreach (var entry in entryList)
                    {
                        if (entry != null)
                        {
                            var name = entry.DisplayInfo.DisplayName;
                            RandomAccessStreamReference stream = entry.DisplayInfo.GetLogo(new Size(50, 50));
                            if (stream != null)
                            {
                                var streamContent = await stream.OpenReadAsync();
                                if (streamContent != null)
                                {
                                    byte[] buffer = new byte[streamContent.Size];
                                    await streamContent.ReadAsync(buffer.AsBuffer(), (uint)streamContent.Size, InputStreamOptions.None);
                                    if (streamContent.Size < 9000)
                                    {
                                        PackageInfoList.Add(new PackageInfo(package.Id.FullName, name, package.Id.FamilyName, buffer));
                                    }
                                    else
                                    {
                                        byte[] resizedBuffer = await ResizeImage(buffer, 50, 50);
                                        if (resizedBuffer.Length < 8192)//8kb
                                            PackageInfoList.Add(new PackageInfo(package.Id.FullName, name, package.Id.FamilyName, resizedBuffer));
                                    }
                                }
                            }
                        }
                    }
                }
                //Debug.WriteLine($"{package.Id.Name} - {package.SignatureKind}");
            }
            return PackageInfoList;
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
            throw;
        }
    }

【讨论】:

    猜你喜欢
    • 2019-03-25
    • 2018-09-28
    • 2018-01-29
    • 2018-02-23
    • 2017-02-13
    • 2021-12-05
    • 2021-08-28
    • 2021-12-04
    • 2019-11-14
    相关资源
    最近更新 更多