diff --git a/appbase/build.properties b/appbase/build.properties index 8e51c0ba..3b345de0 100644 --- a/appbase/build.properties +++ b/appbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Fri Sep 26 05:36:14 HKT 2025 -stageCount=9 +#Sat Sep 27 21:03:20 HKT 2025 +stageCount=10 libraryProject=libappbase baseVersion=15.10 -publishVersion=15.10.8 +publishVersion=15.10.9 buildCount=0 -baseBetaVersion=15.10.9 +baseBetaVersion=15.10.10 diff --git a/build.gradle b/build.gradle index 453f0841..2ec9de6f 100644 --- a/build.gradle +++ b/build.gradle @@ -136,4 +136,3 @@ task clean(type: Delete) { delete rootProject.buildDir } - diff --git a/libappbase/build.properties b/libappbase/build.properties index 8e51c0ba..467f688e 100644 --- a/libappbase/build.properties +++ b/libappbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Fri Sep 26 05:36:14 HKT 2025 -stageCount=9 +#Sat Sep 27 21:03:08 HKT 2025 +stageCount=10 libraryProject=libappbase baseVersion=15.10 -publishVersion=15.10.8 +publishVersion=15.10.9 buildCount=0 -baseBetaVersion=15.10.9 +baseBetaVersion=15.10.10 diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java index 2500de20..8c211866 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java @@ -22,12 +22,12 @@ public class GlobalApplication extends Application { GlobalApplication.isDebuging = isDebuging; } - public static void saveDebugStatus(GlobalApplication application) { - APPModel.saveBeanToFile(application.getAPPModelFilePath(application), new APPModel(GlobalApplication.isDebuging)); + public static void saveDebugStatus(Context context) { + APPModel.saveBeanToFile(getAPPModelFilePath(context), new APPModel(GlobalApplication.isDebuging)); } - static String getAPPModelFilePath(GlobalApplication application) { - return application.getDataDir().getPath() + "/APPModel.json"; + static String getAPPModelFilePath(Context context) { + return context.getDataDir().getPath() + "/APPModel.json"; } public static boolean isDebuging() { diff --git a/powerbell/README.md b/powerbell/README.md index de458908..4280ca17 100644 --- a/powerbell/README.md +++ b/powerbell/README.md @@ -24,7 +24,7 @@ 1. Fork 本仓库 2. 新建 Feat_xxx 分支 -3. 提交代码 : ZhanGSKen(ZhanGSKen) +3. 提交代码 : ZhanGSKen(ZhanGSKen) 4. 新建 Pull Request diff --git a/powerbell/build.gradle b/powerbell/build.gradle index 8defe521..a4a5b862 100644 --- a/powerbell/build.gradle +++ b/powerbell/build.gradle @@ -18,18 +18,22 @@ def genVersionName(def versionName){ } android { - compileSdkVersion 32 - buildToolsVersion "32.0.0" + + // 1. compileSdkVersion:必须 ≥ targetSdkVersion,建议直接等于 targetSdkVersion(30) + compileSdkVersion 30 + + // 2. buildToolsVersion:需匹配 compileSdkVersion,建议使用 30.x.x 最新稳定版(无需高于 compileSdkVersion) + buildToolsVersion "30.0.3" // 这是 30 对应的最新稳定版,避免使用 beta 版 defaultConfig { applicationId "cc.winboll.studio.powerbell" - minSdkVersion 24 + minSdkVersion 23 targetSdkVersion 30 versionCode 6 // versionName 更新后需要手动设置 // .winboll/winbollBuildProps.properties 文件的 stageCount=0 // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" - versionName "15.4" + versionName "15.11" if(true) { versionName = genVersionName("${versionName}") } @@ -41,17 +45,25 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + + // 米盟 + packagingOptions { + doNotStrip "*/*/libmimo_1011.so" + } } dependencies { - api fileTree(dir: 'libs', include: ['*.jar']) - api 'cc.winboll.studio:libaes:15.9.3' - api 'cc.winboll.studio:libapputils:15.8.5' - api 'cc.winboll.studio:libappbase:15.9.5' - - // 吐司提示库 - api 'com.github.getActivity:ToastUtils:10.5' - // 应用介绍页类库 + + // 米盟 + implementation 'com.miui.zeus:mimo-ad-sdk:5.3.+'//请使用最新版sdk + //注意:以下5个库必须要引入 + //implementation 'androidx.appcompat:appcompat:1.4.1' + implementation 'androidx.recyclerview:recyclerview:1.0.0' + implementation 'com.google.code.gson:gson:2.8.5' + implementation 'com.github.bumptech.glide:glide:4.9.0' + //annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' + + // 应用介绍页类库 api 'io.github.medyo:android-about-page:2.0.0' // SSH api 'com.jcraft:jsch:0.1.55' @@ -71,23 +83,9 @@ dependencies { //api 'androidx.vectordrawable:vectordrawable-animated:1.1.0' //api 'androidx.fragment:fragment:1.1.0' - - /*api 'cc.winboll.studio:winboll-shared:1.8.0' - api 'io.github.medyo:android-about-page:2.0.0' - api 'com.jcraft:jsch:0.1.55' - api 'org.jsoup:jsoup:1.13.1' - api 'com.squareup.okhttp3:okhttp:4.4.1' - - api 'androidx.appcompat:appcompat:1.0.0' - api 'androidx.fragment:fragment:1.0.0' - api 'com.google.android.material:material:1.0.0' - - api 'com.baoyz.pullrefreshlayout:library:1.2.0' - api 'com.github.getActivity:ToastUtils:10.5' - api 'io.github.medyo:android-about-page:2.0.0' - api 'org.jsoup:jsoup:1.13.1' - api 'com.squareup.okhttp3:okhttp:4.4.1' - - api 'cc.winboll.studio:libaes:7.6.0' - */ + implementation 'cc.winboll.studio:libaes:15.11.4' + implementation 'cc.winboll.studio:libappbase:15.11.0' + + //api fileTree(dir: 'libs', include: ['*.aar']) + api fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/powerbell/build.properties b/powerbell/build.properties index 643904b7..2fed1875 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Wed Sep 03 20:59:53 HKT 2025 -stageCount=13 +#Wed Nov 19 09:09:24 HKT 2025 +stageCount=4 libraryProject= -baseVersion=15.4 -publishVersion=15.4.12 +baseVersion=15.11 +publishVersion=15.11.3 buildCount=0 -baseBetaVersion=15.4.13 +baseBetaVersion=15.11.4 diff --git a/powerbell/proguard-rules.pro b/powerbell/proguard-rules.pro index 233bad20..ce666849 100644 --- a/powerbell/proguard-rules.pro +++ b/powerbell/proguard-rules.pro @@ -15,3 +15,6 @@ #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} + +## 米盟 +-keep class com.miui.zeus.** { *; } diff --git a/powerbell/src/beta/res/values-zh/string.xml b/powerbell/src/beta/res/values-zh/string.xml index 210946f0..e52345f7 100644 --- a/powerbell/src/beta/res/values-zh/string.xml +++ b/powerbell/src/beta/res/values-zh/string.xml @@ -1,6 +1,6 @@ - 能源钟☆ + PowerBell☆ diff --git a/powerbell/src/main/AndroidManifest.xml b/powerbell/src/main/AndroidManifest.xml index 1bfaabdf..af149d28 100644 --- a/powerbell/src/main/AndroidManifest.xml +++ b/powerbell/src/main/AndroidManifest.xml @@ -1,7 +1,13 @@ + + + + + @@ -24,10 +30,29 @@ + + + + + + + + + + + + + + + + + + android:requestLegacyExternalStorage="true" + android:usesCleartextTraffic="true" + tools:ignore="GoogleAppIndexingWarning"> + + - \ No newline at end of file + diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java index bb5b2c26..6d285616 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java @@ -4,10 +4,10 @@ import android.content.Context; import android.os.Environment; import android.view.Gravity; import cc.winboll.studio.libappbase.GlobalApplication; +import cc.winboll.studio.libappbase.ToastUtils; import cc.winboll.studio.powerbell.receivers.GlobalApplicationReceiver; import cc.winboll.studio.powerbell.utils.AppCacheUtils; import cc.winboll.studio.powerbell.utils.AppConfigUtils; -import com.hjq.toast.ToastUtils; import java.io.File; public class App extends GlobalApplication { @@ -27,6 +27,7 @@ public class App extends GlobalApplication { @Override public void onCreate() { super.onCreate(); + setIsDebugging(BuildConfig.DEBUG); // 临时文件夹方案1 // 获取Pictures文件夹路径(Android 10及以上推荐使用MediaStore,此处为传统方式) @@ -50,7 +51,7 @@ public class App extends GlobalApplication { // 设置 Toast 布局样式 //ToastUtils.setView(R.layout.toast_custom_view); //ToastUtils.setStyle(new WhiteToastStyle()); - ToastUtils.setGravity(Gravity.BOTTOM, 0, 200); + //ToastUtils.setGravity(Gravity.BOTTOM, 0, 200); // 设置数据配置存储工具 _mAppConfigUtils = getAppConfigUtils(this); @@ -77,5 +78,13 @@ public class App extends GlobalApplication { public void clearBatteryHistory() { _mAppCacheUtils.clearBatteryHistory(); } + + @Override + public void onTerminate() { + super.onTerminate(); + ToastUtils.release(); + } + + } 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 b0cce7ce..31994b5e 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -8,36 +8,62 @@ import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; +import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.widget.RelativeLayout; -import android.widget.Toast; -import cc.winboll.studio.libaes.views.AToolbar; +import androidx.appcompat.widget.Toolbar; +import cc.winboll.studio.libaes.views.ADsBannerView; +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.BatteryReporterActivity; +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; +/** + * 主活动类(修复小米广告SDK空Context崩溃问题) + * 核心修改点: + * 1. 添加全局Context安全校验 + * 2. 优化广告请求的生命周期判断 + * 3. 确保广告操作在主线程执行 + * 4. 完善广告资源释放逻辑 + */ public class MainActivity extends WinBoLLActivity { public static final String TAG = "MainActivity"; - public static final int BACKGROUND_PICTURE_REQUEST_CODE = 0; + +// 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 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; - AToolbar mAToolbar; + private App mApplication; + private Menu mMenu; + private Fragment mCurrentShowFragment; + private MainViewFragment mMainViewFragment; + private Toolbar mToolbar; + // 新增:主线程Handler,确保广告操作在主线程执行 + //private Handler mMainHandler; + ADsBannerView mADsBannerView; @Override public Activity getActivity() { @@ -51,26 +77,28 @@ public class MainActivity extends WinBoLLActivity { @Override protected void onCreate(Bundle savedInstanceState) { - //LogUtils.d(TAG, "onCreate(...)"); + LogUtils.d(TAG, "onCreate(...)"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + mADsBannerView = findViewById(R.id.adsbanner); + +// mContainer = findViewById(R.id.ads_container); +// +// // 初始化主线程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); // 初始化工具栏 - mAToolbar = (AToolbar) findViewById(R.id.toolbar); - setActionBar(mAToolbar); - //mAToolbar.setSubtitle("Main"); - mAToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText); + mToolbar = findViewById(R.id.toolbar); + setSupportActionBar(mToolbar); + mToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText); + // 初始化主Fragment if (mMainViewFragment == null) { FragmentTransaction tx = getFragmentManager().beginTransaction(); mMainViewFragment = new MainViewFragment(); @@ -78,13 +106,46 @@ 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); +// } + if(mADsBannerView != null) { + mADsBannerView.releaseAdResources(); + } + } +// +// /** +// * 释放广告资源(关键:避免内存泄漏和空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(); for (Fragment item : getFragmentManager().getFragments()) { @@ -95,7 +156,6 @@ public class MainActivity extends WinBoLLActivity { mCurrentShowFragment = fragment; } - @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); @@ -103,7 +163,8 @@ public class MainActivity extends WinBoLLActivity { } public static void reloadBackground() { - if (_mMainActivity != null) { + // 修复:添加非空校验,避免Activity已销毁时调用 + if (_mMainActivity != null && !_mMainActivity.isFinishing() && !_mMainActivity.isDestroyed()) { _mMainActivity.mMainViewFragment.loadBackground(); } } @@ -113,94 +174,88 @@ 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(); + setBackgroundColor(); + if(mADsBannerView != null) { + mADsBannerView.resumeADs(); + } + +// // 修复:优化广告请求逻辑(添加生命周期判断 + 主线程执行) +// 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(); +// } +// } +// }, 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); - } else if (menuItemId == R.id.action_battery_reporter) { - Intent intent = new Intent(); - intent.setClass(this, BatteryReporterActivity.class); - startActivity(intent); + startActivity(new Intent(this, AboutActivity.class)); + } else if (menuItemId == R.id.action_battery_report) { + 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) { - App.getWinBoLLActivityManager().startLogActivity(this); + 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(); - } - } else { - String sz = "Unsolved requestCode = " + Integer.toString(requestCode); - Toast.makeText(getApplication(), sz, Toast.LENGTH_SHORT).show(); - LogUtils.d(TAG, sz); - } +// if (requestCode == BACKGROUND_PICTURE_REQUEST_CODE) { +// if (resultCode == RESULT_OK) { +// Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_SHORT).show(); +// } +// } else { +// String sz = "Unsolved requestCode = " + Integer.toString(requestCode); +// Toast.makeText(getApplicationContext(), sz, Toast.LENGTH_SHORT).show(); +// LogUtils.d(TAG, sz); +// } } - /** - * 返回键 - */ @Override public void onBackPressed() { if (mCurrentShowFragment != mMainViewFragment) { @@ -210,11 +265,349 @@ 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); + } + } +// +// /** +// * 显示广告(核心修复:传递安全的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()); +// } +// // 4. 显示广告:传递ApplicationContext,避免Activity Context失效 +// mBannerAd.showAd(MainActivity.this, 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 (!isFinishing() && !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 (!isFinishing() && !isDestroyed() && mContainer != null) { +// mContainer.removeView(container); +// } +// } +// }); +// } +// +// /** +// * 请求广告(核心修复: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"); +// } +// +// @Override +// public void onDownloadPaused() { +// LogUtils.d(TAG, "onDownloadPaused"); +// } +// +// @Override +// public void onDownloadFailed(int errorCode) { +// LogUtils.d(TAG, "onDownloadFailed, errorCode = " + errorCode); +// } +// +// @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 (!isFinishing() && !isDestroyed()) { +// showAd(); +// } +// } +// +// @Override +// public void onAdLoadFailed(int errorCode, String errorMsg) { +// LogUtils.e(TAG, "onAdLoadFailed: errorCode = " + errorCode + ", errorMsg = " + errorMsg); +// // 修复:加载失败时移除当前广告实例 +// 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 : +// (BuildConfig.DEBUG ? 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 (isFinishing() || isDestroyed()) { +// return; +// } +// String privacyAgreeValue = getSharedPreferences().getString(PRIVACY_VALUE, null); +// if (TextUtils.equals(privacyAgreeValue, String.valueOf(0))) { +// LogUtils.i(TAG, "已拒绝隐私协议,广告已处于不可用状态..."); +// Toast.makeText(getApplicationContext(), "已拒绝隐私协议,广告已处于不可用状态", Toast.LENGTH_SHORT).show(); +// return; +// } +// if (TextUtils.equals(privacyAgreeValue, String.valueOf(1))) { +// LogUtils.i(TAG, "已同意隐私协议,开始初始化米盟SDK..."); +// initMimoSdk(); +// return; +// } +// 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.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 = getWindowManager(); +// Display d = m.getDefaultDisplay(); +// WindowManager.LayoutParams p = window.getAttributes(); +// p.width = d.getWidth(); +// window.setAttributes(p); +// } +// dialog.show(); +// } +// +// /** +// * 初始化米盟SDK(核心修复:传递ApplicationContext + 异常捕获) +// */ +// private void initMimoSdk() { +// // 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 MimoLocation getMimoLocation() { +// return null; +// } +// +// @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 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 + public boolean dispatchKeyEvent(KeyEvent event) { + return super.dispatchKeyEvent(event); + } + + @Override + public void setupToolbar() { + super.setupToolbar(); + if (getSupportActionBar() != null) { + getSupportActionBar().setDisplayHomeAsUpEnabled(false); + } + } +// +// /** +// * 获取SharedPreferences实例(原逻辑保留,添加空指针校验) +// */ +// public SharedPreferences getSharedPreferences() { +// if (mSharedPreferences == null) { +// // 修复:使用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; +// } +} + diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/AboutActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/AboutActivity.java index 9f54ad02..63ea7804 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/AboutActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/AboutActivity.java @@ -10,9 +10,9 @@ import android.content.Context; import android.os.Bundle; import android.view.ViewGroup; import android.widget.LinearLayout; +import cc.winboll.studio.libaes.models.APPInfo; import cc.winboll.studio.libaes.views.AToolbar; -import cc.winboll.studio.libaes.winboll.APPInfo; -import cc.winboll.studio.libaes.winboll.AboutView; +import cc.winboll.studio.libaes.views.AboutView; import cc.winboll.studio.powerbell.R; public class AboutActivity extends Activity { diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java index f29a768b..9bf3d440 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java @@ -19,7 +19,7 @@ import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import cc.winboll.studio.libaes.views.AToolbar; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.utils.ToastUtils; +import cc.winboll.studio.libappbase.ToastUtils; import cc.winboll.studio.powerbell.App; import cc.winboll.studio.powerbell.R; import cc.winboll.studio.powerbell.beans.BackgroundPictureBean; diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BatteryReportActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BatteryReportActivity.java new file mode 100644 index 00000000..647bf642 --- /dev/null +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BatteryReportActivity.java @@ -0,0 +1,516 @@ +package cc.winboll.studio.powerbell.activities; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/10/22 13:21 + * @Describe BatteryReportActivity + */ +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.provider.Settings; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import cc.winboll.studio.powerbell.R; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import cc.winboll.studio.libappbase.LogUtils; + +public class BatteryReportActivity extends Activity { + public static final String TAG = "BatteryReportActivity"; + + private RecyclerView rvBatteryReport; + private BatteryReportAdapter adapter; + private List dataList = new ArrayList(); + private List filteredList = new ArrayList(); + private BroadcastReceiver batteryReceiver; + private int batteryCapacity = 5400; // 电池容量(mAh) + private float lastBatteryPercent = 100.0f; + private long lastCheckTime = System.currentTimeMillis(); + private EditText etSearch; + private Map appRunTimeCache = new HashMap(); + private Map packageToAppNameCache = new HashMap(); + private PackageManager mPackageManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_battery_report); + mPackageManager = getPackageManager(); + + // 权限检查(Java7 传统条件判断) + if (!hasUsageStatsPermission(this)) { + Toast.makeText(this, "请进入设置-应用-权限-特殊访问权限-使用情况访问权限,开启本应用的权限", Toast.LENGTH_LONG).show(); + startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); + return; + } + + etSearch = (EditText) findViewById(R.id.et_search); + rvBatteryReport = (RecyclerView) findViewById(R.id.rv_battery_report); + rvBatteryReport.setLayoutManager(new LinearLayoutManager(this)); + + // 初始化流程:新增“加载24小时累计耗电”步骤 + loadAllAppPackage(); + preCacheAllAppNames(); + appRunTimeCache = getAppRunTime(); + updateAppRunTimeToModel(); + calculateInitial24hTotalConsumption(); // 初始化时计算24小时累计耗电 + filteredList.addAll(dataList); + adapter = new BatteryReportAdapter(this, filteredList, mPackageManager, packageToAppNameCache); + rvBatteryReport.setAdapter(adapter); + + // 搜索监听(不变) + etSearch.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + filterAppsByPackageAndName(s.toString()); + } + + @Override + public void afterTextChanged(Editable s) {} + }); + + // 电池广播:调用修改后的“单次耗电计算+累计累加”方法 + batteryReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int level = intent.getIntExtra("level", 100); + int scale = intent.getIntExtra("scale", 100); + float currentPercent = (float) level / scale * 100; + LogUtils.d(TAG, "电池百分比变化:" + lastBatteryPercent + " -> " + currentPercent); + + if (currentPercent < lastBatteryPercent) { + float dropPercent = lastBatteryPercent - currentPercent; + long duration = System.currentTimeMillis() - lastCheckTime; + LogUtils.d(TAG, "电池消耗:" + dropPercent + "%,时长:" + duration + "ms"); + appRunTimeCache = getAppRunTime(); + updateAppRunTimeToModel(); + calculateSingleConsumptionAndAccumulate(dropPercent, appRunTimeCache); // 单次+累计逻辑 + } + + lastBatteryPercent = currentPercent; + lastCheckTime = System.currentTimeMillis(); + } + }; + registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + // Java7 显式非空判断 + if (batteryReceiver != null) { + unregisterReceiver(batteryReceiver); + } + } + + /** + * 加载所有应用(仅获取包名,初始化模型时单次耗电、累计耗电均设为0) + */ + private void loadAllAppPackage() { + List appList = mPackageManager.getInstalledApplications(PackageManager.GET_META_DATA); + dataList.clear(); + + LogUtils.d(TAG, "开始加载应用包名列表,共找到" + appList.size() + "个应用"); + + for (ApplicationInfo appInfo : appList) { + String packageName = appInfo.packageName; + // 初始化:单次耗电(consumption)=0,累计耗电(totalConsumption)=0,运行时长=0 + dataList.add(new AppBatteryModel(packageName, 0.0f, 0.0f, 0)); + } + + LogUtils.d(TAG, "应用包名列表加载完成,共添加" + dataList.size() + "个包名。"); + } + + /** + * 预缓存应用名称(逻辑不变) + */ + private void preCacheAllAppNames() { + packageToAppNameCache.clear(); + LogUtils.d(TAG, "开始预缓存包名-应用名称映射"); + + for (AppBatteryModel model : dataList) { + String packageName = model.getPackageName(); + String appName = getAppNameByPackage(packageName); + packageToAppNameCache.put(packageName, appName); + } + + LogUtils.d(TAG, "预缓存完成,共缓存" + packageToAppNameCache.size() + "个应用名称"); + } + + /** + * 通过包名获取应用名称(逻辑不变) + */ + private String getAppNameByPackage(String packageName) { + try { + ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0); + return mPackageManager.getApplicationLabel(appInfo).toString(); + } catch (PackageManager.NameNotFoundException e) { + LogUtils.e(TAG, "包名" + packageName + "对应的应用未找到:" + e.getMessage()); + return packageName; + } catch (Exception e) { + LogUtils.e(TAG, "查询应用名称失败(包名:" + packageName + "):" + e.getMessage()); + return packageName; + } + } + + /** + * 更新运行时长到模型(逻辑不变) + */ + private void updateAppRunTimeToModel() { + int nCount = 0; + for (AppBatteryModel model : dataList) { + String packageName = model.getPackageName(); + Long runTime; + if (appRunTimeCache.containsKey(packageName)) { + runTime = appRunTimeCache.get(packageName); + LogUtils.d(TAG, String.format("应用包 %s 运行时长已更新。", packageName)); + nCount++; + } else { + runTime = 0L; + } + model.setRunTime(runTime); + } + LogUtils.d(TAG, String.format("dataList.size() %d, appRunTimeCache.size() %d。", dataList.size(), appRunTimeCache.size())); + LogUtils.d(TAG, String.format("updateAppRunTimeToModel() 更新的数据量为:%d", nCount)); + } + + /** + * 【新增】初始化时计算24小时累计耗电(赋值给totalConsumption) + * 逻辑:基于24小时运行时长占比,分配当前电池容量的理论24小时消耗 + */ + private void calculateInitial24hTotalConsumption() { + long total24hRunTime = 0; + // 1. 计算24小时内所有应用总运行时长 + for (Map.Entry entry : appRunTimeCache.entrySet()) { + total24hRunTime += entry.getValue(); + } + LogUtils.d(TAG, "24小时内所有应用总运行时长:" + formatRunTime(total24hRunTime)); + + // 2. 按运行时长占比分配24小时累计耗电(假设电池满电循环,用总容量近似24小时总消耗) + for (AppBatteryModel model : dataList) { + String packageName = model.getPackageName(); + Long app24hRunTime = appRunTimeCache.getOrDefault(packageName, 0L); + + // 计算占比与累计耗电 + float ratio = (total24hRunTime > 0) ? (float) app24hRunTime / total24hRunTime : 0; + float initialTotalConsumption = batteryCapacity * ratio; // 用电池容量近似24小时总消耗 + model.setTotalConsumption(initialTotalConsumption); // 初始化累计耗电 + LogUtils.d(TAG, String.format("应用包 %s 24小时累计耗电初始化:%.1f mAh", packageName, initialTotalConsumption)); + } + } + + /** + * 【核心修改】计算单次耗电(赋值给consumption)+ 累加至累计耗电(totalConsumption = totalConsumption + consumption) + */ + private void calculateSingleConsumptionAndAccumulate(float dropPercent, Map runTimeMap) { + long totalSingleRunTime = 0; + // 1. 计算本次电池下降期间的总运行时长 + for (Map.Entry entry : runTimeMap.entrySet()) { + totalSingleRunTime += entry.getValue(); + } + + // 2. 遍历计算每个应用的“单次耗电”并“累加至累计” + for (AppBatteryModel model : dataList) { + String packageName = model.getPackageName(); + Long appSingleRunTime = runTimeMap.getOrDefault(packageName, 0L); + + // 步骤1:计算本次单次耗电(赋值给consumption) + float ratio = (totalSingleRunTime > 0) ? (float) appSingleRunTime / totalSingleRunTime : 0; + float singleConsumption = batteryCapacity * dropPercent / 100 * ratio; // 单次消耗 + model.setConsumption(singleConsumption); // 存储单次耗电 + + // 步骤2:累加单次耗电到累计耗电(totalConsumption = 原有累计 + 本次单次) + float newTotalConsumption = model.getTotalConsumption() + singleConsumption; + model.setTotalConsumption(newTotalConsumption); // 更新累计耗电 + + // 同步运行时长 + model.setRunTime(appSingleRunTime); + + LogUtils.d(TAG, String.format("应用包 %s:单次耗电%.1f mAh,累计耗电%.1f mAh", + packageName, singleConsumption, newTotalConsumption)); + } + + // 3. 按累计耗电排序(从高到低) + Collections.sort(dataList, new Comparator() { + @Override + public int compare(AppBatteryModel m1, AppBatteryModel m2) { + return Float.compare(m2.getTotalConsumption(), m1.getTotalConsumption()); + } + }); + + // 4. 重新应用过滤并刷新列表 + filterAppsByPackageAndName(etSearch.getText().toString()); + } + + /** + * 双维度过滤(逻辑不变) + */ + private void filterAppsByPackageAndName(String keyword) { + filteredList.clear(); + if (keyword == null || keyword.isEmpty()) { + filteredList.addAll(dataList); + } else { + String lowerKeyword = keyword.toLowerCase(); + + for (AppBatteryModel model : dataList) { + String packageName = model.getPackageName(); + String packageNameLower = packageName.toLowerCase(); + String appName = packageToAppNameCache.get(packageName); + String appNameLower = appName.toLowerCase(); + + boolean isMatched = packageNameLower.contains(lowerKeyword) + || appNameLower.contains(lowerKeyword); + + if (isMatched) { + filteredList.add(model); + } + } + } + adapter.notifyDataSetChanged(); + } + + /** + * 获取应用运行时长(逻辑不变,返回24小时运行时长) + */ + private Map getAppRunTime() { + Map runTimeMap = new HashMap(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + try { + android.app.usage.UsageStatsManager manager = + (android.app.usage.UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); + long endTime = System.currentTimeMillis(); + long startTime = endTime - 24 * 3600 * 1000; // 近24小时 + List statsList = manager.queryUsageStats( + android.app.usage.UsageStatsManager.INTERVAL_DAILY, startTime, endTime); + + for (android.app.usage.UsageStats stats : statsList) { + long runTimeMs = stats.getTotalTimeInForeground(); + String packageName = stats.getPackageName(); + LogUtils.d(TAG, "包名" + packageName + "24小时运行时长:" + formatRunTime(runTimeMs)); + runTimeMap.put(packageName, runTimeMs); + if (packageName.equals("aidepro.top")) { + LogUtils.d(TAG, String.format("runTimeMap.put(packageName, runTimeMs) 特殊查询 %s 查询有结果。", packageName)); + } + } + } catch (Exception e) { + LogUtils.e(TAG, "获取应用运行时长失败:" + e.getMessage()); + } + } + + LogUtils.d(TAG, String.format("应用运行时长列表数量%d。", runTimeMap.size())); + return runTimeMap; + } + + /** + * 格式化运行时长(逻辑不变) + */ + private String formatRunTime(long runTimeMs) { + if (runTimeMs <= 0) { + return "0秒"; + } + long seconds = runTimeMs / 1000; + long hours = seconds / 3600; + long minutes = (seconds % 3600) / 60; + seconds = seconds % 60; + + if (hours > 0) { + return String.format("%d时%d分%d秒", hours, minutes, seconds); + } else if (minutes > 0) { + return String.format("%d分%d秒", minutes, seconds); + } else { + return String.format("%d秒", seconds); + } + } + + /** + * 权限检查(逻辑不变) + */ + private boolean hasUsageStatsPermission(Context context) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + return false; + } + + android.app.usage.UsageStatsManager manager = + (android.app.usage.UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE); + if (manager == null) { + return false; + } + + long endTime = System.currentTimeMillis(); + long startTime = endTime - 1000 * 60; + List statsList = manager.queryUsageStats( + android.app.usage.UsageStatsManager.INTERVAL_DAILY, startTime, endTime); + + return statsList != null && !statsList.isEmpty(); + } + + /** + * 【核心修改】数据模型:明确字段含义 + * - consumption:单次耗电(两次电池广播间的消耗,float类型便于计算) + * - totalConsumption:累计耗电(24小时初始化值+后续单次累加,显示用) + */ + public static class AppBatteryModel { + private String packageName; // 应用包名(核心标识) + private float consumption; // 单次耗电(mAh,float类型) + private float totalConsumption;// 累计耗电(mAh,显示+排序用) + private long runTime; // 运行时长(ms) + + // Java7 显式构造:初始化单次耗电、累计耗电为0 + public AppBatteryModel(String packageName, float consumption, float totalConsumption, long runTime) { + this.packageName = packageName; + this.consumption = consumption; // 单次耗电初始为0 + this.totalConsumption = totalConsumption; // 累计耗电初始为0(后续初始化时赋值) + this.runTime = runTime; + } + + // Getter/Setter:覆盖所有字段,确保数据操作正常 + public String getPackageName() { + return packageName; + } + + public float getConsumption() { + return consumption; // 获取单次耗电 + } + + public void setConsumption(float consumption) { + this.consumption = consumption; // 设置单次耗电 + } + + public float getTotalConsumption() { + return totalConsumption; // 获取累计耗电(显示用) + } + + public void setTotalConsumption(float totalConsumption) { + this.totalConsumption = totalConsumption; // 设置累计耗电(初始化/累加用) + } + + public long getRunTime() { + return runTime; + } + + public void setRunTime(long runTime) { + this.runTime = runTime; + } + } + + /** + * RecyclerView 适配器:仅显示累计耗电(totalConsumption),逻辑适配模型修改 + */ + public static class BatteryReportAdapter extends RecyclerView.Adapter { + private Context mContext; + private List mDataList; + private PackageManager mPm; + private Map mPackageToNameCache; + + // Java7 显式构造:接收名称缓存,确保显示时高效获取应用名 + public BatteryReportAdapter(Context context, List dataList, + PackageManager pm, Map packageToNameCache) { + this.mContext = context; + this.mDataList = dataList; + this.mPm = pm; + this.mPackageToNameCache = packageToNameCache; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + // 加载系统列表项布局(text1显示应用名,text2显示累计耗电+时长) + View itemView = LayoutInflater.from(mContext) + .inflate(android.R.layout.simple_list_item_2, parent, false); + return new ViewHolder(itemView); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + // Java7 显式非空判断:避免空指针异常 + if (mDataList == null || mDataList.isEmpty() || position >= mDataList.size()) { + holder.tvAppName.setText("未知应用"); + holder.tvConsumption.setText("累计耗电:0.0 mAh | 运行时长:0秒"); + return; + } + + AppBatteryModel model = mDataList.get(position); + String packageName = model.getPackageName(); + String appName = ""; + + // 优先从缓存获取应用名:减少PackageManager调用,提升性能 + if (mPackageToNameCache != null && mPackageToNameCache.containsKey(packageName)) { + appName = mPackageToNameCache.get(packageName); + } else { + // 缓存无数据时兜底查询,并同步更新缓存 + try { + ApplicationInfo appInfo = mPm.getApplicationInfo(packageName, 0); + appName = mPm.getApplicationLabel(appInfo).toString(); + if (mPackageToNameCache != null) { + mPackageToNameCache.put(packageName, appName); + } + } catch (PackageManager.NameNotFoundException e) { + appName = packageName; // 包名不存在时用包名兜底 + LogUtils.e("Adapter", "包名" + packageName + "对应的应用未找到:" + e.getMessage()); + } catch (Exception e) { + appName = packageName; // 其他异常时用包名兜底 + LogUtils.e("Adapter", "查询应用名称失败(包名:" + packageName + "):" + e.getMessage()); + } + } + + // 显示逻辑:仅展示累计耗电(totalConsumption),隐藏单次耗电 + holder.tvAppName.setText(appName); + // 格式化运行时长 + 累计耗电(保留1位小数,提升可读性) + String runTimeStr = ((BatteryReportActivity) mContext).formatRunTime(model.getRunTime()); + String totalConsumptionText = String.format("累计耗电:%.1f mAh | 运行时长:%s", + model.getTotalConsumption(), runTimeStr); + holder.tvConsumption.setText(totalConsumptionText); + + // 显示优化:文字颜色区分(避免所有应用均标蓝,仅示例可按需修改) + holder.tvAppName.setTextColor(mContext.getResources().getColor(android.R.color.black)); + holder.tvConsumption.setTextColor(mContext.getResources().getColor(android.R.color.darker_gray)); + + // 调整文字大小:适配手机屏幕,提升可读性 + holder.tvAppName.setTextSize(16); + holder.tvConsumption.setTextSize(14); + } + + // 获取列表长度:Java7 三元运算符判断空值,避免空指针 + @Override + public int getItemCount() { + return mDataList == null ? 0 : mDataList.size(); + } + + /** + * ViewHolder:绑定系统布局控件,与显示逻辑对应 + */ + public static class ViewHolder extends RecyclerView.ViewHolder { + TextView tvAppName; // 显示应用名称 + TextView tvConsumption; // 显示累计耗电 + 运行时长 + + // Java7 显式构造:绑定控件ID(系统布局固定ID:text1、text2) + public ViewHolder(View itemView) { + super(itemView); + tvAppName = (TextView) itemView.findViewById(android.R.id.text1); + tvConsumption = (TextView) itemView.findViewById(android.R.id.text2); + } + } + } +} + diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BatteryReporterActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BatteryReporterActivity.java deleted file mode 100644 index f783a924..00000000 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BatteryReporterActivity.java +++ /dev/null @@ -1,51 +0,0 @@ -package cc.winboll.studio.powerbell.activities; - -/** - * @Author ZhanGSKen - * @Date 2025/03/22 14:20:15 - */ -import android.app.Activity; -import android.os.Bundle; -import androidx.recyclerview.widget.DividerItemDecoration; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import cc.winboll.studio.powerbell.R; -import cc.winboll.studio.powerbell.adapters.BatteryAdapter; -import cc.winboll.studio.powerbell.beans.BatteryData; -import java.util.Arrays; -import java.util.List; - -public class BatteryReporterActivity extends Activity { - public static final String TAG = "BatteryReporterActivity"; - - private RecyclerView rvBatteryReport; - private BatteryAdapter adapter; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_battery_reporter); - - rvBatteryReport = findViewById(R.id.rvBatteryReport); - setupRecyclerView(); - loadSampleData(); - } - - private void setupRecyclerView() { - adapter = new BatteryAdapter(); - rvBatteryReport.setLayoutManager(new LinearLayoutManager(this)); - rvBatteryReport.setAdapter(adapter); - rvBatteryReport.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); - } - - private void loadSampleData() { - List dataList = Arrays.asList( - new BatteryData(95, "01:23:45", "00:05:12"), - new BatteryData(80, "02:15:30", "00:10:00"), - new BatteryData(65, "03:45:15", "00:15:30"), - new BatteryData(50, "05:00:00", "00:20:45") - ); - adapter.updateData(dataList); - } -} - diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/ClearRecordActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/ClearRecordActivity.java index d53e7671..99e4d7f0 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/ClearRecordActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/ClearRecordActivity.java @@ -4,11 +4,12 @@ import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; +import android.widget.Switch; import android.widget.TextView; import cc.winboll.studio.libaes.views.AOHPCTCSeekBar; import cc.winboll.studio.libaes.views.AToolbar; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.utils.ToastUtils; +import cc.winboll.studio.libappbase.ToastUtils; import cc.winboll.studio.powerbell.App; import cc.winboll.studio.powerbell.R; import cc.winboll.studio.powerbell.beans.BatteryInfoBean; @@ -16,7 +17,6 @@ import cc.winboll.studio.powerbell.receivers.ControlCenterServiceReceiver; import cc.winboll.studio.powerbell.utils.AppCacheUtils; import cc.winboll.studio.powerbell.utils.StringUtils; import java.util.ArrayList; -import android.widget.Switch; public class ClearRecordActivity extends Activity { diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/PixelPickerActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/PixelPickerActivity.java index a781a888..85fd970c 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/PixelPickerActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/PixelPickerActivity.java @@ -6,6 +6,7 @@ package cc.winboll.studio.powerbell.activities; */ import android.app.Activity; import android.app.Dialog; +import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; @@ -19,11 +20,11 @@ import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; import cc.winboll.studio.libaes.views.AToolbar; import cc.winboll.studio.libappbase.GlobalApplication; -import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; -import cc.winboll.studio.powerbell.MainActivity; import cc.winboll.studio.powerbell.R; +import cc.winboll.studio.powerbell.activities.BackgroundPictureActivity; import cc.winboll.studio.powerbell.activities.PixelPickerActivity; import cc.winboll.studio.powerbell.beans.BackgroundPictureBean; import cc.winboll.studio.powerbell.utils.BackgroundPictureUtils; @@ -233,7 +234,10 @@ public class PixelPickerActivity extends WinBoLLActivity implements IWinBoLLActi @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { - GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), BackgroundPictureActivity.class); + Intent intent = new Intent(); + intent.setClass(this, BackgroundPictureActivity.class); + startActivity(intent); + //GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), ); return true; } // 在switch语句中处理每个ID,并在处理完后返回true,未处理的情况返回false。 @@ -243,7 +247,10 @@ public class PixelPickerActivity extends WinBoLLActivity implements IWinBoLLActi @Override public void onBackPressed() { super.onBackPressed(); - GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), BackgroundPictureActivity.class); + Intent intent = new Intent(); + intent.setClass(this, BackgroundPictureActivity.class); + startActivity(intent); + //GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), BackgroundPictureActivity.class); } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/WinBoLLActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/WinBoLLActivity.java index e44b8257..ad02302d 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/WinBoLLActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/WinBoLLActivity.java @@ -5,40 +5,93 @@ package cc.winboll.studio.powerbell.activities; * @Date 2025/06/19 20:35 * @Describe 应用窗口基类 */ +import android.annotation.SuppressLint; import android.app.Activity; +import android.graphics.Color; import android.os.Bundle; +import android.util.TypedValue; +import android.view.Gravity; import android.view.MenuItem; -import cc.winboll.studio.libappbase.GlobalApplication; -import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; -import cc.winboll.studio.powerbell.App; -import cc.winboll.studio.powerbell.MainActivity; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.TextView; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.powerbell.BuildConfig; import cc.winboll.studio.powerbell.R; -public abstract class WinBoLLActivity extends Activity implements IWinBoLLActivity { +@SuppressLint("SetTextI18n") +public abstract class WinBoLLActivity extends AppCompatActivity implements IWinBoLLActivity { public static final String TAG = "WinBoLLActivity"; - + + protected TextView mTagView; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + changeFullScreen(this); + } + + + @Override + protected void onStart() { + super.onStart(); + addVersionNameToContentView(); + } + + protected void addVersionNameToContentView() { + if (!isTagViewVisible()) { + return; + } + if (mTagView == null) { + mTagView = new TextView(this); + mTagView.setTextColor(Color.GRAY); + mTagView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10); + mTagView.setText("MIMO SDK V" + BuildConfig.VERSION_NAME); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; + FrameLayout frameLayout = findViewById(android.R.id.content); + frameLayout.addView(mTagView, params); + } + } + + protected boolean isTagViewVisible() { + return true; + } + + public void setupToolbar() { + Toolbar mToolbar = findViewById(R.id.toolbar); + if (mToolbar != null) { + setSupportActionBar(mToolbar); + if (getSupportActionBar() != null) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + } } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); - GlobalApplication.getWinBoLLActivityManager().add(this); + //GlobalApplication.getWinBoLLActivityManager().add(this); } @Override protected void onDestroy() { super.onDestroy(); - GlobalApplication.getWinBoLLActivityManager().registeRemove(this); + //GlobalApplication.getWinBoLLActivityManager().registeRemove(this); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { - GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), MainActivity.class); + //GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), MainActivity.class); return true; } // 在switch语句中处理每个ID,并在处理完后返回true,未处理的情况返回false。 @@ -48,6 +101,25 @@ public abstract class WinBoLLActivity extends Activity implements IWinBoLLActivi @Override public void onBackPressed() { super.onBackPressed(); - GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), MainActivity.class); + //GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), MainActivity.class); } + + public void changeFullScreen(Activity activity) { + Window window = activity.getWindow(); + if (window == null){ + return; + } + View decorView = window.getDecorView(); + if (decorView == null){ + return; + } + int flag = decorView.getSystemUiVisibility(); + flag |= View.SYSTEM_UI_FLAG_FULLSCREEN; + flag |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + flag |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + flag |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + flag |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + decorView.setSystemUiVisibility(flag); + window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java index d0730712..955d650b 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java @@ -14,10 +14,12 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.widget.RemoteViews; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.utils.ToastUtils; +import cc.winboll.studio.libappbase.ToastUtils; import cc.winboll.studio.powerbell.App; import cc.winboll.studio.powerbell.MainActivity; import cc.winboll.studio.powerbell.R; @@ -32,8 +34,6 @@ import cc.winboll.studio.powerbell.utils.AppConfigUtils; import cc.winboll.studio.powerbell.utils.NotificationHelper; import cc.winboll.studio.powerbell.utils.ServiceUtils; import cc.winboll.studio.powerbell.utils.StringUtils; -import android.os.Handler; -import android.os.Looper; public class ControlCenterService extends Service { @@ -73,8 +73,8 @@ public class ControlCenterService extends Service { mAppConfigUtils = App.getAppConfigUtils(this); mAppCacheUtils = App.getAppCacheUtils(this); mNotificationHelper = new NotificationHelper(ControlCenterService.this); - - + + if (mMyServiceConnection == null) { mMyServiceConnection = new MyServiceConnection(); } @@ -105,7 +105,7 @@ public class ControlCenterService extends Service { Intent intent = new Intent(this, MainActivity.class); notification = helper.showForegroundNotification(intent, getString(R.string.app_name), "Service Running, Click to open app"); startForeground(NotificationHelper.FOREGROUND_NOTIFICATION_ID, notification); - + // NotificationMessage notificationMessage=createNotificationMessage(); // //Toast.makeText(getApplication(), "", Toast.LENGTH_SHORT).show(); // mNotificationUtils.createForegroundNotification(this, notificationMessage); @@ -116,7 +116,7 @@ public class ControlCenterService extends Service { mControlCenterServiceReceiver = new ControlCenterServiceReceiver(this); mControlCenterServiceReceiver.registerAction(this); } - + new Handler(Looper.getMainLooper()).postDelayed(new Runnable(){ @Override @@ -126,7 +126,7 @@ public class ControlCenterService extends Service { LogUtils.i(TAG, "Service Is Start."); } }, 2000); - + } } @@ -263,15 +263,15 @@ public class ControlCenterService extends Service { NotificationHelper helper = new NotificationHelper(ControlCenterService.this); Intent intent = new Intent(ControlCenterService.this, MainActivity.class); helper.showTemporaryNotification(intent, getString(R.string.app_name), msg); - - - + + + // NotificationMessage notificationMessage = createNotificationMessage(); // notificationMessage.setRemindMSG(szRemindMSG); // //LogUtils.d(TAG, "notificationMessage : " + notificationMessage.getRemindMSG()); // updateRemindNotification(notificationMessage); } - + // 设置颜色背景 public static RemoteViews setLinearLayoutColor(RemoteViews remoteViews, int viewId, int color) { remoteViews.setInt(viewId, "setBackgroundColor", color); diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/MimoUtils.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/MimoUtils.java new file mode 100644 index 00000000..28038ca4 --- /dev/null +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/MimoUtils.java @@ -0,0 +1,33 @@ +package cc.winboll.studio.powerbell.utils; + +import android.content.Context; +import android.util.DisplayMetrics; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/11/14 11:14 + * @Describe 米盟 MimoUtils + */ +public final class MimoUtils { + public static final String TAG = "Utils"; + + public static int dpToPx(Context context, float dp) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (dp * displayMetrics.density + 0.5f); + } + + public static int pxToDp(Context context, float px) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (px / displayMetrics.density + 0.5f); + } + + public static int pxToSp(Context context, float pxValue) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (pxValue / displayMetrics.scaledDensity + 0.5f); + } + + public static int spToPx(Context context, float spValue) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (spValue * displayMetrics.scaledDensity + 0.5f); + } +} diff --git a/powerbell/src/main/res/layout/activity_battery_report.xml b/powerbell/src/main/res/layout/activity_battery_report.xml new file mode 100644 index 00000000..361b96fe --- /dev/null +++ b/powerbell/src/main/res/layout/activity_battery_report.xml @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/powerbell/src/main/res/layout/activity_battery_reporter.xml b/powerbell/src/main/res/layout/activity_battery_reporter.xml deleted file mode 100644 index 0ad37ee1..00000000 --- a/powerbell/src/main/res/layout/activity_battery_reporter.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/powerbell/src/main/res/layout/activity_main.xml b/powerbell/src/main/res/layout/activity_main.xml index 54bf7525..92e11e73 100644 --- a/powerbell/src/main/res/layout/activity_main.xml +++ b/powerbell/src/main/res/layout/activity_main.xml @@ -6,7 +6,7 @@ android:layout_height="match_parent" android:orientation="vertical"> - + android:background="#FFB7B7B7"/> + + diff --git a/powerbell/src/main/res/menu/toolbar_main.xml b/powerbell/src/main/res/menu/toolbar_main.xml index 77ba849b..5ef6f1b5 100644 --- a/powerbell/src/main/res/menu/toolbar_main.xml +++ b/powerbell/src/main/res/menu/toolbar_main.xml @@ -1,8 +1,8 @@ + android:id="@+id/action_battery_report" + android:title="@string/item_battery_report"/> diff --git a/powerbell/src/main/res/values-zh/strings.xml b/powerbell/src/main/res/values-zh/strings.xml index 91a6587f..59f9420a 100644 --- a/powerbell/src/main/res/values-zh/strings.xml +++ b/powerbell/src/main/res/values-zh/strings.xml @@ -1,6 +1,6 @@ - 能源钟 + PowerBell 一个接收手机电量信息的应用,当电量值达到设定范围时会提醒用户。 本应用崩溃了,作者水平有限,敬请谅解! Main View diff --git a/powerbell/src/main/res/values/colors.xml b/powerbell/src/main/res/values/colors.xml index 800b26bd..a81deb77 100644 --- a/powerbell/src/main/res/values/colors.xml +++ b/powerbell/src/main/res/values/colors.xml @@ -25,16 +25,15 @@ #FF0072A4 #FF33C1FF #FFFCC500 - @color/colorShuiDark + + #FFBEBE48 + #FFC85C5C + #FF2677C7 #FF000000 - @color/colorHuo - @color/colorShui - @color/colorXinling + @color/colorBlack - + + @color/colorShui + @color/colorShuiDark + @color/colorShuiAccent @color/colorRed @color/colorBlue @color/colorYellow - --> + #FFFFFFFF diff --git a/powerbell/src/main/res/values/strings.xml b/powerbell/src/main/res/values/strings.xml index 6206849b..1b7491c8 100644 --- a/powerbell/src/main/res/values/strings.xml +++ b/powerbell/src/main/res/values/strings.xml @@ -6,7 +6,7 @@ This application has crashed, the author level is limited, please understand! Main View About - Battery Reporter + Battery Report Clear Record Change Picture Developer View diff --git a/powerbell/src/main/res/xml/file_provider.xml b/powerbell/src/main/res/xml/file_provider.xml index f045677b..b20e01b8 100644 --- a/powerbell/src/main/res/xml/file_provider.xml +++ b/powerbell/src/main/res/xml/file_provider.xml @@ -13,6 +13,9 @@ +