Phát quảng cáo tùy chỉnh bằng SDK IMA cho Android

Cách nhanh nhất và đơn giản nhất để tích hợp SDK IMA dành cho Android vào ứng dụng là yêu cầu SDK xử lý tất cả logic phát quảng cáo, trong khi ứng dụng tập trung vào việc phát video nội dung. Phương pháp này có tên là "phát quảng cáo do SDK sở hữu" là phương án mặc định trong bài viết Bắt đầu.

Tuy nhiên, nếu bạn cũng muốn phát quảng cáo trong trình phát video, SDK sẽ cung cấp một giao diện để làm việc đó. Chúng tôi gọi phương pháp này là "phát quảng cáo tùy chỉnh" và phần còn lại của hướng dẫn này trình bày cách triển khai.

Điều kiện tiên quyết

  • Tích hợp IMA cơ bản.

Bạn nên tham khảo Ví dụ nâng cao trên GitHub nếu bạn hiện chưa tích hợp IMA cơ bản. Ví dụ này đã triển khai tính năng phát quảng cáo tuỳ chỉnh. Phần còn lại của hướng dẫn này sẽ mô tả các tính năng cần thiết để phát quảng cáo tuỳ chỉnh bằng quảng cáo IMA.

Giao diện với VideoAdPlayer

Tính năng phát quảng cáo tuỳ chỉnh yêu cầu ứng dụng của bạn phải triển khai giao diện VideoAdPlayer. SDK sử dụng giao diện này để thông báo cho ứng dụng của bạn phát video quảng cáo. Ứng dụng của bạn cũng sử dụng giao diện này để thông báo cho SDK về các sự kiện quảng cáo dạng video chính. Hãy làm theo các bước sau để triển khai giao diện.

Tạo VideoAdPlayer

Bước đầu tiên là tạo một lớp VideoAdPlayer ẩn danh trong requestAds():

private VideoAdPlayer videoAdPlayer;
...

private void requestAds(String adTagUrl) {
    videoAdPlayer = new VideoAdPlayer() {
    };
}

Thêm phương thức video

Tiếp theo, hãy thêm các phương thức yêu cầu trình phát video phát, tải, dừng và tạm dừng video quảng cáo. Chúng ta cũng thêm các phương thức để phát hành trình phát và lấy âm lượng tại đây:

videoAdPlayer = new VideoAdPlayer() {
        @Override
        public void playAd() {
            if (mIsAdDisplayed) {
                videoPlayer.resume();
            } else {
                isAdDisplayed = true;
                videoPlayer.play();
            }
        }

        @Override
        public void loadAd(String url) {
            isAdDisplayed = true;
            videoPlayer.setVideoPath(url);
        }
        @Override
        public void stopAd() {
            videoPlayer.stopPlayback();
        }
        @Override
        public void pauseAd() {
            videoPlayer.pause();
        }

        @Override
        public void release() {
            // any clean up that needs to be done
        }

        @Override
        public int getVolume() {
            return videoPlayer.getVolume();
        }
};

Các phương thức này là các trình bao bọc mỏng xung quanh các phương thức tương tự của chính trình phát video. Lưu ý rằng các phương thức này sẽ đặt một biến nội bộ dùng để theo dõi xem quảng cáo có hiển thị hay không. Trong chế độ phát quảng cáo tuỳ chỉnh, trình phát video phát cả quảng cáo nội dung dạng video và quảng cáo dạng video. Vì vậy, bạn cần theo dõi quảng cáo nào đang hiển thị.

Tiến trình phát quảng cáo

Giao diện VideoAdPlayer triển khai một giao diện khác là AdProgressProvider, vì vậy, bạn cũng phải triển khai giao diện này. API này chỉ có một phương thức là getAdProgress(). Phương thức này được SDK sử dụng để lấy thông tin phát lại cho quảng cáo. Thêm mã này vào lớp VideoAdPlayer ẩn danh của bạn, bên dưới các phương thức khác:

VideoAdPlayer videoAdPlayer = new VideoAdPlayer() {
        ...
        @Override
        public VideoProgressUpdate getAdProgress() {
            if (!isAdDisplayed || videoPlayer.getDuration() <= 0) {
                return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
            }
            return new VideoProgressUpdate(videoPlayer.getCurrentPosition(),
                    videoPlayer.getDuration());
        }
};

getAdProgress() trả về loại VideoProgressUpdate phải bao gồm vị trí và thời lượng hiện tại của video. Nếu trình phát không phát quảng cáo hoặc không có thời lượng, hãy yêu cầu trình phát trả về VideoProgressUpdate.VIDEO_TIME_NOT_READY như trong ví dụ.

Quản lý các lệnh gọi lại video

Để phát quảng cáo tuỳ chỉnh, ứng dụng của bạn phải thông báo cho SDK về các sự kiện video chính. Từ khung hiển thị của SDK, đây là các lệnh gọi lại do giao diện VideoAdPlayer.VideoAdPlayerCallback mô tả. Trước khi bắt đầu sử dụng các phương thức gọi lại, bạn cần có khả năng thêm và xoá các phương thức gọi lại theo yêu cầu của SDK. Bạn có thể thực hiện việc này bên trong VideoAdPlayer bằng cách sử dụng addCallback()removeCallback():

private List<VideoAdPlayerCallback> adCallbacks = new ArrayList<>(1);

VideoAdPlayer videoAdPlayer = new VideoAdPlayer() {
        ...
        @Override
        public void addCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
            adCallbacks.add(videoAdPlayerCallback);
        }

        @Override
        public void removeCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
            adCallbacks.remove(videoAdPlayerCallback);
        }
};

Cách triển khai này sử dụng List<> cho các lệnh gọi lại để gọi phương thức List<>.add()remove().

Gọi các lệnh gọi lại

Giờ đây, SDK đã có cách để yêu cầu ứng dụng của bạn thêm và xoá lệnh gọi lại, hãy xác định vị trí mà lệnh gọi lại được gọi. Ứng dụng cần gọi những lệnh gọi lại này khi các sự kiện video lớn xảy ra, chẳng hạn như phát, tạm dừng hoặc tiếp tục phát video, hoặc khi một video kết thúc hoặc gặp lỗi.

Để thực hiện việc này, hãy mở rộng SampleVideoPlayer để có trình nghe cho các sự kiện video này được thêm từ VideoFragment. Lý do bạn nên tạo một trình nghe riêng trong SampleVideoPlayer để gọi các lệnh gọi lại quảng cáo này là vì SampleVideoPlayer không biết gì về quảng cáo, vì vậy, bạn phải chuyển tiếp các sự kiện video của trình nghe này đến một trình nghe có thể xử lý quảng cáo.

public interface OnVideoEventsListener {
    void onPlay();
    void onResume();
    void onPause();
    void onError();
}

private final List<OnVideoEventsListener> onVideoEventsListeners = new ArrayList<>(1);

public void addVideoEventsListener(OnVideoEventsListener listener) {
    onVideoEventsListeners.add(listener);
}

Bắt đầu, tạm dừng và tiếp tục

Tạo một enum mới để theo dõi trạng thái phát và thêm các cơ chế ghi đè mới cho phương thức start()pause() trong SampleVideoPlayer:

private enum PlaybackState {
    STOPPED, PAUSED, PLAYING
}

private PlaybackState playbackState = PlaybackState.STOPPED;

@Override
public void start() {
    super.start();
    switch (playbackState) {
        case STOPPED:
            for (OnVideoEventsListener listener : onVideoEventsListeners) {
                listener.onPlay();
            }
            break;
        case PAUSED:
            for (OnVideoEventsListener listener : onVideoEventsListeners) {
                listener.onResume();
            }
            break;
        default:
            // Already playing; do nothing.
            break;
    }
    playbackState = PlaybackState.PLAYING;
}

@Override
public void pause() {
    super.pause();
    playbackState = PlaybackState.PAUSED;
    for (OnVideoEventsListener listener : onVideoEventsListeners) {
        listener.onPause();
    }
}

