diff --git a/aes/build.gradle b/aes/build.gradle index fbc8d4a..d65a9c5 100644 --- a/aes/build.gradle +++ b/aes/build.gradle @@ -39,10 +39,6 @@ android { } } - // 米盟 SDK - packagingOptions { - doNotStrip "*/*/libmimo_1011.so" - } } dependencies { diff --git a/aes/build.properties b/aes/build.properties index f68c3c6..f084835 100644 --- a/aes/build.properties +++ b/aes/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Wed Jun 03 20:29:52 HKT 2026 +#Mon Jun 08 13:18:46 GMT 2026 stageCount=16 libraryProject=libaes baseVersion=15.20 publishVersion=15.20.15 -buildCount=0 +buildCount=3 baseBetaVersion=15.20.16 diff --git a/aes/src/main/java/cc/winboll/studio/aes/SettingsActivity.java b/aes/src/main/java/cc/winboll/studio/aes/SettingsActivity.java index 1767c02..f2f7015 100644 --- a/aes/src/main/java/cc/winboll/studio/aes/SettingsActivity.java +++ b/aes/src/main/java/cc/winboll/studio/aes/SettingsActivity.java @@ -1,11 +1,7 @@ package cc.winboll.studio.aes; import android.app.Activity; -import android.content.Intent; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import cc.winboll.studio.libaes.views.ADsControlView; /** * @Author ZhanGSKen&豆包大模型 @@ -20,7 +16,7 @@ public class SettingsActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); - ADsControlView adsControlView = (ADsControlView) findViewById(R.id.ads_control_view); + //ADsControlView adsControlView = (ADsControlView) findViewById(R.id.ads_control_view); // adsControlView.setOnAdsModeSelectedListener(new ADsControlView.OnAdsModeSelectedListener() { // @Override diff --git a/aes/src/main/res/layout/activity_settings.xml b/aes/src/main/res/layout/activity_settings.xml index 99dee06..272b1da 100644 --- a/aes/src/main/res/layout/activity_settings.xml +++ b/aes/src/main/res/layout/activity_settings.xml @@ -6,12 +6,5 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg_container_border"> - - diff --git a/libaes/build.gradle b/libaes/build.gradle index b5643aa..59e3387 100644 --- a/libaes/build.gradle +++ b/libaes/build.gradle @@ -20,15 +20,11 @@ android { } } - // 米盟 SDK compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } - packagingOptions { - doNotStrip "*/*/libmimo_1011.so" - } } dependencies { @@ -57,7 +53,7 @@ dependencies { //api 'androidx.fragment:fragment:1.1.0' // 米盟 - api 'com.miui.zeus:mimo-ad-sdk:5.3.+'//请使用最新版sdk + //api 'com.miui.zeus:mimo-ad-sdk:5.3.+'//请使用最新版sdk //注意:以下5个库必须要引入 //implementation 'androidx.appcompat:appcompat:1.4.1' api 'androidx.recyclerview:recyclerview:1.0.0' @@ -66,9 +62,9 @@ dependencies { //annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' // WinBoLL库 nexus.winboll.cc 地址 - api 'cc.winboll.studio:libappbase:15.20.26' + //api 'cc.winboll.studio:libappbase:15.20.26' // 备用库 jitpack.io 地址 - //api 'com.github.ZhanGSKen:libappbase:appbase-v15.20.26' - + api 'com.github.ZhanGSKen:libappbase:appbase-v15.20.26' + api fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/libaes/build.properties b/libaes/build.properties index eabb756..f084835 100644 --- a/libaes/build.properties +++ b/libaes/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Wed Jun 03 20:29:39 HKT 2026 +#Mon Jun 08 13:18:46 GMT 2026 stageCount=16 libraryProject=libaes baseVersion=15.20 publishVersion=15.20.15 -buildCount=0 +buildCount=3 baseBetaVersion=15.20.16 diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java index 7d0a47a..63e4de9 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java @@ -15,7 +15,6 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; - import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; @@ -23,9 +22,9 @@ import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; - import cc.winboll.studio.libaes.DrawerMenuDataAdapter; import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; import cc.winboll.studio.libaes.models.AESThemeBean; import cc.winboll.studio.libaes.models.DrawerMenuBean; @@ -33,11 +32,9 @@ import cc.winboll.studio.libaes.utils.AESThemeUtil; import cc.winboll.studio.libaes.utils.DevelopUtils; import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; import cc.winboll.studio.libaes.views.ADrawerMenuListView; -import cc.winboll.studio.libaes.views.ADsBannerView; import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.LogUtils; import com.baoyz.widget.PullRefreshLayout; - import java.util.ArrayList; public abstract class DrawerFragmentActivity extends AppCompatActivity implements IWinBoLLActivity, AdapterView.OnItemClickListener { @@ -91,10 +88,10 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement WinBoLLActivityManager.getInstance().registeRemove(this); super.onDestroy(); // 修复:释放广告资源,避免内存泄漏 - ADsBannerView adsBannerView = findViewById(R.id.adsbanner); - if (adsBannerView != null) { - adsBannerView.releaseAdResources(); - } +// ADsBannerView adsBannerView = findViewById(R.id.adsbanner); +// if (adsBannerView != null) { +// adsBannerView.releaseAdResources(); +// } } @Override @@ -151,10 +148,10 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement protected void onResume() { super.onResume(); - ADsBannerView adsBannerView = findViewById(R.id.adsbanner); - if (adsBannerView != null) { - adsBannerView.resumeADs(DrawerFragmentActivity.this); - } +// ADsBannerView adsBannerView = findViewById(R.id.adsbanner); +// if (adsBannerView != null) { +// adsBannerView.resumeADs(DrawerFragmentActivity.this); +// } } void initRootView() { diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsBannerView.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsBannerView.java deleted file mode 100644 index 89eb74f..0000000 --- a/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsBannerView.java +++ /dev/null @@ -1,491 +0,0 @@ -package cc.winboll.studio.libaes.views; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Handler; -import android.os.Looper; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import cc.winboll.studio.libaes.R; -import cc.winboll.studio.libaes.enums.ADsMode; -import cc.winboll.studio.libaes.utils.MimoUtils; -import cc.winboll.studio.libappbase.GlobalApplication; -import cc.winboll.studio.libappbase.LogUtils; -import com.miui.zeus.mimo.sdk.ADParams; -import com.miui.zeus.mimo.sdk.BannerAd; -import com.miui.zeus.mimo.sdk.MimoCustomController; -import com.miui.zeus.mimo.sdk.MimoLocation; -import com.miui.zeus.mimo.sdk.MimoSdk; -import java.util.ArrayList; -import java.util.List; - -/** - * @Author ZhanGSKen&豆包大模型 - * @Date 2025/11/18 14:41 - * @Describe WinBoLL 横幅广告类 - */ -public class ADsBannerView extends LinearLayout { - - public static final String TAG = "ADsBannerView"; - - - private String BANNER_POS_ID = "802e356f1726f9ff39c69308bfd6f06a"; - private String BANNER_POS_ID_WINBOLL_BETA = "d129ee5a263911f981a6dc7a9802e3e7"; - private String BANNER_POS_ID_WINBOLL = "4ec30efdb32271765b9a4efac902828b"; - - /* - private String BANNER_POS_ID = "802e356f1726f9ff39c69308bfd6f06a"; - private String BANNER_POS_ID_WINBOLL_BETA = "802e356f1726f9ff39c69308bfd6f06a"; - private String BANNER_POS_ID_WINBOLL = "802e356f1726f9ff39c69308bfd6f06a"; - */ - - Context mContext; - View mMianView; - SharedPreferences mSharedPreferences; - ViewGroup mContainer; - BannerAd mBannerAd; - List mAllBanners = new ArrayList<>(); - // 新增:主线程Handler,确保广告操作在主线程执行 - private Handler mMainHandler; - - public ADsBannerView(Context context) { - super(context); - initView(context); - } - - public ADsBannerView(Context context, AttributeSet attrs) { - super(context, attrs); - initView(context); - } - - public ADsBannerView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initView(context); - } - - public ADsBannerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - initView(context); - } - - void initView(Context context) { - this.mContext = context; - initMimoSdk(this.mContext); - - // 初始化主线程Handler(关键:确保广告操作在主线程执行) - mMainHandler = new Handler(Looper.getMainLooper()); - - this.mMianView = inflate(this.mContext, R.layout.view_adsbanner, null); - mContainer = this.mMianView.findViewById(R.id.ads_container); - addView(this.mMianView); - } - - public void resumeADs(final Activity activity) { - // 没有设置米盟广告支持就退出 - if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { - // 2. 释放之前的广告资源 - if (mBannerAd != null) { - mBannerAd.destroy(); - } - return; - } - - // 修复:优化广告请求逻辑(添加生命周期判断 + 主线程执行) - if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) { - if (ADsControlView.getAdsModeFromStatic(this.mContext) == ADsMode.MIMO_SDK) { - LogUtils.i(TAG, "已设置播放米盟广告,正在播放..."); - mMainHandler.postDelayed(new Runnable() { - @Override - public void run() { - // 再次校验生命周期,避免延迟执行时Activity已销毁 - if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) { - fetchAd(activity); - } - } - }, 1000); // 延迟1秒请求广告,提升页面加载体验 - } - } - } - - /** - * 释放广告资源(关键:避免内存泄漏和空Context调用) - */ - public void releaseAdResources() { - // 没有设置米盟广告支持就退出 - if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { - return; - } - - LogUtils.d(TAG, "releaseAdResources()"); - - // 移除Handler回调 - if (mMainHandler != null) { - mMainHandler.removeCallbacksAndMessages(null); - } - - // 销毁所有广告实例 - if (mAllBanners != null && !mAllBanners.isEmpty()) { - for (BannerAd ad : mAllBanners) { - if (ad != null) { - ad.destroy(); - } - } - mAllBanners.clear(); - } - // 置空当前广告引用 - mBannerAd = null; - // 移除广告容器中的视图 - if (mContainer != null) { - mContainer.removeAllViews(); - } - } - - /** - * 显示广告(核心修复:传递安全的Context + 生命周期校验) - */ - private void showAd(final Activity activity) { - // 没有设置米盟广告支持就退出 - if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { - return; - } - - LogUtils.d(TAG, "showAd()"); - // 1. 生命周期校验:避免Activity已销毁时操作UI - if (activity == null || activity.isFinishing() || activity.isDestroyed()) { - LogUtils.e(TAG, "showAd: Activity is finishing or destroyed"); - return; - } - // 2. 非空校验:广告实例和容器 - if (mBannerAd == null || mContainer == null) { - LogUtils.e(TAG, "showAd: BannerAd or Container is null"); - return; - } - // 3. 创建广告容器(使用ApplicationContext避免内存泄漏) - final FrameLayout container = new FrameLayout(activity.getApplicationContext()); - container.setPadding(0, 0, 0, MimoUtils.dpToPx(activity, 10)); - mContainer.addView(container, new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.MATCH_PARENT, - FrameLayout.LayoutParams.WRAP_CONTENT - )); - -// if (mIsBiddingWin) { -// mBannerAd.setPrice(getPrice()); -// } - // 4. 显示广告:传递ApplicationContext,避免Activity Context失效 - mBannerAd.showAd(activity, container, new BannerAd.BannerInteractionListener() { - @Override - public void onAdClick() { - LogUtils.d(TAG, "onAdClick"); - } - - @Override - public void onAdShow() { - LogUtils.d(TAG, "onAdShow"); - } - - @Override - public void onAdDismiss() { - LogUtils.d(TAG, "onAdDismiss"); - // 修复:移除容器时校验Activity状态 - if (activity != null && !activity.isFinishing() && !activity.isDestroyed() && mContainer != null) { - mContainer.removeView(container); - } - } - - @Override - public void onRenderSuccess() { - LogUtils.d(TAG, "onRenderSuccess"); - } - - @Override - public void onRenderFail(int code, String msg) { - LogUtils.e(TAG, "onRenderFail errorCode " + code + " errorMsg " + msg); - // 修复:渲染失败时移除容器 - if (activity != null && !activity.isFinishing() && !activity.isDestroyed() && mContainer != null) { - mContainer.removeView(container); - } - } - }); - } - - /** - * 请求广告(核心修复:Context安全校验 + 异常捕获 + 资源管理) - */ - private void fetchAd(final Activity activity) { - // 没有设置米盟广告支持就退出 - if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { - return; - } - - LogUtils.d(TAG, "fetchAd()"); - // 1. 双重校验:Activity未销毁 + Context非空 - if (activity == null || activity.isFinishing() || activity.isDestroyed() || activity.getApplicationContext() == null) { - LogUtils.e(TAG, "fetchAd: Invalid Context or Activity state"); - return; - } - // 2. 释放之前的广告资源,避免内存泄漏 - if (mBannerAd != null) { - mBannerAd.destroy(); - } - // 3. 初始化广告(使用ApplicationContext,避免Activity Context失效) - try { - mBannerAd = new BannerAd(); - mAllBanners.add(mBannerAd); - } catch (Exception e) { - LogUtils.e(TAG, "fetchAd: Init BannerAd failed", e); - return; - } - // 4. 设置下载监听 - mBannerAd.setDownLoadListener(new BannerAd.BannerDownloadListener() { - @Override - public void onDownloadStarted() { - LogUtils.d(TAG, "onDownloadStarted"); - } - - @Override - public void onDownloadPaused() { - LogUtils.d(TAG, "onDownloadPaused"); - } - - @Override - public void onDownloadFailed(int errorCode) { - String msg = "onDownloadFailed, errorCode = " + errorCode; - LogUtils.d(TAG, msg); - //ToastUtils.show(msg); - } - - @Override - public void onDownloadFinished() { - LogUtils.d(TAG, "onDownloadFinished"); - } - - @Override - public void onDownloadProgressUpdated(int progress) { - LogUtils.d(TAG, "onDownloadProgressUpdated " + progress + "%"); - } - - @Override - public void onInstallFailed(int errorCode) { - LogUtils.d(TAG, "onInstallFailed, errorCode = " + errorCode); - } - - @Override - public void onInstallStart() { - LogUtils.d(TAG, "onInstallStart"); - } - - @Override - public void onInstallSuccess() { - LogUtils.d(TAG, "onInstallSuccess"); - } - - @Override - public void onDownloadCancel() { - LogUtils.d(TAG, "onDownloadCancel"); - } - }); - - // 5. 构建广告参数并请求 - String currentAD_ID = getAD_ID(); - LogUtils.d(TAG, String.format("currentAD_ID = %s", currentAD_ID)); - ADParams params = new ADParams.Builder().setUpId(currentAD_ID).build(); - mBannerAd.loadAd(params, new BannerAd.BannerLoadListener() { - @Override - public void onBannerAdLoadSuccess() { - LogUtils.d(TAG, "onBannerAdLoadSuccess()"); - // 修复:广告加载成功后校验Activity状态 - if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) { - showAd(activity); - //ToastUtils.show("showAd()"); - } - } - - @Override - public void onAdLoadFailed(int errorCode, String errorMsg) { - String msg = "onAdLoadFailed: errorCode = " + errorCode + ", errorMsg = " + errorMsg; - LogUtils.d(TAG, msg); - removeAllBanners(); - } - }); - } - - void removeAllBanners() { - // 没有设置米盟广告支持就退出 - if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { - return; - } - - // 修复:加载失败时移除当前广告实例 - if (mAllBanners.contains(mBannerAd)) { - mAllBanners.remove(mBannerAd); - } - mBannerAd.destroy(); - mBannerAd = null; - } - - /** - * 根据当前秒数获取广告ID(原逻辑保留) - */ - private String getAD_ID() { - long currentSecond = System.currentTimeMillis() / 1000; - return (currentSecond % 2 == 0) ? BANNER_POS_ID : - (GlobalApplication.isDebugging() ? BANNER_POS_ID_WINBOLL_BETA : BANNER_POS_ID_WINBOLL); - } - - /** - * 获取广告价格(原逻辑保留,添加空指针校验) - */ -// private long getPrice() { -// if (mBannerAd == null) { -// return 0; -// } -// Map map = mBannerAd.getMediaExtraInfo(); -// if (map == null || map.isEmpty() || !map.containsKey("price")) { -// LogUtils.w(TAG, "getPrice: media extra info is null or no price key"); -// return 0; -// } -// Object priceObj = map.get("price"); -// if (priceObj instanceof Long) { -// return (Long) priceObj; -// } else if (priceObj instanceof Integer) { -// return ((Integer) priceObj).longValue(); -// } else { -// LogUtils.e(TAG, "getPrice: price type is invalid"); -// return 0; -// } -// } - - /** - * 显示隐私协议弹窗(原逻辑保留,优化Context使用) - */ -// private void showPrivacy() { -// // 校验Activity状态,避免弹窗泄露 -// if (getActivity() == null || getActivity().isFinishing() || getActivity().isDestroyed()) { -// return; -// } -// ADsMode adsMode = ADsControlView.getAdsModeFromStatic(this.mContext); -// if (adsMode == ADsMode.STANDALONE) { -// ADsControlView.updateAdsModeByStatic(this.mContext, ADsMode.STANDALONE); -// LogUtils.i(TAG, "单机模式,广告已处于不可用状态..."); -// Toast.makeText(getActivity().getApplicationContext(), "单机模式,广告已处于不可用状态...", Toast.LENGTH_SHORT).show(); -// return; -// } else if (adsMode == ADsMode.MIMO_SDK) { -// ADsControlView.updateAdsModeByStatic(this.mContext, ADsMode.MIMO_SDK); -// LogUtils.i(TAG, "米盟广告SDK支持模式,现在初始化SDK..."); -// initMimoSdk(); -// return; -// } -// else { -// LogUtils.i(TAG, "开始弹出隐私协议..."); -// AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); -// builder.setTitle("用户须知"); -// builder.setMessage("小米广告SDK隐私政策: https://dev.mi.com/distribute/doc/details?pId=1688, 请复制到浏览器查看"); -// builder.setIcon(R.drawable.ic_launcher); -// builder.setCancelable(false); // 点击对话框以外的区域不消失 -// builder.setPositiveButton("同意", new DialogInterface.OnClickListener() { -// @Override -// public void onClick(DialogInterface dialog, int which) { -// getSharedPreferences().edit() -// .putString(PRIVACY_VALUE, String.valueOf(1)) -// .apply(); -// initMimoSdk(); -// dialog.dismiss(); -// } -// }); -// builder.setNegativeButton("拒绝", new DialogInterface.OnClickListener() { -// @Override -// public void onClick(DialogInterface dialog, int which) { -// getSharedPreferences().edit() -// .putString(PRIVACY_VALUE, String.valueOf(0)) -// .apply(); -// dialog.dismiss(); -// } -// }); -// AlertDialog dialog = builder.create(); -// -// // 配置弹窗位置(底部全屏) -// Window window = dialog.getWindow(); -// if (window != null) { -// window.setGravity(Gravity.BOTTOM); -// WindowManager m = getActivity().getWindowManager(); -// Display d = m.getDefaultDisplay(); -// WindowManager.LayoutParams p = window.getAttributes(); -// p.width = d.getWidth(); -// window.setAttributes(p); -// } -// dialog.show(); -// } -// } - - /** - * 初始化米盟SDK(核心修复:传递ApplicationContext + 异常捕获) - */ - private void initMimoSdk(Context context) { - // 1. 安全获取ApplicationContext,避免Activity Context失效 - Context appContext = context.getApplicationContext(); - if (appContext == null) { - LogUtils.e(TAG, "initMimoSdk: ApplicationContext is null"); - return; - } - // 2. 初始化SDK,捕获异常避免崩溃 - try { - MimoSdk.init(appContext, new MimoCustomController() { - @Override - public boolean isCanUseLocation() { - return true; - } - - @Override - public MimoLocation getMimoLocation() { - return null; - } - - @Override - public boolean isCanUseWifiState() { - return true; - } - - @Override - public boolean alist() { - return true; - } - }, new MimoSdk.InitCallback() { - @Override - public void success() { - LogUtils.d(TAG, "MimoSdk init success"); - } - - @Override - public void fail(int code, String msg) { - LogUtils.e(TAG, "MimoSdk init fail, code=" + code + ",msg=" + msg); - } - }); - MimoSdk.setDebugOn(true); - } catch (Exception e) { - LogUtils.e(TAG, "initMimoSdk: init failed", e); - } - } - - - /** - * 获取SharedPreferences实例(原逻辑保留,添加空指针校验) - */ -// SharedPreferences getSharedPreferences() { -//// if (mSharedPreferences == null) { -//// // 修复:使用ApplicationContext获取SharedPreferences,避免Activity Context泄露 -//// Context appContext = getActivity().getApplicationContext(); -//// if (appContext != null) { -//// mSharedPreferences = appContext.getSharedPreferences(PRIVACY_FILE, Context.MODE_PRIVATE); -//// } else { -//// LogUtils.e(TAG, "getSharedPreferences: ApplicationContext is null"); -//// // 降级方案:若ApplicationContext为空,使用Activity Context(仅作兼容) -//// mSharedPreferences = getActivity().getSharedPreferences(PRIVACY_FILE, Context.MODE_PRIVATE); -//// } -//// } -// return mSharedPreferences; -// } -} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsControlView.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsControlView.java deleted file mode 100644 index c24efca..0000000 --- a/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsControlView.java +++ /dev/null @@ -1,633 +0,0 @@ -package cc.winboll.studio.libaes.views; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.text.Html; -import android.util.AttributeSet; -import android.view.Display; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.PopupMenu; -import android.widget.PopupWindow; -import android.widget.RadioButton; -import android.widget.RadioGroup; -import android.widget.RelativeLayout; -import android.widget.TextView; -import android.widget.Toast; -import androidx.appcompat.app.AlertDialog; -import cc.winboll.studio.libaes.R; -import cc.winboll.studio.libaes.enums.ADsMode; -import cc.winboll.studio.libaes.enums.PrivacyAgreeStatus; -import cc.winboll.studio.libaes.utils.WebUtils; -import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.ToastUtils; -import com.miui.zeus.mimo.sdk.MimoCustomController; -import com.miui.zeus.mimo.sdk.MimoLocation; -import com.miui.zeus.mimo.sdk.MimoSdk; -import java.lang.reflect.Field; - -/** - * @Author ZhanGSKen&豆包大模型 - * @Date 2025/11/26 17:51 - * @LastEditTime 2026/01/08 11:00:00 HKT - * @Describe 广告模式控制控件(Java 7 兼容,云宝物语模式) - * 核心修改:将PopupMenu锚点绑定到view_popmenu_anchor_point控件,菜单精准显示在锚点位置 - */ -public class ADsControlView extends LinearLayout { - public static final String TAG = "ADsControlView"; - - // SP存储配置 - private static final String SP_NAME = "ads_control_config"; - private static final String KEY_SELECTED_MODE = "selected_ads_mode"; - ADsMode mADsMode; - private static final String PRIVACY_VALUE = "privacy_value"; - PrivacyAgreeStatus mPrivacyAgreeStatus; - - // Handler消息标识 - private static final int MSG_UPDATE_MODE = 1001; - - // 控件引用 - private RadioGroup rgADsMode; - private RadioButton rbStandalone; - private RadioButton rbMimoSDK; - private RadioButton rbStoreQrcode; - private RelativeLayout rlWinbollStore; - private ImageView ivWinbollStoreQrcode; - // 新增:锚点控件引用 - private TextView viewPopmenuAnchorPoint; - - // 外部监听、SP实例、Handler实例 - private OnAdsModeSelectedListener listener; - private SharedPreferences sharedPreferences; - private InternalHandler mHandler; - private Context mContext; - - // 静态列表:存储所有已创建的控件实例 - private static final java.util.List sControlViews = new java.util.ArrayList(); - - // 常量定义 - private static final String WECHAT_STORE_URL = "https://store.weixin.qq.com/shop/b/XhrPkZgoeHo4zug"; - private static final int MENU_ITEM_OPEN_STORE = 1001; - - // 构造方法(Java 7 兼容) - public ADsControlView(Context context) { - super(context); - initView(context); - } - - public ADsControlView(Context context, AttributeSet attrs) { - super(context, attrs); - initView(context); - } - - @SuppressWarnings("deprecation") - public ADsControlView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initView(context); - } - - public void setPrivacyAgreeStatus(PrivacyAgreeStatus privacyAgreeStatus) { - this.mPrivacyAgreeStatus = privacyAgreeStatus; - sharedPreferences.edit().putString(PRIVACY_VALUE, this.mPrivacyAgreeStatus.name()).apply(); - } - - public PrivacyAgreeStatus getPrivacyAgreeStatus() { - String privacyAgreeStatusStr = sharedPreferences.getString(PRIVACY_VALUE, PrivacyAgreeStatus.UN_SIGNED.name()); - PrivacyAgreeStatus privacyAgreeStatus = PrivacyAgreeStatus.fromString(privacyAgreeStatusStr); - return privacyAgreeStatus; - } - - public void setADsMode(ADsMode mADsMode) { - this.mADsMode = mADsMode; - sharedPreferences.edit().putString(KEY_SELECTED_MODE, this.mADsMode.name()).apply(); - updateStoreQrcodeLayoutVisibility(mADsMode); - } - - public ADsMode getADsMode() { - String savedModeStr = sharedPreferences.getString(KEY_SELECTED_MODE, ADsMode.STANDALONE.name()); - mADsMode = ADsMode.fromValue(savedModeStr); - return mADsMode; - } - - /** - * 初始化视图、SP、Handler - */ - private void initView(final Context context) { - this.mContext = context; - - // 加载布局 - LayoutInflater.from(context).inflate(R.layout.view_adscontrol, this, true); - - // 初始化SP - sharedPreferences = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE); - - // 绑定控件 - rgADsMode = (RadioGroup) findViewById(R.id.rg_ads_mode); - rbStandalone = (RadioButton) findViewById(R.id.rb_standalone); - rbMimoSDK = (RadioButton) findViewById(R.id.rb_mimo_sdk); - rbStoreQrcode = (RadioButton) findViewById(R.id.rb_store_qrcode); - rlWinbollStore = (RelativeLayout) findViewById(R.id.rl_winboll_store); - ivWinbollStoreQrcode = (ImageView) findViewById(R.id.iv_winboll_store); - // 绑定锚点控件 - viewPopmenuAnchorPoint = (TextView) findViewById(R.id.view_popmenu_anchor_point); - - // 初始化Handler - mHandler = new InternalHandler(Looper.getMainLooper()); - - // 核心修改:初始化图片的点击和长按事件(锚点改为view_popmenu_anchor_point) - initImageViewClickAndLongClick(); - - // 注册控件实例 - registerControlView(this); - - // 从SP读取初始模式 - setSelectedMode(getADsMode()); - - // 单选组选择事件监听 - rgADsMode.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(RadioGroup group, int checkedId) { - if (checkedId == R.id.rb_standalone) { - setADsMode(ADsMode.STANDALONE); - if (listener != null) listener.onModeSelected(ADsMode.STANDALONE); - } else if (checkedId == R.id.rb_mimo_sdk) { - handlePrivacyLogic((Activity) context, PrivacyAgreeStatus.UN_SIGNED, new OnPrivacyChangeListener() { - @Override - public void onAgreePrivacy() { - setADsMode(ADsMode.MIMO_SDK); - if (listener != null) listener.onModeSelected(ADsMode.MIMO_SDK); - } - - @Override - public void onDisagreePrivacy() { - setADsMode(ADsMode.STANDALONE); - setSelectedMode(ADsMode.STANDALONE); - if (listener != null) listener.onModeSelected(ADsMode.STANDALONE); - } - }); - } else if (checkedId == R.id.rb_store_qrcode) { - setADsMode(ADsMode.STORE_QRCODE); - if (listener != null) listener.onModeSelected(ADsMode.STORE_QRCODE); - } - } - }); - } - - /** - * 初始化图片的点击和长按事件 - * 核心:将PopupMenu锚点绑定到view_popmenu_anchor_point控件 - */ - private void initImageViewClickAndLongClick() { - if (ivWinbollStoreQrcode == null || viewPopmenuAnchorPoint == null) { - LogUtils.e(TAG, "initImageViewClickAndLongClick: 控件引用为空"); - return; - } - - // 1. 点击事件:简化为提示信息 - ivWinbollStoreQrcode.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - ToastUtils.show("长按图片可打开微信小店"); - LogUtils.d(TAG, "图片点击:提示用户长按打开微信小店"); - } - }); - - // 2. 长按事件:锚点改为view_popmenu_anchor_point - ivWinbollStoreQrcode.setOnLongClickListener(new OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - // 计算锚点控件的屏幕坐标(用于菜单位置微调) - int[] anchorLocation = new int[2]; - viewPopmenuAnchorPoint.getLocationOnScreen(anchorLocation); - final int anchorX = anchorLocation[0]; - final int anchorY = anchorLocation[1]; - - // 创建PopupMenu,锚点绑定到view_popmenu_anchor_point - PopupMenu popupMenu = new PopupMenu(mContext, viewPopmenuAnchorPoint); - // 设置菜单重力:相对锚点居中显示 - popupMenu.setGravity(Gravity.CENTER); - - Menu menu = popupMenu.getMenu(); - menu.add(Menu.NONE, MENU_ITEM_OPEN_STORE, Menu.NONE, "打开微信小店"); - - // 设置菜单点击事件 - popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - if (item.getItemId() == MENU_ITEM_OPEN_STORE) { - WebUtils.openUrlInBrowser(mContext, WECHAT_STORE_URL); - return true; - } - return false; - } - }); - - try { - // 反射获取PopupWindow,微调菜单位置(可选) - Field popupField = PopupMenu.class.getDeclaredField("mPopup"); - popupField.setAccessible(true); - Object popupObject = popupField.get(popupMenu); - if (popupObject instanceof PopupWindow) { - final PopupWindow popupWindow = (PopupWindow) popupObject; - popupWindow.setAnimationStyle(0); // 关闭默认动画 - - // 延迟微调菜单位置(确保布局测量完成) - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - int menuX = anchorX + viewPopmenuAnchorPoint.getWidth() / 2 - popupWindow.getWidth() / 2; - int menuY = anchorY + viewPopmenuAnchorPoint.getHeight() / 2 - popupWindow.getHeight() / 2; - if (!popupWindow.isShowing()) { - popupWindow.showAtLocation(viewPopmenuAnchorPoint, Gravity.NO_GRAVITY, menuX, menuY); - } - } - }, 30); - } - } catch (NoSuchFieldException | IllegalAccessException e) { - LogUtils.e(TAG, "反射获取PopupWindow失败", e); - } - - // 显示菜单 - popupMenu.show(); - LogUtils.d(TAG, "长按图片,菜单锚点为view_popmenu_anchor_point"); - return true; - } - }); - - // 设置控件可交互标识 - ivWinbollStoreQrcode.setClickable(true); - ivWinbollStoreQrcode.setFocusable(true); - ivWinbollStoreQrcode.setLongClickable(true); - viewPopmenuAnchorPoint.setClickable(false); // 锚点控件不可点击 - viewPopmenuAnchorPoint.setLongClickable(false); - } - - /** - * 从ImageView中提取Bitmap(保留方法,无实际调用) - */ - private Bitmap getBitmapFromImageView(ImageView imageView) { - Drawable drawable = imageView.getDrawable(); - if (drawable instanceof BitmapDrawable) { - return ((BitmapDrawable) drawable).getBitmap(); - } - return null; - } - - /** - * 压缩Bitmap(备用方法,无实际调用) - */ - private Bitmap compressBitmapBySize(Bitmap src, int maxWidth, int maxHeight) { - if (src == null) return null; - int width = src.getWidth(); - int height = src.getHeight(); - float scale = Math.min((float) maxWidth / width, (float) maxHeight / height); - int newWidth = (int) (width * scale); - int newHeight = (int) (height * scale); - return Bitmap.createScaledBitmap(src, newWidth, newHeight, true); - } - - /** - * 计算Bitmap采样率(备用方法,无实际调用) - */ - private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { - final int height = options.outHeight; - final int width = options.outWidth; - int inSampleSize = 1; - if (height > reqHeight || width > reqWidth) { - final int halfHeight = height / 2; - final int halfWidth = width / 2; - while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { - inSampleSize *= 2; - } - } - return inSampleSize; - } - - /** - * 从ImageView反射获取资源ID(备用方法,无实际调用) - */ - private int getResIdFromImageView(ImageView imageView) { - try { - Field field = ImageView.class.getDeclaredField("mSrcResource"); - field.setAccessible(true); - return field.getInt(imageView); - } catch (NoSuchFieldException | IllegalAccessException e) { - LogUtils.e(TAG, "getResIdFromImageView: 反射失败", e); - return 0; - } - } - - /** - * 更新二维码布局显示状态 - */ - private void updateStoreQrcodeLayoutVisibility(ADsMode mode) { - if (rlWinbollStore == null) return; - rlWinbollStore.setVisibility(mode == ADsMode.STORE_QRCODE ? View.VISIBLE : View.GONE); - } - - /** - * 清理SP中的隐私协议状态 - */ - public static void cleanPrivacyStatus(Context context) { - if (context == null) { - LogUtils.e(TAG, "cleanPrivacyStatus: Context is null"); - return; - } - SharedPreferences sp = getPrivacySharedPreferences(context); - sp.edit().remove(PRIVACY_VALUE).apply(); - LogUtils.i(TAG, "隐私协议状态清理成功"); - ToastUtils.show("隐私协议状态已清理"); - } - - /** - * 获取隐私协议SP实例 - */ - private static SharedPreferences getPrivacySharedPreferences(Context context) { - Context appContext = context.getApplicationContext(); - if (appContext != null) { - return appContext.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE); - } - return context.getSharedPreferences(PRIVACY_VALUE, Context.MODE_PRIVATE); - } - - /** - * 处理隐私协议逻辑 - */ - private static void handlePrivacyLogic(final Activity activity, PrivacyAgreeStatus privacyAgreeStatus, final OnPrivacyChangeListener onPrivacyChangeListener) { - if (privacyAgreeStatus == PrivacyAgreeStatus.REJECTED) { - Toast.makeText(activity.getApplicationContext(), "已拒绝隐私协议,广告已处于不可用状态", Toast.LENGTH_SHORT).show(); - return; - } else if (privacyAgreeStatus == PrivacyAgreeStatus.AGREED) { - initMimoSdkStatic(activity.getApplicationContext()); - return; - } else { - AlertDialog dialog = createPrivacyDialog(activity, onPrivacyChangeListener); - Window window = dialog.getWindow(); - if (window != null) { - window.setGravity(Gravity.BOTTOM); - WindowManager m = activity.getWindowManager(); - Display d = m.getDefaultDisplay(); - WindowManager.LayoutParams p = window.getAttributes(); - p.width = d.getWidth(); - window.setAttributes(p); - } - dialog.show(); - } - } - - /** - * 初始化米盟SDK - */ - private static void initMimoSdkStatic(Context appContext) { - if (appContext == null) return; - try { - MimoSdk.init(appContext, new MimoCustomController() { - @Override - public boolean isCanUseLocation() { - return true; - } - - @Override - public MimoLocation getMimoLocation() { - return null; - } - - @Override - public boolean isCanUseWifiState() { - return true; - } - - @Override - public boolean alist() { - return true; - } - }, new MimoSdk.InitCallback() { - @Override - public void success() { - LogUtils.d(TAG, "米盟SDK初始化成功"); - } - - @Override - public void fail(int code, String msg) { - LogUtils.e(TAG, "米盟SDK初始化失败:" + code + ", " + msg); - } - }); - MimoSdk.setDebugOn(true); - } catch (Exception e) { - LogUtils.e(TAG, "米盟SDK初始化异常", e); - } - } - - /** - * 静态方法:更新SP中的模式 - */ - public static void updateAdsModeByStatic(Context context, ADsMode mode) { - if (context == null || mode == null) return; - SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE); - sp.edit().putString(KEY_SELECTED_MODE, mode.name()).apply(); - InternalHandler.sendUpdateModeMessage(mode); - } - - /** - * 静态方法:读取SP中的模式 - */ - public static ADsMode getAdsModeFromStatic(Context context) { - if (context == null) return ADsMode.STANDALONE; - SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE); - String savedModeStr = sp.getString(KEY_SELECTED_MODE, ADsMode.STANDALONE.name()); - return ADsMode.fromValue(savedModeStr); - } - - /** - * 注册控件实例 - */ - private static void registerControlView(ADsControlView view) { - synchronized (sControlViews) { - if (!sControlViews.contains(view)) { - sControlViews.add(view); - } - } - } - - /** - * 移除控件实例 - */ - private static void unregisterControlView(ADsControlView view) { - synchronized (sControlViews) { - sControlViews.remove(view); - } - } - - /** - * 设置选中模式 - */ - private void setSelectedMode(final ADsMode mode) { - final ADsMode mode2 = (mode == null) ? ADsMode.STANDALONE : mode; - if (Looper.myLooper() == Looper.getMainLooper()) { - if (mode2 == ADsMode.STANDALONE) { - rbStandalone.setChecked(true); - } else if (mode2 == ADsMode.MIMO_SDK) { - rbMimoSDK.setChecked(true); - } else if (mode2 == ADsMode.STORE_QRCODE) { - rbStoreQrcode.setChecked(true); - } - updateStoreQrcodeLayoutVisibility(mode2); - } else { - mHandler.post(new Runnable() { - @Override - public void run() { - setSelectedMode(mode2); - } - }); - } - } - - /** - * 获取选中模式 - */ - public ADsMode getSelectedMode() { - int checkedId = rgADsMode.getCheckedRadioButtonId(); - if (checkedId == R.id.rb_mimo_sdk) { - return ADsMode.MIMO_SDK; - } else if (checkedId == R.id.rb_store_qrcode) { - return ADsMode.STORE_QRCODE; - } else { - return ADsMode.STANDALONE; - } - } - - /** - * 设置外部监听 - */ - public void setOnAdsModeSelectedListener(OnAdsModeSelectedListener listener) { - this.listener = listener; - } - - /** - * 内部Handler类 - */ - private static class InternalHandler extends Handler { - static volatile InternalHandler _InternalHandler; - - public InternalHandler(Looper looper) { - super(looper); - _InternalHandler = this; - } - - public static void sendUpdateModeMessage(ADsMode mode) { - if (mode == null || _InternalHandler == null) return; - Message msg = _InternalHandler.obtainMessage(); - msg.what = MSG_UPDATE_MODE; - msg.obj = mode; - _InternalHandler.sendMessage(msg); - } - - @Override - public void handleMessage(Message msg) { - super.handleMessage(msg); - if (msg.what == MSG_UPDATE_MODE) { - ADsMode mode = (ADsMode) msg.obj; - if (mode == null) return; - synchronized (sControlViews) { - for (ADsControlView view : sControlViews) { - if (view != null && view.isShown() && view.isAttachedToWindow()) { - view.setSelectedMode(mode); - view.updateStoreQrcodeLayoutVisibility(mode); - } - } - } - } - } - } - - /** - * 生命周期:控件销毁 - */ - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mHandler != null) { - mHandler.removeCallbacksAndMessages(null); - } - unregisterControlView(this); - } - - /** - * 外部监听接口 - */ - public interface OnAdsModeSelectedListener { - void onModeSelected(ADsMode selectedMode); - } - - /** - * 隐私协议监听接口 - */ - public interface OnPrivacyChangeListener { - void onAgreePrivacy(); - void onDisagreePrivacy(); - } - - /** - * 创建隐私协议对话框 - */ - private static AlertDialog createPrivacyDialog(final Activity activity, final OnPrivacyChangeListener onPrivacyChangeListener) { - View dialogView = LayoutInflater.from(activity).inflate(R.layout.dialog_privacy_agreement, null); - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setView(dialogView).setCancelable(false); - final AlertDialog dialog = builder.create(); - - final TextView tvPrivacyUrl = (TextView) dialogView.findViewById(R.id.tv_privacy_url); - Button btnAgree = (Button) dialogView.findViewById(R.id.btn_agree); - Button btnDisagree = (Button) dialogView.findViewById(R.id.btn_disagree); - - tvPrivacyUrl.setText(Html.fromHtml("" + tvPrivacyUrl.getText().toString() + "")); - tvPrivacyUrl.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - String url = tvPrivacyUrl.getText().toString().trim(); - ToastUtils.show("隐私协议链接:" + url); - } - }); - tvPrivacyUrl.setClickable(true); - tvPrivacyUrl.setFocusable(true); - - btnAgree.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (onPrivacyChangeListener != null) { - onPrivacyChangeListener.onAgreePrivacy(); - } - dialog.dismiss(); - } - }); - - btnDisagree.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (onPrivacyChangeListener != null) { - onPrivacyChangeListener.onDisagreePrivacy(); - } - dialog.dismiss(); - } - }); - - return dialog; - } -} - diff --git a/libaes/src/main/res/layout/activity_drawerfragment.xml b/libaes/src/main/res/layout/activity_drawerfragment.xml index 6c314df..4f727b5 100644 --- a/libaes/src/main/res/layout/activity_drawerfragment.xml +++ b/libaes/src/main/res/layout/activity_drawerfragment.xml @@ -56,10 +56,5 @@ - -