i want guide me from scratch step by step how to m...
创建于:2026年4月26日
使用 GPT-5.5 Thinking 回答 Chat01
创建于:2026年4月26日
使用 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.
تمام — ده Guide من الصفر لعمل Qt 6 Android app هدفه تختبر AdMob بكل الأنواع، وبعدين تعرف تنقل لـ real ads وتكسب بشكل شرعي. هنتكلم مصري، والكود Java + C++/QML لأن Qt بيحتاج bridge مع Android native SDK.
مهم جدًا: أثناء التطوير استخدم test ads فقط. الضغط على إعلاناتك الحقيقية أو تشجيع الناس تضغط عليها يعتبر invalid traffic وممكن يوقف أو يقفل حسابك. Google بتقول إن النقرات/الانطباعات المصطنعة ممنوعة، وإنك كناشر مسؤول عن جودة الترافيك. (Google Help)
إحنا هنعمل app اسمه مثلًا QtAdMobTest فيه شاشة QML فيها أزرار:
Qt هيعرض الواجهة، وJava هيتعامل مع AdMob SDK لأن Google Mobile Ads SDK رسميًا Android native. Qt بيسمحلك تضيف Java/Kotlin code جوه android/src/... وتبني بالـ Gradle، وده مناسب جدًا للموضوع ده. Qt كمان بيستخدم AndroidManifest وGradle في عملية packaging. (doc.qt.io)
هتحتاج:
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.
من Qt Creator:
File > New ProjectQtAdMobTestAndroid Qt 6.x Clang arm64-v8acom.example.qtadmobtestخلي المشروع Qt Quick/QML عشان الشاشة تبقى سهلة.
في Qt Creator:
ده هيعمل فولدر اسمه:
textandroid/
جواه ملفات زي:
textandroid/AndroidManifest.xml android/build.gradle android/src/
Qt رسميًا بيقول إنك تقدر تخلي Qt Creator ينسخ Android templates للمشروع، وبعدها تحدد QT_ANDROID_PACKAGE_SOURCE_DIR في CMake. (doc.qt.io)
في CMakeLists.txt ضيف السطر ده على target بتاعك:
cmakeset_property(TARGET appQtAdMobTest PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
لو اسم الـ target عندك مختلف، استخدم الاسم اللي Qt عمله.
افتح:
textandroid/build.gradle
ودوّر على dependencies وضيف:
gradleimplementation 'com.google.android.gms:play-services-ads:25.2.0'
Google quick start الرسمي حاليًا بيعرض إن app-level Gradle dependency هي:
gradleimplementation 'com.google.android.gms:play-services-ads:25.2.0'
وبيطلب كمان min SDK 23 أو أعلى وcompile SDK 35 أو أعلى. (Google for Developers)
لو لقيت repositories، اتأكد إن فيها:
gradlegoogle() mavenCentral()
ولو عندك إعدادات min/compile SDK في Qt Creator أو Gradle، خليه كده:
gradleminSdkVersion 23 compileSdkVersion 35
افتح:
textandroid/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"/>
اعمل الملف ده:
textandroid/src/com/example/qtadmobtest/AdMobBridge.java
وحط الكود ده:
javapackage 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; } }); } }
اعمل ملف:
textadmobbridge.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(); };
اعمل ملف:
textadmobbridge.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)
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(); }
افتح Main.qml:
qmlimport 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 } } } }
في CMakeLists.txt، لازم تضيف الملفات:
cmakeqt_add_executable(appQtAdMobTest main.cpp admobbridge.h admobbridge.cpp )
وتتأكد إن عندك:
cmaketarget_link_libraries(appQtAdMobTest PRIVATE Qt6::Quick )
من Qt Creator:
لو حصل crash أول ما التطبيق يفتح، غالبًا السبب واحد من دول:
APPLICATION_ID في manifestcom/example/qtadmobtest/AdMobBridge.javacom/example/qtadmobtest/AdMobBridgeاستخدم IDs دي أثناء التطوير فقط:
| النوع | Test Ad Unit ID |
|---|---|
| App Open | ca-app-pub-3940256099942544/9257395921 |
| Adaptive Banner | ca-app-pub-3940256099942544/9214589741 |
| Fixed Banner | ca-app-pub-3940256099942544/6300978111 |
| Interstitial | ca-app-pub-3940256099942544/1033173712 |
| Rewarded | ca-app-pub-3940256099942544/5224354917 |
| Rewarded Interstitial | ca-app-pub-3940256099942544/5354046379 |
| Native | ca-app-pub-3940256099942544/2247696110 |
| Native Video | ca-app-pub-3940256099942544/1044960115 |
دي demo ad units من Google لاختبار كل format. Android emulators متظبطة تلقائيًا كـ test devices، ولو هتستخدم موبايل حقيقي مع ad unit حقيقي لازم تضيفه test device من AdMob أو programmatically. (Google for Developers)
AdMob بيفرق بين Ad format و Ad type:
| Format | استخدامه |
|---|---|
| Banner | إعلان صغير فوق أو تحت الشاشة. أسهل نوع. |
| Interstitial | شاشة كاملة بين انتقالات طبيعية، مثل بعد إنهاء level. |
| Rewarded | المستخدم يختار يشوف إعلان وياخد reward. |
| Rewarded Interstitial | Full-screen مع reward أثناء انتقال طبيعي. |
| Native Advanced | إعلان شكله شبه تصميم تطبيقك، بس لازم يبقى واضح إنه إعلان. |
| App Open | يظهر عند فتح التطبيق أو الرجوع له، فوق loading screen. |
Google بتوضح إن Banner بيظهر أعلى/أسفل الشاشة، Interstitial full-page في natural breaks، Rewarded بيدي مكافأة، Native بيتخصص في عرض assets بشكل متناسق مع التطبيق، وApp Open بيظهر عند فتح التطبيق أو الرجوع له. (Google Help)
للربح وتجربة محترمة:
ما تحطش interstitial كل ضغطة زر. Google بتنبه إن الإعلانات ماينفعش تتنفذ بطريقة تشجع clicks أو تسبب accidental clicks. (Google Help)
بعد ما تتأكد إن test ads شغالة:
ادخل AdMob واعمل account، وبعدين:
AppsAdd appGoogle بتقول إن أول خطوة للربح من AdMob هي إعداد التطبيق داخل AdMob، وكل التطبيقات الجديدة لازم تعدي app readiness review قبل ما تخدم إعلانات بشكل كامل. (Google Help)
في AndroidManifest.xml بدّل:
xmlandroid:value="ca-app-pub-3940256099942544~3347511713"
بـ App ID الحقيقي بتاعك.
وفي AdMobBridge.java بدّل test ad unit IDs بالـ real ad unit IDs بتاعتك.
عشان التطبيق يبقى ready fully، لازم يبقى منشور وموجود في supported store، ومربوط صح في AdMob. Google بتقول إن app readiness review يبدأ لما التطبيق يبقى published ومربوط بمتجر مدعوم، والمراجعة غالبًا بتاخد 2–3 أيام لكن ممكن أكتر. (Google Help)
من 2025، Google بدأت تطلب verification للتطبيقات الجديدة باستخدام app-ads.txt قبل full ad serving. لازم يكون عندك developer website مضاف في Google Play listing، وتحط ملف app-ads.txt في root بتاع الموقع. (Google Help)
مثال محتوى الملف:
textgoogle.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0
خد السطر الحقيقي من AdMob، مش من المثال. AdMob ممكن ياخد لحد 24 ساعة عشان يزحف ويتحقق من الملف. (Google Help)
لو reporting currency عندك EGP، جدول Google بيقول:
EGP£500EGP£500EGP£5000EGP£500ولو الحساب USD، payment threshold بيبقى $100. القيم بتختلف حسب عملة الحساب. (Google Help)
AdMob بيحسب earnings تقديرية طول الشهر، وبعد بداية الشهر اللي بعده بتتحول لـ finalized earnings. لو رصيدك عدى threshold ومفيش holds، الدفع بيصدر تقريبًا حوالين يوم 21 في الشهر. لو ماوصلتش للـ threshold، الرصيد بيتنقل للشهر اللي بعده. (Google Help)
اعمل كده:
Google بتقول إن UMP SDK بيساعدك تدير privacy choices، وتطلب تحديث consent info عند كل app launch وتعرض consent form لو مطلوب. (Google for Developers)
قبل ما ترفع على Google Play:
ده كده يبقى عندك test app كامل بـ Qt 6 يجرب معظم AdMob formats، وبعدها تقدر تنقل للـ real ads بشكل آمن وقابل للربح.