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

Support SDK 31 + Gradle 7 + Android 12 #836

Closed
z80maniac opened this issue Oct 4, 2021 · 56 comments
Closed

Support SDK 31 + Gradle 7 + Android 12 #836

z80maniac opened this issue Oct 4, 2021 · 56 comments
Assignees
Labels
3 testing bug Something isn't working

Comments

@z80maniac
Copy link

Is your feature request related to a problem? Please describe.
The audio_service library cannot be used when an application is targeting SDK 31 and uses Gradle 7 and runs on Android 12.
When you use this setup then the application just crashes upon start.

This was actually reported earlier here: #796
I'm basically reporting the same thing while trying to provide more info and follow the issue template.

This GitHub issue is about a crash, but I'm writing it as a feature request because when you use the SDK and Gradle versions from "the example" (in this repo) everything works as expected. So it's a feature request to support the new versions of SDK and Gradle because I think the support for these new versions is relevant in terms of future-proofing and may help to catch some hidden bugs in the current code.

The crash only happens when all these conditions are met:

  1. Target SDK = 31
  2. Gradle version = 7
  3. App runs on Android 12

For example, the app runs correctly when SDK = 30 or when Gradle version is lower than 7 or when it runs on Android 11 or lower.

Steps to reproduce:

  1. Clone the repo:
git clone https://github.com/z80maniac/audio_service_sdk31_gradle7.git

It's a fork of your repo with needed modifications:

git diff
diff --git a/audio_service/example/android/app/build.gradle b/audio_service/example/android/app/build.gradle
index f8a453b..9f50322 100644
--- a/audio_service/example/android/app/build.gradle
+++ b/audio_service/example/android/app/build.gradle
@@ -25,16 +25,17 @@ apply plugin: 'com.android.application'
 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

 android {
-    compileSdkVersion 30
+    compileSdkVersion 31

     lintOptions {
         disable 'InvalidPackage'
+        abortOnError false
     }

     defaultConfig {
         applicationId "com.ryanheise.audioserviceexample"
         minSdkVersion 21
-        targetSdkVersion 28
+        targetSdkVersion 31
         versionCode flutterVersionCode.toInteger()
         versionName flutterVersionName
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/audio_service/example/android/app/src/main/AndroidManifest.xml b/audio_service/example/android/app/src/main/AndroidManifest.xml
index 724353e..974cd99 100644
--- a/audio_service/example/android/app/src/main/AndroidManifest.xml
+++ b/audio_service/example/android/app/src/main/AndroidManifest.xml
@@ -23,24 +23,25 @@
             android:theme="@style/LaunchTheme"
             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
             android:hardwareAccelerated="true"
-            android:windowSoftInputMode="adjustResize">
+            android:windowSoftInputMode="adjustResize"
+            android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>

-        <service android:name="com.ryanheise.audioservice.AudioService">
+        <service android:name="com.ryanheise.audioservice.AudioService" android:exported="true">
             <intent-filter>
                 <action android:name="android.media.browse.MediaBrowserService" />
             </intent-filter>
         </service>

-        <receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver" >
+        <receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver" android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MEDIA_BUTTON" />
             </intent-filter>
-        </receiver>
+        </receiver>

         <meta-data
             android:name="flutterEmbedding"
diff --git a/audio_service/example/android/build.gradle b/audio_service/example/android/build.gradle
index 0b4cf53..9971094 100644
--- a/audio_service/example/android/build.gradle
+++ b/audio_service/example/android/build.gradle
@@ -5,7 +5,7 @@ buildscript {
     }

     dependencies {
-        classpath 'com.android.tools.build:gradle:4.1.0'
+        classpath 'com.android.tools.build:gradle:7.0.2'
     }
 }

diff --git a/audio_service/example/android/gradle/wrapper/gradle-wrapper.properties b/audio_service/example/android/gradle/wrapper/gradle-wrapper.properties
index bc6a58a..b8793d3 100644
--- a/audio_service/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/audio_service/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
  1. Go to audio_service/example.

  2. Connect a device or emulator that runs Android 12 with SDK 31 (I used the emulator from Android Studio: Pixel 4 + Android S x86_64 with Play Services).

  3. Run flutter build apk.
    It will give two lint errors (which are ignored):

lint errors
💪 Building with sound null safety 💪

/home/user/test/audio_service_bugs/audio_service_android12/audio_service/example/android/app/src/main/AndroidManifest.xml:34: Error: AudioService must extend android.app.Service [Instantiatable]
        <service android:name="com.ryanheise.audioservice.AudioService" android:exported="true">
                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/user/test/audio_service_bugs/audio_service_android12/audio_service/example/android/app/src/main/AndroidManifest.xml:40: Error: MediaButtonReceiver must extend android.content.BroadcastReceiver [Instantiatable]
        <receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver" android:exported="true">
                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   Explanation for issues of type "Instantiatable":
   Activities, services, broadcast receivers etc. registered in the manifest
   file (or for custom views, in a layout file) must be "instantiatable" by
   the system, which means that the class must be public, it must have an
   empty public constructor, and if it's an inner class, it must be a static
   inner class.

2 errors, 0 warnings
Running Gradle task 'assembleRelease'...                           34.6s
✓  Built build/app/outputs/flutter-apk/app-release.apk (17.8MB).

These lint errors were also reported here: #822

I'm not sure if they are relevant to the subject (they also appear when targeting SDK 30 with Gradle 7).
Also, these errors don't happen on debug build. Maybe because of lint settings.
Anyway, these two lint errors may not be relevant at all, but I just decided to include them just in case.

  1. Run the app via flutter run. It will just crash immediately upon launch. It will also crash on release version.

Now here's a tricky part. Flutter may not give you the actual error right away. Sometimes it just crashes with a cryptic error messages:

  • Lost connection to device.

  • Error connecting to the service protocol: failed to connect to http://127.0.0.1:43925/3ebPWbNkhco=/

  • Error initializing DevFS: DevFSException(Service disconnected, _createDevFS: (112) Service has disappeared, null)

But sometimes it will give you the actual error (or at least I believe that it's the actual error that causes the crash). It takes me usually around 10-15 times of invoking flutter run to get some meaningful output. Maybe there's a reliable way to show this error without a trial-and-error, but I don't know it.

Here is the full output with the actual error:

❯ flutter run
Using hardware rendering with device sdk gphone64 x86 64. If you notice graphics artifacts,
consider enabling software rendering with "--enable-software-rendering".
Launching lib/main.dart on sdk gphone64 x86 64 in debug mode...
Running Gradle task 'assembleDebug'...                           2,470ms
✓  Built build/app/outputs/flutter-apk/app-debug.apk.
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/skia    ( 7670): Shader compilation error
D/skia    ( 7670): ------------------------
D/skia    ( 7670): Errors:
D/skia    ( 7670):
D/CompatibilityChangeReporter( 7670): Compat change id reported: 160794467; UID 10147; state: ENABLED
D/AndroidRuntime( 7670): Shutting down VM
E/AndroidRuntime( 7670): FATAL EXCEPTION: main
E/AndroidRuntime( 7670): Process: com.ryanheise.audioserviceexample, PID: 7670
E/AndroidRuntime( 7670): java.lang.RuntimeException: Unable to create service com.ryanheise.audioservice.AudioService: java.lang.IllegalArgumentException: com.ryanheise.audioserviceexample: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
E/AndroidRuntime( 7670): 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.
E/AndroidRuntime( 7670):        at android.app.ActivityThread.handleCreateService(ActivityThread.java:4504)
E/AndroidRuntime( 7670):        at android.app.ActivityThread.access$1700(ActivityThread.java:247)
E/AndroidRuntime( 7670):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2076)
E/AndroidRuntime( 7670):        at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime( 7670):        at android.os.Looper.loopOnce(Looper.java:201)
E/AndroidRuntime( 7670):        at android.os.Looper.loop(Looper.java:288)
E/AndroidRuntime( 7670):        at android.app.ActivityThread.main(ActivityThread.java:7842)
E/AndroidRuntime( 7670):        at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 7670):        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
E/AndroidRuntime( 7670):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
E/AndroidRuntime( 7670): Caused by: java.lang.IllegalArgumentException: com.ryanheise.audioserviceexample: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
E/AndroidRuntime( 7670): 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.
E/AndroidRuntime( 7670):        at android.app.PendingIntent.checkFlags(PendingIntent.java:375)
E/AndroidRuntime( 7670):        at android.app.PendingIntent.getActivityAsUser(PendingIntent.java:458)
E/AndroidRuntime( 7670):        at android.app.PendingIntent.getActivity(PendingIntent.java:444)
E/AndroidRuntime( 7670):        at android.app.PendingIntent.getActivity(PendingIntent.java:408)
E/AndroidRuntime( 7670):        at com.ryanheise.audioservice.AudioService.configure(AudioService.java:329)
E/AndroidRuntime( 7670):        at com.ryanheise.audioservice.AudioService.onCreate(AudioService.java:248)
E/AndroidRuntime( 7670):        at android.app.ActivityThread.handleCreateService(ActivityThread.java:4491)
E/AndroidRuntime( 7670):        ... 9 more
I/Process ( 7670): Sending signal. PID: 7670 SIG: 9
Lost connection to device.
Syncing files to device sdk gphone64 x86 64...                     175ms

