i want guide me from scratch step by step how to m...

Создано: 26 апреля 2026 г.

Отвечено с использованием GPT-5.5 Thinking от Chat01

Вопрос

i want guide me from scratch step by step how to make a mobile app using qt6 to test admob, and tell me how to show real ads and earn money and also show me all ads types and try it on app. in egyptian

note: i want each step has details what.

Мысль

undefined

Мысль

undefined

Мысль

undefined

Мысль

Balancing code details with clarity

I need to provide the solution in Egyptian Arabic and include citations. The full code might be too lengthy, so I could offer a "working skeleton" instead. Since the code will be long, I'll use collapsible sections with markdown headings. Citations are necessary for setup steps but not for the raw code, which can be concise. There's a small issue with loadAppOpen, and I need to handle FrameLayout in the NativeAd code correctly.

Thought for 1m 29s

Ответ

تمام — ده Guide من الصفر لعمل Qt 6 Android app هدفه تختبر AdMob بكل الأنواع، وبعدين تعرف تنقل لـ real ads وتكسب بشكل شرعي. هنتكلم مصري، والكود Java + C++/QML لأن Qt بيحتاج bridge مع Android native SDK.

مهم جدًا: أثناء التطوير استخدم test ads فقط. الضغط على إعلاناتك الحقيقية أو تشجيع الناس تضغط عليها يعتبر invalid traffic وممكن يوقف أو يقفل حسابك. Google بتقول إن النقرات/الانطباعات المصطنعة ممنوعة، وإنك كناشر مسؤول عن جودة الترافيك. (Google Help)


1) الفكرة العامة

إحنا هنعمل app اسمه مثلًا QtAdMobTest فيه شاشة QML فيها أزرار:

  • Show Banner
  • Load / Show Interstitial
  • Load / Show Rewarded
  • Load / Show Rewarded Interstitial
  • Load / Show App Open
  • Load / Show Native

Qt هيعرض الواجهة، وJava هيتعامل مع AdMob SDK لأن Google Mobile Ads SDK رسميًا Android native. Qt بيسمحلك تضيف Java/Kotlin code جوه android/src/... وتبني بالـ Gradle، وده مناسب جدًا للموضوع ده. Qt كمان بيستخدم AndroidManifest وGradle في عملية packaging. (doc.qt.io)


2) نزّل الأدوات المطلوبة

هتحتاج:

  1. Qt 6 + Qt Creator
  2. اختار component اسمه Qt for Android
  3. JDK
  4. Android SDK
  5. Android NDK
  6. Android SDK Build Tools
  7. موبايل Android أو Emulator

Qt الرسمي بيقول إن تطوير Android محتاج JDK وAndroid command line tools، واللي تشمل NDK وSDK Platform وBuild Tools وPlatform Tools، وأسهل طريقة إنك تستخدم Android setup wizard جوه Qt Creator. (doc.qt.io)

من Qt Creator:

Edit > Preferences > Devices > Android

بعدها دوس setup / auto-detect، وخليه يظبط JDK / SDK / NDK.


3) اعمل مشروع Qt جديد

من Qt Creator:

  1. File > New Project
  2. اختار: Application > Qt Quick Application
  3. الاسم: QtAdMobTest
  4. Build system: CMake
  5. Kit: اختار Android kit مثل:
    • Android Qt 6.x Clang arm64-v8a
  6. خلّي الـ package name مثلًا:
    • com.example.qtadmobtest

خلي المشروع Qt Quick/QML عشان الشاشة تبقى سهلة.


4) جهّز Android package templates

في Qt Creator:

  1. افتح تبويب Projects
  2. اختار Android kit
  3. دور على Build Android APK
  4. دوس Create Templates

ده هيعمل فولدر اسمه:

text
android/

جواه ملفات زي:

text
android/AndroidManifest.xml android/build.gradle android/src/

Qt رسميًا بيقول إنك تقدر تخلي Qt Creator ينسخ Android templates للمشروع، وبعدها تحدد QT_ANDROID_PACKAGE_SOURCE_DIR في CMake. (doc.qt.io)

في CMakeLists.txt ضيف السطر ده على target بتاعك:

