I am wondering how I can make the form show in my iOS App https://developers.google.com/admob/ump/ios/quick-start.
I am using Xcode vs 11.6 and exported the game from Godot game engine.
I have changed the GADApplicationIdentifier in my info.plist and I don't get any errors in my code it just doesn't show the form when I run the game. I live in Europe. Any help is appreciated.
This is my current code:
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#import "ViewController1.h"
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#interface ViewController1 ()
#end
#implementation ViewController1
- (void)start {
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
} else {
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
[self loadForm];
}
}
}];
}
- (void)viewDidLoad {
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
} else {
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
[self loadForm];
}
}
}];
[super viewDidLoad];
}
- (void)loadForm {
[UMPConsentForm loadWithCompletionHandler:^(UMPConsentForm *form,
NSError *loadError) {
if (loadError) {
// Handle the error.
} else {
// Present the form. You can also hold on to the reference to present
// later.
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusRequired) {
[form
presentFromViewController:self
completionHandler:^(NSError *_Nullable dismissError) {
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusObtained) {
// App can start requesting ads.
}
}];
} else {
// Keep the form available for changes to user consent.
}
}
}];
}
#end
EDIT
Add a few NSLog to see what gets called.
try the following - just a stone into the bush, maybe it hits something ...
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#import "ViewController1.h"
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#interface ViewController1 ()
#end
#implementation ViewController1
- (void)start {
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
} else {
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
[self loadForm];
}
}
}];
}
// Change this one
- (void)viewDidLoad {
[super viewDidLoad];
}
// Add this one
- ( void ) viewDidAppear:( BOOL ) animated {
[super viewDidAppear:animated];
// View controller is now visible and on screen, so request permission
self.addMobStuff;
}
// Change / add this one
- ( void ) addMobStuff {
NSLog( #"addMobStuff" );
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
if ( ! UMPConsentInformation.sharedInstance )
{
NSLog(#"No shared instance");
}
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
NSLog(#"Some error %#", error);
} else {
NSLog(#"Proceed to form ...");
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
NSLog(#"Loading form ...");
[self loadForm];
}
else {
NSLog(#"Form status is not available");
}
}
}];
}
- (void)loadForm {
[UMPConsentForm loadWithCompletionHandler:^(UMPConsentForm *form,
NSError *loadError) {
if (loadError) {
// Handle the error.
NSLog(#"Form error %#", error);
} else {
// Present the form. You can also hold on to the reference to present
// later.
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusRequired) {
NSLog(#"Presenting form");
[form
presentFromViewController:self
completionHandler:^(NSError *_Nullable dismissError) {
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusObtained) {
// App can start requesting ads.
}
}];
} else {
// Keep the form available for changes to user consent.
NSLog(#"Changes");
}
}
}];
}
#end
note if this works it probably needs a bit more polish before it can be released into the world but hopefully at least the request form will be displayed ...
Related
I am trying to integrate Hyperpay payment into React Native project and I have problems with objective-c, I followed an article and found many issues and with searching, I solve them, but still two issues I can't solve because I am not familiar with objective-c
Issue 1,
No known class method for selector 'presentCheckoutForSubmittingTransactionCompletionHandler:cancelHandler:'
Issue 2,
No known class method for selector 'dismissCheckoutAnimated:completion:'
I am sorry if my code is long but I don't to miss something
// RCTCalendarModule.m
#import "HyperPay.h"
#import "UIKit/UIKit.h"
#import <OPPWAMobile/OPPWAMobile.h>
#implementation HyperPay{
RCTResponseSenderBlock onDoneClick;
RCTResponseSenderBlock onCancelClick;
UIViewController *rootViewController;
NSString *isRedirect;
OPPPaymentProvider *provider;
}
// To export a module named RCTCalendarModule
RCT_EXPORT_METHOD(openHyperPay:(NSDictionary *)indic createDialog:(RCTResponseSenderBlock)doneCallback createDialog:(RCTResponseSenderBlock)cancelCallback) {
onDoneClick = doneCallback;
onCancelClick = cancelCallback;
NSArray *events = #[];
if ([indic[#"is_sandbox"] isEqualToString:#"1"]) {
provider = [OPPPaymentProvider paymentProviderWithMode:OPPProviderModeTest];
} else {
provider = [OPPPaymentProvider paymentProviderWithMode:OPPProviderModeLive];
}
OPPCheckoutSettings *checkoutSettings = [[OPPCheckoutSettings alloc] init];
// Set available payment brands for your shop
checkoutSettings.paymentBrands = #[#"VISA", #"MASTER"];
// Set shopper result URL
checkoutSettings.shopperResultURL = #"com.simicart.enterprise.payments://result";
OPPCheckoutProvider *checkoutProvider = [OPPCheckoutProvider checkoutProviderWithPaymentProvider:provider checkoutID:indic[#"checkoutId"]
settings:checkoutSettings];
dispatch_async(dispatch_get_main_queue(), ^{
[OPPCheckoutProvider presentCheckoutForSubmittingTransactionCompletionHandler:^(OPPTransaction * _Nullable transaction, NSError * _Nullable error) {
if (error) {
// Executed in case of failure of the transaction for any reason
if (isRedirect && ![isRedirect isEqualToString:#"1"]) {
onCancelClick(#[#"cancel", events]);
}
} else if (transaction.type == OPPTransactionTypeSynchronous) {
// Send request to your server to obtain the status of the synchronous transaction
// You can use transaction.resourcePath or just checkout id to do it
NSDictionary *responeDic = #{#"resourcePath" : transaction.resourcePath};
onDoneClick(#[responeDic, events]);
NSLog(#"%#", transaction.resourcePath);
} else {
// The SDK opens transaction.redirectUrl in a browser
// See 'Asynchronous Payments' guide for more details
}
} cancelHandler:^{
onCancelClick(#[#"cancel", events]);
// Executed if the shopper closes the payment page prematurely
}];
});
}
- (instancetype)init{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(getStatusOder:) name:#"getStatusOrder" object:nil];
}
return self;
}
- (void)getStatusOder:(NSNotification*)noti{
[OPPCheckoutProvider dismissCheckoutAnimated:YES completion:^{
isRedirect = #"1";
NSURL *url = noti.object;
NSString *urlString = [url absoluteString];
NSLog(#"%#", urlString);
if (![urlString isEqualToString:#"com.simicart.enterprise.payments://result"]) {
NSArray *events = #[];
NSDictionary *responeDic = #{#"url" : urlString};
onDoneClick(#[responeDic, events]);
}
}];
}
#end
I am trying to bring obj-c code to swift (facebook ios sdk), but autocomplete(intellisense) does not work in handler and I get an error (marked in code) : Set NSObject does not have a member named 'containsObject'
#IBAction func loginWithFacebook(sender: AnyObject) {
/*
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login logInWithReadPermissions:#[#"email"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
// Process error
} else if (result.isCancelled) {
// Handle cancellations
} else {
// If you ask for multiple permissions at once, you
// should check if specific permissions missing
if ([result.grantedPermissions containsObject:#"email"]) {
// Do work
}
}
}];
*/
let fbLoginManager = FBSDKLoginManager()
fbLoginManager.logInWithReadPermissions(["email"], handler: {
result, error in
if ((error) != nil){
}
else if (result.isCancelled){
} else {
if(result.grantedPermissions.containsObject("email")){ //<-- error here
}
}
})
}
Because Swift 1.2 automatically casts all NSSet objects (the ones that coming from external libs/sdks/frameworks etc...) to Set structure you need to call contains instead of containsObject for such things (doc).
I'm implementing v4.1 of the SDK for iOS and when I try to call for publishPermissions:, I get no callback.
For some reason everything works perfectly when I run logInWithReadPermissions:, but when I run logInWithPublishPermissions: it never hits my response handler. Nothing happens.
To test things out, I reset my loginManager before running logInWithPublishPermissions:, and to my surprise it worked then (aka NSLog(#"RESULT") is called).
Am I missing something about how the loginManager works? Shouldn't I be able to use it without resetting it?
// FacebookController.m
#implementation FacebookController
FBSDKLoginManager *loginManager;
static FacebookController *_shared = nil;
- (id)init {
self = [super init];
if (self != nil) {
userData = [[NSMutableDictionary alloc] init];
loginManager = [[FBSDKLoginManager alloc] init];
}
return self;
}
+ (id)getInstance {
if (!_shared) {
_shared = [[self alloc] init];
}
return _shared;
}
- (bool)hasPublishPermissions {
FBSDKAccessToken *accessToken = [FBSDKAccessToken currentAccessToken];
if(accessToken != NULL){
NSSet *permissions = [accessToken permissions];
if([permissions containsObject:#"publish_actions"]){
return TRUE;
}
}
return FALSE;
}
- (void)requestPublishPermissionsWithDelegate:(id)aDelegate {
if(![self hasPublishPermissions]){
// FOR SOME REASON IT WORKS IF I RESET LOGIN MANAGER AS FOLLOWS
// loginManager = [[FBSDKLoginManager alloc] init];
[loginManager logInWithPublishPermissions:#[#"publish_actions"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
NSLog(#"RESULT: %#", result);
}];
}
}
- (void)connectToFacebookWithDelegate:(id)aDelegate {
FBSDKAccessToken *accessToken = [FBSDKAccessToken currentAccessToken];
if(accessToken != nil){
[aDelegate performSelector:#selector(facebookSignedIn)];
} else {
[loginManager logInWithReadPermissions:#[#"email"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
// Process error
NSLog(#"ERROR");
} else if (result.isCancelled) {
// Handle cancellations
NSLog(#"CANCELLED");
} else {
NSLog(#"SUCCESS");
[aDelegate performSelector:#selector(facebookSignedIn)];
}
}];
}
}
#end
Edit #1:
Including videos of it working and not working for the given scenarios:
Not working (loginManager reinitialization commented out):
https://dl.dropboxusercontent.com/u/14277258/not-working.mov
Working (loginManager reinitialized):
https://dl.dropboxusercontent.com/u/14277258/working.mov
Your video stack trace indicates you're calling the request for publish permissions inside the handler for your initial login. This should be avoided:
You're causing another login after the user has already granted you some permissions - it's not very good for the user to have to see another login dialog immediately after completing one.
You're asking for publish permissions when you don't need it - this may violate Facebook developer policies and again is not the best user experience. Instead you should asking for publish only when you need it (i.e., at the time of sharing).
If you really insist, you can dispatch your second login call asynchronously so that the first request finishes entirely but I wouldn't recommend it. We can probably update the SDK to detect this and log though so it's not as confusing.
I have been playing with icloud in the ios 8 beta, and the CloudKitAtlasAnIntroductiontoCloudKit sample project has been very helpful.
https://developer.apple.com/library/prerelease/ios/samplecode/CloudAtlas/Introduction/Intro.html
But I wanted to use the CKDiscoverAllContactsOperation class and I cannot find any sample code for it anywhere at all and the online documentation is not very helpful.
https://developer.apple.com/library/prerelease/ios/documentation/CloudKit/Reference/CKDiscoverAllContactsOperation_class/index.html
If anyone has managed to successfully use CKDiscoverAllContactsOperation could you please help point me in the right direction or show a working example of how it should be called?
I have tried this to see if I could even get an response from iCloud but nothing:
- (void)queryForRecordsOtherUsersInAddressBookcompletionHandler:(void (^)(NSArray *records))completionHandler {
CKDiscoverAllContactsOperation *discoverAllContactsOperation= [[CKDiscoverAllContactsOperation alloc] init];
[discoverAllContactsOperation setContainer:_container];
NSMutableArray *results = [[NSMutableArray alloc] init];
discoverAllContactsOperation.discoverAllContactsCompletionBlock = ^(NSArray *userInfos, NSError *operationError) {
[results addObjectsFromArray:userInfos];
};
discoverAllContactsOperation.discoverAllContactsCompletionBlock=^(NSArray *userInfos, NSError *operationError){
if (operationError) {
// In your app, handle this error with such perfection that your users will never realize an error occurred.
NSLog(#"An error occured in %#: %#", NSStringFromSelector(_cmd), operationError);
abort();
} else {
dispatch_async(dispatch_get_main_queue(), ^(void){
completionHandler(results);
});
}
};
}
and calling with this...
[self.cloudManager queryForRecordsOtherUsersInAddressBookcompletionHandler:^(NSArray *records ) {
if (records.count==0){
NSLog(#"Login name not found");
return;
}
//self.results= records;
//_loggedInRecord = self.results[0];
//NSLog(#"%#,%#",_loggedInRecord[#"lastName"],_loggedInRecord[#"firstName"]);
// [self performSegueWithIdentifier:#"loggedInSegue" sender:self ];
}];
I know the code shouldn't really do anything. Again I was just looking for a response from iCloud.
Here is what I am using. self.container is a CKContainer set with [CKContainer defaultContainer] in the init.
-(void)queryForAllUsers: (void (^)(NSArray *records))completionHandler {
CKDiscoverAllContactsOperation *op = [[CKDiscoverAllContactsOperation alloc] init];
[op setUsesBackgroundSession:YES];
op.queuePriority = NSOperationQueuePriorityNormal;
[op setDiscoverAllContactsCompletionBlock:^(NSArray *userInfos, NSError *error) {
if (error) {
NSLog(#"An error occured in %#: %#", NSStringFromSelector(_cmd), error);
//abort();
} else {
// NSLog(#"Number of records in userInfos is: %ld", (unsigned long)[userInfos count]);
dispatch_async(dispatch_get_main_queue(), ^(void){
completionHandler(userInfos);
});
}
}];
[self.container addOperation:op];
}
Before you can use the CKDiscoverAllContactsOperation operation, you first need to request for permission.
Pls use the method requestApplicationPermission:completion:
func discoverAllContacts() {
let container = CKContainer.defaultContainer()
//Request for user permission
container.requestApplicationPermission([.UserDiscoverability]) { [weak self] status, error in
switch status {
case .Granted where error == nil:
let operation = self?.discoverAllContactsOperation { usersInfo in
//do something here
}
if let operationExists = operation {
//Assuming there is a NSOperationQueue property called operationQueue
self?.operationQueue.addOperation(operationExists)
}
default:
break
}
}
}
func discoverAllContactsOperation(completionHandler: ([CKDiscoveredUserInfo]?) -> ()) -> NSOperation {
let operation = CKDiscoverAllContactsOperation()
operation.discoverAllContactsCompletionBlock = { usersInfo, error in
if error == nil {
print("Discoverd all contacts = \(usersInfo)")
completionHandler(usersInfo)
}
else {
print("Discoverd all contacts error = \(error)")
completionHandler(nil)
}
}
return operation
}
I use SkyDrive on my iOS app, everything works fine until I close my app and when I open it again I have to authenticate user again. I use this code:
- (id)init
{
self = [super init];
if (self) {
self.clientID = #"my id";
self.scopes = #[#"wl.signin", #"wl.skydrive", #"wl.skydrive_update"];
self.liveClient = [[LiveConnectClient alloc] initWithClientId:self.clientID
scopes:self.scopes
delegate:self
userState:#"initialize"];
}
return self;
}
This is for sign in user first time, when I click on the button:
- (void)signInFromViewController:(UIViewController *)viewController
{
if (_liveClient) {
if (self.liveClient.session == nil) {
[self.liveClient login:viewController
scopes:self.scopes
delegate:self
userState:#"signin"];
}
}
}
And LiveAuthDelegate method;
- (void)authCompleted:(LiveConnectSessionStatus)status
session:(LiveConnectSession *)session
userState:(id)userState
{
if ([userState isEqual:#"signin"]) {
if (session != nil) {
NSLog(#"Signed in");
} else {
NSLog(#"Auth error");
}
}
}
What should I do else? Maybe something in authCompleted method when userState is initialize?
I had almost exactly the same issue. The solution was to add the "wl.offline_access" scope to my initial login call.
Source code and other details can be found in the question I posted, which is here:
iOS OneDrive (skydrive) app displays permissions dialog every time it runs
Hope this helps!
Diz