Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support for android API 34 #647

Merged
merged 2 commits into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ 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 <a name="features"></a>
* Android 5.0 (API 21) to Android 13 (API 33) support.
* Android 5.0 (API 21) to Android 14 (API 34) 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*:
Expand Down
2 changes: 1 addition & 1 deletion examples/app/.idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion manifest.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ext {
library_version = '4.8.0'
version_code = 49
min_sdk = 21
target_sdk = 33
target_sdk = 34
demo_app_id = 'net.gotev.uploadservicedemo'

// Gradle classpath dependencies versions
Expand Down
2 changes: 1 addition & 1 deletion uploadservice-ftp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ dependencies {

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

api 'commons-net:commons-net:3.8.0'
api 'commons-net:commons-net:3.10.0'
//api "net.gotev:uploadservice:${version}"
//comment the previous line and uncomment the next line for development (it uses the local lib)
api project(':uploadservice')
Expand Down
2 changes: 1 addition & 1 deletion uploadservice-okhttp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ dependencies {

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

api 'com.squareup.okhttp3:okhttp:4.9.2'
api 'com.squareup.okhttp3:okhttp:4.10.0'
//api "net.gotev:uploadservice:${version}"
//comment the previous line and uncomment the next line for development (it uses the local lib)
api project(':uploadservice')
Expand Down
2 changes: 1 addition & 1 deletion uploadservice/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ version = library_version

android {
namespace "net.gotev.uploadservice"
compileSdkVersion target_sdk

defaultConfig {
compileSdk target_sdk
minSdkVersion min_sdk
targetSdkVersion target_sdk
versionCode version_code
Expand Down
4 changes: 3 additions & 1 deletion uploadservice/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />

<application>

<service
android:name=".UploadService"
android:foregroundServiceType="dataSync"
android:enabled="true"
android:exported="false"></service>
android:exported="false" />

</application>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Notification
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import androidx.core.app.NotificationCompat
Expand Down Expand Up @@ -165,6 +166,15 @@ class UploadService : Service() {
return false
}

private fun stopServiceForeground() {
if (Build.VERSION.SDK_INT >= 24) {
stopForeground(STOP_FOREGROUND_REMOVE)
} else {
@Suppress("DEPRECATION")
stopForeground(true)
}
}

/**
* Called by each task when it is completed (either successfully, with an error or due to
* user cancellation).
Expand All @@ -182,7 +192,7 @@ class UploadService : Service() {

if (UploadServiceConfig.isForegroundService && uploadTasksMap.isEmpty()) {
UploadServiceLogger.debug(TAG, NA) { "All tasks completed, stopping foreground execution" }
stopForeground(true)
stopServiceForeground()
shutdownIfThereArentAnyActiveTasks()
}
}
Expand Down Expand Up @@ -248,7 +258,7 @@ class UploadService : Service() {

if (UploadServiceConfig.isForegroundService) {
UploadServiceLogger.debug(TAG, NA) { "Stopping foreground execution" }
stopForeground(true)
stopServiceForeground()
}

wakeLock.safeRelease()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Intent
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import net.gotev.uploadservice.UploadServiceConfig
import net.gotev.uploadservice.extensions.parcelableCompat
import net.gotev.uploadservice.network.ServerResponse

@Parcelize
Expand All @@ -17,7 +18,7 @@ internal data class BroadcastData @JvmOverloads constructor(
private const val paramName = "broadcastData"

fun fromIntent(intent: Intent): BroadcastData? {
return intent.getParcelableExtra(paramName)
return intent.parcelableCompat(paramName)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package net.gotev.uploadservice.extensions

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Context.RECEIVER_NOT_EXPORTED
import android.content.Intent
import android.os.Build
import android.content.IntentFilter
import android.os.Build.VERSION.SDK_INT
import android.os.Parcelable
import net.gotev.uploadservice.UploadService
import net.gotev.uploadservice.UploadServiceConfig
import net.gotev.uploadservice.UploadTask
Expand Down Expand Up @@ -43,7 +48,7 @@ fun Context.startNewUpload(
*/
startService(intent)
} catch (exc: Throwable) {
if (Build.VERSION.SDK_INT >= 26 && exc is IllegalStateException) {
if (SDK_INT >= 26 && exc is IllegalStateException) {
/*
this is a bugged Android API and Google is not going to fix it

Expand Down Expand Up @@ -79,7 +84,6 @@ data class UploadTaskCreationParameters(
val notificationConfig: UploadNotificationConfig
)

@Suppress("UNCHECKED_CAST")
fun Intent?.getUploadTaskCreationParameters(): UploadTaskCreationParameters? {
if (this == null || action != UploadServiceConfig.uploadAction) {
UploadServiceLogger.error(
Expand All @@ -92,7 +96,7 @@ fun Intent?.getUploadTaskCreationParameters(): UploadTaskCreationParameters? {
return null
}

val params: UploadTaskParameters = getParcelableExtra(taskParametersKey) ?: run {
val params: UploadTaskParameters = parcelableCompat(taskParametersKey) ?: run {
UploadServiceLogger.error(
component = UploadService.TAG,
uploadId = NA,
Expand Down Expand Up @@ -129,7 +133,7 @@ fun Intent?.getUploadTaskCreationParameters(): UploadTaskCreationParameters? {
}

val notificationConfig: UploadNotificationConfig =
getParcelableExtra(taskNotificationConfig) ?: run {
parcelableCompat(taskNotificationConfig) ?: run {
UploadServiceLogger.error(
component = UploadService.TAG,
uploadId = NA,
Expand All @@ -148,7 +152,6 @@ fun Intent?.getUploadTaskCreationParameters(): UploadTaskCreationParameters? {

/**
* Creates a new task instance based on the requested task class in the intent.
* @param intent intent passed to the service
* @return task instance or null if the task class is not supported or invalid
*/
@Suppress("UNCHECKED_CAST")
Expand Down Expand Up @@ -221,9 +224,23 @@ val Intent.uploadIdToCancel: String?

// Adjusts flags for Android 12+
fun flagsCompat(flags: Int): Int {
if (Build.VERSION.SDK_INT > 30) {
if (SDK_INT > 30) {
return flags or PendingIntent.FLAG_IMMUTABLE
}

return flags
}

inline fun <reified T : Parcelable> Intent.parcelableCompat(key: String): T? = when {
SDK_INT >= 34 -> getParcelableExtra(key, T::class.java)
else -> @Suppress("DEPRECATION") getParcelableExtra(key) as? T
}

@SuppressLint("UnspecifiedRegisterReceiverFlag")
fun Context.registerReceiverCompat(receiver: BroadcastReceiver, filter: IntentFilter) {
if (SDK_INT >= 34) {
registerReceiver(receiver, filter, RECEIVER_NOT_EXPORTED)
} else {
registerReceiver(receiver, filter)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import net.gotev.uploadservice.UploadServiceConfig
import net.gotev.uploadservice.data.BroadcastData
import net.gotev.uploadservice.data.UploadInfo
import net.gotev.uploadservice.data.UploadStatus
import net.gotev.uploadservice.extensions.registerReceiverCompat

open class BaseRequestObserver(
private val context: Context,
Expand All @@ -33,7 +34,7 @@ open class BaseRequestObserver(
}

open fun register() {
context.registerReceiver(this, UploadServiceConfig.broadcastStatusIntentFilter)
context.registerReceiverCompat(this, UploadServiceConfig.broadcastStatusIntentFilter)
}

open fun unregister() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.content.Intent
import net.gotev.uploadservice.UploadService
import net.gotev.uploadservice.UploadServiceConfig.broadcastNotificationAction
import net.gotev.uploadservice.UploadServiceConfig.broadcastNotificationActionIntentFilter
import net.gotev.uploadservice.extensions.registerReceiverCompat
import net.gotev.uploadservice.extensions.uploadIdToCancel
import net.gotev.uploadservice.logger.UploadServiceLogger
import net.gotev.uploadservice.logger.UploadServiceLogger.NA
Expand All @@ -28,7 +29,7 @@ open class NotificationActionsObserver(
}

fun register() {
context.registerReceiver(this, broadcastNotificationActionIntentFilter)
context.registerReceiverCompat(this, broadcastNotificationActionIntentFilter)
UploadServiceLogger.debug(NotificationActionsObserver::class.java.simpleName, NA) {
"registered"
}
Expand Down
Loading