cmake
set_property(TARGET appQtAdMobTest PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")

لو اسم الـ target عندك مختلف، استخدم الاسم اللي Qt عمله.


5) إعداد Gradle عشان AdMob SDK

افتح:

text
android/build.gradle

ودوّر على dependencies وضيف:

gradle
implementation 'com.google.android.gms:play-services-ads:25.2.0'

Google quick start الرسمي حاليًا بيعرض إن app-level Gradle dependency هي:

gradle
implementation 'com.google.android.gms:play-services-ads:25.2.0'

وبيطلب كمان min SDK 23 أو أعلى وcompile SDK 35 أو أعلى. (Google for Developers)

لو لقيت repositories، اتأكد إن فيها:

gradle
google() mavenCentral()

ولو عندك إعدادات min/compile SDK في Qt Creator أو Gradle، خليه كده:

gradle
minSdkVersion 23 compileSdkVersion 35

6) إعداد AndroidManifest

افتح:

text
android/AndroidManifest.xml

داخل <application> ضيف App ID التجريبي:

xml
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-3940256099942544~3347511713"/>

ده sample AdMob app ID الرسمي للاختبار. Google بتقول لازم تضيف com.google.android.gms.ads.APPLICATION_ID في الـ manifest، ولو مش موجود التطبيق ممكن يعمل crash برسالة Missing application ID. (Google for Developers)

خارج <application>، جوه <manifest>، ضيف permissions دي:

xml
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

7) اعمل Java bridge لـ AdMob

اعمل الملف ده:

text
android/src/com/example/qtadmobtest/AdMobBridge.java

وحط الكود ده:

java
package com.example.qtadmobtest; import android.app.Activity; import android.graphics.Color; import android.os.Handler; import android.os.Looper; import android.view.Gravity; import android.view.View; import android.widget.Button; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import java.lang.ref.WeakReference; import com.google.android.gms.ads.AdListener; import com.google.android.gms.ads.AdLoader; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.AdSize; import com.google.android.gms.ads.AdView; import com.google.android.gms.ads.FullScreenContentCallback; import com.google.android.gms.ads.LoadAdError; import com.google.android.gms.ads.MobileAds; import com.google.android.gms.ads.appopen.AppOpenAd; import com.google.android.gms.ads.interstitial.InterstitialAd; import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback; import com.google.android.gms.ads.rewarded.RewardedAd; import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback; import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAd; import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAdLoadCallback; import com.google.android.gms.ads.nativead.NativeAd; import com.google.android.gms.ads.nativead.NativeAdView; public class AdMobBridge { private static WeakReference<Activity> activityRef; private static final Handler mainHandler = new Handler(Looper.getMainLooper()); // Test IDs من Google private static final String TEST_BANNER = "ca-app-pub-3940256099942544/6300978111"; private static final String TEST_INTERSTITIAL = "ca-app-pub-3940256099942544/1033173712"; private static final String TEST_REWARDED = "ca-app-pub-3940256099942544/5224354917"; private static final String TEST_REWARDED_INTERSTITIAL = "ca-app-pub-3940256099942544/5354046379"; private static final String TEST_APP_OPEN = "ca-app-pub-3940256099942544/9257395921"; private static final String TEST_NATIVE = "ca-app-pub-3940256099942544/2247696110"; private static AdView bannerView; private static InterstitialAd interstitialAd; private static RewardedAd rewardedAd; private static RewardedInterstitialAd rewardedInterstitialAd; private static AppOpenAd appOpenAd; private static NativeAd nativeAd; private static View nativeContainer; private static Activity activity() { return activityRef == null ? null : activityRef.get(); } public static void initialize(Activity activity) { activityRef = new WeakReference<>(activity); // Google بيفضل initialization مرة واحدة عند بداية التطبيق. new Thread(() -> MobileAds.initialize(activity, status -> {})).start(); mainHandler.post(() -> Toast.makeText(activity, "AdMob initialized", Toast.LENGTH_SHORT).show() ); } public static void showBanner() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; hideBanner(); FrameLayout root = a.findViewById(android.R.id.content); bannerView = new AdView(a); bannerView.setAdSize(AdSize.BANNER); bannerView.setAdUnitId(TEST_BANNER); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT ); params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; root.addView(bannerView, params); bannerView.loadAd(new AdRequest.Builder().build()); }); } public static void hideBanner() { mainHandler.post(() -> { if (bannerView != null) { if (bannerView.getParent() instanceof FrameLayout) { ((FrameLayout) bannerView.getParent()).removeView(bannerView); } bannerView.destroy(); bannerView = null; } }); } public static void loadInterstitial() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; InterstitialAd.load( a, TEST_INTERSTITIAL, new AdRequest.Builder().build(), new InterstitialAdLoadCallback() { @Override public void onAdLoaded(InterstitialAd ad) { interstitialAd = ad; Toast.makeText(a, "Interstitial loaded", Toast.LENGTH_SHORT).show(); } @Override public void onAdFailedToLoad(LoadAdError error) { interstitialAd = null; Toast.makeText(a, "Interstitial failed: " + error.getMessage(), Toast.LENGTH_LONG).show(); } } ); }); } public static void showInterstitial() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; if (interstitialAd == null) { Toast.makeText(a, "Load interstitial first", Toast.LENGTH_SHORT).show(); return; } interstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() { @Override public void onAdDismissedFullScreenContent() { interstitialAd = null; loadInterstitial(); } }); interstitialAd.show(a); }); } public static void loadRewarded() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; RewardedAd.load( a, TEST_REWARDED, new AdRequest.Builder().build(), new RewardedAdLoadCallback() { @Override public void onAdLoaded(RewardedAd ad) { rewardedAd = ad; Toast.makeText(a, "Rewarded loaded", Toast.LENGTH_SHORT).show(); } @Override public void onAdFailedToLoad(LoadAdError error) { rewardedAd = null; Toast.makeText(a, "Rewarded failed: " + error.getMessage(), Toast.LENGTH_LONG).show(); } } ); }); } public static void showRewarded() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; if (rewardedAd == null) { Toast.makeText(a, "Load rewarded first", Toast.LENGTH_SHORT).show(); return; } rewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() { @Override public void onAdDismissedFullScreenContent() { rewardedAd = null; loadRewarded(); } }); rewardedAd.show(a, rewardItem -> { String msg = "Reward earned: " + rewardItem.getAmount() + " " + rewardItem.getType(); Toast.makeText(a, msg, Toast.LENGTH_LONG).show(); }); }); } public static void loadRewardedInterstitial() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; RewardedInterstitialAd.load( a, TEST_REWARDED_INTERSTITIAL, new AdRequest.Builder().build(), new RewardedInterstitialAdLoadCallback() { @Override public void onAdLoaded(RewardedInterstitialAd ad) { rewardedInterstitialAd = ad; Toast.makeText(a, "Rewarded interstitial loaded", Toast.LENGTH_SHORT).show(); } @Override public void onAdFailedToLoad(LoadAdError error) { rewardedInterstitialAd = null; Toast.makeText(a, "Rewarded interstitial failed: " + error.getMessage(), Toast.LENGTH_LONG).show(); } } ); }); } public static void showRewardedInterstitial() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; if (rewardedInterstitialAd == null) { Toast.makeText(a, "Load rewarded interstitial first", Toast.LENGTH_SHORT).show(); return; } rewardedInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() { @Override public void onAdDismissedFullScreenContent() { rewardedInterstitialAd = null; loadRewardedInterstitial(); } }); rewardedInterstitialAd.show(a, rewardItem -> { String msg = "Reward earned: " + rewardItem.getAmount() + " " + rewardItem.getType(); Toast.makeText(a, msg, Toast.LENGTH_LONG).show(); }); }); } public static void loadAppOpen() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; AppOpenAd.load( a, TEST_APP_OPEN, new AdRequest.Builder().build(), new AppOpenAd.AppOpenAdLoadCallback() { @Override public void onAdLoaded(AppOpenAd ad) { appOpenAd = ad; Toast.makeText(a, "App open loaded", Toast.LENGTH_SHORT).show(); } @Override public void onAdFailedToLoad(LoadAdError error) { appOpenAd = null; Toast.makeText(a, "App open failed: " + error.getMessage(), Toast.LENGTH_LONG).show(); } } ); }); } public static void showAppOpen() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; if (appOpenAd == null) { Toast.makeText(a, "Load app open first", Toast.LENGTH_SHORT).show(); return; } appOpenAd.setFullScreenContentCallback(new FullScreenContentCallback() { @Override public void onAdDismissedFullScreenContent() { appOpenAd = null; loadAppOpen(); } }); appOpenAd.show(a); }); } public static void loadNative() { mainHandler.post(() -> { Activity a = activity(); if (a == null) return; AdLoader adLoader = new AdLoader.Builder(a, TEST_NATIVE) .forNativeAd(ad -> { if (nativeAd != null) { nativeAd.destroy(); } nativeAd = ad; showNativeView(a, ad); Toast.makeText(a, "Native loaded", Toast.LENGTH_SHORT).show(); }) .withAdListener(new AdListener() { @Override public void onAdFailedToLoad(LoadAdError error) { Toast.makeText(a, "Native failed: " + error.getMessage(), Toast.LENGTH_LONG).show(); } }) .build(); adLoader.loadAd(new AdRequest.Builder().build()); }); } private static void showNativeView(Activity a, NativeAd ad) { FrameLayout root = a.findViewById(android.R.id.content); if (nativeContainer != null && nativeContainer.getParent() instanceof FrameLayout) { ((FrameLayout) nativeContainer.getParent()).removeView(nativeContainer); } NativeAdView adView = new NativeAdView(a); LinearLayout box = new LinearLayout(a); box.setOrientation(LinearLayout.VERTICAL); box.setPadding(24, 18, 24, 18); box.setBackgroundColor(Color.WHITE); TextView adBadge = new TextView(a); adBadge.setText("Ad"); adBadge.setTextColor(Color.BLACK); adBadge.setTextSize(12); TextView headline = new TextView(a); headline.setTextColor(Color.BLACK); headline.setTextSize(18); headline.setText(ad.getHeadline()); TextView body = new TextView(a); body.setTextColor(Color.DKGRAY); body.setTextSize(14); body.setText(ad.getBody() == null ? "" : ad.getBody()); Button cta = new Button(a); cta.setText(ad.getCallToAction() == null ? "Open" : ad.getCallToAction()); box.addView(adBadge); box.addView(headline); box.addView(body); box.addView(cta); adView.addView(box); adView.setHeadlineView(headline); adView.setBodyView(body); adView.setCallToActionView(cta); adView.setNativeAd(ad); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT ); params.gravity = Gravity.TOP; nativeContainer = adView; root.addView(adView, params); } public static void hideNative() { mainHandler.post(() -> { if (nativeContainer != null && nativeContainer.getParent() instanceof FrameLayout) { ((FrameLayout) nativeContainer.getParent()).removeView(nativeContainer); } nativeContainer = null; if (nativeAd != null) { nativeAd.destroy(); nativeAd = null; } }); } }

8) اعمل C++ bridge عشان QML ينادي Java

