コード例 #1
0
 public void ComputePatch(ApplicationPackage reference, ApplicationPackage target, string pathOutputPatch)
 {
     IDeltaEncodingAlgorithm deltaEncodingAlgorithm = new BSDIFFDeltaEncodingAlgortihm();
     deltaEncodingAlgorithm.ComputeDelta(reference.PackagePath, target.PackagePath, pathOutputPatch);
 }
        /// <summary>
        /// Computes patch file for two versions of application presented as two APK files.
        /// Step 1 - Validate both APK files
        /// Step 2 - Change extensions from .apk to .zip and save new files' paths
        /// Step 3 - Create patch directory
        /// Step 4 - Decompress both APKs into the patch directory
        /// Step 5 - Load manifests for both APKs
        /// Step 6 - Construct sets of marked files (files are marked as DELETE, NEW, SAME, UPDATED)
        /// Step 7 - Copy files that are marked NEW into the constructed patch main directory
        /// Step 8 - Delta encode files that are marked UPDATED nad copy .diff files into the patch
        /// Step 9 - Create PatchManifest.xml
        /// Step 10 - Compress patch
        /// Clean up
        /// </summary>
        /// <param name="reference"></param>
        /// <param name="target"></param>
        /// <param name="pathOutputPatch"></param>
        public void ComputePatch(ApplicationPackage reference, ApplicationPackage target, string pathOutputPatch)
        {
            // Step 1 - Validate both APK files
            if (!AndroidPackageManager.ValidatePackage(reference) || !AndroidPackageManager.ValidatePackage(target))
            {
                LogManager.Log(LogMessageType.Error, "Bad APK input files", "Patcher");
                return;
            }

            // Step 2 - Change extensions from .apk to .zip and save new files' paths
            //pathOldApk = FileManager.ChangeExtension(pathOldApk, ".zip");
            //pathNewApk = FileManager.ChangeExtension(pathNewApk, ".zip");

            // Step 3 - Create patch directory
            string pathPatchingWorkDir = Patcher.GetPatchingWorkDir();
            ConstructPathingWorkDir(pathPatchingWorkDir);

            // Step 4 - Decompress both APKs into the temporary directory
            string pathReferenceDir = Path.Combine(pathPatchingWorkDir, NAME_REFERENCE_DIR);
            string pathTargetDir = Path.Combine(pathPatchingWorkDir, NAME_TARGET_DIR);
            CompressionManager.DecompressZIP(reference.PackagePath, pathReferenceDir);
            CompressionManager.DecompressZIP(target.PackagePath, pathTargetDir);

            // Step 5 - Load manifests for both APKs
            AndroidApplicationManifest referenceManifest = AndroidPackageManager.GetApplicationManifest(pathReferenceDir);
            AndroidApplicationManifest targetManifest = AndroidPackageManager.GetApplicationManifest(pathTargetDir);

            // Step 6 - Construct sets of marked files (files are marked as DELETE, NEW, SAME, UPDATED)
            // Mark DELETE files
            HashSet<AndroidApplicationManifestRecord> filesMarkedDELETE = MarkFilesDELETE(referenceManifest, targetManifest);
            // Mark NEW files
            HashSet<AndroidApplicationManifestRecord> filesMarkedNEW = MarkFilesNEW(referenceManifest, targetManifest);
            // Mark UPDATED files
            HashSet<AndroidApplicationManifestRecord> filesMarkedUPDATED = MarkFilesUPDATED(referenceManifest, targetManifest);

            // Step 7 - Copy files that are marked NEW into the constructed patch main directory
            foreach (AndroidApplicationManifestRecord record in filesMarkedNEW)
            {
                CopyFileIntoPatch(record.FileName, Path.Combine(pathPatchingWorkDir, NAME_PATCH_DIR), pathTargetDir);
            }

            // Step 8 - Delta encode files that are marked UPDATED nad copy .diff files into the patch
            var deltaEncodingAlgorithm = new BSDIFFDeltaEncodingAlgortihm();
            foreach (AndroidApplicationManifestRecord record in filesMarkedUPDATED)
            {
                string pathDiffFile = Path.Combine(pathPatchingWorkDir, NAME_PATCH_DIR, record.FileName.Replace('\\', '+')) + ".diff";
                deltaEncodingAlgorithm.ComputeDelta(Path.Combine(pathReferenceDir, record.FileName),
                                                    Path.Combine(pathTargetDir, record.FileName),
                                                    pathDiffFile);

                // We don't want to include .diff file into the patch if its size is greater than the new file size.
                // Instead, we include the new version of file itself.
                if (FileManager.GetFileSize(pathDiffFile) > FileManager.GetFileSize(Path.Combine(pathTargetDir, record.FileName)))
                {
                    File.Delete(pathDiffFile);
                    CopyFileIntoPatch(record.FileName, Path.Combine(pathPatchingWorkDir, NAME_PATCH_DIR), pathTargetDir);

                    // Add files to filesMarkedNEW and filesMarkedDELETE
                    // During deployment we will delete old file and copy the new one instead of patching the old file
                    filesMarkedDELETE.Add(record);
                    filesMarkedNEW.Add(record);
                }
            }
            // Remove all files that are in filesMarkedNEW from filesMarkedUPDATED
            filesMarkedUPDATED.ExceptWith(filesMarkedNEW);

            // Step 9 - Create PatchManifest.xml
            string patchName = NamingHelper.GetPatchName(reference, target);
            PatchManifest manifest = new PatchManifest(patchName, reference, target);
            // We need only files names in the manifest
            foreach (AndroidApplicationManifestRecord record in filesMarkedNEW)
            {
                manifest.AddFileNEW(record.FileName);
            }
            foreach (AndroidApplicationManifestRecord record in filesMarkedDELETE)
            {
                manifest.AddFileDELETE(record.FileName);
            }
            foreach (AndroidApplicationManifestRecord record in filesMarkedUPDATED)
            {
                manifest.AddFileUPDATED(record.FileName);
            }
            FileManager.SerializeObjectToXML(manifest, Path.Combine(pathPatchingWorkDir, NAME_PATCH_DIR, NAME_PATCH_MANIFEST));

            // Step 10 - Compress patch
            CompressionManager.CompressDirToZIP(Path.Combine(pathPatchingWorkDir, NAME_PATCH_DIR),
                                                Path.Combine(pathPatchingWorkDir, patchName));

            // Clean up
            // Delete temp directory
            FileManager.DeleteDirectory(pathPatchingWorkDir);

            Console.WriteLine(String.Format("Finished patch creation: {0} -> {1}", reference.PackagePath, target.PackagePath));
        }