How to reference asset in Assets folder via Uri?

5704
2
08-20-2020 03:13 PM
James_C_Dorsey
Emerging Contributor

Is it possible to read a local asset (.glb file) as a symbol into a SceneView in a Xamarin.Android AR project?  I'm using the Android template from here - ArcGIS Runtime SDK for .NET - AR Templates - Visual Studio Marketplace 

Here's the code, I get a File Not Found error on the ModelSceneSymbol.CreateAsync() line.

GraphicsOverlay planeOverlay = new GraphicsOverlay();
planeOverlay.SceneProperties.SurfacePlacement = SurfacePlacement.Relative;
arSceneView.GraphicsOverlays.Add(planeOverlay);

Uri modelSourceUri = new Uri(@"ms-appx:///Assets/Duck.glb");
var modelSymbol = await ModelSceneSymbol.CreateAsync(modelSourceUri, 1000);

MapPoint location = new MapPoint(-71.0096, 42.3656, 20, SpatialReferences.Wgs84);
Graphic modelGraphic = new Graphic(location, modelSymbol);
planeOverlay.Graphics.Add(modelGraphic);

The asset is in the Assets folder in the project.  I've tried different BuildActions on the file (AndroidAsset, Content), no luck.  I've tried different Uri schemes (file:///) without luck.  I've also tried loading the asset from a url.  In this case I don't get an error, but the model doesn't render.

The model I'm trying to load is this (also attached) - glTF-Sample-Models/Duck.glb at master · KhronosGroup/glTF-Sample-Models · GitHub 

For reference, in a WPF app I was able to do the same thing successfully with more or less the same code.  So essentially if its possible, what is the correct way to create a Uri to an asset?

Thanks,

Chris

Tags (3)
0 Kudos
2 Replies
dotMorten_esri
Esri Notable Contributor

The ms-appx:/// path is a UWP type of path. It won't work in Android.

Android Assets are packaged with the app and can't be read directly. Typically you'll have to use the Android APIs to unpack the file to disk first.

James_C_Dorsey
Emerging Contributor

Thanks Morten Nielsen‌, you set me on the right path.  Ultimately I had to read the asset, write it back to internal storage, then use that path to create the Uri.  Also make sure your asset has a BuildAction of AndroidAsset. Here's what I used:

GraphicsOverlay planeOverlay = new GraphicsOverlay();
planeOverlay.SceneProperties.SurfacePlacement = SurfacePlacement.Relative;
arSceneView.GraphicsOverlays.Add(planeOverlay);

// open stream from asset manager
Stream stream = Assets.Open("Duck.glb");

// save back to data folder
var backingFile = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "Duck.glb");
var fileStream = File.Create(backingFile);
stream.CopyTo(fileStream);
fileStream.Close();

// create uri from newly saved file
Uri modelSourceUri = new Uri(backingFile, UriKind.Absolute);

var modelSymbol = await ModelSceneSymbol.CreateAsync(modelSourceUri, 1000);
MapPoint location = new MapPoint(-71.0096, 42.3656, 20, SpatialReferences.Wgs84);
Graphic modelGraphic = new Graphic(location, modelSymbol);
planeOverlay.Graphics.Add(modelGraphic);

0 Kudos