Skip to content

Instantly share code, notes, and snippets.

@all12jus
Last active October 8, 2022 09:16
Show Gist options
  • Save all12jus/04852946a98154eebb748e219f53766b to your computer and use it in GitHub Desktop.
Save all12jus/04852946a98154eebb748e219f53766b to your computer and use it in GitHub Desktop.
//
// 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