When entering the application, no ads is displayed - ios

I'm trying to display an ad with GADAppOpenAd
The problem is, every initial login to the application, no advertisement is displayed, only when I go to the background and return to the application, then an advertisement appears,
I'm trying to have an advertisement appear on the initial login as well
var appOpenAd: GADAppOpenAd?
var loadTime = Date()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GADMobileAds.sharedInstance().start(completionHandler: nil)
requestAppOpenAd()
return true
}
extension AppDelegate:GADFullScreenContentDelegate {
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
requestAppOpenAd()
}
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
requestAppOpenAd()
}
func requestAppOpenAd() {
let request = GADRequest()
GADAppOpenAd.load(withAdUnitID: "ca-app-pub-3940256099942544/5662855259",
request: request,
orientation: UIInterfaceOrientation.portrait,
completionHandler: { (appOpenAdIn, _) in
self.appOpenAd = appOpenAdIn
self.appOpenAd?.fullScreenContentDelegate = self
self.loadTime = Date()
print("Ad is ready")
})
}
func tryToPresentAd() {
guard let rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else {
return
}
if let gOpenAd = self.appOpenAd, wasLoadTimeLessThanNHoursAgo(thresholdN: 4){
gOpenAd.present(fromRootViewController: rootViewController)
} else {
self.requestAppOpenAd()
}
}
func wasLoadTimeLessThanNHoursAgo(thresholdN: Int) -> Bool {
let now = Date()
let timeIntervalBetweenNowAndLoadTime = now.timeIntervalSince(self.loadTime)
let secondsPerHour = 3600.0
let intervalInHours = timeIntervalBetweenNowAndLoadTime / secondsPerHour
return intervalInHours < Double(thresholdN)
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func sceneDidBecomeActive(_ scene: UIScene) {
(UIApplication.shared.delegate as? AppDelegate)?.tryToPresentAd()
}
}

Related

BGAppRefreshTask never called

BGAppRefreshTask is not working, I marked the option of background fetch capability
The method inside BGTaskScheduler.shared.register is never called
my code:
private let appRefreshTaskId = "internetDisconnectionsId"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13, *) {
BGTaskScheduler.shared.register(forTaskWithIdentifier: appRefreshTaskId, using: nil) { task in
self.handleAppRefreshTask(task: task as! BGAppRefreshTask)
}
}
return true
}
func handleAppRefreshTask(task: BGAppRefreshTask) {
task.expirationHandler = {
print("Background Working")
task.setTaskCompleted(success: true)
}
}
#available(iOS 13.0, *)
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: appRefreshTaskId)
request.earliestBeginDate = Date(timeIntervalSinceNow: 2 * 60) // Refresh after 2 minutes.
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh task \(error.localizedDescription)")
}
}
func sceneDidEnterBackground(_ scene: UIScene) {
(UIApplication.shared.delegate as! AppDelegate).scheduleAppRefresh()
print("called")
}
I would love to understand where I am wrong

Flutter NFC iOS Mifare UID reading