اعمل ملف:

text
admobbridge.h
cpp
#pragma once #include <QObject> class AdMobBridge : public QObject { Q_OBJECT public: explicit AdMobBridge(QObject *parent = nullptr); Q_INVOKABLE void initialize(); Q_INVOKABLE void showBanner(); Q_INVOKABLE void hideBanner(); Q_INVOKABLE void loadInterstitial(); Q_INVOKABLE void showInterstitial(); Q_INVOKABLE void loadRewarded(); Q_INVOKABLE void showRewarded(); Q_INVOKABLE void loadRewardedInterstitial(); Q_INVOKABLE void showRewardedInterstitial(); Q_INVOKABLE void loadAppOpen(); Q_INVOKABLE void showAppOpen(); Q_INVOKABLE void loadNative(); Q_INVOKABLE void hideNative(); };

اعمل ملف:

text
admobbridge.cpp
cpp
#include "admobbridge.h" #include <QDebug> #ifdef Q_OS_ANDROID #include <QJniObject> #include <QNativeInterface> #endif static const char *JAVA_CLASS = "com/example/qtadmobtest/AdMobBridge"; AdMobBridge::AdMobBridge(QObject *parent) : QObject(parent) {} void AdMobBridge::initialize() { #ifdef Q_OS_ANDROID auto activity = QNativeInterface::QAndroidApplication::context(); QJniObject::callStaticMethod<void>( JAVA_CLASS, "initialize", "(Landroid/app/Activity;)V", activity.object<jobject>() ); #else qDebug() << "AdMob only works on Android in this sample."; #endif } void AdMobBridge::showBanner() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "showBanner", "()V"); #endif } void AdMobBridge::hideBanner() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "hideBanner", "()V"); #endif } void AdMobBridge::loadInterstitial() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "loadInterstitial", "()V"); #endif } void AdMobBridge::showInterstitial() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "showInterstitial", "()V"); #endif } void AdMobBridge::loadRewarded() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "loadRewarded", "()V"); #endif } void AdMobBridge::showRewarded() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "showRewarded", "()V"); #endif } void AdMobBridge::loadRewardedInterstitial() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "loadRewardedInterstitial", "()V"); #endif } void AdMobBridge::showRewardedInterstitial() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "showRewardedInterstitial", "()V"); #endif } void AdMobBridge::loadAppOpen() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "loadAppOpen", "()V"); #endif } void AdMobBridge::showAppOpen() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "showAppOpen", "()V"); #endif } void AdMobBridge::loadNative() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "loadNative", "()V"); #endif } void AdMobBridge::hideNative() { #ifdef Q_OS_ANDROID QJniObject::callStaticMethod<void>(JAVA_CLASS, "hideNative", "()V"); #endif }

