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");
Related
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;
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
I have a content of dash mpd file on string variable
String MPDString = "<?xml version="1.0"?>
" +
"<!-- MPD file Generated with GPAC version 0.5.2-DEV-revVersion: 0.5.2-426-gc5ad4e4+dfsg5-1build1 at 2018-03-07T11:10:44.851Z-->\n" +
...........
</MPD>
";
I want to use this string as dashsource but confused
I looked the link : Create MPD file from String
But still confused
Can anyone please provide me some more information
If you look at the answer you linked to in your question you will see the last example is creating the manifest from a string named 'manifestString'.
DataSource.Factory manifestDataSourceFactory = new DataSource.Factory() {
#Override
public DataSource createDataSource() {
return new ByteArrayDataSource(manifestString.getBytes());
}
};
Assunming your 'MPDString' in your example is a correctly formatted mod then you simply use it above in place of 'manifestString':
DataSource.Factory manifestDataSourceFactory = new DataSource.Factory() {
#Override
public DataSource createDataSource() {
return new ByteArrayDataSource(MPDString.getBytes());
}
};
I'm going to use a pre-populated SQLite database in an Android game which I'm creating using Unity .
Since the simple way doesn't work on Android (It works perfect on Windows thou), I've followed this tutorial to use my database in an Android app.
public void OpenDB(string p) //p is the database name
{
// check if file exists in Application.persistentDataPath
string filepath = Application.persistentDataPath + "/" + p;
if(!File.Exists(filepath))
{
// if it doesn't ->
// open StreamingAssets directory and load the db ->
WWW loadDB = new WWW("jar:file://" + Application.dataPath + "!/assets/" + p); // this is the path to your StreamingAssets in android
while(!loadDB.isDone) {} // CAREFUL here, for safety reasons you shouldn't let this while loop unattended, place a timer and error check
// then save to Application.persistentDataPath
File.WriteAllBytes(filepath, loadDB.bytes);
}
//open db connection
connection = "URI=file:" + filepath;
dbcon = new SqliteConnection(connection);
dbcon.Open();
}
When I run this code, I get following error:
SqliteSyntaxException: file is encrypted or is not a database
Here's the full error:
SqliteSyntaxException: file is encrypted or is not a database
Mono.Data.SqliteClient.SqliteCommand.GetNextStatement (IntPtr pzStart,
System.IntPtr& pzTail, System.IntPtr& pStmt)
Mono.Data.SqliteClient.SqliteCommand.ExecuteReader (CommandBehavior
behavior, Boolean want_results, System.Int32& rows_affected)
Mono.Data.SqliteClient.SqliteCommand.ExecuteReader (CommandBehavior
behavior) Mono.Data.SqliteClient.SqliteCommand.ExecuteDbDataReader
(CommandBehavior behavior) System.Data.Common.DbCommand.ExecuteReader
() System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader
() dbAccess.SingleSelectWhere (System.String tableName, System.String
itemToSelect, System.String wCol, System.String wPar, System.String
wValue) (at Assets/dbAccess.cs:152)
I've downloaded the example from that post, and got the same error.
I'm suspicious about this line:
File.WriteAllBytes(filepath, loadDB.bytes);
and my thought is for some reason, it can't write the database data into the file.
Does anyone know how to solve this?
I solved the problem thanks to this blog.
This code works perfect on every platform due to the if statements which will do different behaviors depending on which platform the app is running on.
Here's the DataService.cs which do the important parts (or maybe I better say the whole part)
using SQLite4Unity3d;
using UnityEngine;
#if !UNITY_EDITOR
using System.Collections;
using System.IO;
#endif
using System.Collections.Generic;
public class DataService {
private SQLiteConnection _connection;
public DataService(string DatabaseName){
#if UNITY_EDITOR
var dbPath = string.Format(#"Assets/StreamingAssets/{0}", DatabaseName);
#else
// check if file exists in Application.persistentDataPath
var filepath = string.Format("{0}/{1}", Application.persistentDataPath, DatabaseName);
if (!File.Exists(filepath))
{
Debug.Log("Database not in Persistent path");
// if it doesn't ->
// open StreamingAssets directory and load the db ->
#if UNITY_ANDROID
var loadDb = new WWW("jar:file://" + Application.dataPath + "!/assets/" + DatabaseName); // this is the path to your StreamingAssets in android
while (!loadDb.isDone) { } // CAREFUL here, for safety reasons you shouldn't let this while loop unattended, place a timer and error check
// then save to Application.persistentDataPath
File.WriteAllBytes(filepath, loadDb.bytes);
#elif UNITY_IOS
var loadDb = Application.dataPath + "/Raw/" + DatabaseName; // this is the path to your StreamingAssets in iOS
// then save to Application.persistentDataPath
File.Copy(loadDb, filepath);
#elif UNITY_WP8
var loadDb = Application.dataPath + "/StreamingAssets/" + DatabaseName; // this is the path to your StreamingAssets in iOS
// then save to Application.persistentDataPath
File.Copy(loadDb, filepath);
#elif UNITY_WINRT
var loadDb = Application.dataPath + "/StreamingAssets/" + DatabaseName; // this is the path to your StreamingAssets in iOS
// then save to Application.persistentDataPath
File.Copy(loadDb, filepath);
#else
var loadDb = Application.dataPath + "/StreamingAssets/" + DatabaseName; // this is the path to your StreamingAssets in iOS
// then save to Application.persistentDataPath
File.Copy(loadDb, filepath);
#endif
Debug.Log("Database written");
}
var dbPath = filepath;
#endif
_connection = new SQLiteConnection(dbPath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create);
Debug.Log("Final PATH: " + dbPath);
}
public void CreateDB(){
_connection.DropTable<Person> ();
_connection.CreateTable<Person> ();
_connection.InsertAll (new[]{
new Person{
Id = 1,
Name = "Tom",
Surname = "Perez",
Age = 56
},
new Person{
Id = 2,
Name = "Fred",
Surname = "Arthurson",
Age = 16
},
new Person{
Id = 3,
Name = "John",
Surname = "Doe",
Age = 25
},
new Person{
Id = 4,
Name = "Roberto",
Surname = "Huertas",
Age = 37
}
});
}
public IEnumerable<Person> GetPersons(){
return _connection.Table<Person>();
}
public IEnumerable<Person> GetPersonsNamedRoberto(){
return _connection.Table<Person>().Where(x => x.Name == "Roberto");
}
public Person GetJohnny(){
return _connection.Table<Person>().Where(x => x.Name == "Johnny").FirstOrDefault();
}
public Person CreatePerson(){
var p = new Person{
Name = "Johnny",
Surname = "Mnemonic",
Age = 21
};
_connection.Insert (p);
return p;
}
}
It follows by two other script to create or use the existing database.
ExistingDBScript.cs
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
public class ExistingDBScript : MonoBehaviour {
public Text DebugText;
// Use this for initialization
void Start () {
var ds = new DataService ("existing.db");
//ds.CreateDB ();
var people = ds.GetPersons ();
ToConsole (people);
people = ds.GetPersonsNamedRoberto ();
ToConsole("Searching for Roberto ...");
ToConsole (people);
ds.CreatePerson ();
ToConsole("New person has been created");
var p = ds.GetJohnny ();
ToConsole(p.ToString());
}
private void ToConsole(IEnumerable<Person> people){
foreach (var person in people) {
ToConsole(person.ToString());
}
}
private void ToConsole(string msg){
DebugText.text += System.Environment.NewLine + msg;
Debug.Log (msg);
}
}
CreateDBScript.cs
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
public class CreateDBScript : MonoBehaviour {
public Text DebugText;
// Use this for initialization
void Start () {
StartSync();
}
private void StartSync()
{
var ds = new DataService("tempDatabase.db");
ds.CreateDB();
var people = ds.GetPersons ();
ToConsole (people);
people = ds.GetPersonsNamedRoberto ();
ToConsole("Searching for Roberto ...");
ToConsole (people);
}
private void ToConsole(IEnumerable<Person> people){
foreach (var person in people) {
ToConsole(person.ToString());
}
}
private void ToConsole(string msg){
DebugText.text += System.Environment.NewLine + msg;
Debug.Log (msg);
}
}
And the person script, demonstrates the person table in the database
using SQLite4Unity3d;
public class Person {
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public override string ToString ()
{
return string.Format ("[Person: Id={0}, Name={1}, Surname={2}, Age={3}]", Id, Name, Surname, Age);
}
}
Also you need to add plugins and Sqlite.cs to your project which you can find in the git repository
It helped me to overcome the issue, Hope it help the others as well.
I'm working on an android application (first application-beginner) and I'm trying to save data when the app closes to load again.
The data I want to store is a list of books, and each book contains info (author, date, etc) and a bitmap containing the book's picture. I tried using GSON to convert the list to JSON and store in SharedPreferences but that caused problems because of the bitmap.
How should I save the file and retrieve it again when the app launches ?
This is a brief version of the code
Library Class
public class Library {
private ArrayList<Entry> library ;
public Library () {
library = new ArrayList<Entry>();
}
public void addEntry( Entry entry ) {
library.add(entry);
}
public void removeEntry ( Entry entry ) {
if (library.contains(entry))
library.remove(entry);
else Log.d ( "Library" , "Entry Not Found");
}
public ArrayList<Entry> getLibrary() {
return library;
}
#Override
public String toString() {
return "Library{" +
"library=" + library +
'}';
}
}
Entry Class
public class Entry {
Book book ;
final LocalDate borrowDate;
LocalDate dueDate;
//some methods for application
}
Book Class
public class Book implements Parcelable {
private String title;
private String author;
private String isbn ;
private double rating;
private int ratingCount;
private int pageCount;
private transient Bitmap image;
private String overview;
//some methods
}
Don't put the bitmap in sharedpreferences. Save it in file.
If you need to persist the bitmap, you can assign it to a static field.
You can also convert it to a 64 bit String.. but that is bad design (and I think it is a very slow and expensive operation!):
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos); //bm is the bitmap object
byte[] b = baos.toByteArray();
String encoded = Base64.encodeToString(b, Base64.DEFAULT);
^ Save that to SharedPreferece. Now to decode:
byte[] imageAsBytes = Base64.decode(encoded.getBytes());
ImageView image = (ImageView)this.findViewById(R.id.ImageView);
image.setImageBitmap(BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length));
Use Picasso and load the urls directly instead of downloading and saving as bitmap
Picasso.with(mContext)
.load("imageURL here")
.placeholder(R.drawable.default_pic)
.error(R.drawable.error_pic)
.resizeDimen(100, 100)
.centerCrop()
.into(holderOrderHistory.mIcon);