与众不同 windows phone (38) - 8.0 关联启动: 使用外部程序打开一个文件或URI, 关联指定的文件类型或协议

原文:与众不同 windows phone (38) - 8.0 关联启动: 使用外部程序打开一个文件或URI, 关联指定的文件类型或协议

[源码下载]

与众不同 windows phone (38) - 8.0 关联启动: 使用外部程序打开一个文件或URI, 关联指定的文件类型或协议

作者:webabcd

介绍
与众不同 windows phone 8.0 之 关联启动

  • 使用外部程序打开一个文件
  • 使用外部程序打开一个 Uri
  • 关联指定的文件类型
  • 关联指定的协议

示例
1、演示如何使用外部程序打开一个文件
AssociationLaunching/LaunchFile.xaml

<phone:PhoneApplicationPage
    x:Class="Demo.AssociationLaunching.LaunchFile"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="True">

    <Grid Background="Transparent">
        <StackPanel>

            <TextBlock Name="lblMsg" Margin="0 0 0 10" />

            <Button Content="打开一个 .log 文件" Name="btnLaunchFile" Click="btnLaunchFile_Click" />

        </StackPanel>
    </Grid>

</phone:PhoneApplicationPage>

AssociationLaunching/LaunchFile.xaml.cs

/*
 * 演示如何使用外部程序打开一个文件
 */

using System;
using System.Windows;
using Microsoft.Phone.Controls;
using Windows.Storage;
using System.IO;
using System.Text;

namespace Demo.AssociationLaunching
{
    public partial class LaunchFile : PhoneApplicationPage
    {
        public LaunchFile()
        {
            InitializeComponent();
        }

        private async void btnLaunchFile_Click(object sender, RoutedEventArgs e)
        {
            // 在 ApplicationData 的根目录下写一个 myLog.log 文件
            StorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
            StorageFile storageFile = await applicationFolder.CreateFileAsync("myLog.log", CreationCollisionOption.ReplaceExisting);
            using (Stream stream = await storageFile.OpenStreamForWriteAsync())
            {
                byte[] content = Encoding.UTF8.GetBytes("hello webabcd");
                await stream.WriteAsync(content, 0, content.Length);
            }

            // 启动与 .log 类型文件关联的默认应用程序,来打开指定的文件
            Windows.System.Launcher.LaunchFileAsync(storageFile);
        }
    }
}

2、演示如何使用外部程序打开一个 Uri(自定义协议)
AssociationLaunching/LaunchUri.xaml

<phone:PhoneApplicationPage
    x:Class="Demo.AssociationLaunching.LaunchUri"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="True">

    <Grid Background="Transparent">
        <StackPanel>

            <TextBlock Name="lblMsg" Margin="0 0 0 10" />

            <Button Content="启动一个协议名为 webabcd 的 uri" Name="btnLaunchUri" Click="btnLaunchUri_Click" />

        </StackPanel>
    </Grid>

</phone:PhoneApplicationPage>

AssociationLaunching/LaunchUri.xaml.cs

/*
 * 演示如何使用外部程序打开一个 Uri(自定义协议)
 */

using System.Windows;
using Microsoft.Phone.Controls;
using Windows.Networking.Proximity;

namespace Demo.AssociationLaunching
{
    public partial class LaunchUri : PhoneApplicationPage
    {
        public LaunchUri()
        {
            InitializeComponent();
        }

        private void btnLaunchUri_Click(object sender, RoutedEventArgs e)
        {
            // 使用外部程序打开指定的 Uri(自定义协议,注意这里没有“//”)
            Windows.System.Launcher.LaunchUriAsync(new System.Uri("webabcd:hello webabcd"));

            // nfc 方式启用另一台 wp nfc 设备打开指定的 Uri(需要在 manifest 中声明 ID_CAP_NETWORKING 和 ID_CAP_PROXIMITY)
            ProximityDevice nfcDevice = ProximityDevice.GetDefault();
            if (nfcDevice != null)
            {
                long Id = nfcDevice.PublishUriMessage(new System.Uri("webabcd:hello webabcd"));
            }
        }
    }
}

3、演示如何关联指定的文件类型(即用本程序打开指定类型的文件)
AssociationLaunching/FileTypeAssociation.xaml