Qt 6 عنده QNativeInterface::QAndroidApplication::context() اللي بيرجع Android context، ولو Activity الحالية موجودة بيرجع Activity. (doc.qt.io)


9) سجّل الـ bridge في main.cpp

افتح main.cpp وخليه بالشكل ده تقريبًا:

cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "admobbridge.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; AdMobBridge admob; engine.rootContext()->setContextProperty("AdMob", &admob); QObject::connect( &engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection ); engine.loadFromModule("QtAdMobTest", "Main"); return app.exec(); }

10) اعمل شاشة QML لتجربة كل الإعلانات

افتح Main.qml:

qml
import QtQuick import QtQuick.Controls import QtQuick.Layouts ApplicationWindow { width: 420 height: 760 visible: true title: "Qt 6 AdMob Test" Component.onCompleted: { AdMob.initialize() } ScrollView { anchors.fill: parent ColumnLayout { width: parent.width spacing: 12 Label { text: "Qt 6 + AdMob Test" font.pixelSize: 24 Layout.alignment: Qt.AlignHCenter padding: 16 } Button { text: "Show Banner" Layout.fillWidth: true onClicked: AdMob.showBanner() } Button { text: "Hide Banner" Layout.fillWidth: true onClicked: AdMob.hideBanner() } Button { text: "Load Interstitial" Layout.fillWidth: true onClicked: AdMob.loadInterstitial() } Button { text: "Show Interstitial" Layout.fillWidth: true onClicked: AdMob.showInterstitial() } Button { text: "Load Rewarded" Layout.fillWidth: true onClicked: AdMob.loadRewarded() } Button { text: "Show Rewarded" Layout.fillWidth: true onClicked: AdMob.showRewarded() } Button { text: "Load Rewarded Interstitial" Layout.fillWidth: true onClicked: AdMob.loadRewardedInterstitial() } Button { text: "Show Rewarded Interstitial" Layout.fillWidth: true onClicked: AdMob.showRewardedInterstitial() } Button { text: "Load App Open" Layout.fillWidth: true onClicked: AdMob.loadAppOpen() } Button { text: "Show App Open" Layout.fillWidth: true onClicked: AdMob.showAppOpen() } Button { text: "Load Native" Layout.fillWidth: true onClicked: AdMob.loadNative() } Button { text: "Hide Native" Layout.fillWidth: true onClicked: AdMob.hideNative() } Label { text: "مهم: دول test ads. ما تستخدمش real ads في debug." wrapMode: Text.WordWrap padding: 16 Layout.fillWidth: true } } } }

11) اتأكد إن الملفات داخلة في CMake

