Android開發之啟動頁與廣告頁
阿新 • • 發佈:2018-12-27
在我們APP的開發過程中,啟動頁面是繞不開的,廣告頁面說不定,但是不得不說,這兩個介面都是經常要用到的。接下來我記錄一下我的實現過程。專案架構為MVP。
那麼先看看我們的需求和流程:(當然這也是可以根據實際需求改動的)
- 展示 logo 頁面3秒
- 服務端可以控制是否播放廣告
- 服務端可以控制播放廣告的秒數
- 服務端可以控制廣告的內容(圖片)和廣告詳情頁面的連結
這裡需要注意的一點是,從服務端請求資料是在展示 3 秒啟動頁的時候獲取的。
啟動頁
如果我們稍微有留意的話,都會發現,我們自己的應用啟動的時候都有一段白屏的狀態。但是微信卻沒有,我們現在要做的是解決這個問題。
首先我們來了解一下,冷啟動,熱啟動。
冷啟動:是指程序從無到有的過程。因為要進行頁面初始化,所以相對其他兩個啟動方式,消耗的時間是相對比較多的。
熱啟動:是指之前的程序還在,在之前程序的基礎上建立 Activity 的過程。這裡耗時相對少一點。
我們可以通過 Activity 的 theme 來修改這個白屏所顯示的介面。根據上面的需求,我們需要顯示3秒 logo 的頁面。那麼,我們乾脆將我們的logo設定為背景圖就行
<style name="AppTheme.NoActionBarWithBackGround"> <item name="windowActionBar">false</item>//取消Actionbar <item name="windowNoTitle">true</item> <item name="android:windowFullscreen">true</item>//設定全屏 <item name="android:windowBackground">@drawable/splash_jyz</item>//設定背景 </style>
然後讓我們的 Activity 使用這個 theme 即可。
<activity android:name=".View.iml.AdActivity" android:theme="@style/AppTheme.NoActionBarWithBackGround"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
廣告頁
廣告頁我嘗試過兩種方式:
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<LoginCheckBean>() {
@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<AdMessageBean>() {
@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<ResponseBody, Bitmap>() {
@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<Bitmap>((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<LoginCheckBean> getLoginCheck() {//假裝伺服器要展示廣告
return Observable.create(new Observable.OnSubscribe<LoginCheckBean>() {
@Override
public void call(Subscriber<? super LoginCheckBean> subscriber) {
subscriber.onNext(new LoginCheckBean(true));
subscriber.onCompleted();
}
});
}
public Observable<AdMessageBean> getAdMessage() {
return Observable.create(new Observable.OnSubscribe<AdMessageBean>() {
@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<ResponseBody> downLoadFile(String fileUrl) {
return retrofitService.downLoadFile(fileUrl);
}