This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021.

The introduction

This paper takes docking open screen advertising as an example

Developers.adnet.qq.com/doc/ios/uni…

AD types access Introduction to the Applicable scenario Release notes
Opening the advertising SDK native rendering The open-screen advertisement takes App startup as the exposure time, and provides 5s perceptive advertisement display. Users can click on an AD to jump to a target page; Or click the “Skip” button in the upper right corner to jump to the home page of app content. The on-screen V+ advertisement is a video advertisement for 5s-30s. During the on-screen display of 5S, the user clicks “Enter the home page” in the upper right corner or after 5s exposure, the video will shrink to the small window in the lower right corner of the APP to continue playing. The APP is started There are two types: open screen and V+

IOS Connection Documents:

Developers.adnet.qq.com/doc/ios/gui…

Ios SDK package: Demo project

OC version: github.com/zhangkn/GDT… , more resources please pay attention to the official number: iOS skills

[d3g.qq.com/gdt/sdk/ios d3g.qq.com/gdt/sdk/ios…

)

IOS14 adaptation guide

Developers.adnet.qq.com/doc/ios/uni… You have used the iOS SDK 4.12.5 or later

This article focuses on pulling the latest SDK library, IDFA adaptation of iOS14 and Modal style adaptation of iOS13

I. SDK deployment

Developers.adnet.qq.com/doc/ios/gui…

1.1 Glossary

APPID: Media ID, which is the ID you obtained when you created media on Tencent Youku Developer Platform. This ID is the unique ID we can identify your application in the advertising network.

PlacementId: AD space ID, which is the ID of the AD space of the type (Banner, open screen, interstition, platform template, motivational video) that you create for your application on Tencent Uvp developer platform.

Data Transfer Objects (Dtos): raw Data returned by an interface

Permission to apply for

Access to some advertising styles requires permission, you can contact Tencent Youku operations to understand and apply for permission. You can only see the type of advertising space you have the corresponding permissions when you create a new advertising space on Tencent Uvista Developer platform. At present, there are special agents in charge of operations and business.

Note: For single media users, allow access to IDFA and positioning rights, targeted advertising; For users who are not allowed to obtain permission, the media can choose whether to provide IDFA and location data to Ucvi, and bear the loss of corresponding AD filling and eCPM unit price reduction.

If you are not registered with Activision, please register to join activision or apply to become an operator

Operators adnet.qq.com/register/be…

Registration: adnet.qq.com/register

1.2 Pull the latest SDK library

pod 'GDTMobSDK'
#-> Installing GDTMobSDK 4.1290. (was 4.1111.)

Copy the code

Those who qualify can go onto ➜ retail git:(develop) qualify pod update GDTMobSDK –verbose

1.3 Access Precautions

Currently, open screen ads are only displayed vertically on iPhone devices.

  1. For full-screen advertisements, the height of the display area must be consistent with that of the device. Developers can provide media logo through the following interface to display the advertisement along with the opening screen.

You are advised to use a transparent background color for the logo, which can be blank

 - (void)loadFullScreenAd;
 - (void)showFullScreenAdInWindow:(UIWindow *)window withLogoImage:(UIImage *)logoImage skipView:(UIView *)skipView;

Copy the code
  1. The height of the display area of an open-screen half-screen advertisement must be greater than 75% of the height of the device (the recommended value is greater than 80%), and the minimum height must be greater than 400dp. Open-screen advertisements are displayed only in portrait mode by default, and landscape mode generally does not meet the size requirements.

  2. Youliu.com open screen ads support preloading open screen ads, the call method is as follows:

    GDTSplashAd *preloadSplashAd = [[GDTSplashAd alloc] initWithPlacementId:YOUR_PLACEMENT_ID];
    [preloadSplashAd preloadSplashOrderWithPlacementId:YOUR_PLACEMENT_ID];

Copy the code
  1. Initialize the SDK, load the AD code recommended indidFinishLaunchingWithOptionsThe first line of the
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    [selfsetupGDTSDKConfig]; .return YES;
}
Copy the code
  1. Because the SDK static library file libgdtmobsdk. a>110M, the submission to git repository may fail due to the file size limitation, so it is recommended that you use. Gitignore to ignore the Pods directory. Other colleagues can be used after pulling the codepod install --verbose --no-repo-updateOnly newly added libraries are installed; updated libraries are ignored. Or update the specified library and ignore other librariesPod update library name --verbose --no-repo-update
# Pods/

Copy the code

