1use crossbow_android::{error::*, jni::JavaVM, plugin::*};
2use std::sync::Arc;
3
4pub struct AdMobPlugin {
5 singleton: Arc<JniSingleton>,
6 vm: Arc<JavaVM>,
7}
8
9impl CrossbowPlugin for AdMobPlugin {
10 fn from_java_vm(vm: Arc<JavaVM>) -> Result<Self>
11 where
12 Self: Sized,
13 {
14 let singleton = get_jni_singleton(Self::get_plugin_name()).ok_or_else(|| {
15 AndroidError::SingletonNotRegistered(Self::get_plugin_name().to_owned())
16 })?;
17 Ok(Self { singleton, vm })
18 }
19
20 fn get_plugin_name() -> &'static str {
21 "CrossbowAdMob"
22 }
23
24 fn get_receiver(&self) -> &Receiver<Signal> {
25 self.singleton.get_receiver()
26 }
27}
28
29impl AdMobPlugin {
30 pub fn initialize<S>(
55 &self,
56 is_for_child_directed_treatment: bool,
57 max_ad_content_rating: S,
58 is_real: bool,
59 is_test_europe_user_consent: bool,
60 ) -> Result<()>
61 where
62 S: AsRef<str>,
63 {
64 let jnienv = self.vm.attach_current_thread_as_daemon()?;
65 let g_str = jnienv.new_string(max_ad_content_rating)?;
66 self.singleton.call_method(
67 &jnienv,
68 "initialize",
69 &[
70 is_for_child_directed_treatment.into(),
71 g_str.into(),
72 is_real.into(),
73 is_test_europe_user_consent.into(),
74 ],
75 )?;
76 jnienv.exception_check()?;
77 Ok(())
78 }
79
80 pub fn is_initialized(&self) -> Result<bool> {
81 let jnienv = self.vm.attach_current_thread_as_daemon()?;
82 let val = self
83 .singleton
84 .call_method(&jnienv, "getIsInitialized", &[])?;
85 Ok(val.z()?)
86 }
87
88 pub fn load_interstitial(&self, ad_id: &str) -> Result<()> {
89 let jnienv = self.vm.attach_current_thread_as_daemon()?;
90 let ad_id = jnienv.new_string(ad_id.to_string())?;
91 self.singleton
92 .call_method(&jnienv, "loadInterstitial", &[ad_id.into()])?;
93 jnienv.exception_check()?;
94 Ok(())
95 }
96
97 pub fn is_interstitial_loaded(&self) -> Result<bool> {
98 let jnienv = self.vm.attach_current_thread_as_daemon()?;
99 let val = self
100 .singleton
101 .call_method(&jnienv, "getIsInterstitialLoaded", &[])?;
102 Ok(val.z()?)
103 }
104
105 pub fn show_interstitial(&self) -> Result<()> {
106 let jnienv = self.vm.attach_current_thread_as_daemon()?;
107 self.singleton
108 .call_method(&jnienv, "showInterstitial", &[])?;
109 jnienv.exception_check()?;
110 Ok(())
111 }
112
113 pub fn request_user_consent(&self) -> Result<()> {
114 let jnienv = self.vm.attach_current_thread_as_daemon()?;
115 self.singleton
116 .call_method(&jnienv, "requestUserConsent", &[])?;
117 jnienv.exception_check()?;
118 Ok(())
119 }
120
121 pub fn reset_consent_state(&self) -> Result<()> {
122 let jnienv = self.vm.attach_current_thread_as_daemon()?;
123 self.singleton
124 .call_method(&jnienv, "resetConsentState", &[])?;
125 jnienv.exception_check()?;
126 Ok(())
127 }
128
129 pub fn load_banner<S>(
130 &self,
131 ad_unit_id: S,
132 position: i32,
133 size: BannerSize,
134 show_instantly: bool,
135 respect_safe_area: bool,
136 ) -> Result<()>
137 where
138 S: AsRef<str>,
139 {
140 let jnienv = self.vm.attach_current_thread_as_daemon()?;
141 let ad_unit_id = jnienv.new_string(ad_unit_id)?;
142 let size = jnienv.new_string(size.to_string())?;
143 self.singleton.call_method(
144 &jnienv,
145 "loadBanner",
146 &[
147 ad_unit_id.into(),
148 position.into(),
149 size.into(),
150 show_instantly.into(),
151 respect_safe_area.into(),
152 ],
153 )?;
154 jnienv.exception_check()?;
155 Ok(())
156 }
157
158 pub fn is_banner_loaded(&self) -> Result<bool> {
159 let jnienv = self.vm.attach_current_thread_as_daemon()?;
160 let val = self
161 .singleton
162 .call_method(&jnienv, "getIsBannerLoaded", &[])?;
163 Ok(val.z()?)
164 }
165
166 pub fn destroy_banner(&self) -> Result<()> {
167 let jnienv = self.vm.attach_current_thread_as_daemon()?;
168 self.singleton.call_method(&jnienv, "destroyBanner", &[])?;
169 jnienv.exception_check()?;
170 Ok(())
171 }
172
173 pub fn show_banner(&self) -> Result<()> {
174 let jnienv = self.vm.attach_current_thread_as_daemon()?;
175 self.singleton.call_method(&jnienv, "showBanner", &[])?;
176 jnienv.exception_check()?;
177 Ok(())
178 }
179
180 pub fn hide_banner(&self) -> Result<()> {
181 let jnienv = self.vm.attach_current_thread_as_daemon()?;
182 self.singleton.call_method(&jnienv, "hideBanner", &[])?;
183 jnienv.exception_check()?;
184 Ok(())
185 }
186
187 pub fn banner_width(&self) -> Result<i32> {
188 let jnienv = self.vm.attach_current_thread_as_daemon()?;
189 let val = self.singleton.call_method(&jnienv, "getBannerWidth", &[])?;
190 Ok(val.i()?)
191 }
192
193 pub fn banner_height(&self) -> Result<i32> {
194 let jnienv = self.vm.attach_current_thread_as_daemon()?;
195 let val = self
196 .singleton
197 .call_method(&jnienv, "getBannerHeight", &[])?;
198 Ok(val.i()?)
199 }
200
201 pub fn banner_width_in_pixels(&self) -> Result<i32> {
202 let jnienv = self.vm.attach_current_thread_as_daemon()?;
203 let val = self
204 .singleton
205 .call_method(&jnienv, "getBannerWidthInPixels", &[])?;
206 Ok(val.i()?)
207 }
208
209 pub fn banner_height_in_pixels(&self) -> Result<i32> {
210 let jnienv = self.vm.attach_current_thread_as_daemon()?;
211 let val = self
212 .singleton
213 .call_method(&jnienv, "getBannerHeightInPixels", &[])?;
214 Ok(val.i()?)
215 }
216
217 pub fn load_rewarded<S>(&self, ad_unit_id: S) -> Result<()>
218 where
219 S: AsRef<str>,
220 {
221 let jnienv = self.vm.attach_current_thread_as_daemon()?;
222 let ad_unit_id = jnienv.new_string(ad_unit_id)?;
223 self.singleton
224 .call_method(&jnienv, "loadRewarded", &[ad_unit_id.into()])?;
225 jnienv.exception_check()?;
226 Ok(())
227 }
228
229 pub fn is_rewarded_loaded(&self) -> Result<bool> {
230 let jnienv = self.vm.attach_current_thread_as_daemon()?;
231 let val = self
232 .singleton
233 .call_method(&jnienv, "getIsRewardedLoaded", &[])?;
234 Ok(val.z()?)
235 }
236
237 pub fn show_rewarded(&self) -> Result<()> {
238 let jnienv = self.vm.attach_current_thread_as_daemon()?;
239 self.singleton.call_method(&jnienv, "showRewarded", &[])?;
240 jnienv.exception_check()?;
241 Ok(())
242 }
243
244 pub fn load_rewarded_interstitial<S>(&self, ad_unit_id: S) -> Result<()>
245 where
246 S: AsRef<str>,
247 {
248 let jnienv = self.vm.attach_current_thread_as_daemon()?;
249 let ad_unit_id = jnienv.new_string(ad_unit_id)?;
250 self.singleton
251 .call_method(&jnienv, "loadRewardedInterstitial", &[ad_unit_id.into()])?;
252 jnienv.exception_check()?;
253 Ok(())
254 }
255
256 pub fn is_rewarded_interstitial_loaded(&self) -> Result<bool> {
257 let jnienv = self.vm.attach_current_thread_as_daemon()?;
258 let val = self
259 .singleton
260 .call_method(&jnienv, "getIsRewardedInterstitialLoaded", &[])?;
261 Ok(val.z()?)
262 }
263
264 pub fn show_rewarded_interstitial(&self) -> Result<()> {
265 let jnienv = self.vm.attach_current_thread_as_daemon()?;
266 self.singleton
267 .call_method(&jnienv, "showRewardedInterstitial", &[])?;
268 jnienv.exception_check()?;
269 Ok(())
270 }
271}
272
273#[derive(Clone, Copy, Default)]
274pub enum BannerSize {
275 Banner,
276 LargeBanner,
277 MediumRectangle,
278 FullBanner,
279 Leaderboard,
280 Adaptive,
281 #[default]
282 SmartBanner,
283}
284
285impl ToString for BannerSize {
286 fn to_string(&self) -> String {
287 match self {
288 Self::Banner => "BANNER".to_string(),
289 Self::LargeBanner => "LARGE_BANNER".to_string(),
290 Self::MediumRectangle => "MEDIUM_RECTANGLE".to_string(),
291 Self::FullBanner => "FULL_BANNER".to_string(),
292 Self::Leaderboard => "LEADERBOARD".to_string(),
293 Self::Adaptive => "ADAPTIVE".to_string(),
294 Self::SmartBanner => "SMART_BANNER".to_string(),
295 }
296 }
297}