android-asset-updates

This commit is contained in:
Geoffrey Goh
2016-01-29 12:17:54 -08:00
parent 73b744c60e
commit d297fc8f43
4 changed files with 359 additions and 323 deletions

View File

@@ -425,41 +425,50 @@ public class CodePush {
}
@ReactMethod
public void getNewStatusReport(Promise promise) {
if (needToReportRollback) {
needToReportRollback = false;
JSONArray failedUpdates = getFailedUpdates();
if (failedUpdates != null && failedUpdates.length() > 0) {
try {
JSONObject lastFailedPackageJSON = failedUpdates.getJSONObject(failedUpdates.length() - 1);
WritableMap lastFailedPackage = CodePushUtils.convertJsonObjectToWriteable(lastFailedPackageJSON);
WritableMap failedStatusReport = codePushTelemetryManager.getRollbackReport(lastFailedPackage);
if (failedStatusReport != null) {
promise.resolve(failedStatusReport);
return;
}
} catch (JSONException e) {
throw new CodePushUnknownException("Unable to read failed updates information stored in SharedPreferences.", e);
}
}
} else if (didUpdate) {
WritableMap currentPackage = codePushPackage.getCurrentPackage();
if (currentPackage != null) {
WritableMap newPackageStatusReport = codePushTelemetryManager.getUpdateReport(currentPackage);
if (newPackageStatusReport != null) {
promise.resolve(newPackageStatusReport);
return;
}
}
} else if (isRunningBinaryVersion) {
WritableMap newAppVersionStatusReport = codePushTelemetryManager.getBinaryUpdateReport(appVersion);
if (newAppVersionStatusReport != null) {
promise.resolve(newAppVersionStatusReport);
return;
}
}
public void getNewStatusReport(final Promise promise) {
promise.resolve("");
AsyncTask asyncTask = new AsyncTask() {
@Override
protected Void doInBackground(Object... params) {
if (needToReportRollback) {
needToReportRollback = false;
JSONArray failedUpdates = getFailedUpdates();
if (failedUpdates != null && failedUpdates.length() > 0) {
try {
JSONObject lastFailedPackageJSON = failedUpdates.getJSONObject(failedUpdates.length() - 1);
WritableMap lastFailedPackage = CodePushUtils.convertJsonObjectToWriteable(lastFailedPackageJSON);
WritableMap failedStatusReport = codePushTelemetryManager.getRollbackReport(lastFailedPackage);
if (failedStatusReport != null) {
promise.resolve(failedStatusReport);
return null;
}
} catch (JSONException e) {
throw new CodePushUnknownException("Unable to read failed updates information stored in SharedPreferences.", e);
}
}
} else if (didUpdate) {
WritableMap currentPackage = codePushPackage.getCurrentPackage();
if (currentPackage != null) {
WritableMap newPackageStatusReport = codePushTelemetryManager.getUpdateReport(currentPackage);
if (newPackageStatusReport != null) {
promise.resolve(newPackageStatusReport);
return null;
}
}
} else if (isRunningBinaryVersion) {
WritableMap newAppVersionStatusReport = codePushTelemetryManager.getBinaryUpdateReport(appVersion);
if (newAppVersionStatusReport != null) {
promise.resolve(newAppVersionStatusReport);
return null;
}
}
promise.resolve("");
return null;
}
};
asyncTask.execute();
}
@ReactMethod

View File

@@ -69,7 +69,7 @@ public class CodePushPackage {
public WritableMap getCurrentPackageInfo() {
String statusFilePath = getStatusFilePath();
if (!CodePushUtils.fileAtPathExists(statusFilePath)) {
if (!FileUtils.fileAtPathExists(statusFilePath)) {
return new WritableNativeMap();
}
@@ -166,6 +166,7 @@ public class CodePushPackage {
File downloadFile = null;
boolean isZip = false;
// Download the file while checking if it is a zip and notifying client of progress.
try {
downloadUrl = new URL(downloadUrlString);
connection = (HttpURLConnection) (downloadUrl.openConnection());
@@ -216,27 +217,34 @@ public class CodePushPackage {
}
if (isZip) {
// Unzip the downloaded file and then delete the zip
String unzippedFolderPath = getUnzippedFolderPath();
CodePushUtils.unzipFile(downloadFile, unzippedFolderPath);
CodePushUtils.deleteFileSilently(downloadFile);
FileUtils.unzipFile(downloadFile, unzippedFolderPath);
FileUtils.deleteFileSilently(downloadFile);
// Merge contents with current update based on the manifest
String diffManifestFilePath = CodePushUtils.appendPathComponent(unzippedFolderPath,
DIFF_MANIFEST_FILE_NAME);
File diffManifestFile = new File(unzippedFolderPath, DIFF_MANIFEST_FILE_NAME);
if (diffManifestFile.exists()) {
String currentPackageFolderPath = getCurrentPackageFolderPath();
CodePushUtils.mergeEntriesInFolder(currentPackageFolderPath, newPackageFolderPath);
FileUtils.copyDirectoryContents(currentPackageFolderPath, newPackageFolderPath);
WritableMap diffManifest = CodePushUtils.getWritableMapFromFile(diffManifestFilePath);
ReadableArray deletedFiles = diffManifest.getArray("deletedFiles");
for (int i = 0; i < deletedFiles.size(); i++) {
String fileNameToDelete = deletedFiles.getString(i);
File fileToDelete = new File(newPackageFolderPath, fileNameToDelete);
CodePushUtils.deleteFileSilently(fileToDelete);
FileUtils.deleteFileSilently(fileToDelete);
}
}
CodePushUtils.mergeEntriesInFolder(unzippedFolderPath, newPackageFolderPath);
CodePushUtils.deleteFileAtPathSilently(unzippedFolderPath);
String relativeBundlePath = findMainBundleInFolder(newPackageFolderPath);
// Move merged update contents to a folder with the packageHash as its name
FileUtils.copyDirectoryContents(unzippedFolderPath, newPackageFolderPath);
FileUtils.deleteFileAtPathSilently(unzippedFolderPath);
// For zip updates, we need to find the relative path to the jsBundle and save it in the
// metadata so that we can find and run it easily the next time.
String relativeBundlePath = CodePushUtils.findJSBundleInUpdateContents(newPackageFolderPath);
if (relativeBundlePath == null) {
throw new CodePushInvalidPackageException();
@@ -252,46 +260,22 @@ public class CodePushPackage {
updatePackage = CodePushUtils.convertJsonObjectToWriteable(updatePackageJSON);
}
} else {
// File is not a zip.
// File is a jsBundle, move it to a folder with the packageHash as its name
File updateBundleFile = new File(newPackageFolderPath, UPDATE_BUNDLE_FILE_NAME);
downloadFile.renameTo(updateBundleFile);
}
// Save metadata to the folder.
String bundlePath = CodePushUtils.appendPathComponent(newPackageFolderPath, PACKAGE_FILE_NAME);
CodePushUtils.writeReadableMapToFile(updatePackage, bundlePath);
}
public String findMainBundleInFolder(String folderPath) {
File folder = new File(folderPath);
File[] folderFiles = folder.listFiles();
for (File file : folderFiles) {
String fullFilePath = CodePushUtils.appendPathComponent(folderPath, file.getName());
if (file.isDirectory()) {
String mainBundlePathInSubFolder = findMainBundleInFolder(fullFilePath);
if (mainBundlePathInSubFolder != null) {
return CodePushUtils.appendPathComponent(file.getName(), mainBundlePathInSubFolder);
}
} else {
String fileName = file.getName();
int dotIndex = fileName.lastIndexOf(".");
if (dotIndex >= 0) {
String fileExtension = fileName.substring(dotIndex + 1);
if (fileExtension.equals("bundle") || fileExtension.equals("js") || fileExtension.equals("jsbundle")) {
return fileName;
}
}
}
}
return null;
}
public void installPackage(ReadableMap updatePackage) throws IOException {
String packageHash = CodePushUtils.tryGetString(updatePackage, PACKAGE_HASH_KEY);
WritableMap info = getCurrentPackageInfo();
String previousPackageHash = getPreviousPackageHash();
if (previousPackageHash != null && !previousPackageHash.equals(packageHash)) {
CodePushUtils.deleteDirectoryAtPath(getPackageFolderPath(previousPackageHash));
FileUtils.deleteDirectoryAtPath(getPackageFolderPath(previousPackageHash));
}
info.putString(PREVIOUS_PACKAGE_KEY, CodePushUtils.tryGetString(info, CURRENT_PACKAGE_KEY));
@@ -302,7 +286,7 @@ public class CodePushPackage {
public void rollbackPackage() {
WritableMap info = getCurrentPackageInfo();
String currentPackageFolderPath = getCurrentPackageFolderPath();
CodePushUtils.deleteDirectoryAtPath(currentPackageFolderPath);
FileUtils.deleteDirectoryAtPath(currentPackageFolderPath);
info.putString(CURRENT_PACKAGE_KEY, CodePushUtils.tryGetString(info, PREVIOUS_PACKAGE_KEY));
info.putNull(PREVIOUS_PACKAGE_KEY);
updateCurrentPackageInfo(info);
@@ -344,6 +328,6 @@ public class CodePushPackage {
public void clearUpdates() {
File statusFile = new File(getStatusFilePath());
statusFile.delete();
CodePushUtils.deleteDirectoryAtPath(getCodePushPath());
FileUtils.deleteDirectoryAtPath(getCodePushPath());
}
}

View File

@@ -31,89 +31,41 @@ public class CodePushUtils {
public static final String CODE_PUSH_TAG = "CodePush";
public static final String REACT_NATIVE_LOG_TAG = "ReactNative";
public static final int WRITE_BUFFER_SIZE = 1024 * 8;
public static String appendPathComponent(String basePath, String appendPathComponent) {
return new File(basePath, appendPathComponent).getAbsolutePath();
}
public static boolean fileAtPathExists(String filePath) {
return new File(filePath).exists();
}
public static String readFileToString(String filePath) throws IOException {
FileInputStream fin = null;
BufferedReader reader = null;
try {
File fl = new File(filePath);
fin = new FileInputStream(fl);
reader = new BufferedReader(new InputStreamReader(fin));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
public static WritableArray convertJsonArrayToWriteable(JSONArray jsonArr) {
WritableArray arr = Arguments.createArray();
for (int i=0; i<jsonArr.length(); i++) {
Object obj = null;
try {
obj = jsonArr.get(i);
} catch (JSONException jsonException) {
// Should not happen.
throw new CodePushUnknownException(i + " should be within bounds of array " + jsonArr.toString(), jsonException);
}
return sb.toString();
} finally {
if (reader != null) reader.close();
if (fin != null) fin.close();
}
}
public static void writeStringToFile(String content, String filePath) throws IOException {
PrintWriter out = null;
try {
out = new PrintWriter(filePath);
out.print(content);
} finally {
if (out != null) out.close();
}
}
public static void deleteDirectoryAtPath(String directoryPath) {
deleteDirectory(new File(directoryPath));
}
public static void deleteDirectory(File directory) {
if (directory.exists()) {
File[] files = directory.listFiles();
if (files != null) {
for (int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
deleteDirectory(files[i]);
}
else {
files[i].delete();
}
}
}
}
directory.delete();
}
public static boolean createFolderAtPath(String filePath) {
File file = new File(filePath);
return file.mkdir();
}
public static WritableMap getWritableMapFromFile(String filePath) throws IOException {
String content = CodePushUtils.readFileToString(filePath);
JSONObject json = null;
try {
json = new JSONObject(content);
return convertJsonObjectToWriteable(json);
} catch (JSONException jsonException) {
throw new CodePushMalformedDataException(filePath, jsonException);
if (obj instanceof JSONObject)
arr.pushMap(convertJsonObjectToWriteable((JSONObject) obj));
else if (obj instanceof JSONArray)
arr.pushArray(convertJsonArrayToWriteable((JSONArray) obj));
else if (obj instanceof String)
arr.pushString((String) obj);
else if (obj instanceof Double)
arr.pushDouble((Double) obj);
else if (obj instanceof Integer)
arr.pushInt((Integer) obj);
else if (obj instanceof Boolean)
arr.pushBoolean((Boolean) obj);
else if (obj == null)
arr.pushNull();
else
throw new CodePushUnknownException("Unrecognized object: " + obj);
}
}
public static void writeReadableMapToFile(ReadableMap map, String filePath) throws IOException {
JSONObject json = CodePushUtils.convertReadableToJsonObject(map);
String jsonString = json.toString();
CodePushUtils.writeStringToFile(jsonString, filePath);
return arr;
}
public static WritableMap convertJsonObjectToWriteable(JSONObject jsonObj) {
@@ -150,73 +102,9 @@ public class CodePushUtils {
return map;
}
public static WritableArray convertJsonArrayToWriteable(JSONArray jsonArr) {
WritableArray arr = Arguments.createArray();
for (int i=0; i<jsonArr.length(); i++) {
Object obj = null;
try {
obj = jsonArr.get(i);
} catch (JSONException jsonException) {
// Should not happen.
throw new CodePushUnknownException(i + " should be within bounds of array " + jsonArr.toString(), jsonException);
}
if (obj instanceof JSONObject)
arr.pushMap(convertJsonObjectToWriteable((JSONObject) obj));
else if (obj instanceof JSONArray)
arr.pushArray(convertJsonArrayToWriteable((JSONArray) obj));
else if (obj instanceof String)
arr.pushString((String) obj);
else if (obj instanceof Double)
arr.pushDouble((Double) obj);
else if (obj instanceof Integer)
arr.pushInt((Integer) obj);
else if (obj instanceof Boolean)
arr.pushBoolean((Boolean) obj);
else if (obj == null)
arr.pushNull();
else
throw new CodePushUnknownException("Unrecognized object: " + obj);
}
return arr;
}
public static JSONObject convertReadableToJsonObject(ReadableMap map) {
JSONObject jsonObj = new JSONObject();
ReadableMapKeySetIterator it = map.keySetIterator();
while (it.hasNextKey()) {
String key = it.nextKey();
ReadableType type = map.getType(key);
try {
switch (type) {
case Map:
jsonObj.put(key, convertReadableToJsonObject(map.getMap(key)));
break;
case Array:
jsonObj.put(key, convertReadableToJsonArray(map.getArray(key)));
break;
case String:
jsonObj.put(key, map.getString(key));
break;
case Number:
jsonObj.put(key, map.getDouble(key));
break;
case Boolean:
jsonObj.put(key, map.getBoolean(key));
break;
case Null:
jsonObj.put(key, null);
break;
default:
throw new CodePushUnknownException("Unrecognized type: " + type + " of key: " + key);
}
} catch (JSONException jsonException) {
throw new CodePushUnknownException("Error setting key: " + key + " in JSONObject", jsonException);
}
}
return jsonObj;
public static WritableMap convertReadableMapToWritableMap(ReadableMap map) {
JSONObject mapJSON = convertReadableToJsonObject(map);
return convertJsonObjectToWriteable(mapJSON);
}
public static JSONArray convertReadableToJsonArray(ReadableArray arr) {
@@ -258,9 +146,87 @@ public class CodePushUtils {
return jsonArr;
}
public static WritableMap convertReadableMapToWritableMap(ReadableMap map) {
JSONObject mapJSON = convertReadableToJsonObject(map);
return convertJsonObjectToWriteable(mapJSON);
public static JSONObject convertReadableToJsonObject(ReadableMap map) {
JSONObject jsonObj = new JSONObject();
ReadableMapKeySetIterator it = map.keySetIterator();
while (it.hasNextKey()) {
String key = it.nextKey();
ReadableType type = map.getType(key);
try {
switch (type) {
case Map:
jsonObj.put(key, convertReadableToJsonObject(map.getMap(key)));
break;
case Array:
jsonObj.put(key, convertReadableToJsonArray(map.getArray(key)));
break;
case String:
jsonObj.put(key, map.getString(key));
break;
case Number:
jsonObj.put(key, map.getDouble(key));
break;
case Boolean:
jsonObj.put(key, map.getBoolean(key));
break;
case Null:
jsonObj.put(key, null);
break;
default:
throw new CodePushUnknownException("Unrecognized type: " + type + " of key: " + key);
}
} catch (JSONException jsonException) {
throw new CodePushUnknownException("Error setting key: " + key + " in JSONObject", jsonException);
}
}
return jsonObj;
}
public static String findJSBundleInUpdateContents(String folderPath) {
File folder = new File(folderPath);
File[] folderFiles = folder.listFiles();
for (File file : folderFiles) {
String fullFilePath = CodePushUtils.appendPathComponent(folderPath, file.getName());
if (file.isDirectory()) {
String mainBundlePathInSubFolder = findJSBundleInUpdateContents(fullFilePath);
if (mainBundlePathInSubFolder != null) {
return CodePushUtils.appendPathComponent(file.getName(), mainBundlePathInSubFolder);
}
} else {
String fileName = file.getName();
int dotIndex = fileName.lastIndexOf(".");
if (dotIndex >= 0) {
String fileExtension = fileName.substring(dotIndex + 1);
if (fileExtension.equals("bundle") || fileExtension.equals("js") || fileExtension.equals("jsbundle")) {
return fileName;
}
}
}
}
return null;
}
public static WritableMap getWritableMapFromFile(String filePath) throws IOException {
String content = FileUtils.readFileToString(filePath);
JSONObject json = null;
try {
json = new JSONObject(content);
return convertJsonObjectToWriteable(json);
} catch (JSONException jsonException) {
throw new CodePushMalformedDataException(filePath, jsonException);
}
}
public static void log(String message) {
Log.d(REACT_NATIVE_LOG_TAG, "[CodePush] " + message);
}
public static void logBundleUrl(String path) {
log("Loading JS bundle from \"" + path + "\"");
}
public static String tryGetString(ReadableMap map, String key) {
@@ -271,113 +237,9 @@ public class CodePushUtils {
}
}
public static void unzipFile(File zipFile, String destination) throws IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;
ZipInputStream zis = null;
try {
fis = new FileInputStream(zipFile);
bis = new BufferedInputStream(fis);
zis = new ZipInputStream(bis);
ZipEntry entry;
File destinationFolder = new File(destination);
if (!destinationFolder.exists()) {
destinationFolder.mkdirs();
}
byte[] buffer = new byte[WRITE_BUFFER_SIZE];
while ((entry = zis.getNextEntry()) != null) {
String fileName = entry.getName();
File file = new File(destinationFolder, fileName);
if (entry.isDirectory()) {
file.mkdirs();
} else {
File parent = file.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
FileOutputStream fout = new FileOutputStream(file);
try {
int numBytesRead;
while ((numBytesRead = zis.read(buffer)) != -1) {
fout.write(buffer, 0, numBytesRead);
}
} finally {
fout.close();
}
}
long time = entry.getTime();
if (time > 0) {
file.setLastModified(time);
}
}
} finally {
try {
if (zis != null) zis.close();
if (bis != null) bis.close();
if (fis != null) fis.close();
} catch (IOException e) {
throw new CodePushUnknownException("Error closing IO resources.", e);
}
}
}
public static void mergeEntriesInFolder(String fromPath, String destinationPath) throws IOException {
File fromDir = new File(fromPath);
File destDir = new File(destinationPath);
if (!destDir.exists()) {
destDir.mkdir();
}
for (File fromFile : fromDir.listFiles()) {
if (fromFile.isDirectory()) {
mergeEntriesInFolder(
CodePushUtils.appendPathComponent(fromPath, fromFile.getName()),
CodePushUtils.appendPathComponent(destinationPath, fromFile.getName()));
} else {
File destFile = new File(destDir, fromFile.getName());
FileInputStream fromFileStream = null;
BufferedInputStream fromBufferedStream = null;
FileOutputStream destStream = null;
byte[] buffer = new byte[WRITE_BUFFER_SIZE];
try {
fromFileStream = new FileInputStream(fromFile);
fromBufferedStream = new BufferedInputStream(fromFileStream);
destStream = new FileOutputStream(destFile);
int bytesRead;
while ((bytesRead = fromBufferedStream.read(buffer)) > 0) {
destStream.write(buffer, 0, bytesRead);
}
} finally {
try {
if (fromFileStream != null) fromFileStream.close();
if (fromBufferedStream != null) fromBufferedStream.close();
if (destStream != null) destStream.close();
} catch (IOException e) {
throw new CodePushUnknownException("Error closing IO resources.", e);
}
}
}
}
}
public static void deleteFileAtPathSilently(String path) {
deleteFileSilently(new File(path));
}
public static void deleteFileSilently(File file) {
if (!file.delete()) {
Log.e(CODE_PUSH_TAG, "Error deleting file " + file.getName());
}
}
public static void log(String message) {
Log.d(REACT_NATIVE_LOG_TAG, "[CodePush] " + message);
}
public static void logBundleUrl(String path) {
log("Loading JS bundle from \"" + path + "\"");
public static void writeReadableMapToFile(ReadableMap map, String filePath) throws IOException {
JSONObject json = CodePushUtils.convertReadableToJsonObject(map);
String jsonString = json.toString();
FileUtils.writeStringToFile(jsonString, filePath);
}
}

View File

@@ -0,0 +1,181 @@
package com.microsoft.codepush.react;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class FileUtils {
public static final int WRITE_BUFFER_SIZE = 1024 * 8;
public static boolean fileAtPathExists(String filePath) {
return new File(filePath).exists();
}
public static String readFileToString(String filePath) throws IOException {
FileInputStream fin = null;
BufferedReader reader = null;
try {
File fl = new File(filePath);
fin = new FileInputStream(fl);
reader = new BufferedReader(new InputStreamReader(fin));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
} finally {
if (reader != null) reader.close();
if (fin != null) fin.close();
}
}
public static void writeStringToFile(String content, String filePath) throws IOException {
PrintWriter out = null;
try {
out = new PrintWriter(filePath);
out.print(content);
} finally {
if (out != null) out.close();
}
}
public static void deleteDirectoryAtPath(String directoryPath) {
deleteDirectory(new File(directoryPath));
}
public static void deleteDirectory(File directory) {
if (directory.exists()) {
File[] files = directory.listFiles();
if (files != null) {
for (int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
deleteDirectory(files[i]);
}
else {
files[i].delete();
}
}
}
}
directory.delete();
}
public static boolean createFolderAtPath(String filePath) {
File file = new File(filePath);
return file.mkdir();
}
public static void unzipFile(File zipFile, String destination) throws IOException {
FileInputStream fileStream = null;
BufferedInputStream bufferedStream = null;
ZipInputStream zipStream = null;
try {
fileStream = new FileInputStream(zipFile);
bufferedStream = new BufferedInputStream(fileStream);
zipStream = new ZipInputStream(bufferedStream);
ZipEntry entry;
File destinationFolder = new File(destination);
if (!destinationFolder.exists()) {
destinationFolder.mkdirs();
}
byte[] buffer = new byte[WRITE_BUFFER_SIZE];
while ((entry = zipStream.getNextEntry()) != null) {
String fileName = entry.getName();
File file = new File(destinationFolder, fileName);
if (entry.isDirectory()) {
file.mkdirs();
} else {
File parent = file.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
FileOutputStream fout = new FileOutputStream(file);
try {
int numBytesRead;
while ((numBytesRead = zipStream.read(buffer)) != -1) {
fout.write(buffer, 0, numBytesRead);
}
} finally {
fout.close();
}
}
long time = entry.getTime();
if (time > 0) {
file.setLastModified(time);
}
}
} finally {
try {
if (zipStream != null) zipStream.close();
if (bufferedStream != null) bufferedStream.close();
if (fileStream != null) fileStream.close();
} catch (IOException e) {
throw new CodePushUnknownException("Error closing IO resources.", e);
}
}
}
public static void copyDirectoryContents(String sourceDirectoryPath, String destinationDirectoryPath) throws IOException {
File sourceDir = new File(sourceDirectoryPath);
File destDir = new File(destinationDirectoryPath);
if (!destDir.exists()) {
destDir.mkdir();
}
for (File sourceFile : sourceDir.listFiles()) {
if (sourceFile.isDirectory()) {
copyDirectoryContents(
CodePushUtils.appendPathComponent(sourceDirectoryPath, sourceFile.getName()),
CodePushUtils.appendPathComponent(destinationDirectoryPath, sourceFile.getName()));
} else {
File destFile = new File(destDir, sourceFile.getName());
FileInputStream fromFileStream = null;
BufferedInputStream fromBufferedStream = null;
FileOutputStream destStream = null;
byte[] buffer = new byte[WRITE_BUFFER_SIZE];
try {
fromFileStream = new FileInputStream(sourceFile);
fromBufferedStream = new BufferedInputStream(fromFileStream);
destStream = new FileOutputStream(destFile);
int bytesRead;
while ((bytesRead = fromBufferedStream.read(buffer)) > 0) {
destStream.write(buffer, 0, bytesRead);
}
} finally {
try {
if (fromFileStream != null) fromFileStream.close();
if (fromBufferedStream != null) fromBufferedStream.close();
if (destStream != null) destStream.close();
} catch (IOException e) {
throw new CodePushUnknownException("Error closing IO resources.", e);
}
}
}
}
}
public static void deleteFileAtPathSilently(String path) {
deleteFileSilently(new File(path));
}
public static void deleteFileSilently(File file) {
if (!file.delete()) {
CodePushUtils.log("Error deleting file " + file.getName());
}
}
}