הפעלת מודעות בהתאמה אישית באמצעות IMA SDK ל-Android

הדרך המהירה והפשוטה ביותר לשלב את IMA SDK ל-Android באפליקציה היא להשתמש ב-SDK בכל הלוגיקה של הפעלת מודעות, בזמן שהאפליקציה מתמקדת בהפעלת תוכן וידאו. הגישה הזו, שנקראת 'הפעלת מודעות בבעלות ה-SDK', היא אפשרות ברירת המחדל בקטע תחילת העבודה.

עם זאת, אם אתם רוצים להפעיל מודעות גם בנגן הווידאו, תוכלו לעשות זאת באמצעות ה-SDK. אנחנו מתייחסים לגישה הזו כ "הפעלת מודעות מותאמות אישית", ושאר המדריך שלנו מסביר על אופן השימוש בה.

דרישות מוקדמות

  • שילוב בסיסי של IMA.

אם אין לכם כרגע שילוב בסיסי של IMA, מומלץ לבחון את הדוגמה המתקדמת ב-github. הדוגמה הזו כבר מיישמת הפעלה של מודעות בהתאמה אישית. בהמשך המדריך מתוארות התכונות הנדרשות להפעלת מודעות מותאמות אישית עם מודעות IMA.

ממשק עם VideoAdPlayer

כדי להפעיל מודעות בהתאמה אישית, צריך להטמיע באפליקציה את ממשק VideoAdPlayer. ה-SDK משתמש בממשק הזה כדי להודיע לאפליקציה להפעיל סרטונים של מודעות. האפליקציה משתמשת בממשק הזה גם כדי לעדכן את ה-SDK לגבי אירועים גדולים של מודעות וידאו. כדי להטמיע את הממשק, פועלים לפי השלבים הבאים.

יצירת VideoAdPlayer

השלב הראשון הוא ליצור מחלקה אנונימית של VideoAdPlayer ב-requestAds():

private VideoAdPlayer videoAdPlayer;
...

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

הוספת שיטות וידאו

בשלב הבא, מוסיפים שיטות שינחו את נגן הווידאו להפעיל, לטעון, לעצור ולהשהות סרטונים של מודעות. אנחנו גם מוסיפים את השיטות לשחרור הנגן ולקבל את עוצמת הקול כאן:

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();
        }
};

השיטות האלה יוצרות wrappers דקות שעולות על השיטות הדומות של נגן הווידאו שלכם. שימו לב שהשיטות האלה מגדירות משתנה פנימי שמשמש למעקב אחרי הצגת המודעה. בהפעלת מודעות מותאמת אישית, נגן הווידאו מפעיל גם מודעות וידאו וגם מודעות וידאו, כך שעליך לעקוב אחרי התוכן שמוצג כרגע.

התקדמות הפעלת המודעה

בממשק VideoAdPlayer מוטמע ממשק אחר, AdProgressProvider, לכן צריך להטמיע גם אותו. יש לו רק שיטה אחת, getAdProgress(), שמשמשת את ה-SDK לקבלת פרטי הפעלה של מודעות. מוסיפים אותו לכיתה VideoAdPlayer האנונימית, מתחת לשיטות האחרות:

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() מחזירה סוג VideoProgressUpdate, שחייב לכלול את המיקום הנוכחי של הסרטון ואת משך הזמן שלו. אם הנגן לא מפעיל מודעה או שמשך הזמן לא זמין, צריך להחזיר אותו VideoProgressUpdate.VIDEO_TIME_NOT_READY כפי שמוצג בדוגמה.

ניהול שיחות וידאו חוזרות

כדי להפעיל מודעות מותאמות אישית, האפליקציה שלך צריכה לעדכן את ה-SDK לגבי אירועים משמעותיים בסרטונים. בתצוגה של ה-SDK, מדובר בקריאות חוזרות (callback) שמתוארות בממשק של VideoAdPlayer.VideoAdPlayerCallback. כדי לעבור לשיטות הקריאה החוזרות (callback) עצמן, צריכה להיות לכם יכולת להוסיף ולהסיר את הקריאות החוזרות לפי בקשת ה-SDK. ניתן לעשות זאת בתוך VideoAdPlayer באמצעות 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);
        }
};

בהטמעה הזו נעשה שימוש ב-List<> עבור הקריאות החוזרות (callback) שאליהן צריך לקרוא את השיטות List<>.add() ו-remove().

התקשרות חזרה

עכשיו, אחרי שיש ל-SDK אפשרות להורות לאפליקציה להוסיף קריאות חוזרות או להסיר אותן, אתם יכולים להגדיר את המקומות שבהם אתם קוראים לקריאה חוזרת (callback). האפליקציה צריכה להפעיל את הקריאות החוזרות (callback) האלה כשמתרחשים אירועי וידאו משמעותיים, כמו הפעלה, השהיה או המשך הפעלה של סרטון, או במקרה של הודעת שגיאה או סיום של סרטון.

לשם כך, אפשר להרחיב את SampleVideoPlayer כך שאירועי הווידאו האלה יוסיפו מאזין ל-VideoFragment. הסיבה להגדרת מאזין נפרד ב-SampleVideoPlayer לבצע קריאה חוזרת של מודעות מהסוג הזה היא שאין ל-SampleVideoPlayer מידע על מודעות, ולכן עליך להעביר את אירועי הסרטון שלו לגורם שיכול להתמודד עם מודעות.

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);
}

התחלה, השהיה והמשך

אפשר ליצור טיפוסים בני מנייה (enum) חדש כדי לעקוב אחר מצב ההפעלה ולהוסיף שינויים חדשים לשיטות הבידינג start() ו-pause() ב-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();
    }
}

טיפול בשגיאות

שינוי השדה 'מאזין שגיאות אנונימיות' של נגן הווידאו שהגדרת ב-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;
}

הטמעת הכלי listener

חוזרים אל VideoFragment ומוסיפים OnVideoEventsListener אנונימי למכונה של 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();
            }
        }
    }
});

משנים את השיטה onVideoCompleted() של OnVideoCompletedListener כדי לטפל במקרה שבו סרטון המודעה הסתיים:

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

מעבר בין תוכן למודעות

בדוגמה הזו נעשה שימוש באותו מופע של נגן הווידאו להפעלת תוכן וגם מודעות, ולכן צריך להוסיף לוגיקה כלשהי כדי לעבור בין התוכן למודעות בנגן. לאחר מכן תוכלו לטעון מחדש ולחפש את הסרטון בתוכן כדי לחזור לנקודה שבה המודעה התחילה. לשם כך, הוסיפו שתי פונקציות:

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;
}

מתבצעת הפעלה של האירועים האלה כשהאירועים CONTENT_PAUSE_REQUESTED ו-CONTENT_RESUME_REQUESTED מתקבלים, ב-VideoFragment.onAdEvent(), בהתאמה:

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

מתן אפשרות להפעלה של מודעות בהתאמה אישית

השלב האחרון הוא להודיע ל-SDK שאתם משתמשים בהפעלת מודעות בהתאמה אישית. פעולה זו מתבצעת על ידי העברת VideoAdPlayer אל AdDisplayContainer:

adDisplayContainer.setPlayer(videoAdPlayer);

חובה להעביר את הנגן שלך אל setPlayer(). אחרת, ה-SDK משתמש בהפעלה בבעלות ה-SDK.

זה הכול. אלה כל השלבים הנדרשים להוספת הפעלה מותאמת אישית של מודעות להטמעת ה-IMA. אם אתם נתקלים בבעיה, תוכלו להשוות בין ההטמעה שלכם לבין הדוגמה המתקדמת ב-GitHub.