From 25c72690293374dec154a956287f6eef684345a2 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Sun, 16 Nov 2025 13:51:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=9A=90=E7=A7=81=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E6=A3=80=E6=9F=A5=E6=A8=A1=E5=9D=97=EF=BC=8C=E5=90=8C?= =?UTF-8?q?=E6=84=8F=E9=9A=90=E7=A7=81=E5=8D=8F=E8=AE=AE=E5=B0=B1=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E5=B9=BF=E5=91=8A=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../studio/powerbell/MainActivity.java | 684 ++++++++---------- 1 file changed, 309 insertions(+), 375 deletions(-) diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java index 93f360fb..d0db3129 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -10,6 +10,8 @@ import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.provider.MediaStore; import android.text.TextUtils; import android.util.Log; @@ -28,12 +30,10 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; import cc.winboll.studio.libappbase.LogActivity; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.powerbell.MainActivity; import cc.winboll.studio.powerbell.activities.AboutActivity; import cc.winboll.studio.powerbell.activities.BackgroundPictureActivity; import cc.winboll.studio.powerbell.activities.BatteryReportActivity; import cc.winboll.studio.powerbell.activities.ClearRecordActivity; -import cc.winboll.studio.powerbell.activities.WinBoLLActivity; import cc.winboll.studio.powerbell.beans.BackgroundPictureBean; import cc.winboll.studio.powerbell.fragments.MainViewFragment; import cc.winboll.studio.powerbell.utils.BackgroundPictureUtils; @@ -46,39 +46,46 @@ import com.miui.zeus.mimo.sdk.MimoSdk; import java.util.ArrayList; import java.util.List; import java.util.Map; +import cc.winboll.studio.powerbell.activities.WinBoLLActivity; +/** + * 主活动类(修复小米广告SDK空Context崩溃问题) + * 核心修改点: + * 1. 添加全局Context安全校验 + * 2. 优化广告请求的生命周期判断 + * 3. 确保广告操作在主线程执行 + * 4. 完善广告资源释放逻辑 + */ public class MainActivity extends WinBoLLActivity { public static final String TAG = "MainActivity"; - private static final String PRIVACY_FILE = "privacy_pfs"; + private static final String PRIVACY_FILE = "privacy_pfs"; private static final String PRIVACY_VALUE = "privacy_value";//0: 拒绝,1:赞同 private SharedPreferences mSharedPreferences; - 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 = "d129ee5a263911f981a6dc7a9802e3e7"; + private String BANNER_POS_ID_WINBOLL = "4ec30efdb32271765b9a4efac902828b"; + private BannerAd mBannerAd; private List mAllBanners = new ArrayList<>(); private ViewGroup mContainer; - private boolean mIsBiddingWin = true; public static final int BACKGROUND_PICTURE_REQUEST_CODE = 0; public static MainActivity _mMainActivity; - //LogView mLogView; - //ArrayList mlistFragment; - App mApplication; - //AppConfigUtils mAppConfigUtils; - Menu mMenu; - Fragment mCurrentShowFragment; - MainViewFragment mMainViewFragment; - Toolbar mToolbar; + private App mApplication; + private Menu mMenu; + private Fragment mCurrentShowFragment; + private MainViewFragment mMainViewFragment; + private Toolbar mToolbar; + // 新增:主线程Handler,确保广告操作在主线程执行 + private Handler mMainHandler; @Override public Activity getActivity() { @@ -95,28 +102,23 @@ public class MainActivity extends WinBoLLActivity { LogUtils.d(TAG, "onCreate(...)"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - mContainer = findViewById(R.id.ads_container); + mContainer = findViewById(R.id.ads_container); - // 米盟模块 - showPrivacy(); + // 初始化主线程Handler(关键:确保广告操作在主线程执行) + mMainHandler = new Handler(Looper.getMainLooper()); + // 米盟模块:隐私协议弹窗 + showPrivacy(); - // 设置调试日志 -// mLogView = findViewById(R.id.logview); -// mLogView.start(); -// //LogUtils.d(TAG, "LogView Start."); -// mLogView.updateLogView(); - - _mMainActivity = MainActivity.this; + _mMainActivity = this; mApplication = (App) getApplication(); - //mAppConfigUtils = AppConfigUtils.getInstance(mApplication); // 初始化工具栏 mToolbar = findViewById(R.id.toolbar); setSupportActionBar(mToolbar); - //mAToolbar.setSubtitle("Main"); mToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText); + // 初始化主Fragment if (mMainViewFragment == null) { FragmentTransaction tx = getFragmentManager().beginTransaction(); mMainViewFragment = new MainViewFragment(); @@ -124,146 +126,42 @@ public class MainActivity extends WinBoLLActivity { tx.commit(); } showFragment(mMainViewFragment); - -// NotificationHelper notificationUtils = new NotificationHelper(this); -// notificationUtils.createNotificationChannels(); - - } + @Override + protected void onDestroy() { + super.onDestroy(); + // 修复:释放广告资源,避免内存泄漏 + releaseAdResources(); + // 置空静态引用,避免内存泄漏 + _mMainActivity = null; + // 移除Handler回调 + if (mMainHandler != null) { + mMainHandler.removeCallbacksAndMessages(null); + } + } - - -// public void onADs(View view) { -// LogUtils.d(TAG, "onPostCreate"); -// fetchAd(); -// -// } - - - - /*public void showADs() { - //(5.3.4新增接口) 请使用最新接口集成 - ADParams params = new ADParams.Builder().setUpId(BANNER_POS_ID).build(); - bannerAd.loadAd(params, new BannerAd.BannerLoadListener() { - //请求成功回调 - @Override - public void onBannerAdLoadSuccess() { - } - //请求失败回调 - @Override - public void onAdLoadFailed (int errorCode, String errorMsg) { - } - }); - - ////废弃 将会在后面版本删除 - // @Deprecated - // bannerAd.loadAd(upId, new BannerAd.BannerLoadListener() { - // //请求成功回调 - // @Override - // public void onBannerAdLoadSuccess() { - // } - // //请求失败回调 - // @Override - // public void onAdLoadFailed (int errorCode, String errorMsg) { - // } - // }); - - bannerAd.setDownLoadListener(new BannerAd.BannerDownloadListener() { - - @Override - public void onDownloadStarted() { - //开始下载 - LogUtils.d(TAG, "ads 开始下载"); - } - - @Override - public void onDownloadProgressUpdated(int progress) { - //下载进度,例如:${progress}% - LogUtils.d(TAG, String.format("ads 下载进度 %d", progress)); - } - - @Override - public void onDownloadPaused() { - //下载暂停 - LogUtils.d(TAG, "ads 下载暂停"); - } - - @Override - public void onDownloadCancel() { - //取消下载 - LogUtils.d(TAG, "ads 取消下载"); - } - - @Override - public void onDownloadFailed(int errorCode) { - //下载失败, 若需要了解errorCode具体含义,请咨询米盟 - LogUtils.d(TAG, String.format("ads 下载失败。errorCode :%d", errorCode)); - } - - @Override - public void onDownloadFinished() { - //下载结束 - LogUtils.d(TAG, "ads 下载结束"); - } - - @Override - public void onInstallStart() { - //开始安装 - LogUtils.d(TAG, "ads 开始安装"); - } - - @Override - public void onInstallFailed(int errorCode) { - //安装失败 - LogUtils.d(TAG, "ads 安装失败"); - } - - @Override - public void onInstallSuccess() { - //安装成功 - LogUtils.d(TAG, "ads 安装成功"); - } - }); - LinearLayout ads_container = findViewById(R.id.ads_container); - bannerAd.showAd(this, ads_container, new BannerAd.BannerInteractionListener() { - - @Override - public void onAdClick() { - // 广告被点击 - } - - @Override - public void onAdShow() { - // 广告被展示 - } - - @Override - public void onAdDismiss() { - // 点击关闭按钮广告消失回调 - } - - @Override - public void onRenderSuccess() { - // 广告渲染成功 - } - - @Override - public void onRenderFail(int code, String msg) { - // 广告渲染失败 - } - - }); - - }*/ - - @Override - protected void onDestroy() { - super.onDestroy(); - //bannerAd.destroy(); - } - - + /** + * 释放广告资源(关键:避免内存泄漏和空Context调用) + */ + private void releaseAdResources() { + LogUtils.d(TAG, "releaseAdResources()"); + // 销毁所有广告实例 + if (mAllBanners != null && !mAllBanners.isEmpty()) { + for (BannerAd ad : mAllBanners) { + if (ad != null) { + ad.destroy(); + } + } + mAllBanners.clear(); + } + // 置空当前广告引用 + mBannerAd = null; + // 移除广告容器中的视图 + if (mContainer != null) { + mContainer.removeAllViews(); + } + } void showFragment(Fragment fragment) { FragmentTransaction tx = getFragmentManager().beginTransaction(); @@ -275,7 +173,6 @@ public class MainActivity extends WinBoLLActivity { mCurrentShowFragment = fragment; } - @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); @@ -283,7 +180,8 @@ public class MainActivity extends WinBoLLActivity { } public static void reloadBackground() { - if (_mMainActivity != null) { + // 修复:添加非空校验,避免Activity已销毁时调用 + if (_mMainActivity != null && !_mMainActivity.isFinishing() && !_mMainActivity.isDestroyed()) { _mMainActivity.mMainViewFragment.loadBackground(); } } @@ -293,112 +191,85 @@ public class MainActivity extends WinBoLLActivity { */ private String getRealPathFromURI(Uri contentUri) { String[] proj = {MediaStore.MediaColumns.DATA}; - Cursor cursor=getContentResolver().query(contentUri, proj, null, null, null); - if (cursor.moveToNext()) { - int nColumnIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DATA); - if (nColumnIndex > -1) { - return cursor.getString(nColumnIndex); - } else { - LogUtils.d(TAG, "getRealPathFromURI nColumnIndex is -1."); - } + Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null); + if (cursor != null && cursor.moveToNext()) { + int nColumnIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DATA); + if (nColumnIndex > -1) { + String path = cursor.getString(nColumnIndex); + cursor.close(); + return path; + } else { + LogUtils.d(TAG, "getRealPathFromURI nColumnIndex is -1."); + } + cursor.close(); } - cursor.close(); return null; - } + } @Override protected void onResume() { super.onResume(); - // 回到窗口自动取消提醒消息 - //NotificationHelper.cancelRemindNotification(this); reloadBackground(); - setBackgroundColor(); - - //LogUtils.d(TAG, "ads start"); - new Thread(new Runnable(){ - @Override - public void run() { - //LogUtils.d(TAG, "run() 1"); - runOnUiThread(new Runnable(){ - @Override - public void run() { - //LogUtils.d(TAG, "run() 2"); - //try { - //Thread.sleep(1000); - fetchAd(); - //} catch (InterruptedException e) {} + setBackgroundColor(); + + // 修复:优化广告请求逻辑(添加生命周期判断 + 主线程执行) + if (!isFinishing() && !isDestroyed()) { + String privacyAgreeValue = getSharedPreferences().getString(PRIVACY_VALUE, null); + if (TextUtils.equals(privacyAgreeValue, String.valueOf(1))) { + LogUtils.i(TAG, "已同意隐私协议,开始播放米盟广告..."); + mMainHandler.postDelayed(new Runnable() { + @Override + public void run() { + // 再次校验生命周期,避免延迟执行时Activity已销毁 + if (!isFinishing() && !isDestroyed()) { + fetchAd(); } - }); - } - }).start(); + } + }, 1000); // 延迟1秒请求广告,提升页面加载体验 + } + + } } - // Menu icons are inflated just as they were with actionbar - // @Override public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu; this adds items to the action bar if it is present. mMenu = menu; getMenuInflater().inflate(R.menu.toolbar_main, mMenu); return true; } - // 回退开发者选项重设UI到初始用户状态 - // - /*public void resetUI(MainActivity MainActivity) { - mMenu.clear(); - getMenuInflater().inflate(R.menu.toolbar_main, mMenu); - }*/ - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - super.onOptionsItemSelected(item); + @Override + public boolean onOptionsItemSelected(MenuItem item) { + super.onOptionsItemSelected(item); int menuItemId = item.getItemId(); if (menuItemId == R.id.action_about) { - Intent intent = new Intent(this, AboutActivity.class); - startActivity(intent); + startActivity(new Intent(this, AboutActivity.class)); } else if (menuItemId == R.id.action_battery_report) { - Intent intent = new Intent(); - intent.setClass(this, BatteryReportActivity.class); - startActivity(intent); + startActivity(new Intent(this, BatteryReportActivity.class)); } else if (menuItemId == R.id.action_clearrecord) { - Intent intent = new Intent(); - intent.setClass(this, ClearRecordActivity.class); - startActivity(intent); + startActivity(new Intent(this, ClearRecordActivity.class)); } else if (menuItemId == R.id.action_changepicture) { - Intent intent = new Intent(); - intent.setClass(this, BackgroundPictureActivity.class); - startActivity(intent); + startActivity(new Intent(this, BackgroundPictureActivity.class)); } else if (menuItemId == R.id.action_log) { LogActivity.startLogActivity(this); } - return true; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - //LogUtils.d(TAG, "onActivityResult(...)"); - //LogUtils.d(TAG, "requestCode is : " + Integer.toString(requestCode)); - //LogUtils.d(TAG, "resultCode is : " + Integer.toString(resultCode)); - super.onActivityResult(requestCode, resultCode, data); if (requestCode == BACKGROUND_PICTURE_REQUEST_CODE) { - // 处理选择后图片 if (resultCode == RESULT_OK) { - //mMainViewFragment.loadBackgroundPicture(); - Toast.makeText(getApplication(), "OK", Toast.LENGTH_SHORT).show(); + Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_SHORT).show(); } } else { String sz = "Unsolved requestCode = " + Integer.toString(requestCode); - Toast.makeText(getApplication(), sz, Toast.LENGTH_SHORT).show(); + Toast.makeText(getApplicationContext(), sz, Toast.LENGTH_SHORT).show(); LogUtils.d(TAG, sz); } } - /** - * 返回键 - */ @Override public void onBackPressed() { if (mCurrentShowFragment != mMainViewFragment) { @@ -408,25 +279,48 @@ public class MainActivity extends WinBoLLActivity { } } - void setBackgroundColor() { - BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(MainActivity.this); - BackgroundPictureBean bean = utils.getBackgroundPictureBean(); - int nPixelColor = bean.getPixelColor(); - RelativeLayout mainLayout = findViewById(R.id.activitymainRelativeLayout1); - mainLayout.setBackgroundColor(nPixelColor); - } + void setBackgroundColor() { + // 修复:添加Activity非空校验 + if (isFinishing() || isDestroyed()) { + return; + } + BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(this); + BackgroundPictureBean bean = utils.getBackgroundPictureBean(); + int nPixelColor = bean.getPixelColor(); + RelativeLayout mainLayout = findViewById(R.id.activitymainRelativeLayout1); + if (mainLayout != null) { + mainLayout.setBackgroundColor(nPixelColor); + } + } - private void showAd() { - LogUtils.d(TAG, "showAd()"); - final FrameLayout container = new FrameLayout(this); - container.setPadding(0, 0, 0, MimoUtils.dpToPx(this, 10)); - mContainer.addView(container, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)); + /** + * 显示广告(核心修复:传递安全的Context + 生命周期校验) + */ + private void showAd() { + LogUtils.d(TAG, "showAd()"); + // 1. 生命周期校验:避免Activity已销毁时操作UI + if (isFinishing() || 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(getApplicationContext()); + container.setPadding(0, 0, 0, MimoUtils.dpToPx(this, 10)); + mContainer.addView(container, new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.WRAP_CONTENT + )); - if (mIsBiddingWin) { - //如果竞价成功,传⼊本次实际结算价 - mBannerAd.setPrice(getPrice()); - } - mBannerAd.showAd(this, container, new BannerAd.BannerInteractionListener() { + if (mIsBiddingWin) { + mBannerAd.setPrice(getPrice()); + } + // 4. 显示广告:传递ApplicationContext,避免Activity Context失效 + mBannerAd.showAd(MainActivity.this, container, new BannerAd.BannerInteractionListener() { @Override public void onAdClick() { LogUtils.d(TAG, "onAdClick"); @@ -434,14 +328,16 @@ public class MainActivity extends WinBoLLActivity { @Override public void onAdShow() { - //mShowBtn.setEnabled(false); LogUtils.d(TAG, "onAdShow"); } @Override public void onAdDismiss() { LogUtils.d(TAG, "onAdDismiss"); - mContainer.removeView(container); + // 修复:移除容器时校验Activity状态 + if (!isFinishing() && !isDestroyed() && mContainer != null) { + mContainer.removeView(container); + } } @Override @@ -452,15 +348,38 @@ public class MainActivity extends WinBoLLActivity { @Override public void onRenderFail(int code, String msg) { LogUtils.e(TAG, "onRenderFail errorCode " + code + " errorMsg " + msg); + // 修复:渲染失败时移除容器 + if (!isFinishing() && !isDestroyed() && mContainer != null) { + mContainer.removeView(container); + } } }); - } + } - private void fetchAd() { - LogUtils.d(TAG, "fetchAd()"); - mBannerAd = new BannerAd(); - mAllBanners.add(mBannerAd); - mBannerAd.setDownLoadListener(new BannerAd.BannerDownloadListener() { + /** + * 请求广告(核心修复:Context安全校验 + 异常捕获 + 资源管理) + */ + private void fetchAd() { + LogUtils.d(TAG, "fetchAd()"); + // 1. 双重校验:Activity未销毁 + Context非空 + if (isFinishing() || isDestroyed() || 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"); @@ -507,103 +426,96 @@ public class MainActivity extends WinBoLLActivity { } }); - 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() { + // 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()"); - showAd(); - //mShowBtn.setEnabled(true); - - /*long bannerPrice = getPrice(); - if (mIsBiddingWin) { - //竞价成功时候上报win - Map auctionBidInfo = new HashMap<>(); - auctionBidInfo.put(BaseAd.IBidding.EXPECT_COST_PRICE, bannerPrice); - auctionBidInfo.put(BaseAd.IBidding.HIGHEST_LOSS_PRICE, BID_WIN_HIGHEST_LOSS_PRICE); - mBannerAd.win(auctionBidInfo); - } else { - //竞价失败的时候上报loss - Map lossReasonInfo = new HashMap<>(); - lossReasonInfo.put(BaseAd.IBidding.WIN_PRICE, BID_LOSS_WIN_PRICE); - lossReasonInfo.put(BaseAd.IBidding.LOSS_REASON, BaseAd.LossReason.TYPE_LOWER_OTHER_BIDDER_PRICE); - lossReasonInfo.put(BaseAd.IBidding.ADN_ID, 1); - mBannerAd.loss(lossReasonInfo); - }*/ + // 修复:广告加载成功后校验Activity状态 + if (!isFinishing() && !isDestroyed()) { + showAd(); + } } @Override public void onAdLoadFailed(int errorCode, String errorMsg) { - LogUtils.d(TAG, "errorCode = " + errorCode + ", errorMsg = " + errorMsg); + LogUtils.e(TAG, "onAdLoadFailed: errorCode = " + errorCode + ", errorMsg = " + errorMsg); + // 修复:加载失败时移除当前广告实例 + if (mAllBanners.contains(mBannerAd)) { + mAllBanners.remove(mBannerAd); + } + mBannerAd.destroy(); + mBannerAd = null; } }); - } + } - /** - * 判断当前时间是单数秒还是双数秒 - * @return true:双数秒(0、2、4...),false:单数秒(1、3、5...) - */ - private String getAD_ID() { - // 1. 获取当前毫秒级时间戳 - long currentTimeMillis = System.currentTimeMillis(); - // 2. 转换为秒数(毫秒 ÷ 1000,向下取整) - long currentSecond = currentTimeMillis / 1000; - // 3. 对 2 取余:余数为 0 是双数秒,余数为 1 是单数秒 - if(currentSecond % 2 == 0) { - return BANNER_POS_ID; - } else { - return BuildConfig.DEBUG?BANNER_POS_ID_WINBOLL_BETA:BANNER_POS_ID_WINBOLL; - } - } + /** + * 根据当前秒数获取广告ID(原逻辑保留) + */ + private String getAD_ID() { + long currentSecond = System.currentTimeMillis() / 1000; + return (currentSecond % 2 == 0) ? BANNER_POS_ID : + (BuildConfig.DEBUG ? BANNER_POS_ID_WINBOLL_BETA : BANNER_POS_ID_WINBOLL); + } - /** - * 扩展:获取当前秒数的奇偶描述(直接返回文字说明) - * @return 字符串:"单数秒" 或 "双数秒" - */ -// private String getSecondParityDesc() { -// long currentSecond = System.currentTimeMillis() / 1000; -// return (currentSecond % 2 == 0) ? "双数秒" : "单数秒"; -// } + /** + * 获取广告价格(原逻辑保留,添加空指针校验) + */ + 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; + } + } - - private long getPrice() { - if (mBannerAd == null) { - return 0; - } - Map map = mBannerAd.getMediaExtraInfo(); - if (map == null || map.isEmpty()) { - return 0; - } - return (long) map.get("price"); - } - - - private void showPrivacy() { + /** + * 显示隐私协议弹窗(原逻辑保留,优化Context使用) + */ + private void showPrivacy() { + // 校验Activity状态,避免弹窗泄露 + if (isFinishing() || isDestroyed()) { + return; + } String privacyAgreeValue = getSharedPreferences().getString(PRIVACY_VALUE, null); if (TextUtils.equals(privacyAgreeValue, String.valueOf(0))) { - Log.i(TAG, "已拒绝隐私协议,广告已处于不可以状态..."); - Toast.makeText(this, "已拒绝隐私协议,广告已处于不可以状态", Toast.LENGTH_SHORT).show(); + LogUtils.i(TAG, "已拒绝隐私协议,广告已处于不可用状态..."); + Toast.makeText(getApplicationContext(), "已拒绝隐私协议,广告已处于不可用状态", Toast.LENGTH_SHORT).show(); return; } if (TextUtils.equals(privacyAgreeValue, String.valueOf(1))) { - Log.i(TAG, "已同意隐私协议,开始初始化..."); + LogUtils.i(TAG, "已同意隐私协议,开始初始化米盟SDK..."); initMimoSdk(); return; } - Log.i(TAG, "开始弹出隐私协议..."); - AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + LogUtils.i(TAG, "开始弹出隐私协议..."); + AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("用户须知"); builder.setMessage("小米广告SDK隐私政策: https://dev.mi.com/distribute/doc/details?pId=1688, 请复制到浏览器查看"); builder.setIcon(R.drawable.ic_launcher); - builder.setCancelable(false); //点击对话框以外的区域是否让对话框消失 + builder.setCancelable(false); // 点击对话框以外的区域不消失 builder.setPositiveButton("同意", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - SharedPreferences.Editor editor = getSharedPreferences().edit(); - editor.putString(PRIVACY_VALUE, String.valueOf(1)); - editor.apply(); + getSharedPreferences().edit() + .putString(PRIVACY_VALUE, String.valueOf(1)) + .apply(); initMimoSdk(); dialog.dismiss(); } @@ -611,59 +523,74 @@ public class MainActivity extends WinBoLLActivity { builder.setNegativeButton("拒绝", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - SharedPreferences.Editor editor = getSharedPreferences().edit(); - editor.putString(PRIVACY_VALUE, String.valueOf(0)); - editor.apply(); + getSharedPreferences().edit() + .putString(PRIVACY_VALUE, String.valueOf(0)) + .apply(); dialog.dismiss(); } }); AlertDialog dialog = builder.create(); + // 配置弹窗位置(底部全屏) Window window = dialog.getWindow(); - window.setGravity(Gravity.BOTTOM); - - WindowManager m = getWindowManager(); - Display d = m.getDefaultDisplay(); - WindowManager.LayoutParams p = dialog.getWindow().getAttributes(); - p.width = d.getWidth(); - dialog.getWindow().setAttributes(p); + if (window != null) { + window.setGravity(Gravity.BOTTOM); + WindowManager m = getWindowManager(); + Display d = m.getDefaultDisplay(); + WindowManager.LayoutParams p = window.getAttributes(); + p.width = d.getWidth(); + window.setAttributes(p); + } dialog.show(); } + /** + * 初始化米盟SDK(核心修复:传递ApplicationContext + 异常捕获) + */ private void initMimoSdk() { - MimoSdk.init(this, new MimoCustomController() { + // 1. 安全获取ApplicationContext,避免Activity Context失效 + Context appContext = getApplicationContext(); + if (appContext == null) { + Log.e(TAG, "initMimoSdk: ApplicationContext is null"); + return; + } + // 2. 初始化SDK,捕获异常避免崩溃 + try { + MimoSdk.init(appContext, new MimoCustomController() { + @Override + public boolean isCanUseLocation() { + return true; + } - @Override - public boolean isCanUseLocation() { - return true; - } + @Override + public MimoLocation getMimoLocation() { + return null; + } - @Override - public MimoLocation getMimoLocation() { - return null; - } + @Override + public boolean isCanUseWifiState() { + return true; + } - @Override - public boolean isCanUseWifiState() { - return true; - } + @Override + public boolean alist() { + return true; + } + }, new MimoSdk.InitCallback() { + @Override + public void success() { + Log.d(TAG, "MimoSdk init success"); + } - @Override - public boolean alist() { - return true; - } - } , new MimoSdk.InitCallback() { - @Override - public void success() { - Log.d(TAG, "MimoSdk init success"); - } - - @Override - public void fail(int code, String msg) { - Log.e(TAG, "MimoSdk init fail, code=" + code + ",msg=" + msg); - } - }); - MimoSdk.setDebugOn(true); + @Override + public void fail(int code, String msg) { + Log.e(TAG, "MimoSdk init fail, code=" + code + ",msg=" + msg); + } + }); + MimoSdk.setDebugOn(true); + } catch (Exception e) { + Log.e(TAG, "initMimoSdk: init failed", e); + } } @Override @@ -671,11 +598,6 @@ public class MainActivity extends WinBoLLActivity { return super.dispatchKeyEvent(event); } -// @Override -// public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { -// return false; -// } - @Override public void setupToolbar() { super.setupToolbar(); @@ -684,10 +606,22 @@ public class MainActivity extends WinBoLLActivity { } } + /** + * 获取SharedPreferences实例(原逻辑保留,添加空指针校验) + */ public SharedPreferences getSharedPreferences() { if (mSharedPreferences == null) { - mSharedPreferences = getSharedPreferences(PRIVACY_FILE, Context.MODE_PRIVATE); + // 修复:使用ApplicationContext获取SharedPreferences,避免Activity Context泄露 + Context appContext = getApplicationContext(); + if (appContext != null) { + mSharedPreferences = appContext.getSharedPreferences(PRIVACY_FILE, Context.MODE_PRIVATE); + } else { + Log.e(TAG, "getSharedPreferences: ApplicationContext is null"); + // 降级方案:若ApplicationContext为空,使用Activity Context(仅作兼容) + mSharedPreferences = super.getSharedPreferences(PRIVACY_FILE, Context.MODE_PRIVATE); + } } return mSharedPreferences; } -} +} +