App启动加载广告页面思路

作者: zhq1992 | 来源:发表于2016-05-20 09:21 被阅读13115次

    需求

    很多app(如淘宝、美团等)在启动图加载完毕后,还会显示几秒的广告,一般都有个跳过按钮可以跳过这个广告,有的app在点击广告页之后还会进入一个广告页面,点击返回进入首页。虽然说这个广告页面对用户体验来说并不是很好,但是如果真的有这个需求,我们还是要想办法去开发,至少这比内嵌广告要友善的多。今天我们就来开发一个广告页面,效果如下。


    效果图.gif

    思路

    1.广告页加载思路。广告页的内容要实时显示,在无网络状态或者网速缓慢的情况下不能延迟加载,或者等到首页出现了再加载广告页。所以这里我不采用网络请求广告接口获取图片地址,然后加载图片的方式,而是先将图片异步下载到本地,并保存图片名,每次打开app时先根据本地存储的图片名查找沙盒中是否存在该图片,如果存在,则显示广告页。

    2.判断广告页面是否更新。无论本地是否存在广告图片,每次启动都需要重新调用广告接口,根据图片名称或者图片id等方法判断广告是否更新,如果获取的图片名称或者图片id跟本地存储的不一致,则需要重新下载新图片,并删除旧图片。

    3.广告页点击。如果点击广告需要跳转广告详情页面,那么广告链接地址也需要用NSUserDefaults存储。注意:广告详情页面是从首页push进去的

    4.广告页的显示代码可以放在AppDeleate中,也可以放在首页的控制器中。如果代码是在AppDelegate中,可以通过发送通知的方式,让首页push到广告详情页。

    5.广告页面的底部和启动图的底部一般都是相同的,给我们的感觉就是启动图加载完之后把广告图放在了启动图上,而且不能有偏差,比如下图淘宝启动画面。美工在制作广告图的时候要注意这点。


    淘宝启动.gif

    6.研究了一下淘宝的广告显示机制,删除淘宝之后重新打开不会显示广告图片,第二次打开才会显示。美团的广告图有时候显示有时候不显示,所以后台在开发广告api的时候可以增加一个字段来判断是否启用广告,如果后台关闭了广告,将沙盒中的图片删除即可。

    步骤

    1.判断沙盒中是否存在广告图片,如果存在,直接显示
        NSString *filePath = [self getFilePathWithImageName:[kUserDefaults valueForKey:adImageName]];
        
        BOOL isExist = [self isFileExistWithFilePath:filePath];
        if (isExist) {// 图片存在
            
            AdvertiseView *advertiseView = [[AdvertiseView alloc] initWithFrame:self.window.bounds];
            advertiseView.filePath = filePath;
            [advertiseView show];
    
        }
    
    2.无论沙盒中是否存在广告图片,都需要重新调用获取广告接口,判断广告是否更新
     AFHTTPRequestOperationManager * manager = [AFHTTPRequestOperationManager manager];
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/html", nil];
        [manager GET:urlStr parameters:nil success:^(AFHTTPRequestOperation * _Nonnull operation, id  _Nonnull responseObject) {
            NSArray *dataArray = responseObject[@"data"];
            NSString *imageUrl = dataArray[0][@"imageUrl"];
            NSArray *stringArr = [imageUrl componentsSeparatedByString:@"/"];
            NSString *imageName = stringArr.lastObject;
            NSString *filePath = [self getFilePathWithImageName:imageName];
            BOOL isExist = [self isFileExistWithFilePath:filePath];
            if (!isExist){// 如果该图片不存在,则下载新图片,删除老图片
                
                [self downloadAdImageWithUrl:imageUrl imageName:imageName];
                
            }
            
        } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) {
            
        }];
    
    
    异步下载图片
    /**
     *  下载新图片
     */
    - (void)downloadAdImageWithUrl:(NSString *)imageUrl imageName:(NSString *)imageName
    {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
            UIImage *image = [UIImage imageWithData:data];
            
            NSString *filePath = [self getFilePathWithImageName:imageName]; // 保存文件的名称
            
            if ([UIImagePNGRepresentation(image) writeToFile:filePath atomically:YES]) {// 保存成功
                NSLog(@"保存成功");
                [self deleteOldImage];// 保存成功后删除旧图片
                [kUserDefaults setValue:imageName forKey:adImageName];
                [kUserDefaults synchronize];
                // 如果有广告链接,需要将广告链接也保存下来
            }else{
                NSLog(@"保存失败");
            }
            
        });
    }
    
    /**
     *  删除旧图片
     */
    - (void)deleteOldImage
    {
        NSString *imageName = [kUserDefaults valueForKey:adImageName];
        if (imageName) {
            NSString *filePath = [self getFilePathWithImageName:imageName];
            NSFileManager *fileManager = [NSFileManager defaultManager];
            [fileManager removeItemAtPath:filePath error:nil];
        }
    }
    
    
    3.广告页面的跳过按钮倒计时功能可以通过定时器或者GCD实现
    // GCD倒计时
    - (void)startCoundown
    {
        __block int timeout = showtime + 1; //倒计时时间 + 1
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
        dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0 * NSEC_PER_SEC, 0); //每秒执行
        dispatch_source_set_event_handler(_timer, ^{
            if(timeout <= 0){ //倒计时结束,关闭
                dispatch_source_cancel(_timer);
                dispatch_async(dispatch_get_main_queue(), ^{
                    
                    [self dismiss];
                    
                });
            }else{
    
                dispatch_async(dispatch_get_main_queue(), ^{
                    [_countBtn setTitle:[NSString stringWithFormat:@"跳过%d",timeout] forState:UIControlStateNormal];
                });
                timeout--;
            }
        });
        dispatch_resume(_timer);
    }
    
    4.为广告页面添加一个点击手势,跳转到广告页面
    //AdvertiseView.m
    - (void)pushToAd{
        
        [self dismiss];
        
        [[NSNotificationCenter defaultCenter] postNotificationName:@"pushtoad" object:nil userInfo:nil];
    }
    
    // ViewController.m
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.title = @"首页";
        
        self.view.backgroundColor = [UIColor orangeColor];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pushToAd) name:@"pushtoad" object:nil];
    }
    
    - (void)pushToAd {
        
        AdvertiseViewController *adVc = [[AdvertiseViewController alloc] init];
        [self.navigationController pushViewController:adVc animated:YES];
        
    }
    

    完整代码下载地址

    代码下载地址

    相关文章

      网友评论

      • 呃哈哈:项目第一次启动是没有广告的
        plantAtree_dAp:现在我的项目,第一次启动要有广告,很爽-
      • 蒙牛神探:有没有关于FFMeng相关的资料
      • d8de97c659c7:如果把启动页的广告比作一个人,老子恨不得一菜刀把他从头顶劈到屁眼!简直是“夺妻只恨”!!!🤬🤬🤬🤬🤬
      • 232ae72d57c9:很赞👍
      • ZhangCc_:有一个问题,就是当前显示的图片,与新的请求下载的图片是一样的时候,以后就不会显示广告了
      • c066fe49abc4:你好,我想请问一下,我的倒计时不准确,会是什么原因导致的呢,比如我设的是4s,但是广告图显示的时间实际上小于4s,而且倒计时的数也不对,有时候直接4然后就到0了,会跟我设置了本地启动图有关系么
      • 大猿媛:大神,我想确认个问题,文章说为保证广告的时效性和准确性,每次启动都要请求后台,,不是本地存储的数据就要重新存储重新展示,那是不是就没必要做本地存储了? 我看腾讯视频,每次启动都有广告图,而且打开一瞬间就有,每次打开都不一样,这种情况不像是启动发生的网络请求,倒像是一次把广告数据都请求存储到本地,每次打开直接取本地数据
        zhq1992:@大猿媛 腾讯视频 第一次安装启动 也是没有广告的, 启动几次之后才有的
        zhq1992:@大猿媛 这也是不错的思路,一次保存多张图片到本地 。但是每次打开都不一样用我那种方法也能实现。
      • Grace233333:去你妹美工
      • 之城之城:demo跑起来。没出现广告页
      • 蚂蚁_a:我们是后台返回广告数组 每个广告返回广告id 广告标题 图片 跳转链接 广告活动结束时间戳,
        第一次启动 先缓存广告数组,第二次启动先读本地缓存数组,活动时间内的广告显示,然后请求广告数组,数组空-》清空本地广告缓存 ,非空-》跟本地广告id比较下,有新广告或者有更新,再缓存下
        蚂蚁_a:@勤奋的小智 :flushed:
        勤奋的小智: @caodaxun 你好,第二次启动广告数组不与服务器匹配就直接显示缓存的?时间是合法范围内,就直接显示了缓存中的广告页配置,再与服务器的进行匹配么?
      • qBryant:这个功能比较实用。。。
      • d12a6f744b0d:写的不错,到时候把广告换成自己的广告就行了。大神你其他的开源代码给说说呗
      • bd0f6bb1db6c:学习了
      • 丶小杨_:我想添加多个广告 怎么弄啊
      • 414697ada450:楼主 仔细查看你写的AdvertiseView , block 中存在 循环引用问题, block 不能出现 self字眼
      • love平_冲:在dismiss方法中 加入下面两行代码,就不会打印两次了,你应该忘了停掉定时器,或者取消gdc的定时,我采用的是你的NSTimer,所以我加入了一下的代码
        [self.countTimer invalidate];
        self.countTimer = nil;
        love平_冲:@周焕强 哈哈,没事,互相学习
        zhq1992:@love平的冲 谢谢指正
      • love平_冲:dismiss方法会调用两遍,你打印一下看看
      • 潸何吊:好文 学习了。 :sunglasses:
      • ifelseboyxx:666,思路不错,学习了
      • 名字难取Jay:您好,下载了2次可是运行不了呢,Xcode运行的哪里直接显示NO Scheme啊。。。
        名字难取Jay:恩恩,成功了,多谢!
        zhq1992:@e985d3a9a2e7 代码重新上传了, No Scheme 这个问题可以通过manager scheme 然后添加一下来解决的,
      • 1338e9393d09:无法显示 大断电 发现下载新图片时保存失败
      • 屮艸芔: 真机上运行会出现倒计时不准,卡顿很明显,该怎么解决啊
        zhq1992:@屮艸芔 没有这种情况啊。。我测试了两个手机。
      • love平_冲:貌似第一次使用的时候,总是下载的慢,然后,第二次运行才会显示
      • 7c4368c8b989:请问我用xcode5 下载广告的源码 那个AFURLRequestSerialization.h文件出现了错误. 怎么解决啊 ??
        zhq1992:@7c4368c8b989 对了,最新那份代码没用到af了,把afnetworking 删除掉就行了。 我代码也重新上传了。
        zhq1992:@7c4368c8b989 我用的是afnetworking 3.0 , 要iOS7以上的系统, xcode7。 Xcode 5 要用2.0-2.5.4的af。
      • c45c75ce4a5f:请问,显示前会有一片白色的,如何解决?
        c45c75ce4a5f:@周焕强 好的,感谢!
        zhq1992:@林辉仙 如果是那个一闪白色的,那是gif的问题;如果是启动白色那是因为没有启动图。
      • 727eacd06b43:给你点个赞@@@
      • 小小叶:很实用。。我也是这个思路。第一次下载存储,之后再打开就可以显示广告了。。不过我小白,考虑的还是少,学习了~
        zhq1992:@小小叶 相互学习
      • e3603ae9278e:很潮很实用
      • _YZG_:你好, 我问下谁去调startCoundown
        zhq1992:@_YZG_ 更具体的代码我没有贴出来了,不然太多了,有兴趣的话可以去下载。就是我那个广告view有一个show方法(显示广告页面), show方法里面会调用开启定时器方法。
        _YZG_:@周焕强 我知道,但是我没有看到谁去调她
        zhq1992:@_YZG_ 封装的广告view中
      • 4daccbd536b2:淘宝的启动页为什么每天第一次打开不显示广告,如何实现?
        zhq1992:@one虚无缥缈 不好意思,这个写的有误,我本来想表达的是有时候启动不会显示广告,实现方法是让后台增加一个enable字段来判断是否启用广告。。并不是每天的第一次启动,已经改掉了。
      • 七秒记忆的鱼儿:你的加载广告是没有实时性的,是个自营广告
        PGOne爱吃饺子:@七秒记忆的鱼儿 其实你接一下百度或者腾讯的广告,挺不错的,很简单的
        七秒记忆的鱼儿:@4140d18ee6fc 就是你进去的时候请求后台,保存广告图到沙盒,下次打开应用的时候直接加载广告,这是我比较喜欢的一种
        PGOne爱吃饺子:大哥,请问一下你说的这个广告没有实时性的是什么意思,我们的项目也是刚刚开始要做广告的,
      • Never_Yg:能不能把启动图到广告(就是那白屏到广告页)的闪屏效果去掉
        Never_Yg:好的,thx
        zhq1992:@Never_Yg 这张gif确实特别闪
        zhq1992:@Never_Yg gif的问题,我用模拟器和真机看过了,不会闪屏
      • JChow:和我做广告页的思路基本一致,gcd倒计时那个学习下:+1:
      • 周小公子丶:码一下。
      • 欧阳铨:mark,周末研究研究
      • niuxinghua:这个保证不了广告的实时性吧
        zhq1992:@低调做事 不是第二天,是第二次,比如广告图片的url改变了,我这次打开app先把这种新图片下载了,下一次再显示。你可以去看看淘宝和美团,我试过了,一天中第一次打开淘宝并不会显示广告页面,第二次打开才会显示。
        萧城x:那就是说 如果广告第二天 要显示 用户只有前一听 打开 下载了 第二天才可以显示
        zhq1992:@niuxinghua 我的方法是第一次启动时下载广告,第二次启动时会更新。既要保证广告不会因为网络问题延迟加载又要保证广告的实时性,有好的思路的话可以探讨下。
      • e1d5d9596e20:发现运行不了,模拟器不能运行
        e1d5d9596e20:@李若玄1998 你那个之前不能模拟器运行的是什么原因呢
        e1d5d9596e20:@周焕强 ok
        zhq1992:@李若玄1998 我这边可以的。。我刚刚重新上传了一份,应该没问题了。
      • e1d5d9596e20:思路很清晰,博主智商很高
      • seay:很实用
        zhq1992:@SeayXu 谢谢
      • zhq1992:要是有错误或者补充还请大家指出
      • fe86d48aad87:感谢分享~
        zhq1992:@heyuze :smile:
      • 微笑的痕迹:正好需要,看一下
      • 轩辕小羽:文章很有用:+1:
        轩辕小羽:@溺水的小小鱼 :relaxed:
        上上上上签:@轩辕小羽 大白屌屌哒 在哪儿都能碰到你 :smiley:
        zhq1992:@轩辕小羽 谢谢

      本文标题:App启动加载广告页面思路

      本文链接:https://www.haomeiwen.com/subject/nqtnrttx.html