var zip:FZip = new FZip();
zip.load(new URLRequest("xx.obb"));
this codes does not work. It throws "Unknown record signature:" error.
how did you extract .obb file ?
that way you need to read it? if it is to load a game I think it is a good way to load it so it would be better to load it from a specific route
for example: sdcard/android/obb/filename.obb
If your obb file is like any other zip file then you can treat it as such. First you will want a list of files to extract (could be all your files who knows).
Here is one way to get the files out :
private function obbFileUnpackingRoutine(event:Event):void{
addChild(obbUnpackScreen);
obbUnpackScreen.obbProgress.scaleX = zipCount/filesToUnpack.length;
setChildIndex(obbUnpackScreen, numChildren -1);
for (var i:uint = 0; i<24; i++){
if (zipCount == filesToUnpack.length){
zipDone = true;
removeEventListener(Event.ENTER_FRAME, obbFileUnpackingRoutine);
removeChild(obbUnpackScreen);
var fr:FileStream=new FileStream();
var str:String = File.applicationStorageDirectory.nativePath;
var cacheDir= new File(str +"/YourSettings");
fr.open(cacheDir.resolvePath("isObbUnpacked.pnr"),FileMode.WRITE);
fr.writeObject([zip.getFileCount(),zipCount]);
fr.close();
return
}
var file:FZipFile = zip.getFileByName(filesToUnpack[zipCount])
var cacheDir:File= null;
var str:String = File.applicationStorageDirectory.nativePath;
cacheDir= new File(str);
var fileContents = file.content
var fr:FileStream=new FileStream();
fr.open(cacheDir.resolvePath(file.filename),FileMode.WRITE);
fr.writeBytes(fileContents);
fr.close();
zipCount++;
}
}
If memory permits you may want to load your files directly from the zip file so you don't have to unpack them.
Any file that can only accessed with a urlRequest will of course have to be extracted
But you can load png files, mp3 files, and your own custom files with byteArrays
My obb file has thousands of tiny mp3 files and it can take upto 3 minutes to extract on an allWinner A10 processor.
Direct loading means it can get the files instantly. And there is almost no delay at all.
Related
I have a problem saving the Xfinium PDF. I loaded a document and simply draw the line across the page and save. The file generated but when I used that file and loaded back to PdfFixedDocument I have the error
Root entry is missing in file trailer
My code is very simple :
var pdf = new PdfFixedDocument (document.Location);
var page = pdf.Pages [pageIndex];
var graphics = page.Graphics;
var directory = FileUtilities.GetExternalPrivateDirectory (PdfCore.CACHE_DIRECTORY);
//var png = FileUtilities.GetFile (directory + "/test.pdf");
//var rawStream = File.OpenWrite (png.AbsolutePath);
var stream = new FileStream (directory + "/test.pdf", FileMode.Create);
pdf.BeginSave (stream);
graphics.DrawLine(new Xfinium.Pdf.Graphics.PdfPen (),
new Xfinium.Pdf.Graphics.PdfPoint (0,0),
new Xfinium.Pdf.Graphics.PdfPoint (page.Width, page.Height));
page.SaveGraphics ();
pdf.EndSave ();
Instead of manually creating the stream and using BeginSave / EndSave, just try using Save:
var pdf = new PdfFixedDocument();
var page = pdf.Pages.Add();
var graphics = page.Graphics;
graphics.DrawLine(new Xfinium.Pdf.Graphics.PdfPen(),
new Xfinium.Pdf.Graphics.PdfPoint(0, 0),
new Xfinium.Pdf.Graphics.PdfPoint(page.Width, page.Height));
var directory = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDownloads);
pdf.Save(Path.Combine(directory.Path, "test.pdf"));
Java.IO.File pdfFILE = new Java.IO.File(Path.Combine(directory.Path, "test.pdf"));
Intent intent = new Intent(Intent.ActionView);
intent.SetDataAndType(Uri.FromFile(pdfFILE), "application/pdf");
StartActivity(intent);
I believe that the PDF document is not properly written to file because the stream is not closed. Try adding these lines at the end of your code (after pdf.EndSave()):
stream.Flush();
stream.Close();
The BeginSave/SaveGraphics/EndSave mode should be used when creating pages with heavy content, such as vector maps, and you want to reduce memory consumption by calling SaveGraphics after drawing a certain number of graphic objects (SaveGraphics can be called multiple times for a page).
For your scenario you can simplify the code as follows (like SushiHangover suggested):
var pdf = new PdfFixedDocument (document.Location);
var page = pdf.Pages [pageIndex];
var graphics = page.Graphics;
graphics.DrawLine(new Xfinium.Pdf.Graphics.PdfPen (),
new Xfinium.Pdf.Graphics.PdfPoint (0,0),
new Xfinium.Pdf.Graphics.PdfPoint (page.Width, page.Height));
var directory = FileUtilities.GetExternalPrivateDirectory(PdfCore.CACHE_DIRECTORY);
pdf.Save(directory + "/test.pdf");
Disclaimer: I work for the company that develops XFINIUM.PDF library.
.Save (document path) is massively slow when it comes to e.g.: 100 pages and lots of data so the end file has about 145MB or more, then the saving operation takes 2 minutes pls - this is ways to slow so I will try the BeginSave and EndSave approach also
In Air for Android Setting's 'Include files' part, I added test1.swf and test2.swf to the main file automatically included. Would the following be correct then:
myLoader.load(new URLRequest("test1.swf")
Or, is there any other folder I should include? Would the following be correct?
myLoader.load(new URLRequest("\..\..test1.swf")
I'm not in a position to test this right now on Android, but I believe included files are put in the application directory, which you can access as follows:
var path:String = File.applicationDirectory.resolvePath("test1.swf").nativePath;
myLoader.load(new URLRequest(path));
You can also use the shorthand url of:
myLoader.load(new URLRequest("app://test1.swf"));
You could also load the swf with the FileStream class, which gives you more control over things. That would look like this:
var file:File = File.applicationDirectory.resolvePath("test1.swf");
if (file.exists) {
var swfData:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
stream.readBytes(swfData);
stream.close();
var myLoader:Loader = new Loader();
var loaderContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
loaderContext.allowCodeImport = true;
myLoader.loadBytes(swfData, loaderContext);
addChild(myLoader);
}else {
trace("file doesn't exist");
}
Im making a Test Maker App for both Desktop and Android. I was able to save and load in Desktop but failed on Android. I can ONLY save my file, but i cannot load my saved file. The Android device says "No files were found". It doesnt even open a file browser. The type of saving and loading that im doing is the type where the user can actually look for his project and open it. Im currently using FileReference to do this. It works on Desktop but not on Android Mobile. Can somebody help me with this?
I'm pretty sure you can't use a FileReference on mobile (though someone feel free to correct me if wrong).
On mobile, you should use the File & FileStream classes for loading/saving local files.
Here is an example, of using a compile time constant you could create (to determine if desktop or AIR) and loading appropriately into and out of a textfield called textfield:
CONFIG::air {
var file:File = File.applicationStorageDirectory.resolvePath("myFile.txt");
if(file.exists){
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
textfield.text = stream.readUTF(); //this may need to changed depending what kind of file data you're reading
stream.close();
}else{
data = "default value"; //file doesn't exist yet
}
}
CONFIG::desktop {
//use your file reference code to populate the data variable
}
And to save: (assuming you have a textfield whose text you want to save)
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeUTF(textfield.text);
fileStream.close();
There are other save methods besides writeUTF (which is for plain text) writeObject is good for saving custom object when combined with flash.net.registerClassAlias
File classes are in the flash.filesystem package
EDIT
Here is something you can try for letting the user pick the location on AIR.
var file:File = File.applicationStorageDirectory;
file.addEventListener(Event.SELECT, onFileSelected);
file.browseForOpen("Open Your File", [new FileFilter("Text Files", "*.txt")]);
function onFileSelected(e:Event):void {
var stream:FileStream = new FileStream();
stream.open(e.target as File, FileMode.READ);
textField.text = stream.readUTF();
}
var saveFile:File = File.applicationStorageDirectory.resolvePath("myFile.txt");
saveFile.addEventListener(Event.SELECT, onSaveSelect);
saveFile.browseForSave("Save Your File");
function onSaveSelect(e:Event):void {
var file:File = e.target as File;
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeUTF(textField.text);
stream.close();
}
I am making an android application in Air for android using actionscript 3. I need to download a file from the server and save it to mobile sdcard. Following is my code, the file gets loaded from the server but how do I save it on sdcard?
import flash.filesystem.*;
var urlString:String = "http://www.mywebsite.com/xyz/myswftodownload.swf";
var urlReq:URLRequest = new URLRequest(urlString);
var urlStream:URLStream = new URLStream();
var fileData:ByteArray = new ByteArray();
urlStream.addEventListener(ProgressEvent.PROGRESS, onProgress);
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.load(urlReq);
function loaded(event:Event):void
{
urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
trace("Loaded");
urlStream.removeEventListener(ProgressEvent.PROGRESS, onProgress);
urlStream.removeEventListener(Event.COMPLETE, loaded);
//NOW HOW TO SAVE THE LOADED FILE ON SDCARD??
}
function onProgress(evt:ProgressEvent):void {
var nPercent:Number = Math.round((evt.bytesLoaded / evt.bytesTotal) * 100);
//loadingAnim.bar.scaleX = nPercent / 100;
status.text = nPercent.toString() + "%";
}
You can do something like this
//NOW HOW TO SAVE THE LOADED FILE ON SDCARD
var file:File = File.userDirectory.resolvePath("myswftodownload.swf");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(fileData, 0, fileData.length);
fileStream.close();
File.userDirectory usually points to the sdcard (external storage). But beware of the fact that external storage doesn't have to be available at all time (for example when device connected as mass storage by usb).
In your case i would consider using internal storage instead and use File.applicationDirectory or File.applicationStorageDirectory for saving your swf files. External storage is better for saving files like images, music, documents..
This code is way cool! Try it. It creates a folder in your user called .007 and saves an mp3 called yahoo.mp3.
It will also do it on an android device if permissions are set correctly.
Once it creates a folder and saves the mp3 it will loop thru the folder and get the file path and the file name.
MY QUESTION IS: How do you access it and play the sound on Android? It works on the desktop as you can see if you test it But not on the droid. Any ideas why?
import flash.filesystem.*;
var urlString:String = "http://YourWebsite.com/YourSound.mp3";
var urlReq:URLRequest = new URLRequest(urlString);
var urlStream:URLStream = new URLStream();
var fileData:ByteArray = new ByteArray();
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.load(urlReq);
function loaded(event:Event):void
{
urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
writeAirFile();
}
function writeAirFile():void
{
var file:File = File.userDirectory.resolvePath(".007/Yahoo.mp3");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(fileData, 0, fileData.length);
fileStream.close();
trace("The file is written.");
var desktop:File = File.userDirectory.resolvePath(".0");
var files:Array = desktop.getDirectoryListing();
for (var i:uint = 0; i < files.length; i++)
{
trace(files[i].nativePath);// gets the path of the files
trace(files[i].name);// gets the name
var mySound:Sound = new Sound();
var myChannel:SoundChannel = new SoundChannel();
var lastPosition:Number = 0;
mySound.load(new URLRequest(files[0].nativePath));
myChannel = mySound.play();
}
}
file:// <-------The Answer!
Got it! The file path needed to access the "sdcard" on a Android phone must begin with: file://
If you want to load a sound from your phone it would look like this. Here is the one important line needed. I will post full code below.
mySound.load(new URLRequest("file://mnt/sdcard/AnyFolder/YourSound.mp3"));
Since I was using a loop above getting all the files in a particular folder this is the code that worked for me in the example above.
mySound.load(new URLRequest("file://"+files[0].nativePath));
FULL CODE TO LOAD AND PLAY SOUND ON DROID
var mySound:Sound = new Sound();
var myChannel:SoundChannel = new SoundChannel();
var lastPosition:Number = 0;
mySound.load(new URLRequest("file://mnt/sdcard/AnyFolder/YourSound.mp3"));
myChannel = mySound.play();
I worked very hard on to find this answer. I hope this helps many. Please remember to +1 if this code has helped you. :)
I love StackOverflow! :)