1.4 Permission Adaptation

For single-media users, users who are allowed to obtain IDFA and positioning rights are allowed to launch targeted advertisements; For users who are not allowed to obtain permission, the media can choose whether to provide IDFA and location data to Ucvi, and bear the loss of corresponding AD filling and eCPM unit price reduction.

See the third chapter of this article for adaptation of IDFA

Switch of obtaining GPS information

On the premise of obtaining GPS permission, media can choose whether to obtain GPS information of users in advertisements, so as to obtain targeted advertisements. The method is as follows:

#import "GDTSDKConfig.h"

[GDTSDKConfig enableGPS:YES]; // Get the user's GPS information. The default value is NO

Copy the code

II. Access code examples

2.1 Import the header file in the AppDelegate header file and declare the instance

#import "GDTSplashAd.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate.GDTSplashAdDelegate>

@property (strong.nonatomic) UIWindow *window;

@property (strong.nonatomic) GDTSplashAd *splash;
@property (retain.nonatomic) UIView *bottomView;

@end

Copy the code

2.2 Initialize and load advertising data

Initialize and load AD data in the Implementation file of the AppDelegate. The full-screen AD supports full-screen and half-screen ads. In the half-screen AD, developers can customize the interface at the bottom of the full-screen AD to display the app Logo.

  1. Register a media ID
    BOOL result = [GDTSDKConfig registerAppId:@"xxx"];//
    
    
    if (result) {
        [self setupGDTSplashAd];

        NSLog(@" Registration successful");
    }

Copy the code
  1. Example Initialize the ID of an open screen AD slot
    GDTSplashAd *splash = [[GDTSplashAd alloc] initWithPlacementId:@ "6806"];

Copy the code
  1. First pull (LoadAd), then manually call display (splash show)
  // splash the LoadAd logic
  GDTSplashAd *splash = [[GDTSplashAd alloc] initWithPlacementId:YOUR_PLACEMENT_ID];
  splash.delegate = self; // Set the proxy
  // Set different background images for different iPhone devices
  if ([[UIScreen mainScreen] bounds].size.height >= 568.0f) {
   splash.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"LaunchImage-568h"]];
  } else {
   splash.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"LaunchImage"]];
  }
  splash.fetchDelay = 3; // Developers can set the opening screen pull time, timeout will abandon display
  [splashAd loadFullScreenAd];



Copy the code

Call manually to display ads after successful pull

#pragma mark - GDTSplashAdDelegate

- (void)splashAdDidLoad:(GDTSplashAd *)splashAd {
// if (splashAd.splashZoomOutView) {
// [self.view addSubview:splashAd.splashZoomOutView];
// splashAd.splashZoomOutView.rootViewController = self;
// // Supports drag and drop
// [splashAd.splashZoomOutView supportDrag];
/ /}
    NSLog(@"%s", __func__);
    
    NSString *text = [NSString stringWithFormat:@"%@ Advertising success", splashAd.adNetworkName];
    
    
    NSLog(@"ecpm:%ld ecpmLevel:%@ text:%@", splashAd.eCPM, splashAd.eCPMLevel,text);
    
    // splash show logic
    // Set a custom logo to display a half-screen advertisement
    
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    [self.splash showFullScreenAdInWindow:window withLogoImage:[UIImage imageNamed:@"img_login_logo"] skipView:nil];

}

- (void)splashAdSuccessPresentScreen:(GDTSplashAd *)splashAd
{
    NSLog(@"%s",__FUNCTION__);
// self.tipsLabel.text = ;
    NSLog(@" Successful AD display");
    

}

Copy the code

Set custom skip buttons

UIView *customSkipView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 50)]; UIWindow *window = [[UIApplication sharedApplication] keyWindow]; [self.splashAd showAdInWindow:window withBottomView:self.bottomView skipView:customSkipView];Copy the code

Use backgroundImage to set different background images for different iPhone devices

You need iPhone 8 [email protected], [email protected], iPhone4@1x_2.png, and splashlogo.png for the startup page

    UIImage *splashImage = [UIImage imageNamed:@"SplashNormal"];
    if (isIPhoneXSeries()) {
        splashImage = [UIImage imageNamed:@"SplashX"];
    } else if ([UIScreen mainScreen].bounds.size.height == 480) {
        splashImage = [UIImage imageNamed:@"SplashSmall"];
    }
    self.splashAd.needZoomOut = self.supportZoomoutViewSwitch.isOn;
    self.splashAd.backgroundImage = splashImage;
    self.splashAd.backgroundImage.accessibilityIdentifier = @"splash_ad";

Copy the code

2.3 Open screen Advertising Demo

AD case in demo

    self.demoArray = [@[
                        @[@self Render 2.0.@"UnifiedNativeAdViewController"], @ [@" Open screen ads".@"SplashViewController"], @ [@" Native template ads".@"NativeExpressAdViewController"], @ [@" Native Video template ads".@"NativeExpressVideoAdViewController"], @ [@" Incentivized video ads".@"RewardVideoViewController"], @ [@"HybridAd".@"HybridAdViewController"], @ [@ Banner2.0 "".@"UnifiedBannerViewController"], @ [2.0 "@" plaque.@"UnifiedInterstitialViewController"], @ [@" Full screen 2.0".@"UnifiedInterstitialFullScreenVideoViewController"], @ [@ "obtain IDFA"@ (1)], @ [@" Trial AD debugging".@"PlayableAdTestViewController"],
                        ] mutableCopy];

Copy the code

#import “SplashViewController.h”

Register the media ID API

/** SDK registration interface, please call during app initialization. @param appId - Media ID @return Whether the registration is successful. * /
+ (BOOL)registerAppId:(NSString *)appId;

Copy the code

/** * The background image can be set as the default background for screen loading */
@property (nonatomic.strong) UIImage *backgroundImage;
/** * The background color of the splash AD * can be set to splash image as the default splash image */
@property (nonatomic.copy) UIColor *backgroundColor;
/** * Call back the splashAdDidLoad method on successful pull and the splashAdFailToPresent method on failed pull
- (void)loadFullScreenAd;

/** * Call isAdValid to check whether the AD material is valid before calling this method. Display advertising success when the callback splashAdSuccessPresentScreen method, display failure when the callback splashAdFailToPresent method * /
- (void)showFullScreenAdInWindow:(UIWindow *)window withLogoImage:(UIImage *)logoImage skipView:(UIView *)skipView;

 /** * Call back the splashAdDidLoad method on a successful pull, and the splashAdFailToPresent method */ on a failed pull
- (void)loadAd;

/** * The isAdValid method is called before calling the isAdValid method to determine whether the AD material is valid. Display advertising success when the callback splashAdSuccessPresentScreen method, display failure when the callback splashAdFailToPresent method * /
- (void)showAdInWindow:(UIWindow *)window withBottomView:(UIView *)bottomView skipView:(UIView *)skipView;

For parallel requests, check before calling showAdInWindow. * @return YES if the AD has been loaded and not exposed, NO */ otherwise
- (BOOL)isAdValid;

Copy the code

III. Adaptation to IDFA

3.1 Adapt to open-screen advertisements

Changes required for the iOS14.5 update to request user authorization to access app-related data to track users or devices. For details, please visit developer.apple.com/documentati…

In the Info. Add NSUserTrackingUsageDescription plist, description for IDFA, etc. The purpose of the advertising identifier

	<key>NSUserTrackingUsageDescription</key>
	<string>This ID will be used to push personalized ads to you</string>

Copy the code

Popover small words copywriting suggestions:

  1. Access to mark permission to provide you with better quality, safe personalized services and content, we will not be used for other purposes without consent; After this function is enabled, you can turn it off at any time in Settings – Privacy.

  2. Access to IDFA and other advertising identifiers to provide you with better quality, secure personalized services and content; After this function is enabled, you can turn it off at any time in Settings – Privacy.

Authorized popup window display needs to call requestTrackingAuthorizationWithCompletionHandler: method.

It is suggested to process the advertising logic after the callback of the traffic master waiting method is completed. In this way, if users are authorized to use advertising identifiers such as IDFA, The iOS SDK can use IDFA and other advertising identifiers for advertising requests. The code is as follows:

#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>. - (void)requestIDFA {
  [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
    // Authorize the callback to complete
     [self loadGDTAd];/ / load first
  }];
}

Copy the code

The complete adaptation code is as follows

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    BOOL result = [GDTSDKConfig registerAppId:@ ""];//
    
    
    if (result) {
// [self setupGDTSplashAd];
        [self requestIDFA];
        

        NSLog(@" Registration successful");
    }

    return YES;
}
- (void)setupGDTSplashAd{
    
    // splash the LoadAd logic
    GDTSplashAd *splash = [[GDTSplashAd alloc] initWithPlacementId:@ ""];
    
    splash.delegate = self; // Set the proxy

    
// If ([[UIScreen mainScreen] bounds].size. Height >= 568.0f) {// If ([[UIScreen mainScreen] bounds].size.
// splash.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"LaunchImage-568h"]];
// } else {
// splash.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"LaunchImage"]];
/ /}
    splash.fetchDelay = 5; // Developers can set the opening screen pull time, timeout will abandon display
    self.splash =splash;
    
    // Set different background images for different iPhone devices
    
    UIImage *splashImage = [UIImage imageNamed:@"SplashNormal"];
    if (isIPhoneXSeries()) {
        splashImage = [UIImage imageNamed:@"SplashX"];
    } else if ([UIScreen mainScreen].bounds.size.height == 480) {
        splashImage = [UIImage imageNamed:@"SplashSmall"];
    }
    // * Whether to require the open screen video V+ function

// self.splash.needZoomOut = self.supportZoomoutViewSwitch.isOn;
    self.splash.backgroundImage = splashImage;
    self.splash.backgroundImage.accessibilityIdentifier = @"splash_ad";

    //
    
    [self.splash loadFullScreenAd];


    

}


#pragma mark - GDTSplashAdDelegate

- (void)splashAdDidLoad:(GDTSplashAd *)splashAd {
// if (splashAd.splashZoomOutView) {
// [self.view addSubview:splashAd.splashZoomOutView];
// splashAd.splashZoomOutView.rootViewController = self;
// // Supports drag and drop
// [splashAd.splashZoomOutView supportDrag];
/ /}
    NSLog(@"%s", __func__);
    
    NSString *text = [NSString stringWithFormat:@"%@ Advertising success", splashAd.adNetworkName];
    
    
    NSLog(@"ecpm:%ld ecpmLevel:%@ text:%@", splashAd.eCPM, splashAd.eCPMLevel,text);
    
    // splash show logic
    // Set a custom logo to display a half-screen advertisement
    
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    [self.splash showFullScreenAdInWindow:window withLogoImage:[UIImage imageNamed:@"img_login_logo"] skipView:nil];

}

- (void)splashAdSuccessPresentScreen:(GDTSplashAd *)splashAd
{
    NSLog(@"%s",__FUNCTION__);
// self.tipsLabel.text = ;
    NSLog(@" Successful AD display");
    

}



