/// <summary> /// Load manifest file (MANIFEST.MF) for the specified APK. /// </summary> /// <param name="pathApkMainDirectory"> /// Directory with all the APK's files. /// </param> /// <returns> /// APK manifest file with records about file in APK. /// Returns NULL if manifest file could not be found. /// </returns> public static AndroidApplicationManifest GetApplicationManifest(string pathAppPackageDir) { var manifest = new AndroidApplicationManifest(); string pathManifest = Path.Combine(pathAppPackageDir, PATH_MANIFEST); // Error if MANIFEST.MF can't be found in the APK's main directory if (!File.Exists(pathManifest)) return null; // We consider the specifics of MANIFEST.MF when we read it // MANIFEST.MF consists of records about files in APK // Record looks like: // Name: file_name (NOTE: may be on 2 lines) // SHA1-Digest: file_sha1 using (StreamReader reader = new StreamReader(pathManifest)) { while (!reader.EndOfStream) { string input = reader.ReadLine(); // Skip empty lines and control information as we are interested only // in records about files if (input.Equals(String.Empty) || !input.StartsWith("Name")) continue; string[] inputParts = input.Split(' '); string fileName; string fileSHA; // Read another line to check that the file's path is presented as one line // If it is one line that it must be followed by SHA1 string secondInput = reader.ReadLine().Trim(); if (secondInput.StartsWith("SHA")) { fileName = inputParts[1]; for (int i = 2; i < inputParts.Length; ++i) { fileName += (" " + inputParts[i]); } fileSHA = secondInput.Split(' ')[1]; } // Case when 2 lines are used for the file name // Add combination of lines as the file name else { fileName = inputParts[1]; for (int i = 2; i < inputParts.Length; ++i) { fileName += (" " + inputParts[i]); } fileName += secondInput; // SHA is on the next line fileSHA = reader.ReadLine().Split(' ')[1]; } // Make all the slashes Windows style FileManager.FixSlashesInPath(ref fileName); manifest.AddFileRecordToManifest(new AndroidApplicationManifestRecord(fileName, fileSHA)); } } return manifest; }
/// <summary> /// Marks appropriate files in the reference package as UPDATED. /// Files marked UPDATED - presented in both the old and the target packages but with different SHAs. /// NOTE: Files marked UPDATED will have SHA from the reference package /// </summary> /// <param name="oldAndroidApplicationManifest"> /// Manifest file of the reference package. /// </param> /// <param name="targetManifest"> /// Manifest file of the target package. /// </param> /// <returns> /// Set of files that are marked UPDATED. /// </returns> private static HashSet<AndroidApplicationManifestRecord> MarkFilesUPDATED(AndroidApplicationManifest referenceManifest, AndroidApplicationManifest targetManifest) { // Get the files presented both in the old and the target packages HashSet<AndroidApplicationManifestRecord> commonFilesInManifest = new HashSet<AndroidApplicationManifestRecord>(referenceManifest.FilesInPackage); commonFilesInManifest.IntersectWith(targetManifest.FilesInPackage); HashSet<AndroidApplicationManifestRecord> filesMarkedUpdated = new HashSet<AndroidApplicationManifestRecord>(); // Go through the files and remove those with that are the same in both manifests foreach (AndroidApplicationManifestRecord record in commonFilesInManifest) { // Get the file's SHA in the target package string newFileSHA = targetManifest.FilesInPackage.First(x => x.FileName == record.FileName).FileSHA; // Files are marked as SAME if SHAs are the same. // Files are marked as UPDATED if SHAs are different. if (!record.FileSHA.Equals(newFileSHA)) { filesMarkedUpdated.Add(record); } } return filesMarkedUpdated; }
/// <summary> /// Marks appropriate files in the reference package as DELETE. /// Files marked DELETE - presented in the reference package but not in the target package. /// </summary> /// <param name="referenceManifest"> /// Manifest file of the reference package. /// </param> /// <param name="targetManifest"> /// Manifest file of the target package. /// </param> /// <returns> /// Set of files that are marked DELETE /// </returns> private static HashSet<AndroidApplicationManifestRecord> MarkFilesDELETE(AndroidApplicationManifest referenceManifest, AndroidApplicationManifest targetManifest) { HashSet<AndroidApplicationManifestRecord> filesMarkedDelete = new HashSet<AndroidApplicationManifestRecord>(referenceManifest.FilesInPackage); filesMarkedDelete.ExceptWith(targetManifest.FilesInPackage); return filesMarkedDelete; }
/// <summary> /// Marks appropriate files in the target package as NEW. /// Files marked NEW - presented in the target package but not in the reference package /// </summary> /// <param name="referenceManifest"> /// Manifest file of the reference package. /// </param> /// <param name="targetManifest"> /// Manifest file of the target package. /// </param> /// <returns> /// Set of files that are marked NEW. /// </returns> private static HashSet<AndroidApplicationManifestRecord> MarkFilesNEW(AndroidApplicationManifest referenceManifest, AndroidApplicationManifest targetManifest) { HashSet<AndroidApplicationManifestRecord> filesMarkedNew = new HashSet<AndroidApplicationManifestRecord>(targetManifest.FilesInPackage); filesMarkedNew.ExceptWith(referenceManifest.FilesInPackage); return filesMarkedNew; }
public AndroidApplicationManifest(AndroidApplicationManifest appManifest) { FilesInPackage = new HashSet<AndroidApplicationManifestRecord>(appManifest.FilesInPackage); }