From f8f6ff248eb9a54de48388c9a492f7addd488719 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 22 Apr 2023 21:16:04 +0530 Subject: [PATCH 01/82] [1/2] Rearrange the project for better Android Studio support Signed-off-by: Aayush Gupta --- {src => lib/src}/main/java/com/aurora/gplayapi/Constants.kt | 0 {src => lib/src}/main/java/com/aurora/gplayapi/DeviceManager.kt | 0 {src => lib/src}/main/java/com/aurora/gplayapi/FileManager.kt | 0 {src => lib/src}/main/java/com/aurora/gplayapi/GooglePlayApi.kt | 0 .../main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt | 0 .../main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt | 0 .../main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt | 0 .../main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt | 0 .../main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt | 0 .../com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt | 0 .../java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt | 0 {src => lib/src}/main/java/com/aurora/gplayapi/data/models/App.kt | 0 .../src}/main/java/com/aurora/gplayapi/data/models/Artwork.kt | 0 .../src}/main/java/com/aurora/gplayapi/data/models/AuthData.kt | 0 .../src}/main/java/com/aurora/gplayapi/data/models/Category.kt | 0 .../src}/main/java/com/aurora/gplayapi/data/models/File.kt | 0 .../main/java/com/aurora/gplayapi/data/models/PlayResponse.kt | 0 .../src}/main/java/com/aurora/gplayapi/data/models/Rating.kt | 0 .../src}/main/java/com/aurora/gplayapi/data/models/Review.kt | 0 .../main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt | 0 .../main/java/com/aurora/gplayapi/data/models/SearchBundle.kt | 0 .../main/java/com/aurora/gplayapi/data/models/StreamBundle.kt | 0 .../main/java/com/aurora/gplayapi/data/models/StreamCluster.kt | 0 .../src}/main/java/com/aurora/gplayapi/data/models/UserProfile.kt | 0 .../main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt | 0 .../main/java/com/aurora/gplayapi/data/models/details/Badge.kt | 0 .../main/java/com/aurora/gplayapi/data/models/details/Chip.kt | 0 .../java/com/aurora/gplayapi/data/models/details/Dependencies.kt | 0 .../java/com/aurora/gplayapi/data/models/details/DevStream.kt | 0 .../com/aurora/gplayapi/data/models/details/TestingProgram.kt | 0 .../com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt | 0 .../com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt | 0 .../com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt | 0 .../main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt | 0 .../main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt | 0 .../com/aurora/gplayapi/data/providers/BaseDeviceInfoProvider.kt | 0 .../java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt | 0 .../java/com/aurora/gplayapi/data/providers/HeaderProvider.kt | 0 .../main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt | 0 .../src}/main/java/com/aurora/gplayapi/exceptions/ApiException.kt | 0 .../main/java/com/aurora/gplayapi/exceptions/AuthException.kt | 0 .../java/com/aurora/gplayapi/exceptions/GooglePlayException.kt | 0 .../main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt | 0 .../main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt | 0 .../src}/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt | 0 .../main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt | 0 .../main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt | 0 .../src}/main/java/com/aurora/gplayapi/network/IHttpClient.kt | 0 {src => lib/src}/main/java/com/aurora/gplayapi/utils/Util.java | 0 {src => lib/src}/main/proto/GooglePlay.proto | 0 {src/main/resources => lib/src/main/res/raw}/ad_g3_pro.properties | 0 .../resources => lib/src/main/res/raw}/bravia_atv2.properties | 0 {src/main/resources => lib/src/main/res/raw}/fp_2.properties | 0 {src/main/resources => lib/src/main/res/raw}/hw_h9.properties | 0 {src/main/resources => lib/src/main/res/raw}/hw_mate20.properties | 0 {src/main/resources => lib/src/main/res/raw}/mi_8_se.properties | 0 {src/main/resources => lib/src/main/res/raw}/mi_a1.properties | 0 {src/main/resources => lib/src/main/res/raw}/mi_mix2.properties | 0 {src/main/resources => lib/src/main/res/raw}/moto_g5.properties | 0 {src/main/resources => lib/src/main/res/raw}/nk_8.properties | 0 {src/main/resources => lib/src/main/res/raw}/nk_9.properties | 0 {src/main/resources => lib/src/main/res/raw}/nk_drx.properties | 0 {src/main/resources => lib/src/main/res/raw}/op_3.properties | 0 {src/main/resources => lib/src/main/res/raw}/op_5.properties | 0 {src/main/resources => lib/src/main/res/raw}/op_5t.properties | 0 {src/main/resources => lib/src/main/res/raw}/op_6.properties | 0 {src/main/resources => lib/src/main/res/raw}/op_7t.properties | 0 {src/main/resources => lib/src/main/res/raw}/op_7t_pro.properties | 0 {src/main/resources => lib/src/main/res/raw}/op_8_pro.properties | 0 {src/main/resources => lib/src/main/res/raw}/op_x.properties | 0 {src/main/resources => lib/src/main/res/raw}/poco_f1.properties | 0 {src/main/resources => lib/src/main/res/raw}/px_3a.properties | 0 {src/main/resources => lib/src/main/res/raw}/rm_4.properties | 0 {src/main/resources => lib/src/main/res/raw}/rm_5.properties | 0 {src/main/resources => lib/src/main/res/raw}/rm_5_plus.properties | 0 {src/main/resources => lib/src/main/res/raw}/rm_5_pro.properties | 0 {src/main/resources => lib/src/main/res/raw}/rm_5i.properties | 0 {src/main/resources => lib/src/main/res/raw}/rm_7.properties | 0 .../main/resources => lib/src/main/res/raw}/rm_k20_pro.properties | 0 {src/main/resources => lib/src/main/res/raw}/rm_note_3.properties | 0 {src/main/resources => lib/src/main/res/raw}/rm_note_5.properties | 0 {src/main/resources => lib/src/main/res/raw}/sm_a3.properties | 0 {src/main/resources => lib/src/main/res/raw}/sm_feel.properties | 0 {src/main/resources => lib/src/main/res/raw}/sm_s7.properties | 0 {src/main/resources => lib/src/main/res/raw}/sm_s8.properties | 0 .../main/resources => lib/src/main/res/raw}/sm_s9_plus.properties | 0 {src/main/resources => lib/src/main/res/raw}/tw_e.properties | 0 {src/main/resources => lib/src/main/res/raw}/xp_5_dual.properties | 0 99 files changed, 0 insertions(+), 0 deletions(-) rename {src => lib/src}/main/java/com/aurora/gplayapi/Constants.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/DeviceManager.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/FileManager.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/GooglePlayApi.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/App.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/Artwork.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/AuthData.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/Category.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/File.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/PlayResponse.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/Rating.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/Review.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/SearchBundle.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/StreamBundle.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/StreamCluster.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/UserProfile.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/details/Badge.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/details/Chip.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/details/DevStream.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/providers/BaseDeviceInfoProvider.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/providers/HeaderProvider.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/exceptions/ApiException.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/exceptions/AuthException.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/exceptions/GooglePlayException.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/network/IHttpClient.kt (100%) rename {src => lib/src}/main/java/com/aurora/gplayapi/utils/Util.java (100%) rename {src => lib/src}/main/proto/GooglePlay.proto (100%) rename {src/main/resources => lib/src/main/res/raw}/ad_g3_pro.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/bravia_atv2.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/fp_2.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/hw_h9.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/hw_mate20.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/mi_8_se.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/mi_a1.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/mi_mix2.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/moto_g5.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/nk_8.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/nk_9.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/nk_drx.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/op_3.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/op_5.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/op_5t.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/op_6.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/op_7t.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/op_7t_pro.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/op_8_pro.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/op_x.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/poco_f1.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/px_3a.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/rm_4.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/rm_5.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/rm_5_plus.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/rm_5_pro.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/rm_5i.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/rm_7.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/rm_k20_pro.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/rm_note_3.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/rm_note_5.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/sm_a3.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/sm_feel.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/sm_s7.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/sm_s8.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/sm_s9_plus.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/tw_e.properties (100%) rename {src/main/resources => lib/src/main/res/raw}/xp_5_dual.properties (100%) diff --git a/src/main/java/com/aurora/gplayapi/Constants.kt b/lib/src/main/java/com/aurora/gplayapi/Constants.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/Constants.kt rename to lib/src/main/java/com/aurora/gplayapi/Constants.kt diff --git a/src/main/java/com/aurora/gplayapi/DeviceManager.kt b/lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/DeviceManager.kt rename to lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt diff --git a/src/main/java/com/aurora/gplayapi/FileManager.kt b/lib/src/main/java/com/aurora/gplayapi/FileManager.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/FileManager.kt rename to lib/src/main/java/com/aurora/gplayapi/FileManager.kt diff --git a/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt b/lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/GooglePlayApi.kt rename to lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt diff --git a/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt rename to lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt diff --git a/src/main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt rename to lib/src/main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt diff --git a/src/main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt rename to lib/src/main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt diff --git a/src/main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt rename to lib/src/main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt diff --git a/src/main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt rename to lib/src/main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt diff --git a/src/main/java/com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt rename to lib/src/main/java/com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt diff --git a/src/main/java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt rename to lib/src/main/java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/App.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/App.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/App.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/App.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/Artwork.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/AuthData.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/AuthData.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/AuthData.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/AuthData.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/Category.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Category.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/Category.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/Category.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/File.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/File.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/File.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/File.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/PlayResponse.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/PlayResponse.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/PlayResponse.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/PlayResponse.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/Rating.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/Rating.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/Review.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Review.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/Review.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/Review.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/SearchBundle.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/SearchBundle.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/SearchBundle.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/SearchBundle.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/StreamBundle.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/StreamBundle.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/StreamBundle.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/StreamBundle.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/StreamCluster.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/StreamCluster.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/StreamCluster.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/StreamCluster.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/UserProfile.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/UserProfile.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/UserProfile.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/UserProfile.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/details/DevStream.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/DevStream.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/details/DevStream.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/details/DevStream.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt diff --git a/src/main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt rename to lib/src/main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt diff --git a/src/main/java/com/aurora/gplayapi/data/providers/BaseDeviceInfoProvider.kt b/lib/src/main/java/com/aurora/gplayapi/data/providers/BaseDeviceInfoProvider.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/providers/BaseDeviceInfoProvider.kt rename to lib/src/main/java/com/aurora/gplayapi/data/providers/BaseDeviceInfoProvider.kt diff --git a/src/main/java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt b/lib/src/main/java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt rename to lib/src/main/java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt diff --git a/src/main/java/com/aurora/gplayapi/data/providers/HeaderProvider.kt b/lib/src/main/java/com/aurora/gplayapi/data/providers/HeaderProvider.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/providers/HeaderProvider.kt rename to lib/src/main/java/com/aurora/gplayapi/data/providers/HeaderProvider.kt diff --git a/src/main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt b/lib/src/main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt rename to lib/src/main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt diff --git a/src/main/java/com/aurora/gplayapi/exceptions/ApiException.kt b/lib/src/main/java/com/aurora/gplayapi/exceptions/ApiException.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/exceptions/ApiException.kt rename to lib/src/main/java/com/aurora/gplayapi/exceptions/ApiException.kt diff --git a/src/main/java/com/aurora/gplayapi/exceptions/AuthException.kt b/lib/src/main/java/com/aurora/gplayapi/exceptions/AuthException.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/exceptions/AuthException.kt rename to lib/src/main/java/com/aurora/gplayapi/exceptions/AuthException.kt diff --git a/src/main/java/com/aurora/gplayapi/exceptions/GooglePlayException.kt b/lib/src/main/java/com/aurora/gplayapi/exceptions/GooglePlayException.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/exceptions/GooglePlayException.kt rename to lib/src/main/java/com/aurora/gplayapi/exceptions/GooglePlayException.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt rename to lib/src/main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt diff --git a/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt b/lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt rename to lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt diff --git a/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt b/lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt similarity index 100% rename from src/main/java/com/aurora/gplayapi/network/IHttpClient.kt rename to lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt diff --git a/src/main/java/com/aurora/gplayapi/utils/Util.java b/lib/src/main/java/com/aurora/gplayapi/utils/Util.java similarity index 100% rename from src/main/java/com/aurora/gplayapi/utils/Util.java rename to lib/src/main/java/com/aurora/gplayapi/utils/Util.java diff --git a/src/main/proto/GooglePlay.proto b/lib/src/main/proto/GooglePlay.proto similarity index 100% rename from src/main/proto/GooglePlay.proto rename to lib/src/main/proto/GooglePlay.proto diff --git a/src/main/resources/ad_g3_pro.properties b/lib/src/main/res/raw/ad_g3_pro.properties similarity index 100% rename from src/main/resources/ad_g3_pro.properties rename to lib/src/main/res/raw/ad_g3_pro.properties diff --git a/src/main/resources/bravia_atv2.properties b/lib/src/main/res/raw/bravia_atv2.properties similarity index 100% rename from src/main/resources/bravia_atv2.properties rename to lib/src/main/res/raw/bravia_atv2.properties diff --git a/src/main/resources/fp_2.properties b/lib/src/main/res/raw/fp_2.properties similarity index 100% rename from src/main/resources/fp_2.properties rename to lib/src/main/res/raw/fp_2.properties diff --git a/src/main/resources/hw_h9.properties b/lib/src/main/res/raw/hw_h9.properties similarity index 100% rename from src/main/resources/hw_h9.properties rename to lib/src/main/res/raw/hw_h9.properties diff --git a/src/main/resources/hw_mate20.properties b/lib/src/main/res/raw/hw_mate20.properties similarity index 100% rename from src/main/resources/hw_mate20.properties rename to lib/src/main/res/raw/hw_mate20.properties diff --git a/src/main/resources/mi_8_se.properties b/lib/src/main/res/raw/mi_8_se.properties similarity index 100% rename from src/main/resources/mi_8_se.properties rename to lib/src/main/res/raw/mi_8_se.properties diff --git a/src/main/resources/mi_a1.properties b/lib/src/main/res/raw/mi_a1.properties similarity index 100% rename from src/main/resources/mi_a1.properties rename to lib/src/main/res/raw/mi_a1.properties diff --git a/src/main/resources/mi_mix2.properties b/lib/src/main/res/raw/mi_mix2.properties similarity index 100% rename from src/main/resources/mi_mix2.properties rename to lib/src/main/res/raw/mi_mix2.properties diff --git a/src/main/resources/moto_g5.properties b/lib/src/main/res/raw/moto_g5.properties similarity index 100% rename from src/main/resources/moto_g5.properties rename to lib/src/main/res/raw/moto_g5.properties diff --git a/src/main/resources/nk_8.properties b/lib/src/main/res/raw/nk_8.properties similarity index 100% rename from src/main/resources/nk_8.properties rename to lib/src/main/res/raw/nk_8.properties diff --git a/src/main/resources/nk_9.properties b/lib/src/main/res/raw/nk_9.properties similarity index 100% rename from src/main/resources/nk_9.properties rename to lib/src/main/res/raw/nk_9.properties diff --git a/src/main/resources/nk_drx.properties b/lib/src/main/res/raw/nk_drx.properties similarity index 100% rename from src/main/resources/nk_drx.properties rename to lib/src/main/res/raw/nk_drx.properties diff --git a/src/main/resources/op_3.properties b/lib/src/main/res/raw/op_3.properties similarity index 100% rename from src/main/resources/op_3.properties rename to lib/src/main/res/raw/op_3.properties diff --git a/src/main/resources/op_5.properties b/lib/src/main/res/raw/op_5.properties similarity index 100% rename from src/main/resources/op_5.properties rename to lib/src/main/res/raw/op_5.properties diff --git a/src/main/resources/op_5t.properties b/lib/src/main/res/raw/op_5t.properties similarity index 100% rename from src/main/resources/op_5t.properties rename to lib/src/main/res/raw/op_5t.properties diff --git a/src/main/resources/op_6.properties b/lib/src/main/res/raw/op_6.properties similarity index 100% rename from src/main/resources/op_6.properties rename to lib/src/main/res/raw/op_6.properties diff --git a/src/main/resources/op_7t.properties b/lib/src/main/res/raw/op_7t.properties similarity index 100% rename from src/main/resources/op_7t.properties rename to lib/src/main/res/raw/op_7t.properties diff --git a/src/main/resources/op_7t_pro.properties b/lib/src/main/res/raw/op_7t_pro.properties similarity index 100% rename from src/main/resources/op_7t_pro.properties rename to lib/src/main/res/raw/op_7t_pro.properties diff --git a/src/main/resources/op_8_pro.properties b/lib/src/main/res/raw/op_8_pro.properties similarity index 100% rename from src/main/resources/op_8_pro.properties rename to lib/src/main/res/raw/op_8_pro.properties diff --git a/src/main/resources/op_x.properties b/lib/src/main/res/raw/op_x.properties similarity index 100% rename from src/main/resources/op_x.properties rename to lib/src/main/res/raw/op_x.properties diff --git a/src/main/resources/poco_f1.properties b/lib/src/main/res/raw/poco_f1.properties similarity index 100% rename from src/main/resources/poco_f1.properties rename to lib/src/main/res/raw/poco_f1.properties diff --git a/src/main/resources/px_3a.properties b/lib/src/main/res/raw/px_3a.properties similarity index 100% rename from src/main/resources/px_3a.properties rename to lib/src/main/res/raw/px_3a.properties diff --git a/src/main/resources/rm_4.properties b/lib/src/main/res/raw/rm_4.properties similarity index 100% rename from src/main/resources/rm_4.properties rename to lib/src/main/res/raw/rm_4.properties diff --git a/src/main/resources/rm_5.properties b/lib/src/main/res/raw/rm_5.properties similarity index 100% rename from src/main/resources/rm_5.properties rename to lib/src/main/res/raw/rm_5.properties diff --git a/src/main/resources/rm_5_plus.properties b/lib/src/main/res/raw/rm_5_plus.properties similarity index 100% rename from src/main/resources/rm_5_plus.properties rename to lib/src/main/res/raw/rm_5_plus.properties diff --git a/src/main/resources/rm_5_pro.properties b/lib/src/main/res/raw/rm_5_pro.properties similarity index 100% rename from src/main/resources/rm_5_pro.properties rename to lib/src/main/res/raw/rm_5_pro.properties diff --git a/src/main/resources/rm_5i.properties b/lib/src/main/res/raw/rm_5i.properties similarity index 100% rename from src/main/resources/rm_5i.properties rename to lib/src/main/res/raw/rm_5i.properties diff --git a/src/main/resources/rm_7.properties b/lib/src/main/res/raw/rm_7.properties similarity index 100% rename from src/main/resources/rm_7.properties rename to lib/src/main/res/raw/rm_7.properties diff --git a/src/main/resources/rm_k20_pro.properties b/lib/src/main/res/raw/rm_k20_pro.properties similarity index 100% rename from src/main/resources/rm_k20_pro.properties rename to lib/src/main/res/raw/rm_k20_pro.properties diff --git a/src/main/resources/rm_note_3.properties b/lib/src/main/res/raw/rm_note_3.properties similarity index 100% rename from src/main/resources/rm_note_3.properties rename to lib/src/main/res/raw/rm_note_3.properties diff --git a/src/main/resources/rm_note_5.properties b/lib/src/main/res/raw/rm_note_5.properties similarity index 100% rename from src/main/resources/rm_note_5.properties rename to lib/src/main/res/raw/rm_note_5.properties diff --git a/src/main/resources/sm_a3.properties b/lib/src/main/res/raw/sm_a3.properties similarity index 100% rename from src/main/resources/sm_a3.properties rename to lib/src/main/res/raw/sm_a3.properties diff --git a/src/main/resources/sm_feel.properties b/lib/src/main/res/raw/sm_feel.properties similarity index 100% rename from src/main/resources/sm_feel.properties rename to lib/src/main/res/raw/sm_feel.properties diff --git a/src/main/resources/sm_s7.properties b/lib/src/main/res/raw/sm_s7.properties similarity index 100% rename from src/main/resources/sm_s7.properties rename to lib/src/main/res/raw/sm_s7.properties diff --git a/src/main/resources/sm_s8.properties b/lib/src/main/res/raw/sm_s8.properties similarity index 100% rename from src/main/resources/sm_s8.properties rename to lib/src/main/res/raw/sm_s8.properties diff --git a/src/main/resources/sm_s9_plus.properties b/lib/src/main/res/raw/sm_s9_plus.properties similarity index 100% rename from src/main/resources/sm_s9_plus.properties rename to lib/src/main/res/raw/sm_s9_plus.properties diff --git a/src/main/resources/tw_e.properties b/lib/src/main/res/raw/tw_e.properties similarity index 100% rename from src/main/resources/tw_e.properties rename to lib/src/main/res/raw/tw_e.properties diff --git a/src/main/resources/xp_5_dual.properties b/lib/src/main/res/raw/xp_5_dual.properties similarity index 100% rename from src/main/resources/xp_5_dual.properties rename to lib/src/main/res/raw/xp_5_dual.properties -- GitLab From 70703f7d739d4d865c6cd4967c59555c93a7312e Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 22 Apr 2023 15:00:04 +0530 Subject: [PATCH 02/82] [2/2] Rearrange the project for better Android Studio support Signed-off-by: Aayush Gupta --- build.gradle | 58 ++--------------------- gradle.properties | 23 +++++++++ gradle/wrapper/gradle-wrapper.properties | 21 ++------- lib/.gitignore | 1 + lib/build.gradle | 59 ++++++++++++++++++++++++ lib/proguard-rules.pro | 21 +++++++++ lib/src/main/AndroidManifest.xml | 2 + settings.gradle | 16 ++++++- 8 files changed, 129 insertions(+), 72 deletions(-) create mode 100644 gradle.properties create mode 100644 lib/.gitignore create mode 100644 lib/build.gradle create mode 100644 lib/proguard-rules.pro create mode 100644 lib/src/main/AndroidManifest.xml diff --git a/build.gradle b/build.gradle index a3c2994..eafd101 100644 --- a/build.gradle +++ b/build.gradle @@ -13,60 +13,12 @@ * GNU General Public License for more details. */ -buildscript { - repositories { - jcenter() - } - dependencies { - classpath("com.google.protobuf:protobuf-gradle-plugin:0.8.12") - } -} - plugins { - id("java-library") - id("com.google.protobuf") version("0.8.12") - id("org.jetbrains.kotlin.jvm") version("1.4.10") + id 'com.android.library' version '7.4.2' apply false + id 'org.jetbrains.kotlin.android' version '1.8.20' apply false + id 'com.google.protobuf' version '0.9.1' apply false } -group("com.aurora") -version("3.0.1") - -repositories { - mavenCentral() +task clean(type: Delete) { + delete rootProject.buildDir } - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - - //Protobuf - implementation "com.google.protobuf:protobuf-java:3.10.0" - - //Fuel - implementation("com.github.kittinunf.fuel:fuel:2.3.0") - - //Gson - implementation 'com.google.code.gson:gson:2.8.6' -} - -sourceSets { - main.kotlin.srcDirs += "src/main/java" - main.kotlin.srcDirs += "build/generated/source/proto/main/java" -} - -tasks.withType(JavaCompile) { - options.encoding = ("UTF-8") -} - -jar { - exclude("*.proto") -} - -clean { - delete protobuf.generatedFilesBaseDir -} - -protobuf { - protoc { - artifact = ("com.google.protobuf:protoc:3.10.0") - } -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..55cce92 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,23 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 09943d3..162b1da 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,21 +1,6 @@ -# -# GPlayApi -# Copyright (C) 2020 Aurora OSS -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# - -#Thu Apr 30 12:26:16 IST 2020 -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +#Fri Apr 21 18:26:18 IST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1 @@ +/build diff --git a/lib/build.gradle b/lib/build.gradle new file mode 100644 index 0000000..5c62139 --- /dev/null +++ b/lib/build.gradle @@ -0,0 +1,59 @@ +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' + id 'com.google.protobuf' +} + +android { + namespace 'com.aurora.gplayapi' + compileSdk 33 + + defaultConfig { + minSdk 19 + targetSdk 33 + aarMetadata { + minCompileSdk = 19 + } + } + + buildTypes { + release { + minifyEnabled false + consumerProguardFiles 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = '11' + } + packagingOptions { + resources { + excludes += '**/*.proto' + } + } +} + +dependencies { + + implementation 'com.google.protobuf:protobuf-javalite:3.22.3' + implementation 'com.github.kittinunf.fuel:fuel:2.3.0' + implementation 'com.google.code.gson:gson:2.10' +} + +protobuf { + protoc { + artifact = 'com.google.protobuf:protoc:3.22.3' + } + generateProtoTasks { + all().configureEach { task -> + task.builtins { + java { + option "lite" + } + } + } + } +} diff --git a/lib/proguard-rules.pro b/lib/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/lib/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/lib/src/main/AndroidManifest.xml b/lib/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8072ee0 --- /dev/null +++ b/lib/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/settings.gradle b/settings.gradle index 517b153..dfc8cc4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,5 +13,19 @@ * GNU General Public License for more details. */ +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} rootProject.name = 'gplayapi' - +include ':lib' -- GitLab From 924f8af3306696cc792badda882e448aa6b3dff2 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 22 Apr 2023 19:46:08 +0530 Subject: [PATCH 03/82] Add support for publications Signed-off-by: Aayush Gupta --- lib/build.gradle | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/build.gradle b/lib/build.gradle index 5c62139..73150ea 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -2,6 +2,7 @@ plugins { id 'com.android.library' id 'org.jetbrains.kotlin.android' id 'com.google.protobuf' + id 'maven-publish' } android { @@ -57,3 +58,24 @@ protobuf { } } } + +// Run "./gradlew publishReleaseToLocalRepository" to generate release AAR locally +publishing { + publications { + release(MavenPublication) { + groupId = 'com.aurora' + artifactId = 'gplayapi' + version = '3.0.1' + + afterEvaluate { + from components.release + } + } + } + repositories { + maven { + name = 'local' + url = "${project.buildDir}/repo" + } + } +} -- GitLab From b6f7660dffba5c7c5c2587a862586a633719a895 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 22 Apr 2023 20:10:59 +0530 Subject: [PATCH 04/82] Import basic GitLab CI configuration Signed-off-by: Aayush Gupta --- .gitlab-ci.yml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..fc10238 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,39 @@ +image: jangrewe/gitlab-ci-android + +before_script: + - export GRADLE_USER_HOME=$(pwd)/.gradle + - chmod +x ./gradlew + +cache: + key: ${CI_PROJECT_ID} + paths: + - .gradle/ + +stages: + - debug + - release + +assembleDebug: + stage: debug + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + when: always + - if: '$CI_COMMIT_BRANCH != "$CI_DEFAULT_BRANCH"' + when: always + script: + - ./gradlew assembleDebug + artifacts: + paths: + - lib/build/outputs/aar/ + +assembleRelease: + stage: release + allow_failure: false + rules: + - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' + when: always + script: + - ./gradlew publishReleaseToLocalRepository + artifacts: + paths: + - lib/build/repo/com/aurora/gplayapi/**/ -- GitLab From 265f3b529a799e274e0e31a26c053f111b0c8ae0 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 22 Apr 2023 22:05:34 +0530 Subject: [PATCH 05/82] fixup! Import basic GitLab CI configuration --- .gitlab-ci.yml | 2 +- lib/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fc10238..2aa67d7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,7 +33,7 @@ assembleRelease: - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' when: always script: - - ./gradlew publishReleaseToLocalRepository + - ./gradlew publishReleasePublicationToLocalRepository artifacts: paths: - lib/build/repo/com/aurora/gplayapi/**/ diff --git a/lib/build.gradle b/lib/build.gradle index 73150ea..97ff392 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -59,7 +59,7 @@ protobuf { } } -// Run "./gradlew publishReleaseToLocalRepository" to generate release AAR locally +// Run "./gradlew publishReleasePublicationToLocalRepository" to generate release AAR locally publishing { publications { release(MavenPublication) { -- GitLab From fdafdcb9318c3e2e45f0389b4cf31718fda807ba Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sun, 23 Apr 2023 12:22:46 +0530 Subject: [PATCH 06/82] Keep device spoofing properties from being shrinked Append a prefix to all properties name and specify that to ensure all our properties are kept when app including the library shrinks resources. Signed-off-by: Aayush Gupta --- lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt | 6 ++---- .../{ad_g3_pro.properties => gplayapi_ad_g3_pro.properties} | 0 ...avia_atv2.properties => gplayapi_bravia_atv2.properties} | 0 .../res/raw/{fp_2.properties => gplayapi_fp_2.properties} | 0 .../res/raw/{hw_h9.properties => gplayapi_hw_h9.properties} | 0 .../{hw_mate20.properties => gplayapi_hw_mate20.properties} | 0 .../raw/{mi_8_se.properties => gplayapi_mi_8_se.properties} | 0 .../res/raw/{mi_a1.properties => gplayapi_mi_a1.properties} | 0 .../raw/{mi_mix2.properties => gplayapi_mi_mix2.properties} | 0 .../raw/{moto_g5.properties => gplayapi_moto_g5.properties} | 0 .../res/raw/{nk_8.properties => gplayapi_nk_8.properties} | 0 .../res/raw/{nk_9.properties => gplayapi_nk_9.properties} | 0 .../raw/{nk_drx.properties => gplayapi_nk_drx.properties} | 0 .../res/raw/{op_3.properties => gplayapi_op_3.properties} | 0 .../res/raw/{op_5.properties => gplayapi_op_5.properties} | 0 .../res/raw/{op_5t.properties => gplayapi_op_5t.properties} | 0 .../res/raw/{op_6.properties => gplayapi_op_6.properties} | 0 .../res/raw/{op_7t.properties => gplayapi_op_7t.properties} | 0 .../{op_7t_pro.properties => gplayapi_op_7t_pro.properties} | 0 .../{op_8_pro.properties => gplayapi_op_8_pro.properties} | 0 .../res/raw/{op_x.properties => gplayapi_op_x.properties} | 0 .../raw/{poco_f1.properties => gplayapi_poco_f1.properties} | 0 .../res/raw/{px_3a.properties => gplayapi_px_3a.properties} | 0 .../res/raw/{rm_4.properties => gplayapi_rm_4.properties} | 0 .../res/raw/{rm_5.properties => gplayapi_rm_5.properties} | 0 .../{rm_5_plus.properties => gplayapi_rm_5_plus.properties} | 0 .../{rm_5_pro.properties => gplayapi_rm_5_pro.properties} | 0 .../res/raw/{rm_5i.properties => gplayapi_rm_5i.properties} | 0 .../res/raw/{rm_7.properties => gplayapi_rm_7.properties} | 0 ...rm_k20_pro.properties => gplayapi_rm_k20_pro.properties} | 0 .../{rm_note_3.properties => gplayapi_rm_note_3.properties} | 0 .../{rm_note_5.properties => gplayapi_rm_note_5.properties} | 0 .../res/raw/{sm_a3.properties => gplayapi_sm_a3.properties} | 0 .../raw/{sm_feel.properties => gplayapi_sm_feel.properties} | 0 .../res/raw/{sm_s7.properties => gplayapi_sm_s7.properties} | 0 .../res/raw/{sm_s8.properties => gplayapi_sm_s8.properties} | 0 ...sm_s9_plus.properties => gplayapi_sm_s9_plus.properties} | 0 .../res/raw/{tw_e.properties => gplayapi_tw_e.properties} | 0 .../{xp_5_dual.properties => gplayapi_xp_5_dual.properties} | 0 lib/src/main/res/raw/keep.xml | 3 +++ 40 files changed, 5 insertions(+), 4 deletions(-) rename lib/src/main/res/raw/{ad_g3_pro.properties => gplayapi_ad_g3_pro.properties} (100%) rename lib/src/main/res/raw/{bravia_atv2.properties => gplayapi_bravia_atv2.properties} (100%) rename lib/src/main/res/raw/{fp_2.properties => gplayapi_fp_2.properties} (100%) rename lib/src/main/res/raw/{hw_h9.properties => gplayapi_hw_h9.properties} (100%) rename lib/src/main/res/raw/{hw_mate20.properties => gplayapi_hw_mate20.properties} (100%) rename lib/src/main/res/raw/{mi_8_se.properties => gplayapi_mi_8_se.properties} (100%) rename lib/src/main/res/raw/{mi_a1.properties => gplayapi_mi_a1.properties} (100%) rename lib/src/main/res/raw/{mi_mix2.properties => gplayapi_mi_mix2.properties} (100%) rename lib/src/main/res/raw/{moto_g5.properties => gplayapi_moto_g5.properties} (100%) rename lib/src/main/res/raw/{nk_8.properties => gplayapi_nk_8.properties} (100%) rename lib/src/main/res/raw/{nk_9.properties => gplayapi_nk_9.properties} (100%) rename lib/src/main/res/raw/{nk_drx.properties => gplayapi_nk_drx.properties} (100%) rename lib/src/main/res/raw/{op_3.properties => gplayapi_op_3.properties} (100%) rename lib/src/main/res/raw/{op_5.properties => gplayapi_op_5.properties} (100%) rename lib/src/main/res/raw/{op_5t.properties => gplayapi_op_5t.properties} (100%) rename lib/src/main/res/raw/{op_6.properties => gplayapi_op_6.properties} (100%) rename lib/src/main/res/raw/{op_7t.properties => gplayapi_op_7t.properties} (100%) rename lib/src/main/res/raw/{op_7t_pro.properties => gplayapi_op_7t_pro.properties} (100%) rename lib/src/main/res/raw/{op_8_pro.properties => gplayapi_op_8_pro.properties} (100%) rename lib/src/main/res/raw/{op_x.properties => gplayapi_op_x.properties} (100%) rename lib/src/main/res/raw/{poco_f1.properties => gplayapi_poco_f1.properties} (100%) rename lib/src/main/res/raw/{px_3a.properties => gplayapi_px_3a.properties} (100%) rename lib/src/main/res/raw/{rm_4.properties => gplayapi_rm_4.properties} (100%) rename lib/src/main/res/raw/{rm_5.properties => gplayapi_rm_5.properties} (100%) rename lib/src/main/res/raw/{rm_5_plus.properties => gplayapi_rm_5_plus.properties} (100%) rename lib/src/main/res/raw/{rm_5_pro.properties => gplayapi_rm_5_pro.properties} (100%) rename lib/src/main/res/raw/{rm_5i.properties => gplayapi_rm_5i.properties} (100%) rename lib/src/main/res/raw/{rm_7.properties => gplayapi_rm_7.properties} (100%) rename lib/src/main/res/raw/{rm_k20_pro.properties => gplayapi_rm_k20_pro.properties} (100%) rename lib/src/main/res/raw/{rm_note_3.properties => gplayapi_rm_note_3.properties} (100%) rename lib/src/main/res/raw/{rm_note_5.properties => gplayapi_rm_note_5.properties} (100%) rename lib/src/main/res/raw/{sm_a3.properties => gplayapi_sm_a3.properties} (100%) rename lib/src/main/res/raw/{sm_feel.properties => gplayapi_sm_feel.properties} (100%) rename lib/src/main/res/raw/{sm_s7.properties => gplayapi_sm_s7.properties} (100%) rename lib/src/main/res/raw/{sm_s8.properties => gplayapi_sm_s8.properties} (100%) rename lib/src/main/res/raw/{sm_s9_plus.properties => gplayapi_sm_s9_plus.properties} (100%) rename lib/src/main/res/raw/{tw_e.properties => gplayapi_tw_e.properties} (100%) rename lib/src/main/res/raw/{xp_5_dual.properties => gplayapi_xp_5_dual.properties} (100%) create mode 100644 lib/src/main/res/raw/keep.xml diff --git a/lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt b/lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt index 0f80852..68532f9 100644 --- a/lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt +++ b/lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt @@ -22,9 +22,7 @@ object DeviceManager { fun loadProperties(deviceName: String?): Properties? { return try { val properties = Properties() - val inputStream = javaClass - .classLoader - .getResourceAsStream(deviceName) + val inputStream = javaClass.classLoader?.getResourceAsStream("gplayapi_${deviceName}") if (inputStream != null) { properties.load(inputStream) } else { @@ -35,4 +33,4 @@ object DeviceManager { null } } -} \ No newline at end of file +} diff --git a/lib/src/main/res/raw/ad_g3_pro.properties b/lib/src/main/res/raw/gplayapi_ad_g3_pro.properties similarity index 100% rename from lib/src/main/res/raw/ad_g3_pro.properties rename to lib/src/main/res/raw/gplayapi_ad_g3_pro.properties diff --git a/lib/src/main/res/raw/bravia_atv2.properties b/lib/src/main/res/raw/gplayapi_bravia_atv2.properties similarity index 100% rename from lib/src/main/res/raw/bravia_atv2.properties rename to lib/src/main/res/raw/gplayapi_bravia_atv2.properties diff --git a/lib/src/main/res/raw/fp_2.properties b/lib/src/main/res/raw/gplayapi_fp_2.properties similarity index 100% rename from lib/src/main/res/raw/fp_2.properties rename to lib/src/main/res/raw/gplayapi_fp_2.properties diff --git a/lib/src/main/res/raw/hw_h9.properties b/lib/src/main/res/raw/gplayapi_hw_h9.properties similarity index 100% rename from lib/src/main/res/raw/hw_h9.properties rename to lib/src/main/res/raw/gplayapi_hw_h9.properties diff --git a/lib/src/main/res/raw/hw_mate20.properties b/lib/src/main/res/raw/gplayapi_hw_mate20.properties similarity index 100% rename from lib/src/main/res/raw/hw_mate20.properties rename to lib/src/main/res/raw/gplayapi_hw_mate20.properties diff --git a/lib/src/main/res/raw/mi_8_se.properties b/lib/src/main/res/raw/gplayapi_mi_8_se.properties similarity index 100% rename from lib/src/main/res/raw/mi_8_se.properties rename to lib/src/main/res/raw/gplayapi_mi_8_se.properties diff --git a/lib/src/main/res/raw/mi_a1.properties b/lib/src/main/res/raw/gplayapi_mi_a1.properties similarity index 100% rename from lib/src/main/res/raw/mi_a1.properties rename to lib/src/main/res/raw/gplayapi_mi_a1.properties diff --git a/lib/src/main/res/raw/mi_mix2.properties b/lib/src/main/res/raw/gplayapi_mi_mix2.properties similarity index 100% rename from lib/src/main/res/raw/mi_mix2.properties rename to lib/src/main/res/raw/gplayapi_mi_mix2.properties diff --git a/lib/src/main/res/raw/moto_g5.properties b/lib/src/main/res/raw/gplayapi_moto_g5.properties similarity index 100% rename from lib/src/main/res/raw/moto_g5.properties rename to lib/src/main/res/raw/gplayapi_moto_g5.properties diff --git a/lib/src/main/res/raw/nk_8.properties b/lib/src/main/res/raw/gplayapi_nk_8.properties similarity index 100% rename from lib/src/main/res/raw/nk_8.properties rename to lib/src/main/res/raw/gplayapi_nk_8.properties diff --git a/lib/src/main/res/raw/nk_9.properties b/lib/src/main/res/raw/gplayapi_nk_9.properties similarity index 100% rename from lib/src/main/res/raw/nk_9.properties rename to lib/src/main/res/raw/gplayapi_nk_9.properties diff --git a/lib/src/main/res/raw/nk_drx.properties b/lib/src/main/res/raw/gplayapi_nk_drx.properties similarity index 100% rename from lib/src/main/res/raw/nk_drx.properties rename to lib/src/main/res/raw/gplayapi_nk_drx.properties diff --git a/lib/src/main/res/raw/op_3.properties b/lib/src/main/res/raw/gplayapi_op_3.properties similarity index 100% rename from lib/src/main/res/raw/op_3.properties rename to lib/src/main/res/raw/gplayapi_op_3.properties diff --git a/lib/src/main/res/raw/op_5.properties b/lib/src/main/res/raw/gplayapi_op_5.properties similarity index 100% rename from lib/src/main/res/raw/op_5.properties rename to lib/src/main/res/raw/gplayapi_op_5.properties diff --git a/lib/src/main/res/raw/op_5t.properties b/lib/src/main/res/raw/gplayapi_op_5t.properties similarity index 100% rename from lib/src/main/res/raw/op_5t.properties rename to lib/src/main/res/raw/gplayapi_op_5t.properties diff --git a/lib/src/main/res/raw/op_6.properties b/lib/src/main/res/raw/gplayapi_op_6.properties similarity index 100% rename from lib/src/main/res/raw/op_6.properties rename to lib/src/main/res/raw/gplayapi_op_6.properties diff --git a/lib/src/main/res/raw/op_7t.properties b/lib/src/main/res/raw/gplayapi_op_7t.properties similarity index 100% rename from lib/src/main/res/raw/op_7t.properties rename to lib/src/main/res/raw/gplayapi_op_7t.properties diff --git a/lib/src/main/res/raw/op_7t_pro.properties b/lib/src/main/res/raw/gplayapi_op_7t_pro.properties similarity index 100% rename from lib/src/main/res/raw/op_7t_pro.properties rename to lib/src/main/res/raw/gplayapi_op_7t_pro.properties diff --git a/lib/src/main/res/raw/op_8_pro.properties b/lib/src/main/res/raw/gplayapi_op_8_pro.properties similarity index 100% rename from lib/src/main/res/raw/op_8_pro.properties rename to lib/src/main/res/raw/gplayapi_op_8_pro.properties diff --git a/lib/src/main/res/raw/op_x.properties b/lib/src/main/res/raw/gplayapi_op_x.properties similarity index 100% rename from lib/src/main/res/raw/op_x.properties rename to lib/src/main/res/raw/gplayapi_op_x.properties diff --git a/lib/src/main/res/raw/poco_f1.properties b/lib/src/main/res/raw/gplayapi_poco_f1.properties similarity index 100% rename from lib/src/main/res/raw/poco_f1.properties rename to lib/src/main/res/raw/gplayapi_poco_f1.properties diff --git a/lib/src/main/res/raw/px_3a.properties b/lib/src/main/res/raw/gplayapi_px_3a.properties similarity index 100% rename from lib/src/main/res/raw/px_3a.properties rename to lib/src/main/res/raw/gplayapi_px_3a.properties diff --git a/lib/src/main/res/raw/rm_4.properties b/lib/src/main/res/raw/gplayapi_rm_4.properties similarity index 100% rename from lib/src/main/res/raw/rm_4.properties rename to lib/src/main/res/raw/gplayapi_rm_4.properties diff --git a/lib/src/main/res/raw/rm_5.properties b/lib/src/main/res/raw/gplayapi_rm_5.properties similarity index 100% rename from lib/src/main/res/raw/rm_5.properties rename to lib/src/main/res/raw/gplayapi_rm_5.properties diff --git a/lib/src/main/res/raw/rm_5_plus.properties b/lib/src/main/res/raw/gplayapi_rm_5_plus.properties similarity index 100% rename from lib/src/main/res/raw/rm_5_plus.properties rename to lib/src/main/res/raw/gplayapi_rm_5_plus.properties diff --git a/lib/src/main/res/raw/rm_5_pro.properties b/lib/src/main/res/raw/gplayapi_rm_5_pro.properties similarity index 100% rename from lib/src/main/res/raw/rm_5_pro.properties rename to lib/src/main/res/raw/gplayapi_rm_5_pro.properties diff --git a/lib/src/main/res/raw/rm_5i.properties b/lib/src/main/res/raw/gplayapi_rm_5i.properties similarity index 100% rename from lib/src/main/res/raw/rm_5i.properties rename to lib/src/main/res/raw/gplayapi_rm_5i.properties diff --git a/lib/src/main/res/raw/rm_7.properties b/lib/src/main/res/raw/gplayapi_rm_7.properties similarity index 100% rename from lib/src/main/res/raw/rm_7.properties rename to lib/src/main/res/raw/gplayapi_rm_7.properties diff --git a/lib/src/main/res/raw/rm_k20_pro.properties b/lib/src/main/res/raw/gplayapi_rm_k20_pro.properties similarity index 100% rename from lib/src/main/res/raw/rm_k20_pro.properties rename to lib/src/main/res/raw/gplayapi_rm_k20_pro.properties diff --git a/lib/src/main/res/raw/rm_note_3.properties b/lib/src/main/res/raw/gplayapi_rm_note_3.properties similarity index 100% rename from lib/src/main/res/raw/rm_note_3.properties rename to lib/src/main/res/raw/gplayapi_rm_note_3.properties diff --git a/lib/src/main/res/raw/rm_note_5.properties b/lib/src/main/res/raw/gplayapi_rm_note_5.properties similarity index 100% rename from lib/src/main/res/raw/rm_note_5.properties rename to lib/src/main/res/raw/gplayapi_rm_note_5.properties diff --git a/lib/src/main/res/raw/sm_a3.properties b/lib/src/main/res/raw/gplayapi_sm_a3.properties similarity index 100% rename from lib/src/main/res/raw/sm_a3.properties rename to lib/src/main/res/raw/gplayapi_sm_a3.properties diff --git a/lib/src/main/res/raw/sm_feel.properties b/lib/src/main/res/raw/gplayapi_sm_feel.properties similarity index 100% rename from lib/src/main/res/raw/sm_feel.properties rename to lib/src/main/res/raw/gplayapi_sm_feel.properties diff --git a/lib/src/main/res/raw/sm_s7.properties b/lib/src/main/res/raw/gplayapi_sm_s7.properties similarity index 100% rename from lib/src/main/res/raw/sm_s7.properties rename to lib/src/main/res/raw/gplayapi_sm_s7.properties diff --git a/lib/src/main/res/raw/sm_s8.properties b/lib/src/main/res/raw/gplayapi_sm_s8.properties similarity index 100% rename from lib/src/main/res/raw/sm_s8.properties rename to lib/src/main/res/raw/gplayapi_sm_s8.properties diff --git a/lib/src/main/res/raw/sm_s9_plus.properties b/lib/src/main/res/raw/gplayapi_sm_s9_plus.properties similarity index 100% rename from lib/src/main/res/raw/sm_s9_plus.properties rename to lib/src/main/res/raw/gplayapi_sm_s9_plus.properties diff --git a/lib/src/main/res/raw/tw_e.properties b/lib/src/main/res/raw/gplayapi_tw_e.properties similarity index 100% rename from lib/src/main/res/raw/tw_e.properties rename to lib/src/main/res/raw/gplayapi_tw_e.properties diff --git a/lib/src/main/res/raw/xp_5_dual.properties b/lib/src/main/res/raw/gplayapi_xp_5_dual.properties similarity index 100% rename from lib/src/main/res/raw/xp_5_dual.properties rename to lib/src/main/res/raw/gplayapi_xp_5_dual.properties diff --git a/lib/src/main/res/raw/keep.xml b/lib/src/main/res/raw/keep.xml new file mode 100644 index 0000000..f0030e8 --- /dev/null +++ b/lib/src/main/res/raw/keep.xml @@ -0,0 +1,3 @@ + + -- GitLab From 68519826c799b591ad0834fdcfed591ba43c1569 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sun, 23 Apr 2023 16:23:27 +0530 Subject: [PATCH 07/82] Expose response codes with a stateflow from IHttpClient This is useful when the app wants to initiate some action based on particular status such as showing a warning when user is rate-limited. Signed-off-by: Aayush Gupta --- lib/build.gradle | 1 + .../com/aurora/gplayapi/network/DefaultHttpClient.kt | 10 +++++++++- .../java/com/aurora/gplayapi/network/IHttpClient.kt | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/build.gradle b/lib/build.gradle index 97ff392..df0ff2a 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -42,6 +42,7 @@ dependencies { implementation 'com.google.protobuf:protobuf-javalite:3.22.3' implementation 'com.github.kittinunf.fuel:fuel:2.3.0' implementation 'com.google.code.gson:gson:2.10' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' } protobuf { diff --git a/lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt b/lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt index a0242e3..432a2f6 100644 --- a/lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt +++ b/lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt @@ -19,9 +19,16 @@ import com.aurora.gplayapi.data.models.PlayResponse import com.github.kittinunf.fuel.Fuel import com.github.kittinunf.fuel.core.* import java.nio.charset.Charset +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow object DefaultHttpClient : IHttpClient { + private val _responseCode = MutableStateFlow(100) + override val responseCode: StateFlow + get() = _responseCode.asStateFlow() + override fun get(url: String, headers: Map): PlayResponse { return get(url, headers, hashMapOf()) } @@ -102,6 +109,7 @@ object DefaultHttpClient : IHttpClient { } isSuccessful = response.isSuccessful code = response.statusCode + _responseCode.value = response.statusCode } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt b/lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt index 2e9745c..da3a5f3 100644 --- a/lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt +++ b/lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt @@ -17,8 +17,11 @@ package com.aurora.gplayapi.network import com.aurora.gplayapi.data.models.PlayResponse import java.io.IOException +import kotlinx.coroutines.flow.StateFlow interface IHttpClient { + val responseCode: StateFlow + @Throws(IOException::class) fun post(url: String, headers: Map, body: ByteArray): PlayResponse -- GitLab From 2aa7ae6470a7938e975e8386ae76e90f793d3a73 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sun, 23 Apr 2023 17:13:23 +0530 Subject: [PATCH 08/82] 3.1.0 Signed-off-by: Aayush Gupta --- lib/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/build.gradle b/lib/build.gradle index df0ff2a..14dddae 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -66,7 +66,7 @@ publishing { release(MavenPublication) { groupId = 'com.aurora' artifactId = 'gplayapi' - version = '3.0.1' + version = '3.1.0' afterEvaluate { from components.release -- GitLab From 910442bf512ab1eded67a395c49a199a02c69b5f Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 19 May 2023 23:22:20 +0530 Subject: [PATCH 09/82] res: raw: Add Google Pixel 7a spoofing configuration Signed-off-by: Aayush Gupta --- .../main/res/raw/gplayapi_px_7a.properties | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 lib/src/main/res/raw/gplayapi_px_7a.properties diff --git a/lib/src/main/res/raw/gplayapi_px_7a.properties b/lib/src/main/res/raw/gplayapi_px_7a.properties new file mode 100644 index 0000000..cd31be5 --- /dev/null +++ b/lib/src/main/res/raw/gplayapi_px_7a.properties @@ -0,0 +1,50 @@ +# +# GPlayApi +# Copyright (C) 2023, The Calyx Institute +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +Build.BOOTLOADER=lynx-1.0-9716681 +Build.BRAND=google +Build.DEVICE=lynx +Build.FINGERPRINT=google/lynx/lynx\:13/TQ2B.230505.005.A1/9808202\:user/release-keys +Build.HARDWARE=lynx +Build.ID=TQ2A.230505.002 +Build.MANUFACTURER=Google +Build.MODEL=Pixel 7a +Build.PRODUCT=lynx +Build.RADIO=g5300n-230203-230323-B-9801058,g5300n-230203-230323-B-9801058 +Build.VERSION.RELEASE=13 +Build.VERSION.SDK_INT=33 +CellOperator=310 +Client=android-google +Features=android.hardware.sensor.proximity,android.hardware.telephony.ims.singlereg,android.hardware.sensor.accelerometer,android.software.controls,android.hardware.faketouch,android.software.telecom,android.hardware.telephony.subscription,android.hardware.telephony.euicc,android.hardware.usb.accessory,android.hardware.telephony.data,android.hardware.sensor.dynamic.head_tracker,android.software.backup,android.hardware.touchscreen,android.hardware.touchscreen.multitouch,android.software.erofs,android.software.print,android.software.activities_on_secondary_displays,android.hardware.wifi.rtt,com.google.android.feature.PIXEL_2017_EXPERIENCE,android.software.voice_recognizers,android.software.picture_in_picture,android.hardware.fingerprint,android.hardware.sensor.gyroscope,android.hardware.audio.low_latency,android.software.vulkan.deqp.level,android.software.cant_save_state,com.google.android.feature.PIXEL_2018_EXPERIENCE,android.hardware.security.model.compatible,android.hardware.telephony.messaging,com.google.android.feature.PIXEL_2019_EXPERIENCE,android.hardware.telephony.calling,android.hardware.opengles.aep,org.lineageos.livedisplay,android.hardware.bluetooth,android.software.window_magnification,android.hardware.telephony.radio.access,android.hardware.camera.autofocus,android.hardware.telephony.gsm,android.hardware.telephony.ims,android.software.incremental_delivery,android.hardware.se.omapi.ese,android.software.opengles.deqp.level,vendor.android.hardware.camera.preview-dis.front,com.google.android.feature.PIXEL_2022_MIDYEAR_EXPERIENCE,android.hardware.camera.concurrent,android.hardware.usb.host,android.hardware.audio.output,android.software.verified_boot,android.hardware.camera.flash,android.hardware.camera.front,android.hardware.sensor.hifi_sensors,android.hardware.se.omapi.uicc,android.hardware.strongbox_keystore,android.hardware.screen.portrait,android.hardware.nfc,com.nxp.mifare,com.google.android.feature.PIXEL_2021_MIDYEAR_EXPERIENCE,android.hardware.sensor.stepdetector,android.software.home_screen,android.hardware.context_hub,vendor.android.hardware.camera.preview-dis.back,android.hardware.microphone,android.software.autofill,org.lineageos.hardware,org.lineageos.globalactions,android.software.securely_removes_users,com.google.android.feature.PIXEL_EXPERIENCE,android.hardware.bluetooth_le,android.hardware.sensor.compass,android.hardware.touchscreen.multitouch.jazzhand,android.hardware.sensor.barometer,android.software.app_widgets,com.google.android.feature.PIXEL_2020_MIDYEAR_EXPERIENCE,android.hardware.telephony.carrierlock,android.software.input_methods,android.hardware.sensor.light,android.hardware.vulkan.version,android.software.companion_device_setup,android.software.device_admin,android.hardware.wifi.passpoint,android.hardware.camera,org.lineageos.trust,android.hardware.device_unique_attestation,android.hardware.screen.landscape,android.software.device_id_attestation,android.hardware.ram.normal,com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE,android.software.managed_users,android.software.webview,android.hardware.sensor.stepcounter,android.hardware.camera.capability.manual_post_processing,android.hardware.camera.any,android.hardware.camera.capability.raw,android.hardware.vulkan.compute,android.hardware.touchscreen.multitouch.distinct,android.hardware.location.network,android.software.cts,android.hardware.camera.capability.manual_sensor,android.software.app_enumeration,android.hardware.camera.level.full,android.hardware.identity_credential,android.hardware.wifi.direct,android.software.live_wallpaper,com.google.android.feature.GOOGLE_EXPERIENCE,android.software.ipsec_tunnels,org.lineageos.settings,android.hardware.audio.pro,android.hardware.nfc.hcef,android.hardware.location.gps,android.software.midi,android.hardware.nfc.any,android.hardware.nfc.ese,android.hardware.nfc.hce,android.hardware.hardware_keystore,com.google.android.feature.PIXEL_2020_EXPERIENCE,android.hardware.telephony.euicc.mep,android.hardware.wifi,android.hardware.location,android.hardware.vulkan.level,com.google.android.feature.PIXEL_2021_EXPERIENCE,android.hardware.keystore.app_attest_key,android.hardware.wifi.aware,com.google.android.feature.PIXEL_2022_EXPERIENCE,android.software.secure_lock_screen,android.hardware.telephony,android.software.file_based_encryption +GL.Extensions=,GL_ANDROID_extension_pack_es31a,GL_ARM_mali_program_binary,GL_ARM_mali_shader_binary,GL_ARM_rgba8,GL_ARM_shader_framebuffer_fetch,GL_ARM_shader_framebuffer_fetch_depth_stencil,GL_ARM_texture_unnormalized_coordinates,GL_EXT_EGL_image_array,GL_EXT_YUV_target,GL_EXT_blend_minmax,GL_EXT_buffer_storage,GL_EXT_clip_control,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_copy_image,GL_EXT_debug_marker,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers_indexed,GL_EXT_draw_elements_base_vertex,GL_EXT_external_buffer,GL_EXT_float_blend,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_occlusion_query_boolean,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_read_format_bgra,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_shader_pixel_local_storage,GL_EXT_shadow_samplers,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_compression_astc_decode_mode,GL_EXT_texture_compression_astc_decode_mode_rgb9e5,GL_EXT_texture_cube_map_array,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_rg,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_RG8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_storage,GL_EXT_texture_type_2_10_10_10_REV,GL_EXT_unpack_subimage,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_debug,GL_KHR_robust_buffer_access_behavior,GL_KHR_robustness,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_KHR_texture_compression_astc_sliced_3d,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_EGL_sync,GL_OES_blend_equation_separate,GL_OES_blend_func_separate,GL_OES_blend_subtract,GL_OES_byte_coordinates,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_copy_image,GL_OES_depth24,GL_OES_depth_texture,GL_OES_depth_texture_cube_map,GL_OES_draw_buffers_indexed,GL_OES_draw_elements_base_vertex,GL_OES_draw_texture,GL_OES_element_index_uint,GL_OES_extended_matrix_palette,GL_OES_fbo_render_mipmap,GL_OES_fixed_point,GL_OES_framebuffer_object,GL_OES_geometry_shader,GL_OES_get_program_binary,GL_OES_gpu_shader5,GL_OES_mapbuffer,GL_OES_matrix_get,GL_OES_matrix_palette,GL_OES_packed_depth_stencil,GL_OES_point_size_array,GL_OES_point_sprite,GL_OES_primitive_bounding_box,GL_OES_query_matrix,GL_OES_read_format,GL_OES_required_internalformat,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_io_blocks,GL_OES_shader_multisample_interpolation,GL_OES_single_precision,GL_OES_standard_derivatives,GL_OES_stencil8,GL_OES_stencil_wrap,GL_OES_surfaceless_context,GL_OES_tessellation_shader,GL_OES_texture_3D,GL_OES_texture_border_clamp,GL_OES_texture_buffer,GL_OES_texture_compression_astc,GL_OES_texture_cube_map,GL_OES_texture_cube_map_array,GL_OES_texture_float_linear,GL_OES_texture_mirrored_repeat,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OVR_multiview,GL_OVR_multiview2,GL_OVR_multiview_multisampled_render_to_texture +GL.Version=196610 +GSF.version=203615037 +HasFiveWayNavigation=false +HasHardKeyboard=false +Keyboard=1 +Locales=af,af_ZA,am,am_ET,ar,ar_EG,ar_XB,as,ast,ast_ES,az,be,bg,bg_BG,bn,bs,ca,ca_ES,ckb,cs,cs_CZ,cy,da,da_DK,de,de_DE,el,el_GR,en,en_AU,en_CA,en_GB,en_IN,en_US,en_XA,en_XC,eo,es,es_419,es_ES,es_US,et,eu,fa,fa_IR,fi,fi_FI,fil,fil_PH,fr,fr_CA,fr_FR,gd,gl,gu,he,hi,hi_IN,hr,hr_HR,ht,hu,hu_HU,hy,ia,id,in,in_ID,is,it,it_IT,iw,iw_IL,ja,ja_JP,ka,kab,kk,km,kmr,kn,ko,ko_KR,ky,lo,lt,lt_LT,lv,lv_LV,mk,ml,mn,mr,ms,ms_MY,my,nb,nb_NO,ne,nl,nl_NL,or,pa,pl,pl_PL,pt,pt_BR,pt_PT,ro,ro_RO,ru,ru_RU,sc,si,sk,sk_SK,sl,sl_SI,so,sq,sr,sr_Latn,sr_RS,sv,sv_SE,sw,sw_TZ,ta,te,th,th_TH,tr,tr_TR,uk,uk_UA,ur,uz,vi,vi_VN,zh_CN,zh_HK,zh_TW,zu,zu_ZA +Navigation=1 +Platforms=arm64-v8a +Roaming=mobile-notroaming +Screen.Density=420 +Screen.Height=2156 +Screen.Width=1080 +ScreenLayout=2 +SharedLibraries=android.test.base,android.test.mock,android.hidl.manager-V1.0-java,google-ril,libedgetpu_client.google.so,libedgetpu_util.so,android.hidl.base-V1.0-java,com.google.android.camera.experimental2022,libOpenCL-pixel.so,com.android.location.provider,oemrilhook,android.net.ipsec.ike,com.android.future.usb.accessory,android.ext.shared,javax.obex,com.google.android.gms,lib_aion_buffer.so,libgxp.so,gxp_metrics_logger.so,android.test.runner,org.apache.http.legacy,com.android.cts.ctsshim.shared_library,com.android.nfc_extras,com.android.media.remotedisplay,com.android.mediadrm.signer,android.system.virtualmachine +SimOperator=38 +TimeZone=UTC-10 +TouchScreen=3 +UserReadableName=Google Pixel 7a +Vending.version=82201710 +Vending.versionString=22.0.17-21 [0] [PR] 332555730 -- GitLab From be5530000ddef767c90da3f468be924484c7b05c Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 19 May 2023 23:41:37 +0530 Subject: [PATCH 10/82] res: raw: Add Xiaomi 11 Lite 5G NE spoofing configuration Signed-off-by: Aayush Gupta --- .../main/res/raw/gplayapi_xm_11a.properties | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 lib/src/main/res/raw/gplayapi_xm_11a.properties diff --git a/lib/src/main/res/raw/gplayapi_xm_11a.properties b/lib/src/main/res/raw/gplayapi_xm_11a.properties new file mode 100644 index 0000000..c85ca2a --- /dev/null +++ b/lib/src/main/res/raw/gplayapi_xm_11a.properties @@ -0,0 +1,50 @@ +# +# GPlayApi +# Copyright (C) 2023, The Calyx Institute +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +Build.BOOTLOADER=unknown +Build.BRAND=Xiaomi +Build.DEVICE=lisa +Build.FINGERPRINT=Xiaomi/lisa_eea/lisa\:13/TKQ1.220829.002/V14.0.6.0.TKOEUXM\:user/release-keys +Build.HARDWARE=qcom +Build.ID=TKQ1.220829.002 +Build.MANUFACTURER=Xiaomi +Build.MODEL=2109119DG +Build.PRODUCT=lisa_eea +Build.RADIO=4.3CPL2-gl-26.1-15406.340227_2053_1f271b2afea,4.3CPL2-gl-26.1-15406.340227_2053_1f271b2afea +Build.VERSION.RELEASE=13 +Build.VERSION.SDK_INT=33 +CellOperator=310 +Client=android-google +Features=android.hardware.sensor.proximity,com.google.android.feature.ASI_MINIMAL,com.quicinc.voice.assist.uvr,android.software.adoptable_storage,android.hardware.sensor.accelerometer,android.software.controls,android.hardware.faketouch,com.google.android.feature.D2D_CABLE_MIGRATION_FEATURE,android.hardware.usb.accessory,android.hardware.telephony.cdma,android.software.backup,android.hardware.touchscreen,android.hardware.touchscreen.multitouch,android.software.print,android.hardware.consumerir,android.software.activities_on_secondary_displays,android.software.voice_recognizers,com.google.lens.feature.CAMERA_INTEGRATION,android.software.picture_in_picture,android.hardware.fingerprint,android.hardware.sensor.gyroscope,android.hardware.audio.low_latency,com.google.android.feature.PERSONAL_SAFETY,android.software.vulkan.deqp.level,android.software.cant_save_state,android.hardware.security.model.compatible,android.hardware.opengles.aep,android.hardware.bluetooth,android.hardware.camera.autofocus,android.hardware.telephony.gsm,android.hardware.telephony.ims,android.software.incremental_delivery,android.software.sip.voip,android.hardware.se.omapi.ese,android.hardware.usb.host,android.hardware.audio.output,android.software.verified_boot,android.hardware.camera.flash,android.hardware.camera.front,android.hardware.se.omapi.uicc,android.hardware.screen.portrait,android.hardware.nfc,com.google.android.feature.TURBO_PRELOAD,com.nxp.mifare,android.hardware.sensor.stepdetector,android.software.home_screen,android.hardware.microphone,android.software.autofill,android.software.securely_removes_users,android.hardware.bluetooth_le,android.hardware.sensor.compass,android.hardware.touchscreen.multitouch.jazzhand,android.software.app_widgets,android.software.input_methods,android.hardware.sensor.light,android.hardware.vulkan.version,android.software.companion_device_setup,com.google.android.feature.EEA_V2_DEVICE,android.software.device_admin,com.google.android.feature.WELLBEING,android.hardware.wifi.passpoint,android.hardware.camera,android.hardware.screen.landscape,com.google.android.feature.AER_OPTIMIZED,android.hardware.ram.normal,android.software.managed_users,android.software.webview,android.hardware.sensor.stepcounter,android.hardware.camera.capability.manual_post_processing,com.google.lens.feature.IMAGE_INTEGRATION,android.hardware.camera.any,android.hardware.camera.capability.raw,android.hardware.vulkan.compute,com.google.android.apps.dialer.call_recording_audio,android.software.connectionservice,android.hardware.touchscreen.multitouch.distinct,android.hardware.location.network,android.software.cts,android.software.sip,android.hardware.camera.capability.manual_sensor,android.software.app_enumeration,com.google.android.apps.dialer.SUPPORTED,android.hardware.camera.level.full,com.google.android.feature.EEA_DEVICE,android.hardware.wifi.direct,android.software.live_wallpaper,android.software.ipsec_tunnels,com.google.android.paid.chrome,com.quicinc.voice.assist,android.hardware.nfc.hcef,android.hardware.nfc.uicc,android.hardware.location.gps,android.software.midi,android.hardware.nfc.any,android.hardware.nfc.ese,android.hardware.nfc.hce,android.hardware.wifi,android.hardware.location,com.google.android.paid.search,android.hardware.vulkan.level,com.google.android.feature.PREMIER_TIER,android.software.secure_lock_screen,android.hardware.telephony,android.software.file_based_encryption +GL.Extensions=,GL_AMD_compressed_ATC_texture,GL_AMD_performance_monitor,GL_ANDROID_extension_pack_es31a,GL_APPLE_texture_2D_limited_npot,GL_ARB_vertex_buffer_object,GL_ARM_shader_framebuffer_fetch_depth_stencil,GL_EXT_EGL_image_array,GL_EXT_EGL_image_external_wrap_modes,GL_EXT_EGL_image_storage,GL_EXT_YUV_target,GL_EXT_blend_func_extended,GL_EXT_blit_framebuffer_params,GL_EXT_buffer_storage,GL_EXT_clip_control,GL_EXT_clip_cull_distance,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_copy_image,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers_indexed,GL_EXT_external_buffer,GL_EXT_fragment_invocation_density,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_read_format_bgra,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_cube_map_array,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_format_sRGB_override,GL_EXT_texture_norm16,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_type_2_10_10_10_REV,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_debug,GL_KHR_no_error,GL_KHR_robust_buffer_access_behavior,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_NV_shader_noperspective_interpolation,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_EGL_sync,GL_OES_blend_equation_separate,GL_OES_blend_func_separate,GL_OES_blend_subtract,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_depth24,GL_OES_depth_texture,GL_OES_depth_texture_cube_map,GL_OES_draw_texture,GL_OES_element_index_uint,GL_OES_framebuffer_object,GL_OES_get_program_binary,GL_OES_matrix_palette,GL_OES_packed_depth_stencil,GL_OES_point_size_array,GL_OES_point_sprite,GL_OES_read_format,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_multisample_interpolation,GL_OES_standard_derivatives,GL_OES_stencil_wrap,GL_OES_surfaceless_context,GL_OES_texture_3D,GL_OES_texture_compression_astc,GL_OES_texture_cube_map,GL_OES_texture_env_crossbar,GL_OES_texture_float,GL_OES_texture_float_linear,GL_OES_texture_half_float,GL_OES_texture_half_float_linear,GL_OES_texture_mirrored_repeat,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_texture_view,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OVR_multiview,GL_OVR_multiview2,GL_OVR_multiview_multisampled_render_to_texture,GL_QCOM_YUV_texture_gather,GL_QCOM_alpha_test,GL_QCOM_extended_get,GL_QCOM_motion_estimation,GL_QCOM_shader_framebuffer_fetch_noncoherent,GL_QCOM_shader_framebuffer_fetch_rate,GL_QCOM_shading_rate,GL_QCOM_texture_foveated,GL_QCOM_texture_foveated_subsampled_layout,GL_QCOM_tiled_rendering,GL_QCOM_validate_shader_binary +GL.Version=196610 +GSF.version=203615037 +HasFiveWayNavigation=false +HasHardKeyboard=false +Keyboard=1 +Locales=af,am,ar,ar_EG,ar_XB,as,as_IN,ast,az,az_AZ,be,be_BY,bg,bg_BG,bn,bn_BD,bn_IN,bs,bs_BA,ca,ca_ES,ckb,cs,cs_CZ,da,da_DK,de,de_DE,el,el_GR,en,en_AU,en_CA,en_GB,en_IN,en_US,en_XA,en_XC,eo,es,es_419,es_ES,es_US,et,et_EE,eu,eu_ES,fa,fa_IR,fi,fi_FI,fil,fr,fr_CA,fr_FR,gl,gl_ES,gu,gu_IN,ha_NG,he,hi,hi_IN,hr,hr_HR,ht,hu,hu_HU,hy,hy_AM,ia,id,in,in_ID,is,it,it_IT,iw,iw_IL,ja,ja_JP,ka,ka_GE,kab,kk,kk_KZ,km,km_KH,kmr,kn,kn_IN,ko,ko_KR,ky,lo,lo_LA,lt,lt_LT,lv,lv_LV,mk,mk_MK,ml,ml_IN,mn,mr,mr_IN,ms,ms_MY,mt_MT,my,my_MM,nb,nb_NO,ne,ne_IN,ne_NP,nl,nl_NL,or,or_IN,pa,pa_IN,pl,pl_PL,pt,pt_BR,pt_PT,ro,ro_RO,ru,ru_RU,sc,si,sk,sk_SK,sl,sl_SI,so,sq,sq_AL,sr,sr_Latn,sr_RS,sv,sv_SE,sw,ta,ta_IN,te,te_IN,th,th_TH,tr,tr_TR,uk,uk_UA,ur,ur_IN,ur_PK,uz,uz_UZ,vi,vi_VN,zh,zh_CN,zh_HK,zh_TW,zu +Navigation=1 +Platforms=arm64-v8a,armeabi-v7a,armeabi +Roaming=mobile-notroaming +Screen.Density=440 +Screen.Height=2296 +Screen.Width=1080 +ScreenLayout=2 +SharedLibraries=libhoaeffects.qti.so,android.test.base,android.test.mock,libqti-perfd-client.so,android.hidl.manager-V1.0-java,libupdateprof.qti.so,qti-telephony-hidl-wrapper,libfastcvopt.so,vendor.qti.ims.connection-V1.0-java,liblistenjni.qti.so,android.hidl.manager.V1_0.IServiceNotification,com.android.hotwordenrollment.common.util,android.hidl.manager.V1_0.IServiceManager,libOpenCL.so,libthermalclient.qti.so,vendor.xiaomi.hardware.misys-V1.0-java,vendor.qti.ims.rcsuce-V1.0-java,com.qualcomm.qti.uimGba.uimgbalibrary,vendor.qti.ims.rcsuce-V1.1-java,vendor.qti.ims.rcsuce-V1.2-java,dpmapi,qti-telephony-utils,com.qti.location.sdk,libbinauralrenderer_wrapper.qti.so,services.core,camerax-vendor-extensions.jar,libdiag_system.qti.so,com.qualcomm.qti.uimGbaManager.uimgbamanagerlibrary,com.qti.media.secureprocessor,qti-telephony-utils-prd,global-cleaner-empty.jar,ims-ext-common,libcdsprpc.so,android.hidl.base-V1.0-java,com.qualcomm.qmapbridge,libmisys_jni.xiaomi.so,com.qualcomm.qti.remoteSimlock.manager.remotesimlockmanagerlibrary,com.qualcomm.qti.audiosphere,libadsprpc.so,com.android.location.provider,vendor.xiaomi.hardware.misys-V4.0-java,com.miui.system,android.hidl.base.V1_0.IBase,com.wapi.wapicertstore,vendor.xiaomi.hardware.misys.V3_0,android.hardware.wifi.supplicant.V1_3.ISupplicant,android.net.ipsec.ike,security-device-credential-sdk.jar,com.nxp.nfc.nq,com.android.future.usb.accessory,version-seperation-dev,android.hardware.wifi.supplicant.V1_2.ISupplicant,com.qti.dpmframework,libsdsprpc.so,android.ext.shared,vendor.xiaomi.hardware.misys-V2.0-java,javax.obex,izat.xt.srv,android.hardware.wifi.supplicant.V1_1.ISupplicant,com.google.android.gms,MiuiSettingsSearchLib.jar,libsnpe_dsp_domains_v2.so,libsnpe_dsp_domains_v3.so,com.qualcomm.qti.uim.uimservicelibrary,libhta.so,com.fingerprints.extension,com.qualcomm.uimremoteclientlibrary,android.hardware.wifi.supplicant.V1_0.ISupplicant,liblistensoundmodel2.so,com.xiaomi.nfc,vendor.qti.ims.factory-V2.0-java,vendor.qti.ims.factory-V2.1-java,com.xiaomi.slalib,vendor.qti.ims.factory-V2.2-java,com.xiaomi.NetworkBoost,com.qti.extphone.extphonelib,vendor.xiaomi.hardware.bgservice-V1.0-java,com.qualcomm.qti.remoteSimlock.uimremotesimlocklibrary,com.qualcomm.uimremoteserverlibrary,libQOC.qti.so,com.qualcomm.qcrilhook,android.test.runner,gson.jar,libSNPE.so,com.google.android.dialer.support,org.apache.http.legacy,vendor.qti.ims.rcssip-V1.0-java,vendor.qti.ims.rcssip-V1.1-java,com.android.cts.ctsshim.shared_library,com.android.nfc_extras,com.android.media.remotedisplay,com.qti.extphone.extphonelib-product,vendor.qti.ims.rcssip-V1.2-java,com.android.mediadrm.signer,com.qualcomm.qti.imscmservice-V2.0-java,qti-telephony-hidl-wrapper-prd,com.qti.snapdragon.sdk.display,com.qualcomm.qti.imscmservice-V2.1-java,com.qualcomm.qti.imscmservice-V2.2-java,libqape.qti.so,com.miui.core,micloud-sdk,com.qualcomm.embmslibrary +SimOperator=38 +TimeZone=UTC-10 +TouchScreen=3 +UserReadableName=Xiaomi 11 Lite 5G NE +Vending.version=82201710 +Vending.versionString=22.0.17-21 [0] [PR] 332555730 -- GitLab From 0b120c7d07de5b1cff7eacee39a595a071988214 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 19 May 2023 23:55:01 +0530 Subject: [PATCH 11/82] Bump to latest stable AGP and kotlin version Signed-off-by: Aayush Gupta --- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index eafd101..84651ef 100644 --- a/build.gradle +++ b/build.gradle @@ -14,8 +14,8 @@ */ plugins { - id 'com.android.library' version '7.4.2' apply false - id 'org.jetbrains.kotlin.android' version '1.8.20' apply false + id 'com.android.library' version '8.0.1' apply false + id 'org.jetbrains.kotlin.android' version '1.8.21' apply false id 'com.google.protobuf' version '0.9.1' apply false } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 162b1da..3d32b9a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Apr 21 18:26:18 IST 2023 +#Fri May 19 23:45:54 IST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip -- GitLab From c25abd64b4d62726751be81d9a4e3524c0866cb1 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 20 May 2023 00:00:17 +0530 Subject: [PATCH 12/82] Copy proguard rule from Aurora Store Makes proguard totally useless but its fine than nothing Signed-off-by: Aayush Gupta --- lib/proguard-rules.pro | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/proguard-rules.pro b/lib/proguard-rules.pro index f1b4245..6159288 100644 --- a/lib/proguard-rules.pro +++ b/lib/proguard-rules.pro @@ -19,3 +19,8 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile + +# TODO: Write actual rules +-keep public class com.aurora.gplayapi.** { + *; +} -- GitLab From be7857db6e132de7fb4b4a5aacd0dfa338c74881 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 20 May 2023 00:01:48 +0530 Subject: [PATCH 13/82] Update fuel and gson dependencies Signed-off-by: Aayush Gupta --- lib/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/build.gradle b/lib/build.gradle index 14dddae..afd687f 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -40,8 +40,8 @@ android { dependencies { implementation 'com.google.protobuf:protobuf-javalite:3.22.3' - implementation 'com.github.kittinunf.fuel:fuel:2.3.0' - implementation 'com.google.code.gson:gson:2.10' + implementation 'com.github.kittinunf.fuel:fuel:2.3.1' + implementation 'com.google.code.gson:gson:2.10.1' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' } -- GitLab From 660342aa4c060742a0edc0f4b12dff60de2dd6ce Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sat, 20 May 2023 00:03:52 +0530 Subject: [PATCH 14/82] gitlab-ci: Switch to updated docker image Signed-off-by: Aayush Gupta --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2aa67d7..393ebc3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: jangrewe/gitlab-ci-android +image: theimpulson/gitlab-ci-android before_script: - export GRADLE_USER_HOME=$(pwd)/.gradle -- GitLab From 7cd3bc1fde98a7bb82e5dc115badad5e575387c8 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 26 May 2023 12:43:01 +0530 Subject: [PATCH 15/82] res: raw: Add Bravia VU2 spoofing configuration Signed-off-by: Aayush Gupta --- .../res/raw/gplayapi_bravia_vu2.properties | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 lib/src/main/res/raw/gplayapi_bravia_vu2.properties diff --git a/lib/src/main/res/raw/gplayapi_bravia_vu2.properties b/lib/src/main/res/raw/gplayapi_bravia_vu2.properties new file mode 100644 index 0000000..3e4fa20 --- /dev/null +++ b/lib/src/main/res/raw/gplayapi_bravia_vu2.properties @@ -0,0 +1,50 @@ +# +# GPlayApi +# Copyright (C) 2023, The Calyx Institute +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +Build.BOOTLOADER=unknown +Build.BRAND=Sony +Build.DEVICE=BRAVIA_VU1_2K +Build.FINGERPRINT=Sony/BRAVIA_VU2/BRAVIA_VU1_2K\:11/RTT7.210923.001/146-60522\:user/release-keys +Build.HARDWARE=rtd2885m +Build.ID=RTT7.210923.001 +Build.MANUFACTURER=Sony +Build.MODEL=BRAVIA VU2 +Build.PRODUCT=BRAVIA_VU2 +Build.RADIO=unknown +Build.VERSION.RELEASE=11 +Build.VERSION.SDK_INT=30 +CellOperator=310 +Client=android-google +Features=android.software.leanback_only,android.software.adoptable_storage,android.hardware.hdmi.cec,android.software.backup,com.amazon.amazonvideo.livingroom.feature.AV_TARGET,android.hardware.ethernet,android.software.activities_on_secondary_displays,android.software.voice_recognizers,android.hardware.audio.low_latency,android.software.vulkan.deqp.level,android.software.cant_save_state,com.sony.dtv.software.braviachat,android.hardware.opengles.aep,android.hardware.type.television,android.hardware.bluetooth,android.software.incremental_delivery,android.hardware.usb.host,android.hardware.audio.output,android.software.verified_boot,android.hardware.gamepad,android.software.live_tv,nrdp.modelgroup,android.software.autofill,android.software.securely_removes_users,android.software.leanback,android.hardware.bluetooth_le,android.software.app_widgets,com.google.android.tv.installed,android.software.input_methods,com.sony.dtv.software.m2.devicecontrolservice,android.hardware.vulkan.version,android.hardware.wifi.passpoint,android.hardware.screen.landscape,com.google.android.feature.GLOBAL_ASSIST_TRIGGERING,android.hardware.ram.normal,android.software.webview,com.sony.dtv.software.braviaapp,android.hardware.camera.any,android.hardware.vulkan.compute,android.hardware.location.network,android.software.cts,android.software.app_enumeration,com.sony.dtv.software.m2.seeds_auth,android.hardware.wifi.direct,android.software.live_wallpaper,android.software.ipsec_tunnels,com.sony.devices,android.hardware.wifi,android.hardware.location,android.hardware.vulkan.level,android.hardware.camera.external,nrdp.validation,android.software.file_based_encryption +GL.Extensions=,GL_ANDROID_extension_pack_es31a,GL_ARM_mali_program_binary,GL_ARM_mali_shader_binary,GL_ARM_rgba8,GL_ARM_shader_framebuffer_fetch,GL_ARM_shader_framebuffer_fetch_depth_stencil,GL_ARM_texture_unnormalized_coordinates,GL_EXT_EGL_image_array,GL_EXT_YUV_target,GL_EXT_blend_minmax,GL_EXT_buffer_storage,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_copy_image,GL_EXT_debug_marker,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers_indexed,GL_EXT_draw_elements_base_vertex,GL_EXT_external_buffer,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_occlusion_query_boolean,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_read_format_bgra,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_shader_pixel_local_storage,GL_EXT_shadow_samplers,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_compression_astc_decode_mode,GL_EXT_texture_compression_astc_decode_mode_rgb9e5,GL_EXT_texture_cube_map_array,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_rg,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_RG8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_storage,GL_EXT_texture_type_2_10_10_10_REV,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_debug,GL_KHR_robust_buffer_access_behavior,GL_KHR_robustness,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_KHR_texture_compression_astc_sliced_3d,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_EGL_sync,GL_OES_blend_equation_separate,GL_OES_blend_func_separate,GL_OES_blend_subtract,GL_OES_byte_coordinates,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_copy_image,GL_OES_depth24,GL_OES_depth_texture,GL_OES_depth_texture_cube_map,GL_OES_draw_buffers_indexed,GL_OES_draw_elements_base_vertex,GL_OES_draw_texture,GL_OES_element_index_uint,GL_OES_extended_matrix_palette,GL_OES_fbo_render_mipmap,GL_OES_fixed_point,GL_OES_framebuffer_object,GL_OES_geometry_shader,GL_OES_get_program_binary,GL_OES_gpu_shader5,GL_OES_mapbuffer,GL_OES_matrix_get,GL_OES_matrix_palette,GL_OES_packed_depth_stencil,GL_OES_point_size_array,GL_OES_point_sprite,GL_OES_primitive_bounding_box,GL_OES_query_matrix,GL_OES_read_format,GL_OES_required_internalformat,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_io_blocks,GL_OES_shader_multisample_interpolation,GL_OES_single_precision,GL_OES_standard_derivatives,GL_OES_stencil8,GL_OES_stencil_wrap,GL_OES_surfaceless_context,GL_OES_tessellation_shader,GL_OES_texture_3D,GL_OES_texture_border_clamp,GL_OES_texture_buffer,GL_OES_texture_compression_astc,GL_OES_texture_cube_map,GL_OES_texture_cube_map_array,GL_OES_texture_mirrored_repeat,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OVR_multiview,GL_OVR_multiview2,GL_OVR_multiview_multisampled_render_to_texture +GL.Version=196610 +GSF.version=203615037 +HasFiveWayNavigation=true +HasHardKeyboard=false +Keyboard=1 +Locales=af,af_ZA,am,ar,ar_EG,as,ast,az,be,bg,bn,bn_IN,bs,ca,ckb,cs,da,de,el,en,en_AU,en_CA,en_GB,en_IN,en_US,en_XC,eo,es,es_419,es_US,et,eu,fa,fa_IR,fi,fil,fr,fr_CA,fr_FR,gl,gu,gu_IN,he,hi,hi_IN,hr,ht,hu,hy,ia,id,in,in_ID,is,it,iw,ja,ka,kab,kk,km,kmr,kn,kn_IN,ko,ky,lo,lt,lv,mk,ml,ml_IN,mn,mr,mr_IN,ms,my,nb,nb_NO,ne,nl,or,pa,pa_IN,pl,pt,pt_BR,pt_PT,ro,ru,ru_RU,sc,si,sk,sl,so,sq,sr,sr_Latn,sv,sw,sw_TZ,ta,ta_IN,te,te_IN,th,th_TH,tr,uk,ur,uz,vi,vi_VN,yue,zh_CN,zh_HK,zh_TW,zu,zu_ZA +Navigation=2 +Platforms=armeabi-v7a,armeabi +Roaming=mobile-notroaming +Screen.Density=213 +Screen.Height=720 +Screen.Width=1280 +ScreenLayout=3 +SharedLibraries=android.test.base,android.test.mock,rtk-mediaplayer,android.hidl.manager-V1.0-java,android.hidl.base-V1.0-java,customer-framework,com.android.location.provider,android.net.ipsec.ike,com.android.future.usb.accessory,rtk-framework,android.ext.shared,javax.obex,com.google.android.gms,android.test.runner,org.apache.http.legacy,com.android.media.remotedisplay,com.android.media.tv.remoteprovider,com.android.mediadrm.signer +SimOperator=38 +TimeZone=UTC-10 +TouchScreen=1 +UserReadableName=BRAVIA VU2 +Vending.version=82201710 +Vending.versionString=22.0.17-21 [0] [PR] 332555730 -- GitLab From aa3a92113b1ffc546391577d0c9a2f79ec963d1c Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 26 May 2023 12:50:20 +0530 Subject: [PATCH 16/82] 3.1.1 Signed-off-by: Aayush Gupta --- CHANGELOG.md | 11 +++++++++++ lib/build.gradle | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d3a62dc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +Changelog : v3.1.1 +• Added Google Pixel 7a, Xiaomi 11 Lite 5G NE and Sony Bravia VU2 spoofing configurations +• Copied proguard rule from Aurora Store +• Updated dependencies and docker image + +Changelog : v3.1.0 +• Exposed response code for network calls via StateFlow from IHttpClient interface +• Keep device properties from being shrinked + +Changelog : v3.0.1 +• Initial changes (migration to AAR) diff --git a/lib/build.gradle b/lib/build.gradle index afd687f..688acbd 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -66,7 +66,7 @@ publishing { release(MavenPublication) { groupId = 'com.aurora' artifactId = 'gplayapi' - version = '3.1.0' + version = '3.1.1' afterEvaluate { from components.release -- GitLab From 89d851df5ab91ab8ccc77991d0a5e58e63c88b10 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 26 May 2023 13:21:37 +0530 Subject: [PATCH 17/82] GooglePlayApi: Use kotlin's way to get value from HashMap getOrDefault is not available below API 24 Signed-off-by: Aayush Gupta --- lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt b/lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt index 0c8c26c..cb91b9b 100644 --- a/lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt +++ b/lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt @@ -168,7 +168,7 @@ class GooglePlayApi(private val authData: AuthData) { val hashMap = Util.parseResponse(playResponse.responseBytes) return if (hashMap.containsKey("Auth")) { - hashMap.getOrDefault("Auth", "") + hashMap["Auth"] ?: "" } else { throw AuthException("Authentication failed : Could not generate OAuth Token") } -- GitLab From 265f94f5639b9e60080f62ed6de950c654b7b999 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 26 May 2023 13:22:36 +0530 Subject: [PATCH 18/82] gitignore: Ignore system configuration files created on MacOS Signed-off-by: Aayush Gupta --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 10e6232..99e9ae4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ gradle-app.setting /local.properties /src/main/java/com/aurora/gplayapi/tests/* okhttp_cache/ + +# MAC OSX system files +*.DS_Store -- GitLab From 75ee74397d7aa640674d5bdc5726a4eb094189f3 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 26 May 2023 13:23:55 +0530 Subject: [PATCH 19/82] jitpack: Create jitpack configuration Signed-off-by: Aayush Gupta --- jitpack.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 jitpack.yml diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..0c8469a --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,4 @@ +jdk: openjdk17 +install: + - chmod +x gradlew + - ./gradlew :lib:publishToMavenLocal \ No newline at end of file -- GitLab From 1de29edeb366ce5452506584c3385df21226cf04 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 26 May 2023 13:48:25 +0530 Subject: [PATCH 20/82] 3.1.2 Signed-off-by: Aayush Gupta --- CHANGELOG.md | 22 +++++++++++++--------- lib/build.gradle | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3a62dc..b2b2241 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,15 @@ -Changelog : v3.1.1 -• Added Google Pixel 7a, Xiaomi 11 Lite 5G NE and Sony Bravia VU2 spoofing configurations -• Copied proguard rule from Aurora Store -• Updated dependencies and docker image +Changelog : v3.1.2 +• Fix lint issue with getting authentication value from HashMap +• Create a jitpack configuration for JDK 17 support -Changelog : v3.1.0 -• Exposed response code for network calls via StateFlow from IHttpClient interface -• Keep device properties from being shrinked +Changelog : v3.1.1 +• Added Google Pixel 7a, Xiaomi 11 Lite 5G NE and Sony Bravia VU2 spoofing configurations +• Copied proguard rule from Aurora Store +• Updated dependencies and docker image -Changelog : v3.0.1 -• Initial changes (migration to AAR) +Changelog : v3.1.0 +• Exposed response code for network calls via StateFlow from IHttpClient interface +• Keep device properties from being shrinked + +Changelog : v3.0.1 +• Initial changes (migration to AAR) diff --git a/lib/build.gradle b/lib/build.gradle index 688acbd..d487533 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -66,7 +66,7 @@ publishing { release(MavenPublication) { groupId = 'com.aurora' artifactId = 'gplayapi' - version = '3.1.1' + version = '3.1.2' afterEvaluate { from components.release -- GitLab From 88e6a25f99f278d1e8701ee434cbaa2ff41d6236 Mon Sep 17 00:00:00 2001 From: Evengard Date: Fri, 26 May 2023 14:37:24 +0300 Subject: [PATCH 21/82] Adding library dependencies --- .../java/com/aurora/gplayapi/data/builders/AppBuilder.kt | 7 +++++++ .../aurora/gplayapi/data/models/details/Dependencies.kt | 3 +++ lib/src/main/proto/GooglePlay.proto | 7 +++++++ 3 files changed, 17 insertions(+) diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt index 7ecb109..1a1e11e 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt @@ -188,6 +188,13 @@ object AppBuilder { dependentSplits.add(splitId) } + it.libraryDependencyList.forEach { dependency -> + var libApp = App(dependency.packageName) + libApp.versionCode = dependency.versionCode + libApp.offerType = 1 + dependentLibraries.add(libApp) + } + totalSize = it.size targetSDK = it.targetSdk } diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt index d08298f..459482e 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt @@ -15,9 +15,12 @@ package com.aurora.gplayapi.data.models.details +import com.aurora.gplayapi.data.models.App + class Dependencies { var dependentPackages = mutableListOf() var dependentSplits = mutableListOf() + var dependentLibraries = mutableListOf() var targetSDK: Int = -1 var totalSize: Long = -1L } \ No newline at end of file diff --git a/lib/src/main/proto/GooglePlay.proto b/lib/src/main/proto/GooglePlay.proto index 54258e5..5db6066 100644 --- a/lib/src/main/proto/GooglePlay.proto +++ b/lib/src/main/proto/GooglePlay.proto @@ -1056,6 +1056,7 @@ message Dependencies { optional int32 targetSdk = 4; optional int32 unknown2 = 5; repeated string splitApks = 11; + repeated LibraryDependency libraryDependency = 13; } message Dependency { @@ -1064,6 +1065,12 @@ message Dependency { optional int32 unknown4 = 4; } +message LibraryDependency { + optional string packageName = 1; + optional int32 versionCode = 2; +} + + message TestingProgramInfo { optional bool subscribed = 2; optional bool subscribedAndInstalled = 3; -- GitLab From f1a68c2ef4accbbdda3a8143c06c20a01dfce3d6 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 31 May 2023 18:33:29 +0800 Subject: [PATCH 22/82] README: Reformat Signed-off-by: Aayush Gupta --- README.md | 102 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 1314fc0..b7ebb58 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Google Play Store Protobuf API wrapper in Kotlin -**For Educational & Research purpose only +**For Educational & Research purpose only** ## Disclaimer @@ -13,78 +13,112 @@ I'm not resposible for anything that may go wrong with: 4. Girlfriend. 5. Crypto Wallet. -***Hold your own beer! +**Hold your own beer!** ## Build - git clone https://gitlab.com/AuroraOSS/gplayapi.git - gradlew :assemble - gradlew :build +To build the library locally, run the following commands: + +```shell +git clone https://gitlab.com/AuroraOSS/gplayapi.git && cd gplayapi +./gradlew publishReleasePublicationToLocalRepository +``` + +This will generate an unsigned release build +([AAR](https://developer.android.com/studio/projects/android-library.html#aar-contents)) in the +`lib/build/repo` directory. ## Work Flow - 1. Obtain AASToken from (Email,Password) pair. - 2. Obtain AuthData from (Email,AASToken) pair. - 3. Use AuthData to access data. -## Usage +1. Obtain AASToken from (Email, Password) pair. +2. Obtain AuthData from (Email, AASToken) pair. +3. Use AuthData to access data. + ### AASToken Use one of the following tools * [Authenticator](https://github.com/whyorean/Authenticator) * [AASTokenGrabber](https://github.com/whyorean/AASTokenGrabber) +## Usage + +You need to build an instance of `AuthData` to call any method related with the API. Building an +instance requires Email and AASToken fetched from the above-mentioned workflow. + ### AuthData - val authData = AuthHelper.build(email,aastoken) +```kotlin +val authData = AuthHelper.build(email, aastoken) +``` ### Fetch App Details - val app = AppDetailsHelper(authData).getAppByPackageName(packageName) +```kotlin +val app = AppDetailsHelper(authData).getAppByPackageName(packageName) +``` ### Fetch Bulk App Details - val appList = AppDetailsHelper.getAppByPackageName(packageNameList) +```kotlin +val appList = AppDetailsHelper.getAppByPackageName(packageNameList) +``` ### Fetch APKs/OBBs/Patches - val files = PurchaseHelper(authData).purchase( - app.packageName, - app.versionCode, - app.offerType - ) +```kotlin +val files = PurchaseHelper(authData).purchase( + app.packageName, + app.versionCode, + app.offerType +) +``` ### Fetch All Categories - val categoryList = CategoryHelper(authData).getAllCategoriesList(type) //type = GAME or APPLICATION +```kotlin +val categoryList = CategoryHelper(authData).getAllCategoriesList(type) //type = GAME or APPLICATION +``` ### Fetch Search Suggestions - val entries = SearchHelper(authData).searchSuggestions(query) +```kotlin +val entries = SearchHelper(authData).searchSuggestions(query) +``` ### Search Apps & Games - var helper = SearchHelper(authData) - var searchBundle = helper.searchResults(query) - var appList = searchBundle.appList - - #To fetch next list - appList = helper.next(searchBundle.subBundles) +```kotlin +var helper = SearchHelper(authData) +var searchBundle = helper.searchResults(query) +var appList = searchBundle.appList + +// To fetch next list +appList = helper.next(searchBundle.subBundles) +``` ### App Reviews - var helper = ReviewsHelper(authData) - var reviewCluster = helper.getReviews(packageName, filter) //filter = ALL, POSITIVE, CRITICAL - #To fetch next list - reviewCluster = helper.next(reviewCluster.nextPageUrl) +```kotlin +var helper = ReviewsHelper(authData) +var reviewCluster = helper.getReviews(packageName, filter) //filter = ALL, POSITIVE, CRITICAL + +// To fetch next list +reviewCluster = helper.next(reviewCluster.nextPageUrl) +``` ### User Reviews - var helper = ReviewsHelper(authData) - //Submit or Edit review - val review = helper.addOrEditReview(packageName, title, content, rating, isBeta) - //Retrive review - val review = helper.getUserReview(packageName, isBeta) +```kotlin +var helper = ReviewsHelper(authData) + +//Submit or Edit review +val review = helper.addOrEditReview(packageName, title, content, rating, isBeta) + +//Retrive review +val review = helper.getUserReview(packageName, isBeta) +``` ## Credits + 1. [googleplay-api](https://github.com/egirault/googleplay-api) 2. [google-play-crawler](https://github.com/Akdeniz/google-play-crawler) 3. [play-store-api](https://github.com/yeriomin/play-store-api) -- GitLab From 4c1caf08cde36346cdc4f82ee5def01596eee494 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 31 May 2023 18:51:56 +0800 Subject: [PATCH 23/82] 3.1.3 Signed-off-by: Aayush Gupta --- CHANGELOG.md | 3 +++ lib/build.gradle | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2b2241..9f4814b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +Changelog : v3.1.3 +• Implement shared library dependencies API + Changelog : v3.1.2 • Fix lint issue with getting authentication value from HashMap • Create a jitpack configuration for JDK 17 support diff --git a/lib/build.gradle b/lib/build.gradle index d487533..fdcfe04 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -66,7 +66,7 @@ publishing { release(MavenPublication) { groupId = 'com.aurora' artifactId = 'gplayapi' - version = '3.1.2' + version = '3.1.3' afterEvaluate { from components.release -- GitLab From b425f02b8adde33955d4fb4fc135e9dac8722d92 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 22 Jun 2023 18:38:34 +0530 Subject: [PATCH 24/82] res: raw: Add Google Pixel Tablet spoofing configuration Signed-off-by: Aayush Gupta --- .../res/raw/gplayapi_px_tablet.properties | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 lib/src/main/res/raw/gplayapi_px_tablet.properties diff --git a/lib/src/main/res/raw/gplayapi_px_tablet.properties b/lib/src/main/res/raw/gplayapi_px_tablet.properties new file mode 100644 index 0000000..7a93449 --- /dev/null +++ b/lib/src/main/res/raw/gplayapi_px_tablet.properties @@ -0,0 +1,50 @@ +# +# GPlayApi +# Copyright (C) 2023, The Calyx Institute +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +Build.BOOTLOADER=tangorpro-1.0-9883529 +Build.BRAND=google +Build.DEVICE=tangorpro +Build.FINGERPRINT=google/tangorpro/tangorpro\:13/TQ3A.230605.009.A1/10100517\:user/release-keys +Build.HARDWARE=tangorpro +Build.ID=TQ3A.230605.012 +Build.MANUFACTURER=Google +Build.MODEL=Pixel Tablet +Build.PRODUCT=tangorpro +Build.RADIO=unknown +Build.VERSION.RELEASE=13 +Build.VERSION.SDK_INT=33 +CellOperator=310 +Client=android-google +Features=android.hardware.sensor.accelerometer,android.software.controls,android.hardware.faketouch,android.software.telecom,android.hardware.usb.accessory,android.hardware.sensor.dynamic.head_tracker,android.software.backup,android.hardware.touchscreen,android.hardware.touchscreen.multitouch,android.software.erofs,android.software.print,android.software.activities_on_secondary_displays,android.hardware.wifi.rtt,com.google.android.feature.PIXEL_2017_EXPERIENCE,android.software.voice_recognizers,android.software.picture_in_picture,android.hardware.fingerprint,android.hardware.sensor.gyroscope,android.hardware.audio.low_latency,android.software.vulkan.deqp.level,android.software.cant_save_state,com.google.android.feature.PIXEL_2018_EXPERIENCE,android.hardware.security.model.compatible,com.google.android.feature.PIXEL_2019_EXPERIENCE,android.hardware.opengles.aep,org.lineageos.livedisplay,android.hardware.bluetooth,android.software.window_magnification,android.software.incremental_delivery,android.software.opengles.deqp.level,vendor.android.hardware.camera.preview-dis.front,com.google.android.feature.PIXEL_2022_MIDYEAR_EXPERIENCE,android.hardware.camera.concurrent,android.hardware.usb.host,android.hardware.audio.output,android.software.verified_boot,android.hardware.camera.front,android.hardware.strongbox_keystore,android.hardware.screen.portrait,android.hardware.uwb,com.google.android.feature.PIXEL_2021_MIDYEAR_EXPERIENCE,android.hardware.sensor.stepdetector,android.software.home_screen,android.hardware.context_hub,vendor.android.hardware.camera.preview-dis.back,android.hardware.microphone,com.google.android.feature.PIXEL_TABLET_2023_EXPERIENCE,android.software.autofill,org.lineageos.hardware,org.lineageos.globalactions,android.software.securely_removes_users,com.google.android.feature.PIXEL_EXPERIENCE,android.hardware.bluetooth_le,android.hardware.sensor.compass,android.hardware.touchscreen.multitouch.jazzhand,android.software.app_widgets,com.google.android.feature.PIXEL_2020_MIDYEAR_EXPERIENCE,android.software.input_methods,android.hardware.sensor.light,android.hardware.vulkan.version,android.software.companion_device_setup,android.software.device_admin,android.hardware.wifi.passpoint,android.hardware.camera,org.lineageos.trust,android.hardware.device_unique_attestation,android.hardware.screen.landscape,android.software.device_id_attestation,android.hardware.ram.normal,vendor.android.hardware.camera.stream-usecase,com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE,android.software.managed_users,android.software.webview,android.hardware.sensor.stepcounter,android.hardware.camera.capability.manual_post_processing,android.hardware.camera.any,android.hardware.camera.capability.raw,android.hardware.vulkan.compute,android.hardware.touchscreen.multitouch.distinct,android.hardware.location.network,android.software.cts,android.hardware.camera.capability.manual_sensor,android.software.app_enumeration,android.hardware.camera.level.full,android.hardware.identity_credential,android.hardware.wifi.direct,android.software.live_wallpaper,com.google.android.feature.GOOGLE_EXPERIENCE,android.software.ipsec_tunnels,org.lineageos.settings,android.hardware.audio.pro,android.software.midi,android.hardware.hardware_keystore,com.google.android.feature.PIXEL_2020_EXPERIENCE,android.hardware.wifi,android.hardware.location,android.hardware.vulkan.level,com.google.android.feature.PIXEL_2021_EXPERIENCE,android.hardware.keystore.app_attest_key,android.hardware.wifi.aware,com.google.android.feature.PIXEL_2022_EXPERIENCE,android.software.secure_lock_screen,android.software.file_based_encryption +GL.Extensions=,GL_ANDROID_extension_pack_es31a,GL_ARM_mali_program_binary,GL_ARM_mali_shader_binary,GL_ARM_rgba8,GL_ARM_shader_framebuffer_fetch,GL_ARM_shader_framebuffer_fetch_depth_stencil,GL_ARM_texture_unnormalized_coordinates,GL_EXT_EGL_image_array,GL_EXT_YUV_target,GL_EXT_blend_minmax,GL_EXT_buffer_storage,GL_EXT_clip_control,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_copy_image,GL_EXT_debug_marker,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers_indexed,GL_EXT_draw_elements_base_vertex,GL_EXT_external_buffer,GL_EXT_float_blend,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_occlusion_query_boolean,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_read_format_bgra,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_shader_pixel_local_storage,GL_EXT_shadow_samplers,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_compression_astc_decode_mode,GL_EXT_texture_compression_astc_decode_mode_rgb9e5,GL_EXT_texture_cube_map_array,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_rg,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_RG8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_storage,GL_EXT_texture_type_2_10_10_10_REV,GL_EXT_unpack_subimage,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_debug,GL_KHR_robust_buffer_access_behavior,GL_KHR_robustness,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_KHR_texture_compression_astc_sliced_3d,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_EGL_sync,GL_OES_blend_equation_separate,GL_OES_blend_func_separate,GL_OES_blend_subtract,GL_OES_byte_coordinates,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_copy_image,GL_OES_depth24,GL_OES_depth_texture,GL_OES_depth_texture_cube_map,GL_OES_draw_buffers_indexed,GL_OES_draw_elements_base_vertex,GL_OES_draw_texture,GL_OES_element_index_uint,GL_OES_extended_matrix_palette,GL_OES_fbo_render_mipmap,GL_OES_fixed_point,GL_OES_framebuffer_object,GL_OES_geometry_shader,GL_OES_get_program_binary,GL_OES_gpu_shader5,GL_OES_mapbuffer,GL_OES_matrix_get,GL_OES_matrix_palette,GL_OES_packed_depth_stencil,GL_OES_point_size_array,GL_OES_point_sprite,GL_OES_primitive_bounding_box,GL_OES_query_matrix,GL_OES_read_format,GL_OES_required_internalformat,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_io_blocks,GL_OES_shader_multisample_interpolation,GL_OES_single_precision,GL_OES_standard_derivatives,GL_OES_stencil8,GL_OES_stencil_wrap,GL_OES_surfaceless_context,GL_OES_tessellation_shader,GL_OES_texture_3D,GL_OES_texture_border_clamp,GL_OES_texture_buffer,GL_OES_texture_compression_astc,GL_OES_texture_cube_map,GL_OES_texture_cube_map_array,GL_OES_texture_float_linear,GL_OES_texture_mirrored_repeat,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OVR_multiview,GL_OVR_multiview2,GL_OVR_multiview_multisampled_render_to_texture +GL.Version=196610 +GSF.version=203615037 +HasFiveWayNavigation=false +HasHardKeyboard=false +Keyboard=1 +Locales=af,af_ZA,am,am_ET,ar,ar_EG,ar_XB,as,ast,ast_ES,az,be,bg,bg_BG,bn,bs,ca,ca_ES,ckb,cs,cs_CZ,cy,da,da_DK,de,de_DE,el,el_GR,en,en_AU,en_CA,en_GB,en_IN,en_US,en_XA,en_XC,eo,es,es_419,es_ES,es_US,et,eu,fa,fa_IR,fi,fi_FI,fil,fil_PH,fr,fr_CA,fr_FR,gd,gl,gu,he,hi,hi_IN,hr,hr_HR,ht,hu,hu_HU,hy,ia,id,in,in_ID,is,it,it_IT,iw,iw_IL,ja,ja_JP,ka,kab,kk,km,kmr,kn,ko,ko_KR,ky,lo,lt,lt_LT,lv,lv_LV,mk,ml,mn,mr,ms,ms_MY,my,nb,nb_NO,ne,nl,nl_NL,or,pa,pl,pl_PL,pt,pt_BR,pt_PT,ro,ro_RO,ru,ru_RU,sc,si,sk,sk_SK,sl,sl_SI,so,sq,sr,sr_Latn,sr_RS,sv,sv_SE,sw,sw_TZ,ta,te,th,th_TH,tr,tr_TR,uk,uk_UA,ur,uz,vi,vi_VN,yue,zh_CN,zh_HK,zh_TW,zu,zu_ZA +Navigation=1 +Platforms=arm64-v8a +Roaming=mobile-notroaming +Screen.Density=320 +Screen.Height=2496 +Screen.Width=1600 +ScreenLayout=4 +SharedLibraries=android.test.base,android.test.mock,android.hidl.manager-V1.0-java,libedgetpu_client.google.so,libedgetpu_util.so,android.hidl.base-V1.0-java,com.google.android.camera.experimental2022,libOpenCL-pixel.so,com.android.location.provider,android.net.ipsec.ike,com.android.future.usb.accessory,android.ext.shared,libaudio_proxy.google.so,javax.obex,com.google.android.gms,lib_aion_buffer.so,libgxp.so,gxp_metrics_logger.so,android.test.runner,org.apache.http.legacy,com.android.cts.ctsshim.shared_library,com.android.nfc_extras,com.android.media.remotedisplay,com.android.mediadrm.signer,android.system.virtualmachine +SimOperator=38 +TimeZone=UTC-10 +TouchScreen=3 +UserReadableName=Google Pixel Tablet +Vending.version=82201710 +Vending.versionString=22.0.17-21 [0] [PR] 332555730 -- GitLab From 58a34d9d0b5309574e6137b5ccc1a8544244edad Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 30 Jun 2023 18:36:47 +0530 Subject: [PATCH 25/82] Bump minSdk to 21 Signed-off-by: Aayush Gupta --- lib/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/build.gradle b/lib/build.gradle index fdcfe04..f052f18 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -10,10 +10,10 @@ android { compileSdk 33 defaultConfig { - minSdk 19 + minSdk 21 targetSdk 33 aarMetadata { - minCompileSdk = 19 + minCompileSdk = 21 } } -- GitLab From 24b6489bb8abcd40c76f2cc36d52ad1021f6d9f3 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 30 Jun 2023 18:38:23 +0530 Subject: [PATCH 26/82] Enable java language 17 features Signed-off-by: Aayush Gupta --- lib/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/build.gradle b/lib/build.gradle index f052f18..64dac52 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -24,11 +24,11 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = '11' + jvmTarget = '17' } packagingOptions { resources { -- GitLab From 50c4decb562032edff211bbbb059c369735b235b Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 30 Jun 2023 18:45:56 +0530 Subject: [PATCH 27/82] Import and reformat kotlin code with ktlint Signed-off-by: Aayush Gupta --- build.gradle | 1 + lib/build.gradle | 1 + .../java/com/aurora/gplayapi/Constants.kt | 2 +- .../java/com/aurora/gplayapi/DeviceManager.kt | 4 +- .../java/com/aurora/gplayapi/FileManager.kt | 3 +- .../java/com/aurora/gplayapi/GooglePlayApi.kt | 29 +-- .../gplayapi/data/builders/AppBuilder.kt | 8 +- .../gplayapi/data/builders/ArtworkBuilder.kt | 2 +- .../gplayapi/data/builders/BadgeBuilder.kt | 2 +- .../gplayapi/data/builders/RatingBuilder.kt | 22 +-- .../gplayapi/data/builders/ReviewBuilder.kt | 2 +- .../data/builders/TestingProgramBuilder.kt | 2 +- .../data/builders/UserProfileBuilder.kt | 3 +- .../com/aurora/gplayapi/data/models/App.kt | 8 +- .../aurora/gplayapi/data/models/Artwork.kt | 2 +- .../aurora/gplayapi/data/models/AuthData.kt | 6 +- .../aurora/gplayapi/data/models/Category.kt | 2 +- .../com/aurora/gplayapi/data/models/File.kt | 4 +- .../gplayapi/data/models/PlayResponse.kt | 2 +- .../com/aurora/gplayapi/data/models/Rating.kt | 20 +- .../gplayapi/data/models/ReviewCluster.kt | 2 +- .../gplayapi/data/models/SearchBundle.kt | 4 +- .../gplayapi/data/models/StreamBundle.kt | 2 +- .../gplayapi/data/models/StreamCluster.kt | 2 +- .../gplayapi/data/models/details/AppInfo.kt | 2 +- .../gplayapi/data/models/details/Badge.kt | 4 +- .../gplayapi/data/models/details/Chip.kt | 4 +- .../data/models/details/Dependencies.kt | 2 +- .../gplayapi/data/models/details/DevStream.kt | 2 +- .../data/models/details/TestingProgram.kt | 2 +- .../data/models/editor/EditorChoiceBundle.kt | 2 +- .../data/models/editor/EditorChoiceCluster.kt | 2 +- .../data/models/editor/EditorChoiceReason.kt | 2 +- .../gplayapi/data/models/sale/AppOnSale.kt | 22 +-- .../gplayapi/data/models/sale/SaleBundle.kt | 8 +- .../data/providers/DeviceInfoProvider.kt | 179 ++++++++++-------- .../gplayapi/data/providers/HeaderProvider.kt | 10 +- .../gplayapi/data/providers/ParamProvider.kt | 14 +- .../gplayapi/exceptions/ApiException.kt | 10 +- .../gplayapi/exceptions/AuthException.kt | 2 +- .../exceptions/GooglePlayException.kt | 2 +- .../gplayapi/helpers/AppDetailsHelper.kt | 29 +-- .../aurora/gplayapi/helpers/AppSalesHelper.kt | 13 +- .../com/aurora/gplayapi/helpers/AuthHelper.kt | 26 +-- .../aurora/gplayapi/helpers/AuthValidator.kt | 2 +- .../com/aurora/gplayapi/helpers/BaseHelper.kt | 87 ++++++--- .../aurora/gplayapi/helpers/CategoryHelper.kt | 3 +- .../aurora/gplayapi/helpers/ClusterHelper.kt | 6 +- .../gplayapi/helpers/ExpandedBrowseHelper.kt | 2 +- .../aurora/gplayapi/helpers/LibraryHelper.kt | 17 +- .../aurora/gplayapi/helpers/PurchaseHelper.kt | 81 ++++---- .../aurora/gplayapi/helpers/ReviewsHelper.kt | 32 +++- .../aurora/gplayapi/helpers/SearchHelper.kt | 18 +- .../aurora/gplayapi/helpers/StreamHelper.kt | 14 +- .../gplayapi/helpers/TopChartsHelper.kt | 6 +- .../gplayapi/helpers/UserProfileHelper.kt | 2 +- .../gplayapi/network/DefaultHttpClient.kt | 56 +++--- .../aurora/gplayapi/network/IHttpClient.kt | 2 +- 58 files changed, 460 insertions(+), 340 deletions(-) diff --git a/build.gradle b/build.gradle index 84651ef..fdd5582 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,7 @@ plugins { id 'com.android.library' version '8.0.1' apply false id 'org.jetbrains.kotlin.android' version '1.8.21' apply false id 'com.google.protobuf' version '0.9.1' apply false + id 'org.jlleitschuh.gradle.ktlint' version '11.4.0' apply false } task clean(type: Delete) { diff --git a/lib/build.gradle b/lib/build.gradle index 64dac52..7a9222a 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -3,6 +3,7 @@ plugins { id 'org.jetbrains.kotlin.android' id 'com.google.protobuf' id 'maven-publish' + id 'org.jlleitschuh.gradle.ktlint' } android { diff --git a/lib/src/main/java/com/aurora/gplayapi/Constants.kt b/lib/src/main/java/com/aurora/gplayapi/Constants.kt index 60db077..daf585a 100644 --- a/lib/src/main/java/com/aurora/gplayapi/Constants.kt +++ b/lib/src/main/java/com/aurora/gplayapi/Constants.kt @@ -62,4 +62,4 @@ object Constants { } } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt b/lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt index 68532f9..f8e20b6 100644 --- a/lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt +++ b/lib/src/main/java/com/aurora/gplayapi/DeviceManager.kt @@ -16,13 +16,13 @@ package com.aurora.gplayapi import java.io.FileNotFoundException -import java.util.* +import java.util.Properties object DeviceManager { fun loadProperties(deviceName: String?): Properties? { return try { val properties = Properties() - val inputStream = javaClass.classLoader?.getResourceAsStream("gplayapi_${deviceName}") + val inputStream = javaClass.classLoader?.getResourceAsStream("gplayapi_$deviceName") if (inputStream != null) { properties.load(inputStream) } else { diff --git a/lib/src/main/java/com/aurora/gplayapi/FileManager.kt b/lib/src/main/java/com/aurora/gplayapi/FileManager.kt index 3e49d9c..46ef9e5 100644 --- a/lib/src/main/java/com/aurora/gplayapi/FileManager.kt +++ b/lib/src/main/java/com/aurora/gplayapi/FileManager.kt @@ -17,7 +17,6 @@ package com.aurora.gplayapi import java.io.BufferedReader import java.io.InputStreamReader -import java.util.* object FileManager { fun loadPackages(fileName: String?): List? { @@ -34,4 +33,4 @@ object FileManager { null } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt b/lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt index cb91b9b..21f1edc 100644 --- a/lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt +++ b/lib/src/main/java/com/aurora/gplayapi/GooglePlayApi.kt @@ -15,7 +15,6 @@ package com.aurora.gplayapi -import com.aurora.gplayapi.GooglePlayApi.Service.* import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.providers.DeviceInfoProvider import com.aurora.gplayapi.data.providers.HeaderProvider.getAuthHeaders @@ -29,7 +28,6 @@ import com.aurora.gplayapi.network.IHttpClient import com.aurora.gplayapi.utils.Util import java.io.IOException import java.math.BigInteger -import java.util.* class GooglePlayApi(private val authData: AuthData) { @@ -129,37 +127,44 @@ class GooglePlayApi(private val authData: AuthData) { params.putAll(getAuthParams(aasToken)) when (service) { - AC2DM -> { + Service.AC2DM -> { params["service"] = "ac2dm" params.remove("app") } - ANDROID_CHECK_IN_SERVER -> { + + Service.ANDROID_CHECK_IN_SERVER -> { params["oauth2_foreground"] = "0" params["app"] = "com.google.android.gms" params["service"] = "AndroidCheckInServer" } - EXPERIMENTAL_CONFIG -> { + + Service.EXPERIMENTAL_CONFIG -> { params["service"] = "oauth2:https://www.googleapis.com/auth/experimentsandconfigs" } - NUMBERER -> { + + Service.NUMBERER -> { params["app"] = "com.google.android.gms" params["service"] = "oauth2:https://www.googleapis.com/auth/numberer" } - GCM -> { + + Service.GCM -> { params["app"] = "com.google.android.gms" params["service"] = "oauth2:https://www.googleapis.com/auth/gcm" } - GOOGLE_PLAY -> { + + Service.GOOGLE_PLAY -> { headers["app"] = "com.google.android.gms" params["service"] = "oauth2:https://www.googleapis.com/auth/googleplay" } - OAUTHLOGIN -> { + + Service.OAUTHLOGIN -> { params["oauth2_foreground"] = "0" params["app"] = "com.google.android.googlequicksearchbox" params["service"] = "oauth2:https://www.google.com/accounts/OAuthLogin" params["callerPkg"] = "com.google.android.googlequicksearchbox" } - ANDROID -> { + + Service.ANDROID -> { params["service"] = "android" } } @@ -216,7 +221,7 @@ class GooglePlayApi(private val authData: AuthData) { const val URL_LIBRARY = "$URL_FDFE/library" const val URL_MODIFY_LIBRARY = "$URL_FDFE/modifyLibrary" - //Not part of Google's API + // Not part of Google's API const val SALES_URL = "https://www.bestappsale.com/api/android/getsale.php" } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt index 1a1e11e..a06a193 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/AppBuilder.kt @@ -81,8 +81,9 @@ object AppBuilder { app.targetSdk = appDetails.targetSdkVersion app.updatedOn = appDetails.infoUpdatedOn - if (app.developerName.isEmpty()) + if (app.developerName.isEmpty()) { app.developerName = item.creator + } appDetails.instantLink?.let { app.instantAppLink = it @@ -259,7 +260,8 @@ object AppBuilder { } private fun getInstalls(downloadInfo: String): Long { - val matcher: Matcher = Pattern.compile("[\\d]+").matcher(downloadInfo.replace("[,.\\s]+".toRegex(), "")) + val matcher: Matcher = + Pattern.compile("[\\d]+").matcher(downloadInfo.replace("[,.\\s]+".toRegex(), "")) return if (matcher.find()) Util.parseLong(matcher.group(0), 0) else 0 } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt index a155af2..417cd60 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/ArtworkBuilder.kt @@ -29,4 +29,4 @@ object ArtworkBuilder { height = image.dimension.height } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt index d566049..586ce80 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/BadgeBuilder.kt @@ -29,4 +29,4 @@ object BadgeBuilder { link = badge.link.toString() } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt index 5e00c54..ef5fec6 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/RatingBuilder.kt @@ -22,16 +22,16 @@ object RatingBuilder { fun build(rating: AggregateRating): Rating { return Rating( - rating.starRating, - rating.oneStarRatings, - rating.twoStarRatings, - rating.threeStarRatings, - rating.fourStarRatings, - rating.fiveStarRatings, - rating.thumbsUpCount, - rating.thumbsDownCount, - rating.ratingLabel, - rating.ratingCountLabelAbbreviated + rating.starRating, + rating.oneStarRatings, + rating.twoStarRatings, + rating.threeStarRatings, + rating.fourStarRatings, + rating.fiveStarRatings, + rating.thumbsUpCount, + rating.thumbsDownCount, + rating.ratingLabel, + rating.ratingCountLabelAbbreviated ) } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt index 4d4ab34..5382646 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/ReviewBuilder.kt @@ -37,4 +37,4 @@ object ReviewBuilder { } } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt index 9d91edc..87fa5f1 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/TestingProgramBuilder.kt @@ -36,4 +36,4 @@ object TestingProgramBuilder { null } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt index 56658cb..2efb686 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/UserProfileBuilder.kt @@ -17,7 +17,6 @@ package com.aurora.gplayapi.data.builders import com.aurora.gplayapi.data.models.UserProfile - object UserProfileBuilder { fun build(userProfileProto: com.aurora.gplayapi.UserProfile): UserProfile { @@ -27,4 +26,4 @@ object UserProfileBuilder { artwork = ArtworkBuilder.build(userProfileProto.getImage(0)) } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/App.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/App.kt index 3524a7d..898e7e1 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/App.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/App.kt @@ -16,7 +16,11 @@ package com.aurora.gplayapi.data.models import com.aurora.gplayapi.Constants.Restriction -import com.aurora.gplayapi.data.models.details.* +import com.aurora.gplayapi.data.models.details.AppInfo +import com.aurora.gplayapi.data.models.details.Badge +import com.aurora.gplayapi.data.models.details.Chip +import com.aurora.gplayapi.data.models.details.Dependencies +import com.aurora.gplayapi.data.models.details.TestingProgram import com.aurora.gplayapi.data.models.editor.EditorChoiceReason class App(var packageName: String) { @@ -85,4 +89,4 @@ class App(var packageName: String) { else -> false } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt index 8f8b207..cd00eed 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt @@ -33,4 +33,4 @@ class Artwork { else -> false } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/AuthData.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/AuthData.kt index 6e67240..8eaa8b2 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/AuthData.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/AuthData.kt @@ -16,7 +16,7 @@ package com.aurora.gplayapi.data.models import com.aurora.gplayapi.data.providers.DeviceInfoProvider -import java.util.* +import java.util.Locale class AuthData { @@ -27,7 +27,7 @@ class AuthData { this.aasToken = aasToken } - constructor(email: String, authToken: String, insecure : Boolean = true) { + constructor(email: String, authToken: String, insecure: Boolean = true) { this.email = email this.authToken = authToken this.isAnonymous = true @@ -50,4 +50,4 @@ class AuthData { var locale: Locale = Locale.getDefault() var deviceInfoProvider: DeviceInfoProvider? = null var userProfile: UserProfile? = null -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/Category.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Category.kt index 2383eff..3aed665 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/Category.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/Category.kt @@ -37,4 +37,4 @@ class Category { else -> false } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/File.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/File.kt index c66e7fd..05948f6 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/File.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/File.kt @@ -15,7 +15,7 @@ package com.aurora.gplayapi.data.models -import java.util.* +import java.util.UUID class File { var id: String = UUID.randomUUID().toString() @@ -38,4 +38,4 @@ class File { else -> false } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/PlayResponse.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/PlayResponse.kt index f62ecfd..baa159d 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/PlayResponse.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/PlayResponse.kt @@ -21,4 +21,4 @@ class PlayResponse { var errorString: String = ("No Error") var isSuccessful: Boolean = false var code: Int = 0 -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt index 84e3d76..6f2ba63 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt @@ -16,14 +16,14 @@ package com.aurora.gplayapi.data.models data class Rating( - var average: Float = 0f, - var oneStar: Long = 0L, - var twoStar: Long = 0L, - var threeStar: Long = 0L, - var fourStar: Long = 0L, - var fiveStar: Long = 0L, - var thumbsUp: Long = 0L, - var thumbsDown: Long = 0L, - var label: String = String(), - var abbreviatedLabel: String = String() + var average: Float = 0f, + var oneStar: Long = 0L, + var twoStar: Long = 0L, + var threeStar: Long = 0L, + var fourStar: Long = 0L, + var fiveStar: Long = 0L, + var thumbsUp: Long = 0L, + var thumbsDown: Long = 0L, + var label: String = String(), + var abbreviatedLabel: String = String() ) diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt index 8755f0b..8ab8f21 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/ReviewCluster.kt @@ -23,4 +23,4 @@ class ReviewCluster { fun hasNext(): Boolean { return nextPageUrl.isNotBlank() } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/SearchBundle.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/SearchBundle.kt index 7512bfd..5627628 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/SearchBundle.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/SearchBundle.kt @@ -15,8 +15,6 @@ package com.aurora.gplayapi.data.models -import java.util.* - class SearchBundle { var id: Int = -1 var query: String = String() @@ -40,4 +38,4 @@ class SearchBundle { } } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/StreamBundle.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/StreamBundle.kt index 95a1727..e9a7ac2 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/StreamBundle.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/StreamBundle.kt @@ -28,4 +28,4 @@ class StreamBundle { fun hasCluster(): Boolean { return streamClusters.isNotEmpty() } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/StreamCluster.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/StreamCluster.kt index 98f13a2..b359201 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/StreamCluster.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/StreamCluster.kt @@ -26,4 +26,4 @@ class StreamCluster { fun hasNext(): Boolean { return clusterNextPageUrl.isNotBlank() } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt index 33b09bf..1d86b82 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt @@ -17,4 +17,4 @@ package com.aurora.gplayapi.data.models.details class AppInfo { var appInfoMap: MutableMap = mutableMapOf() -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt index 07e5b98..09e1db6 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt @@ -16,7 +16,7 @@ package com.aurora.gplayapi.data.models.details import com.aurora.gplayapi.data.models.Artwork -import java.util.* +import java.util.UUID class Badge { var id: String = UUID.randomUUID().toString() @@ -37,4 +37,4 @@ class Badge { override fun hashCode(): Int { return id.hashCode() } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt index 4c20e6f..c02bcc1 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt @@ -15,7 +15,7 @@ package com.aurora.gplayapi.data.models.details -import java.util.* +import java.util.UUID class Chip { var id: String = UUID.randomUUID().toString() @@ -32,4 +32,4 @@ class Chip { else -> false } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt index 459482e..feb0051 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt @@ -23,4 +23,4 @@ class Dependencies { var dependentLibraries = mutableListOf() var targetSDK: Int = -1 var totalSize: Long = -1L -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/DevStream.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/DevStream.kt index 5702e9f..d8dd647 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/DevStream.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/DevStream.kt @@ -22,4 +22,4 @@ class DevStream { var description: String = String() var imgUrl: String = String() var streamBundle: StreamBundle = StreamBundle() -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt index f96c5c8..7d7a81a 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt @@ -29,4 +29,4 @@ class TestingProgram { class TestingProgramStatus { var subscribed: Boolean = false var unsubscribed: Boolean = false -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt index 729a281..8637086 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceBundle.kt @@ -19,4 +19,4 @@ class EditorChoiceBundle { var id: Int = -1 var bundleTitle: String = String() var bundleChoiceClusters: List = ArrayList() -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt index e5fd959..7950ea0 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceCluster.kt @@ -22,4 +22,4 @@ class EditorChoiceCluster { var clusterTitle: String = String() var clusterBrowseUrl: String = String() var clusterArtwork: List = ArrayList() -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt index 81bfc26..d5d0e6f 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt @@ -15,4 +15,4 @@ package com.aurora.gplayapi.data.models.editor -data class EditorChoiceReason(var bulletins: List, var description: String) \ No newline at end of file +data class EditorChoiceReason(var bulletins: List, var description: String) diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt index 137b2ef..1f33662 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/sale/AppOnSale.kt @@ -16,14 +16,14 @@ package com.aurora.gplayapi.data.models.sale class AppOnSale( - var category: String, - var rating: String, - var id: String, - var idandroid: String, - var downloadsmin: String, - var nameapp: String, - var price: String, - var icon: String, - var oldprice: String, - var dateup: String -) \ No newline at end of file + var category: String, + var rating: String, + var id: String, + var idandroid: String, + var downloadsmin: String, + var nameapp: String, + var price: String, + var icon: String, + var oldprice: String, + var dateup: String +) diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt index f2054ac..1887b8d 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/sale/SaleBundle.kt @@ -16,7 +16,7 @@ package com.aurora.gplayapi.data.models.sale class SaleBundle( - var currency: String, - var currencycode: String, - var sales: List, -) \ No newline at end of file + var currency: String, + var currencycode: String, + var sales: List +) diff --git a/lib/src/main/java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt b/lib/src/main/java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt index fc64ce8..aba627a 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/providers/DeviceInfoProvider.kt @@ -15,10 +15,15 @@ package com.aurora.gplayapi.data.providers -import com.aurora.gplayapi.* -import java.util.* +import com.aurora.gplayapi.AndroidBuildProto +import com.aurora.gplayapi.AndroidCheckinProto +import com.aurora.gplayapi.AndroidCheckinRequest +import com.aurora.gplayapi.DeviceConfigurationProto +import com.aurora.gplayapi.DeviceFeature +import java.util.Properties -class DeviceInfoProvider(var properties: Properties, var localeString: String) : BaseDeviceInfoProvider() { +class DeviceInfoProvider(var properties: Properties, var localeString: String) : + BaseDeviceInfoProvider() { @Transient private var timeToReport = System.currentTimeMillis() / 1000 @@ -30,7 +35,8 @@ class DeviceInfoProvider(var properties: Properties, var localeString: String) : override val sdkVersion: Int = properties.getProperty("Build.VERSION.SDK_INT").toInt() override val playServicesVersion: Int = properties.getProperty("GSF.version").toInt() override val mccMnc: String = properties.getProperty("SimOperator") - override val authUserAgentString: String = ("GoogleAuth/1.4 (${properties.getProperty("Build.DEVICE")} ${properties.getProperty("Build.ID")})") + override val authUserAgentString: String = + ("GoogleAuth/1.4 (${properties.getProperty("Build.DEVICE")} ${properties.getProperty("Build.ID")})") override val userAgentString: String get() { @@ -47,49 +53,54 @@ class DeviceInfoProvider(var properties: Properties, var localeString: String) : params.add("model=${properties.getProperty("Build.MODEL")}") params.add("buildId=${properties.getProperty("Build.ID")}") params.add("isWideScreen=${0}") - params.add("supportedAbis=${platforms}") + params.add("supportedAbis=$platforms") - return "Android-Finsky/${properties.getProperty("Vending.versionString")} (${params.joinToString(separator = ",")})" + return "Android-Finsky/${properties.getProperty("Vending.versionString")} (${ + params.joinToString( + separator = "," + ) + })" } override fun generateAndroidCheckInRequest(): AndroidCheckinRequest? { return AndroidCheckinRequest.newBuilder() - .setId(0) - .setCheckin( - AndroidCheckinProto.newBuilder() - .setBuild( - AndroidBuildProto.newBuilder() - .setId(properties.getProperty("Build.FINGERPRINT")) - .setProduct(properties.getProperty("Build.HARDWARE")) - .setCarrier(properties.getProperty("Build.BRAND")) - .setRadio(properties.getProperty("Build.RADIO")) - .setBootloader(properties.getProperty("Build.BOOTLOADER")) - .setDevice(properties.getProperty("Build.DEVICE")) - .setSdkVersion(getInt("Build.VERSION.SDK_INT")) - .setModel(properties.getProperty("Build.MODEL")) - .setManufacturer(properties.getProperty("Build.MANUFACTURER")) - .setBuildProduct(properties.getProperty("Build.PRODUCT")) - .setClient(properties.getProperty("Client")) - .setOtaInstalled(java.lang.Boolean.getBoolean(properties.getProperty("OtaInstalled"))) - .setTimestamp(timeToReport) - .setGoogleServices(getInt("GSF.version")) - ) - .setLastCheckinMsec(0) - .setCellOperator(properties.getProperty("CellOperator")) - .setSimOperator(properties.getProperty("SimOperator")) - .setRoaming(properties.getProperty("Roaming")) - .setUserNumber(0) - ) - .setLocale(localeString) - .setTimeZone(properties.getProperty("TimeZone")) - .setVersion(3) - .setDeviceConfiguration(deviceConfigurationProto) - .setFragment(0) - .build() + .setId(0) + .setCheckin( + AndroidCheckinProto.newBuilder() + .setBuild( + AndroidBuildProto.newBuilder() + .setId(properties.getProperty("Build.FINGERPRINT")) + .setProduct(properties.getProperty("Build.HARDWARE")) + .setCarrier(properties.getProperty("Build.BRAND")) + .setRadio(properties.getProperty("Build.RADIO")) + .setBootloader(properties.getProperty("Build.BOOTLOADER")) + .setDevice(properties.getProperty("Build.DEVICE")) + .setSdkVersion(getInt("Build.VERSION.SDK_INT")) + .setModel(properties.getProperty("Build.MODEL")) + .setManufacturer(properties.getProperty("Build.MANUFACTURER")) + .setBuildProduct(properties.getProperty("Build.PRODUCT")) + .setClient(properties.getProperty("Client")) + .setOtaInstalled(java.lang.Boolean.getBoolean(properties.getProperty("OtaInstalled"))) + .setTimestamp(timeToReport) + .setGoogleServices(getInt("GSF.version")) + ) + .setLastCheckinMsec(0) + .setCellOperator(properties.getProperty("CellOperator")) + .setSimOperator(properties.getProperty("SimOperator")) + .setRoaming(properties.getProperty("Roaming")) + .setUserNumber(0) + ) + .setLocale(localeString) + .setTimeZone(properties.getProperty("TimeZone")) + .setVersion(3) + .setDeviceConfiguration(deviceConfigurationProto) + .setFragment(0) + .build() } @Transient - override val deviceConfigurationProto: DeviceConfigurationProto = DeviceConfigurationProto.newBuilder() + override val deviceConfigurationProto: DeviceConfigurationProto = + DeviceConfigurationProto.newBuilder() .setTouchScreen(getInt("TouchScreen")) .setKeyboard(getInt("Keyboard")) .setNavigation(getInt("Navigation")) @@ -127,9 +138,9 @@ class DeviceInfoProvider(var properties: Properties, var localeString: String) : private fun getDeviceFeatures(): List { return getList("Features").map { DeviceFeature.newBuilder() - .setName(it) - .setValue(0) - .build() + .setName(it) + .setValue(0) + .build() } } @@ -137,14 +148,22 @@ class DeviceInfoProvider(var properties: Properties, var localeString: String) : if (!properties.containsKey("Vending.versionString") && properties.containsKey("Vending.version")) { var vendingVersionString = "7.1.15" if (properties.getProperty("Vending.version").length > 6) { - vendingVersionString = StringBuilder(properties.getProperty("Vending.version").substring(2, 6)).insert(2, ".").insert(1, ".").toString() + vendingVersionString = + StringBuilder(properties.getProperty("Vending.version").substring(2, 6)).insert( + 2, + "." + ).insert(1, ".").toString() } properties["Vending.versionString"] = vendingVersionString } - if (properties.containsKey("Build.FINGERPRINT") && (!properties.containsKey("Build.ID") - || !properties.containsKey("Build.VERSION.RELEASE"))) { - val fingerprint = properties.getProperty("Build.FINGERPRINT").split("/".toRegex()).toTypedArray() + if (properties.containsKey("Build.FINGERPRINT") && ( + !properties.containsKey("Build.ID") || + !properties.containsKey("Build.VERSION.RELEASE") + ) + ) { + val fingerprint = + properties.getProperty("Build.FINGERPRINT").split("/".toRegex()).toTypedArray() var buildId = "" var release = "" @@ -174,39 +193,39 @@ class DeviceInfoProvider(var properties: Properties, var localeString: String) : companion object { @Transient private val requiredFields = arrayOf( - "UserReadableName", - "Build.HARDWARE", - "Build.RADIO", - "Build.BOOTLOADER", - "Build.FINGERPRINT", - "Build.BRAND", - "Build.DEVICE", - "Build.VERSION.SDK_INT", - "Build.MODEL", - "Build.MANUFACTURER", - "Build.PRODUCT", - "TouchScreen", - "Keyboard", - "Navigation", - "ScreenLayout", - "HasHardKeyboard", - "HasFiveWayNavigation", - "GL.Version", - "GSF.version", - "Vending.version", - "Screen.Density", - "Screen.Width", - "Screen.Height", - "Platforms", - "SharedLibraries", - "Features", - "Locales", - "CellOperator", - "SimOperator", - "Roaming", - "Client", - "TimeZone", - "GL.Extensions" + "UserReadableName", + "Build.HARDWARE", + "Build.RADIO", + "Build.BOOTLOADER", + "Build.FINGERPRINT", + "Build.BRAND", + "Build.DEVICE", + "Build.VERSION.SDK_INT", + "Build.MODEL", + "Build.MANUFACTURER", + "Build.PRODUCT", + "TouchScreen", + "Keyboard", + "Navigation", + "ScreenLayout", + "HasHardKeyboard", + "HasFiveWayNavigation", + "GL.Version", + "GSF.version", + "Vending.version", + "Screen.Density", + "Screen.Width", + "Screen.Height", + "Platforms", + "SharedLibraries", + "Features", + "Locales", + "CellOperator", + "SimOperator", + "Roaming", + "Client", + "TimeZone", + "GL.Extensions" ) } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/providers/HeaderProvider.kt b/lib/src/main/java/com/aurora/gplayapi/data/providers/HeaderProvider.kt index bec12e5..85e6544 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/providers/HeaderProvider.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/providers/HeaderProvider.kt @@ -16,7 +16,7 @@ package com.aurora.gplayapi.data.providers import com.aurora.gplayapi.data.models.AuthData -import java.util.* +import java.util.Locale object HeaderProvider { @@ -24,8 +24,9 @@ object HeaderProvider { val headers: MutableMap = HashMap() headers["app"] = "com.google.android.gms" headers["User-Agent"] = builder.deviceInfoProvider!!.authUserAgentString - if (builder.gsfId.isNotBlank()) + if (builder.gsfId.isNotBlank()) { headers["device"] = builder.gsfId + } return headers } @@ -48,7 +49,8 @@ object HeaderProvider { headers["X-DFE-Request-Params"] = "timeoutMs=4000" if (authData.deviceCheckInConsistencyToken.isNotBlank()) { - headers["X-DFE-Device-Checkin-Consistency-Token"] = authData.deviceCheckInConsistencyToken + headers["X-DFE-Device-Checkin-Consistency-Token"] = + authData.deviceCheckInConsistencyToken } if (authData.deviceConfigToken.isNotBlank()) { @@ -95,4 +97,4 @@ object HeaderProvider { } return headers } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt b/lib/src/main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt index 0af91c1..bef05b5 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/providers/ParamProvider.kt @@ -16,19 +16,21 @@ package com.aurora.gplayapi.data.providers import com.aurora.gplayapi.data.models.AuthData -import java.util.* +import java.util.Locale object ParamProvider { fun getDefaultAuthParams(builder: AuthData): Map { val params: MutableMap = HashMap() - if (builder.gsfId.isNotBlank()) + if (builder.gsfId.isNotBlank()) { params["androidId"] = builder.gsfId + } params["sdk_version"] = builder.deviceInfoProvider!!.sdkVersion.toString() params["Email"] = builder.email - params["google_play_services_version"] = builder.deviceInfoProvider!!.playServicesVersion.toString() - params["device_country"] = builder.locale.country.toLowerCase() - params["lang"] = builder.locale.language.toLowerCase() + params["google_play_services_version"] = + builder.deviceInfoProvider!!.playServicesVersion.toString() + params["device_country"] = builder.locale.country.lowercase(Locale.getDefault()) + params["lang"] = builder.locale.language.lowercase(Locale.getDefault()) params["callerSig"] = "38918a453d07199354f8b19af05ec6562ced5788" return params } @@ -56,4 +58,4 @@ object ParamProvider { params["Token"] = oauthToken return params } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/exceptions/ApiException.kt b/lib/src/main/java/com/aurora/gplayapi/exceptions/ApiException.kt index 48a580b..15d144b 100644 --- a/lib/src/main/java/com/aurora/gplayapi/exceptions/ApiException.kt +++ b/lib/src/main/java/com/aurora/gplayapi/exceptions/ApiException.kt @@ -15,19 +15,19 @@ package com.aurora.gplayapi.exceptions -import java.lang.Exception - sealed class ApiException { data class AppNotPurchased(val reason: String = "App not purchased") : Exception() - data class AppNotFound(val reason: String = "App not found, maybe restricted (OEM or Geo)") : Exception() + data class AppNotFound(val reason: String = "App not found, maybe restricted (OEM or Geo)") : + Exception() data class AppNotSupported(val reason: String = "App not supported") : Exception() - data class EmptyDownloads(val reason: String = "File list empty") : Exception() //Not sure about the root cause. + data class EmptyDownloads(val reason: String = "File list empty") : + Exception() // Not sure about the root cause. data class Unknown(val reason: String = "¯\\_(ツ)_/¯") : Exception() data class Server(val code: Int = 500, val reason: String = "Server error") : Exception() -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/exceptions/AuthException.kt b/lib/src/main/java/com/aurora/gplayapi/exceptions/AuthException.kt index 7eeb0c3..7988b98 100644 --- a/lib/src/main/java/com/aurora/gplayapi/exceptions/AuthException.kt +++ b/lib/src/main/java/com/aurora/gplayapi/exceptions/AuthException.kt @@ -20,4 +20,4 @@ import java.io.IOException class AuthException(message: String?) : IOException(message) { var code = 0 var rawResponse: String = String() -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/exceptions/GooglePlayException.kt b/lib/src/main/java/com/aurora/gplayapi/exceptions/GooglePlayException.kt index cde0119..f9e96b5 100644 --- a/lib/src/main/java/com/aurora/gplayapi/exceptions/GooglePlayException.kt +++ b/lib/src/main/java/com/aurora/gplayapi/exceptions/GooglePlayException.kt @@ -20,4 +20,4 @@ import java.io.IOException class GooglePlayException(message: String?) : IOException(message) { var code = 0 var rawResponse: String = String() -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt index a544c35..0b76d71 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/AppDetailsHelper.kt @@ -29,8 +29,6 @@ import com.aurora.gplayapi.data.providers.HeaderProvider.getDefaultHeaders import com.aurora.gplayapi.exceptions.ApiException import com.aurora.gplayapi.network.IHttpClient import java.io.IOException -import java.util.* - class AppDetailsHelper(authData: AuthData) : BaseHelper(authData) { @@ -60,10 +58,12 @@ class AppDetailsHelper(authData: AuthData) : BaseHelper(authData) { if (subItem.hasAnnotations() && subItem.annotations.hasOverlayMetaData()) { if (subItem.annotations.overlayMetaData.hasOverlayTitle()) { devStream.title = subItem.annotations.overlayMetaData.overlayTitle.title - devStream.imgUrl = subItem.annotations.overlayMetaData.overlayTitle.compositeImage.url + devStream.imgUrl = + subItem.annotations.overlayMetaData.overlayTitle.compositeImage.url } if (subItem.annotations.overlayMetaData.hasOverlayDescription()) { - devStream.description = subItem.annotations.overlayMetaData.overlayDescription.description + devStream.description = + subItem.annotations.overlayMetaData.overlayDescription.description } } } @@ -106,13 +106,14 @@ class AppDetailsHelper(authData: AuthData) : BaseHelper(authData) { val bulkDetailsResponse = payload.bulkDetailsResponse for (entry in bulkDetailsResponse.entryList) { val app = AppBuilder.build(entry.item) - //System.out.printf("%s -> %s\n", app.displayName, app.packageName); + // System.out.printf("%s -> %s\n", app.displayName, app.packageName); appList.add(app) } } return appList - } else + } else { throw ApiException.Server(playResponse.code, playResponse.errorString) + } } fun getDetailsStream(streamUrl: String): StreamBundle { @@ -120,7 +121,7 @@ class AppDetailsHelper(authData: AuthData) : BaseHelper(authData) { val params: MutableMap = HashMap() val playResponse = httpClient.get( - "${GooglePlayApi.URL_FDFE}/${streamUrl}", + "${GooglePlayApi.URL_FDFE}/$streamUrl", headers, params ) @@ -171,19 +172,21 @@ class AppDetailsHelper(authData: AuthData) : BaseHelper(authData) { val payload = getPayLoadFromBytes(playResponse.responseBytes) payload.hasTestingProgramResponse() TestingProgramStatus().apply { - if (payload.hasTestingProgramResponse() - && payload.testingProgramResponse.hasResult() - && payload.testingProgramResponse.result.hasDetails() + if (payload.hasTestingProgramResponse() && + payload.testingProgramResponse.hasResult() && + payload.testingProgramResponse.result.hasDetails() ) { val details = payload.testingProgramResponse.result.details - if (details.hasSubscribed()) + if (details.hasSubscribed()) { subscribed = details.subscribed - if (details.hasUnsubscribed()) + } + if (details.hasUnsubscribed()) { unsubscribed = details.unsubscribed + } } } } else { TestingProgramStatus() } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt index 9e42565..97de6c3 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/AppSalesHelper.kt @@ -22,7 +22,7 @@ import com.aurora.gplayapi.data.models.sale.SaleBundle import com.aurora.gplayapi.network.IHttpClient import com.google.gson.Gson import java.io.IOException -import java.util.* +import java.util.Locale class AppSalesHelper(authData: AuthData) : BaseHelper(authData) { @@ -43,11 +43,14 @@ class AppSalesHelper(authData: AuthData) : BaseHelper(authData) { val playResponse = httpClient.get(GooglePlayApi.SALES_URL, headers = mapOf(), params) val saleBundle = Gson().fromJson(String(playResponse.responseBytes), SaleBundle::class.java) - return if (saleBundle.sales.isEmpty()) + return if (saleBundle.sales.isEmpty()) { listOf() - else { + } else { val appDetailsHelper = AppDetailsHelper(authData) - return appDetailsHelper.getAppByPackageName(packageList = saleBundle.sales.map { it.idandroid }.toList()) + return appDetailsHelper.getAppByPackageName( + packageList = saleBundle.sales.map { it.idandroid } + .toList() + ) } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt index f7d7404..c6e9a86 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/AuthHelper.kt @@ -21,7 +21,8 @@ import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.providers.DeviceInfoProvider import com.aurora.gplayapi.network.DefaultHttpClient import com.aurora.gplayapi.network.IHttpClient -import java.util.* +import java.util.Locale +import java.util.Properties class AuthHelper private constructor() { @@ -35,18 +36,20 @@ class AuthHelper private constructor() { fun build(email: String, aasToken: String): AuthData { val properties = DeviceManager.loadProperties("px_3a.properties") - if (properties != null) + if (properties != null) { return build(email, aasToken, properties) - else + } else { throw Exception("Unable to read device config") + } } fun build(email: String, aasToken: String, deviceName: String): AuthData { val properties = DeviceManager.loadProperties(deviceName) - if (properties != null) + if (properties != null) { return build(email, aasToken, properties) - else + } else { throw Exception("Unable to read device config") + } } fun build(email: String, aasToken: String, properties: Properties): AuthData { @@ -74,7 +77,7 @@ class AuthHelper private constructor() { val tosResponse = api.toc() - //Fetch UserProfile + // Fetch UserProfile authData.userProfile = UserProfileHelper(authData).getUserProfile() return authData @@ -86,7 +89,6 @@ class AuthHelper private constructor() { locale: Locale, deviceInfoProvider: DeviceInfoProvider ): AuthData { - val authData = AuthData(email, authToken, true) authData.deviceInfoProvider = deviceInfoProvider @@ -94,21 +96,21 @@ class AuthHelper private constructor() { val api = GooglePlayApi(authData) - //Android GSF ID + // Android GSF ID val gsfId = api.generateGsfId(deviceInfoProvider) authData.gsfId = gsfId - //Upload Device Config + // Upload Device Config val deviceConfigResponse = api.uploadDeviceConfig(deviceInfoProvider) authData.deviceConfigToken = deviceConfigResponse.uploadDeviceConfigToken - //GooglePlay TOS + // GooglePlay TOS val tosResponse = api.toc() - //Fetch UserProfile + // Fetch UserProfile authData.userProfile = UserProfileHelper(authData).getUserProfile() return authData } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt index cd05d24..1702fa0 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/AuthValidator.kt @@ -40,4 +40,4 @@ class AuthValidator(authData: AuthData) : BaseHelper(authData) { GET, POST } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt index 02d4001..375152d 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/BaseHelper.kt @@ -15,16 +15,31 @@ package com.aurora.gplayapi.helpers -import com.aurora.gplayapi.* +import com.aurora.gplayapi.BrowseResponse +import com.aurora.gplayapi.BulkDetailsRequest +import com.aurora.gplayapi.DetailsResponse +import com.aurora.gplayapi.GooglePlayApi +import com.aurora.gplayapi.Item +import com.aurora.gplayapi.ListResponse +import com.aurora.gplayapi.Payload +import com.aurora.gplayapi.PayloadApi +import com.aurora.gplayapi.ResponseWrapper +import com.aurora.gplayapi.ResponseWrapperApi +import com.aurora.gplayapi.SearchResponse +import com.aurora.gplayapi.SearchSuggestResponse import com.aurora.gplayapi.data.builders.AppBuilder.build -import com.aurora.gplayapi.data.models.* +import com.aurora.gplayapi.data.models.App +import com.aurora.gplayapi.data.models.Artwork +import com.aurora.gplayapi.data.models.AuthData +import com.aurora.gplayapi.data.models.PlayResponse +import com.aurora.gplayapi.data.models.StreamBundle +import com.aurora.gplayapi.data.models.StreamCluster import com.aurora.gplayapi.data.models.editor.EditorChoiceBundle import com.aurora.gplayapi.data.models.editor.EditorChoiceCluster import com.aurora.gplayapi.data.providers.HeaderProvider.getDefaultHeaders import com.aurora.gplayapi.network.DefaultHttpClient import com.aurora.gplayapi.network.IHttpClient import java.io.IOException -import java.util.* abstract class BaseHelper(protected var authData: AuthData) { @@ -33,7 +48,11 @@ abstract class BaseHelper(protected var authData: AuthData) { abstract fun using(httpClient: IHttpClient): BaseHelper @Throws(IOException::class) - fun getResponse(url: String, params: Map, headers: Map): PlayResponse { + fun getResponse( + url: String, + params: Map, + headers: Map + ): PlayResponse { return httpClient.get(url, headers, params) } @@ -80,13 +99,19 @@ abstract class BaseHelper(protected var authData: AuthData) { fun getPrefetchPayLoad(bytes: ByteArray?): Payload { val responseWrapper = ResponseWrapper.parseFrom(bytes) val payload = responseWrapper.payload - return if (responseWrapper.preFetchCount > 0 && ((payload.hasSearchResponse() - && payload.searchResponse.itemCount == 0) - || payload.hasListResponse() && payload.listResponse.itemCount == 0 - || payload.hasBrowseResponse()) + return if (responseWrapper.preFetchCount > 0 && ( + ( + payload.hasSearchResponse() && + payload.searchResponse.itemCount == 0 + ) || + payload.hasListResponse() && payload.listResponse.itemCount == 0 || + payload.hasBrowseResponse() + ) ) { responseWrapper.getPreFetch(0).response.payload - } else payload + } else { + payload + } } open fun getAppsFromItem(item: Item): MutableList { @@ -96,7 +121,7 @@ abstract class BaseHelper(protected var authData: AuthData) { if (subItem.type == 1) { val app = build(subItem) appList.add(app) - //System.out.printf("%s -> %s\n", app.displayName, app.packageName); + // System.out.printf("%s -> %s\n", app.displayName, app.packageName); } } } @@ -115,7 +140,9 @@ abstract class BaseHelper(protected var authData: AuthData) { val payload = getPayLoadFromBytes(bytes) return if (payload.hasSearchResponse()) { payload.searchResponse - } else null + } else { + null + } } @Throws(Exception::class) @@ -123,7 +150,9 @@ abstract class BaseHelper(protected var authData: AuthData) { val payload = getPayLoadFromBytes(bytes) return if (payload.hasSearchSuggestResponse()) { payload.searchSuggestResponse - } else null + } else { + null + } } /*--------------------------------------- GENERIC APP STREAMS --------------------------------------------*/ @@ -131,20 +160,22 @@ abstract class BaseHelper(protected var authData: AuthData) { fun getNextStreamResponse(nextPageUrl: String): ListResponse { val headers: Map = getDefaultHeaders(authData) val playResponse = httpClient.get(GooglePlayApi.URL_FDFE + "/" + nextPageUrl, headers) - return if (playResponse.isSuccessful) + return if (playResponse.isSuccessful) { getListResponseFromBytes(playResponse.responseBytes) - else + } else { ListResponse.getDefaultInstance() + } } @Throws(Exception::class) fun getBrowseStreamResponse(browseUrl: String): BrowseResponse { val headers: Map = getDefaultHeaders(authData) val playResponse = httpClient.get(GooglePlayApi.URL_FDFE + "/" + browseUrl, headers) - return if (playResponse.isSuccessful) + return if (playResponse.isSuccessful) { getBrowseResponseFromBytes(playResponse.responseBytes) - else + } else { BrowseResponse.getDefaultInstance() + } } @Throws(Exception::class) @@ -169,9 +200,11 @@ abstract class BaseHelper(protected var authData: AuthData) { } fun getStreamCluster(payload: Payload): StreamCluster { - return if (payload.hasListResponse()) + return if (payload.hasListResponse()) { getStreamCluster(payload.listResponse) - else StreamCluster() + } else { + StreamCluster() + } } fun getStreamCluster(listResponse: ListResponse): StreamCluster { @@ -261,13 +294,15 @@ abstract class BaseHelper(protected var authData: AuthData) { val browseUrl = getBrowseUrl(item) if (item.imageCount > 0) { item.imageList.forEach { - artworkList.add(Artwork().apply { - type = it.imageType - url = it.imageUrl - aspectRatio = it.dimension.aspectRatio - width = it.dimension.width - height = it.dimension.height - }) + artworkList.add( + Artwork().apply { + type = it.imageType + url = it.imageUrl + aspectRatio = it.dimension.aspectRatio + width = it.dimension.width + height = it.dimension.height + } + ) } } return EditorChoiceCluster().apply { @@ -312,4 +347,4 @@ abstract class BaseHelper(protected var authData: AuthData) { return editorChoiceBundles } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt index 95609d4..7830968 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/CategoryHelper.kt @@ -22,7 +22,6 @@ import com.aurora.gplayapi.data.models.Category import com.aurora.gplayapi.data.models.StreamBundle import com.aurora.gplayapi.data.providers.HeaderProvider import com.aurora.gplayapi.network.IHttpClient -import java.util.* class CategoryHelper(authData: AuthData) : BaseHelper(authData) { @@ -71,4 +70,4 @@ class CategoryHelper(authData: AuthData) : BaseHelper(authData) { category.type = type return category } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt index 2b1f506..b8b7eaa 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/ClusterHelper.kt @@ -20,7 +20,6 @@ import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.StreamCluster import com.aurora.gplayapi.data.providers.HeaderProvider.getDefaultHeaders import com.aurora.gplayapi.network.IHttpClient -import java.util.* class ClusterHelper(authData: AuthData) : BaseHelper(authData) { @@ -46,8 +45,9 @@ class ClusterHelper(authData: AuthData) : BaseHelper(authData) { return if (responseBody.isSuccessful) { val listResponse = getListResponseFromBytes(responseBody.responseBytes) getStreamCluster(listResponse) - } else + } else { StreamCluster() + } } enum class Type(var value: String) { @@ -55,4 +55,4 @@ class ClusterHelper(authData: AuthData) : BaseHelper(authData) { MY_APPS_LIBRARY("LIBRARY"), MY_APPS_UPDATES("UPDATES"); } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt index 5c4c238..1efe9d2 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/ExpandedBrowseHelper.kt @@ -61,4 +61,4 @@ class ExpandedBrowseHelper(authData: AuthData) : BaseHelper(authData) { } return appList } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt index a428664..642f4c8 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/LibraryHelper.kt @@ -15,7 +15,9 @@ package com.aurora.gplayapi.helpers -import com.aurora.gplayapi.* +import com.aurora.gplayapi.GooglePlayApi +import com.aurora.gplayapi.ListResponse +import com.aurora.gplayapi.ModifyLibraryRequest import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.providers.HeaderProvider.getDefaultHeaders @@ -57,12 +59,17 @@ class LibraryHelper(authData: AuthData) : BaseHelper(authData) { val builder = ModifyLibraryRequest.newBuilder() .setLibraryId("u-wl") - if (isAddRequest) + if (isAddRequest) { builder.addAddPackageName(packageName) - else + } else { builder.addRemovePackageName(packageName) + } - val playResponse = httpClient.post(GooglePlayApi.URL_MODIFY_LIBRARY, headers, builder.build().toByteArray()) + val playResponse = httpClient.post( + GooglePlayApi.URL_MODIFY_LIBRARY, + headers, + builder.build().toByteArray() + ) return playResponse.isSuccessful } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt index b71157f..65e24c9 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/PurchaseHelper.kt @@ -15,8 +15,12 @@ package com.aurora.gplayapi.helpers -import com.aurora.gplayapi.* +import com.aurora.gplayapi.BuyResponse import com.aurora.gplayapi.Constants.PATCH_FORMAT +import com.aurora.gplayapi.DeliveryResponse +import com.aurora.gplayapi.GooglePlayApi +import com.aurora.gplayapi.ListResponse +import com.aurora.gplayapi.ResponseWrapper import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.File @@ -24,7 +28,6 @@ import com.aurora.gplayapi.data.providers.HeaderProvider import com.aurora.gplayapi.exceptions.ApiException import com.aurora.gplayapi.network.IHttpClient import java.io.IOException -import java.util.* class PurchaseHelper(authData: AuthData) : BaseHelper(authData) { @@ -49,11 +52,12 @@ class PurchaseHelper(authData: AuthData) : BaseHelper(authData) { for (item in listResponse.itemList) { for (subItem in item.subItemList) { if (item.subItemCount > 0) { - if (item.hasAnnotations() - && item.annotations.hasPurchaseHistoryDetails() - && item.annotations.purchaseHistoryDetails.hasPurchaseStatus() - ) + if (item.hasAnnotations() && + item.annotations.hasPurchaseHistoryDetails() && + item.annotations.purchaseHistoryDetails.hasPurchaseStatus() + ) { continue + } purchaseAppList.addAll(getAppsFromItem(subItem)) } } @@ -97,7 +101,6 @@ class PurchaseHelper(authData: AuthData) : BaseHelper(authData) { ), downloadToken: String ): DeliveryResponse { - val params: MutableMap = HashMap() params["ot"] = offerType.toString() params["doc"] = packageName @@ -113,7 +116,11 @@ class PurchaseHelper(authData: AuthData) : BaseHelper(authData) { } val playResponse = - httpClient.get(GooglePlayApi.DELIVERY_URL, HeaderProvider.getDefaultHeaders(authData), params) + httpClient.get( + GooglePlayApi.DELIVERY_URL, + HeaderProvider.getDefaultHeaders(authData), + params + ) val payload = ResponseWrapper.parseFrom(playResponse.responseBytes).payload return payload.deliveryResponse } @@ -131,10 +138,13 @@ class PurchaseHelper(authData: AuthData) : BaseHelper(authData) { when (deliveryResponse.status) { 1 -> return getDownloadsFromDeliveryResponse(packageName, versionCode, deliveryResponse) + 2 -> throw ApiException.AppNotSupported() + 3 -> throw ApiException.AppNotPurchased() + else -> throw ApiException.Unknown() } @@ -147,49 +157,56 @@ class PurchaseHelper(authData: AuthData) : BaseHelper(authData) { ): List { val fileList: MutableList = mutableListOf() if (deliveryResponse != null) { - //Add base apk + // Add base apk val androidAppDeliveryData = deliveryResponse.appDeliveryData if (androidAppDeliveryData != null) { - fileList.add(File().apply { - name = "${packageName}.apk" - url = androidAppDeliveryData.downloadUrl - size = androidAppDeliveryData.downloadSize - type = File.FileType.BASE - }) - - //Obb & patches (if any) + fileList.add( + File().apply { + name = "$packageName.apk" + url = androidAppDeliveryData.downloadUrl + size = androidAppDeliveryData.downloadSize + type = File.FileType.BASE + } + ) + + // Obb & patches (if any) val fileMetadataList = deliveryResponse.appDeliveryData.additionalFileList if (fileMetadataList != null) { for (appFileMetadata in fileMetadataList) { val isOBB = appFileMetadata.fileType == 0 val fileType = if (isOBB) "main" else "patch" - fileList.add(File().apply { - name = "$fileType.$versionCode.$packageName.obb" - url = appFileMetadata.downloadUrl - size = appFileMetadata.size - type = if (isOBB) File.FileType.OBB else File.FileType.PATCH - }) + fileList.add( + File().apply { + name = "$fileType.$versionCode.$packageName.obb" + url = appFileMetadata.downloadUrl + size = appFileMetadata.size + type = if (isOBB) File.FileType.OBB else File.FileType.PATCH + } + ) } } - //Add split apks (if any) + // Add split apks (if any) val splitDeliveryDataList = deliveryResponse.appDeliveryData.splitDeliveryDataList if (fileMetadataList != null) { for (splitDeliveryData in splitDeliveryDataList) { - fileList.add(File().apply { - name = "${splitDeliveryData.name}.apk" - url = splitDeliveryData.downloadUrl - size = splitDeliveryData.downloadSize - type = File.FileType.SPLIT - }) + fileList.add( + File().apply { + name = "${splitDeliveryData.name}.apk" + url = splitDeliveryData.downloadUrl + size = splitDeliveryData.downloadSize + type = File.FileType.SPLIT + } + ) } } } } - if (fileList.isEmpty()) + if (fileList.isEmpty()) { throw ApiException.Unknown() + } return fileList } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt index e043994..7c2bb44 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/ReviewsHelper.kt @@ -23,7 +23,6 @@ import com.aurora.gplayapi.data.models.Review import com.aurora.gplayapi.data.models.ReviewCluster import com.aurora.gplayapi.data.providers.HeaderProvider.getDefaultHeaders import com.aurora.gplayapi.network.IHttpClient -import java.util.* class ReviewsHelper(authData: AuthData) : BaseHelper(authData) { @@ -44,10 +43,11 @@ class ReviewsHelper(authData: AuthData) : BaseHelper(authData) { ): ReviewResponse? { val responseBody = getResponse(url, params, headers) val payload = getPayLoadFromBytes(responseBody.responseBytes) - return if (payload.hasReviewResponse()) + return if (payload.hasReviewResponse()) { payload.reviewResponse - else + } else { null + } } @Throws(Exception::class) @@ -58,14 +58,18 @@ class ReviewsHelper(authData: AuthData) : BaseHelper(authData) { ): ReviewResponse? { val responseBody = getResponse(url, params, headers) val payload = getPayLoadFromBytes(responseBody.responseBytes) - return if (payload.hasReviewSummaryResponse()) + return if (payload.hasReviewSummaryResponse()) { payload.reviewSummaryResponse - else + } else { null + } } @Throws(Exception::class) - private fun postReviewResponse(params: Map, headers: Map): ReviewResponse? { + private fun postReviewResponse( + params: Map, + headers: Map + ): ReviewResponse? { val playResponse = httpClient.post(GooglePlayApi.URL_REVIEW_ADD_EDIT, headers, params) val payload = getPayLoadFromBytes(playResponse.responseBytes) return if (payload.hasReviewResponse()) payload.reviewResponse else null @@ -116,7 +120,8 @@ class ReviewsHelper(authData: AuthData) : BaseHelper(authData) { params["doc"] = packageName val headers: MutableMap = getDefaultHeaders(authData) - val reviewResponse = getReviewSummaryResponse("${GooglePlayApi.URL_FDFE}/reviewSummary", params, headers) + val reviewResponse = + getReviewSummaryResponse("${GooglePlayApi.URL_FDFE}/reviewSummary", params, headers) return getReviewCluster(reviewResponse).reviewList } @@ -139,7 +144,13 @@ class ReviewsHelper(authData: AuthData) : BaseHelper(authData) { } @Throws(Exception::class) - fun addOrEditReview(packageName: String, title: String, content: String, rating: Int, isBeta: Boolean): Review? { + fun addOrEditReview( + packageName: String, + title: String, + content: String, + rating: Int, + isBeta: Boolean + ): Review? { val params: MutableMap = HashMap() params["doc"] = packageName params["title"] = title @@ -162,7 +173,8 @@ class ReviewsHelper(authData: AuthData) : BaseHelper(authData) { fun next(nextPageUrl: String): ReviewCluster { val headers: MutableMap = getDefaultHeaders(authData) - val reviewResponse = getReviewResponse("${GooglePlayApi.URL_FDFE}/${nextPageUrl}", mapOf(), headers) + val reviewResponse = + getReviewResponse("${GooglePlayApi.URL_FDFE}/$nextPageUrl", mapOf(), headers) return getReviewCluster(reviewResponse) } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt index 2f94e07..28556c7 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/SearchHelper.kt @@ -27,7 +27,6 @@ import com.aurora.gplayapi.data.models.SearchBundle import com.aurora.gplayapi.data.models.SearchBundle.SubBundle import com.aurora.gplayapi.data.providers.HeaderProvider.getDefaultHeaders import com.aurora.gplayapi.network.IHttpClient -import java.util.* class SearchHelper(authData: AuthData) : BaseHelper(authData) { @@ -38,10 +37,12 @@ class SearchHelper(authData: AuthData) : BaseHelper(authData) { val nextPageUrl = item.containerMetadata.nextPageUrl if (nextPageUrl.isNotBlank()) { if (nextPageUrl.contains(searchTypeExtra)) { - if (nextPageUrl.startsWith("getCluster?enpt=CkC")) + if (nextPageUrl.startsWith("getCluster?enpt=CkC")) { return SubBundle(nextPageUrl, SearchBundle.Type.SIMILAR) - if (nextPageUrl.startsWith("getCluster?enpt=CkG")) + } + if (nextPageUrl.startsWith("getCluster?enpt=CkG")) { return SubBundle(nextPageUrl, SearchBundle.Type.RELATED_TO_YOUR_SEARCH) + } } else { return SubBundle(nextPageUrl, SearchBundle.Type.GENERIC) } @@ -71,7 +72,9 @@ class SearchHelper(authData: AuthData) : BaseHelper(authData) { val searchSuggestResponse = getSearchSuggestResponseFromBytes(responseBody.responseBytes) return if (searchSuggestResponse != null && searchSuggestResponse.entryCount > 0) { searchSuggestResponse.entryList - } else ArrayList() + } else { + ArrayList() + } } @Throws(Exception::class) @@ -125,13 +128,14 @@ class SearchHelper(authData: AuthData) : BaseHelper(authData) { for (item in itemList) { if (item.subItemCount > 0) { for (subItem in item.subItemList) { - //Filter out only apps, discard other items (Music, Ebooks, Movies) + // Filter out only apps, discard other items (Music, Ebooks, Movies) if (subItem.type == 45) { if (subItem.title.isEmpty() || subItem.title == "Apps") { appList.addAll(getAppsFromItem(subItem)) } else { - if (subItem.title.isNotEmpty()) + if (subItem.title.isNotEmpty()) { continue // Filter out `You Might Also Like` & `Related Apps` + } appList.add(AppBuilder.build(subItem)) } } @@ -143,4 +147,4 @@ class SearchHelper(authData: AuthData) : BaseHelper(authData) { searchBundle.appList = appList return searchBundle } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt index febdfca..04f7c08 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/StreamHelper.kt @@ -22,7 +22,6 @@ import com.aurora.gplayapi.data.models.StreamBundle import com.aurora.gplayapi.data.models.editor.EditorChoiceBundle import com.aurora.gplayapi.data.providers.HeaderProvider.getDefaultHeaders import com.aurora.gplayapi.network.IHttpClient -import java.util.* class StreamHelper(authData: AuthData) : BaseHelper(authData) { @@ -56,16 +55,19 @@ class StreamHelper(authData: AuthData) : BaseHelper(authData) { if (type == Type.EARLY_ACCESS) { params["ct"] = "1" } else { - if (category != Category.NONE) + if (category != Category.NONE) { params["cat"] = category.value + } } - val playResponse = httpClient.get(GooglePlayApi.URL_FDFE + "/" + type.value, headers, params) + val playResponse = + httpClient.get(GooglePlayApi.URL_FDFE + "/" + type.value, headers, params) - return if (playResponse.isSuccessful) + return if (playResponse.isSuccessful) { getListResponseFromBytes(playResponse.responseBytes) - else + } else { ListResponse.getDefaultInstance() + } } enum class Category(var value: String) { @@ -83,4 +85,4 @@ class StreamHelper(authData: AuthData) : BaseHelper(authData) { SUB_NAV("subnavHome"), TOP_CHART("topChartsStream"); } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt index 083d054..5120550 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/TopChartsHelper.kt @@ -20,7 +20,6 @@ import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.StreamCluster import com.aurora.gplayapi.data.providers.HeaderProvider.getDefaultHeaders import com.aurora.gplayapi.network.IHttpClient -import java.util.* class TopChartsHelper(authData: AuthData) : BaseHelper(authData) { @@ -40,8 +39,9 @@ class TopChartsHelper(authData: AuthData) : BaseHelper(authData) { return if (playResponse.isSuccessful) { val listResponse = getListResponseFromBytes(playResponse.responseBytes) getStreamCluster(listResponse) - } else + } else { StreamCluster() + } } enum class Chart(var value: String) { @@ -55,4 +55,4 @@ class TopChartsHelper(authData: AuthData) : BaseHelper(authData) { GAME("GAME"), APPLICATION("APPLICATION"); } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt index 70e3493..c6bd9e8 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/UserProfileHelper.kt @@ -50,4 +50,4 @@ class UserProfileHelper(authData: AuthData) : BaseHelper(authData) { null } } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt b/lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt index 432a2f6..d1943ea 100644 --- a/lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt +++ b/lib/src/main/java/com/aurora/gplayapi/network/DefaultHttpClient.kt @@ -17,11 +17,16 @@ package com.aurora.gplayapi.network import com.aurora.gplayapi.data.models.PlayResponse import com.github.kittinunf.fuel.Fuel -import com.github.kittinunf.fuel.core.* -import java.nio.charset.Charset +import com.github.kittinunf.fuel.core.Headers +import com.github.kittinunf.fuel.core.Request +import com.github.kittinunf.fuel.core.Response +import com.github.kittinunf.fuel.core.isClientError +import com.github.kittinunf.fuel.core.isServerError +import com.github.kittinunf.fuel.core.isSuccessful import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import java.nio.charset.Charset object DefaultHttpClient : IHttpClient { @@ -34,27 +39,27 @@ object DefaultHttpClient : IHttpClient { } override fun get( - url: String, - headers: Map, - params: Map + url: String, + headers: Map, + params: Map ): PlayResponse { val parameters = params - .map { it.key to it.value } - .toList() + .map { it.key to it.value } + .toList() val (request, response, result) = Fuel.get(url, parameters) - .header(headers) - .response() + .header(headers) + .response() return buildPlayResponse(response, request) } override fun get( - url: String, - headers: Map, - paramString: String + url: String, + headers: Map, + paramString: String ): PlayResponse { val (request, response, result) = Fuel.get(url + paramString) - .header(headers) - .response() + .header(headers) + .response() return buildPlayResponse(response, request) } @@ -74,31 +79,30 @@ object DefaultHttpClient : IHttpClient { override fun post(url: String, headers: Map, body: ByteArray): PlayResponse { val (request, response, result) = Fuel.post(url) - .header(headers) - .appendHeader(Headers.CONTENT_TYPE, "application/x-protobuf") - .body(body, Charset.defaultCharset()) - .response() + .header(headers) + .appendHeader(Headers.CONTENT_TYPE, "application/x-protobuf") + .body(body, Charset.defaultCharset()) + .response() return buildPlayResponse(response, request) } override fun post( - url: String, - headers: Map, - params: Map + url: String, + headers: Map, + params: Map ): PlayResponse { val parameters = params - .map { it.key to it.value } - .toList() + .map { it.key to it.value } + .toList() val (request, response, result) = Fuel.post(url, parameters) - .header(headers) - .response() + .header(headers) + .response() return buildPlayResponse(response, request) } @JvmStatic private fun buildPlayResponse(response: Response, request: Request): PlayResponse { return PlayResponse().apply { - if (response.isSuccessful) { responseBytes = response.body().toByteArray() } diff --git a/lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt b/lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt index da3a5f3..3e3e3ba 100644 --- a/lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt +++ b/lib/src/main/java/com/aurora/gplayapi/network/IHttpClient.kt @@ -16,8 +16,8 @@ package com.aurora.gplayapi.network import com.aurora.gplayapi.data.models.PlayResponse -import java.io.IOException import kotlinx.coroutines.flow.StateFlow +import java.io.IOException interface IHttpClient { val responseCode: StateFlow -- GitLab From 341402048d6a50e1ef0d88e003f6d1c0335cf28c Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 5 Jul 2023 21:10:29 +0530 Subject: [PATCH 28/82] Make App class Parcelable This allows users using navigation component to pass the object easily without extra work Signed-off-by: Aayush Gupta --- build.gradle | 1 + lib/build.gradle | 1 + .../com/aurora/gplayapi/data/models/App.kt | 113 +++++++++--------- .../aurora/gplayapi/data/models/Artwork.kt | 17 ++- .../com/aurora/gplayapi/data/models/File.kt | 14 ++- .../com/aurora/gplayapi/data/models/Rating.kt | 6 +- .../com/aurora/gplayapi/data/models/Review.kt | 21 ++-- .../gplayapi/data/models/details/AppInfo.kt | 8 +- .../gplayapi/data/models/details/Badge.kt | 18 +-- .../gplayapi/data/models/details/Chip.kt | 10 +- .../data/models/details/Dependencies.kt | 15 ++- .../data/models/details/TestingProgram.kt | 24 ++-- .../data/models/editor/EditorChoiceReason.kt | 6 +- 13 files changed, 150 insertions(+), 104 deletions(-) diff --git a/build.gradle b/build.gradle index fdd5582..927fd4d 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,7 @@ plugins { id 'com.android.library' version '8.0.1' apply false id 'org.jetbrains.kotlin.android' version '1.8.21' apply false + id 'org.jetbrains.kotlin.plugin.parcelize' version '1.8.21' apply false id 'com.google.protobuf' version '0.9.1' apply false id 'org.jlleitschuh.gradle.ktlint' version '11.4.0' apply false } diff --git a/lib/build.gradle b/lib/build.gradle index 7a9222a..56dfd03 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.android.library' id 'org.jetbrains.kotlin.android' + id 'org.jetbrains.kotlin.plugin.parcelize' id 'com.google.protobuf' id 'maven-publish' id 'org.jlleitschuh.gradle.ktlint' diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/App.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/App.kt index 898e7e1..9090d9a 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/App.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/App.kt @@ -15,6 +15,7 @@ package com.aurora.gplayapi.data.models +import android.os.Parcelable import com.aurora.gplayapi.Constants.Restriction import com.aurora.gplayapi.data.models.details.AppInfo import com.aurora.gplayapi.data.models.details.Badge @@ -22,62 +23,66 @@ import com.aurora.gplayapi.data.models.details.Chip import com.aurora.gplayapi.data.models.details.Dependencies import com.aurora.gplayapi.data.models.details.TestingProgram import com.aurora.gplayapi.data.models.editor.EditorChoiceReason +import kotlinx.parcelize.Parcelize -class App(var packageName: String) { - var id: Int = 0 - var appInfo: AppInfo = AppInfo() - var categoryArtwork: Artwork = Artwork() - var categoryId: Int = 0 - var categoryName: String = String() - var categoryStreamUrl: String? = String() - var changes: String = String() - var chips: MutableList = mutableListOf() - var containsAds = false - var coverArtwork: Artwork = Artwork() - var dependencies: Dependencies = Dependencies() - var description: String = String() - var detailsStreamUrl: String? = String() - var detailsPostAcquireStreamUrl: String? = String() - var developerAddress: String = String() - var developerEmail: String = String() - var developerName: String = String() - var developerWebsite: String = String() - var displayBadges: MutableList = mutableListOf() - var displayName: String = String() - var editorReason: EditorChoiceReason? = null - var downloadString: String = String() - var earlyAccess = false - var fileList: MutableList = mutableListOf() - var footerHtml: String = String() - var iconArtwork: Artwork = Artwork() - var infoBadges: MutableList = mutableListOf() - var inPlayStore = false - var installs: Long = 0 - var instantAppLink: String = String() - var isFree = false - var isInstalled = false - var isSystem = false - var labeledRating: String = String() - var liveStreamUrl: String? = String() - var offerDetails: MutableMap = mutableMapOf() - var offerType = 0 - var permissions: MutableList = mutableListOf() - var price: String = String() - var promotionStreamUrl: String? = String() - var rating: Rating = Rating() - var relatedLinks: MutableMap = mutableMapOf() - var restriction: Restriction = Restriction.NOT_RESTRICTED - var screenshots: MutableList = mutableListOf() - var shareUrl: String = String() - var shortDescription: String = String() - var size: Long = 0 - var targetSdk: Int = 21 - var testingProgram: TestingProgram? = null - var userReview: Review = Review() - var updatedOn: String = String() - var versionCode: Int = 0 - var versionName: String = String() +@Parcelize +data class App( + var packageName: String, + var id: Int = 0, + var appInfo: AppInfo = AppInfo(), + var categoryArtwork: Artwork = Artwork(), + var categoryId: Int = 0, + var categoryName: String = String(), + var categoryStreamUrl: String? = String(), + var changes: String = String(), + var chips: MutableList = mutableListOf(), + var containsAds: Boolean = false, + var coverArtwork: Artwork = Artwork(), + var dependencies: Dependencies = Dependencies(), + var description: String = String(), + var detailsStreamUrl: String? = String(), + var detailsPostAcquireStreamUrl: String? = String(), + var developerAddress: String = String(), + var developerEmail: String = String(), + var developerName: String = String(), + var developerWebsite: String = String(), + var displayBadges: MutableList = mutableListOf(), + var displayName: String = String(), + var editorReason: EditorChoiceReason? = null, + var downloadString: String = String(), + var earlyAccess: Boolean = false, + var fileList: MutableList = mutableListOf(), + var footerHtml: String = String(), + var iconArtwork: Artwork = Artwork(), + var infoBadges: MutableList = mutableListOf(), + var inPlayStore: Boolean = false, + var installs: Long = 0, + var instantAppLink: String = String(), + var isFree: Boolean = false, + var isInstalled: Boolean = false, + var isSystem: Boolean = false, + var labeledRating: String = String(), + var liveStreamUrl: String? = String(), + var offerDetails: MutableMap = mutableMapOf(), + var offerType: Int = 0, + var permissions: MutableList = mutableListOf(), + var price: String = String(), + var promotionStreamUrl: String? = String(), + var rating: Rating = Rating(), + var relatedLinks: MutableMap = mutableMapOf(), + var restriction: Restriction = Restriction.NOT_RESTRICTED, + var screenshots: MutableList = mutableListOf(), + var shareUrl: String = String(), + var shortDescription: String = String(), + var size: Long = 0, + var targetSdk: Int = 21, + var testingProgram: TestingProgram? = null, + var userReview: Review = Review(), + var updatedOn: String = String(), + var versionCode: Int = 0, + var versionName: String = String(), var videoArtwork: Artwork = Artwork() +) : Parcelable { override fun hashCode(): Int { return packageName.hashCode() diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt index cd00eed..2b8607c 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/Artwork.kt @@ -15,13 +15,18 @@ package com.aurora.gplayapi.data.models -class Artwork { - var type: Int = 0 - var url: String = String() - var urlAlt: String = String() - var aspectRatio: Int = 0 - var width: Int = 0 +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class Artwork( + var type: Int = 0, + var url: String = String(), + var urlAlt: String = String(), + var aspectRatio: Int = 0, + var width: Int = 0, var height: Int = 0 +) : Parcelable { override fun hashCode(): Int { return url.hashCode() diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/File.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/File.kt index 05948f6..3e49edf 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/File.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/File.kt @@ -15,14 +15,18 @@ package com.aurora.gplayapi.data.models +import android.os.Parcelable +import kotlinx.parcelize.Parcelize import java.util.UUID -class File { - var id: String = UUID.randomUUID().toString() - var name: String = String() - var url: String = String() - var size: Long = 0L +@Parcelize +data class File( + var id: String = UUID.randomUUID().toString(), + var name: String = String(), + var url: String = String(), + var size: Long = 0L, var type: FileType = FileType.BASE +) : Parcelable { enum class FileType { BASE, OBB, PATCH, SPLIT diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt index 6f2ba63..78f19ac 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/Rating.kt @@ -15,6 +15,10 @@ package com.aurora.gplayapi.data.models +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize data class Rating( var average: Float = 0f, var oneStar: Long = 0L, @@ -26,4 +30,4 @@ data class Rating( var thumbsDown: Long = 0L, var label: String = String(), var abbreviatedLabel: String = String() -) +) : Parcelable diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/Review.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/Review.kt index 0fbe3c3..b867405 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/Review.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/Review.kt @@ -15,15 +15,20 @@ package com.aurora.gplayapi.data.models -class Review { - var title: String = String() - var comment: String = String() - var commentId: String = String() - var userName: String = String() - var userPhotoUrl: String = String() - var appVersion: String = String() - var rating: Int = 0 +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class Review( + var title: String = String(), + var comment: String = String(), + var commentId: String = String(), + var userName: String = String(), + var userPhotoUrl: String = String(), + var appVersion: String = String(), + var rating: Int = 0, var timeStamp: Long = 0L +) : Parcelable { override fun hashCode(): Int { return commentId.hashCode() diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt index 1d86b82..b8fbdf0 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/AppInfo.kt @@ -15,6 +15,8 @@ package com.aurora.gplayapi.data.models.details -class AppInfo { - var appInfoMap: MutableMap = mutableMapOf() -} +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class AppInfo(var appInfoMap: MutableMap = mutableMapOf()) : Parcelable diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt index 09e1db6..850c790 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Badge.kt @@ -15,17 +15,21 @@ package com.aurora.gplayapi.data.models.details +import android.os.Parcelable import com.aurora.gplayapi.data.models.Artwork +import kotlinx.parcelize.Parcelize import java.util.UUID -class Badge { - var id: String = UUID.randomUUID().toString() - var textMajor: String = String() - var textMinor: String = String() - var textMinorHtml: String? = String() - var textDescription: String? = String() - var artwork: Artwork? = null +@Parcelize +data class Badge( + var id: String = UUID.randomUUID().toString(), + var textMajor: String = String(), + var textMinor: String = String(), + var textMinorHtml: String? = String(), + var textDescription: String? = String(), + var artwork: Artwork? = null, var link: String = String() +) : Parcelable { override fun equals(other: Any?): Boolean { return when (other) { diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt index c02bcc1..2096270 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Chip.kt @@ -15,12 +15,16 @@ package com.aurora.gplayapi.data.models.details +import android.os.Parcelable +import kotlinx.parcelize.Parcelize import java.util.UUID -class Chip { - var id: String = UUID.randomUUID().toString() - var title: String = String() +@Parcelize +data class Chip( + var id: String = UUID.randomUUID().toString(), + var title: String = String(), var streamUrl: String? = String() +) : Parcelable { override fun hashCode(): Int { return id.hashCode() diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt index feb0051..893ae10 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/Dependencies.kt @@ -15,12 +15,15 @@ package com.aurora.gplayapi.data.models.details +import android.os.Parcelable import com.aurora.gplayapi.data.models.App +import kotlinx.parcelize.Parcelize -class Dependencies { - var dependentPackages = mutableListOf() - var dependentSplits = mutableListOf() - var dependentLibraries = mutableListOf() - var targetSDK: Int = -1 +@Parcelize +data class Dependencies( + var dependentPackages: MutableList = mutableListOf(), + var dependentSplits: MutableList = mutableListOf(), + var dependentLibraries: MutableList = mutableListOf(), + var targetSDK: Int = -1, var totalSize: Long = -1L -} +) : Parcelable diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt index 7d7a81a..3dffb18 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/details/TestingProgram.kt @@ -15,18 +15,22 @@ package com.aurora.gplayapi.data.models.details +import android.os.Parcelable import com.aurora.gplayapi.data.models.Artwork +import kotlinx.parcelize.Parcelize -class TestingProgram { - var artwork: Artwork = Artwork() - var displayName: String = String() - var email: String = String() - var isAvailable: Boolean = false - var isSubscribed: Boolean = false +@Parcelize +data class TestingProgram( + var artwork: Artwork = Artwork(), + var displayName: String = String(), + var email: String = String(), + var isAvailable: Boolean = false, + var isSubscribed: Boolean = false, var isSubscribedAndInstalled: Boolean = false -} +) : Parcelable -class TestingProgramStatus { - var subscribed: Boolean = false +@Parcelize +data class TestingProgramStatus( + var subscribed: Boolean = false, var unsubscribed: Boolean = false -} +) : Parcelable diff --git a/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt index d5d0e6f..829aad3 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/models/editor/EditorChoiceReason.kt @@ -15,4 +15,8 @@ package com.aurora.gplayapi.data.models.editor -data class EditorChoiceReason(var bulletins: List, var description: String) +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class EditorChoiceReason(var bulletins: List, var description: String) : Parcelable -- GitLab From eb95dc0a182db0196d7f3157c6f2e022e6117b84 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 5 Jul 2023 23:38:36 +0530 Subject: [PATCH 29/82] 3.1.4 Signed-off-by: Aayush Gupta --- CHANGELOG.md | 6 ++++++ lib/build.gradle | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f4814b..97295be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Changelog : v3.1.4 +• Add Google Pixel Tablet spoofing configuration +• Bump minimum compile SDK to API 21 +• Enable and compile with java language 17 features +• Make App class parcelable + Changelog : v3.1.3 • Implement shared library dependencies API diff --git a/lib/build.gradle b/lib/build.gradle index 56dfd03..21e2855 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -68,7 +68,7 @@ publishing { release(MavenPublication) { groupId = 'com.aurora' artifactId = 'gplayapi' - version = '3.1.3' + version = '3.1.4' afterEvaluate { from components.release -- GitLab From 7c98ab8826ed276c0e1d32f3ce020f0b45b685af Mon Sep 17 00:00:00 2001 From: Rahul Patel Date: Tue, 27 Jun 2023 22:43:30 +0530 Subject: [PATCH 30/82] WebSearch [1/3] --- .gitignore | 1 + .../java/com/aurora/gplayapi/Constants.kt | 5 ++ .../gplayapi/data/builders/WebAppBuilder.kt | 28 ++++++++++ .../gplayapi/data/builders/rpc/RpcBuilder.kt | 30 +++++++++++ .../data/builders/rpc/SearchQueryBuilder.kt | 13 +++++ .../com/aurora/gplayapi/helpers/WebClient.kt | 52 +++++++++++++++++++ .../gplayapi/helpers/WebSearchHelper.kt | 42 +++++++++++++++ .../com/aurora/gplayapi/utils/Extensions.kt | 23 ++++++++ 8 files changed, 194 insertions(+) create mode 100644 lib/src/main/java/com/aurora/gplayapi/data/builders/WebAppBuilder.kt create mode 100644 lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/RpcBuilder.kt create mode 100644 lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/SearchQueryBuilder.kt create mode 100644 lib/src/main/java/com/aurora/gplayapi/helpers/WebClient.kt create mode 100644 lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchHelper.kt create mode 100644 lib/src/main/java/com/aurora/gplayapi/utils/Extensions.kt diff --git a/.gitignore b/.gitignore index 99e9ae4..69cdb75 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ gradle-app.setting /request.* /local.properties /src/main/java/com/aurora/gplayapi/tests/* +/lib/src/test/java/com/aurora/gplayapi/* okhttp_cache/ # MAC OSX system files diff --git a/lib/src/main/java/com/aurora/gplayapi/Constants.kt b/lib/src/main/java/com/aurora/gplayapi/Constants.kt index daf585a..9261eff 100644 --- a/lib/src/main/java/com/aurora/gplayapi/Constants.kt +++ b/lib/src/main/java/com/aurora/gplayapi/Constants.kt @@ -62,4 +62,9 @@ object Constants { } } } + + enum class COLLECTION(var value: Array) { + QUERY(arrayOf(0, 1, 1, 21, 0)), + SIMILAR(arrayOf(0, 1, 2, 22, 0)) + } } diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/WebAppBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/WebAppBuilder.kt new file mode 100644 index 0000000..3416679 --- /dev/null +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/WebAppBuilder.kt @@ -0,0 +1,28 @@ +package com.aurora.gplayapi.data.builders + +import com.aurora.gplayapi.data.models.App +import com.aurora.gplayapi.data.models.Artwork +import com.aurora.gplayapi.utils.dig + +object WebAppBuilder { + + fun build(data: Any): App { + val app = App(data.dig(0, 0)) + app.displayName = data.dig(3) + app.description = data.dig(13, 1) + app.developerName = data.dig(14) + app.downloadString = data.dig(15) + app.categoryName = data.dig(5) + app.iconArtwork = Artwork().apply { + url = data.dig(1, 3, 2) + type = 1 + } + app.coverArtwork = Artwork().apply { + url = data.dig(22, 3, 2) + } + app.labeledRating = data.dig(4, 0) + app.isFree = data.dig(25, 0, 0, 0, 0, 1, 0, 2).isEmpty() == true + + return app + } +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/RpcBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/RpcBuilder.kt new file mode 100644 index 0000000..ff4d500 --- /dev/null +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/RpcBuilder.kt @@ -0,0 +1,30 @@ +package com.aurora.gplayapi.data.builders.rpc + +import com.aurora.gplayapi.utils.dig +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +object RpcBuilder { + fun wrapResponse(input: String): HashMap?> { + val lines = input.lines() + val filteredLines = lines.filter { it.startsWith("[[\"wrb.fr") } + val result = HashMap?>() + + filteredLines.forEach { + val jaggedProto = parseJaggedString(it) + val (type, packageName) = (jaggedProto.dig(0, 6) as String).split("@") + + result[type] = hashMapOf( + packageName to parseJaggedString(jaggedProto.dig(0, 2)) + ) + } + + return result + } + + private fun parseJaggedString(input: String): Collection { + val gson = Gson() + val arrayType = object : TypeToken>() {}.type + return gson.fromJson(input, arrayType) + } +} diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/SearchQueryBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/SearchQueryBuilder.kt new file mode 100644 index 0000000..e9f5cc5 --- /dev/null +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/SearchQueryBuilder.kt @@ -0,0 +1,13 @@ +package com.aurora.gplayapi.data.builders.rpc + +object SearchQueryBuilder { + public val TAG = javaClass.name + fun build(query: String, tag: String = TAG): String { + return """ + ["lGYRle","[[[],[[8,[20,50]],null,null,[96,108,72,100,27,183,8,57,169,110,11,184,16,1,139,152,194,165,68,163,211,9,71,31,195,12,64,151,150,148,113,104,55,56,145,32,34,10,122],[],null,null,[[[1,2],[10,8,9]]]],[\"$query\"],4,[null,1],null,null,[],[1]],[1]]",null,"$tag@$query"] + """ + .trimStart() + .trimEnd() + .trimIndent() + } +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/WebClient.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/WebClient.kt new file mode 100644 index 0000000..fba8ad9 --- /dev/null +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/WebClient.kt @@ -0,0 +1,52 @@ +/* + * GPlayApi + * Copyright (C) 2020 Aurora OSS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +package com.aurora.gplayapi.helpers + +import com.github.kittinunf.fuel.httpPost +import com.github.kittinunf.result.Result + +class WebClient { + + fun fetch(rpcRequests: Array): String { + val url = "https://play.google.com/_/PlayStoreUi/data/batchexecute" + val requestsBody = buildFRequest(rpcRequests) + + val (_, _, result) = url + .httpPost() + .header("Content-Type" to "application/x-www-form-urlencoded;charset=utf-8") + .header("Origin" to "https://play.google.com") + .body(requestsBody) + .responseString() + + return when (result) { + is Result.Success -> result.get() + is Result.Failure -> { + throw Exception("Kuchh toh gadbad hai Daya!") + } + } + } + + private fun buildFRequest(rpcRequests: Array): String { + return """ + f.req=[[ + ${rpcRequests.joinToString(separator = ",")} + ]] + """ + .trimStart() + .trimEnd() + .trimIndent() + } +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchHelper.kt new file mode 100644 index 0000000..f6b1859 --- /dev/null +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchHelper.kt @@ -0,0 +1,42 @@ +package com.aurora.gplayapi.helpers + +import com.aurora.gplayapi.Constants +import com.aurora.gplayapi.data.builders.WebAppBuilder +import com.aurora.gplayapi.data.builders.rpc.RpcBuilder +import com.aurora.gplayapi.data.builders.rpc.SearchQueryBuilder +import com.aurora.gplayapi.data.models.App +import com.aurora.gplayapi.utils.dig + +class WebSearchHelper { + fun searchResults(query: String): MutableMap> { + val searchResponse = WebClient().fetch( + arrayOf( + SearchQueryBuilder.build(query) + ) + ).let { + RpcBuilder.wrapResponse(it) + } + + val searchResults = Constants.COLLECTION.values().associateWith { enumValue -> + when (enumValue) { + Constants.COLLECTION.QUERY -> searchResponse.dig>( + SearchQueryBuilder.TAG, + query, + *enumValue.value + ) + + Constants.COLLECTION.SIMILAR -> searchResponse.dig>( + SearchQueryBuilder.TAG, + query, + *enumValue.value + ).map { it.dig>(0) } + } + } + + val apps = searchResults.mapValues { (_, value) -> + value.map { app -> WebAppBuilder.build(app) } + }.toMutableMap() + + return apps + } +} diff --git a/lib/src/main/java/com/aurora/gplayapi/utils/Extensions.kt b/lib/src/main/java/com/aurora/gplayapi/utils/Extensions.kt new file mode 100644 index 0000000..45e944d --- /dev/null +++ b/lib/src/main/java/com/aurora/gplayapi/utils/Extensions.kt @@ -0,0 +1,23 @@ +package com.aurora.gplayapi.utils + +@Suppress("UNCHECKED_CAST") +fun Any.dig(vararg keys: Any): T { + var current: Any? = this + keys.forEach { key -> + current = when (current) { + is Collection<*> -> { + val index = key.toString().toIntOrNull() + index?.let { (current as Collection<*>).elementAtOrNull(it) } + } + + is Map<*, *> -> { + (current as Map<*, *>)[key] + } + + else -> { + null + } + } + } + return current as T +} -- GitLab From 011410064b5c02e8d1a9a953dc216bccc006a746 Mon Sep 17 00:00:00 2001 From: Rahul Patel Date: Wed, 19 Jul 2023 00:48:01 +0530 Subject: [PATCH 31/82] WebSearch [2/3] --- .../java/com/aurora/gplayapi/Constants.kt | 1 + .../gplayapi/data/builders/WebAppBuilder.kt | 22 +++++++++++++++++++ .../gplayapi/helpers/WebSearchHelper.kt | 14 ++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/src/main/java/com/aurora/gplayapi/Constants.kt b/lib/src/main/java/com/aurora/gplayapi/Constants.kt index 9261eff..66d6fdd 100644 --- a/lib/src/main/java/com/aurora/gplayapi/Constants.kt +++ b/lib/src/main/java/com/aurora/gplayapi/Constants.kt @@ -64,6 +64,7 @@ object Constants { } enum class COLLECTION(var value: Array) { + EXACT(arrayOf(0, 1, 0, 23, 16)), QUERY(arrayOf(0, 1, 1, 21, 0)), SIMILAR(arrayOf(0, 1, 2, 22, 0)) } diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/WebAppBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/WebAppBuilder.kt index 3416679..97ff524 100644 --- a/lib/src/main/java/com/aurora/gplayapi/data/builders/WebAppBuilder.kt +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/WebAppBuilder.kt @@ -25,4 +25,26 @@ object WebAppBuilder { return app } + + fun buildExactApp(data: Any): App { + val app = App(data.dig(11, 0, 0)) + app.displayName = data.dig(2, 0, 0) + app.description = data.dig(2, 72, 0, 1) + app.shortDescription = data.dig(2, 73, 0, 1) + app.developerName = data.dig(2, 68, 0) + app.downloadString = data.dig(2, 13, 3) + app.categoryName = data.dig(2, 79, 0, 0, 0) + app.iconArtwork = Artwork().apply { + url = data.dig(2, 95, 0, 3, 2) + type = 1 + } + app.coverArtwork = Artwork().apply { + url = data.dig(2, 96, 0, 3, 2) + } + app.labeledRating = data.dig(2, 51, 0, 0) + app.isFree = data.dig(2, 57, 0, 0, 0, 0, 1, 0, 2).isEmpty() == true + app.containsAds = data.dig(2, 48, 0).isNotEmpty() + + return app + } } diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchHelper.kt index f6b1859..dec9455 100644 --- a/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchHelper.kt +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchHelper.kt @@ -19,6 +19,12 @@ class WebSearchHelper { val searchResults = Constants.COLLECTION.values().associateWith { enumValue -> when (enumValue) { + Constants.COLLECTION.EXACT -> searchResponse.dig>( + SearchQueryBuilder.TAG, + query, + *enumValue.value + ) + Constants.COLLECTION.QUERY -> searchResponse.dig>( SearchQueryBuilder.TAG, query, @@ -33,8 +39,12 @@ class WebSearchHelper { } } - val apps = searchResults.mapValues { (_, value) -> - value.map { app -> WebAppBuilder.build(app) } + val apps = searchResults.mapValues { (key, value) -> + if (key == Constants.COLLECTION.EXACT) { + listOf(WebAppBuilder.buildExactApp(value)) + } else { + value.map { app -> WebAppBuilder.build(app) } + } }.toMutableMap() return apps -- GitLab From 88c9d3ad7d7a6887b5b0384bd440dbcdb8e19005 Mon Sep 17 00:00:00 2001 From: Rahul Patel Date: Wed, 19 Jul 2023 01:17:06 +0530 Subject: [PATCH 32/82] WebSearch [3/3] --- .../rpc/SearchSuggestionQueryBuilder.kt | 13 ++++++++ .../helpers/WebSearchSuggestionHelper.kt | 30 +++++++++++++++++++ .../java/com/aurora/gplayapi/SampleTest.kt | 8 +++++ 3 files changed, 51 insertions(+) create mode 100644 lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/SearchSuggestionQueryBuilder.kt create mode 100644 lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchSuggestionHelper.kt create mode 100644 lib/src/test/java/com/aurora/gplayapi/SampleTest.kt diff --git a/lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/SearchSuggestionQueryBuilder.kt b/lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/SearchSuggestionQueryBuilder.kt new file mode 100644 index 0000000..5845db3 --- /dev/null +++ b/lib/src/main/java/com/aurora/gplayapi/data/builders/rpc/SearchSuggestionQueryBuilder.kt @@ -0,0 +1,13 @@ +package com.aurora.gplayapi.data.builders.rpc + +object SearchSuggestionQueryBuilder { + public val TAG = javaClass.name + fun build(query: String, tag: String = TAG): String { + return """ + ["teXCtc","[null,[\"$query\"],[10],[2,1],4]",null,"$tag@$query"] + """ + .trimStart() + .trimEnd() + .trimIndent() + } +} diff --git a/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchSuggestionHelper.kt b/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchSuggestionHelper.kt new file mode 100644 index 0000000..047a4fa --- /dev/null +++ b/lib/src/main/java/com/aurora/gplayapi/helpers/WebSearchSuggestionHelper.kt @@ -0,0 +1,30 @@ +package com.aurora.gplayapi.helpers + +import com.aurora.gplayapi.SearchSuggestEntry +import com.aurora.gplayapi.data.builders.rpc.RpcBuilder +import com.aurora.gplayapi.data.builders.rpc.SearchSuggestionQueryBuilder +import com.aurora.gplayapi.utils.dig + +class WebSearchSuggestionHelper { + fun searchSuggestions(query: String): List { + val searchResponse = WebClient().fetch( + arrayOf( + SearchSuggestionQueryBuilder.build(query) + ) + ).let { + RpcBuilder.wrapResponse(it) + } + + val suggestions = searchResponse.dig>( + SearchSuggestionQueryBuilder.TAG, + query, + 0 + ).map { + SearchSuggestEntry.newBuilder().apply { + title = it.dig(0) + }.build() + } + + return suggestions + } +} diff --git a/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt b/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt new file mode 100644 index 0000000..132d992 --- /dev/null +++ b/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt @@ -0,0 +1,8 @@ +package com.aurora.gplayapi + +object SampleTest { + @JvmStatic + fun main(args: Array) { + + } +} \ No newline at end of file -- GitLab From 236111a2a77115e40bcb330d38e6194f79fb947a Mon Sep 17 00:00:00 2001 From: Rahul Patel Date: Thu, 10 Aug 2023 03:02:05 +0530 Subject: [PATCH 33/82] Fix linting issue --- lib/src/test/java/com/aurora/gplayapi/SampleTest.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt b/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt index 132d992..4e588bd 100644 --- a/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt +++ b/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt @@ -3,6 +3,5 @@ package com.aurora.gplayapi object SampleTest { @JvmStatic fun main(args: Array) { - } -} \ No newline at end of file +} -- GitLab From de5c730f6095e5194867e2b4f6937afe840e4ead Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Mon, 14 Aug 2023 15:47:28 +0530 Subject: [PATCH 34/82] Bump to latest AGP, Gradle and dependencies version Signed-off-by: Aayush Gupta --- build.gradle | 10 +- gradle/wrapper/gradle-wrapper.jar | Bin 55190 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 7 +- gradlew | 306 ++++++++++++++--------- gradlew.bat | 56 +++-- lib/build.gradle | 4 +- 6 files changed, 228 insertions(+), 155 deletions(-) diff --git a/build.gradle b/build.gradle index 927fd4d..fdccd58 100644 --- a/build.gradle +++ b/build.gradle @@ -14,11 +14,11 @@ */ plugins { - id 'com.android.library' version '8.0.1' apply false - id 'org.jetbrains.kotlin.android' version '1.8.21' apply false - id 'org.jetbrains.kotlin.plugin.parcelize' version '1.8.21' apply false - id 'com.google.protobuf' version '0.9.1' apply false - id 'org.jlleitschuh.gradle.ktlint' version '11.4.0' apply false + id 'com.android.library' version '8.1.1' apply false + id 'org.jetbrains.kotlin.android' version '1.9.0' apply false + id 'org.jetbrains.kotlin.plugin.parcelize' version '1.9.0' apply false + id 'com.google.protobuf' version '0.9.4' apply false + id 'org.jlleitschuh.gradle.ktlint' version '11.5.1' apply false } task clean(type: Delete) { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738cbd051603d91cc39de6cb000dd98fe6b02..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 45075 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

Ag&&P7c z#C4W?w7M&=mMCZQY-E2biKC%w0^NRBb_neDdX*RyNqc{F*u(3^f7|u-li!cP+jB37 zoW5`DD(1B$E-Bu6Xp%#p+2wh?>95r=3PFw20AN+5)xdEtA-EuSCWYQ(^8ow~E!)%?FgVXZEa~#dyotSGZAeUyfB9i8H^@3Y_V5f{sgw`m8BweZIsLZV(ajBnq+`N&A%+EBxs8O>3vt2f|L{IPOmsZoN} zw<&X&siMOI2nitP{%*&yv(AltZ08(y{G$wW}L+JXJeP zD9w~vK7>zp>``41?d@BFaV1!vy zt6i&HpWZ4V8{KMYb6%?}gMm-k>mxBP=Rs6h+M}};pr8lW;KOs=->=fe-U!#2b7Isa zN-N4lJrA5RRV4R(&Fpfl9Wt?#m=1_4)2l4KKNG=b?^cv)SHDfh&8 z&OWpso&ElddnP*nHUk;YeT|;JOD?RZx@P#jL_c33;|`X$R6oBE<*qh@&7)Gkwh+yZ z{G>w0FqZolua5Lfw=P<7nY@l(V|p6{7Caouem1?M^gA35VDhD1UfdopW*}f<{^Bw# zh>NV}>cfZ+#=G=Of$!wI37FppKe=Y$Y)>fX;ef0V0DUGjk0{xgo4s2wHv;HP`+TW7 ziZ7-#6k;#PYS`m>3D%4t;q(_ng1#Sq?5cfXEByiFMqa#jV5YTDdn}OZsI^qpg5wcm z6&tWZ?}hoXjc$jfi^VjiuV)CbQ*@Co*xcETqSG%5VynWhche|zRnCdg*Z`L_vbE!V z{w+;%PS9dQN+kWLuHDY2uiDup)?n`vPH1qSlBcm%0qyK0(5C#-*PNv~pq{f_$;X+# zmj2}pbZ$WXU>oqogC{MWzA;26F-s?0ly7FtTy`6NeAD*JsHIuX{U-4-`ZMzo`Y*HkV2 zfzm7Z{nB$FI_KFL4EQJ|!Pk?=B{gg%6dLoNK4{1vgcgMWlKgfX393vtZNh9n>!iZoMMqbZmLx$X{O zaZVuqb50FKN9J1ptit}Y^QEz`@ke_%uSHb8XWa

^&2{TmT#wE=JH_Aw*Bzk|$H9rio4 zuC|#Zny+Vcd1ioiYNx46q)=?3_Dtd%lWNlvf^X=S$m1Mh_wp&GXb0GZ#95t7TVk^b zi7J3V z*%Mn}t%K7L$3qKPV4{k)q2Zwp3N?BQgSd{7v8nNDJUa==D5%-J3ZRamfeOg>YB}siY_BDsT*#bUi+=FHcXq8w8wwm7aKfsb$+DV+2B3W9rC$=c)%fg9jL% zqvofK8c$IytJI|c2#xR#>hkQ%sT5RR)gMJGd>xrsx%65vbR3ACSFxrKuj-CL7|t1n z6Wzr_qx>!jMMbm@csIhEbS)6{QohVpwo??~zJ+{F8d7-dNR#h=)dT zw|6vzpZIc1pu7qa`hvD4W(6k&;{&60M}`~f?Wc}n6u%0Vmezh-n)*xwBT$HB`fNVr zq)i{kRG-cBxY!w6P9hy@!(zVV9LM^4x&1|RQzKMsfo!mG8=zJUN&s6fiSjz17te={ zZTzsWA@I1L{5$0C9a@wamiC}FR(Hq|Fjy6)NAU8bmn!B611DYu?n=Z%U zuf`kE2z9lS{%qO}XfS9tAfBFYe0D2$kfWsJ<8*7BqWV0m?v^IuzHU7=`AD zoD3C`nF69GT0n5JKC{^q&qEZ~;*cXkiTWA2C_z9vr?B*!4Nz~H_| zPy7U7ApwthAg%+J4w0*qTA*+bp(naSTs@Bz= zgUV*c&vlEwOV9~b1vEr4*wxK1yX$@NF2438tUhc`zRBD`j(qpXxpmup+w()P=XUe< z++0=o4n2rlqB2r9vTY$jSAo92TB=K50s#;&hwhB0X-u`-9N48YcuGS&Ohlcs6Nibr z9T~|huNO&WN$tZ6*qqES?gEj1?+WwUV%n+oCYtEpNbtJ6Q#sridFyo#awOdv$iIDX zi511ZciucZCg6W{4y#Ef;!T*k8{q3%U%;B(IRRNK)>&OfZFS9xc( zBae5n`#*b1d)=a(5ypl4bv(cpv+A6y`FVN!`8C-!%^E;zjL<ncCXwi^ZM03@>6j zeB&4JG2)Om4&$v_7s;-*my=;bxci#Z6d8f>+*S(t^3dmS_sr)l#!#O@aklCkzk`hDlk)zP)119U_dI1UE~-svdY+1J_6`Q){ZFFPOd3 zKuW@gj;Wv>^g|w6z1gsY{oH1qYm0)dgdNY6a%b#x)&r=dqalp=wHCh&V5=d0%p-ffdVFA68Zl~+?BZ>(XdD1g& ze9PjIo(bvb>OBQom%`#DZ}PD0{*)0@r$e~~c#admg5?MHU7Oe79G*!vv`8fS4>RGB zcZ`1Wt?AV{mZyez zDIkCUI4wUM;p?91e7w;+SkiL4m(yFpO7n|li-ws9)-Lvl)4^~fV;S4y2Pdh0Z7LHb zj<8G6TH&=?_HKFs=Igx{{#aXP4qIh;?wQsIV3l0DC)R7lN%mFKK_( zVess5?DZX_O>8HjSVXdpb0-u#A9f$JPY@Ap3GLQqt1;t>ghwO`Lg`_^~@PHbJ)z4K_878k_Ohz%;8@fQ?CYhLJiv{ZD=6+Yz1;hch|Gif%q^G> z!txG-uJ-+~_GQmkL)7iVqU>DYT6T;LBlgF8hZFH=YeL=Ywe3Oz87 z3ST0>c|{E9%W^Tpc|oThT2ziuk}+*4l@y5yAYDOEC391eL7tDkT}nz1?(HC`5k+Fa z)=M7>-&lUraQWyppBbSpoi>vT$Tg30`>vgMHzzk+v+GC+x@Qv(Qyy?{%J$1*=rA}2 zoN~x@3)M9i>BKp2=StZaF7su~DgSG87`tESUP;d<(j&4?tz3k)FPK*^ z*dSCogC^X15BRrTp#r0z{bT5yBVg8FzzYQs^s;#bIe7$K6yxNh@)klgH-F9!Xa@Ai zs_UN$ZeGzV=*P1OM>nE>&OsRoYd15H*$j22i9VE&KuPT5wm8G=uN`q16g?BT56@vi z;Wr@6IR>5aG)AlTpt8MH37e3R00H46`3yB=G+K|Q-{m7Fcr6(OIQm5`9EAs10G7fO zi^y5MI$VoHtQ5P=V}jBRuDl-c)L<1Mp|GKUQicFShbh3^A*=+zo?-f*Bq9XKBly3_ zM1ZU#RDb4V1z4RPC>DSM+_~e22KL|q?kJ((`rv&@up{-afY|0J(EbVN zutZEj5oj`p12shdt2uLy>5l-cZm0{9!Op!gARvUFSaWCkrH(RB`G>mw^+{(rINlp@ zn%7h3Yn*>sk0<)iVCeJ2NT>pX2Em}GKGwN^fijZ7y+8kFzkG4X#>xhtq&z$X1n-lu zcKCilloyEq2&+dY{arbDo~0NJ;d`P!C-h6bHXZL@9^eb6+kOVs0?rbC+Vj&QzaUka zm^l9)*75bXS7|`eMI5Lx@xPUjfnkfde}wXryZjm0ZX5V%i}Oh+9a6x)MS(w5e==Eb zfK~0l{V)1N6;&2Uu_XJ4>Jv)qC#rG^;6NzB4A;ouq1nAe1w~*4)NiH#-vGy0rh=li z1dAwv{|sR}uu#Don7Awf1}%UONNs^8gMz<7;JcFHCzsG)8#=_fILPh^m%=Y*p?_|^ zU(7=PC{x(~SNVTDL;vp5fAb9e_F59G|9_hKlXVF2gm&oP9{$Z*@{fmC&i_ZC|6dN1 ze^Z$J)^%!!?eolI=owr!iw#I}=(Z5tEYwrv~x+xOkt{nu9Yhwke0vFqG- zU+0|DTkw<`a0mry@E@>=pz!GNIH;ho@$`^f&n5rq$`c&&= zXrPG-00YPdqqZggbD=vos3Q{-(ly!U$ z^_W*7fw}4^!`oFW%XIGhw|dD0i=nCW zqx>tZy)OEs4b_6axQP`xMqQVOfYJG9{4Sj%K<+KTwgWv?&&;KNti65T$^0*o&QI+S zD1k*(_qwm36Un!CPUyI_aeGD>LH|x$lSa zD}^V|b*EQw_qhd{hbgHXNtoOtlo1VZ|PFOgTsBGWL^gKWgBb zM}A)qKDN7R8s%uM$_i!0ivX?o&PZt~;Gn4Li1bWldX}D~pP!^ToX~#J6{(}b(<3~l zeIpa5U8;0T#AkG}g{H6FE!Ki+>RMY4Ys_<6+ZFy?|gUa!oRni3%3hqiX)7= z(KWG2tu$dC6^E^f)Zco^M6+Xhmsh8+=BE=)W~VqoT%yo8vA@^u-6`FR!t*q0d9*!x?>VO7T9y9f`I>qWXIfyIits z%g2Ma151WY5C-^K3fb)IE3~$ClHC?FBJk(gzNzhRHU$jddMvNykqO$ODhr*hjPT;x zkW#oJ1Xfl$j`YPQ#BD|CCPEw)k*6CIk3&DM?ULhVCEZUW;)b)`c(zD^T$*NKDLR4m zxFyIFv4iF*%+o|3fo-!}OfXcExFzF1(M24$ z=-~a`6T7*qvEcm8Rh%avN_6k1SbzmRi_EpR{Xo$_WN+FDKVhUm3AwujZhtwgcgh#g zK1byKhgtq;Kb<~9T7iDsKCN8T_z!gcUavbN_Nbpo$itLMKS+iC;m$R}#ScRK9gs#l zWT`5-Ve-e|lix?5<5Di^B7tejk}m{+5eB z$y7G~G#{fDnm(mCnM4qOt}+A=ZqwsSQ1h6TVqH$e@d!@i$WOdof%r3JdaZQGaMy$l4<_ zU(WXOD0KYv3Q3DXVaMXWVK|*-ed5~x0RA_JUf*FS`go20AE|Tr@Tv?K3rgKi8PL!qX*?iei%>A>D2 z+8GfA52B?^Jf#GhZn(w$u{RzZ!VkGMH^e(ThKJz?{td>_j%OIOYQPxZws&=qEZ}yd zDh^bPP{%g6!cMjk%AAR<Jz8HuPnwr#2(zu~Uc5KF)%Of6V9)+9-eJ zN`GW>95MBfMzX2tW?X?QALK=g!v}wN$b?*k*C~gm$ICLCcnyRNKN>Ww&l#l}_DzUN z3Z2pS*Xv{du|OYsRQj?B+Z{#T;a6fVF*Xqb#+?EySc^E)CEi{ynS|{m!Y}L7Zyv(f z80Bk*f?rW;Cw>Vs{E-8#VgZk;!s~gH!iB?ri+v6tbc8YE;|1Z-DPj$$b@IKViOA5o zfv?q|KK_ZYLa{3E@+E`v4nEgLVhL8vxR~lERk8Ry81g>G zNdWrRJ#ocV?A?gV`vG75Af>(FMUc9?li_cw1pKca|G(nP+RT&Lg9rlh7as(K=>L8} z0KKt|p|f+ACXA2Hu;w=~chz08IKTVY)?F`mp|NDi9fLm}jw;=4GM-SGd@$y=$0I2} zw^pHhc&WWEB_%9{P(&6~z%n^oD6lR-wbS@G7QIIP<4nNcNjdkBQejHr3d2I{nZF^_ zt*A=kT%X1MDAWF^^t`{1t)qofGvR z_JI9v3xW?{*e^edujkE@}zb?-2&Ph<_yd18lc|7jot; zgI_7|_$Ryu^0wxs#p;9mizLkaHi!I6TJcN!@_|+KHN(G##`jB{^}8bDTX~XQm$($A{D(TBFizNp?w9WL*@NBCarNqjV)>i7Mj7 zbS3*SCUAKy6xcB*O~Wy%rgLgQSPi#+D5;jp8bQ;1?Cn>GNgx%jY@6sMZXS94Xp**U z+ho#Yu?^#)n{so;TrS&+nM47RELa6iyu-#+YnBuzm0;<#tX?)}+!J|L5GHO@S0PO) z?gi)8ym$HW#!TLqg}Ob`YWws$=4EqhR+>emmmMu*oxH+)x=bMt_bvjkdfR9$)sWj< z^Y2;WJI~@l=UCB>IIddi&|1)ScxSgi^le(SLyoZg2aW{nKq4wC;$hXfTsx{QYBev0 z`x<@Q(?jEav+KEJ1S7{)T?yV>Y8TP4>|g?n;AdmzUxzG}a_*G7zd>syMH_rjiK!^J zg}h5Gf3motu42fHw)_ME@qQE>S~g!s)AhKX<#fD)1lP^Fp!vjX9LEh%Z_+EuV>0o} zm$=KJ1rG5C&qT&IpkIkvdGH`1!XXn#fy{V&?DaU!`4?~e!2LB=9<)dRNGnkHemM9_r z$Sw7ZvnFTnxhZGVmuW(K&$*N?LqjxiYzn%{C+E0_oHy(8w)8R_*k(=MeZ~hHEH#5X z7WM-Y^8TX1=&!tET@^i&>KTI216i*ULm5zB1hXv0#VyZB<4;>s}DrF z{UD8OxM)2NHRVB~hRj!Lo#K$x7)9A(x44AYd?LV-<7 zg<*wK%DBoWk`@zb3A|?{S-;a-0<)7Ei1bw|s5F6sVQmEJbb@nQ!-3%9iq!PaMO@WM zEL`B~Tw}yQZAX1pT9b($HGrlB@!{F!5icCRIL#uy036)+XEaW{(n=U91DD-^oWgn% z^H>2fQ!M;X2JBH1=b%Vp@kVeGW1g^$6$!1|MzOa&L`Gpc=|K&}co#u~#$?UX0kX}N ze$F_pu3AX0xw_Ws838rk!z@WS{@7Rz6lFjyI~6WvAox|GW~o`prn5=7KZy*+unh9J zH&ozX?i5{mN~lwtN~fE%p{Ol}4`hO7u#-~+(FpQ#LQ-wSXCQc}cG|LKn?_%%etRc8 zJq&S#SKH&AN~bGn3YImmg?BSM^Cfc9sjn{%UFH#_o>~(kLFN_wPZz%iKLV{fsuI9r z`u)DGxKo$>ciBi$8he|_j&Yd;@u{fN>FFt{D^_G2oA5^%9xhkj{Ub^|tu|9tTY_TK zAb4rgN@_nZdh2+~L@D)xz>*gul(m{&QeZ{Fh2U058)%D!nSb+`bnPJ4MR#?xa|%p2FKMb#EWyE-Y1HMui+}nZ;f(T}w8(r0(zO zjnRo8KsC&L619HHfePr(I%@QlJeMjO*`^Luo}b-^Zhiza{B|{@Jt}@^x(8U`My0I) zG>+qIk8vCfeU^TNLwg;o>Xak$2=F?$-fS|=R^+NPcLJ$(ytI^d@Bw81eCUQ>owJ_iCAd{B+YWK=0PRh`%szN z!3Oy}Nx{TJ(~+baqR@&lUEnTh`rp2D@T^Mz4^cY?y$w#w4#mUufl_5BL$2I5)oSI; z;_JOC;mbP;Z$oEca~Cb7Ch-n%j83( zTwJG=m5eL=88V)$dW3?%mm5?|WuD}U@q_!zOA$Ms29ml*WdD`vXaX{)Z(Au;xL^-u z`0{kns#ji>9^oF|GWV)zzguCWLqsD#K(aEsJp3xnc@V}NQ!s#SO+qU5_Cyn8#5i8`Vi?CFt?QzsKMIw-Lwm z7X%1;m@!>(9A#7@o;+qWp^!uu!3t6tRM1zkvpyfm3qry(li3R2#O$w+n_KP071Bw% zhB(YewpfcH*yc=wJ+;o{t|3~IZY2A8{&Q7J!F+EimEbEXLm*jepn&t|^+D7dk%RF* zEj3PNbzXhlA&yV9;Wq0FZe|Tp4~((il^70!O>raL#dPD0o>mRD7hlFu9(#`HXng5&6me z*d2e75FqQ?8bG*Ee|96h7Rf)+9h*e?emw?Pu@Us=Yqcf>slW}GcU>^At>pb3I&*`U zf~0&Cp;>tW1I47Vcx7z^`)*d3L9ah=7v!7gurgv`3#_E}w!3}TL;8%_urFHlUl}ZB zpOy2n8Uia52KzTxuJ|n`$eyq?{2{V=+RUxCh?$|n+GdXL;}uqFYPxmL3zg+d z+h?kaG_|hfXS~ySWw)rM@V4W*w@Kt&-sO@o8v+u(8ETL{xA47ExX+Kq)UdK=BM_%`;ZKz<*tu>x%TOO*Y*onA61}%$d_Rr zc4hq4_nY$hOW>bBDl*~WhDkL2AX&ya?n$epEO;a~j3T?G>?k~%F1*hU zIb5~htjrf7_R2;fujw-#HJjjZzu<3?JqoS`$+x7+Qt+}GvNcDCk* zYm-6?XxEO=Pehx(>A9kNVm^r}q}_f_;OD=zz~#?q*@l(%`8ymRhLE*PN}51l`TjXc zANIsnPM2xCC#31Utr=fzJPT4Z_nS;XiVA0f*!q>ULV|ghMPU~c*otuHpZQz716`hf zxAc4BKOyi|V==J|xM19Ok6GBdb&cHyaZAmj)X<_sLtceSUIJ@ak;AZ%iDL zAzSJ*Kr#)~!dUNIvSCirzTNYrp#_JF6zGb!UU39@Ak zMLBZv@{1QzG1?+*&%tpEC74;uR$dDsFj>EXTRq!HiY}G^#iC_@2EzR9J8MYD|8??v zo|Fp@y1_gMeAcjmic5#k!otkBQKZJ$rW>|F^@iv117x8lnJC32tzBHhS6kC}thwMn z$I%P{J(4pQUxyVYZ@n(`LUVCAGKF7FaPsuw7wyOz?6E^f&O4nx0tGd z&bPiS>e;ub9Px|o|Kb#b2kb{!K$EiYS@C&(wEz zg*Y_@t2f@H^C;D6RlR)BuD5!4uy9Vc?0wzk)pg|b3^0$^n}U5@Jtwx@cRzQ1FaLYa zM&flk#Q9UDR1`%)wGv4|qu>yWl}#K{GUkyHfFelWJ8#M(JOp&<@yth>!}K+v^FU2M z?s@9{O}+Jji2Sin+$liYt*3W9knhHZbhHwg>o5g7n=ll$UTfwe^*(&BxK$gowG zi*}82?@rSiG!DRS1wK=I5N_4{3QvlX#3odzg;Ph9F&K+Pia=2BY9-%qfBA^h_^8$R z2ou;{7Qba=^wH_1xRHd&=_@hiDa^&siLb5fDrsX~ajX2-Qgy5${@mMayczn&)zLxv z5>V3Epd~C48O`#bWyZlaM`~yo`7=^mYl16Z6s0{VBLKLpvh|(J>TO>5sR}h(;ivo z591&VlT{+&97*(tl_7{fgg7eW;?7ToxOsE!OdwkAVnyGHywVt28kEkMXt$fiAlHnU zY6c{T@d3H%C}a3BwX?PSc(ZLCo= z%>d~5q-x@S3%4hBNW(>#Hz1E-bqF-#?AL|mAyk|U5uuA4mU9F$qPrVL`5IRzso#3~ z_)ksNaFCDqlxO&nTNm{=QwjFS7QojLon5SDX?sL7#?!L?W=f3I-JNm^KwiA5)ERR`;NS0m5dPE(*rloFirFm?<-+@7!-Z_ zG91IX`a7v83l}{3l2cQY%v~})Us6LgsvnU5RByR|Zfx&|MDXuGT7SzO1-GdQX#!Iz z{Co07+c~BmqJ#Rk?AU<%Ez*bb&_9(AT%_@r*a-0({iAu>LqYk;0}***v)}?Rv-p<< zy@Vi)>_ip4WDE&Wl&5Bkx-`Q@_;VJfG32EnVl5s%F<|j8%S1+_yw%EpwOoc+Bl*Dn zQ4q$mwbk;VHT&^_;d8jM*N75XETBR=kX)J&gh9 zZxsy_2HRYN{Xr|eXu}^yfEkXp|5-QBxTN;%!k~{^nmG-sWK<~V-cI1$AmAe3QluHt z%#EPORz8?H884y|tLa>p(u;1sK6)e3XHs27W1$&56xOY4laqblH1y~(4y>6ibG=`M z*_pOH9nM#E-Si~RAJ+x>-dogbQrbYvx_UapL~ag*aSQcXVIcHij)dkSElv0;%|RYL z3w)IwE<8R3?Az&y+gJB`ii;Wk-ndqYyfaO7d#>!U`*eJZbJU$Y4QU3^Y^lmU6}Ge7 zr|z@tt+uwqUr2F|JZ~b|1|S~k<6cYTpqMF%s})scCflyrgTqZr8qMnQveHt`j%3J_a@M63N*8AFyZZwtta5YGE9>z8gO^Fv807q-7ZD?GR+$%}z z6M;4cDTeHiJaUerI@y<%-HP*An9Bm|+{8Xzd5W9eM(5@zT0w|f36s}&^0Kbtqdjx6 zR`45knAb>c7mkq|D5+g;bgSVe(HI195SOu5_Zn$@#5$m5mjvu@f2&xX!zyzKDHx7b zcs{*cJ20A#c}xOA07tIg_i_q{#w%#MkQaW)9&mmx$3L;3+#K3}n5F_Xos;haHSb}k zI_i&-Z|*XmjbcJ2Eq7`Lw)fu9Fm#$Vy*N@<1{O~aOS#}rg!ut!#~@t1Mal($vXi|{Mak#vG@+e!N|4Lq{rJy2xOuGUJfSk3=fj-hP^AYp_9jXy< zWsQNX?ja+fZbkd>d4Zy?wax@Z8prgXjMXSwN`k2-%6Q_|)^89F+u~Z-p-_)do*6YoMP!Y)fIS8|*oBBVYI$b^}t+up@7mjCN z(U^U3cm#PQuRb;5iUIfC+7a3k9IfGY}XmbLwZ9TVb zfidQ|E*kSyF<&>=&hW1hhupdosmRM@rXSZBkrCYvU{8n78Qf#gRYM>ACTWw4G+&6I zS%@8)q|BI$pt>U8(zq^0=bCGv0JEa+zA8qw=bMbtN|L2!8nrEUyj|3Jz!jIQW7@1Q z5XOuhcEqyHq`gbZc5B~I)7wH8K3rJKN?1(;XQv4nWB-q31HE1DWb;%xVI^hYiPVks zc7>Y&=;_-*b3?F`Fno56uy|l4t2_3i#T41D%C1=9)==5z4qsPl{q)jGJwkiZtru1O zZR|EDDHLxN0Ww|~0I_FWr&6b)#`FX#_N_)uidIQv5AnTM%TZx;fx;nOm>iWWjC;H- zg!VYH^7>oKRAylYv3q0A4SsF6sMbqg6NL^_x^4xAlA=no5oVCQPT!-1k|to7@`OX} zce+`pifu^>NiFmoY{YKEZ#pw|EtyxewQxN_MJksA?oSg89Zwv&K2)1(iZ7)9bzkG=>5JfkFPycm0p&s(pe=gnxntveaJzJX3tXtqaEa$)I9?$kb-! zqM6AQ6YrU&VkkOEns`~Q1oFH*%EZl6vy9ORF79=3B%T{JGzRDr3QE|vL4phxWa7WriqD@g*Gy) zc#(zxb1|9*V`-Y2!7y@v(q9gz|D^5bYKK$NFI;&x(N(-yqCix}zXMe0&tu84|E;o@ zR+U!~_~+e3r$gn*7ZyGeh^y53X}0~}e9KXeK6-5W3b&$dA4OQ*Q8fb&B`ztw>ZbR9 z0&2=$+9RM;eS`t{)7T(Je3Awy(C~&!>-mw^o=j+6ED#}f8^{h-vbEIerHHPY9GurYi zq&fYk8uyQsIMt`M#Lj{$j_*SZk1s0@JP zQshVS$-XrNunJty(-ydFJ543K63fgjJO6i7X&Cy>AhCuqO@>#6NJaM;*dXsLT6C*wuZ^0sIzY{davZ-*J#Fr&mhEexbM^ zztzLyyzu>BpEV9UjY8zxX2_*B`=Ys|WN6*t+aGI~1aB(cPB$@J$ysnn^_k>aA-ufI zthvX&=n%2g9x}cAKXiEo1$$A!)K#l{V+Z}ijm5--G}vs8Y&L1yU0U4h1P}m_J1%7x z-To(~u1<~9YS8SJT4fhzF$Z-mPP|Q}sNF4dbJ`LC6nLzy!bH`Z!jS7dZydLM3Uoa+XXHY8Z2hP9Q8(6=JUH7@Ziq_1H6K2}}#IpnJngvJs*_rEGCLIn^#A2)2!JgJE54;{}yVTA*oIvi+o&)?Ayo#rU@PVB_uO=N_v ze8<&zoln)B#lJFa<}1(ni>=H$IlAwloZX-Oa4_A3WdG8qE^4?mA#8S|~bFb82`t$%t+r+uN$$R0I}( znjdszyKOoyq=6(+`qK2kA(*xxM88+NkeM% zf?@x7SEMhsIdQ~M(Vp1Jm#2kD?K4D`>#Z^JOn7)A9heBxMM<$^r-(Cnpbj~u*z!_s zliqqDAL?w6ap(*P`9NMsPQz=`e9BtI`DN`%h(E(x=m7!VzdVt}C@H!E7dMYoom`@1OB1c^(>H`(N%y%U$61wQN`LUNpC3~x}$1qweRYW9oQ`O(2Fo0xW64&$G zzsAD^kt$>JH%9DVf8;JBiKv@v%@y;|Xw|QrY2b%udls#1Vy5`WI4viqq#B=u9G{3< zHkq;>nflf*@h`zi_Zf;MgB*>}PvY=(5e7RASM)P#t-9* z-~z-6fDv>*^!zX^UcSx`l7%@+!i(s+ek^snKW~V0unQ@?d%7M%y;;{rMFIV=L*Kz$ z#;{!5l=-1E0D%6FME}420thOlv;Z9%2#5;}2*|JhN0||T|GQm4WpR<8qM>v2W(AB0 z{ygkQeJDOmSP-cM3yg$D6xy!o5gB$m*;FSHOp_Iznsrl^Hl5aTxkZtx0?Mxl>qV`N z@~So2isq&AoaRrA&xqph`>hF+1bDDJlIJe>ROjhC{_(E+4NNGcpR;&hBeLtBtt=#k z*i@60mSW~W!Dzf$luwMSGSM+L&y?85nX#Rdb9Pj8>d^iX43A=lq+Rxe@`ekzeDYAm zjiepU_`J#2D6G7@V|OOO4mRwx%lr>|hj{|}q--z21&O%dEh7M~E9n7q&L&5t9%TC!jHdvwSlj2h8IL~C4WLA}_x9TW}SI=NVx+>NSJcekeF)F*v?3UegDKCBb7{S>uZf{!7gC327jlj=j3yon8OsX$eb z4rAU}Ci^S{J^B1>$*#KER;Q!b?X|tBsR9RJtEtxMNT4dY;<3$CBUtFGI*b-$LAKMK zVCkeriNV%d(WrsgZ;xa!bb=(Qs`5&*G}0wq)7rvW{1EKwBq?udIiJ1baz>`n{gM#p zz?%J#QD%~@tdffwr@zdYRfEA0o)paEp_>m_Jaw+M2-rG>8#4B{eTxuKsCjsO(5M9T z;H=5*57Q|Z@LWMhI8%T0ff`fIw?XI=FQ-a7*)+o~Gp|+<`(;_0=>Do?9}u4Oa;XXt ztP>b0fmpVl{o_Nybt$F|l9HL^XkI7#8~SRqyR;hH%k`JpZ@MwcUdVHpz~&!X`-+p$ zB7Ko?bOlhvhxw?C!3@5C%WhgF1&R5A=2*y#{ktxD91|SFc%*Z&*LK#Xw1iB)qB_}3 zWO2cfes(x)SmDy z`f(%J>pz;mPa>i6wpc<+(BTV}(nh^)Y`rK@p>EXSq?^+Y8iX9eN0%Pbt|G+&a4~gH z-dgBiYEW8_X+$*I11D`|yjJ~}j^Hk?bU}(CIDaQ^Q!xC!mWB>*nvdu;^qE=L6t%GA>V}5z2^u!1CQvjTi53XVf8}} z*J+X9ERUZYwuSQO*%BL@ojHV58*cQxofW4CYP zIYQ923Ub+-l|D#U+#LQ|#IiuJ7UL;LTD;vs7d8ngGHzF#hvC4^FJANlSkS@-fAl%z z_b&XBOX;!pDc=?fzS1wS_M^cWf(JUB&bHJZF4Uvc@n+J&;~oYMY!oyc|#3a0~^MF%Hh0#8U@zU z@Fg_@J>H_P0__X&0XNJRfDVdJ`qf&MdxJNE70zl=&#_(uA7$sS4IqYPV@d=n3m*G8m634^gIy67-Wl9h>A5cWu7 z5ac$NG+x#66XiHaMIgaf52r4}fv2zptZC9@{A!s@n{qwTpTYhFxFQdQ)z79e$9Iav^?^bb5BxMnYrsH%JI$e}cSlTe2=MwvMTEZ%Ck(>=(<@|;@ojPca zKfH&Ekgu8L{O+y^{OX|PGjuNLkWE|tKhFpL3tojA2Uv$mGhKNvSQ`~O3T^Ghdn{olSj?8t#m`NSmf`>AAlbg)Y(g76@WEz-2l%_1a3HAk%Zw`nKi)CprE zzwNyQPenIXb|+&GLlb9bXjF6HH8-iE-%%d5gDolJZq+hGSK>gEy$7P7Dt!JRQEyb- z^&7na;xEYcu0UgDlvoozOgc5clzr(37Ju~}>fIBmjaUs_!sevEL*MNWK6xT;!m0^u zkPef}%bTWPVoFgPxZ`Q{SIiq^1y8L*^B2uz;6D_U+V;`M$SW+?G^FAe1CRwFO5cBg z%D*I>)~i-_~yW`|0FNSG!> zI-9WhK}K|Zu`bEVraa-wi`U7Bt zor)rhk-EO;rv66*{Q~#RYMDXgnl^SVS@@p0V?1YYUWKEO8!eC2dMa$x`aBo|sGsIM zFeLNuRH%H#*^A%scvXsrXI}iw5%Xj}9*FIg#7jGpjvPn*cknwSChMWyexPR!yl8i* zcX0WH=!;3<+me-PensYS55#Y|Srj0_U&2Oy>_D4@XllCq>-m=*&ETi_y8j!NsshJL zgwaQ?q-E$=9Rzml>z1)*faQI-&Ztk(d-PvHo6M5*B#%!qM`OLSa^qoj`hSpCm#x9$ zI+$Ed1Fz*w`;wy~a0$#i;l`ND{YWKLj?tt18R{_rluUW7QpBrJFsP^Q%TjaQApDK`TRf8IvP^ zcI09QG0Ye%^f9p7@bSE+|1}Ny@$LE8ASWNVISI8O9;NK7u?-XVw&q3Bz{|AimNM;R zu^m)D;07=56o2dRkPEXf%+l)%wnfZwgBJ_Zf$xt;)vr3ml4!6nD8Ysfv>N(rxYoab z!(|XQbHA>ro2(e2nUv4<#s41b%OzWA4S>glH7f=GTTo0skG={d=eqzFpy02BhN~ig z){jYPI8bo=pTp*SZR38%Z=opaLUZRR|4Ny!eN+A-n}uu;NFtZZ>y;LzqcCo{bnU{Z z%lje0cdA_*warUn&>r1hx9SjkG8}TA-RfPD5m%}G(#)bvN;kv9{2Y{YtQ??p)Uq30 zVlDR5m&Dbufede#fXW9*&vL$a=Z;M_gar)?+^elPBfyt3o}C%teq&#k@<5yxV|#G3 z)XPRLisyUDDj@Yjf_&B1ZdsD@LE(}dPQosjZkBKgYgc*e%JWBs=zu4ejC1W&pIdmi zz6AW7O(+0Y)GkT1;6_J@59DzH^$kp;A5h2872$Le8upICTb=|c5Z8`SOYC@t4XzF! z@Eg^4&W#jm_c^;tL+c~GMmLj~ZCH5Mh0pkK^i(=ylkyXM4```3#YvvhxP34$e>ml5 zg(U0YNK*ucp0Whr-LeH%4@ks|CRXQP|4g^5Czvb^$qxlAe&~s*ukb$Ejg>i!7|R5se)jWD>EW!a95{O6kqs8{Caufv6BKkp zLEdUYV@C?K{pd`Y6QKq_Zjj+q*Xk&G(UDT0XWbbQj6Bh5M^xEhiLDOxv(?ZR;V;aJ zvmrj{jJNBnv}6hQi(;qPj9PT7?1Zp(_-H!Vg_}7Z8Yu!e_n#9>x>Lzn(4S`pAlJd( zPZS?&EBfNCr`waslfCdZSuFi|m;I!-DaZ&y=`e-lwici5B-v%l{v;`9dW~r3tzfh| z=@K00aa$}|oZWLc>pC-R$Wy4Ac-MDWW_+^Y94U%To)ssud!U_WbQ^|7x<7X9D7I7S zFBmZ|)&~G$1)D#br;Fknv1eAmP_0;!Gc3tpb1C_=gsK$8|HzfxTOimDM*Zp*a^Vv# zh4aN!Tu?ED`;oNRA}qP;0y$a2eL``7lBaCdm2?%9u!E!Fin)n!7*%N77H;vzb(z2=>&Tbt6-Q|Rp`jy zOB6vkXaUnVS{1%K*W2F=u96}OGqF1Vd)dDk)yNI>SRZPSK9}0V;-5WBVbZ*TQTSww zuYwVPp;ldJcjoW(RG`j^PQeQ`Lt-^jTuH*Bn-{1I8MY#gL?Pk>!-Ym}C6!ZLo}WNK zT~nJHu|3fqe*~t~z{~)R7=HF z=L5sGA=q!QP!~o?Fpz|Ov)$&A4YsWb`L7HJ$YT{U-`Dv{WsC*U>83GYOh{?YoN@jkh_@nMeVZx#b%HWSi)dGb?QVq>v?&=0#bXC-f7c%BtLf zSJsn&%)BYsJ+`7Qb87962dTe_Y(IU5NxW{Py2#OIV|ON-#PBM@9~~m2hB;~3To1Xa zA-lJXU+}SZYYVc+V+K=ZofrN=ZGUDD7cBT{id)sJBtb^hYN_NPv{LOgP6eI>;1V;&<@VfSKn!t z18yKr;CT0%Z)7eV5Toau%q)$wCS33@ZMEw-UfFto>S#`6yk;NDX?{POzOlYlhid8< ztIKc@%7O0u{!Imf6_^DW_iED*lF z390iGKk3v|8Nyq_1>9`67i19q=Y1w$o z;bT+0*5^jaMr0|_(@$vAd7y4Ch&m3Ma7PW-yZXtuLdqK6H8aePU}rxJZ9aGc#^7oP zBOU5f<3h7bIA^kJIgr*5jh6^d<&lkk^pziA<1S6)vY*l^{|TnzrY+>pbVCLWNxXE% z$(vc{d1Xc(O~_$Gd3`knZ0PM=Wf_{J%m?I4i_BLPU@1|7P-c!b2ops2uUB=0! zz8*R9wnGWo31vhFbWma+%_HPWL%3s?w~Q;n+JLM;r#K3;7UaSLNJ)%YTOoH_dCEkm zOkPMyTToRx$y5~ZubZsf;wo>P7+u|GP_DfmC`&(=< z@<2MLL;xnAO7_6`ino~j?i9#n9R07Fls^PHay0v$5j+Ka7RM5Wl6+nB3bk!aKTu-2 zy|MJVAgF~GC+8a-IH&`f=PWI07WF$##WUtG7-(X%0oG-2+~J{*MEjaDYp6I?+b{20mColIc&rzFTT+6KP=Icp*%RI- zAB~gIaql-Nc&R~y7b1KEe=CrhmJwo9gZ52hK7Pu&&g}nq``oAa<7+cf5Qa(Sp~1W* zZLIg|v0or`vu+g!sQdN_6;MoxR@T2rkllS2x|Fi?j(1qqzNP@RTO%$MR~EB!CO&zh z{}^09L=QIK41P^#gfB$h^OdR`62d<|8ONom!j+?GTvQN^01Yst_PeXD9)v@T5V} zm1GI1dCB1vlFQI!w5w}GZwco8yC!~7gDPBt`}WvO zzS&7A&rD4-ofSd#3!C6O9ZaaeziS2>Y|NBoR?Q>PW5Uh9fF7^ar$%I*M8O4)VhuYF z`7&ll&v~miKg-YyP5zAW3~gLO;YfyM$S54C(wt+&D@1v*E_>EcL;cpI59i*tJz^FC zRvob9$y{)A`E8dLMb6`ke6a+^8cSg!{v?)T^qC!+0oTM}q9*>6vkfa`)5vFHolxA@yG(6gDY0zRn74?N!c$iHH zof$IQ&xo7|&NF4f!Dj3SO2dMo2GcICmB@~#0aW&tI8Xmk9QGgjBMhg_RMr6VPGzRa zCckd2GZhlG>-bWnXuq89Qr07*SCgP@rhxeVdmcm;uQ|v2ejSRv$vLBaam(_A&gzn= zyUUHOBGeX&L-^{N9t|u`h9z|Aug>z+C~RFY?5Vj*isrRou+7@8WNN_SP+EN=KVbC* z&~A99|FDVkY_d6KI4yFOiprzdTm~uH-EBrFP?>WcDokgViV5J8FEgo3ww+&2+eybxp4fh3 z+qToOZQC8Q!!PIDJI?*yGsfOytsnd6+Euk?%{dD*5b8d*$BncQ^Fzd{H72HC-o$!= zxhfI&$^S?~*2pD^&E!-g5Oct92X(?hCCd3s6d*#hr`L4fT(G@Va!WEHG=zvIX6c?K z?Tk7P@bEv!Bq8EH?)xXQrq5~$9O|vDk~jx-@Xf?8=f#1uvx|NqvH|mQ^Zb63e6p}MiX4Qflcs>&_K)beHLfr z0QeQ}ui%(7O+@9S`v?tH;`jyaSij)=)$Sp_6b34!Ed(B-q(1QsZJW1D|ZK%waS3XAJIh@L`_H`tZxaKzeL>(}e}xWk-EC@Ex9esRX`;T!7?sr3 z`)+tUp8O)DQJrBr1+oNYfw)-OcUMRoX(Mw69(cnzZWkZfy~zFBoI)G8IN+3D07crn zb+L8dyXDcN$-NxH^@;v@q%Jp%a6}nV*yJd!t^9Vw_wzO;7&G4{CBDl`m!SoCR-onL z$^|d%h1*^Vo6yRfy1*S-E<1-sZNwPF<{3b?ysKkFJZ@wm# zAHS=i*Qr$|wtf%%wn5LZBCA>y5Kgy;)|)te7gdG5fJrdxY}k*hAxSE$929{_=4oTYP0kx8c5zM;2$V5i z%L*NC5$#=fHGejp*=uc{E33B@F%)ePV-R4^)EA2Mkq>V|RbG3f5C!vhtJ{HsIjf4q zMW7DURqGQ*W3C}+)Cs*>*9yH!JkH@1!J#a#J2LjZPj9R6&E@;ivnunWY6>!$h`2Iz zFN>VM%;4pRa*SR`7H%R9K#e{J3$2SVT4|OgILokUWgfbzQ@?>@V8N87W?xuGNJ(nRT=I8CZ&kJTMM?S=EM6Uf0byPS5=`yc zwpZ1=-5XbS$O_6UjgsljRt2V5A6luhle{{j7lRE^B`OCnH7H{vADHVe&Ez|%0#}WE z)EwSerEe^vi5Y+ZSYI&0b%JwPKDE9N*N1}#tOsVPFE+1L;oO3U{G93>oFD?e2y|nx zxscLLnR$=)VA;lrV({@^WVL))e80{Y7yUeJ=uJ}=9!=qW@?g~3LMvWu`Ho72cHFuA zPOKVZQ=NvBR5i9CCnuW=-_F$i$xO)bZx;nhseS1Z>kvxuqU-i8Ap1UWbQwjQL9*ke zcMs!?y+n6B>6)SzZDaQ9|9Y!TJpUJw9ktPQ{s8R%$Dyj=FGsBVHU|*=POSgOSEc6# z5*WRL1_0W98w4PYSmZyfAIQk&g86`;TOsZh!N8C}OR34Bi-M!<#M5UTNwp_-R#N!U z$dgg@+_>F!ixW{Q`(923^6!`+G^B6|n8q_MLQ^sU>tU>)I#JZds z?wXGp=gqoq#I8A*XZ!2>WrSxu?I=?^E*Bq&Bkc_vZTUFDCfkds5k&>tne~|WsFt@e zfR!7c0$q5f{d(VPG0;NB?B8E21A80>y({A7EH)Y*?N8gyBb)Jm6~`iH*0t6yE*f{y zRJw!=Lc)fr+&{Q6=DP8;&kViv8}&*T~4ng)iC*FOPTYaRQoB8xod&km!mI--+N1j*3|U-k2&OUXe{7Y_gZDS{}9t4JfvhHWYV?PLI7Fh=BDR{ro~ z3?`nMd^8V^r5233To}SEUVM@6@rU9VbbJE}8F3JwMqrwCd@x)?WJWUqk>^jAYB1?> zA~o_+P=KuFH@IN#J$@elu^lwcD-ZvA0>c0!do)>gLvc@w2 z^#uDXhyLH;fhG%tEgbT&f4nUm7!+;MYTEv?XtQlNaW%KB#hcJFbt&pDTE^VGOA)PI zM*Nk_YZs>blEy_nXDx!jtDVZxN7->O=V2E9d#`?+JhR-8H5GL>>57;%#`e zq^O6SF#0ylfgMaBSE*3{#=k>=Blb1aUN*~i@h;qUbsmNyRa%%c%XXn5@$?ePiMOW* zA>#E(6yffkbcr8RFyieyTCPu;hGN(a+{}rm2S;$+&AT!MAXls@-C|~2-P++~VVh-5#5z@Ufrmqog?h$YQLw(m zrsv(xX`(0P?a}FfS76O-ZLac_nm}`bjxqaz|CXpn5bR`Zyt6Be=;(>f?CG#Gnqs#h znJC(gl7fGx5KRX82H63iLFP|_;Uc$4=iX|7=Vvr3FZAl;V7ZLg=PvKf8+83M8vhB4 zr!Zi9!tc0PH2F7;nZZaj&MKxgPDh)kur;@#32)0r@b6@HV5y;1i;?-6%2t|HLe_!T z`1Ws2wv6SZ;OaT2n+;;O?B!qJ9TJ8C3as)O^naNfybO$-R9hhc&C1K{nJ?1Mj0GurAJ=uEwYWaTPTh& zmdjjPIwzz-NlbWB(DJRQR7PWEh@bT1{Tk>n@dIwNS!9`jlZ3ZTLnXVasO_pv2ti-9 zR^!rFHi@-8=WB(8`PVe{(alp`-fO6{a7NY9c|tm+{L*r&SShF+Qz>i>>RPIL`H3s` zJ5OW!wMsH^4BqCpq5=|*1}NyMuTHm7nBVm>;p#WM8yxPP^@~@kaQm5L>$M%}PxJ(# zsy?_o`NMjE2G6|s<{0U2O=}cwy=)Tln^7!kRIOf)UV%got4#LGaKDTS3({nH=t@8m zZ*t@}H*;}>Ssi|)b0Us%--uCY-|+|!fzr}wW>H1S=&D+3PN$$mqY#b!L)GPF1@Cv2lLg>}4;PnF zdTG{k<>1D(u%@b370U8U&u_D>KreIGq!FBiCeQlfj+*=v7nQ~j?~v9`o`}mGxAPAk z{4wpcS|39U$q56l)AuRI^agJH0f_7LV~E zo}ymR**QKFb7Y<$<6!Q19?a2jUEcFjHWT zao6O3Q95U&8wM6r;SBv7X|@@Q3IGx-iqW*Z3MVpS{14AMY(Qq0d=j@Nmb_Ldd+5EA zj!vDSPD(S3h7r?YSw}pE` z7zwN9B_0QFm<^aolyl26w+`j>vVo9EuEPMt2)v`4=mwp!24mtUGGB-Vk}LjffH<2y ziOurt*U*%v$X7b>Gme4$r8qtIo%mM`YJBx0(xv?o3p z@*XX$Ug7>tWx+)N&7c0>bNgE}qDLRu*$sg)2lajdToSAdgaxq0WffY)5imJ{K@4t*nIfp-F z6m*z86f#1#BDBs<0+vIvR5#VMMn?DupxO!InSKs*?_6yo-hGTu9OO*&?H?U*?Y+{7 zLV$BWRmVPTb%NO4LX1cAV@63S2r0zJv1-b-PloGc>kR3_quQxRL6gG%GL^&P=96+q zSJ@y51CK-qN68lG(FJ{KTf>PQD*l0PTMW;wh!GlzB1#p`02r5|)GGoFR=p%@ekESZ zA=-`}to+qffs$6LH+f=-iPkKJEf>=0sgXzQ0M8B|aJFm%)uK?#7q_mNh2o`6L+;3G z6u^Wgr|j+#?&BCr#}#$tk(PLdTp)OSYa*+hno__(U&GLqK?3$6&H4P{ImsS<;Md+4$bT|A z4?<=Q2)>ON@xEWuAHdyXa^Ms!D$*eh%@pm}qugJfLHjk039wfojg_HE>iX2mRVR5qHv6)C^Q&h>6@K~D%bqKiI*fjfirus zh6Tdp%%7~c%03V#S&ce*nuf5%w=>+%=EpwHYw2tE_cJTMf6S+)&iaet(@R6gNJ&W% z;|nofIX*aUVkZ8C#tXtj%xNexelp&#>dIU83!3!O&A=hvhi?z)Os3I^?|x{6-7(e=O%|# zc#*7mc$NeSfQ)e|taEtZzC?N2RwJv>Y3AYC!`WEsZ|T@$18XNuZvrZ~)(j;E-LHjv z(c~-!_Zix{G00lmWAS~Oo6`yG76EQG4DFgh-m?u}9ulF3f~u)e+^5oAkN!G02DM!R zoADa7nT;Y%6=P{uv5NK)B6_UMl7d*90v~M}7ca3IKp@nC2of=yBOkmm9x5JCSZ)tn zG*ibK3qlXyGr#t1IK@wlzlnenW}l`8dc?deUJqW55Ol{WE3b1L#2F@ByYiiCGXq^V zHvd|VUtL}VrW)bfZ1uHvcmXsi{8R%)#o5vDqT1L~+V>ZuFJA7KLc(UUR0vVKB+c@x1Jb^$n#sH{;1F?R2e?!)cI|=X||zY_}fCr+hR=7 zg+XPuZbk5fK5dQdVyutB3vW@3iwaXB_u==S5!Dd>rEw z8s-sF%p`XA;}Vg0`!{v;D_>d({{`^#fBoUb*kXmi7-C_-|GD;mdDC}0(KnS5321-? z&^q`>k_?O85R;+H$4ht^H8fdpcVDGn=D#4nGxWrZk(4mNCxV(}{GFbh z{xmmtw|~1|X(jw&?zrI}s|;!t?FwY8DYPVtkOuu#=OTBJW;CkW<&_;}J%-FNpfm<# zucYu?0yI}gUT7+|+paDZ`{sg&F5*jaed>iK)O$SNvWPm3Rif~f!qIL#%IgRmWHM+e zBz3{KPw4WRDGIK^x-CbX6Aqsf>)7PXX21DnI|4z2(_=L;lDYK2 z9DvcvG{fXs1!0=THND0QkZ4e%?SB@{WaRM*$uH;GCn!Cj4l618DwYsf;t z3gW_KAy`0&jNNo6TZuZhAX5$1%SHG>`?GG=#qOswv6A$O^t@D$zbvsAbJd#C;=V@F zq;EyO`YOi!WJHm5)2IY6OC!Vp!Si`ca!4_Kh`(+N6uU;8MXs5P8V-Du)?v|ObKYs85 zjnMId{xT52Dl%e#1ls2^Mipt)U|U*nOA!M5PoKWcM8ixn@C+SC2W`qGitaHHM|4|m z(g}I}{J7axDT{St>V={&o`u%aogPtMep+rr;~+T-){nw1{UQKPCjH96L_>BPxWvB>=mvWNQa<Lj1@YD%Cp7HUW# zw%rjxszRo%EYp83;&ynDP1I6Q3-&0i!`#`YQb=4&Y!QpWlfddS9u(ev2g$EoQ`e_) ze-@UQ^YG4OX&w=U$JXTPr8S!&{agQ@&czUJR9zamcu}0FCcl6iv$_wbSM!hH>OKj# z(h7Hp4INY&3jwRFLd_*}&xco@^Ot`2hW$FgA|4rT*xRUXOxOzovFuHhQ*B%1%!+Zf z+Zx9!8#>upW-3Fb!L;M13(%zEUCcXwq=$Tc%}F&t@CAKM*#AXtf5)YdTzo|%B99Fl zBIa3|PAH&!*>}TGZ9l)RScszd4r0KUuo>`0sr`0Cz^@p|&k-lk;!o7+|2)Pa=N$|f zq52ofT4*iH5sK*8bM(jvHY-`!16!UX)qwv{Jpu^5#(o9P^!dKv2UM|4+riNyO?EA3F}^_wJ%>6xISvK!9R8lO>kNqDYzHq|ySC(m7})<*xF)kdGfh zcwvLcSTF%%S$6oXLYfg0SEnOSj~AG+YgwpVS0Ya!&elnayaC+D_~1jfKQXfyUFL2b zp$TW(M63~%TYXaKm~lqP=j1IC@=81<+F-zmI?mL>^|_-qf}>_%$`1!L*!&3T$No1c z*hEvQE&mO8Uw_97iT{ZepwtWi_qTebR+WjcNRn_hOJNKT=91ttdAW?mxT4_aeEjoW zx711d2*A+SpD4z(7ek*XLhRdv=_`mJahrY7lj%+F=S^<~3qiow4e}of4%j+nYQsr7 z?oIXyeq33KZreihZv$K!;@)B(bURd*i6uRe7GxK4qk>|ee?GH2KrczaU(YP+*1*^s zw-EK?EQ-cCT6C0ST#_Vt!6d&j5?8W~1a-e!+(}3GDsOytnLt)KhuvmeA8E1uV$A(=rmM)2 z!EEqt%lSVN9IRU%K!!OI^~}f7>T=z#T?tK7P{7q_>9|xTwsos{Bp#Z>SRalq_RSp$+s_)nbGtePF@pB ze8ztDJ;V_m;H;%NOew(av6g~1<%p`yvfzKTfpU)|1}FcyWOs{!d? z4jeWJ-#Pjjn{M!BLo@mSUpL~Ub@htIJ$*_3we#3>6j*mrlO4;i>8ObKke zzyoY)zPY0<;eTzK0@rLIpaQ^9(In)h8az>M0*u$w0>L<7Ik0eU`|5b@Avjna%{icZ zHni<7-juC>1YjgtTY=l4sN|`|HCKlL3Qry$6i@fccCIJ?+9&F*4ibJGO+WixKfCtM zbiOUE06uX2739KZ!J4B}K8S;nfk=qNKL9bzakq)PX5pCGsi1NIB@vczBWMYz)_yqQ zVJOi!NTcL|&;hY>Bpjyk4QA*t5zP?FAP<^g3_kpRR*w|L99Sbxzwux}*!`1e&mKI) zUCgd7qCIhePjbSq3cTLodlY@+3#aaMTT)UU*-X3^MwS~kSb&Tr zpsJltBltRLNwTG)rZr!A^GKqXcN{lg70zwAy=ABB#Bx=~+WU7W$qNU}z8#@*M0D|} zo{j}Es**$?DnV1mR??O28_;RB5D_E=TZh@;iOP}3R|8V_n28_y^Hj8y;_AOBAPWB9@CjfBg??quGQ*X`jGBdm6%M+z*C~neimT)vyD==ZIosbYO$1M zX-{J-pZa3w5keSf$f>xz7LjyWc1fCmuG*+9zZ=J(wtSs zaTQMuf*%vL+|HKIy`jqM4cs3tf!vxvK9N!}VN7nLmPOs`fO7rT@Y!^Sk@2WZ}2ByMy*&ZHoFnocB=eIp%Qqz{$EpdM? zakJTFv9omCfMRDlB8v7R12hvZ>9$ge3HG1*CBw`%Bji~!<`@b=FU)ZGa7}Fo@mXGx z&@FpfOyP^(Q z+(<|czzSFtNND!lL0U0gJag?glGOB%XOll#l#?-MIKFaNww z{w!9)9!ncc`h&ky4*sFG_S?-~6E9|2(HCnXRxVa@9;NemlitHdLMZ1LsU-h4uD>ZVC(9z%&|sVjYp+ES zsl0vRyK2J8z)faT=m1JP)3GXBzRPrUhg>{&SRHNsGQ0-K0wnOpVxIqTV#ipp?X>?G zMmQhlhh0v_KJ(<`{!-z_7Wp>!(&kYl7(00B|3zz2XJFGcUpTUyYnY7|`Sa^iYi%{@ z?X_xZkY-EQe2A{h!l}&*!I`I3+Mlgx{r!n3IrQznKFP%R`{2R%_9tHY(l;d?XRXjV zgFctE+rT6gK<*0(<2l}Lfa7wNYM%X8 z%ncRL3B}OAg^te0r#DTKQ|xjlx{fcwY~-Kfa8DN5Z;Ugv7X<~UP-u!$yq6*^wYMw{ zHozVrofKjNh0Aj-^S8tmo=gZ&SgI?C#u2S~A8R=h;I7OVTd0-wr(3KMnVgQ0e-)$+ zX+!T&#MZMOw*K-brtyXBXh(J1OzSO~mC>uE2h5RV-7Cpq-#B@|geH$B-Y1yK7dTy} z#L!M=X&s-hZo0RegVjBpI+_t8w62(H zQhw(k098wVs_lk?!w+$r6{Idu7d5ylT^PEkH2^(yz$=S+aD@Ha12KEs3%|OH% zlpX3ky`eu{g5j8_pK~`*)RInk0Dd;-EH5F)0WKxH^yK#_Fjq0TvfcVJT$GlN5y#>5 zuzcxR+tQcRksYG`l(w<2Z}Nn6uuT0_pbQvql~(#!U?kM=v<|LFqk+Guu{W8Jz6YJui#_{#I62VURZH$N1tVt zMuh9SsYxmcF@@;Fn-V)4pzo05Tz+C`&i20w!E!kjC zK{4=(Mfw|zSWrS6`EtkIT1LmF36GN#TLW!?ParOXo({vJ%rIo?)4*Jw%(%k%&0BCA z^ZQ}pMFb^e5Yz96VAAbo%j8d4h>66jtPN+sllsft-d;b@w4uaUFejeGQA%kVDpzeu z7|x}&=)_3Jq=PiG*(~}QCo#NMtWblOJ6Q(3Uo`-)O;+saQjxR!sp=u-k(-j*i03EjHyz}EN-C)=1BZ^fSPyEYZuzLE?F#0am=9TbXaZSvJh8>e6axW(0`vP;YP1yA7*L%o}kziUadh!=U4;K zIN5cZAK>#JR=?LuV1A9~c<8wFqF0wt^M%SWT9}?*CKo;9@Jn0ckXeP7LC=jbSt&|I z%>rm`+s;NW=m(~H_rXRvycvCq^2v};f@ZO9YU%&g6#x^ z``X;Ibs)BE_06s0!Jjzxoy?{LXIY@-vivdpge>U9qLRB7dGmvM9vd+O8Q`#I8l;w{ zq!zg|iw@iM{`NZqFTpzq%g^O?l55EybBo2+g;z#5KvYgTxcItUNalSD1baI_i2lR$ zr&#z`8-@r$q8XdzD#7Y>zG((Nx*G?N?fmbq#F~RpgSn*Z^x}*F=s`;^axCUYa9Sg< z^Eb7A^m$4&qU;yQ|19}b!DI!1SL`Z8MUMMzWJw&l{a&Le$+3)ac^q`9$F2 zG{132fQB6OfWdAql+p58CK~q@Rj=ssQ4`&eSZHt{4VoM+Rav-+y0CJeYiRHuTjpj> zGTnyhXbPS(<05!1`()r;9gJeT!_@jY;UtRaqPJChdpf}>g6>;h{HfVQOBXL3;(gzZ z;lEoLQPZVz$B=bUXN`1Q$R9fA?(|c=U-F+V)`{d@zHkFdJr9w+#~~1{7aJoLQBZ5l1A2 zE~G8Y0^)w**c)s1b%p9^D%F)4K~KOr2c%bZ-N@COL$A=bR`{hE)urlGY?-I=5S;jR zmj!5-Qgd5A9V@Q>3LOKKR|j^≠j5WZKO*PC6lWWI^Njoa59k5p>;x)!s-{qRTwOcb02;T8-JEJ{nHUoDXNn~V=aC?ed_c>S zvOMmBk@JahehgqY$OJ&n-arO~3I;R!{UnXpYy286Gl)59fmh(5X3(3N@SS$P;y-!t`*{2Z>o1-} zZpuWOpWFM&L~E=N_(QE9M1}-IoK9NGnKy=#M4ih=ZSWVe4aqXL7l#~R~fU)6fA> z$X5+tfPO$3Q1$sk?vntRUT5=MG<;MNTvn59#kHPtm+#CEu>l*yT*q*KMvUpGb@fV$ zgrfg3vRqVjn?ttE$RxJ|HZ`lmiraG4>M>XGwJtxwN&l!=%()L+FTJQTW!3I_P&~#f zxSrsb^J`+%SZEj`Cn7IhyW41GK%`}6#_}0_Iv4d;cNn9^>ZS(p6lg@tVW#yQ9eIh} zV)1%hKbP)J0zqs7$B0F7P%-Ry09X7)@X?Ea;TCJurgLE#c`y>Fy~6a)1nnCI3SMjn zXB}Fr=baKCVpPQ6Yc`i7(m^&Qkld|w*|P1s%U0~nQtQJ%SGshjOyg2-cG^)W8_6K_ z6I#H@6h5&y(Uc7Ei`7EPhm1Uc*z4JW@-5V8{s_q*d6Rg|BdTB*Q7na|oy9xykUO~b zFI>6eX}f>hufGn}uqRT^o$mH>Tp=z_>D7eNB%iUwPoSPptfL)xERtI7ZkW%3*;Ts& zR(vdBkZF0VeE7DBY{Z@No!(fN_Q~qunCa!1{v!&oF#w zE}B;QtpX|h?jCae57dLmF9izYi`S^l@9`7y|FszlhM&bNfqMc%fG>q_-s9(!*U`9R zk~Wx_GICUtlHF@>%djCP`&&_uxE-05h*c8haDMDY&RCs_x2j9rUh898v%beP8x5rz% zR}<*rYps-SaW=!jq~;D+a@J&nhA7mwuXDOP=#bhe2nE}5n*zA&~hoJT*D_QyO;dV-8on9 z;7h*>ZFka68_Kj9%0wyxrzvle%56wpa(sz~8 z&fvn2)S_%DAlQ|tPc6>h+KVwM%rMF;YUI1AFj}Re)0ePQ+XdxC$*ew;}hkJqRZYTXg!keDnQn<7zjkxc=2O*ST=1t@HoW= z#43q}aqP#xCrTgyrA$@YLdrSJRnP1tPf5*DQM85i$3Y~He9&+n@pS_gSn~}i9x?y( z$Xf_IHY5Qzg=GLU|25w0)7)(%#0(ZapGI4#YF5RRnkYC4NeVTQLQT$E>VYFkUQ5?) z>?-A@_Rm;ms(zPHLBw1o0La|4RzrnReLL$Zc%1p%^XzKg>*M`}{D(x{<-tTEi~$qg z^ZWd&PL3TVgnG8iFE7^R6CNIcT@%>TkqP|G`NtxzhLUhZEI7wW{C0m#jSu z^_Zl?k8nVHlWqF0{Y}3CotV)xD4)z@F9^?=KC}tj7fXwE$TWx4x|&9-a2bxONG5w@ z_;d6`5&=NM^YD}6db*PoT2tjmi_uUVbmY5C9_IB9QzxZ!w}4TDk3w!csVibb5M@`UfNhkki?C zOxCRdO~k>}m*D9*>qOrM&wG$j`H>n9iUO2Pu>kYE_vV@(Gq5hjnv!&(2^WjTY3Cn` zv*eC+t=I%&GokkDrnRh^dG4h_M*jNcFbpBZmhmJ&I?~Lv?jHb2gb}1_>GVUG`9oa% zANGd9bilj8FhS9LzB)C&u!5d|lAe$X+sO}{>aw+8r-kR(C|%k7z$

o?Fv%)cNJ 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 YcTXf)DSq%bBM{rc7rhZQ0ssQ>FL>zZoB#j- diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3d32b9a..4825762 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,9 @@ -#Fri May 19 23:45:54 IST 2023 +#Mon Aug 14 15:44:13 IST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionSha256Sum=591855b517fc635b9e04de1d05d5e76ada3f89f5fc76f87978d1b245b4f69225 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 5912bbf..0adc8e1 100755 --- a/gradlew +++ b/gradlew @@ -1,93 +1,127 @@ -#!/usr/bin/env sh +#!/bin/sh # -# GPlayApi -# Copyright (C) 2020 Aurora OSS +# Copyright © 2015-2021 the original authors. # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -96,92 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 0f8d593..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,4 +1,20 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -9,19 +25,23 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,38 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/lib/build.gradle b/lib/build.gradle index 21e2855..0850f63 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -41,10 +41,10 @@ android { dependencies { - implementation 'com.google.protobuf:protobuf-javalite:3.22.3' + implementation 'com.google.protobuf:protobuf-javalite:3.24.0' implementation 'com.github.kittinunf.fuel:fuel:2.3.1' implementation 'com.google.code.gson:gson:2.10.1' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' } protobuf { -- GitLab From bdfb4e62d40a83bd6fd9ef925d48ce20e46be799 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Mon, 4 Sep 2023 22:50:31 +0530 Subject: [PATCH 35/82] Migrate build scripts to kotlin DSL Kotlin DSL is now the new default for build scripts Signed-off-by: Aayush Gupta --- build.gradle => build.gradle.kts | 14 ++---- lib/build.gradle | 84 -------------------------------- lib/build.gradle.kts | 83 +++++++++++++++++++++++++++++++ lib/proguard-rules.pro | 2 +- 4 files changed, 89 insertions(+), 94 deletions(-) rename build.gradle => build.gradle.kts (61%) delete mode 100644 lib/build.gradle create mode 100644 lib/build.gradle.kts diff --git a/build.gradle b/build.gradle.kts similarity index 61% rename from build.gradle rename to build.gradle.kts index fdccd58..de9168e 100644 --- a/build.gradle +++ b/build.gradle.kts @@ -14,13 +14,9 @@ */ plugins { - id 'com.android.library' version '8.1.1' apply false - id 'org.jetbrains.kotlin.android' version '1.9.0' apply false - id 'org.jetbrains.kotlin.plugin.parcelize' version '1.9.0' apply false - id 'com.google.protobuf' version '0.9.4' apply false - id 'org.jlleitschuh.gradle.ktlint' version '11.5.1' apply false -} - -task clean(type: Delete) { - delete rootProject.buildDir + id("com.android.library") version "8.1.1" apply false + id("org.jetbrains.kotlin.android") version "1.9.0" apply false + id("org.jetbrains.kotlin.plugin.parcelize") version "1.9.0" apply false + id("com.google.protobuf") version "0.9.4" apply false + id("org.jlleitschuh.gradle.ktlint") version "11.5.1" apply false } diff --git a/lib/build.gradle b/lib/build.gradle deleted file mode 100644 index 0850f63..0000000 --- a/lib/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' - id 'org.jetbrains.kotlin.plugin.parcelize' - id 'com.google.protobuf' - id 'maven-publish' - id 'org.jlleitschuh.gradle.ktlint' -} - -android { - namespace 'com.aurora.gplayapi' - compileSdk 33 - - defaultConfig { - minSdk 21 - targetSdk 33 - aarMetadata { - minCompileSdk = 21 - } - } - - buildTypes { - release { - minifyEnabled false - consumerProguardFiles 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlinOptions { - jvmTarget = '17' - } - packagingOptions { - resources { - excludes += '**/*.proto' - } - } -} - -dependencies { - - implementation 'com.google.protobuf:protobuf-javalite:3.24.0' - implementation 'com.github.kittinunf.fuel:fuel:2.3.1' - implementation 'com.google.code.gson:gson:2.10.1' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' -} - -protobuf { - protoc { - artifact = 'com.google.protobuf:protoc:3.22.3' - } - generateProtoTasks { - all().configureEach { task -> - task.builtins { - java { - option "lite" - } - } - } - } -} - -// Run "./gradlew publishReleasePublicationToLocalRepository" to generate release AAR locally -publishing { - publications { - release(MavenPublication) { - groupId = 'com.aurora' - artifactId = 'gplayapi' - version = '3.1.4' - - afterEvaluate { - from components.release - } - } - } - repositories { - maven { - name = 'local' - url = "${project.buildDir}/repo" - } - } -} diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts new file mode 100644 index 0000000..65b9430 --- /dev/null +++ b/lib/build.gradle.kts @@ -0,0 +1,83 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("org.jetbrains.kotlin.plugin.parcelize") + id("com.google.protobuf") + id("maven-publish") + id("org.jlleitschuh.gradle.ktlint") +} + +android { + namespace = "com.aurora.gplayapi" + compileSdk = 33 + + defaultConfig { + minSdk = 21 + targetSdk = 33 + aarMetadata { + minCompileSdk = 21 + } + } + + buildTypes { + release { + isMinifyEnabled = false + consumerProguardFiles("proguard-rules.pro") + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + packagingOptions { + resources { + excludes += "**/*.proto" + } + } +} + +dependencies { + + implementation("com.google.protobuf:protobuf-javalite:3.24.0") + implementation("com.github.kittinunf.fuel:fuel:2.3.1") + implementation("com.google.code.gson:gson:2.10.1") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") +} + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:3.22.3" + } + generateProtoTasks { + all().forEach { task -> + task.builtins { + create("java") { + option("lite") + } + } + } + } +} + +// Run "./gradlew publishReleasePublicationToLocalRepository" to generate release AAR locally +publishing { + publications { + afterEvaluate { + create("release") { + groupId = "com.aurora" + artifactId = "gplayapi" + version = "3.1.4" + from(components["release"]) + } + } + } + repositories { + maven { + name = "local" + url = uri("./build/repo") + } + } +} diff --git a/lib/proguard-rules.pro b/lib/proguard-rules.pro index 6159288..ee6a652 100644 --- a/lib/proguard-rules.pro +++ b/lib/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html -- GitLab From 88f0cf519ac5fb1cadbe5074441985114e2d8616 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Mon, 4 Sep 2023 22:51:41 +0530 Subject: [PATCH 36/82] lib: Drop deprecated targetSdk version Ref: https://issuetracker.google.com/issues/230625468 Signed-off-by: Aayush Gupta --- lib/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 65b9430..4579b5b 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -13,7 +13,6 @@ android { defaultConfig { minSdk = 21 - targetSdk = 33 aarMetadata { minCompileSdk = 21 } -- GitLab From 2d5fb1c59fd8187e9c42044286e40a476d93b81d Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Mon, 4 Sep 2023 22:52:25 +0530 Subject: [PATCH 37/82] lib: Migrate from packagingOptions to packaging - packagingOptions has been deprecated Signed-off-by: Aayush Gupta --- lib/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 4579b5b..1ac8358 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -31,7 +31,7 @@ android { kotlinOptions { jvmTarget = JavaVersion.VERSION_17.toString() } - packagingOptions { + packaging { resources { excludes += "**/*.proto" } -- GitLab From f27fcde19866eb86ff3297708096638445ed94b4 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 7 Sep 2023 12:15:16 +0530 Subject: [PATCH 38/82] fixup! Migrate build scripts to kotlin DSL Signed-off-by: Aayush Gupta --- settings.gradle => settings.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename settings.gradle => settings.gradle.kts (95%) diff --git a/settings.gradle b/settings.gradle.kts similarity index 95% rename from settings.gradle rename to settings.gradle.kts index dfc8cc4..92d45e1 100644 --- a/settings.gradle +++ b/settings.gradle.kts @@ -27,5 +27,5 @@ dependencyResolutionManagement { mavenCentral() } } -rootProject.name = 'gplayapi' -include ':lib' +rootProject.name = "gplayapi" +include(":lib") -- GitLab From dd57dc2ce45b17e2b25feee0fafd14d92170dfc7 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Tue, 19 Sep 2023 14:31:49 +0530 Subject: [PATCH 39/82] test: Drop unused test Signed-off-by: Aayush Gupta --- lib/src/test/java/com/aurora/gplayapi/SampleTest.kt | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 lib/src/test/java/com/aurora/gplayapi/SampleTest.kt diff --git a/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt b/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt deleted file mode 100644 index 4e588bd..0000000 --- a/lib/src/test/java/com/aurora/gplayapi/SampleTest.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.aurora.gplayapi - -object SampleTest { - @JvmStatic - fun main(args: Array) { - } -} -- GitLab From 5321c0bb55a9d05fffda447963061b5565bda28a Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Tue, 19 Sep 2023 14:54:22 +0530 Subject: [PATCH 40/82] sampleapp: Initial commit Signed-off-by: Aayush Gupta --- build.gradle.kts | 5 +- sampleapp/.gitignore | 1 + sampleapp/build.gradle.kts | 79 +++++++++++++++++++ sampleapp/proguard-rules.pro | 21 +++++ sampleapp/src/main/AndroidManifest.xml | 23 ++++++ .../java/com/aurora/sampleapp/MainActivity.kt | 77 ++++++++++++++++++ .../aurora/sampleapp/MainActivityViewModel.kt | 38 +++++++++ .../com/aurora/sampleapp/ui/theme/Theme.kt | 43 ++++++++++ .../res/drawable/ic_launcher_foreground.xml | 15 ++++ .../main/res/mipmap-anydpi/ic_launcher.xml | 5 ++ sampleapp/src/main/res/values/colors.xml | 4 + sampleapp/src/main/res/values/strings.xml | 3 + sampleapp/src/main/res/values/themes.xml | 5 ++ settings.gradle.kts | 1 + 14 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 sampleapp/.gitignore create mode 100644 sampleapp/build.gradle.kts create mode 100644 sampleapp/proguard-rules.pro create mode 100644 sampleapp/src/main/AndroidManifest.xml create mode 100644 sampleapp/src/main/java/com/aurora/sampleapp/MainActivity.kt create mode 100644 sampleapp/src/main/java/com/aurora/sampleapp/MainActivityViewModel.kt create mode 100644 sampleapp/src/main/java/com/aurora/sampleapp/ui/theme/Theme.kt create mode 100644 sampleapp/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 sampleapp/src/main/res/mipmap-anydpi/ic_launcher.xml create mode 100644 sampleapp/src/main/res/values/colors.xml create mode 100644 sampleapp/src/main/res/values/strings.xml create mode 100644 sampleapp/src/main/res/values/themes.xml diff --git a/build.gradle.kts b/build.gradle.kts index de9168e..91eb3d7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,9 +14,10 @@ */ plugins { + id("com.android.application") version "8.1.1" apply false id("com.android.library") version "8.1.1" apply false - id("org.jetbrains.kotlin.android") version "1.9.0" apply false - id("org.jetbrains.kotlin.plugin.parcelize") version "1.9.0" apply false + id("org.jetbrains.kotlin.android") version "1.9.10" apply false + id("org.jetbrains.kotlin.plugin.parcelize") version "1.9.10" apply false id("com.google.protobuf") version "0.9.4" apply false id("org.jlleitschuh.gradle.ktlint") version "11.5.1" apply false } diff --git a/sampleapp/.gitignore b/sampleapp/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/sampleapp/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/sampleapp/build.gradle.kts b/sampleapp/build.gradle.kts new file mode 100644 index 0000000..a4d0ff7 --- /dev/null +++ b/sampleapp/build.gradle.kts @@ -0,0 +1,79 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "com.aurora.sampleapp" + compileSdk = 34 + + defaultConfig { + applicationId = "com.aurora.sampleapp" + minSdk = 33 + targetSdk = 33 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + buildConfigField("String", "GPLAY_API_EMAIL", "\"${System.getenv("GPLAY_API_EMAIL")}\"") + buildConfigField("String", "GPLAY_API_TOKEN", "\"${System.getenv("GPLAY_API_TOKEN")}\"") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + buildFeatures { + buildConfig = true + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.3" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + + // API + implementation(project(":lib")) + + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") + implementation("androidx.activity:activity-compose:1.7.2") + implementation(platform("androidx.compose:compose-bom:2023.08.00")) + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.ui:ui-graphics") + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.compose.material3:material3") + + // Coil + implementation("io.coil-kt:coil-compose:2.4.0") + + // LifeCycle + val lifecycleVersion = "2.6.2" + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion") + implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycleVersion") + + // Protobuf + implementation("com.google.protobuf:protobuf-javalite:3.24.2") +} diff --git a/sampleapp/proguard-rules.pro b/sampleapp/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/sampleapp/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/sampleapp/src/main/AndroidManifest.xml b/sampleapp/src/main/AndroidManifest.xml new file mode 100644 index 0000000..893b961 --- /dev/null +++ b/sampleapp/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/sampleapp/src/main/java/com/aurora/sampleapp/MainActivity.kt b/sampleapp/src/main/java/com/aurora/sampleapp/MainActivity.kt new file mode 100644 index 0000000..b01146c --- /dev/null +++ b/sampleapp/src/main/java/com/aurora/sampleapp/MainActivity.kt @@ -0,0 +1,77 @@ +package com.aurora.sampleapp + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.viewModels +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import coil.compose.AsyncImage +import com.aurora.gplayapi.data.models.AuthData +import com.aurora.sampleapp.ui.theme.GPlayApiTheme + +class MainActivity : ComponentActivity() { + + private val viewModel: MainActivityViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + GPlayApiTheme { + Scaffold() { + val context = LocalContext.current + LaunchedEffect(key1 = Unit) { viewModel.buildAuthData(context) } + + Column( + modifier = Modifier + .padding(it) + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + + val authData: AuthData by viewModel.authData.collectAsStateWithLifecycle() + + if (authData.email.isNotBlank()) { + AsyncImage( + modifier = Modifier + .padding(10.dp) + .requiredSize(192.dp) + .clip(RoundedCornerShape(20.dp)), + model = authData.userProfile?.artwork?.url, + contentDescription = "" + ) + + Text( + modifier = Modifier.padding(vertical = 20.dp), + text = authData.email + ) + + Button(onClick = { viewModel.doSomething(context) }) { + Text(text = "Do something!") + } + } else { + CircularProgressIndicator(modifier = Modifier.requiredSize(100.dp)) + } + } + } + } + } + } +} diff --git a/sampleapp/src/main/java/com/aurora/sampleapp/MainActivityViewModel.kt b/sampleapp/src/main/java/com/aurora/sampleapp/MainActivityViewModel.kt new file mode 100644 index 0000000..a47788b --- /dev/null +++ b/sampleapp/src/main/java/com/aurora/sampleapp/MainActivityViewModel.kt @@ -0,0 +1,38 @@ +package com.aurora.sampleapp + +import android.content.Context +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.aurora.gplayapi.DeviceManager +import com.aurora.gplayapi.data.models.AuthData +import com.aurora.gplayapi.helpers.AuthHelper +import java.util.Properties +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +class MainActivityViewModel : ViewModel() { + + private val _authData = MutableStateFlow(AuthData("", "")) + val authData = _authData.asStateFlow() + + fun buildAuthData(context: Context) { + viewModelScope.launch(Dispatchers.IO) { + val properties = Properties() + context.resources.openRawResource(com.aurora.gplayapi.R.raw.gplayapi_px_7a).use { + properties.load(it) + } + + _authData.value = AuthHelper.build( + BuildConfig.GPLAY_API_EMAIL, + BuildConfig.GPLAY_API_TOKEN, + properties + ) + } + } + + fun doSomething(context: Context) { + // Run the thing you want to test here! + } +} diff --git a/sampleapp/src/main/java/com/aurora/sampleapp/ui/theme/Theme.kt b/sampleapp/src/main/java/com/aurora/sampleapp/ui/theme/Theme.kt new file mode 100644 index 0000000..6acb6b7 --- /dev/null +++ b/sampleapp/src/main/java/com/aurora/sampleapp/ui/theme/Theme.kt @@ -0,0 +1,43 @@ +package com.aurora.sampleapp.ui.theme + +import android.app.Activity +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Typography +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat + +@Composable +fun GPlayApiTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { + val context = LocalContext.current + val colorScheme = if (darkTheme) { + dynamicDarkColorScheme(context) + } else { + dynamicLightColorScheme(context) + } + + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.background.toArgb() + window.navigationBarColor = colorScheme.background.toArgb() + WindowCompat.getInsetsController(window, view).apply { + isAppearanceLightStatusBars = !darkTheme + isAppearanceLightNavigationBars = !darkTheme + } + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography(), + content = content + ) +} diff --git a/sampleapp/src/main/res/drawable/ic_launcher_foreground.xml b/sampleapp/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..9cc493d --- /dev/null +++ b/sampleapp/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/sampleapp/src/main/res/mipmap-anydpi/ic_launcher.xml b/sampleapp/src/main/res/mipmap-anydpi/ic_launcher.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/sampleapp/src/main/res/mipmap-anydpi/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/sampleapp/src/main/res/values/colors.xml b/sampleapp/src/main/res/values/colors.xml new file mode 100644 index 0000000..ad6f6d9 --- /dev/null +++ b/sampleapp/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + + #3DDC84 + diff --git a/sampleapp/src/main/res/values/strings.xml b/sampleapp/src/main/res/values/strings.xml new file mode 100644 index 0000000..d40f731 --- /dev/null +++ b/sampleapp/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Sample App + \ No newline at end of file diff --git a/sampleapp/src/main/res/values/themes.xml b/sampleapp/src/main/res/values/themes.xml new file mode 100644 index 0000000..55f4d44 --- /dev/null +++ b/sampleapp/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +