在我们APP的开发过程中,启动页面是绕不开的,广告页面说不定,但是不得不说,这两个界面都是经常要用到的。接下来我记录一下我的实现过程。项目架构为MVP。

那么先看看我们的需求和流程:(当然这也是可以根据实际需求改动的)

展示 logo 页面3秒

服务端可以控制是否播放广告

服务端可以控制播放广告的秒数

服务端可以控制广告的内容(图片)和广告详情页面的链接

这里需要注意的一点是,从服务端请求数据是在展示 3 秒启动页的时候获取的。

启动页

如果我们稍微有留意的话,都会发现,我们自己的应用启动的时候都有一段白屏的状态。但是微信却没有,我们现在要做的是解决这个问题。

首先我们来了解一下,冷启动,热启动。

冷启动:是指进程从无到有的过程。因为要进行页面初始化,所以相对其他两个启动方式,消耗的时间是相对比较多的。

热启动:是指之前的进程还在,在之前进程的基础上创建 Activity 的过程。这里耗时相对少一点。

我们可以通过 Activity 的 theme 来修改这个白屏所显示的界面。根据上面的需求,我们需要显示3秒 logo 的页面。那么,我们干脆将我们的logo设置为背景图就行。

false//取消Actionbar

true

true//设置全屏

@drawable/splash_jyz//设置背景

然后让我们的 Activity 使用这个 theme 即可。

android:name=".View.iml.AdActivity"

android:theme="@style/AppTheme.NoActionBarWithBackGround">

那么我们来看看效果图:

广告页

广告页我尝试过两种方式:

1. glide 加载

2. 通过下载文件,然后再加载

如果使用glide加载广告图片,如果网络比较差,会存在广告页面空白的情况,因为使用 glide 无法判断在 3 秒展示 logo 的页面是否加载好了广告图片。这给用户的体验是比较差的,也是不太友好的,因为用户在空白界面拜拜等待了 3 秒。所以后面使用了将广告图片下载到本地的方法。

这里进行数秒,这里是通过增加数字值来控制的,解决了服务端要控制广告时间的问题。之前使用过减少数字值来实现,但是要解决服务端控制广告时间,就没那么容易了。

View

private int countNum() {//数秒

timeCount++;

if (timeCount == 3) {//数秒,超过3秒后如果没有网络,则进入下一个页面

if (!NetUtils.isConnected(AdActivity.this)) {

continueCount = false;

toNextActivity();

finish();

}

if (!loginCheckBean.isPlayAd()) {//如果服务端不允许播放广告,则直接进入下一个页面

continueCount = false;

toNextActivity();

finish();

} else {//如果播放,则进行显示

ivAdvertising.setVisibility(View.VISIBLE);

layoutSkip.setVisibility(View.VISIBLE);

}

}

if (timeCount == initTimeCount) {//超过广告显示的最长时间,进入下一个界面

continueCount = false;

toNextActivity();

finish();

}

return timeCount;

}

public void toNextActivity() {//根据是否保存有 token 判断去登录界面还是主界面

L.d("到下一个界面");

Intent intent = null;

String token = (String) SPUtils.get(AdActivity.this, "token", "");

if (TextUtils.isEmpty(token)) {

intent = new Intent(AdActivity.this, LoginActivity.class);

} else {

intent = new Intent(AdActivity.this, MainActivity.class);

MyApplication.setToken(token);

}

startActivity(intent);

finish();

}

Presenter##

向服务端请求是否要播放广告

public void getLoginCheck() {//向服务器请求是否要播放广告

mAdModel.getLoginCheck()

.subscribeOn(Schedulers.io()) //发布者在后台线程中运行

.observeOn(AndroidSchedulers.mainThread()) //订阅者在Android主线程中运行

.subscribe(new RxSubscribe() {

@Override

protected void _onNext(LoginCheckBean loginCheckBean) {

getMyView().setLoginCheckBean(loginCheckBean);

if (loginCheckBean.isPlayAd()) {//这里需要添加一个是否已经下载的判断,如果已经下载,则不再进行下载

getAdMessage();

}

}

@Override

protected void _onError(String message) {

}

@Override

public void onCompleted() {

}

});

}

获取图片地址,详情页面链接,广告的播放时间

public void getAdMessage() {

mAdModel.getAdMessage()

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new RxSubscribe() {

@Override

protected void _onNext(AdMessageBean adMessageBean) {

getMyView().setAdTime(adMessageBean.getAdTime());

getAdPicture(adMessageBean.getAdPictureUrl(), "123.jpg");

}

@Override

protected void _onError(String message) {

}

@Override

public void onCompleted() {

}

});

}

获取广告图片

