このトピックはまだ評価されていません - このトピックを評価する

Windows Phone 8 での SD カードからの読み取り

2013/12/05

対象: Windows Phone 8 のみ

Windows Phone アプリでは、Microsoft.Phone.Storage API を使用して、SD カードから特定のファイルの種類を読み取ることができます。ファイルを読み取るには、アプリではアプリのマニフェスト ファイルにファイルの関連付けを登録して、どのファイルの種類 (拡張子) を処理できるかを宣言する必要があります。ファイルの関連付けが必要なため、アプリを起動すると、SD カード上にないファイルも処理できます。ファイルの関連付けの詳細については、「Windows Phone 8 のファイルおよび URI の関連付けを使用してアプリを自動起動する」を参照してください。

このトピックのコードには、ルート マッパーのサンプルのものが使用されています。サンプルは、ファイルの関連付けの処理と SD カードからの読み取りの主要な手順を示します。

メモメモ:

ルート マッパーのサンプルは、GPX ファイルからルートを読み取ってマップ コントロールに表示します。SD カードとファイルの関連付けから GPX ファイルを読み取ることができます。どちらの場合も、単一ページ (RoutePage.xaml) が使用されます。SD カードから GPX ファイルを読み取るため、MainPage.xaml は、ページを起動する URI によって、RoutePage.xaml にファイルへのパスを送信します。詳細については、「サンプル」を参照してください。

このトピックは、次のセクションで構成されています。

アプリ マニフェスト ファイル WMAppManifest.xml の中の ID_CAP_REMOVEABLE_STORAGE 機能を指定して、SD カードにアクセスします。

<Capability Name="ID_CAP_REMOVABLE_STORAGE" />

特定のファイルの種類を処理するには、ファイルの関連付けの拡張機能を登録します。拡張機能は WMAppManifest.xml で指定します。ファイルの関連付けの拡張機能は、Tokens 要素の直後の Extensions 要素内で、次の FileTypeAssociation 要素で指定されます。

<FileTypeAssociation TaskID="_default" Name="GPX" NavUriFragment="fileToken=%s">
  <Logos>
    <Logo Size="small" IsRelative="true">Assets/Route_Mapper_Logo33x33.png</Logo>
    <Logo Size="medium" IsRelative="true">Assets/Route_Mapper_Logo69x69.png</Logo>
    <Logo Size="large" IsRelative="true">Assets/Route_Mapper_Logo176x176.png</Logo>
  </Logos>
  <SupportedFileTypes>
    <FileType ContentType="application/gpx">.gpx</FileType>
  </SupportedFileTypes>
</FileTypeAssociation>

Windows Phone マニフェスト デザイナーは Extensions 要素はサポートしていません。編集拡張機能の詳細については、「Windows Phone のアプリ マニフェスト ファイルを変更する方法」を参照してください。

SD カードから特定のファイルの種類を読み取るにはファイルの関連付けが必要なため、アプリを起動すると、SD カード上にないファイルも処理できます。これらのシナリオを処理するには、カスタム URI マッパーを追加して、正しいページへのファイルの関連付けのトークンを渡します。このコードには、サンプルの CustomURIMapper.cs ファイルのものが使用されています。


using System;
using System.Windows.Navigation;
using Windows.Phone.Storage.SharedAccess;

namespace sdkRouteMapperWP8CS
{
    class CustomURIMapper : UriMapperBase
    {
        private string tempUri;

        public override Uri MapUri(Uri uri)
        {
            tempUri = uri.ToString();

            // File association launch
            // Example launch URI: /FileTypeAssociation?fileToken=89819279-4fe0-4531-9f57-d633f0949a19
            if (tempUri.Contains("/FileTypeAssociation"))
            {
                // Get the file ID (after "fileToken=").
                int fileIDIndex = tempUri.IndexOf("fileToken=") + 10;
                string fileID = tempUri.Substring(fileIDIndex);

                // Map the file association launch to route page.
                return new Uri("/RoutePage.xaml?fileToken=" + fileID, UriKind.Relative);
            }

            // Otherwise perform normal launch.
            return uri;
        }
    }
}


