Jetpack Compose implementation - pubnative/pubnative-hybid-android-sdk GitHub Wiki

Banner

In order to use Banners, we propose creating a composable for the adView, like in the following example:

@Composable
fun AdView(bannerViewModel: BannerViewModel?, adSize: AdSize) {
    val context = LocalContext.current
    bannerViewModel?.createBannerAd(context, adSize)
    if (bannerViewModel?.getAdView() != null) {
        AndroidView(factory = { bannerViewModel.getAdView()!! })
    }
}

Inside the desired screen, the banner should be loaded, passing the intended ZoneId: bannerViewModel?.loadBannerAd("2") (IMPORTANT: Please make sure the ZoneId is the intended one for the AdSize of the placement)

Inside the view model, the banner is held in a variable: private var banner: HyBidAdView? = null

and it is initiated with:

fun createBannerAd(context: Context, adSize: AdSize) { banner = HyBidAdView(context, adSize) }

Then, the view itself is passed using the getAdView() function, as it can be seen in this example: fun getAdView() : HyBidAdView? { return banner }

The following listeners should be added to the view model:

  • HyBidAdView.Listener
  • VideoListener (for MRect Video ads)

A working sample can be found at https://github.com/pubnative/hybid-compose

Native

In order to display native ad inside your composable function , It is recommended that you create all your design components individually inside your composable function with load button

  • when button is clicked ,Call loadPNAD which is defined inside your view model and pass all data via live data once these data is received via live data example : Inside your view model :

private val _creativeIdState = mutableStateOf("")
val creativeIdState: State<String> = _creativeIdState
private val _titleState = mutableStateOf("")
val titleState: State<String> = _titleState
private val _descriptionState = mutableStateOf("")
    val descriptionState: State<String> = _descriptionState

    private val _callToActionState = mutableStateOf("")
    val callToActionState: State<String> = _callToActionState

    private val _bitmapState: MutableState<Bitmap?> = mutableStateOf(null)
    val bitmapState: MutableState<Bitmap?> = _bitmapState

    private val _bitmapURLState = mutableStateOf("")
    val bitmapURLState: State<String> = _bitmapURLState

    private val _iconBitmapState: MutableState<Bitmap?> = mutableStateOf(null)
    val iconBitmapState: MutableState<Bitmap?> = _iconBitmapState

    private val _iconBitmapURLState = mutableStateOf("")
    val iconBitmapURLState: State<String> = _iconBitmapURLState


@Composable
fun loadPNAd() {
    nativeAdRequest?.setPreLoadMediaAssets(true)
    nativeAdRequest?.load("2", this)
}
override fun onRequestSuccess(ad: NativeAd?) {
        ad?.apply {
            creativeId?.let {
                _creativeIdState.value = it
            }
            description?.let {
                _descriptionState.value = it
            }
            callToActionText?.let {
                _callToActionState.value = it
            }
            if (bannerBitmap != null) {
                _bitmapState.value = bannerBitmap
            } else {
                _bitmapURLState.value = bannerUrl
            }
            if (iconBitmap != null) {
                _iconBitmapState.value = iconBitmap
            } else {
                _iconBitmapURLState.value = ad.iconUrl
            }
        }
}

override fun onRequestFail(p0: Throwable?) {
 creativeId?.let {
    _creativeIdState.value = "fail to load"
  }
}

Inside your composable function :

@OptIn(ExperimentalGlideComposeApi::class)
@Composable
private fun AdContent(padding: PaddingValues, nativeViewModel: NativeViewModel?) {

    val creativeId = remember { nativeViewModel?.creativeIdState }
    val title = remember { nativeViewModel?.titleState }
    val description = remember { nativeViewModel?.descriptionState }
    val callToAction = remember { nativeViewModel?.callToActionState }
    val bitmap = remember { nativeViewModel?.bitmapState }
    val bitmapURL = remember { nativeViewModel?.bitmapURLState }
    val icon = remember { nativeViewModel?.iconBitmapState }
    val iconURL = remember { nativeViewModel?.iconBitmapURLState }

    Column(
        modifier = Modifier
            .fillMaxHeight()
            .fillMaxWidth(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(padding),
            horizontalArrangement = Arrangement.Center,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Spacer(modifier = Modifier.padding(0.dp, 55.dp))
            RowButton(txtResource = R.string.load, onClick = {
                nativeViewModel?.loadPNAd()
            })
            Spacer(modifier = Modifier.padding(8.dp))
        }
        Column(
            modifier = Modifier
                .height(300.dp)
                .fillMaxWidth(),
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(padding),
                horizontalArrangement = Arrangement.Start,
            ) {
                GlideImage(
                    model = iconURL?.value,
                    contentDescription = "iconURL",
                    modifier = Modifier
                        .padding(padding)
                        .width(30.dp)
                        .height(30.dp)
                )
                title?.value?.let { Text(text = it) }
            }

            GlideImage(
                model = bitmapURL?.value,
                contentDescription = "BannerURL",
                modifier = Modifier
                    .padding(padding)
                    .fillMaxWidth()
                    .height(100.dp)
            )
        }
    }
}

It is recommended to use Glide instead of Picasso because it has compose support

⚠️ **GitHub.com Fallback** ⚠️