@@ -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,37 +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 = " d129ee5a263911f981a6dc7a9802e3e7 " ;
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 < BannerAd > 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<Fragment> 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 ( ) {
@@ -93,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 ( ) ;
@@ -122,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 ( ) ;
@@ -273,7 +173,6 @@ public class MainActivity extends WinBoLLActivity {
mCurrentShowFragment = fragment ;
}
@Override
protected void onPostCreate ( Bundle savedInstanceState ) {
super . onPostCreate ( savedInstanceState ) ;
@@ -281,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 ( ) ;
}
}
@@ -291,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") ;
runOnUiThrea d( 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 . postDelaye d( 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 i ntent = new Intent ( ) ;
intent . setClass ( this , BatteryReportActivity . class ) ;
startActivity ( intent ) ;
startActivity ( new I ntent( 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 i ntent = new Intent ( ) ;
intent . setClass ( this , BackgroundPictureActivity . class ) ;
startActivity ( intent ) ;
startActivity ( new I ntent( 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 ) {
@@ -406,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 " ) ;
@@ -432,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
@@ -450,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 " ) ;
@@ -505,99 +426,96 @@ public class MainActivity extends WinBoLLActivity {
}
} ) ;
String currentAD_ID = isEvenSecond ( ) ? BANNER_POS_ID_WINBOLL : BANNER_POS_ID ;
LogUtils . d ( TAG , String . format ( " currentAD_ID = %s " , curren tAD_ID) ) ;
ADParams params = new ADParams . Builder ( ) . setUpId ( currentAD_ID ) . build ( );
mBannerAd . loadAd ( params , new BannerAd . BannerLoadListener ( ) {
// 5. 构建广告参数并请求
String currentAD_ID = ge tAD_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<String, Long> 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<String, Object> 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 boolean isEv enSecond( ) {
// 1. 获取当前毫秒级时间戳
long currentTimeMillis = System . currentTimeMillis ( ) ;
// 2. 转换为秒数(毫秒 ÷ 1000, 向下取整)
long currentSecond = currentTimeMillis / 1000 ;
// 3. 对 2 取余:余数为 0 是双数秒,余数为 1 是单数秒
return currentSecond % 2 = = 0 ;
}
/**
* 根据当前秒数获取广告ID( 原逻辑保留)
*/
private String getAD_ID ( ) {
long curr ent Second = 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 < String , Object > 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 < String , Object > 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 ( ) ;
}
@@ -605,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 isCanUse Location( ) {
return true ;
}
@Override
public MimoLocation getMimo Location( ) {
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 , " init MimoSdk: init failed " , e ) ;
}
}
@Override
@@ -665,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 ( ) ;
@@ -678,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 ;
}
}
}