Last active
October 8, 2022 09:16
-
-
Save all12jus/04852946a98154eebb748e219f53766b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AdView.swift | |
// pdfsRebooks | |
// | |
// Created by Justin Allen on 1/17/20. | |
// Copyright © 2020 Justin Allen. All rights reserved. | |
// | |
/* | |
Before building with this file you will want to do these following steps | |
Run 'pod init' | |
Add "pod 'Google-Mobile-Ads-SDK'" after "# Pods for {ProjectName}" | |
Run 'pod install' | |
Make these modifications in your AppDelegate.swift file. | |
Add 'import GoogleMobileAds' below other imports | |
Add 'self.initAdEngine()' to ALL 'func application(_ application: UIApplication, didFinishLaunchingWithOptions' functions. | |
Add these entries to your Info.plist: GADApplicationIdentifier, GADBannerIdentifier, GADRewardIdentifier | |
*/ | |
import Foundation | |
import UIKit | |
import GoogleMobileAds | |
extension Notification.Name { | |
static let didRemoveAds = Notification.Name("didRemoveAds") | |
} | |
extension UIResponder { | |
var viewController: UIViewController? { | |
if let vc = self as? UIViewController { | |
return vc | |
} | |
return next?.viewController | |
} | |
} | |
class AdverstisementView: UIViewController { | |
public static var RemoveAdsProductCode: String { | |
get { | |
if let dictionary = NSDictionary(contentsOfFile: Bundle.main.path(forResource: "Info", ofType: "plist")!) { | |
if let code = dictionary["RemoveAdsProductCode"] { | |
return "\(code)" | |
} else { | |
return "remove_ads_forever" | |
} | |
} else { | |
return "remove_ads_forever" | |
} | |
} | |
} | |
public static var AppID: String? | |
} | |
extension UIView: GADBannerViewDelegate, SKPaymentTransactionObserver, GADRewardedAdDelegate { | |
private static var _myComputedProperty = [String:Double]() | |
var hideAfterTime: Double { | |
get { | |
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) | |
return UIView._myComputedProperty[tmpAddress] ?? -1 | |
} | |
set(newValue) { | |
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) | |
UIView._myComputedProperty[tmpAddress] = newValue | |
} | |
} | |
private static var _myViewProperty = [String:GADBannerView]() | |
var adBannerView: GADBannerView? { | |
get { | |
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) | |
return UIView._myViewProperty[tmpAddress] ?? nil | |
} | |
set(newValue) { | |
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) | |
UIView._myViewProperty[tmpAddress] = newValue | |
} | |
} | |
private static var _vwProperty = [String:UIView]() | |
var adView: UIView? { | |
get { | |
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) | |
return UIView._vwProperty[tmpAddress] ?? nil | |
} | |
set(newValue) { | |
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) | |
UIView._vwProperty[tmpAddress] = newValue | |
} | |
} | |
private static var _rwProperty = [String:GADRewardedAd]() | |
var rewardedAd: GADRewardedAd? { | |
get { | |
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) | |
return UIView._rwProperty[tmpAddress] ?? nil | |
} | |
set(newValue) { | |
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) | |
UIView._rwProperty[tmpAddress] = newValue | |
} | |
} | |
func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) { | |
DispatchQueue.main.asyncAfter(deadline: .now() + seconds) { | |
completion() | |
} | |
} | |
func injectAds(duration: Double? = nil) { | |
getAppDetailsFromServer() | |
let calendar = Calendar.current | |
let date = calendar.date(byAdding: .hour, value: 0, to: Date())! | |
let dateFormatter = DateFormatter() | |
dateFormatter.locale = Locale(identifier: "en_US_POSIX") | |
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" | |
dateFormatter.timeZone = TimeZone(identifier: "UTC") | |
var adFreeUntilActive = false | |
if let until = UserDefaults.standard.string(forKey: "ad-free-until") { | |
let adFreeUntil = dateFormatter.date(from: until)! | |
print(adFreeUntil) | |
if date <= adFreeUntil { | |
adFreeUntilActive = true | |
} | |
} | |
if !UserDefaults.standard.bool(forKey: "ad-free") && !adFreeUntilActive { | |
loadRewardAd() | |
SKPaymentQueue.default().add(self) | |
let removeBTN = UIButton(type: .system) | |
removeBTN.setTitle("X", for: .normal) | |
removeBTN.addTarget(self, action: #selector(removeAdsBTNClicked), for: .touchDown) | |
removeBTN.alpha = 0 | |
let bannerView = GADBannerView(adSize: kGADAdSizeBanner) | |
addSubview(bannerView) | |
addSubview(removeBTN) | |
let _ = Utils.SetupContraints( | |
child: bannerView, parent: self, addToParent: false, | |
top: false, | |
leading: false, | |
trailing: false, | |
bottom: true, bottomConstant: 10, | |
centerX: true, centerXConstant: -10 | |
) | |
let _ = Utils.SetupContraints( | |
child: removeBTN, parent: self, addToParent: false, | |
top: false, | |
leading: true, leadingConstant: 2, leadingTarget: bannerView.trailingAnchor, | |
trailing: false, | |
bottom: false, | |
centerY: true, centerYConstant: 0, centerYTarget: bannerView.centerYAnchor | |
) | |
#if targetEnvironment(simulator) | |
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716" | |
#else | |
if let dictionary = NSDictionary(contentsOfFile: Bundle.main.path(forResource: "Info", ofType: "plist")!) { | |
if let adID = dictionary["GADBannerIdentifier"] { | |
bannerView.adUnitID = "\(adID)" | |
} else { | |
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716" | |
} | |
} else { | |
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716" | |
} | |
#endif | |
bannerView.rootViewController = viewController | |
bannerView.load(GADRequest()) | |
bannerView.delegate = self | |
if let time = duration { | |
if time > 0 { | |
hideAfterTime = time | |
} | |
} | |
print("Showing ads.") | |
adBannerView = bannerView | |
adView = removeBTN | |
} else { | |
print("AD Free. No ads to show.") | |
} | |
} | |
func removeAds() { | |
UIView.animate(withDuration: 1, animations: { | |
self.adBannerView?.alpha = 0 | |
self.adView?.alpha = 0 | |
}) { (b) in | |
self.adBannerView?.removeFromSuperview() | |
self.adBannerView = nil | |
self.adView?.removeFromSuperview() | |
self.adView = nil | |
} | |
NotificationCenter.default.post(name: .didRemoveAds, object: nil) | |
} | |
// MARK: Delegate Functions | |
public func adViewDidReceiveAd(_ bannerView: GADBannerView) { | |
bannerView.alpha = 0 | |
self.adView?.alpha = 0 | |
UIView.animate(withDuration: 1) { | |
bannerView.alpha = 1 | |
self.adView?.alpha = 1 | |
if self.hideAfterTime > -1 { | |
self.delayWithSeconds(self.hideAfterTime) { | |
UIView.animate(withDuration: 1, animations: { | |
bannerView.alpha = 0 | |
self.adView?.alpha = 0 | |
}) { (bo) in | |
bannerView.removeFromSuperview() | |
self.adView?.removeFromSuperview() | |
} | |
} | |
} | |
} | |
} | |
func purchaseRemoveAdsInAPP (){ | |
let product = AppDelegate.products[AdverstisementView.RemoveAdsProductCode] | |
if let pro = product { | |
if pro.productIdentifier == AdverstisementView.RemoveAdsProductCode { | |
if SKPaymentQueue.canMakePayments(){ | |
let request = SKMutablePayment(product: pro) | |
SKPaymentQueue.default().add(request) | |
} | |
} | |
} | |
} | |
func loadRewardAd(){ | |
#if targetEnvironment(simulator) | |
rewardedAd = GADRewardedAd(adUnitID: "ca-app-pub-3940256099942544/1712485313") | |
#else | |
if let dictionary = NSDictionary(contentsOfFile: Bundle.main.path(forResource: "Info", ofType: "plist")!) { | |
if let adID = dictionary["GADRewardIdentifier"] { | |
rewardedAd = GADRewardedAd(adUnitID: "\(adID)") | |
} else { | |
rewardedAd = GADRewardedAd(adUnitID: "ca-app-pub-3940256099942544/1712485313") | |
} | |
} else { | |
rewardedAd = GADRewardedAd(adUnitID: "ca-app-pub-3940256099942544/1712485313") | |
} | |
#endif | |
rewardedAd?.load(GADRequest()) { error in | |
if let error = error { | |
print("Loading failed: \(error)") | |
} else { | |
print("Loading Succeeded") | |
} | |
} | |
} | |
func rewardAd(){ | |
if rewardedAd?.isReady == true { | |
rewardedAd?.present(fromRootViewController: viewController!, delegate:self) | |
} | |
} | |
// Tells the delegate that the user earned a reward. | |
public func rewardedAd(_ rewardedAd: GADRewardedAd, userDidEarn reward: GADAdReward) { | |
print("Reward received with currency: \(reward.type), amount \(reward.amount).") | |
let calendar = Calendar.current | |
let date = calendar.date(byAdding: .hour, value: Int(truncating: reward.amount), to: Date()) | |
let dateFormatter = DateFormatter() | |
dateFormatter.locale = Locale(identifier: "en_US_POSIX") | |
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" | |
dateFormatter.timeZone = TimeZone(identifier: "UTC") | |
let str = dateFormatter.string(from: date!) | |
UserDefaults.standard.set(str, forKey: "ad-free-until") | |
} | |
// Tells the delegate that the rewarded ad was presented. | |
public func rewardedAdDidPresent(_ rewardedAd: GADRewardedAd) { | |
print("Rewarded ad presented.") | |
} | |
// Tells the delegate that the rewarded ad was dismissed. | |
public func rewardedAdDidDismiss(_ rewardedAd: GADRewardedAd) { | |
print("Rewarded ad dismissed.") | |
// loadRewardAd() | |
} | |
// Tells the delegate that the rewarded ad failed to present. | |
public func rewardedAd(_ rewardedAd: GADRewardedAd, didFailToPresentWithError error: Error) { | |
print("Rewarded ad failed to present.") | |
} | |
@objc public func removeAdsBTNClicked(){ | |
showRemoveAdsActions() | |
} | |
public func showRemoveAdsActions(){ | |
print("Removing Ads Coming soon.") | |
let optionMenu = UIAlertController(title: nil, message: "Remove Ads", preferredStyle: .actionSheet) | |
let iAPProductPrice = AppDelegate.products[AdverstisementView.RemoveAdsProductCode]?.localizedPrice | |
let purchaseIAPAction = UIAlertAction(title: "Remove Ads Forever \(iAPProductPrice!)", style: .default, handler: { | |
(action) in | |
print("Activated Remove Forever.") | |
self.purchaseRemoveAdsInAPP() | |
} ) | |
optionMenu.addAction(purchaseIAPAction) | |
// restorePurchases | |
let restorePurchasesAction = UIAlertAction(title: "Restore Purchases", style: .default, handler: { | |
(action) in | |
print("Restore Purchases") | |
#if DEBUG | |
let defaults = UserDefaults.standard | |
defaults.set(true, forKey: "ad-free") | |
self.removeAds() | |
#else | |
if SKPaymentQueue.canMakePayments() { | |
SKPaymentQueue.default().restoreCompletedTransactions() | |
} | |
#endif | |
}) | |
optionMenu.addAction(restorePurchasesAction) | |
// reward ads | |
if let ra = rewardedAd { | |
if let rw = ra.reward { | |
let val = rw.amount.doubleValue | |
if val > 0.0 { | |
let rewardAdAction = UIAlertAction(title:"Reward Ad \(rw.amount) Hours", style: .default, handler: { | |
(action) in | |
print("Reward ad") | |
self.rewardAd() | |
}) | |
optionMenu.addAction(rewardAdAction) | |
} | |
} | |
} | |
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) | |
optionMenu.addAction(cancelAction) | |
if let popoverController = optionMenu.popoverPresentationController { | |
popoverController.sourceView = self | |
// could have this actually be the button it comes from. | |
popoverController.sourceRect = CGRect(x: self.bounds.midX, y: self.bounds.midY, width: 0, height: 0) | |
popoverController.permittedArrowDirections = [] | |
} | |
viewController!.present(optionMenu, animated: true, completion: nil) | |
} | |
public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { | |
for transaction in transactions { | |
print(transaction) | |
// print(transaction.error) | |
// print(transaction.transactionState) | |
if transaction.transactionState == .purchased { | |
print("Transaction Successful") | |
// removeAds(transaction: transaction) | |
UserDefaults.standard.set(true, forKey: "ad-free") | |
self.removeAds() | |
SKStoreReviewController.requestReview() | |
} else if transaction.transactionState == .failed { | |
print("Transaction Failed") | |
SKPaymentQueue.default().finishTransaction(transaction as SKPaymentTransaction) | |
} else if transaction.transactionState == .restored { | |
print("restored") | |
// removeAds(transaction: transaction) | |
UserDefaults.standard.set(true, forKey: "ad-free") | |
self.removeAds() | |
} else if transaction.transactionState == .purchasing { | |
print("Purchasing") | |
} | |
} | |
} | |
public func adView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: GADRequestError) { | |
print(error) | |
bannerView.backgroundColor = .white | |
let adButton = UIButton(type: .system) | |
adButton.setTitle("Share This App", for: .normal) | |
adButton.tintColor = .black | |
adButton.titleLabel?.textAlignment = .center | |
adButton.addTarget(self, action: #selector(shareApp), for: .touchDown) | |
let _ = Utils.SetupContraints(child: adButton, parent: bannerView) | |
self.adView?.alpha = 1 | |
} | |
func getAppDetailsFromServer() { | |
var bundleIdentifier: String { | |
return Bundle.main.infoDictionary?["CFBundleIdentifier"] as! String | |
} | |
let baseURL: String = "https://itunes.apple.com/lookup?bundleId=\(bundleIdentifier)" | |
let encodedURL = baseURL.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) | |
// Creating URL Object | |
let url = URL(string:encodedURL!) | |
// Creating a Mutable Request | |
var request = URLRequest.init(url: url!) | |
//Setting HTTP values | |
request.httpMethod = "GET" | |
request.timeoutInterval = 120 | |
let configuration = URLSessionConfiguration.default | |
let session = URLSession(configuration: configuration) | |
let downloadTask = session.dataTask(with: request, completionHandler: { (data, response, error) -> Void in | |
//API Call over,getting Main queue | |
DispatchQueue.main.async(execute: { () -> Void in | |
if error == nil { | |
if data != nil { | |
do { | |
let resultDictionary:NSDictionary! = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary | |
if resultDictionary != nil && resultDictionary.count > 0 { | |
if (resultDictionary.object(forKey: "results") as! NSArray).count != 0 { | |
let AppName = "\(((resultDictionary.object(forKey: "results") as! NSArray).object(at: 0) as! NSDictionary).object(forKey: "trackCensoredName")!)" | |
let AppId = "\(((resultDictionary.object(forKey: "results") as! NSArray).object(at: 0) as! NSDictionary).object(forKey: "trackId")!)" | |
print("AppName : \(AppName) \nAppId: \(AppId)") | |
AdverstisementView.AppID = AppId | |
} | |
} else { | |
print("Unable to proceed your request,Please try again") | |
} | |
} catch { | |
print("Unable to proceed your request,Please try again") | |
} | |
} else { | |
print("Unable to proceed your request,Please try again") | |
} | |
} else { | |
print("Unable to proceed your request,Please try again") | |
} | |
}) | |
}) | |
downloadTask.resume() | |
} | |
@objc func shareApp(){ | |
// 1. | |
print(AdverstisementView.AppID) | |
guard let appID = AdverstisementView.AppID else { | |
return | |
} | |
guard let productURL = URL(string: "itms-apps://itunes.apple.com/app/" + appID) else { return } | |
let activityViewController = UIActivityViewController( | |
activityItems: [productURL], | |
applicationActivities: nil) | |
// 2. | |
viewController?.present(activityViewController, animated: true, completion: nil) | |
} | |
} | |
extension AppDelegate: SKProductsRequestDelegate { | |
static var products: [String:SKProduct] = [String: SKProduct]() | |
// MARK: IN-APP-PURCHASE | |
func LoadProducts(){ | |
let products: Set = [AdverstisementView.RemoveAdsProductCode] | |
let request = SKProductsRequest(productIdentifiers: products) | |
request.delegate = self | |
request.start() | |
} | |
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { | |
print(response) | |
for pro in response.products { | |
print(pro.productIdentifier) | |
AppDelegate.products[pro.productIdentifier] = pro | |
} | |
} | |
func initAdEngine(){ | |
self.LoadProducts() | |
GADMobileAds.sharedInstance().start(completionHandler: nil) | |
GADMobileAds.sharedInstance().disableSDKCrashReporting() | |
} | |
} | |
public extension SKProduct { | |
var localizedPrice: String { | |
let formatter = NumberFormatter() | |
formatter.numberStyle = .currency | |
formatter.locale = priceLocale | |
return formatter.string(from: price)! | |
} | |
convenience init(identifier: String, price: String, priceLocale: Locale) { | |
self.init() | |
self.setValue(identifier, forKey: "productIdentifier") | |
self.setValue(NSDecimalNumber(string: price), forKey: "price") | |
self.setValue(priceLocale, forKey: "priceLocale") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment