react-native-google-mobile-ads 14.7.2 → 14.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/README.md +4 -2
  2. package/android/build.gradle +10 -0
  3. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeAppModule.java +2 -2
  4. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsConsentModule.java +2 -2
  5. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsMediaView.kt +57 -0
  6. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsMediaViewManager.kt +55 -0
  7. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsModule.kt +5 -4
  8. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsNativeAdView.kt +107 -0
  9. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsNativeAdViewManager.kt +85 -0
  10. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsNativeModule.kt +211 -0
  11. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsPackage.kt +102 -13
  12. package/android/src/oldarch/com/facebook/react/viewmanagers/RNGoogleMobileAdsMediaViewManagerDelegate.java +29 -0
  13. package/android/src/oldarch/com/facebook/react/viewmanagers/RNGoogleMobileAdsMediaViewManagerInterface.java +10 -0
  14. package/android/src/oldarch/com/facebook/react/viewmanagers/RNGoogleMobileAdsNativeViewManagerDelegate.java +33 -0
  15. package/android/src/oldarch/com/facebook/react/viewmanagers/RNGoogleMobileAdsNativeViewManagerInterface.java +10 -0
  16. package/android/src/oldarch/io/invertase/googlemobileads/NativeGoogleMobileAdsNativeModuleSpec.kt +18 -0
  17. package/docs/displaying-ads.mdx +4 -0
  18. package/docs/index.mdx +6 -4
  19. package/docs/native-ads.mdx +385 -0
  20. package/docs.json +1 -0
  21. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsMediaView.h +49 -0
  22. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsMediaView.mm +152 -0
  23. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsNativeModule.h +35 -0
  24. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsNativeModule.mm +290 -0
  25. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsNativeView.h +48 -0
  26. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsNativeView.mm +223 -0
  27. package/jest.setup.ts +7 -0
  28. package/lib/commonjs/NativeAdEventType.js +19 -0
  29. package/lib/commonjs/NativeAdEventType.js.map +1 -0
  30. package/lib/commonjs/TestIds.js +15 -8
  31. package/lib/commonjs/TestIds.js.map +1 -1
  32. package/lib/commonjs/ads/native-ad/NativeAd.js +122 -0
  33. package/lib/commonjs/ads/native-ad/NativeAd.js.map +1 -0
  34. package/lib/commonjs/ads/native-ad/NativeAdContext.js +26 -0
  35. package/lib/commonjs/ads/native-ad/NativeAdContext.js.map +1 -0
  36. package/lib/commonjs/ads/native-ad/NativeAdView.js +48 -0
  37. package/lib/commonjs/ads/native-ad/NativeAdView.js.map +1 -0
  38. package/lib/commonjs/ads/native-ad/NativeAsset.js +71 -0
  39. package/lib/commonjs/ads/native-ad/NativeAsset.js.map +1 -0
  40. package/lib/commonjs/ads/native-ad/NativeMediaView.js +58 -0
  41. package/lib/commonjs/ads/native-ad/NativeMediaView.js.map +1 -0
  42. package/lib/commonjs/common/ref.js +45 -0
  43. package/lib/commonjs/common/ref.js.map +1 -0
  44. package/lib/commonjs/index.js +47 -0
  45. package/lib/commonjs/index.js.map +1 -1
  46. package/lib/commonjs/specs/components/GoogleMobileAdsBannerViewNativeComponent.js +17 -0
  47. package/lib/commonjs/specs/components/GoogleMobileAdsBannerViewNativeComponent.js.map +1 -1
  48. package/lib/commonjs/specs/components/GoogleMobileAdsMediaViewNativeComponent.js +26 -0
  49. package/lib/commonjs/specs/components/GoogleMobileAdsMediaViewNativeComponent.js.map +1 -0
  50. package/lib/commonjs/specs/components/GoogleMobileAdsNativeViewNativeComponent.js +31 -0
  51. package/lib/commonjs/specs/components/GoogleMobileAdsNativeViewNativeComponent.js.map +1 -0
  52. package/lib/commonjs/specs/modules/NativeGoogleMobileAdsModule.js +1 -1
  53. package/lib/commonjs/specs/modules/NativeGoogleMobileAdsNativeModule.js +25 -0
  54. package/lib/commonjs/specs/modules/NativeGoogleMobileAdsNativeModule.js.map +1 -0
  55. package/lib/commonjs/types/NativeAdRequestOptions.js +37 -0
  56. package/lib/commonjs/types/NativeAdRequestOptions.js.map +1 -0
  57. package/lib/commonjs/types/index.js +11 -0
  58. package/lib/commonjs/types/index.js.map +1 -1
  59. package/lib/commonjs/version.js +1 -1
  60. package/lib/module/NativeAdEventType.js +13 -0
  61. package/lib/module/NativeAdEventType.js.map +1 -0
  62. package/lib/module/TestIds.js +15 -8
  63. package/lib/module/TestIds.js.map +1 -1
  64. package/lib/module/ads/native-ad/NativeAd.js +115 -0
  65. package/lib/module/ads/native-ad/NativeAd.js.map +1 -0
  66. package/lib/module/ads/native-ad/NativeAdContext.js +20 -0
  67. package/lib/module/ads/native-ad/NativeAdContext.js.map +1 -0
  68. package/lib/module/ads/native-ad/NativeAdView.js +40 -0
  69. package/lib/module/ads/native-ad/NativeAdView.js.map +1 -0
  70. package/lib/module/ads/native-ad/NativeAsset.js +63 -0
  71. package/lib/module/ads/native-ad/NativeAsset.js.map +1 -0
  72. package/lib/module/ads/native-ad/NativeMediaView.js +50 -0
  73. package/lib/module/ads/native-ad/NativeMediaView.js.map +1 -0
  74. package/lib/module/common/ref.js +38 -0
  75. package/lib/module/common/ref.js.map +1 -0
  76. package/lib/module/index.js +5 -0
  77. package/lib/module/index.js.map +1 -1
  78. package/lib/module/specs/components/GoogleMobileAdsBannerViewNativeComponent.js +17 -0
  79. package/lib/module/specs/components/GoogleMobileAdsBannerViewNativeComponent.js.map +1 -1
  80. package/lib/module/specs/components/GoogleMobileAdsMediaViewNativeComponent.js +20 -0
  81. package/lib/module/specs/components/GoogleMobileAdsMediaViewNativeComponent.js.map +1 -0
  82. package/lib/module/specs/components/GoogleMobileAdsNativeViewNativeComponent.js +24 -0
  83. package/lib/module/specs/components/GoogleMobileAdsNativeViewNativeComponent.js.map +1 -0
  84. package/lib/module/specs/modules/NativeGoogleMobileAdsModule.js +1 -1
  85. package/lib/module/specs/modules/NativeGoogleMobileAdsNativeModule.js +20 -0
  86. package/lib/module/specs/modules/NativeGoogleMobileAdsNativeModule.js.map +1 -0
  87. package/lib/module/types/NativeAdRequestOptions.js +32 -0
  88. package/lib/module/types/NativeAdRequestOptions.js.map +1 -0
  89. package/lib/module/types/index.js +1 -0
  90. package/lib/module/types/index.js.map +1 -1
  91. package/lib/module/version.js +1 -1
  92. package/lib/typescript/NativeAdEventType.d.ts +39 -0
  93. package/lib/typescript/NativeAdEventType.d.ts.map +1 -0
  94. package/lib/typescript/TestIds.d.ts +3 -0
  95. package/lib/typescript/TestIds.d.ts.map +1 -1
  96. package/lib/typescript/ads/native-ad/NativeAd.d.ts +46 -0
  97. package/lib/typescript/ads/native-ad/NativeAd.d.ts.map +1 -0
  98. package/lib/typescript/ads/native-ad/NativeAdContext.d.ts +10 -0
  99. package/lib/typescript/ads/native-ad/NativeAdContext.d.ts.map +1 -0
  100. package/lib/typescript/ads/native-ad/NativeAdView.d.ts +8 -0
  101. package/lib/typescript/ads/native-ad/NativeAdView.d.ts.map +1 -0
  102. package/lib/typescript/ads/native-ad/NativeAsset.d.ts +18 -0
  103. package/lib/typescript/ads/native-ad/NativeAsset.d.ts.map +1 -0
  104. package/lib/typescript/ads/native-ad/NativeMediaView.d.ts +7 -0
  105. package/lib/typescript/ads/native-ad/NativeMediaView.d.ts.map +1 -0
  106. package/lib/typescript/common/ref.d.ts +13 -0
  107. package/lib/typescript/common/ref.d.ts.map +1 -0
  108. package/lib/typescript/index.d.ts +6 -1
  109. package/lib/typescript/index.d.ts.map +1 -1
  110. package/lib/typescript/specs/components/GoogleMobileAdsBannerViewNativeComponent.d.ts.map +1 -1
  111. package/lib/typescript/specs/components/GoogleMobileAdsMediaViewNativeComponent.d.ts +9 -0
  112. package/lib/typescript/specs/components/GoogleMobileAdsMediaViewNativeComponent.d.ts.map +1 -0
  113. package/lib/typescript/specs/components/GoogleMobileAdsNativeViewNativeComponent.d.ts +14 -0
  114. package/lib/typescript/specs/components/GoogleMobileAdsNativeViewNativeComponent.d.ts.map +1 -0
  115. package/lib/typescript/specs/modules/NativeGoogleMobileAdsModule.d.ts +1 -17
  116. package/lib/typescript/specs/modules/NativeGoogleMobileAdsModule.d.ts.map +1 -1
  117. package/lib/typescript/specs/modules/NativeGoogleMobileAdsNativeModule.d.ts +37 -0
  118. package/lib/typescript/specs/modules/NativeGoogleMobileAdsNativeModule.d.ts.map +1 -0
  119. package/lib/typescript/types/NativeAdRequestOptions.d.ts +36 -0
  120. package/lib/typescript/types/NativeAdRequestOptions.d.ts.map +1 -0
  121. package/lib/typescript/types/index.d.ts +1 -0
  122. package/lib/typescript/types/index.d.ts.map +1 -1
  123. package/lib/typescript/version.d.ts +1 -1
  124. package/package.json +1 -1
  125. package/src/NativeAdEventType.ts +46 -0
  126. package/src/TestIds.ts +13 -6
  127. package/src/ads/native-ad/NativeAd.ts +152 -0
  128. package/src/ads/native-ad/NativeAdContext.ts +26 -0
  129. package/src/ads/native-ad/NativeAdView.tsx +43 -0
  130. package/src/ads/native-ad/NativeAsset.tsx +66 -0
  131. package/src/ads/native-ad/NativeMediaView.tsx +44 -0
  132. package/src/common/ref.ts +44 -0
  133. package/src/index.ts +5 -0
  134. package/src/specs/components/GoogleMobileAdsBannerViewNativeComponent.ts +17 -0
  135. package/src/specs/components/GoogleMobileAdsMediaViewNativeComponent.ts +30 -0
  136. package/src/specs/components/GoogleMobileAdsNativeViewNativeComponent.ts +44 -0
  137. package/src/specs/modules/NativeGoogleMobileAdsModule.ts +2 -2
  138. package/src/specs/modules/NativeGoogleMobileAdsNativeModule.ts +64 -0
  139. package/src/types/NativeAdRequestOptions.ts +55 -0
  140. package/src/types/index.ts +1 -0
  141. package/src/version.ts +1 -1
package/README.md CHANGED
@@ -86,7 +86,7 @@ You decide how and where they're placed, so the layout is more consistent your a
86
86
 
87
87
  <img width="300" src="https://developers.google.com/static/admob/images/format-native.svg" alt="Native">
88
88
 
89
- [Work In Progress](https://github.com/invertase/react-native-google-mobile-ads/pull/650)
89
+ [Learn More](https://docs.page/invertase/react-native-google-mobile-ads/native-ads)
90
90
 
91
91
  ### Interstitial
92
92
 
@@ -119,16 +119,18 @@ This package can be used in both The Old and [The New Architecture](https://reac
119
119
  When using The New Architecture, some legacy code will still be used though. See status below:
120
120
 
121
121
  | Platform | Feature | Status |
122
- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
122
+ | -------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------| ----------- |
123
123
  | iOS | Mobile Ads SDK Methods (Turbo Native Module) | ✅ Complete |
124
124
  | iOS | Banners (Fabric Native Component) | ✅ Complete |
125
125
  | iOS | Full Screen Ads (Turbo Native Module) | ✅ Complete |
126
+ | iOS | Native Ads (Turbo Native Module, Fabric Native Component) | ✅ Complete |
126
127
  | iOS | User Messaging Platform (Turbo Native Module) | ✅ Complete |
127
128
  | iOS | [EventEmitter](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/turbo-modules.md#add-event-emitting-capabilities) (Turbo Native Module) | ⏳ To-Do |
128
129
  | iOS | Revenue Precision Constants (Turbo Native Module) | ✅ Complete |
129
130
  | Android | Mobile Ads SDK Methods (Turbo Native Module) | ⏳ To-Do |
130
131
  | Android | Banners (Fabric Native Component) | ⏳ To-Do |
131
132
  | Android | Full Screen Ads (Turbo Native Module) | ⏳ To-Do |
133
+ | Android | Native Ads (Turbo Native Module, Fabric Native Component) | ✅ Complete |
132
134
  | Android | User Messaging Platform (Turbo Native Module) | ⏳ To-Do |
133
135
  | Android | [EventEmitter](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/turbo-modules.md#add-event-emitting-capabilities) (Turbo Native Module) | ⏳ To-Do |
134
136
  | Android | Revenue Precision Constants (Turbo Native Module) | ⏳ To-Do |
@@ -108,6 +108,16 @@ android {
108
108
  appJSONGoogleMobileAdsOptimizeAdLoading : appJSONGoogleMobileAdsOptimizeAdLoadingBool
109
109
  ]
110
110
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
111
+
112
+ sourceSets {
113
+ main {
114
+ if (isNewArchitectureEnabled()) {
115
+ java.srcDirs += ['src/newarch']
116
+ } else {
117
+ java.srcDirs += ['src/oldarch']
118
+ }
119
+ }
120
+ }
111
121
  }
112
122
  lintOptions {
113
123
  disable 'GradleCompatible'
@@ -30,10 +30,10 @@ import io.invertase.googlemobileads.common.ReactNativeModule;
30
30
  import io.invertase.googlemobileads.common.ReactNativePreferences;
31
31
 
32
32
  public class ReactNativeAppModule extends ReactNativeModule {
33
- private static final String TAG = "RNAppModule";
33
+ static final String NAME = "RNAppModule";
34
34
 
35
35
  ReactNativeAppModule(ReactApplicationContext reactContext) {
36
- super(reactContext, TAG);
36
+ super(reactContext, NAME);
37
37
  }
38
38
 
39
39
  @Override
@@ -35,11 +35,11 @@ import javax.annotation.Nonnull;
35
35
 
36
36
  public class ReactNativeGoogleMobileAdsConsentModule extends ReactNativeModule {
37
37
 
38
- private static final String TAG = "RNGoogleMobileAdsConsentModule";
38
+ static final String NAME = "RNGoogleMobileAdsConsentModule";
39
39
  private ConsentInformation consentInformation;
40
40
 
41
41
  public ReactNativeGoogleMobileAdsConsentModule(ReactApplicationContext reactContext) {
42
- super(reactContext, TAG);
42
+ super(reactContext, NAME);
43
43
  consentInformation = UserMessagingPlatform.getConsentInformation(reactContext);
44
44
  }
45
45
 
@@ -0,0 +1,57 @@
1
+ package io.invertase.googlemobileads
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import android.annotation.SuppressLint
21
+ import android.widget.ImageView
22
+ import com.facebook.react.bridge.ReactContext
23
+ import com.google.android.gms.ads.nativead.MediaView
24
+
25
+ @SuppressLint("ViewConstructor")
26
+ class ReactNativeGoogleMobileAdsMediaView(
27
+ private val context: ReactContext
28
+ ): MediaView(context) {
29
+ fun setResponseId(responseId: String?) {
30
+ val nativeModule = context.getNativeModule(ReactNativeGoogleMobileAdsNativeModule::class.java)
31
+ nativeModule?.getNativeAd(responseId ?: "")?.let {
32
+ this.mediaContent = it.mediaContent
33
+ requestLayout()
34
+ }
35
+ }
36
+
37
+ fun setResizeMode(resizeMode: String?) {
38
+ when (resizeMode) {
39
+ "cover" -> setImageScaleType(ImageView.ScaleType.CENTER_CROP)
40
+ "contain" -> setImageScaleType(ImageView.ScaleType.CENTER_INSIDE)
41
+ "stretch" -> setImageScaleType(ImageView.ScaleType.FIT_XY)
42
+ }
43
+ }
44
+
45
+ override fun requestLayout() {
46
+ super.requestLayout()
47
+ post(measureAndLayout)
48
+ }
49
+
50
+ private val measureAndLayout = Runnable {
51
+ measure(
52
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
53
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
54
+ )
55
+ layout(left, top, right, bottom)
56
+ }
57
+ }
@@ -0,0 +1,55 @@
1
+ package io.invertase.googlemobileads
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import com.facebook.react.bridge.ReactApplicationContext
21
+ import com.facebook.react.module.annotations.ReactModule
22
+ import com.facebook.react.uimanager.ThemedReactContext
23
+ import com.facebook.react.uimanager.ViewGroupManager
24
+ import com.facebook.react.uimanager.ViewManagerDelegate
25
+ import com.facebook.react.uimanager.annotations.ReactProp
26
+ import com.facebook.react.viewmanagers.RNGoogleMobileAdsMediaViewManagerDelegate
27
+ import com.facebook.react.viewmanagers.RNGoogleMobileAdsMediaViewManagerInterface
28
+
29
+ @ReactModule(name = ReactNativeGoogleMobileAdsMediaViewManager.NAME)
30
+ class ReactNativeGoogleMobileAdsMediaViewManager(
31
+ reactContext: ReactApplicationContext
32
+ ) : ViewGroupManager<ReactNativeGoogleMobileAdsMediaView>(reactContext),
33
+ RNGoogleMobileAdsMediaViewManagerInterface<ReactNativeGoogleMobileAdsMediaView> {
34
+ private val delegate: ViewManagerDelegate<ReactNativeGoogleMobileAdsMediaView> = RNGoogleMobileAdsMediaViewManagerDelegate(this)
35
+
36
+ override fun getDelegate(): ViewManagerDelegate<ReactNativeGoogleMobileAdsMediaView> = delegate
37
+
38
+ override fun getName(): String = NAME
39
+
40
+ override fun createViewInstance(context: ThemedReactContext): ReactNativeGoogleMobileAdsMediaView = ReactNativeGoogleMobileAdsMediaView(context)
41
+
42
+ @ReactProp(name = "responseId")
43
+ override fun setResponseId(view: ReactNativeGoogleMobileAdsMediaView, responseId: String?) {
44
+ view.setResponseId(responseId)
45
+ }
46
+
47
+ @ReactProp(name = "resizeMode")
48
+ override fun setResizeMode(view: ReactNativeGoogleMobileAdsMediaView, resizeMode: String?) {
49
+ view.setResizeMode(resizeMode)
50
+ }
51
+
52
+ companion object {
53
+ const val NAME = "RNGoogleMobileAdsMediaView"
54
+ }
55
+ }
@@ -26,13 +26,11 @@ import com.google.android.gms.ads.AdRequest
26
26
  import com.google.android.gms.ads.AdValue;
27
27
  import com.google.android.gms.ads.OnAdInspectorClosedListener
28
28
 
29
- private const val SERVICE = "RNGoogleMobileAdsModule";
30
-
31
29
  class ReactNativeGoogleMobileAdsModule(
32
30
  reactContext: ReactApplicationContext
33
31
  ) : ReactContextBaseJavaModule(reactContext) {
34
32
 
35
- override fun getName() = SERVICE
33
+ override fun getName() = NAME
36
34
 
37
35
  override fun getConstants(): Map<String, Any> {
38
36
  return mapOf(
@@ -164,7 +162,6 @@ class ReactNativeGoogleMobileAdsModule(
164
162
  }
165
163
  }
166
164
 
167
-
168
165
  @ReactMethod
169
166
  fun openDebugMenu(adUnit: String) {
170
167
  currentActivity?.runOnUiThread {
@@ -181,4 +178,8 @@ class ReactNativeGoogleMobileAdsModule(
181
178
  fun setAppMuted(muted: Boolean) {
182
179
  MobileAds.setAppMuted(muted)
183
180
  }
181
+
182
+ companion object {
183
+ const val NAME = "RNGoogleMobileAdsModule"
184
+ }
184
185
  }
@@ -0,0 +1,107 @@
1
+ package io.invertase.googlemobileads
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import android.annotation.SuppressLint
21
+ import android.widget.FrameLayout
22
+ import com.facebook.react.bridge.ReactContext
23
+ import com.facebook.react.uimanager.UIManagerHelper
24
+ import com.facebook.react.uimanager.common.UIManagerType
25
+ import com.facebook.react.views.view.ReactViewGroup
26
+ import com.google.android.gms.ads.nativead.MediaView
27
+ import com.google.android.gms.ads.nativead.NativeAd
28
+ import com.google.android.gms.ads.nativead.NativeAdView
29
+ import kotlinx.coroutines.CoroutineScope
30
+ import kotlinx.coroutines.Dispatchers
31
+ import kotlinx.coroutines.Job
32
+ import kotlinx.coroutines.delay
33
+ import kotlinx.coroutines.launch
34
+
35
+
36
+ @SuppressLint("ViewConstructor")
37
+ class ReactNativeGoogleMobileAdsNativeAdView(
38
+ private val context: ReactContext
39
+ ): FrameLayout(context) {
40
+ val viewGroup = ReactViewGroup(context)
41
+ private val nativeAdView = NativeAdView(context)
42
+ private var nativeAd: NativeAd? = null
43
+ private var reloadJob: Job? = null
44
+
45
+ init {
46
+ nativeAdView.addView(viewGroup)
47
+ addView(nativeAdView)
48
+ }
49
+
50
+ fun setResponseId(responseId: String?) {
51
+ val nativeModule = context.getNativeModule(ReactNativeGoogleMobileAdsNativeModule::class.java)
52
+ nativeModule?.getNativeAd(responseId ?: "")?.let {
53
+ if (nativeAd == it) {
54
+ return
55
+ }
56
+ nativeAd = it
57
+ reloadAd()
58
+ }
59
+ }
60
+
61
+ fun registerAsset(assetType: String, reactTag: Int) {
62
+ val uiManager = UIManagerHelper.getUIManagerForReactTag(context, reactTag)
63
+ val assetView = uiManager?.resolveView(reactTag) ?: return
64
+ when (assetType) {
65
+ "advertiser" -> nativeAdView.advertiserView = assetView
66
+ "body" -> nativeAdView.bodyView = assetView
67
+ "callToAction" -> nativeAdView.callToActionView = assetView
68
+ "headline" -> nativeAdView.headlineView = assetView
69
+ "price" -> nativeAdView.priceView = assetView
70
+ "store" -> nativeAdView.storeView = assetView
71
+ "starRating" -> nativeAdView.starRatingView = assetView
72
+ "icon" -> nativeAdView.iconView = assetView
73
+ "image" -> nativeAdView.imageView = assetView
74
+ "media" -> nativeAdView.mediaView = assetView as MediaView
75
+ }
76
+ reloadAd()
77
+ }
78
+
79
+ private fun reloadAd() {
80
+ reloadJob?.cancel()
81
+ reloadJob = CoroutineScope(Dispatchers.Main).launch {
82
+ delay(100)
83
+ nativeAd?.let { nativeAdView.setNativeAd(it) }
84
+ nativeAdView.rootView.requestLayout()
85
+ }
86
+ }
87
+
88
+ override fun requestLayout() {
89
+ super.requestLayout()
90
+ post(measureAndLayout)
91
+ }
92
+
93
+ fun destroy() {
94
+ reloadJob?.cancel()
95
+ reloadJob = null
96
+ nativeAdView.removeView(viewGroup)
97
+ nativeAdView.destroy()
98
+ }
99
+
100
+ private val measureAndLayout = Runnable {
101
+ measure(
102
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
103
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
104
+ )
105
+ layout(left, top, right, bottom)
106
+ }
107
+ }
@@ -0,0 +1,85 @@
1
+ package io.invertase.googlemobileads
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import android.view.View
21
+ import com.facebook.react.bridge.ReactApplicationContext
22
+ import com.facebook.react.bridge.ReactMethod
23
+ import com.facebook.react.module.annotations.ReactModule
24
+ import com.facebook.react.uimanager.ThemedReactContext
25
+ import com.facebook.react.uimanager.ViewGroupManager
26
+ import com.facebook.react.uimanager.ViewManagerDelegate
27
+ import com.facebook.react.uimanager.annotations.ReactProp
28
+ import com.facebook.react.viewmanagers.RNGoogleMobileAdsNativeViewManagerDelegate
29
+ import com.facebook.react.viewmanagers.RNGoogleMobileAdsNativeViewManagerInterface
30
+
31
+ @ReactModule(name = ReactNativeGoogleMobileAdsNativeAdViewManager.NAME)
32
+ class ReactNativeGoogleMobileAdsNativeAdViewManager(
33
+ reactContext: ReactApplicationContext
34
+ ) : ViewGroupManager<ReactNativeGoogleMobileAdsNativeAdView>(reactContext),
35
+ RNGoogleMobileAdsNativeViewManagerInterface<ReactNativeGoogleMobileAdsNativeAdView> {
36
+ private val delegate: ViewManagerDelegate<ReactNativeGoogleMobileAdsNativeAdView> = RNGoogleMobileAdsNativeViewManagerDelegate(this)
37
+
38
+ override fun getDelegate(): ViewManagerDelegate<ReactNativeGoogleMobileAdsNativeAdView> = delegate
39
+
40
+ override fun getName(): String = NAME
41
+
42
+ override fun createViewInstance(context: ThemedReactContext): ReactNativeGoogleMobileAdsNativeAdView = ReactNativeGoogleMobileAdsNativeAdView(context)
43
+
44
+ override fun onDropViewInstance(adView: ReactNativeGoogleMobileAdsNativeAdView) {
45
+ super.onDropViewInstance(adView)
46
+ adView.destroy()
47
+ }
48
+
49
+ override fun prepareToRecycleView(
50
+ reactContext: ThemedReactContext,
51
+ view: ReactNativeGoogleMobileAdsNativeAdView
52
+ ): ReactNativeGoogleMobileAdsNativeAdView? {
53
+ return null
54
+ }
55
+
56
+ @ReactProp(name = "responseId")
57
+ override fun setResponseId(view: ReactNativeGoogleMobileAdsNativeAdView, responseId: String?) {
58
+ view.setResponseId(responseId)
59
+ }
60
+
61
+ @ReactMethod
62
+ override fun registerAsset(view: ReactNativeGoogleMobileAdsNativeAdView, assetKey: String, reactTag: Int) {
63
+ view.registerAsset(assetKey, reactTag)
64
+ }
65
+
66
+ override fun addView(parent: ReactNativeGoogleMobileAdsNativeAdView, child: View, index: Int) {
67
+ parent.viewGroup.addView(child, index)
68
+ }
69
+
70
+ override fun getChildCount(parent: ReactNativeGoogleMobileAdsNativeAdView): Int {
71
+ return parent.viewGroup.childCount
72
+ }
73
+
74
+ override fun getChildAt(parent: ReactNativeGoogleMobileAdsNativeAdView, index: Int): View? {
75
+ return parent.viewGroup.getChildAt(index)
76
+ }
77
+
78
+ override fun removeViewAt(parent: ReactNativeGoogleMobileAdsNativeAdView, index: Int) {
79
+ parent.viewGroup.removeViewAt(index)
80
+ }
81
+
82
+ companion object {
83
+ const val NAME = "RNGoogleMobileAdsNativeView"
84
+ }
85
+ }
@@ -0,0 +1,211 @@
1
+ package io.invertase.googlemobileads
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import com.facebook.react.bridge.Arguments
21
+ import com.facebook.react.bridge.Promise
22
+ import com.facebook.react.bridge.ReactApplicationContext
23
+ import com.facebook.react.bridge.ReactMethod
24
+ import com.facebook.react.bridge.ReadableMap
25
+ import com.facebook.react.module.annotations.ReactModule
26
+ import com.google.android.gms.ads.AdListener
27
+ import com.google.android.gms.ads.AdLoader
28
+ import com.google.android.gms.ads.MediaAspectRatio
29
+ import com.google.android.gms.ads.VideoController.VideoLifecycleCallbacks
30
+ import com.google.android.gms.ads.VideoOptions
31
+ import com.google.android.gms.ads.nativead.NativeAd
32
+ import com.google.android.gms.ads.nativead.NativeAdOptions
33
+
34
+ @ReactModule(ReactNativeGoogleMobileAdsNativeModule.NAME)
35
+ class ReactNativeGoogleMobileAdsNativeModule(
36
+ reactContext: ReactApplicationContext
37
+ ) : NativeGoogleMobileAdsNativeModuleSpec(reactContext) {
38
+ private val adHolders = HashMap<String, NativeAdHolder>()
39
+
40
+ override fun getName() = NAME
41
+
42
+ @ReactMethod
43
+ override fun load(adUnitId: String, requestOptions: ReadableMap, promise: Promise) {
44
+ val holder = NativeAdHolder(adUnitId, requestOptions)
45
+ holder.loadAd { nativeAd ->
46
+ val responseId = nativeAd.responseInfo?.responseId ?: return@loadAd
47
+ adHolders[responseId] = holder
48
+
49
+ val data = Arguments.createMap()
50
+ data.putString("responseId", responseId)
51
+ data.putString("advertiser", nativeAd.advertiser)
52
+ data.putString("body", nativeAd.body)
53
+ data.putString("callToAction", nativeAd.callToAction)
54
+ data.putString("headline", nativeAd.headline)
55
+ data.putString("price", nativeAd.price)
56
+ data.putString("store", nativeAd.store)
57
+ nativeAd.starRating?.let {
58
+ data.putDouble("starRating", it)
59
+ } ?: run {
60
+ data.putNull("starRating")
61
+ }
62
+ nativeAd.icon?.let {
63
+ val icon = Arguments.createMap()
64
+ icon.putDouble("scale", it.scale)
65
+ icon.putString("url", it.uri.toString())
66
+ data.putMap("icon", icon)
67
+ } ?: run {
68
+ data.putNull("icon")
69
+ }
70
+ val mediaContent = Arguments.createMap()
71
+ nativeAd.mediaContent?.let {
72
+ mediaContent.putDouble("aspectRatio", it.aspectRatio.toDouble())
73
+ mediaContent.putBoolean("hasVideoContent", it.hasVideoContent())
74
+ mediaContent.putDouble("duration", it.duration.toDouble())
75
+ data.putMap("mediaContent", mediaContent)
76
+ }
77
+
78
+ promise.resolve(data)
79
+ }
80
+ }
81
+
82
+ @ReactMethod
83
+ override fun destroy(responseId: String) {
84
+ adHolders[responseId]?.destroy()
85
+ adHolders.remove(responseId)
86
+ }
87
+
88
+ override fun invalidate() {
89
+ super.invalidate()
90
+ adHolders.values.forEach {
91
+ it.destroy()
92
+ }
93
+ adHolders.clear()
94
+ }
95
+
96
+ fun getNativeAd(responseId: String): NativeAd? {
97
+ return adHolders[responseId]?.nativeAd
98
+ }
99
+
100
+ private inner class NativeAdHolder(private val adUnitId: String, private val requestOptions: ReadableMap) {
101
+ var nativeAd: NativeAd? = null
102
+ private set
103
+
104
+ private val adListener: AdListener = object : AdListener() {
105
+ override fun onAdImpression() {
106
+ emitAdEvent("impression")
107
+ }
108
+
109
+ override fun onAdClicked() {
110
+ emitAdEvent("clicked")
111
+ }
112
+
113
+ override fun onAdOpened() {
114
+ emitAdEvent("opened")
115
+ }
116
+
117
+ override fun onAdClosed() {
118
+ emitAdEvent("closed")
119
+ }
120
+ }
121
+
122
+ private val videoLifecycleCallbacks: VideoLifecycleCallbacks = object : VideoLifecycleCallbacks() {
123
+ override fun onVideoPlay() {
124
+ emitAdEvent("video_played")
125
+ }
126
+
127
+ override fun onVideoPause() {
128
+ emitAdEvent("video_paused")
129
+ }
130
+
131
+ override fun onVideoEnd() {
132
+ emitAdEvent("video_ended")
133
+ }
134
+
135
+ override fun onVideoMute(isMuted: Boolean) {
136
+ emitAdEvent(if (isMuted) {
137
+ "video_muted"
138
+ } else {
139
+ "video_unmuted"
140
+ })
141
+ }
142
+ }
143
+
144
+ fun loadAd(loadedListener: NativeAd.OnNativeAdLoadedListener) {
145
+ val mediaAspectRatio = if (requestOptions.hasKey("aspectRatio")) {
146
+ when (requestOptions.getInt("aspectRatio")) {
147
+ 1 -> MediaAspectRatio.ANY
148
+ 2 -> MediaAspectRatio.PORTRAIT
149
+ 3 -> MediaAspectRatio.LANDSCAPE
150
+ 4 -> MediaAspectRatio.SQUARE
151
+ else -> MediaAspectRatio.UNKNOWN
152
+ }
153
+ } else {
154
+ MediaAspectRatio.ANY
155
+ }
156
+ val adChoicesPlacement = if (requestOptions.hasKey("adChoicesPlacement")) {
157
+ when (requestOptions.getInt("adChoicesPlacement")) {
158
+ 0 -> NativeAdOptions.ADCHOICES_TOP_RIGHT
159
+ 1 -> NativeAdOptions.ADCHOICES_TOP_LEFT
160
+ 2 -> NativeAdOptions.ADCHOICES_BOTTOM_RIGHT
161
+ 3 -> NativeAdOptions.ADCHOICES_BOTTOM_LEFT
162
+ else -> NativeAdOptions.ADCHOICES_TOP_RIGHT
163
+ }
164
+ } else {
165
+ NativeAdOptions.ADCHOICES_TOP_RIGHT
166
+ }
167
+ val startVideoMuted = if (requestOptions.hasKey("startVideoMuted")) {
168
+ requestOptions.getBoolean("startVideoMuted")
169
+ } else {
170
+ true
171
+ }
172
+ val videoOptions = VideoOptions.Builder()
173
+ .setStartMuted(startVideoMuted)
174
+ .build()
175
+ val nativeAdOptions = NativeAdOptions.Builder()
176
+ // .setReturnUrlsForImageAssets(true)
177
+ .setMediaAspectRatio(mediaAspectRatio)
178
+ .setAdChoicesPlacement(adChoicesPlacement)
179
+ .setVideoOptions(videoOptions)
180
+ .build()
181
+ val adLoader = AdLoader.Builder(reactApplicationContext, adUnitId)
182
+ .withNativeAdOptions(nativeAdOptions)
183
+ .withAdListener(adListener)
184
+ .forNativeAd { nativeAd ->
185
+ this.nativeAd = nativeAd
186
+ nativeAd.mediaContent?.videoController?.videoLifecycleCallbacks = videoLifecycleCallbacks
187
+ loadedListener.onNativeAdLoaded(nativeAd)
188
+ }
189
+ .build()
190
+ val adRequest = ReactNativeGoogleMobileAdsCommon.buildAdRequest(requestOptions)
191
+ adLoader.loadAd(adRequest)
192
+ }
193
+
194
+ fun destroy() {
195
+ nativeAd?.destroy()
196
+ nativeAd = null
197
+ }
198
+
199
+ private fun emitAdEvent(type: String) {
200
+ val nativeAd = this.nativeAd ?: return
201
+ val payload = Arguments.createMap()
202
+ payload.putString("responseId", nativeAd.responseInfo?.responseId)
203
+ payload.putString("type", type)
204
+ this@ReactNativeGoogleMobileAdsNativeModule.emitOnAdEvent(payload)
205
+ }
206
+ }
207
+
208
+ companion object {
209
+ const val NAME = "RNGoogleMobileAdsNativeModule"
210
+ }
211
+ }