<phone:PhoneApplicationPage
    x:Class="Demo.AssociationLaunching.FileTypeAssociation"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="True">

    <Grid Background="Transparent">
        <StackPanel>

            <TextBlock Name="lblMsg" TextWrapping="Wrap" />

            <TextBlock TextWrapping="Wrap" Margin="0 10 0 0">
                <Run>本程序可以打开 .log 类型的文件</Run>
                <LineBreak />
                <Run>测试方法:通过 LaunchFile.xaml 打开一个 .log 类型的文件</Run>
            </TextBlock>

        </StackPanel>
    </Grid>

</phone:PhoneApplicationPage>

AssociationLaunching/FileTypeAssociation.xaml.cs

/*
 * 演示如何关联指定的文件类型(即用本程序打开指定类型的文件)
 *
 *
 * 由于配置为 NavUriFragment="fileToken=%s",所以本 app 打开某类型的文件会通过 /FileTypeAssociation?fileToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 启动
 * 相关的 UriMapper 参见 MyUriMapper.cs
 *
 *
 * 注:
 * 需要在 manifest 中增加类似如下的配置
 *  <Extensions>
      <!--
          NavUriFragment="fileToken=%s" 的意思是:
          1、某 app 启动外部程序打开 .xxx 文件时会传递文件的 token
          2、如果最终是由本 app 打开 .xxx 文件,则本 app 会通过 /FileTypeAssociation?fileToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 启动
      -->
      <FileTypeAssociation TaskID="_default" Name="myFileTypeAssociation" NavUriFragment="fileToken=%s">
        <Logos>
          <!--相关类型的文件显示在电子邮件附件中的图标,33x33 像素,其会显示在白色的背景前-->
          <Logo Size="small" IsRelative="true">Assets/AppIcon_33x33.png</Logo>
          <!--相关类型的文件显示在 Office 中心列表视图中的图标,69x69 像素,其会显示在白色的背景前-->
          <Logo Size="medium" IsRelative="true">Assets/AppIcon_69x69.png</Logo>
          <!--相关类型的文件显示在浏览器下载中的图标,176x176 像素,其会显示在白色的背景前-->
          <Logo Size="large" IsRelative="true">Assets/AppIcon_176x176.png</Logo>
        </Logos>
        <SupportedFileTypes>
          <!--关联的文件类型列表-->
          <FileType ContentType="text/plain">.log</FileType>
          <FileType ContentType="application/rar">.rar</FileType>
        </SupportedFileTypes>
      </FileTypeAssociation>
    </Extensions>
 */

using System;
using System.Collections.Generic;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Windows.Phone.Storage.SharedAccess;
using Windows.Storage;
using Windows.Storage.Streams;
using System.IO;
using System.Text;

namespace Demo.AssociationLaunching
{
    public partial class FileTypeAssociation : PhoneApplicationPage
    {
        public FileTypeAssociation()
        {
            InitializeComponent();
        }

        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            IDictionary<string, string> queryStrings = this.NavigationContext.QueryString;

            if (queryStrings.ContainsKey("fileToken"))
            {
                // 获取需要打开的文件的 token
                string fileToken = queryStrings["fileToken"];
                // 保存需要打开的文件到本 app 的 ApplicationData
                await SharedStorageAccessManager.CopySharedFileAsync(ApplicationData.Current.LocalFolder, "myLog2.log", NameCollisionOption.ReplaceExisting, fileToken);
                // 获取文件的文件名称
                string fileName = SharedStorageAccessManager.GetSharedFileName(fileToken);

                lblMsg.Text = "fileName: " + fileName;
                lblMsg.Text += Environment.NewLine;

                // 获取 ApplicationData 中指定的文件
                StorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
                StorageFile storageFile = await applicationFolder.GetFileAsync("myLog2.log");

                // 显示文件内容
                IRandomAccessStreamWithContentType accessStream = await storageFile.OpenReadAsync();
                using (Stream stream = accessStream.AsStreamForRead((int)accessStream.Size))
                {
                    byte[] content = new byte[stream.Length];
                    await stream.ReadAsync(content, 0, (int)stream.Length);

                    lblMsg.Text += Encoding.UTF8.GetString(content, 0, content.Length);
                }
            }

