Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.d4rk.androidtutorials.java.ads.preferences;

import android.content.Context;
import android.util.AttributeSet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;

import com.d4rk.androidtutorials.java.R;
import com.d4rk.androidtutorials.java.ads.views.NativeAdBannerView;
import com.google.android.gms.ads.AdRequest;

/**
* Preference that displays a NativeAdBannerView.
*/
public class NativeAdPreference extends Preference {

public NativeAdPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setLayoutResource(R.layout.native_ad_preference);
}

public NativeAdPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}

public NativeAdPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public NativeAdPreference(@NonNull Context context) {
this(context, null);
}

@Override
public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
NativeAdBannerView adView = (NativeAdBannerView) holder.itemView.findViewById(R.id.native_ad_view);
if (adView != null) {
adView.loadAd(new AdRequest.Builder().build());
}
}
}
85 changes: 85 additions & 0 deletions app/src/main/res/layout/android_studio_list_native_ad.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<com.google.android.material.card.MaterialCardView
android:id="@+id/ad_card"
style="@style/Widget.Material3.CardView.Outlined"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.CardViewBottomRounded">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">

<include layout="@layout/ad_attribution" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal"
android:gravity="center_vertical">

<FrameLayout
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginEnd="16dp">

<com.google.android.gms.ads.nativead.MediaView
android:id="@+id/ad_media"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<ImageView
android:id="@+id/ad_app_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout>

<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">

<TextView
android:id="@+id/ad_headline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Material3.TitleSmall" />

<TextView
android:id="@+id/ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Material3.BodySmall" />

<me.zhanghai.android.materialratingbar.MaterialRatingBar
android:id="@+id/ad_stars"
style="@style/Widget.MaterialRatingBar.RatingBar.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isIndicator="true"
android:numStars="5"
android:stepSize="0.5" />
</LinearLayout>

<com.google.android.material.button.MaterialButton
android:id="@+id/ad_call_to_action"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</com.google.android.gms.ads.nativead.NativeAdView>
7 changes: 7 additions & 0 deletions app/src/main/res/layout/native_ad_preference.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<com.d4rk.androidtutorials.java.ads.views.NativeAdBannerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/native_ad_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:nativeAdLayout="@layout/android_studio_list_native_ad" />
1 change: 1 addition & 0 deletions app/src/main/res/xml/preferences_android_studio.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
android:targetPackage="com.d4rk.androidtutorials.java" />
</androidx.preference.Preference>
</androidx.preference.PreferenceCategory>
<com.d4rk.androidtutorials.java.ads.preferences.NativeAdPreference/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Add title or null-check for native ad preference

The newly inserted NativeAdPreference has no title attribute. AndroidStudioFragment.applyFilter assumes every Preference returns a non-null title and calls pref.getTitle().toString() when the search view is used, which now throws a NullPointerException because this ad preference lacks a title. Either give this preference a dummy title or make the filter logic null-safe so searching in the Android Studio lessons screen doesn’t crash.

Useful? React with 👍 / 👎.

<androidx.preference.PreferenceCategory
app:icon="@drawable/ic_category_build_tinted"
app:title="@string/basics">
Expand Down