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
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:
<SPAN class="comment token">// "Topographic.tpk" is in the application's "Assets" folder: Build action = "Content", Copy = "Do not copy"</SPAN> <SPAN class="keyword token">var</SPAN> tpkFile <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">await</SPAN> StorageFile<SPAN class="punctuation token">.</SPAN><SPAN class="token function">GetFileFromApplicationUriAsync</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">Uri</SPAN><SPAN class="punctuation token">(</SPAN>@"ms<SPAN class="operator token">-</SPAN>appx<SPAN class="punctuation token">:</SPAN><SPAN class="operator token">/</SPAN><SPAN class="comment token">//Assets/Topographic.tpk"));</SPAN> <SPAN class="comment token">// After opening the file from the app's Assets folder, use the path to create the tile cache</SPAN> TileCache tileCache <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">TileCache</SPAN><SPAN class="punctuation token">(</SPAN>tpkFile<SPAN class="punctuation token">.</SPAN>Path<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">// Load the cache using that file </SPAN> <SPAN class="comment token">// Note: this is where an exception is thrown if a file is not accessible</SPAN> <SPAN class="keyword token">await</SPAN> tileCache<SPAN class="punctuation token">.</SPAN><SPAN class="token function">LoadAsync</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">// Make a new tiled layer from the local cache</SPAN> ArcGISTiledLayer localTileLayer <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">ArcGISTiledLayer</SPAN><SPAN class="punctuation token">(</SPAN>tileCache<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">// Add it to the map</SPAN> <SPAN class="keyword token">var</SPAN> map <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">Map</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> map<SPAN class="punctuation token">.</SPAN>Basemap<SPAN class="punctuation token">.</SPAN>BaseLayers<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Add</SPAN><SPAN class="punctuation token">(</SPAN>localTileLayer<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> MyMapView<SPAN class="punctuation token">.</SPAN>Map <SPAN class="operator token">=</SPAN> map<SPAN class="punctuation token">;</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
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:
<SPAN class="comment token">// Create a file picker to get a *.tpk file from the user</SPAN> FileOpenPicker openPicker <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">FileOpenPicker</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> openPicker<SPAN class="punctuation token">.</SPAN>FileTypeFilter<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Add</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">".tpk"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> openPicker<SPAN class="punctuation token">.</SPAN>SuggestedStartLocation <SPAN class="operator token">=</SPAN> PickerLocationId<SPAN class="punctuation token">.</SPAN>PicturesLibrary<SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">// Show the picker and get the selected file</SPAN> StorageFile selectedFile <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">await</SPAN> openPicker<SPAN class="punctuation token">.</SPAN><SPAN class="token function">PickSingleFileAsync</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="keyword token">if</SPAN><SPAN class="punctuation token">(</SPAN>selectedFile <SPAN class="operator token">==</SPAN> <SPAN class="keyword token">null</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="punctuation token">{</SPAN> <SPAN class="keyword token">return</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="punctuation token">}</SPAN> <SPAN class="comment token">// Open the selected .tpk file for read</SPAN> <SPAN class="keyword token">var</SPAN> stream <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">await</SPAN> selectedFile<SPAN class="punctuation token">.</SPAN><SPAN class="token function">OpenReadAsync</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">// Create a local copy of the tpk file; replace if exists</SPAN> StorageFolder localStorage <SPAN class="operator token">=</SPAN> ApplicationData<SPAN class="punctuation token">.</SPAN>Current<SPAN class="punctuation token">.</SPAN>LocalFolder<SPAN class="punctuation token">;</SPAN> StorageFile localTpkFile <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">await</SPAN> localStorage<SPAN class="punctuation token">.</SPAN><SPAN class="token function">CreateFileAsync</SPAN><SPAN class="punctuation token">(</SPAN>selectedFile<SPAN class="punctuation token">.</SPAN>Name<SPAN class="punctuation token">,</SPAN> CreationCollisionOption<SPAN class="punctuation token">.</SPAN>ReplaceExisting<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">// Write the contents of the selected .tpk to the new local file</SPAN> <SPAN class="keyword token">var</SPAN> writeStream <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">await</SPAN> localTpkFile<SPAN class="punctuation token">.</SPAN><SPAN class="token function">OpenStreamForWriteAsync</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> stream<SPAN class="punctuation token">.</SPAN><SPAN class="token function">AsStreamForRead</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="token function">CopyTo</SPAN><SPAN class="punctuation token">(</SPAN>writeStream<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> writeStream<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Flush</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">// ** Important to dispose ... won't be able to access the file otherwise!</SPAN> writeStream<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Dispose</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">// Create a new TileCache with the path to the *local storage* version of the file</SPAN> TileCache tileCache <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">TileCache</SPAN><SPAN class="punctuation token">(</SPAN>localTpkFile<SPAN class="punctuation token">.</SPAN>Path<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="keyword token">await</SPAN> tileCache<SPAN class="punctuation token">.</SPAN><SPAN class="token function">LoadAsync</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">// Create a new tile layer from the cache and add it to the map</SPAN> ArcGISTiledLayer localTileLayer <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">ArcGISTiledLayer</SPAN><SPAN class="punctuation token">(</SPAN>tileCache<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="keyword token">var</SPAN> map <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">Map</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> map<SPAN class="punctuation token">.</SPAN>Basemap<SPAN class="punctuation token">.</SPAN>BaseLayers<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Add</SPAN><SPAN class="punctuation token">(</SPAN>localTileLayer<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> MyMapView<SPAN class="punctuation token">.</SPAN>Map <SPAN class="operator token">=</SPAN> map<SPAN class="punctuation token">;</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
I hope that helps!
Thad
Los miembros registrados pueden publicar, seguir actualizaciones y más. ¿Nuevo aquí? Regístrate gratis.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.