Appcelerator App crashes when downloading large (>500mb) zip file - ios

We are currently developing an iOS-App with Appcelerator which stores media files on the device for later viewing (pdf, mp4, zipped web pages).
We are now facing a problem with files above 500MB which crash the app on iPhone. The app is working on iPad2, but all iPhones tested crash (at random) when downloading these files.
The files are unzipped (all media files come with additional information inside the archive) via ti.compression.
The code used is (broken down to the relevant parts):
var zipDownloader = Ti.Network.createHTTPClient({
'onload' : function() {
var tempname = Math.floor((Math.random() * 10000000) + 1);
var dir = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory, 'tempDownloads', tempname);
dir.createDirectory();
filename = '' + tempname + '.zip';
var f = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'tempDownloads', filename);
f.write(this.responseData);
var Compression = require('ti.compression');
var zipFileName = Ti.Filesystem.applicationDataDirectory + 'tempDownloads/' + filename;
var outputDirectory = Ti.Filesystem.applicationDataDirectory + 'tempDownloads/' + tempname + '/';
var start = Math.floor(Date.now() / 1000);
var result = Compression.unzip(outputDirectory, zipFileName, true);
var finished = Math.floor(Date.now() / 1000) - start;
f.deleteFile();
Compression = null;
this.callback(outputDirectory);
}
});
zipDownloader.open('GET', url);
zipDownloader.callback = callback; // given in previous code, not relevant
zipDownloader.send();

Set the file property of the HTTPClient (https://docs.appcelerator.com/platform/latest/#!/api/Titanium.Network.HTTPClient-property-file) instead of writing the file once it is downloaded.
This will work for larger files because it writes the data directly into the file. Otherwise it will try to cache your file first and your app might crash because of memory errors. Tried it with 500+MB files

Related

Firebase Dynamic Links on Unity iOS says "Deep Link does not contain valid required params"

I'm using Firebase Dynamic Links for Unity, and I've got it working well with Android. I've even got a solution for Desktop, where the fallback link takes users to a webpage where I can provide instructions to the user for how to get their link content on Desktop.
On iOS, however, I always get errors like this when trying dynamic links:
[Firebase/Analytics][I-ACS023001] Deep Link does not contain valid required params. URL params: {
"_cpb" = 1;
"_cpt" = cpit;
"_fpb" = "CIAIEIAGGgVlbi11cw==";
"_iipp" = 1;
"_iumchkactval" = 1;
"_iumenbl" = 1;
"_osl" = "https://cgs.link/zu_tiles_hime?_iipp=1";
"_plt" = 260;
"_uit" = 1064;
apn = "com.finoldigital.cardgamesim";
cid = 8062347334713659136;
ibi = "com.finoldigital.CardGameSim";
isi = 1392877362;
link = "https://www.cardgamesimulator.com/link%%3Furl%%3Dhttps://www.cardgamesimulator.com/games/zu_tiles_hime/zu_tiles_hime.json";
sd = "Play Zu Tile: Hime on CGS!";
si = "https://www.cardgamesimulator.com/games/zu_tiles_hime/Banner.png";
st = "Card Game Simulator - Zu Tiles: Hime";
}
I saw in another issue that it could be because of ?, =, and & symbols in the link, so I url-encoded those, but I am still getting the same error.
For reference, my code for iOS is effectively:
private void Start()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
{
var dependencyStatus = task.Result;
if (dependencyStatus != DependencyStatus.Available)
{
Debug.LogError("Could not resolve all Firebase dependencies: " + dependencyStatus);
return;
}
DynamicLinks.DynamicLinkReceived += OnDynamicLinkReceived;
});
}
I immediately log in OnDynamicLinkReceived, so this callback is clearly never happening. Does anybody know what I am doing wrong, or what I could do to get the dynamic link received callback?
For anyone who runs into the same issue:
I solved this by modifying my build script to add the values for FirebaseDynamicLinksCustomDomains and FirebaseAppDelegateProxyEnabled to Info.plist as part of my build process.
PostProcess code:
var pbxProjectPath = PBXProject.GetPBXProjectPath(buildPath);
var pbxProject = new PBXProject(); pbxProject.ReadFromFile(pbxProjectPath);
const string targetName = "Unity-iPhone"; var targetGuid = pbxProject.GetUnityMainTargetGuid();
var src = AssetDatabase.GetAssetPath(file);
var fileName = Path.GetFileName(src);
var dst = buildPath + "/" + targetName + "/" + fileName;
if (!File.Exists(dst)) FileUtil.CopyFileOrDirectory(src, dst); pbxProject.AddFile(targetName + "/" + fileName, fileName);
pbxProject.AddBuildProperty(targetGuid, "CODE_SIGN_ENTITLEMENTS", targetName + "/" + fileName);
pbxProject.WriteToFile(pbxProjectPath);
var plistPath = buildPath + "/Info.plist";
var plistDocument = new PlistDocument(); plistDocument.ReadFromString(File.ReadAllText(plistPath));
var rootDict = plistDocument.root;
rootDict.SetBoolean("FirebaseAppDelegateProxyEnabled", false);
PlistElementArray customDomains = rootDict.CreateArray("FirebaseDynamicLinksCustomDomains");
customDomains.AddString("https://cgs.link");
File.WriteAllText(plistPath);

