dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.28k stars 1.76k forks source link

Adding a Connectivity.ConnectivityChanged handler throw an exception on Android 14 #17861

Closed daniel-c closed 1 year ago

daniel-c commented 1 year ago

Description

When adding a Connectivity.ConnectivityChanged handler, the following exception is thrown on an Android 14 device, when the targetSdkVersion is 34 (the default with new Maui app) an when run on Android 14:

Exception has occurred: Java.Lang.SecurityException
com.companyname.dotnetmaui: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts
    at Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualObjectMethod(JniObjectReference instance, JniObjectReference type, JniMethodInfo method, JniArgumentValue* args) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:20416
    at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualObjectMethod(String encodedMember, IJavaPeerable self, JniArgumentValue* parameters) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:876
    at Android.Content.ContextWrapper.RegisterReceiver(BroadcastReceiver receiver, IntentFilter filter) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net8.0/android-34/mcw/Android.Content.ContextWrapper.cs:2605
    at Microsoft.Maui.Networking.ConnectivityImplementation.StartListeners() in D:\a\_work\1\s\src\Essentials\src\Connectivity\Connectivity.android.cs:48
    at Microsoft.Maui.Networking.ConnectivityImplementation.add_ConnectivityChanged(EventHandler`1 value) in D:\a\_work\1\s\src\Essentials\src\Connectivity\Connectivity.shared.cs:91
    at Microsoft.Maui.Networking.Connectivity.add_ConnectivityChanged(EventHandler`1 value) in D:\a\_work\1\s\src\Essentials\src\Connectivity\Connectivity.shared.cs:58
    at DotnetMaui.App..ctor() in /Users/daniel/Development/Samples/DotnetMaui/App.xaml.cs:9

Steps to Reproduce

  1. Create a new MAUI app with botnet new maui
  2. In the App constructor in App.xaml.cs, add : Connectivity.ConnectivityChanged += (sender, e) => { };
  3. Start the app on an Android 14 emulator or device.

Link to public reproduction project repository

No response

Version with bug

8.0.0-rc.1.9171

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 14

Did you find any workaround?

Change the target Android version to 13. The code will work on Android 14 then.

Relevant log output

Exception has occurred: Java.Lang.SecurityException
com.companyname.dotnetmaui: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts
    at Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualObjectMethod(JniObjectReference instance, JniObjectReference type, JniMethodInfo method, JniArgumentValue* args) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:20416
    at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualObjectMethod(String encodedMember, IJavaPeerable self, JniArgumentValue* parameters) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:876
    at Android.Content.ContextWrapper.RegisterReceiver(BroadcastReceiver receiver, IntentFilter filter) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net8.0/android-34/mcw/Android.Content.ContextWrapper.cs:2605
    at Microsoft.Maui.Networking.ConnectivityImplementation.StartListeners() in D:\a\_work\1\s\src\Essentials\src\Connectivity\Connectivity.android.cs:48
    at Microsoft.Maui.Networking.ConnectivityImplementation.add_ConnectivityChanged(EventHandler`1 value) in D:\a\_work\1\s\src\Essentials\src\Connectivity\Connectivity.shared.cs:91
    at Microsoft.Maui.Networking.Connectivity.add_ConnectivityChanged(EventHandler`1 value) in D:\a\_work\1\s\src\Essentials\src\Connectivity\Connectivity.shared.cs:58
    at DotnetMaui.App..ctor() in /Users/daniel/Development/Samples/DotnetMaui/App.xaml.cs:9
    at at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Constructor(Object obj, IntPtr* args)
    at at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
    at at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
    at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSiteMain(ServiceCallSite callSite, RuntimeResolverContext argument)
    at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
    at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite, RuntimeResolverContext argument)
    at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
    at at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(ServiceIdentifier serviceIdentifier)
    at at System.Collections.Concurrent.ConcurrentDictionary`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.Extensions.DependencyInjection.ServiceProvider.ServiceAccessor, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].GetOrAdd(ServiceIdentifier key, Func`2 valueFactory)
    at at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
    at at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
    at Microsoft.Maui.MauiContext.WrappedServiceProvider.GetService(Type serviceType) in D:\a\_work\1\s\src\Core\src\MauiContext.cs:68
    at Microsoft.Maui.MauiContext.WrappedServiceProvider.GetService(Type serviceType) in D:\a\_work\1\s\src\Core\src\MauiContext.cs:68
    at at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
    at at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[IApplication](IServiceProvider provider)
    at Microsoft.Maui.MauiApplication.OnCreate() in D:\a\_work\1\s\src\Core\src\Platform\Android\MauiApplication.cs:46
    at Android.App.Application.n_OnCreate(IntPtr jnienv, IntPtr native__this) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net8.0/android-34/mcw/Android.App.Application.cs:1086
    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:26
    at java.lang.SecurityException: com.companyname.dotnetmaui: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts
    at at android.os.Parcel.createExceptionOrNull(Parcel.java:3057)
    at at android.os.Parcel.createException(Parcel.java:3041)
    at at android.os.Parcel.readException(Parcel.java:3024)
    at at android.os.Parcel.readException(Parcel.java:2966)
    at at android.app.IActivityManager$Stub$Proxy.registerReceiverWithFeature(IActivityManager.java:5684)
    at at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1852)
    at at android.app.ContextImpl.registerReceiver(ContextImpl.java:1792)
    at at android.app.ContextImpl.registerReceiver(ContextImpl.java:1780)
    at at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:755)
    at at crc6488302ad6e9e4df1a.MauiApplication.n_onCreate(Native Method)
    at at crc6488302ad6e9e4df1a.MauiApplication.onCreate(MauiApplication.java:28)
    at at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1316)
    at at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6998)
    at at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
    at at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2236)
    at at android.os.Handler.dispatchMessage(Handler.java:106)
    at at android.os.Looper.loopOnce(Looper.java:205)
    at at android.os.Looper.loop(Looper.java:294)
    at at android.app.ActivityThread.main(ActivityThread.java:8177)
    at at java.lang.reflect.Method.invoke(Native Method)
    at at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
    at Caused by: android.os.RemoteException: Remote stack trace:
    at at com.android.server.am.ActivityManagerService.registerReceiverWithFeature(ActivityManagerService.java:13908)
    at at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2570)
    at at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2720)
    at at android.os.Binder.execTransactInternal(Binder.java:1339)
    at at android.os.Binder.execTransact(Binder.java:1275)