I believe that the source of the crash is this:

Unable to create service com.ryanheise.audioservice.AudioService: java.lang.IllegalArgumentException: com.ryanheise.audioserviceexample: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Describe the solution you'd like
The application should not crash.

Describe alternatives you've considered
The only workaround is to not use this specific combination: SDK 31 + Gradle 7 + Android 12.

Additional context

flutter doctor
❯ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.5.2, on Ubuntu 21.04 5.11.0-36-generic, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Chrome - develop for the web
[✗] Linux toolchain - develop for Linux desktop
    ✗ GTK 3.0 development libraries are required for Linux development.
      They are likely available from your distribution (e.g.: apt install libgtk-3-dev)
[✓] Android Studio (version 2020.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2021.1)
[✓] VS Code (version 1.55.2)
[✓] VS Code
[✓] Connected device (3 available)

! Doctor found issues in 1 category.
@z80maniac z80maniac added 1 backlog enhancement New feature or request labels Oct 4, 2021
@ryanheise ryanheise added bug Something isn't working and removed enhancement New feature or request labels Oct 5, 2021
@ryanheise
Copy link
Owner

Thanks for the report and reproduction project. I've relabeled it as a bug.

Although I haven't installed the Android 12 beta yet, I have updated the code in the fix/android_intent_flags branch to set FLAG_IMMUTABLE on all pending intents. Can you try it and let me know if it works for you?

@z80maniac
Copy link
Author

Yes, with fix/android_intent_flags applied, there's no crash anymore and everything works as usual. I tested it on my repo and on this one - both cases work normally. Thanks for the quick fix!

Those two lint errors are still there though, but it does not seem like they affect anything (if the abortOnError is set to false). Should I still file a separate bug report for them?

@ryanheise
Copy link
Owner

ryanheise commented Oct 6, 2021

   Activities, services, broadcast receivers etc. registered in the manifest
   file (or for custom views, in a layout file) must be "instantiatable" by
   the system, which means that the class must be public, it must have an
   empty public constructor, and if it's an inner class, it must be a static
   inner class.

This lint really confuses me.

  • Must be public - tick
  • Must have an empty public constructor - tick
  • If it's an inner class - N/A

As for this:

AudioService must extend android.app.Service

Well, AudioService might not directly extend android.app.Service but it extends MediaBrowserServiceCompat (following Android's own documentation) which in turn extends android.app.Service. If that's bad practice, then their lint is simply inconsistent with their documentation.

This S/O post seems to be related, but my Gradle file looks like it has the right dependency:

https://stackoverflow.com/questions/62282686/cant-use-mediabrowserservicecompat

@z80maniac
Copy link
Author

I've fiddled around with the code a bit, changing this and that, but also couldn't figure out how to "satisfy" those lint errors. It may as well be some bug in the Gradle, since this Instantiatable lint check has a history of false positives: https://issuetracker.google.com/issues?q=Instantiatable

I guess it can be ignored then. Or maybe suppressed? But suppressed where exactly? In the audio_service library or in an end-user project? Or maybe there's some other workaround, I don't know.

@ryanheise
Copy link
Owner

What the S/O post made me think of is that there might be multiple versions of the same class in the build system due to the way dependencies are all built and merged, so it could be getting confused because of this.

@z80maniac
Copy link
Author

Yes, I also had that thought. But MediaBrowserServiceCompat always extends Service in any version of its package (judging by its git history), so it should not be the issue. Unless it expects some other version of Service. But I think Gradle throws an error if it detects the same class in two different locations. Also, when I open MediaBrowserServiceCompat in Android Studio it tells me that "Library source does not match the bytecode for class MediaBrowserServiceCompat" (even if I invalidate and clean all caches). However, I'm not sure if it means anything or it's just a setup error on my side. I've also decompiled *.dex files from the resulting APK (in debug mode), but didn't find anything useful.

So, basically I have no idea how to fix it and why it happens. :)

@ryanheise
Copy link
Owner

Right, so what I was guessing is that there might be multiple versions of the Service class during dependency merging. Let's say for simplicity there are two of them which come from two different dependencies. Then we have it that MediaBrowserServiceCompat[2] extends Service[2] but the lint complains that it does not extend Service[1]. I guess this theory could be confirmed by trying to temporarily eliminate as much merging as possible during the build process, e.g. by removing the just_audio and audio_session dependencies, and then see how the build goes.

@z80maniac
Copy link
Author

I've removed all dependencies, but still get those lint errors.

z80maniac/audio_service_sdk31_gradle7_nodeps@c161b63#diff-f920e61e5cf3d7dde1f988b1d2a1cc9bff6637e59ecc768cf8df884e64633f8f

git clone https://github.com/z80maniac/audio_service_sdk31_gradle7_nodeps.git
cd audio_service_sdk31_gradle7_nodeps/audio_service/example/
flutter build apk

@z80maniac
Copy link
Author

On the other hand, an empty Flutter project with just an empty MediaBrowserServiceCompat child (and the corresponding <service> in the manifest) does not produce any lint errors.

git clone https://github.com/z80maniac/mediabrowserservicecompat_test.git

@ryanheise
Copy link
Owner

Yep, complete mystery, but the situation is reminiscent of the same issues that can happen with class loaders at runtime, so here we could have two different versions of the MediaBrowserServiceCompat class as well. I've tried creating a lint.xml file to no avail:

https://developer.android.com/studio/write/lint.html#config