private void getLocalPicture(String localUrl) {

Bitmap bitmap = BitmapFactory.decodeFile(localUrl);

getMyView().setAdImg(bitmap);

}

public void getAdPicture(final String fileUrl, final String fileName) {//获取要展示的广告图片

if (SPUtils.get((Context) getMyView(), "adPictureUrl", "").equals(fileUrl)) {//判断是否存在缓存

L.d("从本地获取图片");

getLocalPicture((String) SPUtils.get((Context) getMyView(),"adPictureAddress",""));

} else {

L.d("从网络中获取图片");

mAdModel.downLoadFile(fileUrl)

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.map(new Func1() {

@Override

public Bitmap call(ResponseBody responseBody) {

if (responseBody != null) {

L.d("收到的responseBody不为空!");

}

if (writeResponseBodyToDisk(responseBody, fileName, fileUrl)) {

Bitmap bitmap = BitmapFactory.decodeFile(((Context) getMyView()).getExternalFilesDir(null) + File.separator + fileName);

return bitmap;

}

return null;

}

}).subscribe(new RxSubscribe((Context) getMyView()) {

@Override

protected void _onNext(Bitmap bitmap) {

getMyView().setAdImg(bitmap);

}

@Override

protected void _onError(String message) {

}

@Override

public void onCompleted() {

}

});

}

}

private boolean writeResponseBodyToDisk(ResponseBody body, String fileName, String fileUrl) {//保存图片到本地

try {

// todo change the file location/name according to your needs

File futureStudioIconFile = new File(((Context) getMyView()).getExternalFilesDir(null) + File.separator + fileName);

L.d("文件的保存地址为:" + ((Context) getMyView()).getExternalFilesDir(null) + File.separator + fileName);

InputStream inputStream = null;

OutputStream outputStream = null;

try {

byte[] fileReader = new byte[4096];

long fileSize = body.contentLength();

long fileSizeDownloaded = 0;

inputStream = body.byteStream();

outputStream = new FileOutputStream(futureStudioIconFile);

while (true) {

int read = inputStream.read(fileReader);

if (read == -1) {

break;

}

outputStream.write(fileReader, 0, read);

fileSizeDownloaded += read;

L.d("file download: " + fileSizeDownloaded / fileSize * 100);

L.d("file download: " + fileSizeDownloaded + " of " + fileSize);

}

outputStream.flush();

SPUtils.put((Context) getMyView(), "adPictureAddress", ((Context) getMyView()).getExternalFilesDir(null) + File.separator + fileName);//下载好广告图片后,保存好当前广告图片的地址,为判断是否已经下载好图片做准备

SPUtils.put((Context) getMyView(), "adPictureUrl", fileUrl);

return true;

} catch (IOException e) {

return false;

} finally {

if (inputStream != null) {

inputStream.close();

}

if (outputStream != null) {

outputStream.close();

}

}

} catch (IOException e) {

return false;

}

}

Model

public Observable getLoginCheck() {//假装服务器要展示广告

return Observable.create(new Observable.OnSubscribe() {

@Override

public void call(Subscriber super LoginCheckBean> subscriber) {

subscriber.onNext(new LoginCheckBean(true));

subscriber.onCompleted();

}

});

}

public Observable getAdMessage() {

return Observable.create(new Observable.OnSubscribe() {

@Override

public void call(Subscriber super AdMessageBean> subscriber) {//假装要展示 3 秒广告,且广告图为如下地址

subscriber.onNext(new AdMessageBean(3,"http://odjfpxwey.bkt.clouddn.com/2017-3-3-20-141110180-Screenshot_2017-02-23-23-10-26-062_com.tmall.wireless.png","http://www.baidu.com"));

subscriber.onCompleted();

}

});

}

public Observable downLoadFile(String fileUrl) {

return retrofitService.downLoadFile(fileUrl);

}

关注微信公众号:zone7,获取最新技术文章

