1. 程式人生 > >Android開發之啟動頁與廣告頁

Android開發之啟動頁與廣告頁

 在我們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);
    }