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

[Android] Does not work when targetSdkVersion is set to 31+ #8

Open
Colton127 opened this issue Jun 10, 2022 · 10 comments
Open

[Android] Does not work when targetSdkVersion is set to 31+ #8

Colton127 opened this issue Jun 10, 2022 · 10 comments

Comments

@Colton127
Copy link
Contributor

To replicate: Open example, change targetSdkVersion to 31 (or 32) in build.gradle, make the necessary changes in AndroidManifest, and build.

You will have to make these minor adjustments in AndroidManifest
Under "<activity
android:exported="true"

And make this the intent-filter

     <receiver
            android:name="flutter.moum.headset_event.HeadsetBroadcastReceiver"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.HEADSET_PLUG" />
                <action android:name="android.intent.action.MEDIA_BUTTON" />
            </intent-filter>
        </receiver>

This will allow you to successfully build the release onto your device. However, the listener does not work at all. It simply does not respond to bluetooth connect/disconnect events. Setting TargetSdkVersion to 30, even while keeping the above manifest changes, fixes the problem entirely. This is on an Android 12 device.

@Colton127
Copy link
Contributor Author

The problem is that, after setting TargetSdk to 31+, you have to request permissions for bluetoothconnect. This requires the user agreeing to a prompt. See my fork here: https://github.com/Colton127/headset_connection_event

I discovered a different way of detecting headset status, including listening to events, by using https://github.com/ryanheise/audio_session. session.getDevices returns currently connected devices, and session.devicesChangedEventStream will listen to changes. You have to then create a function that determines if the device is a headset or not.

I'll leave this open while I continue my research. I should be pulling my fork soon.

@anleac
Copy link

anleac commented Jun 10, 2022

Wow awesome catch @Colton127 - I was wondering why a few months ago my app stopped working when I did seemingly minor version bumps, thanks for the fork, will use it 👍

@Colton127
Copy link
Contributor Author

Colton127 commented Jun 10, 2022

Wow awesome catch @Colton127 - I was wondering why a few months ago my app stopped working when I did seemingly minor version bumps, thanks for the fork, will use it 👍

Thank you, and you're welcome. I actually used your fork earlier in attempt to fix the problem but had no luck.

I have a HeadPhone manager class that utilizes audio_session and doesn't require any annoying permissions. I may publish it once I verify it works 100%.

Until then, Google is out to annoy us!

@themobilecoder
Copy link
Owner

The problem is that, after setting TargetSdk to 31+, you have to request permissions for bluetoothconnect. This requires the user agreeing to a prompt. See my fork here: https://github.com/Colton127/headset_connection_event

I discovered a different way of detecting headset status, including listening to events, by using https://github.com/ryanheise/audio_session. session.getDevices returns currently connected devices, and session.devicesChangedEventStream will listen to changes. You have to then create a function that determines if the device is a headset or not.

I'll leave this open while I continue my research. I should be pulling my fork soon.

@Colton127 awesome fork mate!

Apologies for not updating this project anymore. Feel free to publish your fork/library in pub.dev and I'll link yours from here so users can start using that. Or you can raise a PR here for that fork and ill merge it.

Cheers

@anleac
Copy link

anleac commented Jun 11, 2022

The problem is that, after setting TargetSdk to 31+, you have to request permissions for bluetoothconnect. This requires the user agreeing to a prompt. See my fork here: https://github.com/Colton127/headset_connection_event
I discovered a different way of detecting headset status, including listening to events, by using https://github.com/ryanheise/audio_session. session.getDevices returns currently connected devices, and session.devicesChangedEventStream will listen to changes. You have to then create a function that determines if the device is a headset or not.
I'll leave this open while I continue my research. I should be pulling my fork soon.

@Colton127 awesome fork mate!

Apologies for not updating this project anymore. Feel free to publish your fork/library in pub.dev and I'll link yours from here so users can start using that. Or you can raise a PR here for that fork and ill merge it.

Cheers

Haha apologies about my fork not working - I had it working locally but when I tried to integrate my plugin with my actual app it was crashing (and didn't revisit the plugin) - would be absolutely curious with your HeadPhone manager class, though I might play around with also implementing my own today based on your earlier info about the device stream with https://github.com/ryanheise/audio_session

Update - nice, the devices changed stream is perfect, I just did something really hacky and quick:

  final session = await AudioSession.instance;
    session.devicesChangedEventStream.listen((AudioDevicesChangedEvent payload) {
      // The user unplugged the headphones, so we should pause or lower the volume.
      if (payload.devicesRemoved.isNotEmpty &&
          _audioPlayer?.state == PlayerState.playing) {
        // pause logic
      }
    });

but depending if you wanted bluetooth specific you could easily do payload.devicesRemoved.any((device) => isBlueTooth(device)) with checks on the bluetooth type.

I imagine @Colton127 that is what you ended up with doing

@themobilecoder
Copy link
Owner

I have merged your PR #11 and published it as part of the latest release @Colton127 🙏

@Heech
Copy link

Heech commented Jan 13, 2023

@Colton127 @themobilecoder
Thank you for working on this fix. 🙇‍♂️

I have a HeadPhone manager class that utilizes audio_session and doesn't require any annoying permissions.

So looking at the PR we still have to request permission for Android 12+?
Or is there a way to detect a bluetooth device disconnect without showing the permission popup?

@themobilecoder
Copy link
Owner

Hi @Heech!

It seems like this specific Bluetooth functionality that we use (BLUETOOTH_CONNECT) requires user intervention to allow this permission starting Android 12 from google.

The BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT, and BLUETOOTH_SCAN permissions are runtime permissions. Therefore, you must explicitly request user approval in your app before you can look for Bluetooth devices, make a device discoverable to other devices, or communicate with already-paired Bluetooth devices. When your app requests at least one of these permissions, the system prompts the user to allow your app to access Nearby devices, as shown in figure 1.

So I'm not sure if there's a way to circumvent this

@Heech
Copy link

Heech commented Jan 24, 2023

@themobilecoder
Ah ok thanks for the clarification. It seems the youtube app can currently pause playback on disconnect while not requiring the bluetooth permissions even on android 12. So I wondered if there was maybe some alternative way to detect it or perhaps it's just some special privilege of the youtube app.

@themobilecoder
Copy link
Owner

@Heech mate that's a really good point.

So the permission that we use in this repo is BLUETOOTH_CONNECT, which would appear as "Nearby Devices" in the permission settings.

Looking at Youtube, like you said, no such permission.

I got curious and found this stackoverflow thread, and looks like there's a way to capture this event without ever needing bluetooth permission. (Use AudioManager)

Only thing here is that it does not use BroadcastReceiver, so there's a need to wrap this up within a Service or something that runs on the background.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants