From 7d2a6467dba49f74c79c718a48b30499afdf570d Mon Sep 17 00:00:00 2001
From: mwang <8205347@qq.com>
Date: Wed, 12 Jun 2019 00:14:19 +0800
Subject: [PATCH] add qq ad
---
zhuike/build.gradle | 2 +-
zhuike/src/main/AndroidManifest.xml | 24 +-
.../novelbook/android/AD/SplashAdManager.java | 17 +-
.../novelbook/android/AD/qq/Constants.java | 25 ++
.../android/AD/qq/SplashActivity.java | 290 +++++++++++++
.../android/AD/toutiao/SplashActivity.java | 4 +-
.../novelbook/android/Activity_Search.java | 2 +-
.../com/novelbook/android/Activity_base.java | 388 +++++++++++++++++-
.../android/Activity_cate_books.java | 4 +
.../com/novelbook/android/BookActivity.java | 4 +-
.../android/Fragments/BasicFragment.java | 56 ++-
.../java/com/novelbook/android/MyApp.java | 10 +
.../com/novelbook/android/ReadActivity.java | 92 +++--
.../novelbook/android/netutils/NetUtil.java | 63 +--
.../com/novelbook/android/utils/Config.java | 49 ++-
.../novelbook/android/utils/Constants.java | 8 +
.../novelbook/android/utils/PageFactory.java | 20 +-
.../res/drawable-v21/background_circle.xml | 19 +
.../main/res/layout/ad_qq_activity_splash.xml | 59 +++
zhuike/src/main/res/layout/zactivity_read.xml | 175 ++++----
zhuike/src/main/res/values/strings.xml | 4 +-
zhuike/zhuike.iml | 97 ++---
22 files changed, 1171 insertions(+), 241 deletions(-)
create mode 100644 zhuike/src/main/java/com/novelbook/android/AD/qq/Constants.java
create mode 100644 zhuike/src/main/java/com/novelbook/android/AD/qq/SplashActivity.java
create mode 100644 zhuike/src/main/res/drawable-v21/background_circle.xml
create mode 100644 zhuike/src/main/res/layout/ad_qq_activity_splash.xml
diff --git a/zhuike/build.gradle b/zhuike/build.gradle
index 8ac0bdd..859ca45 100644
--- a/zhuike/build.gradle
+++ b/zhuike/build.gradle
@@ -13,7 +13,7 @@ android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
- applicationId "com.novelbook.android"
+ applicationId "com.qq.e.union.demo"
minSdkVersion 19 //target 19 Android 4.4 以下版本仅占比4.1%
targetSdkVersion 28
versionCode 5
diff --git a/zhuike/src/main/AndroidManifest.xml b/zhuike/src/main/AndroidManifest.xml
index bebfd2a..ef84f6f 100644
--- a/zhuike/src/main/AndroidManifest.xml
+++ b/zhuike/src/main/AndroidManifest.xml
@@ -66,7 +66,10 @@
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/ToolBarTheme.NoActionBar">
-
+
+
+
+
-
+
+
+
+
+
+
@@ -121,7 +134,7 @@
-->
+ android:required="false" />
-
-
-
-
+
interVal));
return in >interVal;
diff --git a/zhuike/src/main/java/com/novelbook/android/AD/qq/Constants.java b/zhuike/src/main/java/com/novelbook/android/AD/qq/Constants.java
new file mode 100644
index 0000000..71c2e9b
--- /dev/null
+++ b/zhuike/src/main/java/com/novelbook/android/AD/qq/Constants.java
@@ -0,0 +1,25 @@
+package com.novelbook.android.AD.qq;
+
+public class Constants {
+ public static final String APPID = "1101152570";
+ public static final String BannerPosID = "9079537218417626401";
+ public static final String InterteristalPosID = "8575134060152130849";
+ public static final String SplashPosID = "8863364436303842593";
+ public static final String NativePosID = "5010320697302671";
+ public static final String NativeVideoPosID = "5090421627704602";
+ public static final String NativeExpressPosID = "7030020348049331"; //如果选择支持视频的模版样式,请使用NativeExpressSupportVideoPosID测试广告位拉取
+ public static final String NativeUnifiedPosID = "6040749702835933";
+ public static final String NativeExpressSupportVideoPosID = "2000629911207832"; //支持视频模版样式的广告位
+ public static final String ContentADPosID = "5060323935699523";
+ public static final String RewardVideoADPosIDSupportH = "2090845242931421";//支持竖版出横版视频
+ public static final String RewardVideoADPosIDUnsupportH = "5040942242835423";//不支持竖版出横版视频
+ public static final String IEGRewardVideoADPosID = "6000625736289442";//内广激励视频广告位id
+ public static final String UNIFIED_BANNER_POS_ID = "4080052898050840";
+ public static final String UNIFIED_INTERSTITIAL_ID_LARGE_SMALL = "3040652898151811";// 大小规格
+ public static final String UNIFIED_INTERSTITIAL_ID_ONLY_SMALL = "8020259898964453";// 只小规格
+
+ public static final String POS_ID = "pos_id";
+ public static final String MAX_VIDEO_DURATION = "maxVideoDuration";
+ public static final int VIDEO_DURATION_SETTING_MIN = 5;
+ public static final int VIDEO_DURATION_SETTING_MAX = 60;
+}
diff --git a/zhuike/src/main/java/com/novelbook/android/AD/qq/SplashActivity.java b/zhuike/src/main/java/com/novelbook/android/AD/qq/SplashActivity.java
new file mode 100644
index 0000000..527a402
--- /dev/null
+++ b/zhuike/src/main/java/com/novelbook/android/AD/qq/SplashActivity.java
@@ -0,0 +1,290 @@
+package com.novelbook.android.AD.qq;
+
+import android.Manifest;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.novelbook.android.Main2Activity;
+import com.novelbook.android.R;
+import com.qq.e.ads.splash.SplashAD;
+import com.qq.e.ads.splash.SplashADListener;
+import com.qq.e.comm.util.AdError;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 这是demo工程的入口Activity,在这里会首次调用广点通的SDK。
+ *
+ * 在调用SDK之前,如果您的App的targetSDKVersion >= 23,那么一定要把"READ_PHONE_STATE"、"WRITE_EXTERNAL_STORAGE"、"ACCESS_FINE_LOCATION"这几个权限申请到,否则SDK将不会工作。
+ */
+public class SplashActivity extends Activity implements SplashADListener {
+
+ private SplashAD splashAD;
+ private ViewGroup container;
+ private TextView skipView;
+ //private ImageView splashHolder;
+ private TextView splashHolder;
+ private TextView tvTitle;
+ private static final String SKIP_TEXT = "点击跳过 %d";
+
+ public boolean canJump = false;
+ private boolean needStartDemoList = true;
+
+ /**
+ * 为防止无广告时造成视觉上类似于"闪退"的情况,设定无广告时页面跳转根据需要延迟一定时间,demo
+ * 给出的延时逻辑是从拉取广告开始算开屏最少持续多久,仅供参考,开发者可自定义延时逻辑,如果开发者采用demo
+ * 中给出的延时逻辑,也建议开发者考虑自定义minSplashTimeWhenNoAD的值(单位ms)
+ **/
+ private int minSplashTimeWhenNoAD = 2000;
+ /**
+ * 记录拉取广告的时间
+ */
+ private long fetchSplashADTime = 0;
+ private Handler handler = new Handler(Looper.getMainLooper());
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.ad_qq_activity_splash );
+ container = (ViewGroup) this.findViewById(R.id.splash_container);
+ skipView = (TextView) findViewById(R.id.skip_view);
+ tvTitle = (TextView) findViewById(R.id.textTile);
+ splashHolder = (TextView) findViewById(R.id.splash_holder);
+
+ tvTitle.setText(R.string.app_name);
+ getWindow().getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
+ | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ // | View.SYSTEM_UI_FLAG_IMMERSIVE
+ );
+
+ /* boolean needLogo = getIntent().getBooleanExtra("need_logo", true);
+ needStartDemoList = getIntent().getBooleanExtra("need_start_demo_list", true);
+ if (!needLogo) {
+ findViewById(R.id.app_logo).setVisibility(View.GONE);
+ }*/
+ // 如果targetSDKVersion >= 23,就要申请好权限。如果您的App没有适配到Android6.0(即targetSDKVersion < 23),那么只需要在这里直接调用fetchSplashAD接口。
+ if (Build.VERSION.SDK_INT >= 23) {
+ checkAndRequestPermission();
+ } else {
+ // 如果是Android6.0以下的机器,默认在安装时获得了所有权限,可以直接调用SDK
+ fetchSplashAD(this, container, skipView, Constants.APPID, getPosId(), this, 0);
+ }
+ }
+
+ private String getPosId() {
+ String posId = getIntent().getStringExtra("pos_id");
+ return TextUtils.isEmpty(posId) ? Constants.SplashPosID : posId;
+ }
+
+ /**
+ *
+ * ----------非常重要----------
+ *
+ * Android6.0以上的权限适配简单示例:
+ *
+ * 如果targetSDKVersion >= 23,那么必须要申请到所需要的权限,再调用广点通SDK,否则广点通SDK不会工作。
+ *
+ * Demo代码里是一个基本的权限申请示例,请开发者根据自己的场景合理地编写这部分代码来实现权限申请。
+ * 注意:下面的`checkSelfPermission`和`requestPermissions`方法都是在Android6.0的SDK中增加的API,如果您的App还没有适配到Android6.0以上,则不需要调用这些方法,直接调用广点通SDK即可。
+ */
+ @TargetApi(Build.VERSION_CODES.M)
+ private void checkAndRequestPermission() {
+ List lackedPermission = new ArrayList();
+ if (!(checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED)) {
+ lackedPermission.add(Manifest.permission.READ_PHONE_STATE);
+ }
+
+ if (!(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
+ lackedPermission.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ }
+
+ if (!(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {
+ lackedPermission.add(Manifest.permission.ACCESS_FINE_LOCATION);
+ }
+
+ // 权限都已经有了,那么直接调用SDK
+ if (lackedPermission.size() == 0) {
+ fetchSplashAD(this, container, skipView, Constants.APPID, getPosId(), this, 0);
+ } else {
+ // 请求所缺少的权限,在onRequestPermissionsResult中再看是否获得权限,如果获得权限就可以调用SDK,否则不要调用SDK。
+ String[] requestPermissions = new String[lackedPermission.size()];
+ lackedPermission.toArray(requestPermissions);
+ requestPermissions(requestPermissions, 1024);
+ }
+ }
+
+ private boolean hasAllPermissionsGranted(int[] grantResults) {
+ for (int grantResult : grantResults) {
+ if (grantResult == PackageManager.PERMISSION_DENIED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 1024 && hasAllPermissionsGranted(grantResults)) {
+ fetchSplashAD(this, container, skipView, Constants.APPID, getPosId(), this, 0);
+ } else {
+ // 如果用户没有授权,那么应该说明意图,引导用户去设置里面授权。
+ Toast.makeText(this, "应用缺少必要的权限!请点击\"权限\",打开所需要的权限。", Toast.LENGTH_LONG).show();
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.setData(Uri.parse("package:" + getPackageName()));
+ startActivity(intent);
+ finish();
+ }
+ }
+
+ /**
+ * 拉取开屏广告,开屏广告的构造方法有3种,详细说明请参考开发者文档。
+ *
+ * @param activity 展示广告的activity
+ * @param adContainer 展示广告的大容器
+ * @param skipContainer 自定义的跳过按钮:传入该view给SDK后,SDK会自动给它绑定点击跳过事件。SkipView的样式可以由开发者自由定制,其尺寸限制请参考activity_splash.xml或者接入文档中的说明。
+ * @param appId 应用ID
+ * @param posId 广告位ID
+ * @param adListener 广告状态监听器
+ * @param fetchDelay 拉取广告的超时时长:取值范围[3000, 5000],设为0表示使用广点通SDK默认的超时时长。
+ */
+ private void fetchSplashAD(Activity activity, ViewGroup adContainer, View skipContainer,
+ String appId, String posId, SplashADListener adListener, int fetchDelay) {
+ fetchSplashADTime = System.currentTimeMillis();
+ Map tags = new HashMap<>();
+ tags.put("tag_s1", "value_s1");
+ tags.put("tag_s2", "value_s2");
+
+ splashAD = new SplashAD(activity, adContainer, skipContainer, appId, posId, adListener,
+ fetchDelay, tags);
+ // 如果不需要传tag,使用如下构造函数
+ // splashAD = new SplashAD(activity, adContainer, skipContainer, appId, posId, adListener, fetchDelay);
+ }
+
+ @Override
+ public void onADPresent() {
+ Log.i("AD_DEMO", "SplashADPresent");
+ splashHolder.setVisibility(View.INVISIBLE); // 广告展示后一定要把预设的开屏图片隐藏起来
+ }
+
+ @Override
+ public void onADClicked() {
+ Log.i("AD_DEMO", "SplashADClicked clickUrl: "
+ + (splashAD.getExt() != null ? splashAD.getExt().get("clickUrl") : ""));
+ }
+
+ /**
+ * 倒计时回调,返回广告还将被展示的剩余时间。
+ * 通过这个接口,开发者可以自行决定是否显示倒计时提示,或者还剩几秒的时候显示倒计时
+ *
+ * @param millisUntilFinished 剩余毫秒数
+ */
+ @Override
+ public void onADTick(long millisUntilFinished) {
+ Log.i("AD_DEMO", "SplashADTick " + millisUntilFinished + "ms");
+ skipView.setText(String.format(SKIP_TEXT, Math.round(millisUntilFinished / 1000f)));
+ }
+
+ @Override
+ public void onADExposure() {
+ Log.i("AD_DEMO", "SplashADExposure");
+ }
+
+ @Override
+ public void onADDismissed() {
+ Log.i("AD_DEMO", "SplashADDismissed");
+ next();
+ }
+
+ @Override
+ public void onNoAD(AdError error) {
+ Log.i(
+ "AD_DEMO",
+ String.format("LoadSplashADFail, eCode=%d, errorMsg=%s", error.getErrorCode(),
+ error.getErrorMsg()));
+ /**
+ * 为防止无广告时造成视觉上类似于"闪退"的情况,设定无广告时页面跳转根据需要延迟一定时间,demo
+ * 给出的延时逻辑是从拉取广告开始算开屏最少持续多久,仅供参考,开发者可自定义延时逻辑,如果开发者采用demo
+ * 中给出的延时逻辑,也建议开发者考虑自定义minSplashTimeWhenNoAD的值
+ **/
+ long alreadyDelayMills = System.currentTimeMillis() - fetchSplashADTime;//从拉广告开始到onNoAD已经消耗了多少时间
+ long shouldDelayMills = alreadyDelayMills > minSplashTimeWhenNoAD ? 0 : minSplashTimeWhenNoAD
+ - alreadyDelayMills;//为防止加载广告失败后立刻跳离开屏可能造成的视觉上类似于"闪退"的情况,根据设置的minSplashTimeWhenNoAD
+ // 计算出还需要延时多久
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+
+ SplashActivity.this.finish();
+ }
+ }, shouldDelayMills);
+ }
+
+ /**
+ * 设置一个变量来控制当前开屏页面是否可以跳转,当开屏广告为普链类广告时,点击会打开一个广告落地页,此时开发者还不能打开自己的App主页。当从广告落地页返回以后,
+ * 才可以跳转到开发者自己的App主页;当开屏广告是App类广告时只会下载App。
+ */
+ private void next() {
+ if (canJump) {
+
+ this.finish();
+ } else {
+ canJump = true;
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ canJump = false;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (canJump) {
+ next();
+ }
+ canJump = true;
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ handler.removeCallbacksAndMessages(null);
+ }
+
+ /** 开屏页一定要禁止用户对返回按钮的控制,否则将可能导致用户手动退出了App而广告无法正常曝光和计费 */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME) {
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+}
diff --git a/zhuike/src/main/java/com/novelbook/android/AD/toutiao/SplashActivity.java b/zhuike/src/main/java/com/novelbook/android/AD/toutiao/SplashActivity.java
index 7960121..956479d 100644
--- a/zhuike/src/main/java/com/novelbook/android/AD/toutiao/SplashActivity.java
+++ b/zhuike/src/main/java/com/novelbook/android/AD/toutiao/SplashActivity.java
@@ -183,8 +183,8 @@ public class SplashActivity extends Activity implements WeakHandler.IHandler {
*/
private void goToMainActivity() {
- Intent intent = new Intent(SplashActivity.this, Main2Activity.class);
- startActivity(intent);
+ /* Intent intent = new Intent(SplashActivity.this, Main2Activity.class);
+ startActivity(intent);*/
if(mSplashContainer!=null) {
mSplashContainer.removeAllViews();
}
diff --git a/zhuike/src/main/java/com/novelbook/android/Activity_Search.java b/zhuike/src/main/java/com/novelbook/android/Activity_Search.java
index 577a2af..9a806f6 100644
--- a/zhuike/src/main/java/com/novelbook/android/Activity_Search.java
+++ b/zhuike/src/main/java/com/novelbook/android/Activity_Search.java
@@ -44,7 +44,7 @@ public class Activity_Search extends Activity_base {
@Override
protected void initViews() {
- loadNativeBannerAd(mBannerContainer,BuildConfig.AD_SLOT_TOUTIAO_BANNER_NATIVE_ID);
+ loadNativeBannerAd(mBannerContainer);
}
diff --git a/zhuike/src/main/java/com/novelbook/android/Activity_base.java b/zhuike/src/main/java/com/novelbook/android/Activity_base.java
index 42d3db2..81c081c 100644
--- a/zhuike/src/main/java/com/novelbook/android/Activity_base.java
+++ b/zhuike/src/main/java/com/novelbook/android/Activity_base.java
@@ -1,9 +1,13 @@
package com.novelbook.android;
+import android.Manifest;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -23,6 +27,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
+import com.androidquery.AQuery;
import com.androidquery.callback.AQuery2;
import com.androidquery.callback.ImageOptions;
import com.bytedance.sdk.openadsdk.AdSlot;
@@ -59,15 +64,40 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import com.qq.e.ads.banner.AbstractBannerADListener;
+import com.qq.e.ads.banner.BannerView;
+import com.qq.e.ads.cfg.VideoOption;
+import com.qq.e.ads.nativ.ADSize;
+import com.qq.e.ads.nativ.NativeADUnifiedListener;
+import com.qq.e.ads.nativ.NativeExpressAD;
+import com.qq.e.ads.nativ.NativeExpressADView;
+import com.qq.e.ads.nativ.NativeExpressMediaListener;
+import com.qq.e.ads.nativ.NativeUnifiedAD;
+import com.qq.e.ads.nativ.NativeUnifiedADData;
+import com.qq.e.comm.constants.AdPatternType;
+import com.qq.e.comm.pi.AdData;
+import com.qq.e.comm.util.AdError;
+
+import org.litepal.util.Const;
+
import butterknife.BindView;
import butterknife.ButterKnife;
-public abstract class Activity_base extends AppCompatActivity {
+import static com.novelbook.android.utils.Constants.AD_TENCENT_QQ;
+import static com.novelbook.android.utils.Constants.AD_TOUTIAO;
+
+public abstract class Activity_base extends AppCompatActivity implements NativeExpressAD.NativeExpressADListener {
+
private static String TAG ="Activity_base";
private ProgressDialog mProgressDialog;
private MyApp application;
private Activity_base oContext;
protected Gson gson = new Gson();
+
+ //---qq ad---->
+ private NativeExpressAD nativeExpressAD;
+ private NativeExpressADView nativeExpressADView;
+ //---qq ad end----
@Nullable
@BindView(R.id.toolbar)
Toolbar toolbar;
@@ -77,9 +107,6 @@ public abstract class Activity_base extends AppCompatActivity {
/* @Nullable
@BindView(R.id.banner_native_container)
FrameLayout mNativeBannerContainer;*/
-
-
-
@Nullable
@BindView(R.id.recycleViewBookList)
RecyclerView rvshudan;
@@ -111,19 +138,47 @@ public abstract class Activity_base extends AppCompatActivity {
ButterKnife.bind(this);
setupToolbar();
// 初始化View注入
-
+ this.mAQuery = new AQuery2(this);
initAD_TouTiao();
setTitle();
initData();
initViews();
initNaviBanner();
+ if (Build.VERSION.SDK_INT >= 23) {
+ checkAndRequestPermission();
+ }
+ }
+ @TargetApi(Build.VERSION_CODES.M)
+ private void checkAndRequestPermission() {
+ List lackedPermission = new ArrayList();
+ if (!(checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED)) {
+ lackedPermission.add(Manifest.permission.READ_PHONE_STATE);
+ }
+
+ if (!(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
+ lackedPermission.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ }
+
+ if (!(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {
+ lackedPermission.add(Manifest.permission.ACCESS_FINE_LOCATION);
+ }
+
+
+
+ // 请求所缺少的权限,在onRequestPermissionsResult中再看是否获得权限,如果获得权限就可以调用SDK,否则不要调用SDK。
+ String[] requestPermissions = new String[lackedPermission.size()];
+ if(requestPermissions.length>0) {
+ lackedPermission.toArray(requestPermissions);
+ requestPermissions(requestPermissions, 1024);
+ }
+
}
void initNaviBanner(){
if(mBannerContainer==null){
return;
}
if(Constants.SHOWAD){
- loadNativeBannerAd(mBannerContainer,BuildConfig.AD_SLOT_TOUTIAO_BANNER_NATIVE_ID);
+ loadNativeBannerAd();
mBannerContainer.setVisibility(View.VISIBLE);
}else{
mBannerContainer.setVisibility(View.GONE);
@@ -258,6 +313,8 @@ public abstract class Activity_base extends AppCompatActivity {
};
+
+
class MyViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.title)
TextView tvTitle;
@@ -343,6 +400,45 @@ public abstract class Activity_base extends AppCompatActivity {
super.finish();
}
+ public void loadNativeBannerAd(FrameLayout bannerContainer ) {
+ mBannerContainer =bannerContainer;
+ loadNativeBannerAd( ) ;
+ }
+
+ private void loadNativeBannerAd() {
+ /* if (mBannerContainer .getVisibility() != View.VISIBLE) {
+ mBannerContainer.setVisibility(View.VISIBLE);
+ }
+ */
+ if (mBannerContainer.getChildCount() > 0) {
+ mBannerContainer.removeAllViews();
+ }
+
+ if(!Constants.SHOWAD ){return;}
+ if(Constants.AD_NATIVE_BANNER_SOURCE == AD_TENCENT_QQ) {
+ loadNativeBanner_qq(-1, 388);
+ }else if(Constants.AD_NATIVE_BANNER_SOURCE == AD_TOUTIAO) {
+ loadNativeBanner_toutiao(mBannerContainer ,690,388);
+ }
+ }
+
+ public void loadBanner(FrameLayout bannerContainer, int width, int height) {
+ mBannerContainer =bannerContainer;
+ loadBanner( width, height);
+ }
+
+ private void loadBanner( int width, int height){
+ if(Constants.AD_BANNER_SOURCE == AD_TENCENT_QQ) {
+ getBanner_qq();
+ // loadNativeBanner_qq(-1, 388);
+ }else if(Constants.AD_BANNER_SOURCE == AD_TOUTIAO) {
+ loadBanner_toutiao(mBannerContainer, width,height);
+
+ }
+ }
+
+
+
//------ 头条 ad -----
AQuery2 mAQuery;
Button mCreativeButton;
@@ -353,7 +449,7 @@ public abstract class Activity_base extends AppCompatActivity {
mTTAdNative = TTAdManagerHolder.get().createAdNative(this);
//step3:(可选,强烈建议在合适的时机调用):申请部分权限,如read_phone_state,防止获取不了imei时候,下载类广告没有填充的问题。
TTAdManagerHolder.get().requestPermissionIfNecessary(this);
- this.mAQuery = new AQuery2(this);
+ //this.mAQuery = new AQuery2(this);
}catch (Exception er){
Log.e(TAG, "initAD_TouTiao: ", er);
}
@@ -369,12 +465,16 @@ public abstract class Activity_base extends AppCompatActivity {
return mTTAdNative;
}
-//----toutiao ad ----
+
+
+
+
+ //----toutiao ad ----
// boolean mShowAd =false;
- public void loadBannerAd(FrameLayout bannerContainer, String codeId, int width, int height) {
+ void loadBanner_toutiao(FrameLayout bannerContainer,int width, int height) {
//step4:创建广告请求参数AdSlot,具体参数含义参考文档
if(!Constants.SHOWAD || getTTAdNative()==null ){return;}
-
+ String codeId =BuildConfig.AD_SLOT_TOUTIAO_BANNER_ID;
/* if(height >390){
width =(int)(height*1.78);
if(width > Constants.SCREEN_WIDTH_PIX-50 ){
@@ -511,21 +611,19 @@ public abstract class Activity_base extends AppCompatActivity {
});
}
//-------------native toutiao ad
- void loadNativeBannerAd(FrameLayout bannerContainer,String codeId) {
- loadNativeBannerAd(bannerContainer,codeId,690,388);
- }
// List toutiaoNati_Banner_AdCache = new ArrayList();
Map > toutiaoNati_Banner_AdCache = new ConcurrentHashMap>();
- void loadNativeBannerAd(FrameLayout bannerContainer,String codeId,int width,int height) {
+ void loadNativeBanner_toutiao(FrameLayout bannerContainer,int width,int height) {
//step4:创建广告请求参数AdSlot,注意其中的setNativeAdtype方法,具体参数含义参考文档
if (!Constants.SHOWAD || getTTAdNative() == null) {
return;
}
+ String codeId =BuildConfig.AD_SLOT_TOUTIAO_BANNER_NATIVE_ID;
final String key =width+"_"+height;
List adCache =null;
@@ -585,7 +683,7 @@ public abstract class Activity_base extends AppCompatActivity {
if (isfillAd1) {
setNativeBanner(bannerContainer, key);
}else{
- loadNativeBannerAd(bannerContainer, codeId, width, height);
+ loadNativeBanner_toutiao(mBannerContainer, width, height);
Log.d(TAG, String.format("loadNativeBannerAd: load again ... containsKey(key) ? %s,ads size %s",toutiaoNati_Banner_AdCache.containsKey(key),
toutiaoNati_Banner_AdCache.containsKey(key)?toutiaoNati_Banner_AdCache.get(key).size() :0
));
@@ -909,7 +1007,7 @@ public abstract class Activity_base extends AppCompatActivity {
/**
* 加载 toutiao feed广告
*/
- public void loadListAd(BookListAdapter adapter, int adCnt, boolean addFooter) {
+ public void loadListAd_toutiao(BookListAdapter adapter, int adCnt, boolean addFooter) {
//feed广告请求类型参数
AdSlot adSlot = new AdSlot.Builder()
.setCodeId(BuildConfig.AD_SLOT_TOUTIAO_FEEDAD_ID)
@@ -942,4 +1040,262 @@ public abstract class Activity_base extends AppCompatActivity {
}
});
}
+
+
+ // qq ad ------------------------------begin
+ //private AQuery mAQuery;
+
+
+
+ BannerView bv;
+ private void getBanner_qq() {
+
+ if(this.bv != null){
+ mBannerContainer.removeView(bv);
+ bv.destroy();
+ }
+
+ this.bv = new BannerView(this, com.qq.e.ads.banner.ADSize.BANNER,com.novelbook.android.AD.qq.Constants. APPID,com.novelbook.android.AD.qq.Constants.BannerPosID);
+ // 注意:如果开发者的banner不是始终展示在屏幕中的话,请关闭自动刷新,否则将导致曝光率过低。
+ // 并且应该自行处理:当banner广告区域出现在屏幕后,再手动loadAD。
+ // bv.setRefresh(0);
+ bv.setADListener(new AbstractBannerADListener() {
+
+ @Override
+ public void onNoAD(AdError error) {
+ Log.i(
+ "AD_DEMO",
+ String.format("Banner onNoAD,eCode = %d, eMsg = %s", error.getErrorCode(),
+ error.getErrorMsg()));
+ }
+
+ @Override
+ public void onADReceiv() {
+ Log.i("AD_DEMO", "ONBannerReceive");
+ }
+ });
+ mBannerContainer.addView(bv);
+ this.bv.loadAD();
+ }
+
+
+ private void loadNativeBanner_qq(int adWidth,int adHeight) {
+ try {
+
+ /* if(mAdList!=null && mAdList.size()>1){
+ nativeExpressADView = mAdList.get(0);
+ // bindAD();
+ Log.d(TAG, "loadNativeBanner_qq: mAdList.size()" +mAdList.size());
+ if(mAdList.size()>1){
+ return;
+ }
+ }*/
+
+
+ nativeExpressAD = new NativeExpressAD(this, getMyADSize(adWidth, adHeight), com.novelbook.android.AD.qq.Constants.APPID, com.novelbook.android.AD.qq.Constants.NativeExpressPosID, this); // 这里的Context必须为Activity
+ /* nativeExpressAD.setVideoOption(new VideoOption.Builder()
+ .setAutoPlayPolicy(VideoOption.AutoPlayPolicy.WIFI) // 设置什么网络环境下可以自动播放视频
+ .setAutoPlayMuted(true) // 设置自动播放视频时,是否静音
+ .build()); // setVideoOption是可选的,开发者可根据需要选择是否配置
+ nativeExpressAD.setMaxVideoDuration(com.novelbook.android.AD.qq.Constants.VIDEO_DURATION_SETTING_MAX);*/
+ nativeExpressAD.loadAD(1);
+
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "ad size invalid.");
+ Toast.makeText(this, "请输入合法的宽高数值", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ private ADSize getMyADSize(int adWidth,int adHeight) {
+
+ return new ADSize(adWidth, adHeight);
+ }
+
+ /**
+ * 获取广告数据
+ *
+ * @param nativeExpressADView
+ * @return
+ */
+ private String getAdInfo(NativeExpressADView nativeExpressADView) {
+ AdData adData = nativeExpressADView.getBoundData();
+ if (adData != null) {
+ StringBuilder infoBuilder = new StringBuilder();
+ infoBuilder.append("title:").append(adData.getTitle()).append(",")
+ .append("desc:").append(adData.getDesc()).append(",")
+ .append("patternType:").append(adData.getAdPatternType());
+ if (adData.getAdPatternType() == AdPatternType.NATIVE_VIDEO) {
+ infoBuilder.append(", video info: ").append(getVideoInfo(adData.getProperty(AdData.VideoPlayer.class)));
+ }
+ return infoBuilder.toString();
+ }
+ return null;
+ }
+ /**
+ * 获取播放器实例
+ *
+ * 仅当视频回调{@link NativeExpressMediaListener#onVideoInit(NativeExpressADView)}调用后才会有返回值
+ *
+ * @param videoPlayer
+ * @return
+ */
+ private String getVideoInfo(AdData.VideoPlayer videoPlayer) {
+ if (videoPlayer != null) {
+ StringBuilder videoBuilder = new StringBuilder();
+ videoBuilder.append("{state:").append(videoPlayer.getVideoState()).append(",")
+ .append("duration:").append(videoPlayer.getDuration()).append(",")
+ .append("position:").append(videoPlayer.getCurrentPosition()).append("}");
+ return videoBuilder.toString();
+ }
+ return null;
+ }
+
+ FrameLayout getNativeContainer(){
+ return mBannerContainer;
+ }
+ List mAdList;
+ @Override
+ public void onADLoaded(List adList){
+ // 释放前一个展示的NativeExpressADView的资源
+
+ if(mAdList==null){
+ mAdList = new ArrayList();
+ }
+ boolean toBind = mAdList.size()==0;
+ mAdList.addAll(0,adList);
+ for(NativeExpressADView ad :mAdList){
+ Log.d(TAG, "onADLoaded: ad is " +ad);
+ }
+ /* if(toBind ){
+ bindAD(adList);
+ }*/
+ bindAD(adList);
+
+ }
+ void bindAD(List adList){
+ if (nativeExpressADView != null) {
+ nativeExpressADView.destroy();
+ }
+ FrameLayout bannerContainer = getNativeContainer();
+
+ if (bannerContainer .getVisibility() != View.VISIBLE) {
+ return;
+ // bannerContainer.setVisibility(View.VISIBLE);
+ }
+
+ if (bannerContainer.getChildCount() > 0) {
+ bannerContainer.removeAllViews();
+ }
+
+ nativeExpressADView = adList.get(0);
+
+ /* Log.i(TAG, "onADLoaded, video info: " + getAdInfo(nativeExpressADView));
+ if (nativeExpressADView.getBoundData().getAdPatternType() == AdPatternType.NATIVE_VIDEO) {
+ nativeExpressADView.setMediaListener(mediaListener);
+ }*/
+ // 广告可见才会产生曝光,否则将无法产生收益。
+ bannerContainer.addView(nativeExpressADView);
+ nativeExpressADView.render();
+ // mAdList.remove(0);
+ }
+ @Override
+ public void onNoAD(AdError adError) {
+ Log.i(
+ TAG,
+ String.format("onNoAD, error code: %d, error msg: %s", adError.getErrorCode(),
+ adError.getErrorMsg()));
+ }
+
+ @Override
+ public void onRenderFail(NativeExpressADView adView) {
+ Log.i(TAG, "onRenderFail");
+ }
+
+ @Override
+ public void onRenderSuccess(NativeExpressADView adView) {
+ Log.i(TAG, "onRenderSuccess");
+ }
+
+ @Override
+ public void onADExposure(NativeExpressADView adView) {
+ Log.i(TAG, "onADExposure");
+ }
+
+ @Override
+ public void onADClicked(NativeExpressADView var1){
+
+ }
+
+ @Override
+ public void onADClosed(NativeExpressADView var1) {
+ FrameLayout bannerContainer = getNativeContainer();
+ if (bannerContainer != null && bannerContainer.getChildCount() > 0) {
+ bannerContainer.removeAllViews();
+ // bannerContainer.setVisibility(View.GONE);
+ }
+ }
+ @Override
+ public void onADLeftApplication(NativeExpressADView var1){
+
+ }
+
+ @Override
+ public void onADOpenOverlay(NativeExpressADView var1){
+
+ }
+
+ @Override
+ public void onADCloseOverlay(NativeExpressADView var1){
+
+ }
+ private NativeExpressMediaListener mediaListener = new NativeExpressMediaListener() {
+ @Override
+ public void onVideoInit(NativeExpressADView nativeExpressADView) {
+ Log.i(TAG, "onVideoInit: "
+ + getVideoInfo(nativeExpressADView.getBoundData().getProperty(AdData.VideoPlayer.class)));
+ }
+
+ @Override
+ public void onVideoLoading(NativeExpressADView nativeExpressADView) {
+ Log.i(TAG, "onVideoLoading");
+ }
+
+ @Override
+ public void onVideoReady(NativeExpressADView nativeExpressADView, long l) {
+ Log.i(TAG, "onVideoReady");
+ }
+
+ @Override
+ public void onVideoStart(NativeExpressADView nativeExpressADView) {
+ Log.i(TAG, "onVideoStart: "
+ + getVideoInfo(nativeExpressADView.getBoundData().getProperty(AdData.VideoPlayer.class)));
+ }
+
+ @Override
+ public void onVideoPause(NativeExpressADView nativeExpressADView) {
+ Log.i(TAG, "onVideoPause: "
+ + getVideoInfo(nativeExpressADView.getBoundData().getProperty(AdData.VideoPlayer.class)));
+ }
+
+ @Override
+ public void onVideoComplete(NativeExpressADView nativeExpressADView) {
+ Log.i(TAG, "onVideoComplete: "
+ + getVideoInfo(nativeExpressADView.getBoundData().getProperty(AdData.VideoPlayer.class)));
+ }
+
+ @Override
+ public void onVideoError(NativeExpressADView nativeExpressADView, AdError adError) {
+ Log.i(TAG, "onVideoError");
+ }
+
+ @Override
+ public void onVideoPageOpen(NativeExpressADView nativeExpressADView) {
+ Log.i(TAG, "onVideoPageOpen");
+ }
+
+ @Override
+ public void onVideoPageClose(NativeExpressADView nativeExpressADView) {
+ Log.i(TAG, "onVideoPageClose");
+ }
+ };
}
diff --git a/zhuike/src/main/java/com/novelbook/android/Activity_cate_books.java b/zhuike/src/main/java/com/novelbook/android/Activity_cate_books.java
index d233109..664314d 100644
--- a/zhuike/src/main/java/com/novelbook/android/Activity_cate_books.java
+++ b/zhuike/src/main/java/com/novelbook/android/Activity_cate_books.java
@@ -94,6 +94,10 @@ public class Activity_cate_books extends Activity_base {
}
void initTabs2() {
+ if(Constants.lstProgressType==null){
+ return;
+ }
+
if (mFragments == null ) {
diff --git a/zhuike/src/main/java/com/novelbook/android/BookActivity.java b/zhuike/src/main/java/com/novelbook/android/BookActivity.java
index 2557bc2..b03d9c6 100644
--- a/zhuike/src/main/java/com/novelbook/android/BookActivity.java
+++ b/zhuike/src/main/java/com/novelbook/android/BookActivity.java
@@ -251,7 +251,7 @@ public class BookActivity extends Activity_base {
rvBooklistAuthor.setLayoutManager(new LinearLayoutManager(this));
rvBooklistAuthor.setAdapter(mAdapterAuthor);
- loadListAd(mAdapterAuthor, 1 ,false);
+ loadListAd_toutiao(mAdapterAuthor, 1 ,false);
}
private void setNovelsRelated(){
@@ -270,7 +270,7 @@ public class BookActivity extends Activity_base {
rvBooklistRelated.setLayoutManager(new LinearLayoutManager(this));
rvBooklistRelated.setAdapter(mAdapterRelated);
- loadListAd(mAdapterRelated, 1 ,false);
+ loadListAd_toutiao(mAdapterRelated, 1 ,false);
}
/**
diff --git a/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java b/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java
index 232f22d..9570151 100644
--- a/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java
+++ b/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java
@@ -65,6 +65,11 @@ import com.novelbook.android.utils.ImageUtil;
import com.novelbook.android.utils.MyImageLoader;
import com.novelbook.android.utils.OnItemClickListener;
import com.novelbook.android.utils.PageFactory;
+import com.qq.e.ads.nativ.NativeADUnifiedListener;
+import com.qq.e.ads.nativ.NativeExpressAD;
+import com.qq.e.ads.nativ.NativeUnifiedAD;
+import com.qq.e.ads.nativ.NativeUnifiedADData;
+import com.qq.e.comm.util.AdError;
import com.umeng.analytics.MobclickAgent;
import com.youth.banner.loader.ImageLoader;
@@ -84,7 +89,7 @@ import butterknife.ButterKnife;
/**
* A simple {@link Fragment} subclass.
*/
-public abstract class BasicFragment extends Fragment {
+public abstract class BasicFragment extends Fragment implements NativeADUnifiedListener {
private static String TAG = BasicFragment.class.getSimpleName();
protected View rootView;
@@ -157,6 +162,7 @@ public abstract class BasicFragment extends Fragment {
mBannerContainer.setVisibility(View.GONE);
}
}
+
return view;
// Inflate the layout for this fragment
@@ -474,15 +480,59 @@ void initTabs(){
return;
}
- activity .loadBannerAd(bannerContainer, BuildConfig.AD_SLOT_TOUTIAO_BANNER_ID,(int)(adHeight*5.9), adHeight);
+ activity .loadBanner(bannerContainer, (int)(adHeight*5.9), adHeight);
if( mBannerContainer.getVisibility() !=View.VISIBLE)
mBannerContainer.setVisibility(View.VISIBLE);
}
+ // qq ad ------------------------------begin
+ private NativeUnifiedAD mAdManager;
+ private List mAds = new ArrayList<>();
+ public void loadListAd_qq(BookListAdapter adapter, int adCnt, boolean addFooter) {
+ if(mAdManager==null) {
+ mAdManager = new NativeUnifiedAD(activity, com.novelbook.android.AD.qq.Constants.APPID,
+ com.novelbook.android.AD.qq.Constants.UNIFIED_INTERSTITIAL_ID_ONLY_SMALL, this);
+ }
+ mAdManager.loadData(adCnt);
+ qqAdapter =adapter;
+ qqAddFooter=addFooter;
+
+ }
+
+ private boolean qqAddFooter;
+ private BookListAdapter qqAdapter;
+ @Override
+ public void onADLoaded(List ads) {
+ // mIsLoading = false;
+ // 防止在onDestory后网络回包
+ if(qqAdapter==null){
+ return;
+ }
+ if(qqAddFooter) {
+ qqAdapter.AddFooterItem(ads);
+ }else{
+ qqAdapter.AddHeaderItem(ads);
+ }
+ }
+ @Override
+ public void onNoAD(AdError adError) {
+ Log.i(
+ TAG,
+ String.format("onNoAD, error code: %d, error msg: %s", adError.getErrorCode(),
+ adError.getErrorMsg()));
+ }
+
+ //qq ad end<-------------
+
/**
* 加载 toutiao feed广告
*/
void loadListAd( BookListAdapter adapter, int adCnt, boolean addFooter) {
- activity.loadListAd(adapter, adCnt ,addFooter);
+ if(Constants.AD_UNIFIED_RECYCLE_SOURCE==1) {
+ loadListAd_qq(adapter, adCnt, addFooter);
+ }else if(Constants.AD_UNIFIED_RECYCLE_SOURCE==2){
+ activity.loadListAd_toutiao(adapter, adCnt, addFooter);
+ }
+
}
}
diff --git a/zhuike/src/main/java/com/novelbook/android/MyApp.java b/zhuike/src/main/java/com/novelbook/android/MyApp.java
index 8f77ab2..9cc01e4 100644
--- a/zhuike/src/main/java/com/novelbook/android/MyApp.java
+++ b/zhuike/src/main/java/com/novelbook/android/MyApp.java
@@ -54,6 +54,16 @@ public class MyApp extends Application {
Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT = config.getAdTopBannerRate();
Constants.AD_CHAPT_NATIVE_BANNER_PER_PAGE_COUNT= config.getAdNativeBannerInLinesRate() ;
+ Constants.AD_SPLASH_SOURCE=config.getAdSplashSource();
+ Constants.AD_UNIFIED_RECYCLE_SOURCE=config.getAdUnifiedRecycleSource();
+ Constants.AD_NATIVE_BANNER_SOURCE=config.getAdNativeBannerSource();
+ Constants.AD_BANNER_SOURCE=config.getAdBannerSource();
+
+
+
+
+
+
Constants.ONE_DP_SIZE = (int)applicationContext.getResources().getDimension(R.dimen.one_dp);
}
diff --git a/zhuike/src/main/java/com/novelbook/android/ReadActivity.java b/zhuike/src/main/java/com/novelbook/android/ReadActivity.java
index b8252ce..56b7971 100644
--- a/zhuike/src/main/java/com/novelbook/android/ReadActivity.java
+++ b/zhuike/src/main/java/com/novelbook/android/ReadActivity.java
@@ -137,11 +137,10 @@ public class ReadActivity extends Activity_base implements AdInterface {
@BindView(R.id.frmAD)
FrameLayout frmAD;
- @BindView(R.id.native_banner_container )
+ @BindView(R.id.native_banner_container )
FrameLayout mNative_status_banner_container;
-
- @BindView(R.id.native_banner_container_in_lines )
- FrameLayout mNative_banner_container_in_lines;
+ @BindView(R.id.banner_container )
+ FrameLayout mBannerContainer;
@BindView(R.id.llShelfBottom)
LinearLayout llShelf;
private Config config;
@@ -482,8 +481,8 @@ public class ReadActivity extends Activity_base implements AdInterface {
public void showAdAfterIni() {
// if(frmAD.getVisibility()== View.INVISIBLE)
// frmAD.setVisibility(View.VISIBLE);
- /* if(mNative_banner_container_in_lines.getVisibility()== View.GONE)
- mNative_banner_container_in_lines.setVisibility(View.VISIBLE);*/
+ /* if(mBannerContainer.getVisibility()== View.GONE)
+ mBannerContainer.setVisibility(View.VISIBLE);*/
// Log.d(TAG, "pageAnimation showAdAfterIni: ");
pageFactory.showAd();
}
@@ -492,9 +491,9 @@ public class ReadActivity extends Activity_base implements AdInterface {
public void hideAdBeforeIni() {
// if(frmAD.getVisibility()== View.VISIBLE)
// frmAD.setVisibility(View.INVISIBLE);
- /* if(mNative_banner_container_in_lines.getVisibility()== View.VISIBLE)
- mNative_banner_container_in_lines.setVisibility(View.GONE);*/
- // mNative_banner_container_in_lines.removeAllViews();
+ /* if(mBannerContainer.getVisibility()== View.VISIBLE)
+ mBannerContainer.setVisibility(View.GONE);*/
+ // mBannerContainer.removeAllViews();
// Log.d(TAG, "pageAnimation hideAdBeforeIni: ");
@@ -1079,31 +1078,43 @@ public class ReadActivity extends Activity_base implements AdInterface {
}
*/
+ FrameLayout tmpFrame =mBannerContainer;
+ @Override
+ FrameLayout getNativeContainer(){
+ return tmpFrame;
+ }
+
public void hideStatusAds(){
- Log.d(TAG, "loadBannerAd: hideAds()");
+
/* try{
throw new Exception("");
}catch (Exception e){
Log.e(TAG, "loadBannerAd: ", e);
}*/
if(mNative_status_banner_container.getVisibility() ==View.VISIBLE) {
- mNative_status_banner_container.setVisibility(View.GONE);
+ Log.d(TAG, "loadBannerAd: hideStatusAds()");
+ mNative_status_banner_container.setVisibility(View.GONE);
}
-// mNative_banner_container_in_lines.removeAllViews();
-// mNative_banner_container_in_lines.setBackgroundResource(R.color.transparent);
+ // mBannerContainer.removeAllViews();
+// mBannerContainer.setBackgroundResource(R.color.transparent);
}
private void hideAdSlot(ViewGroup view){
- mNative_banner_container_in_lines.removeAllViews();
- if(view.getVisibility() ==View.VISIBLE) {
+
+ if(view.getChildCount()>0) {
+ view.removeAllViews();
+ Log.d(TAG, "loadBannerAd: hideAdSlot()");
+ }
+
+ /* if(view.getVisibility() ==View.VISIBLE) {
view.setVisibility(View.GONE);
- }
+ }*/
/* FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
params.width =0;
view.setLayoutParams(params);*/
// view.setBackgroundResource(R.color.transparent);
- //mNative_banner_container_in_lines.removeAllViews();
- // mNative_banner_container_in_lines.setBackgroundResource(R.color.transparent);
+ //mBannerContainer.removeAllViews();
+ // mBannerContainer.setBackgroundResource(R.color.transparent);
}
private void showAdSlot(ViewGroup view){
@@ -1120,11 +1131,11 @@ public class ReadActivity extends Activity_base implements AdInterface {
public void showNativeBannerInLines(int height,int adY){
// hideSystemUI();
// hideAdSlot(mNative_banner_container);
- // hideAdSlot(mNative_banner_container_in_lines);
- // mNative_banner_container_in_lines.removeAllViews();
- // mNative_banner_container_in_lines.removeAllViews();
- // mNative_banner_container_in_lines.setBackgroundResource(R.color.transparent);
- hideAdSlot(mNative_banner_container_in_lines);
+ // hideAdSlot(mBannerContainer);
+ // mBannerContainer.removeAllViews();
+ // mBannerContainer.removeAllViews();
+ // mBannerContainer.setBackgroundResource(R.color.transparent);
+ hideAdSlot(mBannerContainer);
if(height<=0){
return;
}
@@ -1132,14 +1143,16 @@ public class ReadActivity extends Activity_base implements AdInterface {
if( adY >390*Constants.ONE_DP_SIZE){
return;
}
+ tmpFrame =mBannerContainer;
+
Log.d(TAG, String.format("loadBannerAd:showNativeBannerInLines width %s, height %s ,adY %s ",Constants.SCREEN_WIDTH_PIX-50,height,adY));
- loadNativeBannerAd(mNative_banner_container_in_lines,BuildConfig.AD_SLOT_TOUTIAO_BANNER_NATIVE_ID);
- FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mNative_banner_container_in_lines.getLayoutParams();
+ loadNativeBannerAd(mBannerContainer);
+ FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mBannerContainer.getLayoutParams();
params.setMargins(10*Constants.ONE_DP_SIZE, adY+5*Constants.ONE_DP_SIZE, 10*Constants.ONE_DP_SIZE, 0*Constants.ONE_DP_SIZE);
params.width =-1;
params.height = (int) getResources().getDimension(R.dimen.nativeBannerHeight);
- mNative_banner_container_in_lines.setLayoutParams(params);
- showAdSlot(mNative_banner_container_in_lines);
+ mBannerContainer.setLayoutParams(params);
+ showAdSlot(mBannerContainer);
@@ -1150,19 +1163,20 @@ public class ReadActivity extends Activity_base implements AdInterface {
// mTopBannerContainer.setVisibility(View.INVISIBLE);//翻页引起抖动
//mTopBannerContainer.removeAllViews();
Log.d(TAG, String.format("loadBannerAd:showTopBanner width %s, height %s ,adY %s ",Constants.SCREEN_WIDTH_PIX-50,adHeight,adY));
- hideAdSlot(mNative_banner_container_in_lines);
+ tmpFrame =mBannerContainer;
+ hideAdSlot(mBannerContainer);
if(adHeight<=0){
return;
}
Log.d(TAG, String.format("loadBannerAd:showTopBanner width %s, height %s ,adY %s ",Constants.SCREEN_WIDTH_PIX-50,adHeight,adY));
- FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mNative_banner_container_in_lines.getLayoutParams();
- loadBannerAd(mNative_banner_container_in_lines,BuildConfig.AD_SLOT_TOUTIAO_BANNER_ID, Constants.SCREEN_WIDTH_PIX-50,adHeight);
+ FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mBannerContainer.getLayoutParams();
+ loadBanner(mBannerContainer, Constants.SCREEN_WIDTH_PIX-50,adHeight);
// loadNativeBannerAd(mTopBannerContainer,BuildConfig.AD_SLOT_TOUTIAO_BANNER_NATIVE_ID, 304,200);
params.setMargins(10*Constants.ONE_DP_SIZE, adY -5*Constants.ONE_DP_SIZE, 10*Constants.ONE_DP_SIZE, 0);
params.width =-1;
params.height = (int) getResources().getDimension(R.dimen.topBannerHeight);
- mNative_banner_container_in_lines.setLayoutParams(params);
- showAdSlot(mNative_banner_container_in_lines);
+ mBannerContainer.setLayoutParams(params);
+ showAdSlot(mBannerContainer);
}
@@ -1192,19 +1206,19 @@ public class ReadActivity extends Activity_base implements AdInterface {
// Log.d(TAG, String.format("loadBannerAd:width %s, height %s ,adY %s",Constants.SCREEN_WIDTH_PIX-50,adHeight,adY));
if(adHeight>150*Constants.ONE_DP_SIZE && adY <400*Constants.ONE_DP_SIZE){
- Log.d(TAG, String.format("loadBannerAd:width %s, height %s ,adY %s ",Constants.SCREEN_WIDTH_PIX-50,adHeight/Constants.ONE_DP_SIZE,adY/Constants.ONE_DP_SIZE ));
- hideAdSlot(mNative_banner_container_in_lines);
+ Log.d(TAG, String.format("loadBannerAd: showStatusAd width %s, height %s ,adY %s ",Constants.SCREEN_WIDTH_PIX-50,adHeight/Constants.ONE_DP_SIZE,adY/Constants.ONE_DP_SIZE ));
+ hideAdSlot(mBannerContainer);
// hideAdSlot(mTopBannerContainer);
-
+ tmpFrame =mNative_status_banner_container;
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mNative_status_banner_container.getLayoutParams();
hideAdSlot(mNative_status_banner_container);
- // mNative_banner_container_in_lines.removeAllViews();
- // mNative_banner_container_in_lines.setBackgroundResource(R.color.transparent);
+ // mBannerContainer.removeAllViews();
+ // mBannerContainer.setBackgroundResource(R.color.transparent);
- loadNativeBannerAd(mNative_status_banner_container,BuildConfig.AD_SLOT_TOUTIAO_BANNER_NATIVE_ID);
+ loadNativeBannerAd(mNative_status_banner_container);
params.setMargins(10*Constants.ONE_DP_SIZE, adY-20*Constants.ONE_DP_SIZE, 10*Constants.ONE_DP_SIZE, 50*Constants.ONE_DP_SIZE);
- params.height=-1;
+ // params.height=-1;
mNative_status_banner_container.setLayoutParams(params);
showAdSlot(mNative_status_banner_container);
// mNative_banner_container.setVisibility(View.VISIBLE);
diff --git a/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java b/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java
index 5a9072c..2ab0f65 100644
--- a/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java
+++ b/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java
@@ -360,55 +360,66 @@ public class NetUtil {
static long lastUpgradCheck =0;
static void initHostConstants( JSONObject jsonObject ) throws JSONException {
- Constants.announcement =jsonObject.getString("declare");
- Constants.email =jsonObject.getString("email");
- String tmp =jsonObject.getString("upgradeUrl");
- Constants.updateUrl =TextUtils.isEmpty(tmp)?Constants.updateUrl:tmp;
- Constants.minVersion = jsonObject.getInt("minVersion");
+ Constants.announcement = jsonObject.getString("declare");
+ Constants.email = jsonObject.getString("email");
+ String tmp = jsonObject.getString("upgradeUrl");
+ Constants.updateUrl = TextUtils.isEmpty(tmp) ? Constants.updateUrl : tmp;
+ Constants.minVersion = jsonObject.getInt("minVersion");
- JSONObject ads = jsonObject.getJSONObject("adsenseSetting") ;
+ JSONObject ads = jsonObject.getJSONObject("adsenseSetting");
// Gson gson = new Gson();
// AdSetting ads = gson.fromJson(adStr, AdSetting.class);
- Constants.AD_SPLASH_INVTERVAL =(long) 1000 * ads.getInt("splashInterval");
- Constants.AD_SPLASH_PAGES = ads.getInt("splashPageCount");
- Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT = ads.getInt("times4ChapterTopBanner");
- Constants.AD_CHAPT_NATIVE_BANNER_PER_PAGE_COUNT = ads.getInt("times4ChapterContentBanner");
+ Constants.AD_SPLASH_INVTERVAL = (long) 1000 * ads.getInt("splashInterval");
+ Constants.AD_SPLASH_PAGES = ads.getInt("splashPageCount");
+ Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT = ads.getInt("times4ChapterTopBanner");
+ Constants.AD_CHAPT_NATIVE_BANNER_PER_PAGE_COUNT = ads.getInt("times4ChapterContentBanner");
- if(Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT >1 && Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT == Constants.AD_CHAPT_NATIVE_BANNER_PER_PAGE_COUNT ){
- Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT--; //顶部广告和页内广告要错开
- }
+ /* Constants.AD_SPLASH_SOURCE = ads.getInt("splashSource");
+ Constants.AD_UNIFIED_RECYCLE_SOURCE = ads.getInt("unifiedReceycleSource");
+ Constants.AD_NATIVE_BANNER_SOURCE = ads.getInt("nativeBannerSource");
+ Constants.AD_BANNER_SOURCE = ads.getInt("bannerSource");*/
- Log.d(TAG, String.format("initHostConstants: Constants.AD_SPLASH_INVTERVAL %s,AD_SPLASH_PAGES %s",Constants.AD_SPLASH_INVTERVAL,Constants.AD_SPLASH_PAGES ));
- // try {
- Constants.version = CommonUtil.getVersionCode(MyApp.applicationContext);
- if (lastUpgradCheck == 0 ||Constants.version 1 && Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT == Constants.AD_CHAPT_NATIVE_BANNER_PER_PAGE_COUNT) {
+ Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT--; //顶部广告和页内广告要错开
+ }
- }
+ Log.d(TAG, String.format("initHostConstants: Constants.AD_SPLASH_INVTERVAL %s,AD_SPLASH_PAGES %s", Constants.AD_SPLASH_INVTERVAL, Constants.AD_SPLASH_PAGES));
+ // try {
+ Constants.version = CommonUtil.getVersionCode(MyApp.applicationContext);
+ if (lastUpgradCheck == 0 || Constants.version < Constants.minVersion) {
+ lastUpgradCheck = new Date().getTime();
+ checkUpdate(true);
+
+ }
// }catch (Exception er){
// Log.e(TAG, "initHostConstants: update error ",er );
// }
- if( ads.getBoolean("showAdsense")){
- if(!Constants.SHOWAD ){
+ if (ads.getBoolean("showAdsense")) {
+ if (!Constants.SHOWAD) {
Constants.SHOWAD = ads.getBoolean("showAdsense");
TTAdManagerHolder.init(MyApp.applicationContext);
}
}
Config config = Config.getInstance();
Constants.SHOWAD = ads.getBoolean("showAdsense");
- Constants.PRE_LOAD_CHAPT= jsonObject.getBoolean("preLoadChapter");
+ Constants.PRE_LOAD_CHAPT = jsonObject.getBoolean("preLoadChapter");
config.setShowAd(Constants.SHOWAD);
config.setPreLoadChapter(Constants.PRE_LOAD_CHAPT);
- config.setAdTopBannerRate( Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT);
+ config.setAdTopBannerRate(Constants.AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT);
config.setAdNativeBannerInLinesRate(Constants.AD_CHAPT_NATIVE_BANNER_PER_PAGE_COUNT);
+
+ config.setAdSplashSource(Constants.AD_SPLASH_SOURCE);
+ config.setAdUnifiedRecycleSource(Constants.AD_UNIFIED_RECYCLE_SOURCE);
+ config.setAdNativeBannerSource(Constants.AD_NATIVE_BANNER_SOURCE);
+ config.setAdBannerSource(Constants.AD_BANNER_SOURCE);
+
Log.d(TAG, String.format("initHostConstants: Constants.AD_SPLASH_INVTERVAL %s,AD_SPLASH_PAGES %s, Constants.SHOWAD %s,Constants.AD_PRE_LOAD_CHAPT %s "
- ,Constants.AD_SPLASH_INVTERVAL,Constants.AD_SPLASH_PAGES, Constants.SHOWAD, Constants.PRE_LOAD_CHAPT ));
+ , Constants.AD_SPLASH_INVTERVAL, Constants.AD_SPLASH_PAGES, Constants.SHOWAD, Constants.PRE_LOAD_CHAPT));
- }
+ }
public static void checkUpdate(boolean isSilence){
UpdateManager manager = new UpdateManager(Main2Activity.activityContext);
diff --git a/zhuike/src/main/java/com/novelbook/android/utils/Config.java b/zhuike/src/main/java/com/novelbook/android/utils/Config.java
index 9907b8d..6c46232 100644
--- a/zhuike/src/main/java/com/novelbook/android/utils/Config.java
+++ b/zhuike/src/main/java/com/novelbook/android/utils/Config.java
@@ -41,10 +41,14 @@ public class Config {
public final static int PAGE_MODE_SLIDE = 2;
public final static int PAGE_MODE_NONE = 3;
public final static boolean SHOW_AD = false;
- public final static String SHOW_AD_KEY = "showAd";
+ private final static String SHOW_AD_KEY = "showAd";
private static final String PRE_LOAD_CHAPT_KEY ="preloadchapt" ;
private static final String AD_TOP_BANNER_SEEDS_KEY ="topbannerseeds" ;
private static final String AD_NATVIE_BANNER_IN_LINES_SEEDS_KEY ="nativebannerinlinesseeds" ;
+
+
+
+
private Context mContext;
private static Config config;
private SharedPreferences sp;
@@ -234,6 +238,48 @@ public class Config {
sp.edit().putInt(AD_TOP_BANNER_SEEDS_KEY,pageCnt).commit();
}
+
+
+
+ private final static String AD_NATIVE_BANNER_SOURCE_KEY = "AD_NATIVE_BANNER_SOURCE_KEY";
+ private final static String AD_BANNER_SOURCE_KEY = "AD_BANNER_SOURCE_KEY";
+ private final static String AD_UNIFIED_RECYCLE_SOURCE_KEY = "AD_UNIFIED_RECYCLE_SOURCE_KEY";
+ private final static String AD_SPLASH_SOURCE_KEY = "AD_SPLASH_SOURCE_KEY";
+
+
+ public int getAdNativeBannerSource(){
+ return sp.getInt(AD_NATIVE_BANNER_SOURCE_KEY,Constants.AD_TENCENT_QQ);
+ }
+
+ public void setAdNativeBannerSource(int source){
+ sp.edit().putInt(AD_NATIVE_BANNER_SOURCE_KEY,source).commit();
+ }
+
+ public int getAdBannerSource(){
+ return sp.getInt(AD_BANNER_SOURCE_KEY,Constants.AD_TENCENT_QQ);
+ }
+
+ public void setAdBannerSource(int source){
+ sp.edit().putInt(AD_BANNER_SOURCE_KEY,source).commit();
+ }
+
+ public int getAdUnifiedRecycleSource(){
+ return sp.getInt(AD_UNIFIED_RECYCLE_SOURCE_KEY,Constants.AD_TENCENT_QQ);
+ }
+
+ public void setAdUnifiedRecycleSource(int source){
+ sp.edit().putInt(AD_UNIFIED_RECYCLE_SOURCE_KEY,source).commit();
+ }
+
+ public int getAdSplashSource(){
+ return sp.getInt(AD_SPLASH_SOURCE_KEY,Constants.AD_TENCENT_QQ);
+ }
+
+ public void setAdSplashSource(int source){
+ sp.edit().putInt(AD_SPLASH_SOURCE_KEY,source).commit();
+ }
+
+
public int getAdNativeBannerInLinesRate(){
return sp.getInt(AD_NATVIE_BANNER_IN_LINES_SEEDS_KEY,0);
}
@@ -241,4 +287,5 @@ public class Config {
public void setAdNativeBannerInLinesRate(int pageCnt){
sp.edit().putInt(AD_NATVIE_BANNER_IN_LINES_SEEDS_KEY,pageCnt).commit();
}
+
}
diff --git a/zhuike/src/main/java/com/novelbook/android/utils/Constants.java b/zhuike/src/main/java/com/novelbook/android/utils/Constants.java
index 64b6910..4e52998 100644
--- a/zhuike/src/main/java/com/novelbook/android/utils/Constants.java
+++ b/zhuike/src/main/java/com/novelbook/android/utils/Constants.java
@@ -14,8 +14,16 @@ public class Constants {
public static final int MAXAGE_MAX =60*60*24*28; //28 天 ;
public static final int MAXAGE_MULU = 60*60*24*7*2; //2周;;
public static final String VERSION_ADDRESS ="version.xml";
+
+ public static final int AD_TENCENT_QQ =1;
+ public static final int AD_TOUTIAO =2;
public static boolean AD_BACKGROUND_TRANSPARENT =true ;
public static boolean SHOWAD =false ;
+ public static int AD_NATIVE_BANNER_SOURCE = 2 ; //1:tencent,2:toutiao
+ public static int AD_BANNER_SOURCE = 1 ; //1:tencent,2:toutiao
+ public static int AD_UNIFIED_RECYCLE_SOURCE = 2 ; //1:tencent,2:toutiao
+ public static int AD_SPLASH_SOURCE = 1 ; //1:tencent,2:toutiao
+ public static int AD_SOURCE =1 ; //1:tencent,2:toutiao
public static boolean PRE_LOAD_CHAPT = false;
public static long AD_SPLASH_INVTERVAL = 5*60*1000;//间隔5分钟
public static int AD_SPLASH_PAGES = 15;
diff --git a/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java b/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java
index 993ebec..58b6607 100644
--- a/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java
+++ b/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java
@@ -473,9 +473,10 @@ public class PageFactory implements ChangeSource{
int pageNo =0;
long starttime = new Date().getTime();
while(length =chars.length){
if(page.getLines().size()< mLineCount/2)
page.setTopBannerHeight(0);
}
+
+ chaptPages.add(page);
// Log.d(TAG, String.format("prepare book build page %s ready for chapter %s,cost %s",pageNo, chaptId,new Date().getTime()-starttime1));
}
// Log.d(TAG, String.format(" prepare book build pages ready for chapter %s,cost %s", chaptId,new Date().getTime()-starttime));
@@ -1089,7 +1096,11 @@ private void hideSysUI(){
}
y+=trPage.getNativeBannerHeight() +m_fontSize +lineSpace ;
Log.d(TAG, String.format("onDraw showNativeBannerInLines : lineno %s,strline %s ",lineNo,strLine));
-
+ space = m_fontSize + lineSpace;
+ // y-=lineSpace;
+ if (strLine.length() > 0 && (strLine.charAt(strLine.length() - 1) + "").equals("\n")) {
+ space = m_fontSize + paragraphSpace;
+ }
}else {
if (strLine.length() > 0 && (strLine.charAt(strLine.length() - 1) + "").equals("\n")) {
@@ -1105,6 +1116,7 @@ private void hideSysUI(){
// Log.d(TAG,String.format("prepare book %s,y plus is %s" ,strLine, m_fontSize + lineSpace));
}
+
}
c.drawText(strLine, measureMarginWidth, y, mPaint);
diff --git a/zhuike/src/main/res/drawable-v21/background_circle.xml b/zhuike/src/main/res/drawable-v21/background_circle.xml
new file mode 100644
index 0000000..1ae1939
--- /dev/null
+++ b/zhuike/src/main/res/drawable-v21/background_circle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zhuike/src/main/res/layout/ad_qq_activity_splash.xml b/zhuike/src/main/res/layout/ad_qq_activity_splash.xml
new file mode 100644
index 0000000..e2e90ab
--- /dev/null
+++ b/zhuike/src/main/res/layout/ad_qq_activity_splash.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zhuike/src/main/res/layout/zactivity_read.xml b/zhuike/src/main/res/layout/zactivity_read.xml
index 4185d15..11fe705 100644
--- a/zhuike/src/main/res/layout/zactivity_read.xml
+++ b/zhuike/src/main/res/layout/zactivity_read.xml
@@ -12,8 +12,8 @@
-->
+ android:layout_height="match_parent">
+
-
+ app:popupTheme="@style/AppTheme.PopupOverlay">
+
+ android:id="@+id/tvUrl"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:background="@color/read_dialog_bg"
+ android:ellipsize="end"
+ android:gravity="bottom"
+ android:lines="1"
+ android:paddingLeft="10dp"
+ android:text="http://abc.om..fd"
+ android:textColor="@color/whitesmoke"
+ android:textSize="11sp" />
-
+
+
+ android:contentDescription="TODO"
+ android:scaleType="centerCrop"
+ android:src="@mipmap/loading"
+ android:visibility="gone" />
-
+ -->
-
-
+ -->
-
- android:visibility="visible"
- />
+
+
+
-
-
-
+
+
+
+
+
-
+ android:text="@string/put_to_shelf"
+ android:textAlignment="center" />
+
+
+
-
+
-
+ android:id="@+id/btnShelf"
+ style="@style/buttonCates"
+ android:text="加入书架"
+ android:textColor="@color/colorAccent" />
+
-
diff --git a/zhuike/src/main/res/values/strings.xml b/zhuike/src/main/res/values/strings.xml
index be77951..21db03d 100644
--- a/zhuike/src/main/res/values/strings.xml
+++ b/zhuike/src/main/res/values/strings.xml
@@ -1,5 +1,5 @@
- 网书助手
+ qqAd网书助手
书架
书城
排行榜
@@ -141,6 +141,8 @@
提示
喜欢就加入书架吧
[推广]
+ gdtslogan
+ 点击跳过
- 小燕—女青、中英、普通话
diff --git a/zhuike/zhuike.iml b/zhuike/zhuike.iml
index dc9cd64..1106ac4 100644
--- a/zhuike/zhuike.iml
+++ b/zhuike/zhuike.iml
@@ -126,98 +126,99 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-