- (void)requestIDFA {
    
    
    if([self isNeedrequestTrackingAuthorization]){
        
        if (@available(iOS 14. *)) { [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {// Authorize the callback to complete
               [self setupGDTSplashAd ];// Load loadGDTAd first
            }];
              

        } else{[self setupGDTSplashAd ];// Load loadGDTAd first}}else{[self setupGDTSplashAd ];// Load loadGDTAd first}} - (BOOL)isNeedrequestTrackingAuthorization{

    
if (@available(iOS 14, *)) {
        ATTrackingManagerAuthorizationStatus status = ATTrackingManager.trackingAuthorizationStatus;
        switch (status) {
            case ATTrackingManagerAuthorizationStatusDenied:
                NSLog(@" User rejected");
                return YES;
                

                break;
            case ATTrackingManagerAuthorizationStatusAuthorized:
                NSLog(@" User permission");
                break;
            case ATTrackingManagerAuthorizationStatusNotDetermined:
                NSLog(@" User for selection or not popup");
                return YES;

                break;
            default:
                break; }}else {
        // Fallback on earlier versions
       if ([ASIdentifierManager.sharedManager isAdvertisingTrackingEnabled]) {
       }else {
          NSLog("User has enabled restricted AD tracking"); }}return NO;
    
    
}



Copy the code

In cases where users refuse to authorize UserTracking, consider tapping into Apple’s SKAdNetwork framework for AD analytics.

Developer.apple.com/documentati…

    <key>SKAdNetworkItems</key>
    <array>
        <dict>
            <key>SKAdNetworkIdentifier</key>
            <string>f7s53z58qe.skadnetwork</string>
        </dict>
        <dict>
             <key>SKAdNetworkIdentifier</key>
             <string>example200.skadnetwork</string>
        </dict>
    </array>

Copy the code

SKAdNetworkIdentifier : f7s53z58qe.skadnetwork

3.2 Adaptation to aurora push

To use the AppTrackingTransparency Framework To request user authorization To access IDFA information

———————————————— Copyright notice: This article is the original article of CSDN blogger “# public account: iOS Reverse”, in accordance with CC 4.0 BY-SA copyright agreement, please attach the original source link and this statement.

The original link: blog.csdn.net/z929118967/…

Register the aurora

    [JPUSHService setupWithOption:launchOptions appKey:@ "" channel:@"App Store" apsForProduction:YES advertisingIdentifier:[self testIDFA]];

Copy the code

Get idfaString

#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>

- (NSString*)testIDFA {
    NSString  __block *idfaString = @ "";
    
    
    
    if (@available(iOS 14. *)) { [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {if(status == ATTrackingManagerAuthorizationStatusAuthorized) { idfaString = [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString; }}]; }else {
        // Use the original method to access IDFA
        if ([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]) {
             idfaString = [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString;
        }


    }
    NSLog(@"idfaString: %@", idfaString);

    return idfaString;
    
}


Copy the code

3.3 Mounting Permission Configuration

Added the function of open screen advertising, app privacy statement of appStoreConnect background, collected data must contain IDFA, idFA needs to be added for advertising, otherwise it will be rejected.

Specific configuration:

App home page privacy collection this time added an identifier -> AD identifier for third-party ads, not associated with the user’s identity, will use the device ID for tracking purposes.

IV FaQs

4.1 SDK adaptation after 4.13.26 upgraded from 4.12.90

-> Installing GDTMobSDK 4.13.26 (was 4.12.90)

2021-11-01 09:55:54.785169+0800 +[GDTSDKConfig enableGPS:]: unrecognized selector sent to class 0x104cf83b8

Copy the code

Solution: Comment directly

// [GDTSDKConfig enableGPS:YES]; // Get the user's GPS information. The default value is NO

Copy the code

4.2 Half-Screen Adaptation in iOS13

Since the type of advertisement in this paper is full-screen, So using classification set advertising controller GDTSplashImageViewController modalPresentationStyle to UIModalPresentationFullScreen click on ads, if not to open the third party app, Will modal to GDTLandingPageWebViewController for web page display, so it is best to GDT shown here at the beginning of the controller are UIModalPresentationFullScreen.

    if([NSStringFromClass(viewControllerToPresent.class) hasPrefix:@"GDT"])

    {
        
        
        
        
        return UIModalPresentationFullScreen;
        
        
    }

Copy the code

Use categories to control modal styles

- (void)K_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void(^) (void))completion {
    if (@available(iOS 13.0, *)) {
        if (viewControllerToPresent.K_automaticallySetModalPresentationStyle) {
            
            
            viewControllerToPresent.modalPresentationStyle = [QCTSession getModalPresentationStyleWith:viewControllerToPresent];
            
            
            
                        

            
        }
        [self K_presentViewController:viewControllerToPresent animated:flag completion:completion];
    } else {
        // Fallback on earlier versions
        [selfK_presentViewController:viewControllerToPresent animated:flag completion:completion]; }}Copy the code

The corresponding controller is GDTSplashImageViewController debugging found advertising page

(lldb) po [QCT_Common getCurrentVC] <GDTSplashImageViewController: 0x159ea5f70> superclass: GDTSplashViewController title: (null) view: <UIView: 0x159d30d80; frame = (0 0; 414, 736); autoresize = W+H; layer = <CAGradientLayer: 0x280f56640>>Copy the code

For more details, see this article:

Blog.csdn.net/z929118967/…

- (NSMutableArray *)FullScreenClasss{
    
    if(_FullScreenClasss == nil){
        
        _FullScreenClasss = [NSMutableArray array];
        
        
        [_FullScreenClasss addObject:@"PGDatePickManager"];
        
        [_FullScreenClasss addObject:@"GDTSplashImageViewController"];

    }
    return _FullScreenClasss;
    
}

Copy the code

The realization of the getCurrentVC

// Get the current VC
+ (UIViewController *)getCurrentVC
{
    UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    
    UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];
    
    return currentVC;
}


+ (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC
{
    UIViewController *currentVC;
    
    if ([rootVC presentedViewController]) {
        // The view is presented
        rootVC = [rootVC presentedViewController];
    }
    
    if ([rootVC isKindOfClass:[UITabBarController class]]) {
        // The root view is UITabBarController
        currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];
        
    } else if ([rootVC isKindOfClass:[UINavigationController class]]) {// The root view is UINavigationController
        currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];
    } else {
        // The root view is a non-navigational class
        currentVC = rootVC;
    }
    return currentVC;
}


Copy the code

see also

For more, check out # Applets: iOS Reverse, which presents valuable information only for you, focusing on the mobile technology research field.

Author: public number iOS reverse