About Android can't load json file in Application.persistentDataPath - android

I put json file in Application.persistentDataPath,then It's can load and work on PC.
But It can't work in Android ,I'm stuck for a long time.
I found the many way , but no one can fix it .
please help me , thank you!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class QuizCon : MonoBehaviour
{
public RoundData[] allRoundData;
private string gameDataFileName = "quiz.json";
private void Start()
{
DontDestroyOnLoad(gameObject);
LoadGameData();
}
public RoundData GetCurrectRoundData()
{
return allRoundData[0];
}
private void LoadGameData()
{
string filePath = Path.Combine(Application.persistentDataPath, gameDataFileName);
if(File.Exists(filePath))
{
string dataJson = File.ReadAllText(filePath);
GameData loadedData = JsonUtility.FromJson<GameData>(dataJson);
allRoundData = loadedData.allRoundData;
}
else
{
Debug.LogError("Cannot load game data!");
}
}

Try writing the file to External (SDCard) instead of Internal.
You can change this under PlayerSettings -> Android

Related

Xamarin Forms MediaElement: Playing video selected from gallery with CrossMedia plugin

I'm trying to use the MediaElement to play a video selected from the Gallery. The path to the Video is saved within the app then bound to the MediaElement Source.
<xct:MediaElement Source="{Binding VideoUri, Converter={StaticResource VideoSourceConverter}}"
AutoPlay="False"
ShowsPlaybackControls="True"
Aspect="AspectFit"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
I'm using a converter as described in the documentation:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
if (string.IsNullOrWhiteSpace(value.ToString()))
return null;
if (value.ToString().StartsWith("http"))
return value;
return new Uri($"ms-appdata:///{value}");
}
https://learn.microsoft.com/en-gb/xamarin/community-toolkit/views/mediaelement#play-local-media
But am getting the error: Invalid UriParameter name: Source
The saved path on Android is:
"/storage/emulated/0/Android/data/[app identifier]/files/Movies/temp/[filename].mp4"
Haven't tested in iOS yet.
Any guidance will be much appreciated.
Thanks.
The Converter you used is used for the UWP. UWP could play media files that are located in the app's xxxx folder by prefixing the media file with ms-appdata:///xxxx/.
For mobile devices, when you use the CrossMedia to select the video, you could get the stream directly from the file.
I use a button to do the select operation and then use the INotifyPropertyChanged to update the binding. Here is the code for your reference.
Xaml:
<Button Clicked="Button_Clicked" Text="Select"/>
<xct:MediaElement Source="{Binding VideoUri}"
AutoPlay="False"
ShowsPlaybackControls="True"
Aspect="AspectFit"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
Code:
public partial class Page29 : ContentPage
{
Page29ViewModel viewModel = new Page29ViewModel();
public Page29()
{
InitializeComponent();
this.BindingContext = viewModel;
}
private async void Button_Clicked(object sender, EventArgs e)
{
string path = string.Empty;
MediaFile video = null;
if (CrossMedia.Current.IsPickVideoSupported)
{
video = await CrossMedia.Current.PickVideoAsync();
}
var fileName = "sample";
var newFile = Path.Combine(FileSystem.AppDataDirectory, fileName + ".mp4");
if (!File.Exists(newFile))
{
using (var inputStream = video.GetStream())
{
using (FileStream outputStream = File.Create(newFile))
{
await inputStream.CopyToAsync(outputStream);
}
}
}
viewModel.VideoUri = newFile;
}
}
public class Page29ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string _videoUri;
public string VideoUri
{
get { return _videoUri; }
set { _videoUri = value; NotifyPropertyChanged(nameof(VideoUri)); }
}
public Page29ViewModel()
{
}
}
You dont need the converter just return the path to the mediaplayer control .
mediaFile = await this._mediaPicker.PickVideoAsync();
VideoUri = mediaFile.Path;

How can I show an pdf file in xamarin pcl uwp that is outside my instal folder?

Hy, I'm working in a Xamarin PCL project with the platforms Android and UWP. As a feature the user should be able to open an pdf file.
For this I'm using Mozilla pdf.js. I have followed this link to get it done on Android and UWP.
https://developer.xamarin.com/recipes/cross-platform/xamarin-forms/controls/display-pdf/
Only for UWP I can't get it to function.
Here is my custom renderer for UWP
[assembly: ExportRenderer(typeof(PdfView),
typeof(PDF.UWP.Renderers.PdfViewRenderer))]
namespace PDF.UWP.Renderers
{
/// <summary>
/// The asset folder of the UWP app must contain the pdfjs folder and files.
/// </summary>
public class PdfViewRenderer: WebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
PdfView pdfView = Element as PdfView;
string sFile = string.Format("ms-appx-web://{0}", WebUtility.UrlEncode(pdfView.Uri));
Control.Source = new Uri(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html?file={0}", sFile));
}
}
}
}
Here is my PdfView class.
public class PdfView: WebView
{
public static readonly BindableProperty DocumentInfoProperty =
BindableProperty.Create(propertyName: nameof(TheDocumentInfo), returnType: typeof(DocumentInfo),
declaringType: typeof(PdfView), defaultValue: default(DocumentInfo));
public DocumentInfo TheDocumentInfo
{
get { return (DocumentInfo)GetValue(DocumentInfoProperty); }
set { SetValue(DocumentInfoProperty, value); }
}
public string Uri { get { return TheDocumentInfo.LocalUrl; } }
public string FileName { get { return TheDocumentInfo.FileName; } }
}
The file location on uwp =
"ms-appx-web://C%3A%5CUsers%5CUser%5CAppData%5CLocal%5CPackages%5CPDFTEST.UWP_v4j5n0js0cwst%5CLocalState%5CPDFTest.pdf"
And this is correct.
But the error is:
Message: Unexpected server response (0) while retrieving PDF
"ms-appx-web://C:/Users/User/AppData/Local/Packages/PDFTest.UWP_v4j5n0js0cwst/LocalState/PDFTest.pdf/".
UPDATE
I have recreated the renderer to:
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
// TODO: testen
PdfView pdfView = Element as PdfView;
string sFile = string.Format("ms-appx-web://{0}/{1}", pdfView.Uri.Replace(pdfView.FileName, ""), WebUtility.UrlEncode(pdfView.FileName));
Control.Source = new Uri(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html?file={0}", sFile));
}
}
I don't know if this is the solution to my problem but this error is gone.
The error now is:
PDF.js v1.1.366 (build: 9e9df56)
Message: stream must have data
UPDATE (I don't know if u should add this in this question or if I should made another one).
My error is still
stream must have data
I know now why. Because I'm developing a UWP application and I want to access a file outside my instal folder. This location is
C:\Users\User\AppData\Local\Packages\PDFTest.UWP_v4j5n0js0cwst\LocalState\
Apperently I can't access files outside my instalation folder. This includes coping the file to my install folder and read it there.
UPDATE
I have 2 versions of pdf.js in my project. (1.1.366 and 1.9.426)
This is my code now
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
PdfView pdfView = Element as PdfView;
var uriString = "ms-appdata:///local/" + WebUtility.UrlEncode(pdfView.FileName);
Control.Source = new Uri(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html?file={0}", uriString));
}
}
When I try to open the file with Launcher.LaunchFileAsync and use the uriString it opens my browser and shows me the file.
In my application I get the following error's
(v1.1.366) Stream must have data.
(v1.9.426) Unexpected server response (0) while retrieving PDF "ms-appdata:///local/PDFTest.pdf".
I know that the pdf uri is correct and accessible but it still doesn't work.
(for v1.9.426 I have added in viewer.js
var HOSTED_VIEWER_ORIGINS = ['null', 'http://mozilla.github.io', 'https://mozilla.github.io', 'ms-appdata://', 'ms-appx-web://PDFTest.uwp'];)
link to the testproject
I know now why. Because I'm developing a UWP application and I want to access a file outside my instal folder. This location is
You have use ms-appx-web: uri scheme as your pdf file access path. Actually, your pdf path is C:\Users\User\AppData\Local\Packages\PDFTest.UWP_v4j5n0js0cwst\LocalState\ that stored in the app's local folder. So the file will not be accessed.
I have also tested with "ms-appdata:///local/" uri scheme to access the pdf file base on your project. Unfortunately, It can't be recognised by viewer.js.
And then, I tried to convert pdf file into Base64String then opening it by calling the openPdfAsBase64 JS function in the viewer.js.
private async Task<string> OpenAndConvert(string FileName)
{
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.GetFileAsync(FileName);
var filebuffer = await file.OpenAsync(FileAccessMode.Read);
var reader = new DataReader(filebuffer.GetInputStreamAt(0));
var bytes = new byte[filebuffer.Size];
await reader.LoadAsync((uint)filebuffer.Size);
reader.ReadBytes(bytes);
return Convert.ToBase64String(bytes);
}
Usage
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
Control.Source = new Uri("ms-appx-web:///Assets/pdfjs3/web/viewer.html");
Control.LoadCompleted += Control_LoadCompleted;
}
}
private async void Control_LoadCompleted(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
CustomWebView pdfView = Element as CustomWebView;
if (string.IsNullOrEmpty(pdfView?.Filename)) return;
var ret = await OpenAndConvert(pdfView?.Filename);
var obj = await Control.InvokeScriptAsync("openPdfAsBase64", new[] { ret });
}
You could use this viewer.js that was added openPdfAsBase64 method.
Got hints following: How to embed the PDFjs into your C# Project.