في CMakeLists.txt، لازم تضيف الملفات:

cmake
qt_add_executable(appQtAdMobTest main.cpp admobbridge.h admobbridge.cpp )

وتتأكد إن عندك:

cmake
target_link_libraries(appQtAdMobTest PRIVATE Qt6::Quick )

12) اعمل Build وشغّل على موبايل أو Emulator

من Qt Creator:

  1. اختار Android kit
  2. وصل موبايلك وفعّل USB debugging
  3. دوس Run

لو حصل crash أول ما التطبيق يفتح، غالبًا السبب واحد من دول:

  • نسيت APPLICATION_ID في manifest
  • package path غلط:
    com/example/qtadmobtest/AdMobBridge.java
  • class name في C++ مش مطابق: com/example/qtadmobtest/AdMobBridge
  • Gradle dependency ناقص
  • compile SDK أقل من 35 أو min SDK أقل من 23

13) Test Ad Unit IDs لكل الأنواع

استخدم IDs دي أثناء التطوير فقط:

النوعTest Ad Unit ID
App Openca-app-pub-3940256099942544/9257395921
Adaptive Bannerca-app-pub-3940256099942544/9214589741
Fixed Bannerca-app-pub-3940256099942544/6300978111
Interstitialca-app-pub-3940256099942544/1033173712
Rewardedca-app-pub-3940256099942544/5224354917
Rewarded Interstitialca-app-pub-3940256099942544/5354046379
Nativeca-app-pub-3940256099942544/2247696110
Native Videoca-app-pub-3940256099942544/1044960115

دي demo ad units من Google لاختبار كل format. Android emulators متظبطة تلقائيًا كـ test devices، ولو هتستخدم موبايل حقيقي مع ad unit حقيقي لازم تضيفه test device من AdMob أو programmatically. (Google for Developers)


14) أنواع الإعلانات في AdMob

AdMob بيفرق بين Ad format و Ad type:

  • Ad format: الإعلان هيظهر إزاي وفين جوه التطبيق.
  • Ad type: محتوى الإعلان نفسه، زي text/image/rich media/video/interactive. (Google Help)

Ad formats

Formatاستخدامه
Bannerإعلان صغير فوق أو تحت الشاشة. أسهل نوع.
Interstitialشاشة كاملة بين انتقالات طبيعية، مثل بعد إنهاء level.
Rewardedالمستخدم يختار يشوف إعلان وياخد reward.
Rewarded InterstitialFull-screen مع reward أثناء انتقال طبيعي.
Native Advancedإعلان شكله شبه تصميم تطبيقك، بس لازم يبقى واضح إنه إعلان.
App Openيظهر عند فتح التطبيق أو الرجوع له، فوق loading screen.

Google بتوضح إن Banner بيظهر أعلى/أسفل الشاشة، Interstitial full-page في natural breaks، Rewarded بيدي مكافأة، Native بيتخصص في عرض assets بشكل متناسق مع التطبيق، وApp Open بيظهر عند فتح التطبيق أو الرجوع له. (Google Help)


15) إمتى تستخدم كل نوع؟

للربح وتجربة محترمة:

  • Banner: شاشة home أو قائمة ثابتة.
  • Interstitial: بعد ما المستخدم يخلص action، مش في نص استخدامه.
  • Rewarded: أفضل نوع لو عندك coins / hints / unlock feature.
  • Rewarded Interstitial: استخدمه بحذر، ولازم المستخدم يفهم المكافأة.
  • Native: في feeds أو lists، بس لازم label واضح “Ad”.
  • App Open: عند start/resume فقط، مش كل شوية.

ما تحطش interstitial كل ضغطة زر. Google بتنبه إن الإعلانات ماينفعش تتنفذ بطريقة تشجع clicks أو تسبب accidental clicks. (Google Help)


16) إزاي تشغل real ads وتكسب فلوس؟

بعد ما تتأكد إن test ads شغالة:

A) اعمل حساب AdMob

ادخل AdMob واعمل account، وبعدين:

  1. Apps
  2. Add app
  3. اختار Android
  4. لو التطبيق لسه مش منشور، اختار Unpublished
  5. خد AdMob App ID
  6. اعمل ad units لكل نوع:
    • Banner
    • Interstitial
    • Rewarded
    • Native
    • App Open