Converting docx to images using Aspose.Words

I'm converting a generated doc to a pdf and to png's, see the code below. But for some reason there is something wrong with the fonts. On my local develop machine everything is right, but when deployed on the production servers the fonts in the PNG's are missing. I've checked but they are installed on the servers. Can someone help me with this?
var dstDoc = doc.Clone();
var newInvoice = new InvoicePdf(factuur);
var ds = newInvoice.ToDataSet();
dstDoc.BuiltInDocumentProperties.Title = newInvoice.InvoiceID;
dstDoc.BuiltInDocumentProperties.Subject = newInvoice.SendDate;
dstDoc.MailMerge.FieldMergingCallback = new HandleMergeFieldAlternatingRows();
dstDoc.MailMerge.ExecuteWithRegions(ds);
var filePath = Path.Combine(folderInvoices, newInvoice.SendDateOrginal.Year.ToString(CultureInfo.InvariantCulture));
Directory.CreateDirectory(filePath);
var fileName = string.Format("{0} - {1}", newInvoice.InvoiceID, newInvoice.DebtorCompany.ToString(true));
filePath = Path.Combine(filePath, fileName);
filePaths.Add(filePath + ".pdf");
dstDoc.Save(filePath + ".pdf", SaveFormat.Pdf);
var options = new ImageSaveOptions(SaveFormat.Png) { PageCount = 1, Resolution = 120, UseAntiAliasing = true, PrettyFormat = true, UseHighQualityRendering = true };
for (var i = 0; i < dstDoc.PageCount; i++)
{
options.PageIndex = i;
dstDoc.Save(string.Format("{0}_{1}.png", filePath, i), options);
}
If it is a shared server, then most probably it is a security issue. Aspose.Words for .NET DLL needs access to the Windows registry, to find the fonts folder. Refer to http://www.aspose.com/docs/display/wordsnet/Considerations+When+Running+on+a+Shared+Server+Environment for more details.
A workaround is also possible to specify the path of folder, which has all the required fonts. Please see http://www.aspose.com/docs/display/wordsnet/How+to++Specify+True+Type+Fonts+Location for sample code.
I work with Aspose as Developer evangelist.

PhoneGap file download not working properly on IOS devices

I am using PhoneGap version 2.9.0 to download file from URL to specific folder. Which is working fine for me in android, as file get download in specific folder, but in case of IOS devices file is not download fully.
Ex. IF file size = 2.3mb
and download file size = 111 bytes
My code -
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, fileSystemSuccess, fileSystemFail);
function fileSystemSuccess(fileSystem) {
var uri = $("#URL").val(); // Get URL
var download_link = encodeURI(uri);
var path = download_link,
ext = path.substr(path.lastIndexOf('.') + 1); //Get extension of URL
var folder_name = $("#folder").val(); // Get folder name
var file_name = $("#filename").val(); //Get file name
var directoryEntry = fileSystem.root; // to get root path to directory
directoryEntry.getDirectory(folder_name, { create: true, exclusive: false }, onDirectorySuccess, onDirectoryFail); // creating folder in sdcard
var rootdir = fileSystem.root;
var fp = rootdir.fullPath;
fp = fp + "/" + folder_name + "/" + file_name + "." + ext; // fullpath and name of the file which we want to give
// download function call
var fileTransfer = new FileTransfer();
//File download function with URL and local path
fileTransfer.download(download_link, fp,
function (entry) {
alert("download complete: " + entry.fullPath);
},
function (error) {
alert("download error source " + error.source);
alert("download error target " + error.target);
alert("upload error code" + error.code);
}
);
}
function onDirectorySuccess(parent) {
//alert(parent);
}
function onDirectoryFail(error) {
//Error while creating directory
alert("Unable to create new directory: " + error.code);
}
function fileSystemFail(evt) {
alert(evt.target.error.code);
}
Folder is creating in IOS, issue is only download file size. I am stuck with this IOS issue. Help me out.
Finally I got my solution.
<access origin="*" />
Above my code is working fine for download from URL in both android and IOS. Creating folder and download in it.

Adobe AIR Mobile on iOS - processing text very slow

