Is it possible to download a folder and its contents using air for android? I would like to also use the same code on iPhone.
I need it to be stored in the application storage so we can reference the content once downloaded.
I know it's possible to download content as referenced in this question: Download Content using Air For Android
but can a person download the entire folder and again store it in the application directory?
Thanks
#lukevain? :)
Are you downloading this from a web server? If so this is not going to work and I would recommend using a php script to list all the files in the remote directory.
If this is local you can use this:
//using the application storage dir. This will work on iOS and Android
var f:File = File.applicationStorageDirectory.resolvePath("yourFolder/");
//you can also use getDirectoryListingAsync to have this run in the background
var filesList:Array = f.getDirectoryListing();
for (var i:int = 0; i < filesList.length; i++) {
trace(filesList[i].nativePath);
}
This is not the answer of how to get contents of a folder from the server but it is a way to search through a folder of your choice on the local machine. It only goes 3 levels deep and it may not be the best way to find folders because it checks to see if their extension is null and I made it assume it is a folder. Then I search in that folder. Anyway here it is.
You will need do create a text field and give it an instance name of "daText";
Here is the code:
import flash.filesystem.*;
import flash.media.*;
var myFolder:String = "images/"; /// change this to the folder of your choice :)
var desktop:File = File.applicationDirectory.resolvePath(myFolder);
var files:Array = desktop.getDirectoryListing();
for (var i:uint = 0; i < files.length; i++)
{
if (files[i].extension == null)
{
daText.text += files[i].name + "\n";
var anotherArray:File = File.applicationDirectory.resolvePath(myFolder+files[i].name);
var h:Array = anotherArray.getDirectoryListing();
for (var a:uint = 0; a < h.length; a++)
{
daText.text += "----" + h[a].name + "\n";
if (h[a].extension == null)
{
var oneMoreArray:File = File.applicationDirectory.resolvePath(myFolder+files[i].name+"/"+h[a].name+"/");
var C:Array = oneMoreArray.getDirectoryListing();
for (var B:uint = 0; B < C.length; B++)
{
daText.text += "*******"+C[B].name + "\n";
}
}
}
}
}
Related
I'm creating library in Xamarin platform and I need to get device (android,iOS and windows) font file.
In android I can get the font files from/system/fonts folder.
Android:
string[] fontfiles = System.IO.Directory.GetFiles("/system/fonts");
Can anyone share your idea to get font file from the Windows device?.
Thanks in Advance.
Sasi.
How to get font file from windows phone
You can't get system font file in Windows Phone, but you can get the system font. Refer to ptallett's blog, do the following steps :
In order to get system font in UWP, we must use DirectX, install these NuGet pacakges into your project :
SharpDX
SharpDX.Direct2D1
GetFontFiles() will return all system fonts.
public class GetFont : FontDemo.IGetFont
{
public string[] GetFontFiles()
{
var fontList = new List<string>();
var factory = new SharpDX.DirectWrite.Factory();
var fontCollection = factory.GetSystemFontCollection(false);
var familyCount = fontCollection.FontFamilyCount;
for (int i = 0; i < familyCount; i++)
{
var fontFamily = fontCollection.GetFontFamily(i);
var familyNames = fontFamily.FamilyNames;
int index;
if (!familyNames.FindLocaleName(CultureInfo.CurrentCulture.Name, out index))
{
if (!familyNames.FindLocaleName("en-us", out index))
{
index = 0;
}
}
string name = familyNames.GetString(index);
fontList.Add(name);
}
return fontList.ToArray();
}
}
Using DependencyService in your PCL to get the result :
string[] fontfiles = DependencyService.Get<IGetFont>().GetFontFiles();
I wrote some code to get all the folders inside a folder inside the StreamingAssets and then to get all the files in that folder.
It works well on Windows but I can't get it to work on Android.
Here is the code :
foreach (string s in Directory.GetDirectories(model.path + "/Levels")) {
GameObject el = (GameObject)Instantiate(listButton, Vector3.zero, Quaternion.identity);
el.transform.SetParent(grid1.transform);
string[] words = s.Split('/');
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
words = s.Split('\\');
#endif
el.GetComponentInChildren<Text>().text = words[words.Length - 1];
el.GetComponent<Button>().onClick.AddListener(() => {
MapSizeButtonClick(Int32.Parse(el.GetComponentInChildren<Text>().text));
});
}
I had to add the #if UNITY_STANDALONE_WIN for windows because of the '\'.
Then for the files inside that folder I wrote this :
foreach (string s in Directory.GetFiles(model.path + "/Levels/" + model.mapSize + "/" + model.colorNumber)) {
string[] words = s.Split('/');
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
words = s.Split('\\');
#endif
words = words[words.Length - 1].Split('.');
if (words[1] == "json") {
GameObject el = (GameObject)Instantiate(listButton, Vector3.zero, Quaternion.identity);
el.transform.SetParent(grid3.transform);
el.GetComponentInChildren<Text>().text = words[0];
el.GetComponent<Button>().onClick.AddListener(() => {
levelButtonClick(Int32.Parse(el.GetComponentInChildren<Text>().text));
});
}
}
I'm using UnityEngine.UI.Directory but I read that it can't be use on Android and I must use WWW instead. Something like this :
string xmlSetUpPath = "jar:file://" + Application.dataPath + "!/assets/xml/xmlSetUp.xml";
WWW book1WWW = new WWW(book1Path);
yield return book1WWW;
if(!File.Exists(Application.persistentDataPath + "/xml/book1.xml"))
{
File.WriteAllBytes(Application.persistentDataPath + "/xml/book1.xml", book1WWW.bytes);
}
However I couldn't find anything like Directory.getFiles() or Directory.getFolder(). So I thought I could use WWW to check if the file exists (as the file names are 1.json, 2.json, 3.json) and iterate until a file doesn't exist.
But I would also need to check if a folder exists for the 1st part of the script and I can't find how to check if a folder exists with WWW. (My folders names are also 1,2,3,4...)
So how to check if a folder exists with WWW ?
Or what else can I do ?
UPDATE :
I updated the code, now it looks like this :
for (int i = 0; i < 100; i++) {
if (Directory.Exists(Path.Combine(model.path, "Levels/" + i.ToString()))){
GameObject el = (GameObject)Instantiate(listButton, Vector3.zero, Quaternion.identity);
el.transform.SetParent(grid1.transform);
el.GetComponentInChildren<Text>().text = i.ToString();
el.GetComponent<Button>().onClick.AddListener(() => {
MapSizeButtonClick(Int32.Parse(el.GetComponentInChildren<Text>().text));
});
}
}
I use path.combine() and check every folder from 0 to 100. It works on Windows but it still doesn't work in Android.
The path is set like this :
#if UNITY_IPHONE
path = Application.dataPath + "/Raw";
#endif
#if UNITY_ANDROID
path = "jar:file://" + Application.dataPath + "!/assets";
#endif
#if UNITY_STANDALONE || UNITY_EDITOR
path = Application.dataPath + "/StreamingAssets";
#endif
QUESTION UPDATE
I made a script that generate the file paths. The paths are always the same : "FolderNumerotedFromYToX/FolderNumerotedFromYToX/FileNumerotedFrom1ToX.json". The generation works but the writing to JSON doesn't. It outputs "{}".
// Generate level list
List<KeyValuePair<int, List<KeyValuePair<int, List<int>>>>> l;
l = new List<KeyValuePair<int, List<KeyValuePair<int, List<int>>>>>();
for (int i = 1; i < 100; i++) {
if (Directory.Exists(Path.Combine(Path.Combine(Application.dataPath, "StreamingAssets"), "Levels/" + i.ToString()))) {
l.Add(new KeyValuePair<int, List<KeyValuePair<int, List<int>>>>(i, new List<KeyValuePair<int, List<int>>>()));
for (int j = 1; j < 100; j++) {
if (Directory.Exists(Path.Combine(Path.Combine(Application.dataPath, "StreamingAssets"), "Levels/" + i + "/" + j))) {
l[l.Count - 1].Value.Add(new KeyValuePair<int, List<int>>(j, new List<int>()));
int k = 1;
while (true) {
if (File.Exists(Path.Combine(Path.Combine(Application.dataPath, "StreamingAssets"), "Levels/" + i + "/" + j + "/" + k + ".json"))) {
l[l.Count - 1].Value[l[l.Count - 1].Value.Count - 1].Value.Add(k);
}
else
break;
k++;
}
}
}
}
}
string ljson = JsonUtility.ToJson(l);
var lsr = File.CreateText("Assets/StreamingAssets/levels.json");
lsr.WriteLine(ljson);
lsr.Close();
Can you help me finding a way to store this to a file ?
It may sound hard, but you really have to use the WWW class to access your files from StreamingAssets on Android.
And you have to keep a list of your filenames, to be able to access them, as there seems to be no way to use something like File.Exists or Directory.GetFiles.
Example:
WWW www = new WWW(source);
yield return www;
if (string.IsNullOrEmpty(www.error))
{
// make sure the destination directory exists
File.WriteAllBytes(destination, www.bytes);
}
else
{
// error handling
}
Your source files (base) path should look like this:
jar:file://" + Application.dataPath + "!/assets/
From the docs:
Note that on Android, the files are contained within a compressed .jar
file (which is essentially the same format as standard zip-compressed
files). This means that if you do not use Unity’s WWW class to
retrieve the file then you will need to use additional software to see
inside the .jar archive and obtain the file.
Source: http://docs.unity3d.com/Manual/StreamingAssets.html
To solve this problem I created pre-compilation script which will run before the compilation; this script will list the names of the files you want to access later in text file
#if UNITY_EDITOR
using UnityEditor.Build;
using UnityEditor;
using System.IO;
public class BM_AndroidBuildPrepartion : IPreprocessBuild
{
public int callbackOrder { get { return 0; } }
public void OnPreprocessBuild(BuildTarget target, string path)
{
// Do the preprocessing here
string[] fileEntries = Directory.GetFiles("Assets/Resources/Prefabs/alphabet", "*.prefab");
System.IO.Directory.CreateDirectory("Assets/StreamingAssets/");
using (StreamWriter sw = new StreamWriter("Assets/StreamingAssets/alphabet.txt", false))
{
foreach (string filename in fileEntries) {
sw.WriteLine(Path.GetFileNameWithoutExtension(filename));
}
}
}
}
#endif
then I read the text file and you can access the files in same way but you have to put them inside your project in Assets/StreamingAssets/
#if UNITY_ANDROID
string path = "jar:file://" + Application.dataPath + "!/assets/alphabet.txt";
WWW wwwfile = new WWW(path);
while (!wwwfile.isDone) { }
var filepath = string.Format("{0}/{1}", Application.persistentDataPath, "alphabet.t");
File.WriteAllBytes(filepath, wwwfile.bytes);
StreamReader wr = new StreamReader(filepath);
string line;
while ((line = wr.ReadLine()) != null)
{
//your code
}
#endif
I have a problem,
I'm trying to add images in my pdf with jsPDF. b64Tab is an array containing the base64 data of my jpg images that i want to add.
After the
doc.output();
The different pages are created with the text added, but the images are not displayed. I test this on a 4.2.2 Android phone.
Here is a piece of code :
for (var j = 0; j < b64Tab.length; j++) {
doc.addPage();
doc.setFontSize(22);
doc.text(130, 65, descriptions[j]);
doc.addImage(b64Tab[j], 'JPEG', 40, 100, 500, 500);
}
I'm using the latest jsPDF's build.
Any help would be welcomed.
Thanks.
If you are not using File plugin then replace pdf output with doc.output("blob");
If you are using File plugin then create a buffer to write on the file eg.
var data = getPDFFile();
var buffer = new ArrayBuffer(data.length);
var array = new Uint8Array(buffer);
for (var i = 0; i < data.length; i++) {
array[i] = data.charCodeAt(i);
}
writer.write(buffer); // here you write on file using File plugin
Error in checking the file.
I have use one code. But i think there is some problem. The file got stuck to one file. And always keep dowloading the same file.
here is how i code this. Here in the below code. I am trying to download the images to local sdcard. If the file is already available i dont want it to download. And if not, then download. But it seems its just keep repeat download the same file.
function appReady(datadira){
$(".gallery").html("Ready to check remote files...");
$.get("http://www.pankhida.com/main/?json=get_page&page_id=115&callback=?", {}, function(res) {
if (res.page.attachments.length > 0) {
$(".gallery").html("Going to sync some images...");
for (var i = 0; i < res.page.attachments.length; i++) {
if (knownfiles.indexOf(res.page.attachments[i].url) == -1) {
//alert("need to download " + res[i]);
var ft = new FileTransfer();
var fullPath = res.page.attachments[i].url;
var filename = fullPath.replace(/^.*[\\\/]/, '');
var dlPath = DATADIR.toURL() + "/" + filename;
var uri= res.page.attachments[i].url;
uri = encodeURI(uri);
//console.log("downloading crap to " + dlPath);
window.resolveLocalFileSystemURL(DATADIR.toURL() +"/"+ filename, appStart, function(){
ft.download(uri, dlPath, function(e){
//renderPicture(e.toURL());
alert("Successful download of "+e.toURL());
}, onError, true);
});
}
}
}
$(".gallery").html("");
}, "json");
}
I am using window.resolveLocalFileSystemURL which i got from this URL http://www.raymondcamden.com/2014/7/1/Cordova-Sample-Check-for-a-file-and-download-if-it-isnt-there.
Please suggest where i am wrong. Or any correct code will be really helpful.
It has to do with the closure inside resolveLocalFileSystemURL.The value of ft ends up being the last one used from the loop. Try changing
for (var i = 0; i < res.page.attachments.length; i++) {
to
res.page.attachments.forEach(function(attachment) {
and the last } to }).
Inside the loop, use attachment instead of res.page.attachments[i].
This is my first time really getting my teeth into Air for Android so please forgive me if this issue has been covered already. If it has then I've been unable to find it.
So I have an application that loads and displays xml data.
In the app I've got code to check if wiFi or equivalent is available and if so then pull live xml file and if not then pull the local xml file that was packaged with the application.
The app works fine if I am pulling in the xml from the live url but not if pulling from local.
After doing some research I discovered that when pulling in local file then Air for Android works slightly differently. So I need to resolve the application directory.
I did this and still no joy.
After a bit more research I read some post's that said I should use fileStream()
Tried this and still nada :(
All the time whilst testing in Flash IDE it works as intended.
If I had any more hair left I would be pulling it out right now!
The local xml file is set in the "includes"
Sample code below I am using for testing
var subURL:String = "xml_feeds/myxmlfile.xml"
var fileStream:FileStream = new FileStream();
var file:File = File.applicationDirectory.resolvePath(subURL);
fileStream.addEventListener(Event.COMPLETE, processXMLData);
fileStream.openAsync(file, FileMode.READ);
MovieClip(parent).txStates.text = file.url+" - TRYING"
var prefsXML:XML = new XML()
function processXMLData(event:Event):void{
MovieClip(parent).txStates.text = file.url+" - OPEN"
prefsXML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
var tempArr:Array = new Array();
var reportCount:Number = prefsXML.row.column.length()
for (var i = 0; i < reportCount; i++) {
var rName:String = prefsXML.row.column[i].#name.toString();
var rValue:String = prefsXML.row.column[i].toString();
var rTitle:String = prefsXML.row.column[i].#name.toString()
tempArr.push([rName, rValue, rTitle]);
}
showData()
fileStream.close();
}
Is there anything I've missed?
UPDATE: 21/08/12
No idea what is going on with this. Here is the code i now have to use in order to load in the local xml file. Seems rather long winded
function listing():void{
var folders:Array = new Array();
folders = File.applicationDirectory.getDirectoryListing();
for(var i:Number =0;i<folders.length;i++){
if(folders[i].isDirectory){
if(folders[i].name=="xml_feeds"){
var files:Array = new Array();
files = folders[i].getDirectoryListing();
for(var j:Number=0;j<files.length;j++){
if(files[j].name=="CTSection2.xml"){
fileStream.openAsync(files[j], FileMode.READ);
fileStream.addEventListener(Event.COMPLETE, processXMLData);
fileStream.addEventListener(IOErrorEvent.IO_ERROR, localXMLFailLoad);
}
}
}
}
}
}