drasticactions commented 1 year ago

https://github.com/xamarin/xamarin-android/blob/19d978bc1b6ee04e6dd4b11ec01d2a9c8f6b3e49/src/Mono.Android/Android.Content/Context.cs#L22-L25

There is a breaking change for Android API 34 that requires setting the RecieverFlags. I believe if we update

https://github.com/dotnet/maui/blob/main/src/Essentials/src/Connectivity/Connectivity.android.cs#L48

to this new API,

Application.Context.RegisterReceiver(conectivityReceiver, filter, ReceiverFlags.NotExported);

it would work again... the problem being, it's only in the Android 34 dlls (In that, it's in the preprocessor defs to only be compiled for Android 34, and as far as I can tell can't be referenced on early versions. I'm not sure if MAUI ships multiple editions for essentials that target specific Android versions like that.

@jonpryor @jpobst do ya'll know how to access this API in Essentials? Or did I misunderstand the problem?

jpobst commented 1 year ago

Context: https://github.com/xamarin/xamarin-android/commit/d9e440710574e3d261faa4514eb1a46091bca9b9

This new API will only be available for projects targeting .NET 8+. If you want to be able to call this API for earlier projects you will need to call the incorrectly enumified version that has existed for many years:

https://learn.microsoft.com/en-us/dotnet/api/android.content.context.registerreceiver?view=xamarin-android-sdk-13#android-content-context-registerreceiver(android-content-broadcastreceiver-android-content-intentfilter-android-content-activityflags)

You can cast the enums as needed:

Application.Content.RegisteredReceiver(conectivityReceiver, filter, (ActivityFlags)ReceiverFlags.NotExported);
XamlTest commented 1 year ago

Verified this on Visual Studio Enterprise 17.8.0 Preview 2.0(8.0.0-rc.1.9171). Repro on Android 14.0-API34 with below Project: 17861.zip

image

pasha-o commented 1 year ago

verified the issue exists on Xamarin forms as well

albertruff commented 1 year ago

We also face this issue. Is there any chance to temporary avoid this exception?

dondestas commented 1 year ago

@albertruff You can temporary avoid this exception by setting the Android targetSdkVersion to 33 instead of 34.

albertruff commented 1 year ago

@dondestas Thank you. It works

Redth commented 1 year ago

This needs to be updated in other areas too. We need to do an audit of our code base to see where it's implicated and determine the correct values to use.

Alex-Dobrynin commented 1 year ago

Got this crash today after update to .net 8

edgedj commented 1 year ago

I'm getting this on a project after .net 8 upgrade, specifically during this call:

Connectivity.ConnectivityChanged += OnConnectivityChanged;

dylix commented 1 year ago

EDIT: ah its in nightly builds now... zzzz. i'll wait :P Why is this closed? It's not fixed in .net8 release.

Alex-Dobrynin commented 1 year ago

@dylix if maui team counts that it is fixed then it is fixed, don't you understand this?

jfversluis commented 1 year ago

@dylix closing PRs/issues only when something is released is a pretty hard thing to administer. Whenever something is merged we consider it fixed but it is pending release. Keep you eye on the release notes.

ieuangriffiths97 commented 1 year ago

+1 Commenting so I can keep track of when this gets released

stefanpirkl commented 1 year ago

+1 Commenting so I can keep track of when this gets released

Commenting your comment for the same reason

logtagenginterna commented 1 year ago

+1

+1 Commenting so I can keep track of when this gets released

Commenting your comment for the same reason

Raynham commented 1 year ago

+1

davidschachtschabel commented 1 year ago

+1

PATRICKdallat commented 1 year ago

+1

mikeluken commented 1 year ago

+1

mikeluken commented 1 year ago

Are you able to provide an update on the timing of when this fix will get released?

eli191 commented 12 months ago

Hello :) Getting same error here .Net8/Android 34 with Connectivity. Always a pleasure joining other guys on the side of the road.

ghost commented 12 months ago

@jfversluis Hello Guys. What is the final status of this issue? Is it resolved now? Yesterday I've run mobile app with the newest version of CommunityToolkit.Maui but the issue still occurs.

jfversluis commented 12 months ago

This issue has been resolved and a fix is merged but is yet to be released. I expect it to be part of the upcoming service release.

ghost commented 12 months ago

Thank you for your answer. So be patient and wait for new release.

albertruff commented 12 months ago

@albertruff You can temporary avoid this exception by setting the Android targetSdkVersion to 33 instead of 34.

How? <TargetFrameworks>net8.0-android33.0</TargetFrameworks> is not valid target.

Explicitly in the AndroidManifest under the Platform folder

logtagenginterna commented 11 months ago

Still get the exception on Connectivity.ConnectivityChanged in the newest pre-release from 3days ago, not sure if it's my fault or if the pre-release didn't include the fix

AmaluThomas commented 11 months ago

Hi @jfversluis Is the version out? still have the same issue

jfversluis commented 11 months ago

I don't think this has been released yet. If you want to be sure, check the nightly feed.

dartasen commented 11 months ago

+1

ghost commented 11 months ago

Hello lovely human, thank you for your comment on this issue. Because this issue has been closed for a period of time, please strongly consider opening a new issue linking to this issue instead to ensure better visibility of your comment. Thank you!

dylix commented 11 months ago

So exactly what nightly package is this fix included in?

korandasolutions commented 11 months ago

@dylix I just got around this by using nightly builds. This video got me going. Pioneers get the arrows, settlers get the land. I'm full of arrows.
https://www.youtube.com/watch?v=3EoAGNsYSDk

DanielCauser commented 10 months ago

+1

logtagenginterna commented 10 months ago

@dylix I just got around this by using nightly builds. This video got me going. Pioneers get the arrows, settlers get the land. I'm full of arrows. https://www.youtube.com/watch?v=3EoAGNsYSDk

+1 works on newest nightly build

EgonRasmussen commented 10 months ago

+1

nichojo89 commented 10 months ago

+1

TranTrieuLamQuynh commented 10 months ago

I'm using 8.0.6-nightly.9870. This issue has been resolved but on Android 14 event not trigger when connectivity change. Android 13 and below still works.

Thank for support!

mikeluken commented 10 months ago

I concur with @TranTrieuLamQuynh. The error is fixed in the nightly builds, but the connection change event is never hit when toggling Wi-Fi on/off. As such, this should be re-opened as it has not been resolved.

gabsamples6 commented 10 months ago

Connectivity Change event does not fire in android 34 and also does not fire in iOS

TranTrieuLamQuynh commented 10 months ago

@gabsamples6 We have checked again. Connectivity Change event work in iOS with me.

@mikeluken I used broadcast receiver register on Android and set intent.setPackage(getPackageName()) => the registered receiver will be able to listen for the action.

Note: All, I found the solution for all requireActivity().registerReceiver() calls. They will only listen for the action if the action is sent with the package name of the application. So whenever we send a broadcast, we should also set the package with the intent using intent.setPackage(getPackageName()). Then, the registered receiver will be able to listen for the action.

Reference link: https://developer.android.com/about/versions/14/behavior-changes-14#runtime-receivers-exported

mikeluken commented 10 months ago

@TranTrieuLamQuynh

Thanks for the comment. However, I do not fully understand your post. I don't have a broadcast receiver to register. In App.xaml.cs, I am just specifying:

Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;