Guys, I need your help, please.
What do I need: to get the tag's UID using iOS app
What do I have: I have an app Flutter, which works fine on Android (I can read the tag's UID) and do nothing on iOS
Details:
I have this type of cards (plastic card)
card's data, Mifare Classis 1k
As you can see, this is the Mifare Classic 1k card with payload "My text with spaces"
I used flutter channels to communicate between flutter and iOS native (swift)
On iOS side I created two implementations: one for NFCTagReaderSession, another one for NFCNDEFReaderSession (I do not use it at the same time, only separated)
1. NFCTagReaderSession implementation
import UIKit
import Flutter
import CoreNFC
#available(iOS 13.0, *)
var session_tag: NFCTagReaderSession?
#available(iOS 13.0, *)
var flutterResult: FlutterResult!
#available(iOS 13.0, *)
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate, NFCTagReaderSessionDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let nfcChannel = FlutterMethodChannel(name: "samples.flutter.dev/nfc", binaryMessenger: controller.binaryMessenger)
nfcChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: #escaping FlutterResult) -> Void in
// Note: this method is invoked on the UI thread.
guard call.method == "getNFCTag" else {
result(FlutterMethodNotImplemented)
return
}
if NFCTagReaderSession.readingAvailable {
print("we are ready for reading");
self?.startReadingNFC(result: result)
} else {
print("sorry byt not working");
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func startReadingNFC(result: #escaping FlutterResult) {
flutterResult = result
session_tag = NFCTagReaderSession(pollingOption: .iso14443, delegate: self, queue: DispatchQueue.main)
session_tag?.alertMessage = "Hold ur phone!"
session_tag?.begin()
}
func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
print("Tag session active")
}
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
print("Did detect tag reader session")
print(tags.count)
if case let NFCTag.miFare(tag) = tags.first! {
session.connect(to: tags.first!) { (error: Error?) in
let tagUIDData = tag.identifier
var byteData: [UInt8] = []
tagUIDData.withUnsafeBytes { byteData.append(contentsOf: $0) }
session.invalidate()
print(self.hexEncodedString(byteArray: byteData))
// DispatchQueue.main.async {
//flutterResult(self.hexEncodedString(byteArray: byteData))
// }
}
}
}
func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
print("Tag Error: \(error.localizedDescription)")
}
func hexEncodedString(byteArray: [UInt8]) -> String {
let hexDigits = Array("0123456789abcdef".utf16)
var hexChars = [UTF16.CodeUnit]()
hexChars.reserveCapacity(byteArray.count * 2)
for byte in byteArray {
let (index1, index2) = Int(byte).quotientAndRemainder(dividingBy: 16)
hexChars.append(hexDigits[index1])
hexChars.append(hexDigits[index2])
}
return String(utf16CodeUnits: hexChars, count: hexChars.count)
}
}
When i'm pressing the button in my app, i can see the NFC reading window on my phone
iOS app NFC reading window
But, when i put the card up to a phone, there is noting happened. Android Studio console
Android studio console
2. NFCNDEFReaderSession
import UIKit
import Flutter
import CoreNFC
#available(iOS 13.0, *)
var session_tag: NFCNDEFReaderSession?
#available(iOS 13.0, *)
var flutterResult: FlutterResult!
#available(iOS 13.0, *)
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate, NFCNDEFReaderSessionDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let nfcChannel = FlutterMethodChannel(name: "samples.flutter.dev/nfc", binaryMessenger: controller.binaryMessenger)
nfcChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: #escaping FlutterResult) -> Void in
// Note: this method is invoked on the UI thread.
guard call.method == "getNFCTag" else {
result(FlutterMethodNotImplemented)
return
}
if NFCNDEFReaderSession.readingAvailable {
print("we are ready for reading");
self?.startReadingNFC(result: result)
} else {
print("sorry byt not working");
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
func startReadingNFC(result: #escaping FlutterResult) {
print("start reading session")
flutterResult = result
// session_tag = NFCNDEFReaderSession(pollingOption: [.iso14443], delegate: self, queue: DispatchQueue.main)
session_tag = NFCNDEFReaderSession(delegate: self, queue: DispatchQueue.main, invalidateAfterFirstRead: false)
session_tag?.alertMessage = NSLocalizedString("Hold it!", comment: "my comment")
session_tag?.begin()
}
func tagReaderSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
print("Tag session active")
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
print(messages)
for message in messages {
for record in message.records {
print("next message")
print(record)
}
}
}
func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) {
if (tags.count > 0) {
session.connect(to: tags.first!, completionHandler: { (connection_error) in
tags.first?.readNDEF(completionHandler: { (message, error) in
if ((message?.records.count)! > 0) {
if let dataMessage = String(data: (message?.records.first!.payload)!, encoding:.utf8) {
session.invalidate()
print(dataMessage)
}
}
})
})
}
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
print("Tag Error: \(error.localizedDescription)")
}
func tagReaderSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
print("Tag Error: \(error.localizedDescription)")
// DispatchQueue.main.async {
// session.invalidate()
// print(error.localizedDescription)
// flutterResult(error.localizedDescription)
// }
}
}
After pressing the button in the app, NFC reading window also shows up. And with the card i can get the payload
Message: My message with spaces
Both approaches start fine and open the iOS's window with "read a tag", but with NFCTagReaderSession nothing is happening. It seems like there is no card. With NFCNDEFReaderSession implementation, I can read the message "My text with spaces" but, of course, I can't read the tag's UID
Am'I doing something wrong to get the UID of the card?