この例では、ファイルの関連付けでアプリが起動すると、URI マッパーが受信 URI を RoutePage.xaml という名前のページにマップし、fileToken 値を宛先ページに渡して、ページによってファイルが開けるようにします。何らかの理由でアプリが起動すると、マッパーは受信 URI を元の状態で返します。

App.xaml.cs ファイルの InitializePhoneApplication メソッドで URI マッパーがどのように App オブジェクトに割り当てられるかを次のコードに示します。


private void InitializePhoneApplication()
{
    if (phoneApplicationInitialized)
        return;

    // Create the frame but don't set it as RootVisual yet; this allows the splash
    // screen to remain active until the application is ready to render.
    RootFrame = new PhoneApplicationFrame();
    RootFrame.Navigated += CompleteInitializePhoneApplication;

    // Assign the URI-mapper class to the application frame.
    RootFrame.UriMapper = new CustomURIMapper();


    // Handle navigation failures
    RootFrame.NavigationFailed += RootFrame_NavigationFailed;

    // Handle reset requests for clearing the backstack
    RootFrame.Navigated += CheckForResetNavigation;

    // Ensure we don't initialize again
    phoneApplicationInitialized = true;
}


ページの起動時、そのページは、ページの NavigationContext オブジェクトの QueryString プロパティを使用して、(ページを起動した) URI のすべてのパラメーターにアクセスできます。URI から fileToken パラメーターの値を抽出して、後で使用するために変数に割り当てる方法を次の例に示します。このコードは、サンプルの RoutePage.xaml.cs ファイルからのものです。


// Assign the path or token value, depending on how the page was launched.
protected override async void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    // Route is from a file association.
    if (NavigationContext.QueryString.ContainsKey("fileToken"))
    {
        _fileToken = NavigationContext.QueryString["fileToken"];
        await ProcessExternalGPXFile(_fileToken);
    }
    // Route is from the SD card.
    else if (NavigationContext.QueryString.ContainsKey("sdFilePath"))
    {
        _sdFilePath = NavigationContext.QueryString["sdFilePath"];
        await ProcessSDGPXFile(_sdFilePath);
    }
}


SD カードのファイルへのパスは、sdFilePath という名前のパラメーターを使用して、MainPage.xaml から RoutePage.xaml に渡されます。そのコードは手順 6. で解説されています。

ファイルの関連付けには、起動するファイルへのアクセスに使用できるアプリ起動 URI のトークン、fileToken が含まれます。前の手順で示されるとおり、ページでファイルにアクセスできるように、トークンを URI マッパーからページにコピーします。CopySharedFileAsync を使用して、使用する前にファイルをアプリのローカル フォルダーにコピーします。コピーする前にファイルの名前にアクセスする場合は、ページまたは URI マッパーから GetSharedFileName メソッドを呼び出すことができます。サンプルの RoutePage.xaml で、ProcessExternalGPXFile メソッドはトークンを使用してファイルをアプリのローカル フォルダーにコピーしています。


// Process a route from a file association.
public async Task ProcessExternalGPXFile(string fileToken)
{
    // Create or open the routes folder.
    IStorageFolder routesFolder = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync(ROUTES_FOLDER_NAME, CreationCollisionOption.OpenIfExists);

    // Get the full file name of the route (.GPX file) from the file association.
    string incomingRouteFilename = Windows.Phone.Storage.SharedAccess.SharedStorageAccessManager.GetSharedFileName(fileToken);

    // Copy the route (.GPX file) to the Routes folder.
    IStorageFile routeFile = await Windows.Phone.Storage.SharedAccess.SharedStorageAccessManager.CopySharedFileAsync((StorageFolder)routesFolder, incomingRouteFilename, NameCollisionOption.GenerateUniqueName, fileToken);

    // Create a stream for the route.
    var routeStream = await routeFile.OpenReadAsync();

    // Read the route data.
    ReadGPXFile(routeStream.AsStream());
}


この例に示す ReadGPXFile メソッドは、ルート データを処理して、マップ コントロールに描画します。アプリにおけるマップの使用方法の詳細については、「Windows Phone 8 のマップとナビゲーション」を参照してください。

