4

Currently I am trying to load file "json" from my Android project, using Xamarin.Forms.

Here is my code:

var path = @"client_secret.json";
using (var stream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
}

For path I tried many different cases to place "client_secret.json" in project root folder, assets folder, bin, bin>Debug, bin>Release as well for ".Droid" project and PCL too. I tried also to change file build action to "Content", "Embedded Resource", "Additional Files", "AndroidResource" and "AndroidEnvironment". I tried also to change "client_secret.json" and use physical path (D:\Apps....\Project.Android\client_secret.json) and try to find it in different folders:

Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath

Directory.GetFiles(Directory.GetCurrentDirectory())

Directory.GetFiles(Android.OS.Environment.RootDirectory.AbsolutePath)

Directory.GetFiles(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal))

And still nowhere I find it. "Copy to output" file property is changed to "Copy always" and still no result.

Does anybody know what I am doing wrong in that case to make FileStream on this file?

Thanks in advance

Brandon Minnick
  • 13,342
  • 15
  • 65
  • 123

2 Answers2

2

Using Android Assets

AssetManager assets = this.Assets;
using (StreamReader sr = new StreamReader (assets.Open ("client_secret.json")))
{
    content = sr.ReadToEnd ();
}
Jason
  • 86,222
  • 15
  • 131
  • 146
  • Thank you for your answer. But can I read it as FileStream? Because latter I am using method which required "FileStream" type. Thanks –  Aug 25 '17 at 21:20
  • not that I'm aware of. What are you trying to do that will only work with a FileStream? – Jason Aug 25 '17 at 21:32
  • I am trying to use DriveService, which comes from Google API. But before that I have to authenticate user, so I can access his files. And in official documentation of Google, to achieve successful authentication I have to use FileStream with "client_secret.json", which they provide. –  Aug 25 '17 at 21:50
2

1. In order to use FileStream - you will most probably need the absolute file path name; which is not possible for an asset file (there are cases where you can use URL syntax file:///android_asset/... like in WebView etc. but not in FileStream);

What you can do is get access to InputStream using AssetManager, which should be compatible with GoogleClientSecrets.Load() method.

using(var stream = this.Assets.Open(@"client_secret.json"))
{
     var secrets = GoogleClientSecrets.Load(stream).Secrets;
     ...

2. Another option would be to copy your asset file to storage and then try and access in FileStream using destination path.

var path = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), @"client_secret.json");
using (var asset = Assets.Open("client_secret.json"))
    using (var dest = System.IO.File.Create(path))
         asset.CopyTo(dest);

using (var stream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
    var secrets = GoogleClientSecrets.Load(stream).Secrets;
    ...

Note: For option 1, and 2; make sure that you follow the steps to add this json file as an asset to android app

3. The next option would be to use embedded resources - and you can access file using Assembly.GetManifestResourceStream().

var assembly = typeof(MainActivity).GetTypeInfo().Assembly;
using (var stream = assembly.GetManifestResourceStream("AssemblyNamespace.client_secret.json"))
{
    var secrets = GoogleClientSecrets.Load(stream).Secrets;
    ...

Note: For option 3; make sure to follow the steps to add this json file as an embedded resource to android app or assembly

Sharada Gururaj
  • 13,471
  • 1
  • 22
  • 50
  • Hi there, thank you for your answer. I tried to use 3-rd option, but on "await GoogleWebAuthorizationBroker.AuthorizeAsync( GoogleClientSecrets.Load(stream).Secrets, Scopes, "user", CancellationToken.None);" I receive "Cannot find the specified file" –  Aug 29 '17 at 18:16
  • In third option - it is very easy to miss and use the wrong namespace while specifying resource-id. Please make sure you are using the right one. Also, did you get a chance to try option 1 or 2? – Sharada Gururaj Aug 29 '17 at 18:19
  • Also, can you please share some stacktrace of the exception you received. – Sharada Gururaj Aug 29 '17 at 18:49