From 0d6918d5084deab428e62cd988d21caf6b3ccb72 Mon Sep 17 00:00:00 2001 From: Yueyu Date: Mon, 22 Mar 2021 13:05:58 +0800 Subject: [PATCH] clean up zips before creating a new one --- .../java/org/scratchjr/android/IOManager.java | 18 ++++++ .../android/JavaScriptDirectInterface.java | 32 ++++------ .../org/scratchjr/android/ScratchJrUtil.java | 60 ++++++++++++++++++- ios/ScratchJr/src/IO.m | 34 +++++++++-- 4 files changed, 116 insertions(+), 28 deletions(-) diff --git a/android/ScratchJr/app/src/main/java/org/scratchjr/android/IOManager.java b/android/ScratchJr/app/src/main/java/org/scratchjr/android/IOManager.java index 1a4a388..d89013a 100644 --- a/android/ScratchJr/app/src/main/java/org/scratchjr/android/IOManager.java +++ b/android/ScratchJr/app/src/main/java/org/scratchjr/android/IOManager.java @@ -39,6 +39,24 @@ public class IOManager { _databaseManager = application.getDatabaseManager(); } + /** + * clean up sharing zips in cache dir. + */ + public void cleanZips() { + String suffix = ScratchJrUtil.getExtension(); + File dir = _application.getCacheDir(); + Log.i(LOG_TAG, "Cleaning files of type '" + suffix + "' in dir: " + dir.getAbsolutePath()); + for (File file : dir.listFiles()) { + String filename = file.getName(); + Log.i(LOG_TAG, filename); + if (!filename.endsWith(suffix)) { + continue; + } + Log.i(LOG_TAG, "removing file: " + filename); + file.delete(); + } + } + /** * Clean any assets that are not referenced in the database * diff --git a/android/ScratchJr/app/src/main/java/org/scratchjr/android/JavaScriptDirectInterface.java b/android/ScratchJr/app/src/main/java/org/scratchjr/android/JavaScriptDirectInterface.java index 6f02d11..c432d21 100644 --- a/android/ScratchJr/app/src/main/java/org/scratchjr/android/JavaScriptDirectInterface.java +++ b/android/ScratchJr/app/src/main/java/org/scratchjr/android/JavaScriptDirectInterface.java @@ -1,8 +1,6 @@ package org.scratchjr.android; -import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -578,10 +576,12 @@ public class JavaScriptDirectInterface { @JavascriptInterface public String createZipForProject(String projectData, String metadataJson, String name) { + // clean up old zip files + _activity.getIOManager().cleanZips(); // create a temp folder File tempPath = new File(_activity.getCacheDir() + File.separator + UUID.randomUUID().toString()); tempPath.mkdir(); - // save project.json + // save data.json // Log.d(LOG_TAG, "writing data.json"); File dataFile = new File(tempPath.getAbsolutePath() + File.separator + "data.json"); try { @@ -605,7 +605,6 @@ public class JavaScriptDirectInterface { Iterator keys = metadata.keys(); while (keys.hasNext()) { String key = keys.next(); - Log.d(LOG_TAG, key); File folder = new File(tempPath.getAbsolutePath() + File.separator + key); if (!folder.exists()) { folder.mkdir(); @@ -633,21 +632,15 @@ public class JavaScriptDirectInterface { } } } - // Log.d(LOG_TAG, "copy assets done"); // create zip file - String extension; - if (BuildConfig.APPLICATION_ID.equals("org.pbskids.scratchjr")) { - extension = ".psjr"; - } else { - extension = ".sjr"; - } + String extension = ScratchJrUtil.getExtension(); String fullName = name + extension; - File file = new File(_activity.getCacheDir() + File.separator + fullName); - file.deleteOnExit(); - // Log.d(LOG_TAG, "creating zip"); - ScratchJrUtil.zipFileAtPath(tempPath.getAbsolutePath(), file.getAbsolutePath()); + ScratchJrUtil.zipFileAtPath( + tempPath.getAbsolutePath(), + _activity.getCacheDir() + File.separator + fullName + ); // remove the temp folder - tempPath.deleteOnExit(); + ScratchJrUtil.removeFile(tempPath); return fullName; } @@ -655,12 +648,7 @@ public class JavaScriptDirectInterface { public void sendSjrUsingShareDialog(String fileName, String emailSubject, String emailBody, int shareType) { // Write a temporary file with the project data passed in from JS - String mimetype; - if (BuildConfig.APPLICATION_ID.equals("org.pbskids.scratchjr")) { - mimetype = "application/x-pbskids-scratchjr-project"; - } else { - mimetype = "application/x-scratchjr-project"; - } + String mimetype = ScratchJrUtil.getMimeType(); File file = new File(_activity.getCacheDir() + File.separator + fileName); Log.d(LOG_TAG, file.getAbsolutePath()); final Intent it = new Intent(Intent.ACTION_SEND); diff --git a/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrUtil.java b/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrUtil.java index 33fb16a..837a198 100644 --- a/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrUtil.java +++ b/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrUtil.java @@ -40,6 +40,55 @@ public class ScratchJrUtil { return result; } + /** + * get sharing file extension based on APPLICATION_ID + * @return extension + */ + public static String getExtension() { + String extension; + if (BuildConfig.APPLICATION_ID.equals("org.pbskids.scratchjr")) { + extension = ".psjr"; + } else { + extension = ".sjr"; + } + return extension; + } + + /** + * get sharing file mime-type based on APPLICATION_ID + * @return mime type + */ + public static String getMimeType() { + String mimetype; + if (BuildConfig.APPLICATION_ID.equals("org.pbskids.scratchjr")) { + mimetype = "application/x-pbskids-scratchjr-project"; + } else { + mimetype = "application/x-scratchjr-project"; + } + return mimetype; + } + + /** + * remove file or folder + * if `file` is a folder, it will be cleaned up before removing + * @param file to be removed + */ + public static void removeFile(File file) { + if (file.isDirectory()) { + for (File f : file.listFiles()) { + removeFile(f); + } + } + file.delete(); + } + + /** + * Copy file from a location to target location + * + * @param sourceLocation file path to be copied + * @param targetLocation file path bo be copied to + * @throws IOException + */ public static void copyFile(File sourceLocation, File targetLocation) throws IOException { @@ -56,8 +105,17 @@ public class ScratchJrUtil { out.close(); } + /** + * zip a folder to target location + * @param sourcePath folder to compress + * @param toLocation the target location to save the zip + * @return successful or not + */ public static boolean zipFileAtPath(String sourcePath, String toLocation) { File sourceFile = new File(sourcePath); + if (sourceFile.exists()) { + sourceFile.delete(); + } try { BufferedInputStream origin; FileOutputStream dest = new FileOutputStream(toLocation); @@ -86,9 +144,7 @@ public class ScratchJrUtil { } /* - * * Zips a subfolder - * */ private static void zipSubFolder(ZipOutputStream out, File folder, int basePathLength) throws IOException diff --git a/ios/ScratchJr/src/IO.m b/ios/ScratchJr/src/IO.m index 2c9cc8f..8ee5684 100644 --- a/ios/ScratchJr/src/IO.m +++ b/ios/ScratchJr/src/IO.m @@ -203,9 +203,32 @@ NSMutableDictionary *soundtimers; return @"1"; } ++ (void) cleanZips{ + NSString *dir = NSTemporaryDirectory(); + NSError *error; + NSFileManager *filemgr = [NSFileManager defaultManager]; + NSDirectoryEnumerator *dirEnumerator = [filemgr enumeratorAtURL:[NSURL fileURLWithPath:dir] + includingPropertiesForKeys:@[NSURLNameKey] + options:NSDirectoryEnumerationSkipsHiddenFiles | NSDirectoryEnumerationSkipsSubdirectoryDescendants + errorHandler:nil]; + + NSString* extension = @".sjr"; + + #if PBS + extension = @".psjr"; + #endif + for (NSURL *theURL in dirEnumerator) { + if ([theURL.lastPathComponent hasSuffix:extension]) { + NSLog(@"remove file %@", theURL.path); + [filemgr removeItemAtURL:theURL error:&error]; + } + } +} + + (NSString *) createZipForProject: (NSString *) projectData :(NSDictionary *) metadata :(NSString *) zipName { + [self cleanZips]; // create a temperary folder for project - NSString *tempDir = [[[NSString alloc] initWithString:NSTemporaryDirectory()] stringByAppendingPathComponent: [[NSUUID alloc] init].UUIDString]; + NSString *tempDir = [self getTmpPath:[NSUUID alloc].UUIDString].path; // NSLog(@"%@", tempDir); NSFileManager *fileManager = [NSFileManager defaultManager]; [fileManager createDirectoryAtPath:tempDir withIntermediateDirectories:true attributes:nil error:nil]; @@ -234,8 +257,7 @@ NSMutableDictionary *soundtimers; #endif NSString *fullName = [NSString stringWithFormat:extensionFormat, zipName]; - NSURL *url = [self getDocumentPath:fullName]; - NSString *zipPath = url.path; + NSString *zipPath = [self getTmpPath:fullName].path; NSLog(@"target zip path %@", zipPath); if ([fileManager fileExistsAtPath:zipPath]) { [fileManager removeItemAtPath:zipPath error:nil]; @@ -249,7 +271,7 @@ NSMutableDictionary *soundtimers; // Receive a .sjr file from inside the app. Send using native UI - Airdrop or Email + (NSString*) sendSjrUsingShareDialog:(NSString *)fileName :(NSString*)emailSubject :(NSString*)emailBody :(int)shareType { - NSURL *url = [self getDocumentPath:fileName]; + NSURL *url = [self getTmpPath:fileName]; if (shareType == 0) { [HTML showShareEmail:url withName:fileName withSubject:emailSubject withBody:emailBody]; } else { @@ -342,6 +364,10 @@ NSMutableDictionary *soundtimers; return [NSURL fileURLWithPath: [dir stringByAppendingPathComponent: name]]; } ++ (NSURL*)getTmpPath:(NSString *)name{ + return [NSURL fileURLWithPath: [NSTemporaryDirectory() stringByAppendingPathComponent: name]]; +} + /////////////////////////////// // Base64 encode and decode //////////////////////////////