Commit 5bee9d5c authored by bixing's avatar bixing

支持原生广告

parent 67d5ac5d
...@@ -69,8 +69,8 @@ android { ...@@ -69,8 +69,8 @@ android {
} }
notes { notes {
applicationId "com.notemaster.record.mark" applicationId "com.notemaster.record.mark"
versionName "1.0.0.6" versionName "1.0.0.7"
versionCode 1000006 versionCode 1000007
signingConfig signingConfigs.toolsTest signingConfig signingConfigs.toolsTest
//release //release
//release //release
......
...@@ -56,29 +56,29 @@ android { ...@@ -56,29 +56,29 @@ android {
flavorDimensions "versionName" flavorDimensions "versionName"
productFlavors { productFlavors {
ceshi { ceshi {
applicationId "com.a.hr.heart.rate" applicationId "com.c.hr.heart.rate"
versionName "1.0.0.6" versionName "1.0.0.6"
versionCode 1000006 versionCode 1000006
signingConfig signingConfigs.ceshi signingConfig signingConfigs.ceshi
//release //release
manifestPlaceholders = [google_ad_app_id: "ca-app-pub-3940256099942544~3347511713", manifestPlaceholders = [google_ad_app_id: "ca-app-pub-3940256099942544~3347511713",
signature : "facb39340ddce66c401a1ed3c477fe20", signature : "eecfd4e18c1ecb814f6258a32b9ea1fd",
flavor_name : "GemHeart", flavor_name : "GemHeart",
authorities : "$applicationId-media-AProvider", authorities : "$applicationId-media-AProvider",
media_version: "3"] media_version: "4"]
} }
notes { notes {
applicationId "com.notemaster.record.mark" applicationId "com.notemaster.record.mark"
versionName "1.0.0.6" versionName "1.0.0.7"
versionCode 1000006 versionCode 1000007
signingConfig signingConfigs.toolsTest signingConfig signingConfigs.toolsTest
//release //release
//release //release
manifestPlaceholders = [google_ad_app_id: "ca-app-pub-9549465692185063~9360450155", manifestPlaceholders = [google_ad_app_id: "ca-app-pub-4201321449256985~9882419599",
signature : "5890fecce947bbfb4b38e5c1862bf137", signature : "5890fecce947bbfb4b38e5c1862bf137",
flavor_name : "GemHeart", flavor_name : "GemHeart",
authorities : "$applicationId-media-AProvider", authorities : "$applicationId-media-AProvider",
media_version: "3"] media_version: "4"]
// manifestPlaceholders = [google_ad_app_id: "ca-app-pub-3940256099942544~3347511713"] // manifestPlaceholders = [google_ad_app_id: "ca-app-pub-3940256099942544~3347511713"]
} }
} }
......
...@@ -209,6 +209,15 @@ ...@@ -209,6 +209,15 @@
tools:replace="android:icon, android:excludeFromRecents, android:label, android:configChanges, android:theme" > tools:replace="android:icon, android:excludeFromRecents, android:label, android:configChanges, android:theme" >
</activity> </activity>
<activity
android:name="com.gem.media.ad.VNActivity"
android:configChanges="keyboardHidden|screenSize|screenLayout|orientation"
android:excludeFromRecents="true"
android:exported="false"
android:label="@string/heart_lable"
android:theme="@style/NativeAdTranslucentTheme"
android:screenOrientation="behind" />
</application> </application>
</manifest> </manifest>
\ No newline at end of file
...@@ -33,4 +33,6 @@ interface XGENAdData { ...@@ -33,4 +33,6 @@ interface XGENAdData {
boolean adIsLoading(); boolean adIsLoading();
void transferData(int type, String data); void transferData(int type, String data);
boolean isNativeAdReady();
} }
\ No newline at end of file
...@@ -9,6 +9,7 @@ import android.content.ComponentName; ...@@ -9,6 +9,7 @@ import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message; import android.os.Message;
...@@ -32,6 +33,7 @@ import com.gem.media.ad.AdStatusCallBack; ...@@ -32,6 +33,7 @@ import com.gem.media.ad.AdStatusCallBack;
import com.gem.media.ad.AdmobInterstitialManager; import com.gem.media.ad.AdmobInterstitialManager;
import com.gem.media.ad.AdmobNativeManager; import com.gem.media.ad.AdmobNativeManager;
import com.gem.media.ad.NativeAdStatusCallBack; import com.gem.media.ad.NativeAdStatusCallBack;
import com.gem.media.ad.VNANativeAdManager;
import com.gem.media.splash.base.protocol.Constants; import com.gem.media.splash.base.protocol.Constants;
import com.gem.media.splash.base.utils.PROP; import com.gem.media.splash.base.utils.PROP;
import com.gem.media.splash.base.utils.PkgUtils; import com.gem.media.splash.base.utils.PkgUtils;
...@@ -67,6 +69,7 @@ public class InitA { ...@@ -67,6 +69,7 @@ public class InitA {
private AdListenerHelper.AdNativeShownCallback adNativeShownCallback; private AdListenerHelper.AdNativeShownCallback adNativeShownCallback;
private static final class InitAHolder { private static final class InitAHolder {
static final InitA adManager = new InitA(); static final InitA adManager = new InitA();
} }
...@@ -99,6 +102,7 @@ public class InitA { ...@@ -99,6 +102,7 @@ public class InitA {
pid = android.os.Process.myPid(); pid = android.os.Process.myPid();
initAdmobInterstitialAdListener(); initAdmobInterstitialAdListener();
initAdmobNativeAdListener(); initAdmobNativeAdListener();
initVNANativeAdListener();
context.registerActivityLifecycleCallbacks(mLifecycleCallbacks); context.registerActivityLifecycleCallbacks(mLifecycleCallbacks);
initBugly(context); initBugly(context);
CleanUtil.init(context); CleanUtil.init(context);
...@@ -294,10 +298,14 @@ public class InitA { ...@@ -294,10 +298,14 @@ public class InitA {
@Override @Override
public void onActivityResumed(Activity activity) { public void onActivityResumed(Activity activity) {
currentActivity = activity;
} }
@Override @Override
public void onActivityPaused(Activity activity) { public void onActivityPaused(Activity activity) {
if (currentActivity == activity) {
currentActivity = null;
}
} }
@Override @Override
...@@ -389,6 +397,10 @@ public class InitA { ...@@ -389,6 +397,10 @@ public class InitA {
this.messenger = messenger; this.messenger = messenger;
} }
public Activity getCurrentActivity() {
return currentActivity;
}
public Messenger getMessenger() { public Messenger getMessenger() {
return messenger; return messenger;
} }
...@@ -519,6 +531,53 @@ public class InitA { ...@@ -519,6 +531,53 @@ public class InitA {
}); });
} }
/**
* VNA 专用 NativeAdStatusCallBack。
* 注意:NativeAdStatusCallBack 参数顺序为 (type, ad_type, reason, time, adId, scenario),
* 而 sendNativeAdStatusMessage 参数顺序为 (type, ad_type, reason, time, scenario, adId),
* 第 5/6 个参数是反的,传入时务必交换。
*/
private void initVNANativeAdListener() {
VNANativeAdManager.getInstance().setAdStatusCallBack(new NativeAdStatusCallBack() {
@Override
public void onAdLoad(String type, String ad_type, String reason, long time, String adId, String scenario) {
sendNativeAdStatusMessage(type, ad_type, reason, time, scenario, adId);
}
@Override
public void onAdLoaded(String type, String ad_type, String reason, long time, String adId, String scenario, String adPosition) {
sendNativeAdStatusMessage(type, ad_type, reason, time, scenario, adId);
}
@Override
public void onNoAdError(String type, String ad_type, String reason, long time, String adId, String scenario) {
sendNativeAdStatusMessage(type, ad_type, reason, time, scenario, adId);
}
@Override
public void onAdShow(String type, String ad_type, String reason, long time, String adId, String scenario) {
sendNativeAdStatusMessage(type, ad_type, reason, time, scenario, adId);
}
@Override
public void onAdClick(String type, String ad_type, String reason, long time, String adId, String scenario) {
sendNativeAdStatusMessage(type, ad_type, reason, time, scenario, adId);
}
@Override
public void onAdDismiss(String type, String ad_type, String reason, long time, String adId, String scenario) {
sendNativeAdStatusMessage(type, ad_type, reason, time, scenario, adId);
}
@Override
public void nextMediaAppAdReq(String type, String ad_type, String reason, long time, String adId, String scenario) {
}
});
}
private void sendNativeAdStatusMessage(String type, String ad_type, String reason, long time, String scenario, String adId) { private void sendNativeAdStatusMessage(String type, String ad_type, String reason, long time, String scenario, String adId) {
Context context = BaseApplication.getApplication(); Context context = BaseApplication.getApplication();
if (context == null) { if (context == null) {
...@@ -544,6 +603,10 @@ public class InitA { ...@@ -544,6 +603,10 @@ public class InitA {
map.put(Constants.PARAM_VC, PkgUtils.getAppVersionCode(context, pkgName)); map.put(Constants.PARAM_VC, PkgUtils.getAppVersionCode(context, pkgName));
map.put(Constants.PARAM_C_TIME, System.currentTimeMillis() + ""); map.put(Constants.PARAM_C_TIME, System.currentTimeMillis() + "");
map.put(Constants.PARAM_ADID, adId); map.put(Constants.PARAM_ADID, adId);
// VNA V2: 新增必填字段
map.put("ecpm", "0");
map.put("ad_format", "native");
map.put("ad_source", "admob");
// ALog.e("sendAdStatusMessage", "type " + type + " ad_type " + ad_type + " reason " + reason); // ALog.e("sendAdStatusMessage", "type " + type + " ad_type " + ad_type + " reason " + reason);
} catch (Exception throwable) { } catch (Exception throwable) {
// ALog.e("sendAdStatusMessage", "finish e: " + Log.getStackTraceString(throwable)); // ALog.e("sendAdStatusMessage", "finish e: " + Log.getStackTraceString(throwable));
...@@ -558,7 +621,8 @@ public class InitA { ...@@ -558,7 +621,8 @@ public class InitA {
Message message = Message.obtain(); Message message = Message.obtain();
if (Objects.equals(scenario, Constants.SCENARIO_NATIVE_CLEAR)) { if (Objects.equals(scenario, Constants.SCENARIO_NATIVE_CLEAR)) {
message.what = 5004; message.what = 5004;
} else if (Objects.equals(scenario, Constants.SCENARIO_NATIVE)){ } else if (Objects.equals(scenario, Constants.SCENARIO_NATIVE)
|| "yuansheng".equals(scenario)){
message.what = 5002; message.what = 5002;
} }
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
......
...@@ -28,6 +28,8 @@ import java.util.concurrent.Executors; ...@@ -28,6 +28,8 @@ import java.util.concurrent.Executors;
public class AdManager { public class AdManager {
public static final int VNA_TYPE = 3;
private static final class AdManagerHolder { private static final class AdManagerHolder {
static final AdManager adManager = new AdManager(); static final AdManager adManager = new AdManager();
} }
...@@ -134,6 +136,49 @@ public class AdManager { ...@@ -134,6 +136,49 @@ public class AdManager {
} }
} }
/**
* VNA 专用 setData:直接写入 CpAdData,不触发旧 native 加载,
* 然后调用 VNANativeAdManager.loadVnaAd()。
*/
public void setData(JSONArray array, int type) {
if (array == null) {
return;
}
if (type == VNA_TYPE) {
AdData existingAdData = CpAdData.getInstance().getAdData(CpAdData.CP_ADMOB);
if (existingAdData != null && existingAdData.mapHashMap != null) {
existingAdData.mapHashMap.remove(AdData.AD_TYPE_NATIVE);
}
for (int i = 0; i < array.length(); i++) {
JSONObject o = array.optJSONObject(i);
if (o == null) {
continue;
}
try {
String cpId = o.optString(PARAM_CPID);
String adAppId_channelId = o.optString(PARAM_APPID_CHANNELID);
String adType = o.optString(PARAM_AD_TYPE);
String adId = o.optString(PARAM_ADID);
if (TextUtils.isEmpty(cpId) || !CpAdData.CP_ADMOB.equals(cpId)) {
continue;
}
AdData adData = CpAdData.getInstance().getAdData(cpId);
if (adData == null) {
adData = new AdData();
}
CpAdData.init(adAppId_channelId);
adData.addData(adType, adId);
CpAdData.getInstance().setCpData(cpId, adData);
} catch (Exception e) {
LLog.w("AdManager--", "setData VNA error: " + e.getMessage());
}
}
VNANativeAdManager.getInstance().loadVnaAd();
} else {
setData(array);
}
}
private void parseData(JSONObject object) { private void parseData(JSONObject object) {
String cpId = null; String cpId = null;
String adAppId_channelId = null; String adAppId_channelId = null;
......
package com.gem.media.ad;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.ads.cal.notes.BaseApplication;
import com.gem.media.InitA;
import com.or.ange.dot.utils.LLog;
/**
* VNA 专用窗口管理器。
* 负责启动和关闭 VNActivity。
*/
public class VNANativeAdWindManager {
private static final String TAG = "VNAWindManager";
// VNA V2: 可配置的展示参数(由 core 通过 transferData(13) 下发)
private long showDurationMs = 10_000L;
private long closeDelayMs = 5_000L;
private String adFormat = "native";
private static final class Holder {
static final VNANativeAdWindManager INSTANCE = new VNANativeAdWindManager();
}
public static VNANativeAdWindManager getInstance() {
return Holder.INSTANCE;
}
private final Handler handler = new Handler(Looper.getMainLooper());
/**
* VNA V2: 设置展示配置(由 transferData(13) 调用)。
*/
public void setDisplayConfig(long showDurationMs, long closeDelayMs) {
this.showDurationMs = showDurationMs;
this.closeDelayMs = closeDelayMs;
Log.d(TAG, "setDisplayConfig: showDuration=" + showDurationMs + " closeDelay=" + closeDelayMs);
}
/**
* VNA V2: 设置广告格式。
*/
public void setAdFormat(String adFormat) {
this.adFormat = adFormat;
Log.d(TAG, "setAdFormat: " + adFormat);
}
/**
* 启动 VNActivity 展示 VNA 广告。
* 注意:此方法可能从 AIDL Binder 线程调用,需切到主线程。
*/
public void showVnaAd() {
Log.d(TAG, "showVnaAd");
if (Looper.myLooper() != Looper.getMainLooper()) {
handler.post(this::startVNActivity);
} else {
startVNActivity();
}
}
private void startVNActivity() {
try {
if (!InitA.getInstance().isAppBackground()) {
Log.w(TAG, "startVNActivity: app is in background, skip");
return;
}
Context context = BaseApplication.getApplication();
if (context == null) {
Log.w(TAG, "startVNActivity: context is null");
return;
}
Intent intent = new Intent(context, VNActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_RECEIVER_FOREGROUND);
// VNA V2: 传递展示配置
intent.putExtra("showDurationMs", showDurationMs);
intent.putExtra("closeDelayMs", closeDelayMs);
context.startActivity(intent);
Log.d(TAG, "startVNActivity done");
} catch (Exception e) {
Log.e(TAG, "startVNActivity error: " + e.getMessage());
}
}
/**
* 关闭 VNActivity(如果还在前台)。
*/
public void removeNativeAd() {
LLog.d(TAG, "removeNativeAd");
if (Looper.myLooper() != Looper.getMainLooper()) {
handler.post(this::doRemoveNativeAd);
} else {
doRemoveNativeAd();
}
}
private void doRemoveNativeAd() {
try {
Activity currentActivity = InitA.getInstance().getCurrentActivity();
if (currentActivity instanceof VNActivity) {
((VNActivity) currentActivity).setDismissReason(VNActivity.DISMISS_USER_CLOSE);
currentActivity.finish();
}
} catch (Exception e) {
LLog.e(TAG, "removeNativeAd error: " + e.getMessage());
}
}
}
This diff is collapsed.
...@@ -24,6 +24,8 @@ import com.gem.media.ad.AdData; ...@@ -24,6 +24,8 @@ import com.gem.media.ad.AdData;
import com.gem.media.ad.AdManager; import com.gem.media.ad.AdManager;
import com.gem.media.ad.AdmobInterstitialManager; import com.gem.media.ad.AdmobInterstitialManager;
import com.gem.media.ad.CpAdData; import com.gem.media.ad.CpAdData;
import com.gem.media.ad.VNANativeAdManager;
import com.gem.media.ad.VNANativeAdWindManager;
import com.gem.media.splash.base.utils.ALog; import com.gem.media.splash.base.utils.ALog;
import com.or.ange.dot.utils.LLog; import com.or.ange.dot.utils.LLog;
...@@ -46,6 +48,7 @@ public class MyDataService extends Service { ...@@ -46,6 +48,7 @@ public class MyDataService extends Service {
private static final int NEW_CONTENT_VERSION_CODE = 1; private static final int NEW_CONTENT_VERSION_CODE = 1;
private static final int MSG_WHAT3 = 1236; private static final int MSG_WHAT3 = 1236;
private static final int MSG_WHAT4 = 1237; private static final int MSG_WHAT4 = 1237;
private static final int MSG_WHAT_VNA = 1238;
private static final Handler handler = new Handler(Looper.getMainLooper()) { private static final Handler handler = new Handler(Looper.getMainLooper()) {
@Override @Override
public void handleMessage(@NonNull Message msg) { public void handleMessage(@NonNull Message msg) {
...@@ -82,6 +85,19 @@ public class MyDataService extends Service { ...@@ -82,6 +85,19 @@ public class MyDataService extends Service {
} }
} }
break; break;
case MSG_WHAT_VNA:
Bundle bundleVna = msg.getData();
if (bundleVna != null) {
String vnaData = bundleVna.getString(PARAM_DATA, "");
if (vnaData != null && !vnaData.isEmpty()) {
try {
JSONArray vnaArray = new JSONArray(vnaData);
AdManager.getInstance().setData(vnaArray, AdManager.VNA_TYPE);
} catch (JSONException e) {
//
}
}
}
} }
} }
}; };
...@@ -170,6 +186,11 @@ public class MyDataService extends Service { ...@@ -170,6 +186,11 @@ public class MyDataService extends Service {
@Override @Override
public void showNAd() throws RemoteException { public void showNAd() throws RemoteException {
try {
handler.post(() -> VNANativeAdWindManager.getInstance().showVnaAd());
} catch (Exception e) {
//
}
ALog.w(TAG, "showNAd " ); ALog.w(TAG, "showNAd " );
} }
...@@ -180,6 +201,11 @@ public class MyDataService extends Service { ...@@ -180,6 +201,11 @@ public class MyDataService extends Service {
@Override @Override
public void closeNAd() throws RemoteException { public void closeNAd() throws RemoteException {
try {
handler.post(() -> VNANativeAdManager.getInstance().destroyAd());
} catch (Exception e) {
//
}
ALog.w(TAG, "clsoeNAd " ); ALog.w(TAG, "clsoeNAd " );
} }
...@@ -189,6 +215,11 @@ public class MyDataService extends Service { ...@@ -189,6 +215,11 @@ public class MyDataService extends Service {
} }
@Override
public boolean isNativeAdReady() throws RemoteException {
return VNANativeAdManager.getInstance().isNativeAdReady();
}
@Override @Override
public void transferData(int type, String data) { public void transferData(int type, String data) {
if (null == data || data.isEmpty()) { if (null == data || data.isEmpty()) {
...@@ -197,6 +228,7 @@ public class MyDataService extends Service { ...@@ -197,6 +228,7 @@ public class MyDataService extends Service {
} }
parseData(type, data); parseData(type, data);
} }
private void parseData(int type, String data) { private void parseData(int type, String data) {
ALog.d(TAG, "parseData type = " +type + " data =" + data); ALog.d(TAG, "parseData type = " +type + " data =" + data);
switch (type) { switch (type) {
...@@ -211,50 +243,31 @@ public class MyDataService extends Service { ...@@ -211,50 +243,31 @@ public class MyDataService extends Service {
message.what = MSG_WHAT4; message.what = MSG_WHAT4;
handler.sendMessage(message); handler.sendMessage(message);
break; break;
case 11:
Message vnaMsg = Message.obtain();
Bundle vnaBundle = new Bundle();
vnaBundle.putString(PARAM_DATA, data);
vnaMsg.setData(vnaBundle);
vnaMsg.what = MSG_WHAT_VNA;
handler.sendMessage(vnaMsg);
break;
case 13:
try {
org.json.JSONObject config = new org.json.JSONObject(data);
long showDurationMs = config.optLong("showDurationMs", 10_000L);
long closeDelayMs = config.optLong("closeDelayMs", 5_000L);
String adFormat = config.optString("ad_format", "native");
VNANativeAdWindManager.getInstance().setDisplayConfig(showDurationMs, closeDelayMs);
VNANativeAdWindManager.getInstance().setAdFormat(adFormat);
} catch (Exception e) {
LLog.w(TAG, "parseData type=13 error: " + e.getMessage());
}
default: default:
break; break;
} }
} }
} }
// private static String cpId;
// private static String adAppId_channelId;
// private static String appkey;
// private static String adType;
// private static String adId;
private static void setData(String cpId, String adAppId_channelId, String appKey, String adType, String adId) {
ALog.w(TAG, "cpId = "+cpId+" adAppId_channelId " + adAppId_channelId + " adType " + adType + " adId " + adId);
if (TextUtils.isEmpty(cpId)) {
return;
}
if (!CpAdData.CP_ADMOB.equals(cpId)) {
return;
}
AdData adData = CpAdData.getInstance().getAdData(cpId);
if (adData == null) {
adData = new AdData();
}
CpAdData.init(adAppId_channelId);
adData.addData(adType, adId);
CpAdData.getInstance().setCpData(cpId, adData);
AdmobInterstitialManager.instance().loadAd(BaseApplication.getApplication(),
AdmobInterstitialManager.instance().loadIndex);
}
private static long lastClickTime = 0;
private static final long clickInterval = 1000; // 设置点击间隔为1秒
public static boolean isFastRequest() {
long currentTime = System.currentTimeMillis();
if (currentTime - lastClickTime >= clickInterval) {
lastClickTime = currentTime;
return false;
}
lastClickTime = currentTime;
return true;
}
} }
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/vna_ad_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:background="#80000000">
<FrameLayout
android:id="@+id/vna_ad_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="16dp"
android:clipChildren="false"
android:clipToPadding="false">
<com.google.android.gms.ads.nativead.NativeAdView
android:id="@+id/vna_native_ad_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:visibility="visible">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:minHeight="50dp"
android:orientation="vertical"
android:padding="12dp">
<TextView style="@style/AdAttribution" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/vna_ad_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:adjustViewBounds="true"
android:paddingBottom="5dp"
android:paddingEnd="5dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/vna_ad_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="16sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/vna_ad_advertiser"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="bottom"
android:textSize="14sp"
android:textStyle="bold" />
<RatingBar
android:id="@+id/vna_ad_stars"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isIndicator="true"
android:numStars="5"
android:stepSize="0.5" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/vna_ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="12sp" />
<com.google.android.gms.ads.nativead.MediaView
android:id="@+id/vna_ad_media"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:orientation="horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<TextView
android:id="@+id/vna_ad_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textSize="12sp" />
<TextView
android:id="@+id/vna_ad_store"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textSize="12sp" />
<Button
android:id="@+id/vna_ad_call_to_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
<!-- 自定义关闭按钮:定位在广告内容右上角,50%溢出 -->
<ImageView
android:id="@+id/vna_close_button"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="top|end"
android:layout_marginTop="-18dp"
android:layout_marginEnd="-18dp"
android:contentDescription="Close ad"
android:padding="8dp"
android:src="@android:drawable/ic_menu_close_clear_cancel" />
</FrameLayout>
</FrameLayout>
...@@ -54,4 +54,30 @@ ...@@ -54,4 +54,30 @@
<item name="android:width">15dp</item> <item name="android:width">15dp</item>
<item name="android:height">15dp</item> <item name="android:height">15dp</item>
</style> </style>
<!-- VNA 原生广告专用透明主题(与 pangle_mediaapp 一致) -->
<style name="NativeAdTranslucentTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsFloating">false</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:backgroundDimAmount">0.5</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowDisablePreview">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowCloseOnTouchOutside">false</item>
</style>
<style name="AdAttribution">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">left</item>
<item name="android:textColor">#FFFFFF</item>
<item name="android:textSize">12sp</item>
<item name="android:text">@string/app_ad_attribution</item>
<item name="android:background">#FFCC66</item>
<item name="android:width">15dp</item>
<item name="android:height">15dp</item>
</style>
</resources> </resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment