-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[In_App_Purchase] Avoids possible NullPointerException with background registrations. #2014
[In_App_Purchase] Avoids possible NullPointerException with background registrations. #2014
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for finding this issue and submitting a fix!
Could you also add a test for this? We don't have it wired up to CI yet unfortunately, but we do have JUnit tests that we've been running manually in packages/in_app_purchase/example/android/app/src/test/
. I've been running them by opening packages/in_app_purchase/example/android
in Android Studio, and then executing them from there.
@@ -67,10 +68,13 @@ | |||
|
|||
/** Plugin registration. */ | |||
public static void registerWith(Registrar registrar) { | |||
final Activity activity = registrar.activity(); | |||
if (activity == null) { | |||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for devs in this state it's better to throw a RuntimeException
with an error message and crash than to silently fail, even in release mode. This case means that none of the functions of the plugin are going to actually work, so silently returning is slipping the app into an unrecoverable error state. None of the API calls will work, and there isn't going to be a clear sign or reason why from the app developer's side. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used the same strategy used here. It is of my understanding that the plugin will get a second change to register itself when an Activity is available. Raising an exception here would make that impossible to to flutter developers to handle. When a background or foreground registration happens it execute a "register all command" . That can be seem here and in foreground here. In other words, it would make impossible to use Alarm Manager Plugin and In App Purchase plugin in the same project.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks for the clarification. I've done some digging on my end to understand this better.
So from my testing IFF the user sets up a custom Application.java
with android_alarm_manager
, like in the example app, the callbacks always try to register with a null activity. The Flutter app using these periodic callbacks sets up the plugins using MainActivity
in the typical way in its standard isolate, and can make calls like expected. However the callbacks are always registered with a null activity, regardless of whether or not the plugin is in the foreground when the callbacks fire.
Throwing an exception like I originally suggested definitely doesn't make sense, because this registration happens for all plugins whether or not they're actually used in the callback. So that would make this unusable in conjunction with the plugin, like you mentioned.
This return also introduces some potential new runtime errors IFF the callbacks try to use the IAP API at all in their callbacks, since they always execute with a background isolate and null activity, but not all of the IAP methods actually need an activity at all. On some more thought about this I think that's a regression we probably want to avoid. The critical launchBillingFlow
one requires an Activity
, but I can see a dev using only unrelated methods like queryPurchases
in their background callbacks instead.
Sorry about the back and forth. With that in mind, I think a better approach would be to actually accept registration when activity
is null, but to mark InAppPurchasePlugin#activity
as @Nullable
and return result.error()
in launchBillingFlow
if it's called while activity
is null. This is similar to how we enforce that BillingClient
has been set correctly in API calls that require it with the InAppPurchase#billingClientError
helper method. I think the same "UNAVAILABLE"
tag but with a different message about the activity would make sense. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no problem in this back and forth. We are evolving in the solution. :-)
I hadn't thought about enabling the plugin usage in background, nice catch.
I will update the code/tests as needed.
...app_purchase/android/src/main/java/io/flutter/plugins/inapppurchase/InAppPurchasePlugin.java
Outdated
Show resolved
Hide resolved
… in a more specific method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...app_purchase/android/src/main/java/io/flutter/plugins/inapppurchase/InAppPurchasePlugin.java
Outdated
Show resolved
Hide resolved
…ins/inapppurchase/InAppPurchasePlugin.java Co-Authored-By: Michael Klimushyn <mklim@google.com>
Co-Authored-By: Michael Klimushyn <mklim@google.com>
@BugsBunnyBR I'm not sure why, but the ETA: Talked offline with @collinjackson and confirmed that merging in master will fix this failure for sure. |
…yBR/plugins into plugin/in_app_purchase_null_fix
I updated the master branch, but the tests are still failing. I tried to run |
Thanks doc! |
…d registrations. (flutter#2014) This PR delays the get of a reference of a Activity instance and raises an error in case of a invalid access to the method that uses it.
…d registrations. (flutter#2014) This PR delays the get of a reference of a Activity instance and raises an error in case of a invalid access to the method that uses it.
Description
This PR delays the get of a reference of a Activity instance and raises an error in case of a invalid access to the method that uses it.
Related Issues
flutter/flutter#38692
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]
). This will ensure a smooth and quick review process.///
).flutter analyze
) does not report any problems on my PR.Breaking Change
Does your PR require plugin users to manually update their apps to accommodate your change?