how to implement protocol delegate pattern in App Delegate when using Platform Specific code in Flutter?

I want to implement platform specific code for my Flutter app on iOS. I want to implement EventKit from native iOS. but now I am confused how to implement protocol delegate pattern in the app delegate when using Platform Channel in Flutter.
in native iOS, my code will be like this
import EventKitUI
class MyViewController : UIViewController, EKEventEditViewDelegate, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonPressed(_ sender: Any) {
// after pressing a button then show a VC
showEventKitViewController()
}
func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
// this is the method to conform the protocol
dismiss(animated: true, completion: nil)
}
func showEventKitViewController() {
let eventVC = EKEventEditViewController()
eventVC.editViewDelegate = self // I am confused in this line
eventVC.eventStore = EKEventStore()
let event = EKEvent(eventStore: eventVC.eventStore)
eventVC.event = event
present(eventVC, animated: true)
}
}
as you can see, I assign self ( MyViewController class as the delegate ) for editViewDelegate
now I am confused how to implement showEventKitViewController method above in Flutter app delegate below
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "useOtherApp", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler({ (call: FlutterMethodCall, result: FlutterResult) -> Void in
if (call.method == "saveToEventKit") {
// what should I do in here to get the same result like my code above in native?
}
})
}
especially when I need to assign a class as the delegate for editViewDelegate like this
I can solve it by using the code like this by using extension. please scroll to the very bottom to see FlutterViewController extension
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
setUpMethodChannels(controller: controller) // set the method channel
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func setUpMethodChannels(controller: FlutterViewController) {
let channel = FlutterMethodChannel(name: "useOtherApp", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler({ (call: FlutterMethodCall, result: FlutterResult) -> Void in
guard let args = call.arguments as? [String : Any] else {return}
if (call.method == "saveToCalendar") {
let eventVC = EKEventEditViewController()
eventVC.editViewDelegate = controller // set FlutterViewController as the delegate
eventVC.eventStore = EKEventStore()
let event = EKEvent(eventStore: eventVC.eventStore)
eventVC.event = event
eventVC.title = "hallooooo"
controller.present(eventVC, animated: true)
} else {
result(FlutterMethodNotImplemented)
}
})
}
}
// set the extension like below OUTSIDE the AppDelegate class
extension FlutterViewController : EKEventEditViewDelegate, UINavigationControllerDelegate {
// conform to the EKEventEditViewDelegate protocol
public func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
dismiss(animated: true, completion: nil)
}
}

BackgroundTask iOS 13 Swift

I want to run the function in the background. But I get an error. The error I received is
"nw_connection_receive_internal_block_invoke.
Why am I getting this problem? I'm trying it on an iOS 13 device. But I can't run the application in the background. I added a background run feature in Info.plist. I want to run the interator.tickTimer function in the background. But I'm getting an error. Does not work in the background. In the background, I want to periodically retrieve data from firebase.
import BackgroundTasks
#available(iOS 13.0, *)
extension AppDelegate {
func cancelAllPandingBGTask() {
BGTaskScheduler.shared.cancelAllTaskRequests()
}
func scheduleImageFetcher() {
let request = BGProcessingTaskRequest(identifier: "....")
request.requiresNetworkConnectivity = true // Need to true if your task need to network process. Defaults to false.
request.requiresExternalPower = false
request.earliestBeginDate = Date(timeIntervalSinceNow: 40)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule image featch: \(error)")
}
}
func handleAppRefreshTask(task: BGAppRefreshTask) {
task.expirationHandler = {
}
DispatchQueue.main.async {
let interator = MainTableViewController()
interator.tickTimer()
}
task.setTaskCompleted(success: true)
}
func handleImageFetcherTask(task: BGProcessingTask) {
scheduleImageFetcher() // Recall
//Todo Work
task.expirationHandler = {
}
task.setTaskCompleted(success: true)
}
}
xtension AppDelegate {
func registerLocalNotification() {
let notificationCenter = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
notificationCenter.requestAuthorization(options: options) {
(didAllow, error) in
if !didAllow {
// print("User has declined notifications")
}
}
}
func scheduleLocalNotification() {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.getNotificationSettings { (settings) in
if settings.authorizationStatus == .authorized {
self.fireNotification()
}
}
}
func fireNotification() {
// Create Notification Content
let notificationContent = UNMutableNotificationContent()
// Configure Notification Content
notificationContent.title = "Bg"
notificationContent.body = "BG Notifications."
// Add Trigger
let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 1.0, repeats: false)
// Create Notification Request
let notificationRequest = UNNotificationRequest(identifier: "local_notification", content: notificationContent, trigger: notificationTrigger)
// Add Request to User Notification Center
UNUserNotificationCenter.current().add(notificationRequest) { (error) in
if let error = error {
print("Unable to Add Notification Request (\(error), \(error.localizedDescription))")
}
}
}
}
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UITabBarControllerDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
registerBackgroundTaks()
registerLocalNotification()
} else {
// Fallback on earlier versions
}
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
if #available(iOS 13.0, *) {
cancelAllPandingBGTask()
scheduleImageFetcher()
} else {
// Fallback on earlier versions
}
}
//MARK: Regiater BackGround Tasks
#available(iOS 13.0, *)
private func registerBackgroundTaks() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "....-...", using: nil) { task in
//This task is cast with processing request (BGProcessingTask)
self.scheduleLocalNotification()
self.handleImageFetcherTask(task: task as! BGProcessingTask)
}
}

Why Firebase Remote Config doesn't update values?

I'm using Firebase Remote Config, I have some troubles to update values.
My values are updated only if I close and relaunch the app.
But never if my app enters in foreground.
The developer is activated, with no cache delay.
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
let _ = RCFirebaseValues.sharedInstance
}
}
My Firebase Remote Config class:
enum ValueKey: String {
case force_update
}
class RCFirebaseValues {
static let sharedInstance = RCFirebaseValues()
var loadingDoneCallback: (() -> ())?
var fetchComplete: Bool = false
private init() {
loadDefaultValues()
fetchCloudValues()
}
func loadDefaultValues() {
RemoteConfig.remoteConfig().setDefaults(fromPlist: "RemoteConfigDefaults")
}
func fetchCloudValues() {
#if DEBUG
let expirationDuration: TimeInterval = 0
RemoteConfig.remoteConfig().configSettings = RemoteConfigSettings(developerModeEnabled: true)
#else
let expirationDuration: TimeInterval = 3600
#endif
RemoteConfig.remoteConfig().fetch(withExpirationDuration: expirationDuration) {
[weak self] (status, error) in
guard error == nil else {
DLog(message:"Uh-oh. Got an error fetching remote values \(String(describing: error))")
return
}
RemoteConfig.remoteConfig().activateFetched()
self?.fetchComplete = true
self?.loadingDoneCallback?()
}
}
func bool(forKey key: ValueKey) -> Bool {
return RemoteConfig.remoteConfig()[key.rawValue].boolValue
}
func string(forKey key: ValueKey) -> String {
return RemoteConfig.remoteConfig()[key.rawValue].stringValue ?? ""
}
func double(forKey key: ValueKey) -> Double {
if let numberValue = RemoteConfig.remoteConfig()[key.rawValue].numberValue {
return numberValue.doubleValue
} else {
return 0.0
}
}
}
What's wrong?
EDIT after Mosbah's response:
class AppDelegate: UIResponder, UIApplicationDelegate {
var remoteConfig:RCFirebaseValues!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
self. remoteConfig = RCFirebaseValues.sharedInstance
}
}
Your RCFirebaseValues scope is wrong, it will be nil as soon as you are out of application: didFinishLaunchingWithOptions: so you should keep a strong reference to your object (create a var on AppDelegate).

Resources