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

Add prototype of Google AdMob ads #1760

Merged
merged 49 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
d2d0a0c
Add AdMob app ID to AndroidManifest
nilsreichardt Oct 10, 2024
3824aad
Add `google_mobile_ads` as dependency
nilsreichardt Oct 10, 2024
e851361
Add `AdBanner` widget
nilsreichardt Oct 10, 2024
feddfb4
Add native add to dashboard page
nilsreichardt Oct 10, 2024
140371e
Init AdMob on app startup
nilsreichardt Oct 10, 2024
25b346b
Add empty ads controller
nilsreichardt Oct 10, 2024
133d9e6
Add ads banner to timetable page
nilsreichardt Oct 10, 2024
dadd756
Add test add to homework fab
nilsreichardt Oct 10, 2024
254d2ba
Rewrite `AdsController`
nilsreichardt Oct 12, 2024
99652db
Add `removeAds` to `SharezonePlusFeature`
nilsreichardt Oct 12, 2024
4eb62dc
Remove `MobileAds.instance.initialize` from `run_app.dart`
nilsreichardt Oct 12, 2024
f7d341a
Add ad banner to homework page
nilsreichardt Oct 12, 2024
11840aa
Add `ads_enabled` to Remote Config setup
nilsreichardt Oct 12, 2024
36cf167
Make `ad_section.dart` on dashboard more native
nilsreichardt Oct 12, 2024
b04734f
Improve ad banner
nilsreichardt Oct 12, 2024
bb452c2
Revert `homework_fab.dart`
nilsreichardt Oct 12, 2024
0911bd4
Add homework counter
nilsreichardt Oct 12, 2024
05f64e0
Show ad after adding a homework
nilsreichardt Oct 12, 2024
6d58245
Remove unused import
nilsreichardt Oct 12, 2024
2ebb489
Add App ID for iOS
nilsreichardt Oct 12, 2024
1046018
Fix app ids
nilsreichardt Oct 12, 2024
787bad9
Add `ad_content_url` to default values
nilsreichardt Oct 12, 2024
4bd9eef
Fix Provider
nilsreichardt Oct 12, 2024
b42ba99
Ad advantage of "remove ads" to Sharezone Plus page
nilsreichardt Oct 13, 2024
a771f73
Fix displaying ads in text mode
nilsreichardt Oct 13, 2024
0b848b6
Fix displaying fullscreen ad after adding/editing homework
nilsreichardt Oct 13, 2024
1f317b6
Ad info dialog
nilsreichardt Oct 13, 2024
dd3ce7d
Add LH
nilsreichardt Oct 13, 2024
1428c6b
Set to false
nilsreichardt Oct 13, 2024
7da4ed5
Remove unused code
nilsreichardt Oct 13, 2024
5d96269
Fix homework tests
nilsreichardt Oct 13, 2024
147b054
Merge remote-tracking branch 'origin/main' into ads
nilsreichardt Oct 13, 2024
dff857c
Update mocks
nilsreichardt Oct 13, 2024
b902caa
Improve comments
nilsreichardt Oct 13, 2024
b2b6a38
Formatting
nilsreichardt Oct 13, 2024
d0b552f
Install Pods
nilsreichardt Oct 13, 2024
5da6749
Add platform check
nilsreichardt Oct 13, 2024
434abbf
Add activation flag
nilsreichardt Oct 13, 2024
076e0e6
Fix bug with info dialog
nilsreichardt Oct 13, 2024
e4e4af1
Fix flag for activation code
nilsreichardt Oct 13, 2024
1edd830
Improve native ads layout
nilsreichardt Oct 13, 2024
a055702
Show fullscreen after every fifth homework check
nilsreichardt Oct 14, 2024
fdc5691
Remove counter from homework dialog
nilsreichardt Oct 14, 2024
4bbfb7e
Fix update reminder card tests
nilsreichardt Oct 14, 2024
d05f2d5
Fix homework dialog test
nilsreichardt Oct 14, 2024
ca195c5
Show dialog also for activation code
nilsreichardt Oct 14, 2024
178bc60
Update ads info dialog
nilsreichardt Oct 14, 2024
b454800
Fix ad unit ids
nilsreichardt Oct 14, 2024
36131ef
Fix gap on timetable page
nilsreichardt Oct 14, 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
3 changes: 3 additions & 0 deletions app/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
</queries>

<application android:requestLegacyExternalStorage="true" android:label="@string/app_name" android:icon="@mipmap/ic_launcher">
<!-- From: https://developers.google.com/admob/flutter/quick-start#platform_specific_setup -->
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-7730914075870960~2331360962"/>

<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/statusbar_notification" />
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorAccent" />
<meta-data android:name="flutterEmbedding" android:value="2" />
Expand Down
15 changes: 15 additions & 0 deletions app/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,12 @@ PODS:
- SDWebImageWebPCoder
- flutter_timezone (0.0.1):
- Flutter
- Google-Mobile-Ads-SDK (11.10.0):
- GoogleUserMessagingPlatform (>= 1.1)
- google_mobile_ads (5.2.0):
- Flutter
- Google-Mobile-Ads-SDK (~> 11.10.0)
- webview_flutter_wkwebview
- google_sign_in_ios (0.0.1):
- AppAuth (>= 1.7.4)
- Flutter
Expand Down Expand Up @@ -304,6 +310,7 @@ PODS:
- GoogleToolboxForMac/Defines (= 4.2.1)
- "GoogleToolboxForMac/NSData+zlib (4.2.1)":
- GoogleToolboxForMac/Defines (= 4.2.1)
- GoogleUserMessagingPlatform (2.6.0)
- GoogleUtilities/AppDelegateSwizzler (7.13.3):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
Expand Down Expand Up @@ -462,6 +469,7 @@ DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_image_compress_common (from `.symlinks/plugins/flutter_image_compress_common/ios`)
- flutter_timezone (from `.symlinks/plugins/flutter_timezone/ios`)
- google_mobile_ads (from `.symlinks/plugins/google_mobile_ads/ios`)
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
Expand Down Expand Up @@ -515,11 +523,13 @@ SPEC REPOS:
- FirebaseSessions
- FirebaseSharedSwift
- FirebaseStorage
- Google-Mobile-Ads-SDK
- GoogleAppMeasurement
- GoogleDataTransport
- GoogleMLKit
- GoogleSignIn
- GoogleToolboxForMac
- GoogleUserMessagingPlatform
- GoogleUtilities
- GoogleUtilitiesComponents
- GTMAppAuth
Expand Down Expand Up @@ -581,6 +591,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_image_compress_common/ios"
flutter_timezone:
:path: ".symlinks/plugins/flutter_timezone/ios"
google_mobile_ads:
:path: ".symlinks/plugins/google_mobile_ads/ios"
google_sign_in_ios:
:path: ".symlinks/plugins/google_sign_in_ios/darwin"
image_picker_ios:
Expand Down Expand Up @@ -676,12 +688,15 @@ SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
flutter_timezone: ffb07bdad3c6276af8dada0f11978d8a1f8a20bb
Google-Mobile-Ads-SDK: 13e6e98edfd78ad8d8a791edb927658cc260a56f
google_mobile_ads: 2a538d8e42b1813809782792e48f8cf4374c2180
google_sign_in_ios: 07375bfbf2620bc93a602c0e27160d6afc6ead38
GoogleAppMeasurement: 9abf64b682732fed36da827aa2a68f0221fd2356
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleMLKit: 97ac7af399057e99182ee8edfa8249e3226a4065
GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db
GoogleToolboxForMac: d1a2cbf009c453f4d6ded37c105e2f67a32206d8
GoogleUserMessagingPlatform: 0c3a08353e53ce8c2feab7addd0b652cde522450
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
GoogleUtilitiesComponents: 679b2c881db3b615a2777504623df6122dd20afe
GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
Expand Down
6 changes: 6 additions & 0 deletions app/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,10 @@
"${PODS_CONFIGURATION_BUILD_DIR}/FirebaseFirestoreGRPCCPPBinary/FirebaseFirestoreGRPCCPPBinary_Privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/FirebaseFirestoreGRPCCoreBinary/FirebaseFirestoreGRPCCoreBinary_Privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/FirebaseFirestoreInternalBinary/FirebaseFirestoreInternalBinary_Privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/Google-Mobile-Ads-SDK/GoogleMobileAdsResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUserMessagingPlatform/UserMessagingPlatformResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/firebase_messaging/firebase_messaging_Privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/google_mobile_ads/google_mobile_ads.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/google_sign_in_ios/google_sign_in_ios_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/mobile_scanner/mobile_scanner_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/permission_handler_apple/permission_handler_apple_privacy.bundle",
Expand All @@ -488,7 +491,10 @@
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseFirestoreGRPCCPPBinary_Privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseFirestoreGRPCCoreBinary_Privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseFirestoreInternalBinary_Privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleMobileAdsResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/UserMessagingPlatformResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/firebase_messaging_Privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/google_mobile_ads.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/google_sign_in_ios_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/mobile_scanner_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/permission_handler_apple_privacy.bundle",
Expand Down
2 changes: 2 additions & 0 deletions app/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,7 @@
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-7730914075870960~4953718516</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,33 @@ class EnterActivationCodeBloc extends BlocBase {
return;
}

// Required for testing as long we run the A/B test.
//
// In case you are in A/B test group, you can't deactivate the ads by
// entering 'ads' in the activation code field.
if (_lastEnteredValue?.trim().toLowerCase() == 'ads') {
_toggleAds();
return;
}

_changeEnterActivationCodeResult(LoadingEnterActivationCodeResult());

final enterActivationCodeResult = await _runAppFunction(enteredValue);
_changeEnterActivationCodeResult(enterActivationCodeResult);
}

void _toggleAds() {
final currentValue = keyValueStore.getBool('show-ads') ?? false;
keyValueStore.setBool('show-ads', !currentValue);

_changeEnterActivationCodeResult(
SuccessfulEnterActivationCodeResult(
'ads',
'Ads wurden ${!currentValue ? 'aktiviert' : 'deaktiviert'}. Starte die App neu, um die Änderungen zu sehen.',
),
);
}

Future<void> _clearCache(BuildContext context) async {
await Future.wait([
keyValueStore.clear(),
Expand Down
85 changes: 85 additions & 0 deletions app/lib/ads/ad_banner.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) 2024 Sharezone UG (haftungsbeschränkt)
// Licensed under the EUPL-1.2-or-later.
//
// You may obtain a copy of the Licence at:
// https://joinup.ec.europa.eu/software/page/eupl
//
// SPDX-License-Identifier: EUPL-1.2

import 'package:flutter/widgets.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:provider/provider.dart';
import 'package:sharezone/ads/ads_controller.dart';

class AdBanner extends StatefulWidget {
const AdBanner({
super.key,
required this.adUnitId,
});

final String adUnitId;

@override
State<AdBanner> createState() => _AdBannerState();
}

class _AdBannerState extends State<AdBanner> {
BannerAd? ad;
bool _isLoaded = false;

@override
void initState() {
super.initState();
if (context.read<AdsController>().isQualifiedForAds()) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
final size =
await AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(
MediaQuery.sizeOf(context).width.truncate());

if (size == null) {
// Unable to get width of anchored banner.
return;
}

if (!mounted) {
return;
}

ad = BannerAd(
adUnitId: widget.adUnitId,
request: context.read<AdsController>().createAdRequest(),
size: size,
listener: BannerAdListener(
onAdLoaded: (ad) {
debugPrint('$ad loaded.');
setState(() {
_isLoaded = true;
});
},
onAdFailedToLoad: (ad, err) {
debugPrint('BannerAd failed to load: $err');
ad.dispose();
},
),
)..load();
});
}
}

@override
void dispose() {
ad?.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final areAdsVisible = context.watch<AdsController>().areAdsVisible;
if (!areAdsVisible || _isLoaded == false) return Container();
return SizedBox(
height: ad!.size.height.toDouble(),
width: ad!.size.width.toDouble(),
child: AdWidget(ad: ad!),
);
}
}
56 changes: 56 additions & 0 deletions app/lib/ads/ad_info_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) 2024 Sharezone UG (haftungsbeschränkt)
// Licensed under the EUPL-1.2-or-later.
//
// You may obtain a copy of the Licence at:
// https://joinup.ec.europa.eu/software/page/eupl
//
// SPDX-License-Identifier: EUPL-1.2

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:sharezone/sharezone_plus/page/sharezone_plus_page.dart';
import 'package:sharezone_widgets/sharezone_widgets.dart';

void showAdInfoDialog(BuildContext context) async {
final navigateToPlusPage = await showDialog<bool>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Werbung in Sharezone'),
content: Text.rich(
TextSpan(
children: [
const TextSpan(
text:
'Innerhalb der nächsten Wochen führen wir ein Experiment mit Werbung in Sharezone durch. Wenn du keine Werbung sehen möchten, kannst du ',
),
TextSpan(
text: 'Sharezone Plus',
style: const TextStyle(
color: primaryColor,
decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap = () => Navigator.of(context).pop(true),
),
const TextSpan(
text: ' erwerben.',
),
],
),
),
actions: <Widget>[
ElevatedButton(
style: ElevatedButton.styleFrom(foregroundColor: Colors.white),
child: const Text('OK'),
onPressed: () => Navigator.of(context).pop(),
),
],
);
},
);

if (navigateToPlusPage == true && context.mounted) {
navigateToSharezonePlusPage(context);
}
}
Loading
Loading