现在很多app都有广告页这一功能,广告页应该都清楚,无非就是在闪屏页的后面又加了一个一页面,支持点击跳转网页或者h5页面,如果项目做大了,别人找你放广告还可以挣广告费,当然,一切公司说的算。
首先,思路就是在app启动展示闪屏页的同时,在这三秒内请求网络吧图片下载缓存起来,等到闪屏页结束,取缓存数据展示,如果不取缓存进行请求页面会很别扭,闪烁一下或着网差,没展示出来,白白展示了3秒的白屏,多尴尬。
起初,想用glide来做,因为支持三级缓存,但是效果不理想,展示的时候还是闪烁一下;然后又换了文件缓存,在6.0一下没事,展示页很快,因为取的本地嘛,6.0以上涉及到动态权限就取不到了,就会出现展示白屏操作,如果说动态请求权限,关键在哪里请求权限是个重要的问题,项目启动是个闪屏页,你加个动态权限,可能吗?后面紧接着就是广告页了,更不可能了,体验差到极致了。后来就用了picasso的tager和rxjava才成功了!
页面布局文件
<ImageView
android:id="@+id/delayed_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/delayed_icon" />
<Button
android:visibility="gone"
android:padding="4dp"
android:id="@+id/bt_delayed"
android:layout_width="70dp"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:layout_marginRight="24px"
android:layout_marginTop="60px"
android:background="@drawable/jump_bg"
android:gravity="center"
android:text="跳过"
android:textColor="#FFFFFF"
android:textSize="30px" />
图片展示的就是闪屏页图片,button是跳过按钮,广告页和闪屏页讲究的是衔接性,就是跳转的时候显示很流畅,所以我的闪屏页和广告页都是在一个页面,不是两个activity页面跳转,体验好,展示3秒闪屏页后,将上面的imageview替换成广告页不就实现了连个页面连续跳转吗,(并非跳转,实际是替换图片)。思路就是这样
主要代码:
/**
* 全屏显示
*/
public void setStatusBar() {
Window window = getWindow();
requestWindowFeature(Window.FEATURE_NO_TITLE);
int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
//设置当前窗体为全屏显示
window.setFlags(flag, flag);
}
/**
* 请求广告页的网络请求
*/
public void getAdvertisingMap() {
HTTPSHelper.post(SysParam.advertising, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int i, Header[] headers, byte[] bytes) {
String body = new String(bytes);
Gson gson = new Gson();
advertising = gson.fromJson(body, new TypeToken<List<AdvertisingBean>>() {
}.getType());
//取出解析后的广告页图片路径和需要跳转的路径
imageUrl = advertising.get(0).getAdvert_ImgUrl();
jumpUrl = advertising.get(0).getAdvert_Url();
//获取应用程序缓存文件夹下的指定目录
String imageCachePath = FileUtil.getAppCacheFile(getApplicationContext(), imageUrl.substring(imageUrl.lastIndexOf("/"), imageUrl.length()));
imageCacheFile = new File(imageCachePath);
if (imageCacheFile.exists()) {
//一个用于判断广告页是否加载完成
isAdLoaded = true;
} else {
//Picasso的Target
yunDouTarget = new YunDouTarget();
Picasso.get()
.load(imageUrl)
.networkPolicy(NetworkPolicy.NO_STORE)
.memoryPolicy(MemoryPolicy.NO_STORE)
.resize(getResources().getDisplayMetrics().widthPixels,
getResources().getDisplayMetrics().heightPixels)
.centerCrop()
.into(yunDouTarget);
}
}
@Override
public void onFailure(int i, Header[] headers, byte[] bytes, Throwable throwable) {
}
});
}
/**
* 自定义的PicassoTarget
*/
class YunDouTarget implements Target {
@Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
isAdLoaded = true;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(imageCacheFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/* 使用io线程保存图片 */
final FileOutputStream finalFos = fos;
Observable.just(fos)
.subscribeOn(Schedulers.io())
.subscribe(new Action1<FileOutputStream>() {
@Override
public void call(FileOutputStream fileOutputStream) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, finalFos);
try {
finalFos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
try {
finalFos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
@Override
public void onBitmapFailed(Exception e, Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
实现延时效果
private Button delayed;
private Timer timer = new Timer();
private static String imageUrl = null;
private String jumpUrl = null;
private File imageCacheFile;
/* 广告是否已经加载完成 */
private boolean isAdLoaded;
/* 默认页面是否已经显示完成 */
private boolean isDefaultPageFinished;
private List<AdvertisingBean> advertising;
private YunDouTarget yunDouTarget;
private ImageView delayed_icon;
private Handler handler;
private boolean isClick = false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStatusBar();//隐藏状态栏
setContentView(R.layout.activity_delayed);
getAdvertisingMap();
delayed = (Button) findViewById(.bt_delayed);
delayed_icon = (ImageView) findViewById(.delayed_icon);
handler = new Handler();
//用的handler和timer,按理说用一个就可以,timer用习惯了,handler本不想用,主要是postDelayed是主线程,可以更新ui,timer在子线程,更新ui会崩溃的;其实可以都用handler,懒的改了
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (isAdLoaded) {
//判断默认页面是否已经显示完成
isDefaultPageFinished = true;
//跳转按钮显示
delayed.setVisibility(View.VISIBLE);
String imageCachePath = FileUtil.getAppCacheFile(getApplicationContext(), advertising.get(0).getAdvert_ImgUrl().substring(advertising.get(0).getAdvert_ImgUrl().lastIndexOf("/"), advertising.get(0).getAdvert_ImgUrl().length()));
Bitmap bitmap = BitmapFactory.decodeFile(imageCachePath);
//拿到保存的广告页展示
delayed_icon.setBackground(new BitmapDrawable(getResources(), bitmap));
timer.schedule(new TimerTask() {
@Override
public void run() {
startIntent();
}
}, 3000);
} else {
startIntent();
}
}
}, 2000);
//跳过按钮
delayed.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//防止点击和自动跳转重复,形成页面多次跳转
if (timer!=null){
timer.cancel();
}
startIntent();
}
});
//广告详情
delayed_icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (jumpUrl != null) {
//判断图片是否加载完成
if (!isAdLoaded || !isDefaultPageFinished) {
return;
}
isClick = true;
Uri uri = Uri.parse(jumpUrl);
Intent intenWeb = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intenWeb);
}
}
});
}
广告图点击逻辑
public void startIntent() {
//用于判断是否点击了广告图,不然会形成你点击了广告图进入网页,接着你退回了,发现广告页停了或者还在走,我的做法是在OnResume方法里直接跳转
if (isClick) {
return;
}
intent = new Intent(DelayedActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
@Override
protected void onResume() {
super.onResume();
为true说明你点击了广告,页面再次获得焦点,直接跳转
if (isClick) {
if (timer!=null){
//取消自动跳转,不然会形成重复跳转
timer.cancel();
}
isClick = false;
startIntent();
}
}
最后,取消timer和handler
@Override
protected void onDestroy() {
super.onDestroy();
if (timer != null) {
timer.cancel();
}
if (handler != null) {
handler.removeCallbacksAndMessages(null);
}
}
FileUtils类
public class FileUtil {
/**
* 获取应用程序缓存文件夹下的指定目录
* @param context
* @param name
* @return
*/
public static String getAppCacheFile(Context context, String name) {
String savePath = context.getCacheDir().getAbsolutePath() + "/" + name;
return savePath;
}
}