I am writing an iOS app in Flash Builder 4.6 that will need to process a large text file. So far, I am just trying to get the version information from the file, a simple task that runs very fast in the simulator but takes a very long time (on the order of 10 seconds) on my iPad 2.
As the file is large (about 11MB), I am trying to only read far enough into the file to get the version data. Is it possible that the filestream loads the whole file into memory anyway? If so, how do I avoid that?
Note that the code works correctly, and displays the correct version info.
Any advice on how to speed it up would be greatly appreciated.
The file being processed can be found here: http://oanda.sca.org:80/oanda.db
The code is as follows:
Calling code:
protected function view1_viewActivateHandler(event:ViewNavigatorEvent):void
{
var DT:DatabaseTools = new DatabaseTools();
var version:String;
//Get version information from local file:
version = DT.GetLocalVer("oanda.db");
lblLclVer.text=version;
}
Actual function:
public function GetLocalVer(fileName:String):String
{
var out:ByteArray = new ByteArray();
var line_Out:String;
var char:int;
var line:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
var file:File = File.documentsDirectory.resolvePath(fileName);
var lineString:String;
var result:String = "Error";
stream.open(file,FileMode.READ);
var found:Boolean=false;
while((stream.bytesAvailable > 0) && !found)
{
char=stream.readByte();
if(String.fromCharCode(char) == "\n")
{
//reset the line
out=line;
line = new ByteArray();
//process the line to see if its the version info.
lineString=out.toString(); //since the version line never has UTF characters, convert it to a regular string
if(lineString.length > 25) //Any line shorter than this can't be the version line
{
var startOfLine:String = lineString.substr(0,17);
if(startOfLine == " ||C|Last update:")
{
result = lineString.substr(19,6);
found = true;
}
}
}
else
{
line.writeByte(char);
}
}
stream.close();
return result;
}
Thanks.

AS3 Save SWF to iOS device and then load it back into a MovieClip

I have an iOS app that's using AS3 and AIR. I have external swfs downloading from a server and playing properly--all of this works perfectly fine.
I don't want the user to have to download these swfs every time they launch the app, though, so after the swf is downloaded the first time I want to save it to disk. That way I can load it from the local copy when I need it in the future, instead of downloading it again. I found this example online for saving files in AS3:
var file:File = File.applicationStorageDirectory.resolvePath("Swfs/" + "mySwfName" + ".swf");
var wr:File = new File(file.nativePath);
var stream:FileStream = new FileStream();
stream.open(wr, FileMode.WRITE);
stream.writeBytes(SWF_FILE_GOES_HERE, 0, SWF_FILE_DATA_LENGTH_GOES_HERE);
stream.close();
The problem is in the writeBytes line. The sample I found was for saving images to disk, and that line read like this:
stream.writeBytes(imageData, 0, imageData.length);
But I need to do this for a swf, not an image, and I'm not sure how to get the requisite data from my swf file. I've searched online for saving swf files, getting data from swf files, etc... But I haven't found anything. I need to get the swf's data and data length (I'm assuming this is a number of bytes?). Has anyone solved this problem before, or have a resource they can point me in the direction of?
UPDATE: Based on #LondonDrugs_MediaServices' comments, I figured out the writeBytes line:
stream.writeBytes(mySwf.loaderInfo.bytes, 0, mySwf.loaderInfo.bytesTotal);
This seems to work, in as much as it compiles and runs without errors. But when I try to grab the file and put it back into a movie clip, I get this error:
Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found.
Which implies that the file was not, in fact, saved correctly. When I print the file locations, however, they seem to be right! When I save the file to the applicationStorageDirectory:
/Users/MyName/Library/Preferences/com.appdir/Local Store/Swfs/mySwName.swf
And the filename when I try and load it out of storage and into a movie clip:
/Users/MyName/Library/Preferences/com.appdir/Local Store/Swfs/mySwName.swf
This is the code I'm using to try and load it back into a movie clip:
var videoFileName:String = "Swfs/" + ENVAR.currentVideoSelected + ".swf";
var videoFilePath:File = File.applicationStorageDirectory.resolvePath(videoFileName);
var inFileStream:FileStream = new FileStream();
trace("[Loading] filepath: ", videoFilePath.nativePath);
inFileStream.open(videoFilePath, FileMode.READ);
var fileContents:String = inFileStream.readUTFBytes(inFileStream.bytesAvailable);
inFileStream.close();
var req:URLRequest = new URLRequest(videoFilePath.nativePath);
var mLoader:Loader = new Loader();
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onVideoLoadComplete);
mLoader.load(req);
And my onVideoLoadComplete function contains these lines:
var myMC:MovieClip = e.target.content as MovieClip;
addChild(myMC);
But I'm getting that error 2044 and it doesn't think the file exists. Can anyone spot the problem? Thanks!
You can get the raw bytes of a loaded swf file by using it's loaderInfo.bytes parameter. So for you example you could do this:
var file:File = File.applicationStorageDirectory.resolvePath("Swfs/" + key + ".swf");
var wr:File = new File(file.nativePath);
var stream:FileStream = new FileStream();
stream.open(wr, FileMode.WRITE);
stream.writeBytes(mySwf.loaderInfo.bytes, 0, mySwf.loaderInfo.bytesTotal);
stream.close();
Then to pull it back out into a MovieClip:
var videoFileName:String = "Swfs/" + ENVAR.currentVideoSelected + ".swf";
var videoFilePath:File = File.applicationStorageDirectory.resolvePath(videoFileName);
var inFileStream:FileStream = new FileStream();
inFileStream.open(videoFilePath, FileMode.READ);
var swfBytes:ByteArray = new ByteArray();
inFileStream.readBytes(swfBytes);
inFileStream.close();
var mLoader:Loader = new Loader();
var loaderContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
loaderContext.allowCodeImport = true;
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onVideoLoadComplete);
mLoader.loadBytes(swfBytes, loaderContext);

Resources