Xử lý lỗi

Ghi đè trình nghe lỗi ẩn danh của trình phát video mà bạn đã thiết lập trong init():

@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
    playbackState = PlaybackState.STOPPED;
    for (OnVideoEventsListener listener : onVideoEventsListeners) {
        listener.onError();
    }

    // Returning true signals to MediaPlayer that the error was handled.
    // This  prevents the completion handler from being called.
    return true;
}

Triển khai trình nghe

Quay lại VideoFragment và thêm một OnVideoEventsListener ẩn danh vào thực thể SampleVideoPlayer:

mVideoPlayer.addVideoEventsListener(new OnVideoEventsListener() {
    @Override
    public void onPlay() {
        if (isAdDisplayed) {
            for (VideoAdPlayerCallback callback : adCallbacks) {
                callback.onPlay();
            }
        }
    }

    @Override
    public void onResume() {
        if (isAdDisplayed) {
            for (VideoAdPlayerCallback callback : adCallbacks) {
                callback.onResume();
            }
        }
    }

    @Override
    public void onPause() {
        if (isAdDisplayed) {
            for (VideoAdPlayerCallback callback : adCallbacks) {
                callback.onPause();
            }
        }
    }

    @Override
    public void onError() {
        if (isAdDisplayed) {
            for (VideoAdPlayerCallback callback : adCallbacks) {
                callback.onError();
            }
        }
    }
});

Thay đổi phương thức onVideoCompleted() của OnVideoCompletedListener để xử lý trường hợp video quảng cáo đã kết thúc:

public void onVideoCompleted() {
    // Handle completed event for playing post-rolls.
    if (isAdDisplayed) {
        for (VideoAdPlayerCallback callback : adCallbacks) {
            callback.onEnded();
        }
    } else {
        if (adsLoader != null) {
            adsLoader.contentComplete();
    }
}

Chuyển đổi giữa nội dung và quảng cáo

Ví dụ này sử dụng cùng một phiên bản của trình phát video để phát cả nội dung và quảng cáo. Vì vậy, bạn cần thêm một số logic để chuyển đổi giữa nội dung và quảng cáo trong trình phát của mình. Sau đó, bạn có thể tải lại và tìm video nội dung để trở về thời điểm bắt đầu quảng cáo. Thêm 2 hàm để thực hiện việc này:

private int savedContentPosition = 0;

private void pauseContent() {
    savedContentPosition = videoPlayer.getCurrentPosition();
    videoPlayer.stopPlayback();
    isAdDisplayed = true;
}

private void resumeContent() {
    videoPlayer.setVideoPath(getString(R.string.content_url));
    videoPlayer.seekTo(mSavedContentPosition);
    videoPlayer.play();
    isAdDisplayed = false;
}

Các lệnh này được gọi khi hệ thống nhận được các sự kiện CONTENT_PAUSE_REQUESTEDCONTENT_RESUME_REQUESTED lần lượt trong VideoFragment.onAdEvent():

case CONTENT_PAUSE_REQUESTED:
    pauseContent();
    break;
case CONTENT_RESUME_REQUESTED:
    resumeContent();
    break;

Bật tính năng phát quảng cáo tuỳ chỉnh

Bước cuối cùng là cho SDK biết rằng bạn đang sử dụng chế độ phát quảng cáo tuỳ chỉnh. Bạn có thể thực hiện việc này bằng cách truyền VideoAdPlayer vào AdDisplayContainer:

adDisplayContainer.setPlayer(videoAdPlayer);

Bạn cần phải chuyển trình phát của mình cho setPlayer(). Nếu không, SDK sẽ sử dụng chế độ phát do SDK sở hữu.

Vậy là xong. Đó là tất cả các bước cần thiết để thêm chế độ phát quảng cáo tuỳ chỉnh vào hoạt động triển khai IMA của bạn. Bạn có thể so sánh cách triển khai của chính mình với Ví dụ nâng cao trên GitHub nếu gặp vấn đề.