            base.OnNavigatedTo(e);
        }
    }
}

4、演示如何关联指定的协议(即用本程序处理指定的协议)
AssociationLaunching/ProtocolAssociation.xaml

<phone:PhoneApplicationPage
    x:Class="Demo.AssociationLaunching.ProtocolAssociation"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="True">

    <Grid Background="Transparent">
        <StackPanel>

            <TextBlock Name="lblMsg" TextWrapping="Wrap" />

            <TextBlock TextWrapping="Wrap" Margin="0 10 0 0">
                <Run>本程序可以处理 webabcd 协议</Run>
                <LineBreak />
                <Run>测试方法:通过 LaunchUri 打开一个名为 webabcd 的协议</Run>
            </TextBlock>

        </StackPanel>
    </Grid>

</phone:PhoneApplicationPage>

AssociationLaunching/ProtocolAssociation.xaml.cs

/*
 * 演示如何关联指定的协议(即用本程序处理指定的协议)
 *
 *
 * 由于配置为 NavUriFragment="encodedLaunchUri=%s",所以本 app 打开某协议会通过 /Protocol?encodedLaunchUri=webabcd:xxxxxxxxxx 启动
 * 相关的 UriMapper 参见 MyUriMapper.cs
 *
 *
 * 注:
 * 需要在 manifest 中增加类似如下的配置
 *  <Extensions>
      <!--
          Name 是协议名称,对于本例来说协议的示例为“webabcd:hello webabcd”,注意其没有“//”
      -->
      <Protocol TaskID="_default" Name="webabcd" NavUriFragment="encodedLaunchUri=%s" />
    </Extensions>
 */

using System.Collections.Generic;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;

namespace Demo.AssociationLaunching
{
    public partial class ProtocolAssociation : PhoneApplicationPage
    {
        public ProtocolAssociation()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // 显示协议的详细信息
            IDictionary<string, string> queryStrings = this.NavigationContext.QueryString;
            if (queryStrings.ContainsKey("protocol"))
            {
                lblMsg.Text = queryStrings["protocol"];
            }

            base.OnNavigatedTo(e);
        }
    }
}

自定义 UriMapper,用于处理当本 app 由文件打开或协议打开或镜头扩展打开或图片扩展打开时,导航到相关的处理页面
MyUriMapper.cs