android广告页白屏_Android 启动页面与广告页面的实现-Go语言中文社区相关推荐

  1. android广告页白屏_Android 启动页白屏解决方案

    当我们打开app的时候是不是会有一瞬间的白屏然后再进入主活动,虽然这并不会造成什么不好的后果,但是感觉用户体验就不是很好.像网易云音乐等等,打开一瞬间就显示了他们的loge,无缝衔接,没有白屏,怎么 ...

  2. android广告页白屏_android 白屏

    从首篇介绍我为什么写文章到现在已经过去好久.......(懒),但从此刻开始,不出意外情况每周给大家至少写一篇文章,就按平时app开发流程以及本人遇到的问题,从app欢迎页面开始吧! 一:为什么会有欢 ...

  3. android广告页白屏_年度整理!2056页《大厂安卓岗面试真题解析合集》火爆全网...

    前言 2020年还有最后一个月就结束了,时间一眨眼就过去了.今年面试有没有被面试官虐呢,明年跳槽想跳去哪个大厂呢,这是个问题.说实话,今年我面试也被虐了,为了明年能找到一份心怡的工作,特地的从朋友那里 ...

  4. android广告页白屏_微信官方朋友圈广告营销技巧

    微信作为一个月活跃用户高达10亿的社交平台,用户年龄从15~40岁覆盖,渗透率高达93%.一个聚集了庞大的流量平台是如何玩转广告生态的呢?又是如何快速的帮助商家曝光.引流.成交的呢?在现实中,办公.生 ...

  5. xmanager linux,教您用xmanager启动Linux上的图形界面程序-Go语言中文社区

    对于习惯实体化的开发人员来说,还是界面化用着比较习惯,所以这就涉及到掌握使用Xmanager启动Linux上的图形界面程序,为了方便大家的使用,本集小编就详细的为大家讲解具体操作. 具体步骤如下: 1 ...

  6. windows远程android传输文件,电脑(Linux/Windows)使用SSH远程登录安卓(Android)手机实现无线传输和管理文件(图文详解)-Go语言中文社区...

    电脑(Linux/Windows系统)使用SSH远程登录安卓(Android)手机实现无线传输和管理文件(图文详解) 温馨提示 本文只针对安卓(Android)手机!iPhone或者WP的手机用户,请 ...

  7. Android启动页白屏背景图拉伸的解决方案

    Android启动页白屏&背景图拉伸的解决方案 1.前言 2.问题点 3.代码及说明 4.注意点 1.前言 新项目的闪屏页面用到一张大图,UI那边要求那张图片填充全屏,而且不能压缩或拉伸. 然 ...

  8. Android APP应用启动页白屏(StartingWindow)优化

    转自:https://www.cnblogs.com/whycxb/p/9312914.html 本人采用这种方法没有效果,启动图片出来第一帧,我应用的第一帧也出来了. 启动背景颜色没有调试出来,Th ...

  9. android 加载图片 白屏,android启动页白屏和图片自适应问题

    android启动页白屏和图片自适应问题,自适应官方给的说法也只是做多套图去适配不同的分辨率,本文通过几个设置几行代码即可解决启动页短暂白屏和自适应问题. 网上的说法是通过启动页代码裁切图片或者在Im ...

最新文章

  1. Python: translate()审查清理文本字符串
  2. 洛谷【P2257】YY的GCD
  3. 初学Java Web(4)——Servlet学习总结
  4. day21.模块和包
  5. listrecord根据某个属性去重_去哪网开发实战记录(9):城市选择页(中)
  6. 【JavaWeb】数据库基础复习
  7. 容器编排技术 -- Kubernetes kubectl 与 Docker 命令关系
  8. Java基础教程【第五章:Java数组】
  9. Mac盖上屏幕后外接屏幕持续黑画面的解决方法
  10. 里恩eLearning在线培训考核系统介绍
  11. 模块化机房建设指导书_模块化数据中心机房建设方案
  12. 【翻译】ILSVRC2012数据集介绍
  13. chrome 打开默认页 被篡改_Chrome谷歌浏览器主页总被篡改怎么解决?
  14. 艺术摄影--曝光与测光(2学时)--SDUST
  15. 山东大学软件过程管理复习纲要
  16. 浙大愤青郑强教授的演讲(大学生都来看看吧)
  17. APFS 强在哪里?
  18. 安装 opencv-python 出现Command “python setup.py egg_info“ failed with error code 1 in /tmp/pip-build-npa
  19. 解决高并发下Redis连接失败redis.clients.jedis.exceptions.JedisConnectionException Attempting to read from a bro
  20. U盘损坏和文件修复(前方高能!!!)

热门文章

  1. android标题栏上增加按钮,Android:向自定义标题栏添加按钮
  2. VB讲课笔记02:VB程序开发环境
  3. SciTE文本编辑器初体验
  4. 【BZOJ2768】冠军调查,网络流之最小割
  5. 【BZOJ3049】Island Travels,SPFA预处理+状态压缩DP
  6. 2017.10.30 覆盖问题 思考记录
  7. render注册一个链接组件_详解vue 动态加载并注册组件且通过 render动态创建该组件...
  8. 【英语学习】【English L06】U04 Adventure L6 My favorite tourist destination
  9. 【英语学习】【WOTD】resurrection 释义/词源/示例
  10. ef 在此上下文中只支持基本类型或枚举类型_Java枚举不应该成为你成功路上得绊脚石,源码给你讲解清楚