In Android 13, this works. In Android 14, Connectivity_ConnectivityChanged is never hit when toggling on/off Wi-Fi.

Can you please provide a full example of how you got this to work?

It appears as though a fix was already attempted for this:

https://github.com/dotnet/maui/blame/584d99f14d9b54c25819d1594ceecd370183b92c/src/Essentials/src/Connectivity/Connectivity.android.cs#L48

However, I am running the latest nightly builds and this still does not work.

Note: I also added this to my MainActivity.OnCreate(...):

Intent.SetPackage(AppInfo.PackageName);

It had no effect.

TranTrieuLamQuynh commented 10 months ago

@mikeluken Particularly for android 14. I don't use Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged; Instead. I created BroadcastReceiver:

[BroadcastReceiver(Enabled = true, Exported = true)]
public class PowerConnectedBroadcastReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // Handle when wifi on/off
    }
}

Creat in MainActivity:

    PowerConnectedBroadcastReceiver _receiver;
    IntentFilter _intentFilter;

Then in OnStart() of MainActivity:

        if (OperatingSystem.IsAndroidVersionAtLeast(34))
        {
            Intent.SetPackage(AppInfo.Current.PackageName);
            _receiver = new ();
            _intentFilter = new ();
            _intentFilter.AddAction("android.net.conn.CONNECTIVITY_CHANGE");
            _intentFilter.Priority = (int)IntentFilterPriority.HighPriority;
            ContextCompat.RegisterReceiver(this, _receiver, _intentFilter, 1);
        }

I use this temporary solution until MAUI makes a correction If I have anything wrong. Wish you sympathize!

mikeluken commented 10 months ago

Thanks. Yes I was able to get broadcast receivers to work. I was however trying to point out the fact that ConnectivityChanged event in dotnet Maui doesn't work for Android 14.

gabsamples6 commented 10 months ago

The only hope we have now is that https://github.com/dotnet/maui/issues/19949 that you raised @mikeluken gets fixed.. and from what I can see is no part of any milestone.. which you know what that means

anotherlab commented 10 months ago

Adding the obligatory comment so I'll know when I can target Android 14

pasha-o commented 10 months ago

hi @jfversluis - Since Essentials is part of Maui now, is this issue going to be fixed? or a new issue should be created since this one is closed.

ataparia commented 10 months ago

+1 to keep it on my radar

samhouts commented 9 months ago

@TranTrieuLamQuynh

Thanks for the comment. However, I do not fully understand your post. I don't have a broadcast receiver to register. In App.xaml.cs, I am just specifying:

Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;

In Android 13, this works. In Android 14, Connectivity_ConnectivityChanged is never hit when toggling on/off Wi-Fi.

Can you please provide a full example of how you got this to work?

It appears as though a fix was already attempted for this:

https://github.com/dotnet/maui/blame/584d99f14d9b54c25819d1594ceecd370183b92c/src/Essentials/src/Connectivity/Connectivity.android.cs#L48

However, I am running the latest nightly builds and this still does not work.

Note: I also added this to my MainActivity.OnCreate(...):

Intent.SetPackage(AppInfo.PackageName);

It had no effect.

@mikeluken Thank you! Can you please open a new issue for this? It'll be easier for us to track it. Thanks!!!

dimplevador commented 9 months ago

@TranTrieuLamQuynh Thanks for the comment. However, I do not fully understand your post. I don't have a broadcast receiver to register. In App.xaml.cs, I am just specifying:

Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;

In Android 13, this works. In Android 14, Connectivity_ConnectivityChanged is never hit when toggling on/off Wi-Fi. Can you please provide a full example of how you got this to work? It appears as though a fix was already attempted for this: https://github.com/dotnet/maui/blame/584d99f14d9b54c25819d1594ceecd370183b92c/src/Essentials/src/Connectivity/Connectivity.android.cs#L48 However, I am running the latest nightly builds and this still does not work. Note: I also added this to my MainActivity.OnCreate(...):

Intent.SetPackage(AppInfo.PackageName);

It had no effect.

@mikeluken Thank you! Can you please open a new issue for this? It'll be easier for us to track it. Thanks!!!

Just adding my two cents, this intent https://github.com/dotnet/maui/blob/977642b689f1af22afe0f4cbaf21b6d8106f648c/src/Essentials/src/Connectivity/Connectivity.android.cs#L18 needs to have package info set in order for the connectivity change event to fire because of this change by google: https://developer.android.com/about/versions/14/behavior-changes-14#safer-intents

If I set this in the constructor of that class, everything works fine:

connectivityIntent.SetPackage(AppInfo.PackageName);