gotev / android-upload-service

Easily upload files (Multipart/Binary/FTP out of the box) in the background with progress notification. Support for persistent upload requests, customizations and custom plugins.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support android 12

MichalFrSN opened this issue · comments

Hi,
We're using an older version of the library and when we try to upload a file from a device with Android 12 OS the app crashes with the following exception:

java.lang.IllegalArgumentException: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles. at android.app.PendingIntent.checkFlags(PendingIntent.java:375) at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645) at android.app.PendingIntent.getBroadcast(PendingIntent.java:632) at net.gotev.uploadservice.UploadNotificationStatusConfig.getClickIntent(UploadNotificationStatusConfig.java:69) at net.gotev.uploadservice.UploadTask.createNotification(UploadTask.java:457) at net.gotev.uploadservice.UploadTask.run(UploadTask.java:145) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:920)

Is the latest release version of the library supports android 12?
If not, are you planning to release a new version soon with API 31 support?

Thank you

Hi,
no official support for Android 12 yet, but you're welcome to contribute with a PR :)

Consider targeting a lower Android API than the latest in your App to support more Android devices and versions. With target up to API 30 the library has no known issues.

commented

I basically did this

PendingIntent clickIntent;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
  clickIntent = PendingIntent.getActivity(context, 1, new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_MUTABLE);
} else {
  clickIntent = PendingIntent.getActivity(context, 1, new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
}

That got me past clickIntent that left me with actions which I had cancelAction ContextExtensionsKt.getCancelUploadIntent had to remove that for Android 12 for now until the library is updated.

You're welcome to make a PR 😉

Really apreciate if someone make a PR to support Android 12. Also worth mention that this library uses android services which will no longer be usable if your app is not visible, not even if it's a foreground service (https://developer.android.com/guide/components/foreground-services#background-start-restrictions). Probably should migrate to something with WorkManager expedite jobs or some observable work.

WorkManager is the way to go for the future. I have limited time now and the next months for such an implementation, but I can support people willing to contribute.

Android 12 is now supported https://github.com/gotev/android-upload-service/releases/tag/4.7.0 ! Please allow some time to Maven Central to process the new release 😉

Not sure if this fixes everything in Android 12. Have you tested starting the upload inside a workmanager while the app is not visible/destroyed? I see that you still uses Service and due new restrictions in apps targeting Android 12 this won't be possible anymore (if the app does not respect this exceptions: https://developer.android.com/guide/components/foreground-services#bg-access-restriction-exemptions).

@psmorandi the library is intended for uploads to be started from activities/fragments/viewmodels. Starting stuff while the app is in the background is a known limitation at the current state of the art, even before Android 12. #578 (comment)

try {
/*
When trying to start a service on API 26+
while the app is in the background, an IllegalStateException will be fired
https://developer.android.com/reference/android/content/Context#startService(android.content.Intent)
Then why not using startForegroundService always on API 26+? Read below
*/
startService(intent)
} catch (exc: Throwable) {
if (Build.VERSION.SDK_INT >= 26 && exc is IllegalStateException) {
/*
this is a bugged Android API and Google is not going to fix it
https://issuetracker.google.com/issues/76112072
Android SDK can not guarantee that the service is going to be started in under 5 seconds
which in turn can cause the non catchable
RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
so the library is going to use this bugged API only as a last resort, to be able
to support starting uploads also when the app is in the background, but preventing
non catchable exceptions when you launch uploads while the app is in foreground.
*/
startForegroundService(intent)
} else {
UploadServiceLogger.error(
component = "UploadService",
uploadId = params.id,
exception = exc,
message = {
"Error while starting AndroidUploadService"
}
)
}
}
return params.id
}

I'm also wondering if it does make sense to still maintain the lib, as moving to WorkManager will mean a total rewrite from the ground up, to be "just" a bunch of job implementations to be used with WorkManager APIs.

Current internal architecture revolves around the now "old school" android way of doing stuff:

  • Create an intent
  • Start a service with that intent
  • Do stuff in the service
  • Send broadcast intents from the service
  • Listen to broadcast intents coming from the service to display the notification or to update some app UI

With WorkManager it will be completely different. Also the library name as it is now won't be representative anymore.

@psmorandi the library is intended for uploads to be started from activities/fragments/viewmodels. Starting stuff while the app is in the background is a known limitation at the current state of the art, even before Android 12. #578 (comment)

try {
/*
When trying to start a service on API 26+
while the app is in the background, an IllegalStateException will be fired
https://developer.android.com/reference/android/content/Context#startService(android.content.Intent)
Then why not using startForegroundService always on API 26+? Read below
*/
startService(intent)
} catch (exc: Throwable) {
if (Build.VERSION.SDK_INT >= 26 && exc is IllegalStateException) {
/*
this is a bugged Android API and Google is not going to fix it
https://issuetracker.google.com/issues/76112072
Android SDK can not guarantee that the service is going to be started in under 5 seconds
which in turn can cause the non catchable
RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
so the library is going to use this bugged API only as a last resort, to be able
to support starting uploads also when the app is in the background, but preventing
non catchable exceptions when you launch uploads while the app is in foreground.
*/
startForegroundService(intent)
} else {
UploadServiceLogger.error(
component = "UploadService",
uploadId = params.id,
exception = exc,
message = {
"Error while starting AndroidUploadService"
}
)
}
}
return params.id
}

I know, but with the service and foreground service it worked pretty well for me. Until now of course.

I'm also wondering if it does make sense to still maintain the lib, as moving to WorkManager will mean a total rewrite from the ground up, to be "just" a bunch of job implementations to be used with WorkManager APIs.

Current internal architecture revolves around the now "old school" android way of doing stuff:

  • Create an intent
  • Start a service with that intent
  • Do stuff in the service
  • Send broadcast intents from the service
  • Listen to broadcast intents coming from the service to display the notification or to update some app UI

With WorkManager it will be completely different. Also the library name as it is now won't be representative anymore.

That got me thinking too. But you know, there are a lot of stuff in WorkManager to observe the work being done. And your lib would be very useful to help build an easy way to display progress. Even if you are using WorkManager you still have some boiler plate to get progress done. But I got your point, maybe we need to update to a more "modern school" of doing stuff. Maybe some android-upload-work/worker.

@psmorandi created a dedicated thread to continue the discussion: #610