Google بتقول إن أول خطوة للربح من AdMob هي إعداد التطبيق داخل AdMob، وكل التطبيقات الجديدة لازم تعدي app readiness review قبل ما تخدم إعلانات بشكل كامل. (Google Help)

B) بدّل IDs

في AndroidManifest.xml بدّل:

xml
android:value="ca-app-pub-3940256099942544~3347511713"

بـ App ID الحقيقي بتاعك.

وفي AdMobBridge.java بدّل test ad unit IDs بالـ real ad unit IDs بتاعتك.

C) انشر التطبيق

عشان التطبيق يبقى ready fully، لازم يبقى منشور وموجود في supported store، ومربوط صح في AdMob. Google بتقول إن app readiness review يبدأ لما التطبيق يبقى published ومربوط بمتجر مدعوم، والمراجعة غالبًا بتاخد 2–3 أيام لكن ممكن أكتر. (Google Help)

D) اعمل app-ads.txt

من 2025، Google بدأت تطلب verification للتطبيقات الجديدة باستخدام app-ads.txt قبل full ad serving. لازم يكون عندك developer website مضاف في Google Play listing، وتحط ملف app-ads.txt في root بتاع الموقع. (Google Help)

مثال محتوى الملف:

text
google.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0

خد السطر الحقيقي من AdMob، مش من المثال. AdMob ممكن ياخد لحد 24 ساعة عشان يزحف ويتحقق من الملف. (Google Help)


17) الدفع في مصر

لو reporting currency عندك EGP، جدول Google بيقول:

  • Verification threshold: EGP£500
  • Payment method threshold: EGP£500
  • Payment threshold: EGP£5000
  • Cancellation threshold: EGP£500

ولو الحساب USD، payment threshold بيبقى $100. القيم بتختلف حسب عملة الحساب. (Google Help)

AdMob بيحسب earnings تقديرية طول الشهر، وبعد بداية الشهر اللي بعده بتتحول لـ finalized earnings. لو رصيدك عدى threshold ومفيش holds، الدفع بيصدر تقريبًا حوالين يوم 21 في الشهر. لو ماوصلتش للـ threshold، الرصيد بيتنقل للشهر اللي بعده. (Google Help)


18) أهم قواعد الأمان عشان حسابك مايتقفلش

اعمل كده:

  • استخدم test ads أثناء التطوير.
  • ما تضغطش على إعلان حقيقي في تطبيقك.
  • ما تقولش للناس “اضغطوا عشان تدعموني”.
  • ما تعرضش interstitial فجأة في أماكن تسبب ضغطات بالغلط.
  • ما تستخدمش bot traffic أو installs وهمية.
  • راقب AdMob reports حسب country / ad unit / app screen.
  • حط privacy policy واضحة.
  • لو بتستهدف أطفال، لازم تظبط إعدادات child-directed treatment.
  • استخدم UMP consent لو عندك مستخدمين في مناطق محتاجة privacy consent.

Google بتقول إن UMP SDK بيساعدك تدير privacy choices، وتطلب تحديث consent info عند كل app launch وتعرض consent form لو مطلوب. (Google for Developers)


19) Checklist قبل النشر

قبل ما ترفع على Google Play:

  • Test ads شغالة لكل format.
  • مفيش crash في startup.
  • App ID الحقيقي في Manifest.
  • Real ad unit IDs موجودة في release build فقط.
  • التطبيق منشور public.
  • AdMob app مربوط بالـ Play Store listing.
  • app-ads.txt موجود ومتحقق منه.
  • Privacy policy موجودة.
  • الإعلانات مش بتغطي أزرار مهمة.
  • Interstitial في natural breaks فقط.
  • Rewarded ads بتدي reward فعلي وواضح.
  • Native ads عليها label واضح “Ad”.
  • App open ads مش بتظهر كل مرة بشكل مزعج.

ده كده يبقى عندك test app كامل بـ Qt 6 يجرب معظم AdMob formats، وبعدها تقدر تنقل للـ real ads بشكل آمن وقابل للربح.

Поделиться этим Q&A