VideoAdView
:
This is the Custom View for video playback and sending tracking events.
This can be allocated directly in the layout file.
VideoAdActivity
:
Activities displayed on the full screen.
As with VideoAdView
, video playback and tracking event transmission is performed, but the number of video playback control functions are increased.
Use the SDK VideoAdActivity
to support full-screen display with video SDK. Register this with AndroidManifest.xml
.
<activity android:name="jp.fout.rfp.android.sdk.video.VideoAdActivity" />
In case of video advertising, RFPInstreamInfoModel#isVideo()
returns true
. You can use this to judge whether there is any video advertising or not.
private boolean isAd(int position) {
return getItem(position) instanceof RFPInstreamInfoModel;
}
private boolean isVideoAd(int position) {
if (!isAd(position)) {
return false;
}
RFPInstreamInfoModel item = (RFPInstreamInfoModel) getItem(position);
return item.isVideo();
}
Detailed information on video advertising is stored in RFPInstreamInfoModel
, and based on this, it is necessary to process in VideoAdView
to assemble video advertisements.
In the actual implementation, the RFPInstreamInfoModel
instance is transferred to VideoAdView#processAd()
.
static class AdViewHolder {
TextView advertiserName;
TextView adText;
ImageView adImage;
TextView adSponsoredLabel;
VideoAdView adVideo;
AdViewHolder(View convertView) {
advertiserName = (TextView) convertView.findViewById(R.id.custom_instream_advertiser_name);
adText = (TextView) convertView.findViewById(R.id.custom_instream_ad_text);
adImage = (ImageView) convertView.findViewById(R.id.custom_instream_ad_image);
adSponsoredLabel = (TextView) convertView.findViewById(R.id.custom_instream_sponsor_name);
adVideo = (VideoAdView) convertView.findViewById(R.id.custom_instream_video_view);
}
void setData(RFPInstreamInfoModel adData) {
advertiserName.setText(adData.title());
adText.setText(adData.content());
String displayedAdvertiser = adData.displayedAdvertiser();
if (null != displayedAdvertiser && 0 < displayedAdvertiser.length()) {
adSponsoredLabel.setText(displayedAdvertiser);
}
adVideo.processAd(adData);
}
}
The text for the button located in the video advertising can be set from the advertising management screen.
This set value can be obtained from RFPInstreamInfoModel#cta_text()
.
static class AdViewHolder {
// ... ...
Button adButton;
AdViewHolder(View convertView) {
// ... ...
adButton = (Button) convertView.findViewById(R.id.custom_instream_action_button);
}
void setData(RFPInstreamInfoModel adData) {
// ... ...
String adButtonText = adData.cta_text();
if (adButtonText != null && adButtonText.length() > 0) {
adButton.setText(adButtonText);
}
adVideo.processAd(adData);
}
}
This calls VideoAdView#processAd()
, and playback starts automatically once video playback is possible.
By setting VideoAdView#setAutoStart(false)
, it is possible to control automatic playback. In this case, it is necessary to call VideoAdView#play()
from the app and start playback. Furthermore, by calling VideoAdView#pause()
, it is possible to stop at any point.
Tap the video area to move to full-screen display.
This behavior is the default action, and when full-screen mode ends, additional implementation is required if you want to synchronize the video playback position when full-screen mode ends.
Full-screen mode is an Activity, so to carry on the playback position and tracking event transmission mode, transfer the results with Activity#startActivityForResult()
and Activity#onActivityResult()
.
As VideoAdView
calls OnFullscreenRequestListener#onRequestFullscreen()
when moving to full-screen mode, this is implemented. As the target ‘VideoAdView” and the intent to take over the information are passed as arguments, Activity#startActivityForResult()
is called based on this. Use RFP.getVideoAdFullscreenRequestCode()
as the request code for the Activity.
By using VideoAdView#restore(Intent)
, it is possible to carry over the playback position and the tracking event transmission state.
It is necessary to know VideoAdView
for which the Activity is VideoAdView#restore(Intent)
, but by implementing VideoAdView.OnFullscreenRequestListener
, which is the full screen callback for VideoAdView
, this can be notified as an Activity.
In the following example, greenrobot/EventBus is used to notify and save VideoAdView
as an Activity.
class VideoAdViewHolder extends RecyclerView.ViewHolder
implements VideoAdView.OnFullscreenRequestListener {
RFPInstreamAdPlacer adPlacer;
VideoAdView adVideo;
VideoAdViewHolder(View itemView, RFPInstreamAdPlacer placer) {
super(itemView);
adPlacer = placer;
// ... ...
adVideo = (VideoAdView) itemView.findViewById(R.id.custom_instream_ad_image);
adVideo.setOnFullscreenRequestListener(this);
}
@Override
public void onRequestFullscreen(VideoAdView view, Intent intent) {
EventBus.getDefault().post(new RequestFullscreenEvent(view, intent));
}
}
VideoAdView mSourceVideoAdView = null;
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRequestFullscreen(RequestFullscreenEvent event) {
mSourceVideoAdView = event.view;
startActivityForResult(event.intent, RFP.getVideoAdFullscreenRequestCode());
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RFP.getVideoAdFullscreenRequestCode()
&& resultCode == Activity.RESULT_OK
&& mSourceVideoAdView != null) {
mSourceVideoAdView.restore(data);
}
}
The RFP#getVideoAdFullscreenRequestCode()
default value is 18416
, and by using RFP#setVideoAdFullscreenRequestCode(int)
, this can be changed to any value.
RFP.setVideoAdFullscreenRequestCode(1000);
When controlling automatic playback using VideoAdView#setAutoStart()
, it is necessary to call VideoAdView#play()
on recovery.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RFP.getVideoAdFullscreenRequestCode()
&& resultCode == Activity.RESULT_OK
&& mSourceVideoAdView != null) {
mSourceVideoAdView.restore(data);
mSourceVideoAdView.play();
}
}
When transitioning to full-screen mode, and moving to the landing page with the action button, this must be stopped in order to retrieve the tracking event correctly.
The transition to full-screen mode and the action button within full-screen mode are all handled correctly within SDK, but for the action button within the feed for control on the app side, it is necessary to describe the video stop processing. Describe VideoAdView#pause()
as either Activity#onStop()
or Activity#onPause()
when utilizing onClick`.
VideoAdView adVideo = (VideoAdView) itemView.findViewById(R.id.custom_instream_ad_image);
Button adButton = (Button) itemView.findViewById(R.id.custom_instream_ad_action_button);
adButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
adVideo.pause();
adPlacer.sendClickEvent(adData);
}
});
By default, tap video area to move to full-screen display, you can customize this behavior via VideoAdView#setOnVideoAreaClickListener(OnClickLisner)
.
An example for customizing video area tap behavior below:
RFPInstreamAdPlacer adPlacer;
VideoAdViewHolder(View itemView, RFPInstreamAdPlacer placer) {
super(itemView);
adPlacer = placer;
}
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == ITEM_VIEW_TYPE_AD_VIDEO) {
final VideoAdViewHolder h = (VideoAdViewHolder) holder;
final RFPInstreamInfoModel model = (RFPInstreamInfoModel) mModels.get(position);
h.adVideoView.setOnVideoAreaClickListener(new OnClickListener() {
public void onClick(View v) {
h.adVideoView.pause();
adPlacer.sendClickEvent(model);
}
}
} else {
// ... ...
}
}
When an error occurs on loading video advertisements, you can describe and control the error processing.
Implement VideoAdView#OnErrorListener
within the feed, and set the listener with VideoAdView#setOnErrorListener()
.
static class AdViewHolder implements VideoAdView.OnErrorListener {
VideoAdView adVideo;
VideoAdViewHolder(View itemView, RFPInstreamAdPlacer placer) {
super(itemView);
// ... ...
adVideo = (VideoAdView) itemView.findViewById(R.id.custom_instream_ad_image);
adVideo.setOnErrorListener(this);
}
@Override
public void onError(VideoAdView view, String message, @Nullable Throwable t) {
// view: VideoAdView in which error occurred
// message: Error content
// t: relevant exception where an exception has occurred
Log.d(TAG, message, t);
}
}
Where an error occurs in full screen, the activity is ended and RESULT_CANCELED
is found in the onActivityResult()
resultCode
. It is possible to describe error processing by judging based on this. In such a case, the error content can be found in Intent
.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RFP.getVideoAdFullscreenRequestCode()) {
if (resultCode == Activity.RESULT_OK) {
// Normal processing
} else if (resultCode == Activity.RESULT_CANCELED) {
// Processing on errors
String message = data.getStringExtra("error_message");
Throwable t = (Throwable) data.getSerializableExtra("error");
Log.d(TAG, message, t);
}
}
}
RFP can store a certain amount of video advertisements within the internal storage cache area.
For the cache capacity, use the setting values recommended by RFP. This value can be changed from the app side.
int size = RFP.getVideoCacheSize(); //Returns the current setting value
RFP.setVideoCacheSize(50); // Uses 50 MB as the cache area
RFP.setVideoCacheSize(0); // Disables the cache
SDK does not save video’s state when it’s detached from its parent view. This behavior is the default action and additional implementation is needed if you want to synchronize the video playback position when it’s reattach to the parent view.
When VideoAdView
is detached from its parent view, by implementing VideoAdView#OnDetachedListener
will get VideoAdView
’s Bundle information for synchronize.
When VideoAdView
is reattach to the parent view, please pass the stored Bundle to VideoAdView#processAd(RFPInstreamInfoModel adModel, @Nullable Bundle savedState)
for taking over the playback state.
// store ad's information for resume
private SparseArray<Bundle> mResumeVideosArray = new SparseArray<>();
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == ITEM_VIEW_TYPE_AD_VIDEO) {
final VideoAdViewHolder h = (VideoAdViewHolder) holder;
final RFPInstreamInfoModel model = (RFPInstreamInfoModel) mModels.get(position);
// get resume ad's information if exist
Bundle state = mResumeVideosArray.get(position);
// remove ad's old information if exist
mResumeVideosArray.remove(position);
// reset ad's information when it's detached from window
h.adVideoView.setOnDetachedListener(bundle -> mResumeVideosArray.put(position, bundle));
h.setData(adInfo, null, state);
} else {
// ... ...
}
}
static class AdViewHolder {
VideoAdView adVideo;
// ... ...
AdViewHolder(View convertView) {
adVideo = (VideoAdView) itemView.findViewById(R.id.custom_instream_ad_image);
// ... ...
}
void setData(RFPInstreamInfoModel adData, Bundle savedState) {
// ... ...
// restart ad from the position when being detached
adVideo.processAd(adData, savedState);
}