From 239dae2e46674715040f31770b428e96283648dd Mon Sep 17 00:00:00 2001 From: Alex Gotev Date: Sun, 9 Jul 2023 13:27:48 +0200 Subject: [PATCH 1/5] feat: updated all dependencies, gradle and bumped target SDK to 33 --- examples/app/.idea/gradle.xml | 2 +- examples/app/demoapp/build.gradle | 5 ++-- .../app/demoapp/src/main/AndroidManifest.xml | 3 +- examples/app/gradle.properties | 1 + .../gradle/wrapper/gradle-wrapper.properties | 4 +-- gradle.properties | 1 + gradle/wrapper/gradle-wrapper.properties | 2 +- manifest.gradle | 28 +++++++++---------- uploadservice-ftp/build.gradle | 5 ++-- .../src/main/AndroidManifest.xml | 2 +- uploadservice-okhttp/build.gradle | 5 ++-- .../src/main/AndroidManifest.xml | 2 +- .../uploadservice/okhttp/OkHttpExtensions.kt | 3 +- .../okhttp/OkHttpStackRequest.kt | 3 +- uploadservice/build.gradle | 5 ++-- uploadservice/src/main/AndroidManifest.xml | 3 +- .../gotev/uploadservice/HttpUploadRequest.kt | 3 +- .../extensions/StringExtensions.kt | 5 ++-- .../persistence/PersistableData.kt | 2 +- .../protocols/binary/BinaryUploadTask.kt | 3 +- 20 files changed, 43 insertions(+), 44 deletions(-) diff --git a/examples/app/.idea/gradle.xml b/examples/app/.idea/gradle.xml index 3fef248f..e784d877 100644 --- a/examples/app/.idea/gradle.xml +++ b/examples/app/.idea/gradle.xml @@ -8,6 +8,7 @@ - diff --git a/examples/app/demoapp/build.gradle b/examples/app/demoapp/build.gradle index 76bac481..2393bff6 100644 --- a/examples/app/demoapp/build.gradle +++ b/examples/app/demoapp/build.gradle @@ -2,6 +2,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android { + namespace "net.gotev.uploadservicedemo" compileSdkVersion target_sdk defaultConfig { @@ -31,8 +32,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } } diff --git a/examples/app/demoapp/src/main/AndroidManifest.xml b/examples/app/demoapp/src/main/AndroidManifest.xml index 81349435..b34b9b7e 100644 --- a/examples/app/demoapp/src/main/AndroidManifest.xml +++ b/examples/app/demoapp/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + + diff --git a/uploadservice-okhttp/build.gradle b/uploadservice-okhttp/build.gradle index 6446f947..381f6ec9 100644 --- a/uploadservice-okhttp/build.gradle +++ b/uploadservice-okhttp/build.gradle @@ -20,6 +20,7 @@ group = library_project_group version = library_version android { + namespace "net.gotev.uploadservice.okhttp" compileSdkVersion target_sdk defaultConfig { @@ -38,8 +39,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } lintOptions { diff --git a/uploadservice-okhttp/src/main/AndroidManifest.xml b/uploadservice-okhttp/src/main/AndroidManifest.xml index 44ca342a..97577c33 100644 --- a/uploadservice-okhttp/src/main/AndroidManifest.xml +++ b/uploadservice-okhttp/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - + diff --git a/uploadservice-okhttp/src/main/java/net/gotev/uploadservice/okhttp/OkHttpExtensions.kt b/uploadservice-okhttp/src/main/java/net/gotev/uploadservice/okhttp/OkHttpExtensions.kt index c28e3dfe..66c2b3f8 100644 --- a/uploadservice-okhttp/src/main/java/net/gotev/uploadservice/okhttp/OkHttpExtensions.kt +++ b/uploadservice-okhttp/src/main/java/net/gotev/uploadservice/okhttp/OkHttpExtensions.kt @@ -1,6 +1,5 @@ package net.gotev.uploadservice.okhttp -import java.util.Locale import net.gotev.uploadservice.network.ServerResponse import okhttp3.Response @@ -13,7 +12,7 @@ private fun String.requiresRequestBody() = private fun String.permitsRequestBody() = !(this == "GET" || this == "HEAD") internal fun String.hasBody(): Boolean { - val method = trim().toUpperCase(Locale.getDefault()) + val method = trim().uppercase() return method.permitsRequestBody() || method.requiresRequestBody() } diff --git a/uploadservice-okhttp/src/main/java/net/gotev/uploadservice/okhttp/OkHttpStackRequest.kt b/uploadservice-okhttp/src/main/java/net/gotev/uploadservice/okhttp/OkHttpStackRequest.kt index fb13a535..612c4d02 100644 --- a/uploadservice-okhttp/src/main/java/net/gotev/uploadservice/okhttp/OkHttpStackRequest.kt +++ b/uploadservice-okhttp/src/main/java/net/gotev/uploadservice/okhttp/OkHttpStackRequest.kt @@ -12,7 +12,6 @@ import okhttp3.RequestBody import okio.BufferedSink import java.io.IOException import java.net.URL -import java.util.Locale import java.util.UUID /** @@ -41,7 +40,7 @@ class OkHttpStackRequest( @Throws(IOException::class) override fun setHeaders(requestHeaders: List): HttpRequest { for (param in requestHeaders) { - if ("content-type" == param.name.trim().toLowerCase(Locale.getDefault())) + if ("content-type" == param.name.trim().lowercase()) contentType = param.value.trim().toMediaTypeOrNull() requestBuilder.header(param.name.trim(), param.value.trim()) diff --git a/uploadservice/build.gradle b/uploadservice/build.gradle index 771ac750..b7d8a326 100644 --- a/uploadservice/build.gradle +++ b/uploadservice/build.gradle @@ -21,6 +21,7 @@ group = library_project_group version = library_version android { + namespace "net.gotev.uploadservice" compileSdkVersion target_sdk defaultConfig { @@ -45,8 +46,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } lintOptions { diff --git a/uploadservice/src/main/AndroidManifest.xml b/uploadservice/src/main/AndroidManifest.xml index bd360818..e1d9524f 100644 --- a/uploadservice/src/main/AndroidManifest.xml +++ b/uploadservice/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/uploadservice/src/main/java/net/gotev/uploadservice/HttpUploadRequest.kt b/uploadservice/src/main/java/net/gotev/uploadservice/HttpUploadRequest.kt index f1753606..1590d166 100644 --- a/uploadservice/src/main/java/net/gotev/uploadservice/HttpUploadRequest.kt +++ b/uploadservice/src/main/java/net/gotev/uploadservice/HttpUploadRequest.kt @@ -6,7 +6,6 @@ import net.gotev.uploadservice.data.HttpUploadTaskParameters import net.gotev.uploadservice.data.NameValue import net.gotev.uploadservice.extensions.addHeader import net.gotev.uploadservice.extensions.isValidHttpUrl -import java.util.Locale /** * Represents a generic HTTP upload request.

@@ -104,7 +103,7 @@ abstract class HttpUploadRequest>(context: Context, ser * @return self instance */ fun setMethod(method: String): B { - httpParams.method = method.toUpperCase(Locale.ROOT) + httpParams.method = method.uppercase() return self() } diff --git a/uploadservice/src/main/java/net/gotev/uploadservice/extensions/StringExtensions.kt b/uploadservice/src/main/java/net/gotev/uploadservice/extensions/StringExtensions.kt index 92ea4907..d09a825d 100644 --- a/uploadservice/src/main/java/net/gotev/uploadservice/extensions/StringExtensions.kt +++ b/uploadservice/src/main/java/net/gotev/uploadservice/extensions/StringExtensions.kt @@ -2,7 +2,6 @@ package net.gotev.uploadservice.extensions import android.webkit.MimeTypeMap import java.net.URL -import java.util.Locale internal const val APPLICATION_OCTET_STREAM = "application/octet-stream" internal const val VIDEO_MP4 = "video/mp4" @@ -17,7 +16,7 @@ fun String.autoDetectMimeType(): String { val index = lastIndexOf(".") return if (index in 0 until lastIndex) { - val extension = substring(index + 1).toLowerCase(Locale.getDefault()) + val extension = substring(index + 1).lowercase() if (extension == "mp4") { VIDEO_MP4 @@ -35,7 +34,7 @@ fun String?.isASCII(): Boolean { return false for (index in 0 until length) { - if (this[index].toInt() > 127) { + if (this[index].code > 127) { return false } } diff --git a/uploadservice/src/main/java/net/gotev/uploadservice/persistence/PersistableData.kt b/uploadservice/src/main/java/net/gotev/uploadservice/persistence/PersistableData.kt index 44b0a291..e4890a00 100644 --- a/uploadservice/src/main/java/net/gotev/uploadservice/persistence/PersistableData.kt +++ b/uploadservice/src/main/java/net/gotev/uploadservice/persistence/PersistableData.kt @@ -42,7 +42,7 @@ open class PersistableData() : Parcelable { override fun describeContents() = 0 - override fun writeToParcel(dest: Parcel?, flags: Int) { + override fun writeToParcel(dest: Parcel, flags: Int) { toBundle().writeToParcel(dest, flags) } diff --git a/uploadservice/src/main/java/net/gotev/uploadservice/protocols/binary/BinaryUploadTask.kt b/uploadservice/src/main/java/net/gotev/uploadservice/protocols/binary/BinaryUploadTask.kt index a5db2bf7..d921fcc3 100644 --- a/uploadservice/src/main/java/net/gotev/uploadservice/protocols/binary/BinaryUploadTask.kt +++ b/uploadservice/src/main/java/net/gotev/uploadservice/protocols/binary/BinaryUploadTask.kt @@ -3,7 +3,6 @@ package net.gotev.uploadservice.protocols.binary import net.gotev.uploadservice.HttpUploadTask import net.gotev.uploadservice.extensions.addHeader import net.gotev.uploadservice.network.BodyWriter -import java.util.Locale /** * Implements a binary file upload task. @@ -16,7 +15,7 @@ class BinaryUploadTask : HttpUploadTask() { override fun performInitialization() { with(httpParams.requestHeaders) { - if (none { it.name.toLowerCase(Locale.getDefault()) == "content-type" }) { + if (none { it.name.lowercase() == "content-type" }) { addHeader("Content-Type", file.contentType(context)) } } From c487e9982a690ed307bd9cd976509dd2249d0fbe Mon Sep 17 00:00:00 2001 From: Alex Gotev Date: Sun, 9 Jul 2023 14:19:20 +0200 Subject: [PATCH 2/5] feat: updated library manifest to include POST_NOTIFICATIONS permission and demo app to request notifications permissions on demand on android API 33+ --- .../activities/BaseActivity.kt | 21 +++++++++++++++++++ uploadservice/src/main/AndroidManifest.xml | 1 + 2 files changed, 22 insertions(+) diff --git a/examples/app/demoapp/src/main/java/net/gotev/uploadservicedemo/activities/BaseActivity.kt b/examples/app/demoapp/src/main/java/net/gotev/uploadservicedemo/activities/BaseActivity.kt index 7ced95d5..f3dfe8cb 100644 --- a/examples/app/demoapp/src/main/java/net/gotev/uploadservicedemo/activities/BaseActivity.kt +++ b/examples/app/demoapp/src/main/java/net/gotev/uploadservicedemo/activities/BaseActivity.kt @@ -1,12 +1,17 @@ package net.gotev.uploadservicedemo.activities +import android.Manifest import android.app.PendingIntent import android.content.Intent +import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.Color import android.os.Build +import android.os.Bundle +import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import net.gotev.uploadservice.data.UploadNotificationAction import net.gotev.uploadservice.data.UploadNotificationConfig import net.gotev.uploadservice.data.UploadNotificationStatusConfig @@ -19,6 +24,22 @@ import net.gotev.uploadservicedemo.extensions.inputMethodManager import java.util.ArrayList open class BaseActivity : AppCompatActivity() { + + private val notificationPermissionRequest = registerForActivityResult(ActivityResultContracts.RequestPermission()) { + // custom logic when the user either allows or disallows notifications + } + + private fun checkPostNotificationsPermission() { + if (Build.VERSION.SDK_INT >= 33 && ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { + notificationPermissionRequest.launch(Manifest.permission.POST_NOTIFICATIONS) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + checkPostNotificationsPermission() + } + override fun onPause() { super.onPause() diff --git a/uploadservice/src/main/AndroidManifest.xml b/uploadservice/src/main/AndroidManifest.xml index e1d9524f..61d63087 100644 --- a/uploadservice/src/main/AndroidManifest.xml +++ b/uploadservice/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ + From d44fc997d558253bf063b4b1470ee8deda23fb2f Mon Sep 17 00:00:00 2001 From: Alex Gotev Date: Sun, 9 Jul 2023 14:28:03 +0200 Subject: [PATCH 3/5] ci: bump java to 17 and API to 33 --- .github/workflows/android.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index b72ca9f4..988fdfe3 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -18,7 +18,7 @@ jobs: - name: run tests uses: reactivecircus/android-emulator-runner@v2 with: - api-level: 31 + api-level: 33 script: ./gradlew connectedCheck unit-test-and-build: @@ -29,7 +29,7 @@ jobs: - name: set up JDK uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Unit Test run: ./gradlew testDebugUnitTest - name: Android Test Report @@ -46,6 +46,6 @@ jobs: - name: set up JDK uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Build with Gradle run: cd examples/app && ./gradlew clean assembleDebug From 08c4fbf423dfc3ef8fc58756edd4eb80b7600b66 Mon Sep 17 00:00:00 2001 From: Alex Gotev Date: Sun, 9 Jul 2023 14:37:06 +0200 Subject: [PATCH 4/5] readme: update for android 13 --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aefbd8fd..7f26ccf5 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,9 @@ You are also safe if your app is put in the background. All the uploads will con Bear in mind that if you kill your app, the service gets killed as well, as it's attached to your app's process and all the currently running uploads will be terminated abruptly. ## Features -* Android 5.0 (API 21) to Android 12 (API 31) support. +* Android 5.0 (API 21) to Android 13 (API 33) support. + * *Android 13 Note, for apps targeting API 33 or newer*: + * Due to new behavior changes, you are [required to request POST_NOTIFICATIONS permission at runtime in your app](https://developer.android.com/develop/ui/views/notifications/notification-permission) or else the upload progress won't be shown. To see an example, please look at the BaseActivity in the `examples/app` folder. * *Android 12 Note, for apps targeting API 31 or newer*: * What's supported: uploads initiated while the app is in foreground, with progress indication notification * What's NOT supported: uploads started while the app is in the background or uploads without progress indication notification. This is due to the Service limitations imposed by Google, which requires all background services to display a notification to the user. Current architecture cannot support this. For support of those use-cases, WorkManager is the only option. From 7d6bddcc77f9b2c8bc65d64bbb783323dca7ccee Mon Sep 17 00:00:00 2001 From: Alex Gotev Date: Sun, 9 Jul 2023 15:23:48 +0200 Subject: [PATCH 5/5] feat: updated SimpleMultipartUpload demo app --- .../SimpleMultipartUpload/app/build.gradle | 30 ++++++++++++------- .../app/src/main/AndroidManifest.xml | 8 +++-- .../java/it/gotev/testapp/MainActivity.kt | 16 ++++++++++ examples/SimpleMultipartUpload/build.gradle | 11 +++++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 7 files changed, 52 insertions(+), 19 deletions(-) diff --git a/examples/SimpleMultipartUpload/app/build.gradle b/examples/SimpleMultipartUpload/app/build.gradle index 9fde6c45..e8d152ff 100644 --- a/examples/SimpleMultipartUpload/app/build.gradle +++ b/examples/SimpleMultipartUpload/app/build.gradle @@ -2,34 +2,42 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android { - compileSdkVersion 30 + namespace "it.gotev.testapp" + compileSdkVersion target_sdk + defaultConfig { applicationId "it.gotev.testapp" minSdkVersion 21 - targetSdkVersion 30 - versionCode 2 - versionName "1.1" + targetSdkVersion target_sdk + versionCode 3 + versionName "1.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.3.0' - implementation 'androidx.core:core-ktx:1.5.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' - testImplementation 'junit:junit:4.13' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'androidx.core:core-ktx:1.10.1' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' - def uploadServiceVersion = "4.5.5" + def uploadServiceVersion = "4.7.0" implementation "net.gotev:uploadservice:$uploadServiceVersion" } diff --git a/examples/SimpleMultipartUpload/app/src/main/AndroidManifest.xml b/examples/SimpleMultipartUpload/app/src/main/AndroidManifest.xml index f9ec4c43..685f4343 100644 --- a/examples/SimpleMultipartUpload/app/src/main/AndroidManifest.xml +++ b/examples/SimpleMultipartUpload/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ - + + + - + diff --git a/examples/SimpleMultipartUpload/app/src/main/java/it/gotev/testapp/MainActivity.kt b/examples/SimpleMultipartUpload/app/src/main/java/it/gotev/testapp/MainActivity.kt index f7f0f27b..963fdc7c 100644 --- a/examples/SimpleMultipartUpload/app/src/main/java/it/gotev/testapp/MainActivity.kt +++ b/examples/SimpleMultipartUpload/app/src/main/java/it/gotev/testapp/MainActivity.kt @@ -1,10 +1,15 @@ package it.gotev.testapp +import android.Manifest import android.app.Activity import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build import android.os.Bundle import android.widget.Button +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import net.gotev.uploadservice.protocols.multipart.MultipartUploadRequest class MainActivity : AppCompatActivity() { @@ -15,9 +20,20 @@ class MainActivity : AppCompatActivity() { const val pickFileRequestCode = 42 } + private val notificationPermissionRequest = registerForActivityResult(ActivityResultContracts.RequestPermission()) { + // custom logic when the user either allows or disallows notifications + } + + private fun checkPostNotificationsPermission() { + if (Build.VERSION.SDK_INT >= 33 && ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { + notificationPermissionRequest.launch(Manifest.permission.POST_NOTIFICATIONS) + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + checkPostNotificationsPermission() findViewById