private async Task PrintExpansion(StringBuilder sb, EditsResource edits, AppEdit appEdit, int version) { try { ExpansionFile expansionResponse = await edits.Expansionfiles.Get(PackageName, appEdit.Id, version, EditsResource.ExpansionfilesResource.GetRequest.ExpansionFileTypeEnum.Main).ExecuteAsync(_cts.Token); if (expansionResponse.ReferencesVersion != null) { sb.AppendLine($"Expansion ref ver: {expansionResponse.ReferencesVersion.Value}"); ExpansionFile expansionRefResponse = await edits.Expansionfiles.Get(PackageName, appEdit.Id, expansionResponse.ReferencesVersion.Value, EditsResource.ExpansionfilesResource.GetRequest.ExpansionFileTypeEnum.Main).ExecuteAsync(_cts.Token); if (expansionRefResponse.FileSize != null && expansionRefResponse.FileSize.Value > 0) { sb.AppendLine($"Expansion size: {expansionRefResponse.FileSize.Value}"); } } else if ((expansionResponse.FileSize != null && expansionResponse.FileSize.Value > 0)) { sb.AppendLine($"Expansion size: {expansionResponse.FileSize.Value}"); } } catch (Exception) { // ignored } }
private async Task <ExpansionInfo> GetNewestExpansionFile(EditsResource edits, AppEdit appEdit) { try { ApksListResponse apksResponse = await edits.Apks.List(PackageName, appEdit.Id).ExecuteAsync(_cts.Token); int apkVersion = -1; int expansionVersion = -1; long fileSize = 0; foreach (Apk apk in apksResponse.Apks) { // ReSharper disable once UseNullPropagation if (apk.VersionCode != null) { if (apk.VersionCode.Value > apkVersion) { try { ExpansionFile expansionResponse = await edits.Expansionfiles.Get(PackageName, appEdit.Id, apk.VersionCode.Value, EditsResource.ExpansionfilesResource.GetRequest.ExpansionFileTypeEnum.Main).ExecuteAsync(_cts.Token); if (expansionResponse.ReferencesVersion != null) { expansionVersion = expansionResponse.ReferencesVersion.Value; ExpansionFile expansionRefResponse = await edits.Expansionfiles.Get(PackageName, appEdit.Id, expansionResponse.ReferencesVersion.Value, EditsResource.ExpansionfilesResource.GetRequest.ExpansionFileTypeEnum.Main).ExecuteAsync(_cts.Token); if (expansionRefResponse.FileSize != null && expansionRefResponse.FileSize.Value > 0) { apkVersion = apk.VersionCode.Value; expansionVersion = expansionResponse.ReferencesVersion.Value; fileSize = expansionRefResponse.FileSize.Value; } } else if (expansionResponse.FileSize != null && expansionResponse.FileSize.Value > 0) { apkVersion = apk.VersionCode.Value; expansionVersion = apkVersion; fileSize = expansionResponse.FileSize.Value; } } catch (Exception) { // ignored } } } } if (apkVersion < 0) { return(null); } return(new ExpansionInfo(apkVersion, expansionVersion, fileSize)); } catch (Exception) { // ignored } return(null); }
public void SetExpansionFile(ExpansionFileType type, ExpansionFile file) { var index = (int)type; SetExpansionFileName(index, file.FileName); SetExpansionFileSize(index, file.FileSize); SetExpansionURL(index, file.Url); }
// ReSharper disable once UnusedMethodReturnValue.Local private bool UploadApk(string apkFileName, string expansionFileName, string track, List <UpdateInfo> apkChanges) { if (_serviceThread != null) { return(false); } if (!File.Exists(apkFileName)) { UpdateStatus("Apk file not existing"); return(false); } if (!string.IsNullOrEmpty(expansionFileName) && !File.Exists(expansionFileName)) { UpdateStatus("Expansion file not existing"); return(false); } UpdateStatus(string.Empty); _cts = new CancellationTokenSource(); _serviceThread = new Thread(async() => { UpdateStatus(string.Empty); StringBuilder sb = new StringBuilder(); try { if (apkChanges != null) { sb.Append("Changes info for languages: "); foreach (UpdateInfo updateInfo in apkChanges) { sb.Append($"{updateInfo.Language} "); } sb.AppendLine(); UpdateStatus(sb.ToString()); } UserCredential credential = await GetCredatials(); using (AndroidPublisherService service = new AndroidPublisherService(GetInitializer(credential))) { EditsResource edits = service.Edits; EditsResource.InsertRequest editRequest = edits.Insert(null, PackageName); AppEdit appEdit = await editRequest.ExecuteAsync(_cts.Token); bool reuseExpansion = false; ExpansionInfo expansionInfo = await GetNewestExpansionFile(edits, appEdit); if (expansionInfo != null) { sb.AppendLine($"Latest expansion: apk version={expansionInfo.ApkVersion}, expansion version={expansionInfo.ExpansionVersion}, size={expansionInfo.FileSize}"); if (!string.IsNullOrEmpty(expansionFileName)) { FileInfo fileInfo = new FileInfo(expansionFileName); if (fileInfo.Exists && fileInfo.Length == expansionInfo.FileSize) { sb.AppendLine("Size unchanged, reusing old expansion file"); reuseExpansion = true; } } } Apk apkUploaded = null; using (FileStream apkStream = new FileStream(apkFileName, FileMode.Open, FileAccess.Read)) { long fileLength = (apkStream.Length > 0) ? apkStream.Length : 1; EditsResource.ApksResource.UploadMediaUpload upload = edits.Apks.Upload(PackageName, appEdit.Id, apkStream, "application/vnd.android.package-archive"); upload.ChunkSize = ResumableUpload.MinimumChunkSize; upload.ProgressChanged += progress => { UpdateStatus(sb.ToString() + $"Apk progress: {100 * progress.BytesSent / fileLength}%"); }; upload.ResponseReceived += apk => { apkUploaded = apk; }; IUploadProgress uploadProgress = await upload.UploadAsync(_cts.Token); sb.AppendLine($"Upload status: {uploadProgress.Status.ToString()}"); UpdateStatus(sb.ToString()); if (uploadProgress.Exception != null) { throw uploadProgress.Exception; } } int?versionCode = apkUploaded?.VersionCode; if (!versionCode.HasValue) { throw new Exception("No apk version code"); } sb.AppendLine($"Version code uploaded: {versionCode.Value}"); UpdateStatus(sb.ToString()); if (!string.IsNullOrEmpty(expansionFileName) && !reuseExpansion) { using (FileStream expansionStream = new FileStream(expansionFileName, FileMode.Open, FileAccess.Read)) { long fileLength = (expansionStream.Length > 0) ? expansionStream.Length : 1; EditsResource.ExpansionfilesResource.UploadMediaUpload upload = edits.Expansionfiles.Upload(PackageName, appEdit.Id, versionCode.Value, EditsResource.ExpansionfilesResource.UploadMediaUpload.ExpansionFileTypeEnum.Main, expansionStream, "application/octet-stream"); upload.ChunkSize = ResumableUpload.MinimumChunkSize; upload.ProgressChanged += progress => { UpdateStatus(sb.ToString() + $"Expansion progress: {100 * progress.BytesSent / fileLength}%"); }; IUploadProgress uploadProgress = await upload.UploadAsync(_cts.Token); sb.AppendLine($"Upload status: {uploadProgress.Status.ToString()}"); UpdateStatus(sb.ToString()); if (uploadProgress.Exception != null) { throw uploadProgress.Exception; } } } else { if (expansionInfo != null) { ExpansionFile expansionRef = new ExpansionFile { ReferencesVersion = expansionInfo.ExpansionVersion }; await edits.Expansionfiles.Update(expansionRef, PackageName, appEdit.Id, versionCode.Value, EditsResource.ExpansionfilesResource.UpdateRequest.ExpansionFileTypeEnum.Main).ExecuteAsync(_cts.Token); sb.AppendLine($"Expansion version {expansionInfo.ExpansionVersion} assigned"); } else { sb.AppendLine("No existing expansion found!"); } } Track updateTrack = new Track { VersionCodes = new List <int?> { versionCode.Value } }; EditsResource.TracksResource.UpdateRequest updateRequest = edits.Tracks.Update(updateTrack, PackageName, appEdit.Id, track); Track updatedTrack = await updateRequest.ExecuteAsync(_cts.Token); sb.AppendLine($"Track updated: {updatedTrack.TrackValue}"); UpdateStatus(sb.ToString()); if (apkChanges != null) { foreach (UpdateInfo updateInfo in apkChanges) { ApkListing apkListing = new ApkListing { RecentChanges = updateInfo.Changes }; await edits.Apklistings.Update(apkListing, PackageName, appEdit.Id, versionCode.Value, updateInfo.Language).ExecuteAsync(_cts.Token); sb.AppendLine($"Changes for language {updateInfo.Language} updated"); UpdateStatus(sb.ToString()); } } EditsResource.CommitRequest commitRequest = edits.Commit(PackageName, appEdit.Id); AppEdit appEditCommit = await commitRequest.ExecuteAsync(_cts.Token); sb.AppendLine($"App edit committed: {appEditCommit.Id}"); UpdateStatus(sb.ToString()); } } catch (Exception e) { sb.AppendLine($"Exception: {e.Message}"); } finally { _serviceThread = null; _cts.Dispose(); UpdateStatus(sb.ToString()); } }); _serviceThread.Start(); return(true); }
/// <summary> /// Updates the APK's Expansion File configuration to reference another APK's Expansion Files. To add a new Expansion File use the Upload method. /// Documentation https://developers.google.com/androidpublisher/v2/reference/expansionfiles/update /// Generation Note: This does not always build corectly. Google needs to standardise things I need to figuer out which ones are wrong. /// </summary> /// <param name="service">Authenticated AndroidPublisher service.</param> /// <param name="packageName">Unique identifier for the Android app that is being updated; for example, "com.spiffygame".</param> /// <param name="editId">Unique identifier for this edit.</param> /// <param name="apkVersionCode">The version code of the APK whose Expansion File configuration is being read or modified.</param> /// <param name="expansionFileType">NA</param> /// <param name="body">A valid AndroidPublisher v2 body.</param> /// <returns>ExpansionFileResponse</returns> public static ExpansionFile Update(AndroidPublisherService service, string packageName, string editId, int apkVersionCode, string expansionFileType, ExpansionFile body) { try { // Initial validation. if (service == null) { throw new ArgumentNullException("service"); } if (body == null) { throw new ArgumentNullException("body"); } if (packageName == null) { throw new ArgumentNullException(packageName); } if (editId == null) { throw new ArgumentNullException(editId); } if (expansionFileType == null) { throw new ArgumentNullException(expansionFileType); } // Make the request. return(service.Expansionfiles.Update(body, packageName, editId, apkVersionCode, expansionFileType).Execute()); } catch (Exception ex) { throw new Exception("Request Expansionfiles.Update failed.", ex); } }