/*
 * 自定义 UriMapper,用于处理当本 app 由文件打开或协议打开或镜头扩展打开或图片扩展打开时,导航到相关的处理页面
 *
 * 注:
 * 要使此 UriMapper 有效,需要在 App.xaml.cs 中增加 RootFrame.UriMapper = new Demo.MyUriMapper();
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Windows.Navigation;
using Windows.Phone.Storage.SharedAccess;

namespace Demo
{
    public class MyUriMapper : UriMapperBase
    {
        public override Uri MapUri(Uri uri)
        {
            string tempUrl = HttpUtility.UrlDecode(uri.ToString());

            // 由文件启动本 app 时会通过 /FileTypeAssociation?fileToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 启动
            if (tempUrl.StartsWith("/FileTypeAssociation"))
            {
                // 获取 fileToken
                int fileTokenIndex = tempUrl.IndexOf("fileToken=") + 10;
                string fileToken = tempUrl.Substring(fileTokenIndex);

                // 获取相关的文件名
                string fileName = SharedStorageAccessManager.GetSharedFileName(fileToken); // myLog.log

                // 获取相关的文件名的扩展名
                string fileType = Path.GetExtension(fileName);

                // 根据文件类型的不同导航到不同的处理页面
                switch (fileType)
                {
                    case ".log":
                        return new Uri("/AssociationLaunching/FileTypeAssociation.xaml?fileToken=" + fileToken, UriKind.Relative);
                    default:
                        return new Uri("/MainPage.xaml", UriKind.Relative);
                }
            }
            // 由协议启动本 app 时会通过 /Protocol?encodedLaunchUri=webabcd:xxxxxxxxxx 启动
            else if (tempUrl.StartsWith("/Protocol"))
            {
                // 获取协议的详细信息
                int protocolIndex = tempUrl.IndexOf("encodedLaunchUri=") + 17;
                string protocol = tempUrl.Substring(protocolIndex);

                // 导航到处理 webabcd 协议的处理页面
                return new Uri("/AssociationLaunching/ProtocolAssociation.xaml?protocol=" + protocol, UriKind.Relative);
            }
            // 由镜头扩展启动本 app 时会通过 /MainPage.xaml?Action=ViewfinderLaunch 启动
            else if (tempUrl.Contains("Action=ViewfinderLaunch"))
            {
                return new Uri("/CameraAndPhoto/LensExtensibility.xaml?fromLens=true", UriKind.Relative);
            }
            // 由图片扩展之“共享...”启动本 app 时会通过 /MainPage.xaml?Action=ShareContent&FileId={xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} 启动
            else if (tempUrl.Contains("Action=ShareContent"))
            {
                string fileId = tempUrl.Substring(tempUrl.IndexOf("FileId=") + 7).Replace("{", "").Replace("}", "");
                return new Uri("/CameraAndPhoto/PhotoExtensibility.xaml?type=share&token=" + fileId, UriKind.Relative);
            }
            // 由图片扩展之“编辑...”启动本 app 时会通过 /MainPage.xaml?Action=EditPhotoContent&FileId={xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} 启动
            else if (tempUrl.Contains("Action=EditPhotoContent"))
            {
                string fileId = tempUrl.Substring(tempUrl.IndexOf("FileId=") + 7).Replace("{", "").Replace("}", "");
                return new Uri("/CameraAndPhoto/PhotoExtensibility.xaml?type=edit&token=" + fileId, UriKind.Relative);
            }
            // 由图片扩展之“自动上传”启动本 app 时会通过 /MainPage.xaml?Action=ConfigurePhotosUploadSettings 启动
            else if (tempUrl.Contains("Action=ConfigurePhotosUploadSettings"))
            {
                return new Uri("/CameraAndPhoto/PhotoAutoUpload.xaml?fromConfig=true", UriKind.Relative);
            }
            // 在锁屏设置界面,如果将本 app 设置为背景提供程序,则锁屏界面上会有一个名为“打开应用”的按钮,点击后会通过 /MainPage.xaml?WallpaperSettings=1 启动本 app
            else if (tempUrl.Contains("WallpaperSettings=1"))
            {
                return new Uri("/Others/LockScreen.xaml?WallpaperSettings=1", UriKind.Relative);
            }

            return uri;
        }
    }
}

将此 app 的 UriMapper 设置为我们自定义的 UriMapper
App.xaml.cs

private void InitializePhoneApplication()
{
    // 设置本 app 的 UriMapper
    RootFrame.UriMapper = new Demo.MyUriMapper();
}

OK
[源码下载]

时间: 2024-10-27 01:03:46

与众不同 windows phone (38) - 8.0 关联启动: 使用外部程序打开一个文件或URI, 关联指定的文件类型或协议的相关文章

重新想象 Windows 8 Store Apps (33) - 关联启动: 使用外部程序打开一个文件或uri, 关联指定的文件类型或协议

原文:重新想象 Windows 8 Store Apps (33) - 关联启动: 使用外部程序打开一个文件或uri, 关联指定的文件类型或协议 [源码下载] 重新想象 Windows 8 Store Apps (33) - 关联启动: 使用外部程序打开一个文件或uri, 关联指定的文件类型或协议 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 关联启动 使用外部程序打开一个文件 使用外部程序打开一个 Uri 关联指定的文件类型(即用本程序打开指定类型的文件)

与众不同windows phone (38)

8.0 关联启动: 使用外部程序打开一个文件或URI, 关联指定的文件类型或协议 介绍 与众不同 windows phone 8.0 之 关联启动 使用外部程序打开一个文件 使用 外部程序打开一个 Uri 关联指定的文件类型 关联指定的协议 示例 1.演示如何使用 外部程序打开一个文件 AssociationLaunching/LaunchFile.xaml <phone:PhoneApplicationPage x:Class="Demo.AssociationLaunching.Lau

与众不同 windows phone (47) - 8.0 其它: 锁屏信息和锁屏背景, 电池状态, 多分辨率, 商店, 内置协议, 快速恢复

原文:与众不同 windows phone (47) - 8.0 其它: 锁屏信息和锁屏背景, 电池状态, 多分辨率, 商店, 内置协议, 快速恢复 [源码下载] 与众不同 windows phone (47) - 8.0 其它: 锁屏信息和锁屏背景, 电池状态, 多分辨率, 商店, 内置协议, 快速恢复 作者:webabcd 介绍与众不同 windows phone 8.0 之 其它 锁屏信息和锁屏背景 电池状态 多分辨率应用 与 Windows Phone 商店相关的操作 系统的内置协议 快

与众不同 windows phone (43) - 8.0 相机和照片: 镜头的可扩展性, 图片的可扩展性, 图片的自动上传扩展

原文:与众不同 windows phone (43) - 8.0 相机和照片: 镜头的可扩展性, 图片的可扩展性, 图片的自动上传扩展 [源码下载] 与众不同 windows phone (43) - 8.0 相机和照片: 镜头的可扩展性, 图片的可扩展性, 图片的自动上传扩展 作者:webabcd 介绍与众不同 windows phone 8.0 之 相机和照片 镜头的可扩展性 图片的可扩展性 图片的自动上传扩展 示例1.演示如何将本 app 注册为镜头扩展CameraAndPhoto/Len

与众不同 windows phone (37) - 8.0 文件系统: StorageFolder, StorageFile, 通过 Uri 引用文件, 获取 SD 卡中的文件

原文:与众不同 windows phone (37) - 8.0 文件系统: StorageFolder, StorageFile, 通过 Uri 引用文件, 获取 SD 卡中的文件 [源码下载] 与众不同 windows phone (37) - 8.0 文件系统: StorageFolder, StorageFile, 通过 Uri 引用文件, 获取 SD 卡中的文件 作者:webabcd 介绍与众不同 windows phone 8.0 之 文件系统 通过 StorageFolder 和

与众不同 windows phone (46) - 8.0 通信: Socket, 其它

原文:与众不同 windows phone (46) - 8.0 通信: Socket, 其它 [源码下载] 与众不同 windows phone (46) - 8.0 通信: Socket, 其它 作者:webabcd 介绍与众不同 windows phone 8.0 之 通信 Socket Demo 获取当前连接的信息 http rss odata socket bluetooth nfc voip winsock 示例1.演示 socket tcp 的应用(本例既做服务端又做客户端)Com

与众不同 windows phone (45) - 8.0 语音: TTS, 语音识别, 语音命令

原文:与众不同 windows phone (45) - 8.0 语音: TTS, 语音识别, 语音命令 [源码下载] 与众不同 windows phone (45) - 8.0 语音: TTS, 语音识别, 语音命令 作者:webabcd 介绍与众不同 windows phone 8.0 之 语音 TTS(Text To Speech) 语音识别 语音命令 示例1.演示 TTS(Text To Speech)的应用Speech/TTS.xaml <phone:PhoneApplicationP

与众不同 windows phone (40) - 8.0 媒体: 音乐中心的新增功能, 图片中心的新增功能, 后台音乐播放的新增功能

原文:与众不同 windows phone (40) - 8.0 媒体: 音乐中心的新增功能, 图片中心的新增功能, 后台音乐播放的新增功能 [源码下载] 与众不同 windows phone (40) - 8.0 媒体: 音乐中心的新增功能, 图片中心的新增功能, 后台音乐播放的新增功能 作者:webabcd 介绍与众不同 windows phone 8.0 之 媒体 添加音乐到音乐中心,从音乐中心删除音乐 与图片中心相关的新增功能 BackgroundAudioPlayer 的新增功能 示例

与众不同 windows phone (41) - 8.0 相机和照片: 通过 AudioVideoCaptureDevice 捕获视频和音频

原文:与众不同 windows phone (41) - 8.0 相机和照片: 通过 AudioVideoCaptureDevice 捕获视频和音频 [源码下载] 与众不同 windows phone (41) - 8.0 相机和照片: 通过 AudioVideoCaptureDevice 捕获视频和音频 作者:webabcd 介绍与众不同 windows phone 8.0 之 相机和照片 通过 AudioVideoCaptureDevice 捕获视频和音频 示例演示 AudioVideoCa