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

Update and implementation of UMP SDK to 2.2.0/2.4.0 #1062

Merged
merged 27 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
25a0677
Updated UMP dependency to 2.2.0
LTPhantom Mar 26, 2024
180f65e
Dart layer update
LTPhantom Apr 17, 2024
2931e01
Added UMP 2.2.0 Android implementation
LTPhantom Apr 18, 2024
2a9a225
Format Fix
LTPhantom Apr 18, 2024
397a519
Implemented iOS side of UMP methods
LTPhantom Apr 19, 2024
cd73eaf
Format fix
LTPhantom Apr 19, 2024
0607f02
Format fix
LTPhantom Apr 19, 2024
458f251
Format fix iOS
LTPhantom Apr 19, 2024
bdd72d5
Testing ConsentForm dart
LTPhantom Apr 19, 2024
1e4b574
Merge branch 'main' into umpUpdate
LTPhantom Apr 19, 2024
41dcd31
Format fix
LTPhantom Apr 19, 2024
a28baf4
Added Android unit tests
LTPhantom Apr 22, 2024
64eb4c3
Format Fix
LTPhantom Apr 22, 2024
0555826
Added iOS unit tests
LTPhantom Apr 23, 2024
5be8709
Format fix
LTPhantom Apr 23, 2024
dac660a
Format fix
LTPhantom Apr 23, 2024
260b182
More detailed CHANGELOG
LTPhantom Apr 25, 2024
21c3c38
Merge remote-tracking branch 'refs/remotes/origin/umpUpdate' into ump…
LTPhantom Apr 25, 2024
7dcbdb7
Update google_mobile_ads.yaml
LTPhantom Apr 25, 2024
1507669
Update google_mobile_ads.yaml
LTPhantom Apr 25, 2024
f22bc7c
Update google_mobile_ads.yaml
LTPhantom Apr 25, 2024
9931af5
Update google_mobile_ads.yaml
LTPhantom Apr 29, 2024
97ce7c7
Update google_mobile_ads.yaml
LTPhantom Apr 29, 2024
f3c4785
Update google_mobile_ads.yaml
LTPhantom Apr 29, 2024
9f7f0e8
Update google_mobile_ads.yaml
LTPhantom Apr 29, 2024
cfc57e7
Update google_mobile_ads.yaml
LTPhantom Apr 30, 2024
689a713
Corrected CHANGELOG
LTPhantom May 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/google_mobile_ads.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
flutter clean
flutter pub get
pod install
xcodebuild -configuration Debug -resultBundlePath TestResults VERBOSE_SCRIPT_LOGGING=YES -workspace Runner.xcworkspace -scheme Runner -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14 Pro,OS=16.2' test
xcodebuild -configuration Debug -resultBundlePath TestResults VERBOSE_SCRIPT_LOGGING=YES -workspace Runner.xcworkspace -scheme Runner -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.5' test
- uses: actions/upload-artifact@v4
if: failure()
with:
Expand Down
4 changes: 4 additions & 0 deletions packages/google_mobile_ads/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Next Version
* Adds support for APIs from the [Android](https://developers.google.com/admob/android/privacy/release-notes) UMP SDK version 2.2.0.
* Adds support for APIs from the [iOS](https://developers.google.com/admob/ios/privacy/download#release_notes) UMP SDK version 2.4.0.

## 5.0.0
* Adds `MediationExtras` class to include parameters when using mediation through the implementation of `FlutterMediationExtras` in Android and `FlutterMediationExtras` in iOS.
* Deprecates `MediationNetworkExtrasProvider` and `FLTMediationNetworkExtrasProvider`.
Expand Down
2 changes: 1 addition & 1 deletion packages/google_mobile_ads/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ android {
}
dependencies {
api 'com.google.android.gms:play-services-ads:23.0.0'
implementation 'com.google.android.ump:user-messaging-platform:2.1.0'
implementation 'com.google.android.ump:user-messaging-platform:2.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-process:2.6.2'
implementation 'com.google.errorprone:error_prone_annotations:2.16'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.ump.ConsentForm;
import com.google.android.ump.FormError;
import io.flutter.plugin.common.StandardMessageCodec;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
Expand All @@ -31,6 +32,7 @@ public class UserMessagingCodec extends StandardMessageCodec {
private static final byte VALUE_CONSENT_REQUEST_PARAMETERS = (byte) 129;
private static final byte VALUE_CONSENT_DEBUG_SETTINGS = (byte) 130;
private static final byte VALUE_CONSENT_FORM = (byte) 131;
private static final byte VALUE_FORM_ERROR = (byte) 132;

private final Map<Integer, ConsentForm> consentFormMap;

Expand All @@ -53,6 +55,11 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, @NonNull Object
} else if (value instanceof ConsentForm) {
stream.write(VALUE_CONSENT_FORM);
writeValue(stream, value.hashCode());
} else if (value instanceof FormError) {
stream.write(VALUE_FORM_ERROR);
FormError formError = (FormError) value;
writeValue(stream, formError.getErrorCode());
writeValue(stream, formError.getMessage());
} else {
super.writeValue(stream, value);
}
Expand Down Expand Up @@ -96,6 +103,12 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
Integer hash = (Integer) readValueOfType(buffer.get(), buffer);
return consentFormMap.get(hash);
}
case VALUE_FORM_ERROR:
{
Integer errorCode = (Integer) readValueOfType(buffer.get(), buffer);
String errorMessage = (String) readValueOfType(buffer.get(), buffer);
return new FormError(errorCode, errorMessage);
}
default:
return super.readValueOfType(type, buffer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,35 @@ public void onConsentInfoUpdateFailure(FormError error) {
});
break;
}
case "ConsentInformation#canRequestAds":
result.success(getConsentInformation().canRequestAds());
break;
case "ConsentInformation#getPrivacyOptionsRequirementStatus":
switch (getConsentInformation().getPrivacyOptionsRequirementStatus()) {
case NOT_REQUIRED:
result.success(0);
break;
case REQUIRED:
result.success(1);
break;
default:
result.success(2);
}
break;
case "UserMessagingPlatform#loadAndShowConsentFormIfRequired":
if (activity == null) {
result.error(
INTERNAL_ERROR_CODE,
"UserMessagingPlatform#loadAndShowConsentFormIfRequired called before plugin has been registered to an activity.",
null);
break;
}
UserMessagingPlatform.loadAndShowConsentFormIfRequired(
activity,
loadAndShowError -> {
result.success(loadAndShowError);
});
break;
case "UserMessagingPlatform#loadConsentForm":
UserMessagingPlatform.loadConsentForm(
context,
Expand All @@ -149,6 +178,20 @@ public void onConsentFormLoadFailure(FormError formError) {
}
});
break;
case "UserMessagingPlatform#showPrivacyOptionsForm":
if (activity == null) {
result.error(
INTERNAL_ERROR_CODE,
"UserMessagingPlatform#showPrivacyOptionsForm called before plugin has been registered to an activity.",
null);
break;
}
UserMessagingPlatform.showPrivacyOptionsForm(
activity,
loadAndShowError -> {
result.success(loadAndShowError);
});
break;
case "ConsentInformation#isConsentFormAvailable":
{
result.success(getConsentInformation().isConsentFormAvailable());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static org.mockito.Mockito.mock;

import com.google.android.ump.ConsentForm;
import com.google.android.ump.FormError;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -130,4 +131,16 @@ public void testConsentForm() {
decoded = (ConsentForm) codec.decodeMessage((ByteBuffer) message.position(0));
assertNull(decoded);
}

@Test
public void testFormError() {
FormError formError = new FormError(123, "testMessage");

final ByteBuffer message = codec.encodeMessage(formError);
FormError decoded = (FormError) codec.decodeMessage((ByteBuffer) message.position(0));

assert decoded != null;
assertEquals(formError.getErrorCode(), decoded.getErrorCode());
assertEquals(formError.getMessage(), decoded.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.google.android.ump.ConsentInformation.ConsentStatus;
import com.google.android.ump.ConsentInformation.OnConsentInfoUpdateFailureListener;
import com.google.android.ump.ConsentInformation.OnConsentInfoUpdateSuccessListener;
import com.google.android.ump.ConsentInformation.PrivacyOptionsRequirementStatus;
import com.google.android.ump.ConsentRequestParameters;
import com.google.android.ump.FormError;
import com.google.android.ump.UserMessagingPlatform;
Expand Down Expand Up @@ -170,6 +171,59 @@ public void testConsentInformation_isConsentFormAvailable() {
verify(result).success(eq(false));
}

@Test
public void testConsentInformation_canRequestAds() {
doReturn(true).when(mockConsentInformation).canRequestAds();
MethodCall methodCall = new MethodCall("ConsentInformation#canRequestAds", null);
Result result = mock(Result.class);

manager.onMethodCall(methodCall, result);

verify(result).success(eq(true));
}

@Test
public void testConsentInformation_getPrivacyOptionsRequirementStatus_notRequiredReturns0() {
doReturn(PrivacyOptionsRequirementStatus.NOT_REQUIRED)
.when(mockConsentInformation)
.getPrivacyOptionsRequirementStatus();
MethodCall methodCall =
new MethodCall("ConsentInformation#getPrivacyOptionsRequirementStatus", null);
Result result = mock(Result.class);

manager.onMethodCall(methodCall, result);

verify(result).success(eq(0));
}

@Test
public void testConsentInformation_getPrivacyOptionsRequirementStatus_requiredReturns1() {
doReturn(PrivacyOptionsRequirementStatus.REQUIRED)
.when(mockConsentInformation)
.getPrivacyOptionsRequirementStatus();
MethodCall methodCall =
new MethodCall("ConsentInformation#getPrivacyOptionsRequirementStatus", null);
Result result = mock(Result.class);

manager.onMethodCall(methodCall, result);

verify(result).success(eq(1));
}

@Test
public void testConsentInformation_getPrivacyOptionsRequirementStatus_requiredReturns2() {
doReturn(PrivacyOptionsRequirementStatus.UNKNOWN)
.when(mockConsentInformation)
.getPrivacyOptionsRequirementStatus();
MethodCall methodCall =
new MethodCall("ConsentInformation#getPrivacyOptionsRequirementStatus", null);
Result result = mock(Result.class);

manager.onMethodCall(methodCall, result);

verify(result).success(eq(2));
}

@Test
public void testUserMessagingPlatform_loadConsentFormAndDispose() {
MethodCall methodCall = new MethodCall("UserMessagingPlatform#loadConsentForm", null);
Expand Down Expand Up @@ -204,6 +258,78 @@ public void testUserMessagingPlatform_loadConsentFormAndDispose() {
verify(result).success(null);
}

@Test
public void testUserMessagingPlatform_loadAndShowConsentFormIfRequired() {
manager.setActivity(activity);
MethodCall methodCall =
new MethodCall("UserMessagingPlatform#loadAndShowConsentFormIfRequired", null);
Result result = mock(Result.class);

manager.onMethodCall(methodCall, result);

ArgumentCaptor<OnConsentFormDismissedListener> listenerCaptor =
ArgumentCaptor.forClass(OnConsentFormDismissedListener.class);
mockedUmp.verify(
() ->
UserMessagingPlatform.loadAndShowConsentFormIfRequired(
eq(activity), listenerCaptor.capture()));
listenerCaptor.getValue().onConsentFormDismissed(null);
verify(result).success(isNull());
}

@Test
public void testUserMessagingPlatform_loadAndShowConsentFormIfRequired_withFormError() {
manager.setActivity(activity);
FormError mockFormError = mock(FormError.class);
MethodCall methodCall =
new MethodCall("UserMessagingPlatform#loadAndShowConsentFormIfRequired", null);
Result result = mock(Result.class);

manager.onMethodCall(methodCall, result);

ArgumentCaptor<OnConsentFormDismissedListener> listenerCaptor =
ArgumentCaptor.forClass(OnConsentFormDismissedListener.class);
mockedUmp.verify(
() ->
UserMessagingPlatform.loadAndShowConsentFormIfRequired(
eq(activity), listenerCaptor.capture()));
listenerCaptor.getValue().onConsentFormDismissed(mockFormError);
verify(result).success(mockFormError);
}

@Test
public void testUserMessagingPlatform_showPrivacyOptionsForm() {
manager.setActivity(activity);
MethodCall methodCall = new MethodCall("UserMessagingPlatform#showPrivacyOptionsForm", null);
Result result = mock(Result.class);

manager.onMethodCall(methodCall, result);

ArgumentCaptor<OnConsentFormDismissedListener> listenerCaptor =
ArgumentCaptor.forClass(OnConsentFormDismissedListener.class);
mockedUmp.verify(
() -> UserMessagingPlatform.showPrivacyOptionsForm(eq(activity), listenerCaptor.capture()));
listenerCaptor.getValue().onConsentFormDismissed(null);
verify(result).success(isNull());
}

@Test
public void testUserMessagingPlatform_showPrivacyOptionsForm_withFormError() {
manager.setActivity(activity);
FormError mockFormError = mock(FormError.class);
MethodCall methodCall = new MethodCall("UserMessagingPlatform#showPrivacyOptionsForm", null);
Result result = mock(Result.class);

manager.onMethodCall(methodCall, result);

ArgumentCaptor<OnConsentFormDismissedListener> listenerCaptor =
ArgumentCaptor.forClass(OnConsentFormDismissedListener.class);
mockedUmp.verify(
() -> UserMessagingPlatform.showPrivacyOptionsForm(eq(activity), listenerCaptor.capture()));
listenerCaptor.getValue().onConsentFormDismissed(mockFormError);
verify(result).success(mockFormError);
}

@Test
public void testConsentForm_show() {
manager.setActivity(activity);
Expand Down
Loading