Reputation: 2697
I am trying to write a 20MB blob to file on an Android device. This code works fine for 4-5MB or so, but crashes for larger files.
tp = cordova.file.dataDirectory; // for Android
$cordovaFile.writeFile(tp, "temp-file.gif", blob,true);
is there a way to handle larger blobs? thanks. I already have android:largeHeap="true"
in the manifest.
the logcat error:
E/JavaBinder( 809): !!! FAILED BINDER TRANSACTION !!!
I/art ( 809): Background sticky concurrent mark sweep GC freed 62202(4MB) AllocSpace objects, 96(3MB) LOS objects, 20% free, 25MB/31MB, paused 20.488ms total 176.243ms
E/JavaBinder( 809): !!! FAILED BINDER TRANSACTION !!!
W/ActivityManager( 809): Exception thrown during pause
W/ActivityManager( 809): android.os.TransactionTooLargeException
W/ActivityManager( 809): at android.os.BinderProxy.transactNative(Native Method)
W/ActivityManager( 809): at android.os.BinderProxy.transact(Binder.java:496)
W/ActivityManager( 809): at android.app.ApplicationThreadProxy.schedulePauseActivity(ApplicationThreadNative.java:711)
W/ActivityManager( 809): at com.android.server.am.ActivityStack.startPausingLocked(ActivityStack.java:829)
W/ActivityManager( 809): at com.android.server.am.ActivityStack.finishActivityLocked(ActivityStack.java:2749)
W/ActivityManager( 809): at com.android.server.am.ActivityStack.finishTopRunningActivityLocked(ActivityStack.java:2606)
W/ActivityManager( 809): at com.android.server.am.ActivityStackSupervisor.finishTopRunningActivityLocked(ActivityStackSupervisor.java:2544)
W/ActivityManager( 809): at com.android.server.am.ActivityManagerService.handleAppCrashLocked(ActivityManagerService.java:11721)
W/ActivityManager( 809): at com.android.server.am.ActivityManagerService.makeAppCrashingLocked(ActivityManagerService.java:11618)
W/ActivityManager( 809): at com.android.server.am.ActivityManagerService.crashApplication(ActivityManagerService.java:12330)
W/ActivityManager( 809): at com.android.server.am.ActivityManagerService.handleApplicationCrashInner(ActivityManagerService.java:11819)
W/ActivityManager( 809): at com.android.server.am.NativeCrashListener$NativeCrashReporter.run(NativeCrashListener.java:86)
Upvotes: 3
Views: 1520
Reputation: 2697
The solution, after experimentation is to break up the write into chunks - that seems to work for 20-30MB files that I've tested so far.
function writeFile2( path, file, blob, isAppend)
{
var csize = 4 * 1024 * 1024; // 4MB
var d = $q.defer();
NVRDataModel.debug ("Inside writeFile2 with blob size="+blob.size);
// nothing more to write, so all good?
if (!blob.size)
{
NVRDataModel.debug ("writeFile2 all done");
d.resolve(true);
return $q.resolve(true);
}
if (!isAppend)
{
// return the delegated promise, even if it fails
return $cordovaFile.writeFile(path, file, blob.slice(0,csize), true)
.then (function (succ) {
return writeFile2(path,file,blob.slice(csize),true);
});
}
else
{
// return the delegated promise, even if it fails
return $cordovaFile.writeExistingFile(path, file, blob.slice(0,csize))
.then (function (succ) {
return writeFile2(path,file,blob.slice(csize),true);
});
}
}
Credit: @Andre Werlang helped me with this here: https://stackoverflow.com/a/40935231/1361529
Upvotes: 2
Reputation: 10658
This is what I use and I have no limit or haven't reached it
function writeFile(__filename, __data){
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function(dir){
dir.getFile(__filename, {create:true}, function(file){
file.createWriter(function(fileWriter){
var blob = new Blob([__data], {type:'text/plain'});
fileWriter.write(blob);
});
});
});
};
Upvotes: 1