I'm new to this SDK and how do you read a tpk file offline on a windows 10 phone using UWP? What are the restrictions of where the tpk can be loaded on windows 10 phone.?

873
1
02-06-2017 01:55 PM
WilliamWhite1
New Contributor

I'm trying to read a local .tpk file on a windows 10 phone using your .NET SDK version 100. I've tried the picture library and then found on the internet this directory is not valid for this SDK. Any help would be appreciated. Thanks  

0 Kudos
1 Reply
ThadTilton
Esri Contributor

Hi William -

I've dealt with this frustration too. 

You can use something like a FileOpenPicker to choose a file, or programmatically access one using StorageLibrary, but you're not guaranteed to have access to the returned file through its Path property (which is what the TileCache constructor takes). If your TPK file is in the app's directory, however, it's pretty easy. Here are a couple of options:

Perhaps the easiest solution is to just package your TPK file(s) with the app. You can add them to your project (in the Assets folder, for example) and give them a Build Action of "Content" and set Copy to Output Directory to "Do not copy". In your app code, you can use an "ms-appx" URI to access things in your app's local folder, like so:

// "Topographic.tpk" is in the application's "Assets" folder: Build action = "Content", Copy = "Do not copy"
var tpkFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(@"ms-appx:///Assets/Topographic.tpk"));

// After opening the file from the app's Assets folder, use the path to create the tile cache
TileCache tileCache = new TileCache(tpkFile.Path);

// Load the cache using that file
// Note: this is where an exception is thrown if a file is not accessible
await tileCache.LoadAsync();

// Make a new tiled layer from the local cache
ArcGISTiledLayer localTileLayer = new ArcGISTiledLayer(tileCache);

// Add it to the map
var map = new Map();
map.Basemap.BaseLayers.Add(localTileLayer);
MyMapView.Map = map;

If you still would like your user to select a TPK from their device and add it as a tile layer, you can take the extra step of copying the selected file to the app's local storage. Once there, you can create the TileCache using its Path. Here's an example:

    // Create a file picker to get a *.tpk file from the user
    FileOpenPicker openPicker = new FileOpenPicker();
    openPicker.FileTypeFilter.Add(".tpk");
    openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;

    // Show the picker and get the selected file
    StorageFile selectedFile = await openPicker.PickSingleFileAsync();
    if(selectedFile == null) { return; }

    // Open the selected .tpk file for read
    var stream = await selectedFile.OpenReadAsync();

    // Create a local copy of the tpk file; replace if exists
    StorageFolder localStorage = ApplicationData.Current.LocalFolder;
    StorageFile localTpkFile = await localStorage.CreateFileAsync(selectedFile.Name, CreationCollisionOption.ReplaceExisting);

    // Write the contents of the selected .tpk to the new local file
    var writeStream = await localTpkFile.OpenStreamForWriteAsync();
    stream.AsStreamForRead().CopyTo(writeStream);
    writeStream.Flush();
    // ** Important to dispose ... won't be able to access the file otherwise!
    writeStream.Dispose();

    // Create a new TileCache with the path to the *local storage* version of the file
    TileCache tileCache = new TileCache(localTpkFile.Path);
    await tileCache.LoadAsync();

    // Create a new tile layer from the cache and add it to the map
    ArcGISTiledLayer localTileLayer = new ArcGISTiledLayer(tileCache);
    var map = new Map();
    map.Basemap.BaseLayers.Add(localTileLayer);
    MyMapView.Map = map;

I hope that helps!

Thad