Maybe an IDE would have some tool to update the appropriate files (although I don't use an IDE).

@z80maniac
Copy link
Author

Turns out this error happens in AndroidManifest.xml, so it's impossible to suppress it in the library. Also, lint.xml is not the best solution here, because it can only suppress a particular error in the entire file. A more careful approach is to suppress the errors only in places where they occur. For that you need to add tools:ignore to the manifest (just as described in the link you provided):

diff --git a/audio_service/example/android/app/src/main/AndroidManifest.xml b/audio_service/example/android/app/src/main/AndroidManifest.xml
index 974cd99..7913e65 100644
--- a/audio_service/example/android/app/src/main/AndroidManifest.xml
+++ b/audio_service/example/android/app/src/main/AndroidManifest.xml
@@ -31,13 +31,23 @@
             </intent-filter>
         </activity>
 
-        <service android:name="com.ryanheise.audioservice.AudioService" android:exported="true">
+        <service
+            android:name="com.ryanheise.audioservice.AudioService"
+            android:exported="true"
+            xmlns:tools="http://schemas.android.com/tools"
+            tools:ignore="Instantiatable"
+        >
             <intent-filter>
                 <action android:name="android.media.browse.MediaBrowserService" />
             </intent-filter>
         </service>
 
-        <receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver" android:exported="true">
+        <receiver
+            android:name="com.ryanheise.audioservice.MediaButtonReceiver"
+            android:exported="true"
+            xmlns:tools="http://schemas.android.com/tools"
+            tools:ignore="Instantiatable"
+        >
             <intent-filter>
                 <action android:name="android.intent.action.MEDIA_BUTTON" />
             </intent-filter>

Since these errors can't be suppressed in the library itself, maybe it makes sense to mention this case in the docs?

@ryanheise
Copy link
Owner

The build process should merge the plugin's AndroidManifest.xml with the app's, so it is theoretically possible to address this in the plugin, but only if the plugin hard codes the receiver and service declarations (which I've not wanted to do so far).

So yes, probably the README and example should be updated.

@z80maniac
Copy link
Author

we could have two different versions of the MediaBrowserServiceCompat class as well

I decompiled the *.dex files, but didn't find any duplicate classes of MediaBrowserServiceCompat or Service. Though, I'm not 100% sure I didn't miss anything.

but only if the plugin hard codes the receiver and service declarations (which I've not wanted to do so far)

This will be a breaking change then. And it's probably an overkill for just silencing a linter.

@prilepskiy
Copy link

I have this error with audio_service 0.18.1, how I can fix it?

W/System.err( 8837): java.lang.IllegalArgumentException: io.meduza.meduza: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
W/System.err( 8837): 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.

@ryanheise
Copy link
Owner

Hi @prilepskiy , the current work to fix it is on the fix/antroid_intent_flags branch (see above for context).

@squallsama
Copy link

Any plans to merge fix/antroid_intent_flags into main branch ?

@ryanheise
Copy link
Owner

Unfortunately there is still an unresolved problem so I can't merge it yet. I currently have Gradle flagging warnings as errors (as a quality control measure) and while that's what I want, the current solution to this issue generates warnings when compiling a release build.

For now, you can use the branch directly, but I'm also open to feedback on this if you were able to solve this issue yourself.

@squallsama
Copy link

Yeah, I'm using it via

  audio_service:
    git:
      url: https://github.com/ryanheise/audio_service.git
      path: audio_service
      ref: fix/android_intent_flags

I'll try to see what can be done to resolve these warnings. Thanks for explanation !

@squallsama
Copy link

Hey, I created a fork and fixed locally lint errors. Please take a look on #871

@ryanheise
Copy link
Owner

Hi @squallsama , thanks. I'll take a look at it.

Although I just realised I have some stashed changes that I haven't committed/pushed yet, in the gradle and manifest files which I think do some of the same things in this PR. Let me compare and see if there are any significant differences.

@squallsama
Copy link

Also, it would be great if you provide command line which I can use to check if lint errors still exists or not. For now I used gradle clean build and checked status + lint report html file

@ryanheise
Copy link
Owner

I've just pushed my local (previously uncommitted) changes.

I don't see any difference with your PR aside from version 7.0.3 instead of 7.0.2 in gradle, except mainly that your PR doesn't update the example to target Android 12 (maybe that's why it's working for you??)

In any case, can you try my latest commit to see if you are able to reproduce the issue?

@squallsama
Copy link

Sure. And also I'll try to update example to target android 12.

@BecoStopclub
Copy link

@ryanheise It's working, tested on real device with android 12 (Galaxy S21+), #887 builds fine but notification does not appear

Audio_service_android12.mp4

.

@ryanheise
Copy link
Owner

Thanks for testing, @BecoStopclub . Did you apply the same changes to your manifest as in the example? Does the example work for you? If that's the case, you should be able to copy what it does, otherwise let me know if the example is also failing for you.

@BecoStopclub
Copy link

BecoStopclub commented Dec 17, 2021

@ryanheise I didn't try the example or change the manifest, I just overwritten to use fix/android_intent_flags and ran.

My current manifest:
Screenshot_20211217-140030_Chrome

I can test more later today :)

@BecoStopclub
Copy link

BecoStopclub commented Dec 18, 2021

@ryanheise Sorry for the delay.
I ran the example and everything worked fine without having to change anything, no errors/warnings.

audio_service_a12

@ryanheise
Copy link
Owner

Thanks for testing that. Regarding the issue with the notification not showing in your own app, the only difference I can see is that you have exported="false" instead of exported="true". You could try changing that.

@BecoStopclub
Copy link

BecoStopclub commented Dec 18, 2021

Hi @ryanheise, I ran a full test on the two available solutions: (branch: fix/android_intent_flags) and PR (#887), in different scenarios, here are the results:

1 - fix/android_intent_flags

It worked correctly regardless of the configuration.

configs audio_service's example My Own app
service.exported=true && receiver.exported=true OK OK
service.exported=true && receiver.exported=false OK OK
service.exported=false && receiver.exported=true OK OK
service.exported=false && receiver.exported=false OK OK

2 - PR #887

Compiles, the notification appears when you press PLAY for the first time, but if you press STOP and PLAY again, it doesn't appear anymore.

configs audio_service's example My Own app
service.exported=true && receiver.exported=true FAIL FAIL
service.exported=true && receiver.exported=false FAIL FAIL
service.exported=false && receiver.exported=true FAIL FAIL
service.exported=false && receiver.exported=false FAIL FAIL

Both audio_services's example and My own app running with:

  • compileSdkVersion 31
  • targetSdkVersion 31

@ryanheise
Copy link
Owner

@BecoStopclub I'm curious why it failed before and worked now given the same exported parameters. Do you know what changed that would have caused the same fix/android_intent_flags/ branch to fail for you before but work now?

@BecoStopclub
Copy link

@ryanheise My comment about not working was related to PR #887 (was tagged above).

Sorry for the misunderstanding, English is not my first language.

@ryanheise
Copy link
Owner

Ah, sorry it was my misunderstanding since you did mention that earlier.

It's good to know fix/android_intent_flags is working for you. Can anyone else confirm that this branch works for them?

@swiftymf
Copy link

We had to update a project to sdkVersion 31 and this popped up for us too. This branch fixes and we're able to run our project again!

@mehayhe
Copy link

mehayhe commented Dec 20, 2021

@ryanheise Doesn't work for me. Got the same Instantiatable lint errors when tried to build in release mode.

If I moved the service & receiver elements to the package's AndroidManifest.xml then it will build fine. Those will be merged with the main AndroidManifest during the build process. You can take a look at the changes here: mehayhe@5827ff9

@z80maniac
Copy link
Author

z80maniac commented Dec 20, 2021

Can confirm that it does not work (unless you add tools:ignore="Instantiatable" to the <receiver> and <service>). The solution from @mehayhe works, though I don't understand how, since the resulting manifest should be the same, right? Maybe the linter simply does not check the library?

Regarding receiver > android:exported="true". In my case the notification appeared even if exported=false (Android 11), but headset media buttons only work when I set exported=true. The exported attribute on the <service> does not seem to affect anything in my case.

@z80maniac
Copy link
Author

Just to clarify: the main problem (and the reason I submitted this issue in the first place) was actually fixed long ago (the application crash). Now just this weird linter error remains. AFAIK it can be safely ignored - I've built my own music player app with that fix/android_intent_flags and used it for several weeks and didn't encounter any errors.

Maybe that branch should be released since it actually fixes the initial problem? And that linter error is a completely separate problem for which a fix can be released separately.

@ryanheise
Copy link
Owner

ryanheise commented Dec 21, 2021

If I moved the service & receiver elements to the package's AndroidManifest.xml then it will build fine. Those will be merged with the main AndroidManifest during the build process. You can take a look at the changes here: mehayhe@5827ff9

That's certainly interesting. Although hard coding this in the package is also problematic since it hard codes certain components and can cause issues with manifest merging when an app tries to define custom components.

@ryanheise
Copy link
Owner

+        <service
+            android:name="com.ryanheise.audioservice.AudioService"
+            android:exported="true"
+            xmlns:tools="http://schemas.android.com/tools"
+            tools:ignore="Instantiatable"

Out of curiosity, why did you add xmlns:tools=... to the <service> element when it is already declared at the root? Didn't this declaration get inherited by child elements?

@kiratheone
Copy link

kiratheone commented Dec 21, 2021

I've tested with real device Android 12 using this branch fix/android_intent_flags/ for my case. It's working. So it will be merged soon? Thanks before @ryanheise

@ryanheise
Copy link
Owner

I should still address the issue mentioned in my previous comment. Maybe you can try setting tools:ignore="Instantiable" with just one xmlns declaration at the root element and let me know if it works?

@mehayhe
Copy link

mehayhe commented Dec 21, 2021

I tried the tools:ignore="Instatiable" setting and was able to build the app fine without the modification I had before. It can be added to either the manifest or service & receiver elements.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" tools:ignore="Instantiatable"
    package="com.ryanheise.audioserviceexample">

or

<service android:name="com.ryanheise.audioservice.AudioService" android:exported="true" tools:ignore="Instantiatable">
  <intent-filter>
    <action android:name="android.media.browse.MediaBrowserService" />
  </intent-filter>
</service>

<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver" android:exported="true" tools:ignore="Instantiatable">
  <intent-filter>
    <action android:name="android.intent.action.MEDIA_BUTTON" />
  </intent-filter>
</receiver>

@ryanheise
Copy link
Owner

That's surprising, but sure enough the documentation also says it is so:

https://developer.android.com/studio/write/tool-attributes#error_handling_attributes

In that case, I think I'll go with that approach for the official example and README just because it will cause less friction.

@z80maniac
Copy link
Author

Out of curiosity, why did you add xmlns:tools=... to the element when it is already declared at the root?

Hmm, I don't remember... Maybe I was testing against the main branch where the xmlns:tools wasn't declared at the root. But yes, it can be declared only at the root.

@ryanheise
Copy link
Owner

In that case, I think I'll go with that approach for the official example and README just because it will cause less friction.

On second thought, adding it on each component causes less friction since most developers will copy and paste the service and receiver component declarations whole.

@ryanheise
Copy link
Owner

I've just committed some changes to the fix/android_intent_flags to address the discussion above.

This updates the README and the example with the lint ignore. Since it has been working for me recently even without the lint ignore, I can't test this, but if anyone who had the lint errors can just test this release candidate, let me know and I'll push out a release.

@z80maniac
Copy link
Author

After merging fix/android_intent_flags into minor it builds without errors:

❯ flutter build apk --release
Running "flutter pub get" in example...                          2,820ms

💪 Building with sound null safety 💪

Note: /home/user/.pub-cache/hosted/pub.dartlang.org/path_provider_android-2.0.10/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
No issues found.
Running Gradle task 'assembleRelease'...                           37.0s
✓  Built build/app/outputs/flutter-apk/app-release.apk (17.7MB).

@ryanheise
Copy link
Owner

Thanks for testing! I might update the path_provider dependency given the compile note, and I notice the latest path_provider targets Android 12.

@ryanheise
Copy link
Owner

Thanks all for contributing with both testing and research regarding the lint issue. I've now published the fix in release 0.18.3.

@github-actions
Copy link

github-actions bot commented Jan 8, 2022

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs, or use StackOverflow if you need help with audio_service.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 8, 2022
@ryanheise ryanheise unpinned this issue Sep 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
3 testing bug Something isn't working
Projects
None yet
Development

No branches or pull requests

9 participants