How can I read xml on android with unity?

So here's my code, it works perfectly fine in unity editor but not on android, it only reads the first line of the xml file.
I don't know what is wrong with it.
The file exists on the phone but it only reads the first line.
In the unity editor it works perfectly fine.
Thank for your help.
using System.Xml;
using System.Xml.Serialization;
public class Mission
{ [XmlAttribute("id")]
public int Id;
public string description;
public int ordre;
}
Here is the class that loads the xml
using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;
[XmlRoot("Missionss")]
public class Missions{
[XmlArray("Missions"), XmlArrayItem("Mission")]
public List<Mission> Mission_List;
private Missions(){}
public static Missions LoadFromFile(string filepath){
XmlSerializer serializer = new XmlSerializer(typeof(Missions));
using(FileStream stream = new FileStream(filepath, FileMode.Open))
{
return serializer.Deserialize(stream) as Missions;
}
}
public void Save (string path)
{
XmlSerializer serializer = new XmlSerializer (typeof(Missions));
using (FileStream stream = new FileStream (path, FileMode.Create)) {
serializer.Serialize (stream, this);
}
}
}
and finally:
public void LoadXML(){
string filename="/phases.xml";
string filename1="/missions.xml";
phases = Phases.LoadFromFile(Application.persistentDataPath + filename);
missions = Missions.LoadFromFile (Application.persistentDataPath + filename1);
}
public void save(){
phases.Save(Application.streamingAssetsPath + "phases.xml");
missions.Save(Application.streamingAssetsPath + "missions.xml");
}
dont you need "\" written somewhere? lets say: phases.Save(Application.streamingAssetsPath +"\\"+ "phases.xml");

After downloading file .obb not find the next scene

I am making an application in Unity3D and I have a problem with the file .obb. After downloading the file .obb from my dropbox try to open the next scene and tells me I can not find it. If I close the application and return open functioning OK. What can be?
using UnityEngine;
using System.Collections;
using System.IO;
using System;
using UnityEngine.UI;
public class DownloadFile : MonoBehaviour {
private string path;
private string url = "";
private float m_CurrentValue = 0;
public GameObject btnStart;
private string nextScene = "Splash";
void log( string t )
{
print("MYLOG " + t);
}
// Use this for initialization
void Start ()
{
CheckObb ();
}
// Update is called once per frame
void Update () {
}
void CheckObb()
{
if (!GooglePlayDownloader.RunningOnAndroid())
{
log ( "Use GooglePlayDownloader only on Android device!");
return;
}
string expPath = GooglePlayDownloader.GetExpansionFilePath();
if (expPath == null)
{
log("External storage is not available!");
}
else
{
string package = GooglePlayDownloader.Package();
int version = GooglePlayDownloader.Version();
path = String.Format("{0}/main.{1}.{2}.obb", expPath, version, package);
url = String.Format("https://www.dropbox.com/s/xxxxxxxxxxxxxx/main.{0}.{1}.obb?dl=1", version, package);
if (File.Exists(path))
{
// After downloading the file if you close the game and you become open, OK ¿?
Application.LoadLevel(nextScene);
}
else
{
//check if directory doesn't exit
if(!Directory.Exists(expPath))
{
//if it doesn't, create it
Directory.CreateDirectory(expPath);
}
btnStart.SetActive(true);
}
}
}
// Click Start button download obb
public void ClickStart()
{
btnStart.SetActive(false);
StartCoroutine(DownloadObb());
}
// Download obb
IEnumerator DownloadObb() {
WWW download = new WWW(url);
while( !download.isDone ) {
m_CurrentValue = download.progress * 100;
yield return null;
}
if (!string.IsNullOrEmpty(download.error)) {
//Error
} else
{
// success!
File.WriteAllBytes (path, download.bytes);
// Here says that there is the scene
Application.LoadLevel(nextScene);
}
}
}
I tried to upload the apk and obb as alpha version in the developer console but when I go to download the .obb tells me this:
"Download failed because the resources could not be found"
Thanks.
I follow this tutorial in order to split my Unity app into *.obb file. It help me a lot.
Now, when I was performing my test in GooglePlay as an Alpha version everything goes OK, the download of the obb file and the process in the app but it doesn`t load my first scene.
It took me a lot to notice that when I put the loader as the scene 0 my index to load the next Scene was wrong. I know it is a poor error but thats the History behind my 10 hours research.
Hope you'll find useful.

Convert Jsonstring from Web request to String

I tried to parse json from Web request in Xamarin Android application. But i am getting the below json string
[{\"type1\":val1,\"type2\":\"val2",\"type3\":\"val3\",\"type4\":val4},
{\"type1\":val1,\"type2\":\"val2",\"type3\":\"val3\",\"type4\":val4}]
How to convert this into string like below
[{"type1":"val1","type2":"val2","type3":"val3","type4":"val4"},
{"type1":"val1","type2":"val2","type3":"val3","type4":"val4"}]
Did you get the string value by copying the C# runtime value? If so, it looks to be correct with some minor errors.
[{\"type1\":val1,\"type2\":\"val2",\"type3\":\"val3\",\"type4\":val4},
{\"type1\":val1,\"type2\":\"val2",\"type3\":\"val3\",\"type4\":val4}]
Should probable be:
[{\"type1\":\"val1\",\"type2\":\"val2\",\"type3\":\"val3\",\"type4\":\"val4\"},
{\"type1\":\"val1\",\"type2\":\"val2\",\"type3\":\"val3\",\"type4\":\"val4\"}]
Some of the val*'s didn't have quotes at all and the type2 was missing \ on the quote.
Is it your own web service? Did your web request specify JSON as format? If the service is running JavaScript, does it call JSON.stringify(...) to normalize the JSON object? If you are using MVC or other MS technology make sure you are not wrapping the response in double JSON (f.e. returning a string by the controller where the string is JSON serialized as this will cause the doubling).
Good tool to verify the JSON returned by the web service is PostMan. If it also returns the string with the \'s in it then something is wrong with the service itself.
Here is a little tester for Android with JSON.Net serializer:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Collections.Generic;
using Android.Util;
namespace JsonTest
{
public class TypeClass
{
public string type1 { get; set; }
public string type2 { get; set; }
public string type3 { get; set; }
public string type4 { get; set; }
}
[Activity (Label = "JsonTest", MainLauncher = true)]
public class MainActivity : Activity
{
int count = 1;
private const string JsonText = "[{\"type1\":\"val1\",\"type2\":\"val2\",\"type3\":\"val3\",\"type4\":\"val4\"}," +
"{\"type1\":\"val1\",\"type2\":\"val2\",\"type3\":\"val3\",\"type4\":\"val4\"}]";
protected override void OnCreate(Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button> (Resource.Id.myButton);
button.Click += delegate
{
var resp = Newtonsoft.Json.JsonConvert.DeserializeObject<List<TypeClass>>(JsonText);
foreach (var t in resp)
{
Log.Info("Type1", t.type1);
Log.Info("Type2", t.type2);
Log.Info("Type3", t.type3);
Log.Info("Type4", t.type4);
}
};
}
}
}
Try this
String jsonString = json.replaceAll("\\\\", "");

Categories

Resources