ルート マッパーのサンプルでは、SD カード機能が 2 つ別々の部分に分割されています。SD カードをスキャンする機能と Path からファイルを開く機能です。次のコードで、アプリは SD カードの GPX ファイルをスキャンし、そのファイル パスを Routes という名前の ObservableCollection<T> に保存します。MainPage.xaml で、RoutesgpxFilesListBox という名前の ListBox にバインドされているため、アプリで SD カードに存在する GPX ファイルの名前を表示できます。


// Connect to the current SD card.
ExternalStorageDevice _sdCard = (await ExternalStorage.GetExternalStorageDevicesAsync()).FirstOrDefault();

// If the SD card is present, add GPX files to the Routes collection.
if (_sdCard != null)
{
    try
    {
        // Look for a folder on the SD card named Routes.
        ExternalStorageFolder routesFolder = await _sdCard.GetFolderAsync("Routes");

        // Get all files from the Routes folder.
        IEnumerable<ExternalStorageFile> routeFiles = await routesFolder.GetFilesAsync();

        // Add each GPX file to the Routes collection.
        foreach (ExternalStorageFile esf in routeFiles)
        {
            if (esf.Path.EndsWith(".gpx"))
            {
                Routes.Add(esf);
            }
        }
    }
    catch (FileNotFoundException)
    {
        // No Routes folder is present.
        MessageBox.Show("The Routes folder is missing on your SD card. Add a Routes folder containing at least one .GPX file and try again.");
    }
}
else 
{
    // No SD card is present.
    MessageBox.Show("The SD card is mssing. Insert an SD card that has a Routes folder containing at least one .GPX file and try again.");
}


ユーザーが gpxFilesListBox に表示される GPX ファイルをタップすると、MainPage.xaml によって RoutePage.xaml が起動し、ファイル パスを URI パラメーターとして渡します。gpxFilesListBoxRoutes にバインドされていて、Routes の型が ExternalStorageFile であるため、gpxFilesListBox_SelectionChanged_1 イベント ハンドラーによって返される sender パラメーターを使用して、SD カードのファイル パスにアクセスできます。URI が作成されるときに、次のように Path にアクセスされます。


// When a different route is selected, launch the RoutePage and send the file path with the URI.
private void gpxFilesListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
    ListBox lb = (ListBox)sender;

    if (lb.SelectedItem != null)
    {
        ExternalStorageFile esf = (ExternalStorageFile)lb.SelectedItem;
        NavigationService.Navigate(new Uri("/RoutePage.xaml?sdFilePath=" + esf.Path, UriKind.Relative));
    }
}


最後に RoutePage.xaml で、ProcessSDGPXFile メソッドはパスを使用して SD カードからファイルを取得し、ReadGPXFiles メソッドに対してそのファイルへのストリームを開きます。


// Process a route from the SD card.
private async Task ProcessSDGPXFile(string _sdFilePath)
{
    // Connect to the current SD card.
    ExternalStorageDevice sdCard = (await ExternalStorage.GetExternalStorageDevicesAsync()).FirstOrDefault();

    // If the SD card is present, get the route from the SD card.
    if (sdCard != null)
    {
        try
        {
            // Get the route (.GPX file) from the SD card.
            ExternalStorageFile file = await sdCard.GetFileAsync(_sdFilePath);

            // Create a stream for the route.
            Stream s = await file.OpenForReadAsync();

            // Read the route data.
            ReadGPXFile(s);
        }
        catch (FileNotFoundException)
        {
            // The route is not present on the SD card.
            MessageBox.Show("That route is missing on your SD card.");
        }
    }
    else
    {
        // No SD card is present.
        MessageBox.Show("The SD card is mssing. Insert an SD card that has a Routes folder containing at least one .GPX file and try again.");
    }
}


ReadGPXFiles がマップ コントロール上のルートをどのように表示するかの詳細については、ルート マッパーのサンプルをダウンロードしてください。

この情報は役に立ちましたか。
(残り 1500 文字)
フィードバックをいただき、ありがとうございました
表示:
© 2014 Microsoft. All rights reserved.