Skip to content

Commit

Permalink
Set location and pub provided id (googleads#367)
Browse files Browse the repository at this point in the history
* Add support for location and publisher provided id
  • Loading branch information
jjliu15 authored Oct 7, 2021
1 parent 2f5cbcb commit f32f2e8
Show file tree
Hide file tree
Showing 15 changed files with 664 additions and 290 deletions.
7 changes: 6 additions & 1 deletion packages/google_mobile_ads/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,16 @@
* [Ad manager iOS](https://developers.google.com/ad-manager/mobile-ads-sdk/ios/banner/inline-adaptive)
* Fix for [#369](https://github.com/googleads/googleads-mobile-flutter/issues/369)
* Fixes setting the app volume in android (doesn't affect iOS).
* Adds support for setting location in `AdRequest` and `AdManagerAdRequest`.
* Both `AdRequest` and `AdManagerAdRequest` have a new param, `location`.
* Location data is not used to target Google Ads, but may be used by 3rd party ad networks.
* See other packages for getting the location. For example, https://pub.dev/packages/location.
* Adds `publisherProvidedId` to `AdManagerAdRequest` to support [publisher provided ids](https://support.google.com/admanager/answer/2880055).

## 0.13.5

* Adds support for app open.
* Implementation guidance can be found [here](https://developers.devsite.corp.google.com/admob/flutter/app-open).
* Implementation guidance can be found [here](https://developers.google.com/admob/flutter/app-open).
* As a reference please also see the [example app](https://github.com/googleads/googleads-mobile-flutter/tree/master/packages/app_open_example).
* Best practices can be found [here](https://support.google.com/admob/answer/9341964?hl=en).

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 @@ -8,7 +8,7 @@ buildscript {
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.flutter.plugins.googlemobileads;

import android.content.Context;
import android.location.Location;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
Expand Down Expand Up @@ -52,6 +53,7 @@ class AdMessageCodec extends StandardMessageCodec {
private static final byte VALUE_NATIVE_AD_OPTIONS = (byte) 144;
private static final byte VALUE_VIDEO_OPTIONS = (byte) 145;
private static final byte VALUE_INLINE_ADAPTIVE_BANNER_AD_SIZE = (byte) 146;
static final byte VALUE_LOCATION_PARAMS = (byte) 147;

@NonNull Context context;
@NonNull final FlutterAdSize.AdSizeFactory adSizeFactory;
Expand All @@ -75,12 +77,27 @@ void setContext(@NonNull Context context) {
protected void writeValue(ByteArrayOutputStream stream, Object value) {
if (value instanceof FlutterAdSize) {
writeAdSize(stream, (FlutterAdSize) value);
} else if (value instanceof FlutterAdManagerAdRequest) {
stream.write(VALUE_ADMANAGER_AD_REQUEST);
final FlutterAdManagerAdRequest request = (FlutterAdManagerAdRequest) value;
writeValue(stream, request.getKeywords());
writeValue(stream, request.getContentUrl());
writeValue(stream, request.getCustomTargeting());
writeValue(stream, request.getCustomTargetingLists());
writeValue(stream, request.getNonPersonalizedAds());
writeValue(stream, request.getNeighboringContentUrls());
writeValue(stream, request.getHttpTimeoutMillis());
writeValue(stream, request.getPublisherProvidedId());
writeValue(stream, request.getLocation());
} else if (value instanceof FlutterAdRequest) {
stream.write(VALUE_AD_REQUEST);
final FlutterAdRequest request = (FlutterAdRequest) value;
writeValue(stream, request.getKeywords());
writeValue(stream, request.getContentUrl());
writeValue(stream, request.getNonPersonalizedAds());
writeValue(stream, request.getNeighboringContentUrls());
writeValue(stream, request.getHttpTimeoutMillis());
writeValue(stream, request.getLocation());
} else if (value instanceof FlutterRewardedAd.FlutterRewardItem) {
stream.write(VALUE_REWARD_ITEM);
final FlutterRewardedAd.FlutterRewardItem item = (FlutterRewardedAd.FlutterRewardItem) value;
Expand Down Expand Up @@ -113,14 +130,6 @@ protected void writeValue(ByteArrayOutputStream stream, Object value) {
writeValue(stream, error.code);
writeValue(stream, error.domain);
writeValue(stream, error.message);
} else if (value instanceof FlutterAdManagerAdRequest) {
stream.write(VALUE_ADMANAGER_AD_REQUEST);
final FlutterAdManagerAdRequest request = (FlutterAdManagerAdRequest) value;
writeValue(stream, request.getKeywords());
writeValue(stream, request.getContentUrl());
writeValue(stream, request.getCustomTargeting());
writeValue(stream, request.getCustomTargetingLists());
writeValue(stream, request.getNonPersonalizedAds());
} else if (value instanceof FlutterAdapterStatus.AdapterInitializationState) {
stream.write(VALUE_INITIALIZATION_STATE);
final FlutterAdapterStatus.AdapterInitializationState state =
Expand Down Expand Up @@ -165,6 +174,13 @@ protected void writeValue(ByteArrayOutputStream stream, Object value) {
writeValue(stream, options.clickToExpandRequested);
writeValue(stream, options.customControlsRequested);
writeValue(stream, options.startMuted);
} else if (value instanceof Location) {
stream.write(VALUE_LOCATION_PARAMS);
Location location = (Location) value;
writeValue(stream, location.getAccuracy());
writeValue(stream, location.getLongitude());
writeValue(stream, location.getLatitude());
writeValue(stream, location.getTime());
} else {
super.writeValue(stream, value);
}
Expand Down Expand Up @@ -200,6 +216,9 @@ protected Object readValueOfType(byte type, ByteBuffer buffer) {
.setKeywords((List<String>) readValueOfType(buffer.get(), buffer))
.setContentUrl((String) readValueOfType(buffer.get(), buffer))
.setNonPersonalizedAds(booleanValueOf(readValueOfType(buffer.get(), buffer)))
.setNeighboringContentUrls((List<String>) readValueOfType(buffer.get(), buffer))
.setHttpTimeoutMillis((Integer) readValueOfType(buffer.get(), buffer))
.setLocation((Location) readValueOfType(buffer.get(), buffer))
.build();
case VALUE_REWARD_ITEM:
return new FlutterRewardedAd.FlutterRewardItem(
Expand Down Expand Up @@ -229,14 +248,18 @@ protected Object readValueOfType(byte type, ByteBuffer buffer) {
(String) readValueOfType(buffer.get(), buffer),
(String) readValueOfType(buffer.get(), buffer));
case VALUE_ADMANAGER_AD_REQUEST:
return new FlutterAdManagerAdRequest.Builder()
.setKeywords((List<String>) readValueOfType(buffer.get(), buffer))
.setContentUrl((String) readValueOfType(buffer.get(), buffer))
.setCustomTargeting((Map<String, String>) readValueOfType(buffer.get(), buffer))
.setCustomTargetingLists(
(Map<String, List<String>>) readValueOfType(buffer.get(), buffer))
.setNonPersonalizedAds((Boolean) readValueOfType(buffer.get(), buffer))
.build();
FlutterAdManagerAdRequest.Builder builder = new FlutterAdManagerAdRequest.Builder();
builder.setKeywords((List<String>) readValueOfType(buffer.get(), buffer));
builder.setContentUrl((String) readValueOfType(buffer.get(), buffer));
builder.setCustomTargeting((Map<String, String>) readValueOfType(buffer.get(), buffer));
builder.setCustomTargetingLists(
(Map<String, List<String>>) readValueOfType(buffer.get(), buffer));
builder.setNonPersonalizedAds((Boolean) readValueOfType(buffer.get(), buffer));
builder.setNeighboringContentUrls((List<String>) readValueOfType(buffer.get(), buffer));
builder.setHttpTimeoutMillis((Integer) readValueOfType(buffer.get(), buffer));
builder.setPublisherProvidedId((String) readValueOfType(buffer.get(), buffer));
builder.setLocation((Location) readValueOfType(buffer.get(), buffer));
return builder.build();
case VALUE_INITIALIZATION_STATE:
final String state = (String) readValueOfType(buffer.get(), buffer);
switch (state) {
Expand Down Expand Up @@ -273,6 +296,14 @@ protected Object readValueOfType(byte type, ByteBuffer buffer) {
(Boolean) readValueOfType(buffer.get(), buffer),
(Boolean) readValueOfType(buffer.get(), buffer),
(Boolean) readValueOfType(buffer.get(), buffer));
case VALUE_LOCATION_PARAMS:
Location location = new Location("");
// This is necessary because StandardMessageCodec converts floats to double.
location.setAccuracy(((Double) readValueOfType(buffer.get(), buffer)).floatValue());
location.setLongitude((double) readValueOfType(buffer.get(), buffer));
location.setLatitude((double) readValueOfType(buffer.get(), buffer));
location.setTime((long) readValueOfType(buffer.get(), buffer));
return location;
default:
return super.readValueOfType(type, buffer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package io.flutter.plugins.googlemobileads;

import android.location.Location;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.google.ads.mediation.admob.AdMobAdapter;
Expand All @@ -26,29 +27,17 @@
* Instantiates and serializes {@link com.google.android.gms.ads.admanager.AdManagerAdRequest} for
* the Google Mobile Ads Plugin.
*/
class FlutterAdManagerAdRequest {
@Nullable private List<String> keywords;
@Nullable private String contentUrl;
class FlutterAdManagerAdRequest extends FlutterAdRequest {

@Nullable private Map<String, String> customTargeting;
@Nullable private Map<String, List<String>> customTargetingLists;
@Nullable private Boolean nonPersonalizedAds;
@Nullable private String publisherProvidedId;

static class Builder extends FlutterAdRequest.Builder {

public static class Builder {
@Nullable private List<String> keywords;
@Nullable private String contentUrl;
@Nullable private Map<String, String> customTargeting;
@Nullable private Map<String, List<String>> customTargetingLists;
@Nullable private Boolean nonPersonalizedAds;

public Builder setKeywords(@Nullable List<String> keywords) {
this.keywords = keywords;
return this;
}

public Builder setContentUrl(@Nullable String contentUrl) {
this.contentUrl = contentUrl;
return this;
}
@Nullable private String publisherProvidedId;

public Builder setCustomTargeting(@Nullable Map<String, String> customTargeting) {
this.customTargeting = customTargeting;
Expand All @@ -61,34 +50,57 @@ public Builder setCustomTargetingLists(
return this;
}

public Builder setNonPersonalizedAds(@Nullable Boolean nonPersonalizedAds) {
this.nonPersonalizedAds = nonPersonalizedAds;
public Builder setPublisherProvidedId(@Nullable String publisherProvidedId) {
this.publisherProvidedId = publisherProvidedId;
return this;
}

FlutterAdManagerAdRequest build() {
final FlutterAdManagerAdRequest request = new FlutterAdManagerAdRequest();
request.keywords = keywords;
request.contentUrl = contentUrl;
request.customTargeting = customTargeting;
request.customTargetingLists = customTargetingLists;
request.nonPersonalizedAds = nonPersonalizedAds;
return request;
return new FlutterAdManagerAdRequest(
getKeywords(),
getContentUrl(),
customTargeting,
customTargetingLists,
getNonPersonalizedAds(),
getNeighboringContentUrls(),
getHttpTimeoutMillis(),
getLocation(),
publisherProvidedId);
}
}

private FlutterAdManagerAdRequest() {}
private FlutterAdManagerAdRequest(
@Nullable List<String> keywords,
@Nullable String contentUrl,
@Nullable Map<String, String> customTargeting,
@Nullable Map<String, List<String>> customTargetingLists,
@Nullable Boolean nonPersonalizedAds,
@Nullable List<String> neighboringContentUrls,
@Nullable Integer httpTimeoutMillis,
@Nullable Location location,
@Nullable String publisherProvidedId) {
super(
keywords,
contentUrl,
nonPersonalizedAds,
neighboringContentUrls,
httpTimeoutMillis,
location);
this.customTargeting = customTargeting;
this.customTargetingLists = customTargetingLists;
this.publisherProvidedId = publisherProvidedId;
}

AdManagerAdRequest asAdManagerAdRequest() {
final AdManagerAdRequest.Builder builder = new AdManagerAdRequest.Builder();
if (keywords != null) {
for (final String keyword : keywords) {
if (getKeywords() != null) {
for (final String keyword : getKeywords()) {
builder.addKeyword(keyword);
}
}

if (contentUrl != null) {
builder.setContentUrl(contentUrl);
if (getContentUrl() != null) {
builder.setContentUrl(getContentUrl());
}
if (customTargeting != null) {
for (final Map.Entry<String, String> entry : customTargeting.entrySet()) {
Expand All @@ -100,38 +112,34 @@ AdManagerAdRequest asAdManagerAdRequest() {
builder.addCustomTargeting(entry.getKey(), entry.getValue());
}
}
if (nonPersonalizedAds != null && nonPersonalizedAds) {
if (getNonPersonalizedAds() != null && getNonPersonalizedAds()) {
final Bundle extras = new Bundle();
extras.putString("npa", "1");
builder.addNetworkExtrasBundle(AdMobAdapter.class, extras);
}
if (publisherProvidedId != null) {
builder.setPublisherProvidedId(publisherProvidedId);
}
if (getLocation() != null) {
builder.setLocation(getLocation());
}
builder.setRequestAgent(Constants.REQUEST_AGENT_PREFIX_VERSIONED);
return builder.build();
}

@Nullable
public List<String> getKeywords() {
return keywords;
}

@Nullable
public String getContentUrl() {
return contentUrl;
}

@Nullable
public Map<String, String> getCustomTargeting() {
protected Map<String, String> getCustomTargeting() {
return customTargeting;
}

@Nullable
public Map<String, List<String>> getCustomTargetingLists() {
protected Map<String, List<String>> getCustomTargetingLists() {
return customTargetingLists;
}

@Nullable
public Boolean getNonPersonalizedAds() {
return nonPersonalizedAds;
protected String getPublisherProvidedId() {
return publisherProvidedId;
}

@Override
Expand All @@ -143,20 +151,13 @@ public boolean equals(Object o) {
}

FlutterAdManagerAdRequest request = (FlutterAdManagerAdRequest) o;

return Objects.equals(keywords, request.keywords)
&& Objects.equals(contentUrl, request.contentUrl)
return super.equals(o)
&& Objects.equals(customTargeting, request.customTargeting)
&& Objects.equals(nonPersonalizedAds, request.nonPersonalizedAds)
&& Objects.equals(customTargetingLists, request.customTargetingLists);
}

@Override
public int hashCode() {
int result = keywords != null ? keywords.hashCode() : 0;
result = 31 * result + (contentUrl != null ? contentUrl.hashCode() : 0);
result = 31 * result + (customTargeting != null ? customTargeting.hashCode() : 0);
result = 31 * result + (customTargetingLists != null ? customTargetingLists.hashCode() : 0);
return result;
return Objects.hash(super.hashCode(), customTargeting, customTargetingLists);
}
}
Loading

0 comments on commit f32f2e8

Please sign in to comment.