@@ -39,7 +39,6 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   RecyclerView   rvBatteryReport ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   BatteryReportAdapter   adapter ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     // 数据列表:仅存储包名、耗电、时长(不存储名称,计算全程用包名) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   List < AppBatteryModel >   dataList   =   new   ArrayList < AppBatteryModel > ( ) ;   
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   List < AppBatteryModel >   filteredList   =   new   ArrayList < AppBatteryModel > ( ) ;   
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   BroadcastReceiver   batteryReceiver ; 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -47,18 +46,14 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   float   lastBatteryPercent   =   100 . 0f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   long   lastCheckTime   =   System . currentTimeMillis ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   EditText   etSearch ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     // 应用运行时长缓存(  key:  包名,  value:  时长ms)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   Map < String ,   Long >   appRunTimeCache   =   new   HashMap < String ,   Long > ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     // 新增:包名-应用名称映射缓存(用于搜索匹配名称,避免重复查询) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   Map < String ,   String >   packageToAppNameCache   =   new   HashMap < String ,   String > ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     // 包管理工具(全局持有,避免重复获取) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   PackageManager   mPackageManager ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     @Override 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     protected   void   onCreate ( Bundle   savedInstanceState )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         super . onCreate ( savedInstanceState ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         setContentView ( R . layout . activity_battery_report ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 初始化包管理工具(仅一次,供后续查询名称使用) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         mPackageManager   =   getPackageManager ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 权限检查(  Java7 传统条件判断) 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -72,34 +67,31 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         rvBatteryReport   =   ( RecyclerView )   findViewById ( R . id . rv_battery_report ) ;   
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         rvBatteryReport . setLayoutManager ( new   LinearLayoutManager ( this ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 1. 加载所有应用(仅存包名,不查名称)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 初始化流程:  新增“加载24小时累计耗电”步骤  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         loadAllAppPackage ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 2. 预缓存所有包名对应的应用名称(为搜索名称做准备) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         preCacheAllAppNames ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 4. 首次获取运行时长(  key:  包名)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         appRunTimeCache   =   getAppRunTime ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 5. 更新时长到数据模型(用包名匹配) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         updateAppRunTimeToModel ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 6. 初始化过滤列表和适配器(传入包管理工具+名称缓存) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         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 ( ) ) ;   // 替换为新的双维度过滤方法 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									 filterAppsByPackageAndName ( s . toString ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								 } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								 @Override 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								 public   void   afterTextChanged ( Editable   s )   { } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							 } ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 电池广播(耗电计算全程用包名)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 电池广播:调用修改后的“单次耗电计算+累计累加”方法  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         batteryReceiver   =   new   BroadcastReceiver ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             @Override 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             public   void   onReceive ( Context   context ,   Intent   intent )   { 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -108,17 +100,13 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 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 " ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     // 重新获取最新运行时长(  key:  包名)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     appRunTimeCache   =   getAppRunTime ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     // 更新模型中的运行时长(包名匹配) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     updateAppRunTimeToModel ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     // 分配耗电(包名计算) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     distributeBatteryConsumption ( dropPercent ,   appRunTimeCache ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     calculateSingleConsumptionAndAccumulate ( dropPercent ,   appRunTimeCache ) ;   // 单次+累计逻辑 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 lastBatteryPercent   =   currentPercent ; 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -138,67 +126,63 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 加载所有应用(仅获取包名,不查询应用名称,数据计算核心步骤 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 加载所有应用(仅获取包名,初始化模型时单次耗电、累计耗电均设为0 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   void   loadAllAppPackage ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         List < ApplicationInfo >   appList   =   mPackageManager . getInstalledApplications ( PackageManager . GET_META_DATA ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         dataList . clear ( ) ;   // 清空列表避免重复 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         dataList . clear ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         LogUtils . d ( TAG ,   " 开始加载应用包名列表,共找到 "   +   appList . size ( )   +   " 个应用 " ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 仅遍历包名,不处理名称(避免名称获取异常影响) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         for   ( ApplicationInfo   appInfo   :   appList )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   packageName   =   appInfo . packageName ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // 模型仅存包名、初始耗电0、初始时长0(  名称显示/搜索时用缓存)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             dataList . add ( new   AppBatteryModel ( packageName ,   " 0.0 " ,   0 ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // 初始化:  单次耗电(  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 ( ) ;   // 清空旧缓存 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         packageToAppNameCache . clear ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         LogUtils . d ( TAG ,   " 开始预缓存包名-应用名称映射 " ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         for   ( AppBatteryModel   model   :   dataList )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   packageName   =   model . getPackageName ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   appName   =   getAppNameByPackage ( packageName ) ;   // 复用工具方法获取名称 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             packageToAppNameCache . put ( packageName ,   appName ) ;   // 缓存映射关系 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             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 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // Java7 显式判断包名是否在缓存中 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             if   ( appRunTimeCache . containsKey ( packageName ) )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 runTime   =   appRunTimeCache . get ( packageName ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 LogUtils . d ( TAG ,   String . format ( " 应用包 %s 运行时长已更新。 " ,   packageName ) ) ; 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -213,30 +197,94 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 新增:双维度过滤(包名+应用名称 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 搜索关键词同时匹配“包名(不区分大小写)”或“应用名称(不区分大小写)”  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 【 新增】初始化时计算24小时累计耗电(  赋值给totalConsumption )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 逻辑:  基于24小时运行时长占比,  分配当前电池容量的理论24小时消耗  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   void   calculateInitial24hTotalConsumption ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         long   total24hRunTime   =   0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 1. 计算24小时内所有应用总运行时长 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         for   ( Map . Entry < String ,   Long >   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 < String ,   Long >   runTimeMap )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         long   totalSingleRunTime   =   0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 1. 计算本次电池下降期间的总运行时长 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         for   ( Map . Entry < String ,   Long >   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 < AppBatteryModel > ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								 @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 ( ) ;   // 统一转为小写,实现不区分大小写搜索 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   lowerKeyword   =   keyword . toLowerCase ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             for   ( AppBatteryModel   model   :   dataList )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 String   packageName   =   model . getPackageName ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 String   packageNameLower   =   packageName . toLowerCase ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 // 从缓存中获取应用名称(  避免重复查询PackageManager)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 String   appName   =   packageToAppNameCache . get ( packageName ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 String   appNameLower   =   appName . toLowerCase ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 // 匹配规则:包名包含关键词 OR 应用名称包含关键词 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 boolean   isMatched   =   packageNameLower . contains ( lowerKeyword )   
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									 | |   appNameLower . contains ( lowerKeyword ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     | |   appNameLower . contains ( lowerKeyword ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 if   ( isMatched )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     filteredList . add ( model ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -244,7 +292,7 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 获取应用运行时长(返回包名-时长映射,不处理名称 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 获取应用运行时长(逻辑不变,  返回24小时运行时长 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   Map < String ,   Long >   getAppRunTime ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         Map < String ,   Long >   runTimeMap   =   new   HashMap < String ,   Long > ( ) ; 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -257,11 +305,10 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 List < android . app . usage . UsageStats >   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   +   " 运行时长: "   +   formatRunTime ( runTimeMs ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     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 ) ) ; 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -277,7 +324,7 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 格式化运行时长(工具方法,与包名无关 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 格式化运行时长(逻辑不变 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   String   formatRunTime ( long   runTimeMs )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if   ( runTimeMs   < =   0 )   { 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -298,48 +345,7 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 分配电池消耗(全程用包名计算,不涉及名称 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   void   distributeBatteryConsumption ( float   totalDropPercent ,   Map < String ,   Long >   runTimeMap )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         long   totalRunTime   =   0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 遍历包名计算总时长 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         for   ( Map . Entry < String ,   Long >   entry   :   runTimeMap . entrySet ( ) )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             totalRunTime   + =   entry . getValue ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 按包名匹配计算各应用耗电 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         for   ( AppBatteryModel   model   :   dataList )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   packageName   =   model . getPackageName ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             Long   appRunTime ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // Java7 显式判断包名是否存在 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             if   ( runTimeMap . containsKey ( packageName ) )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 appRunTime   =   runTimeMap . get ( packageName ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             }   else   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 appRunTime   =   0L ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             float   ratio   =   ( totalRunTime   >   0 )   ?   ( float )   appRunTime   /   totalRunTime   :   0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             float   consumption   =   batteryCapacity   *   totalDropPercent   /   100   *   ratio ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             model . setConsumption ( String . format ( " %.1f " ,   consumption ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             model . setRunTime ( appRunTime ) ;   // 同步更新时长 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 按耗电排序(用包名对应的耗电值排序) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         Collections . sort ( dataList ,   new   Comparator < AppBatteryModel > ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								 @Override 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								 public   int   compare ( AppBatteryModel   m1 ,   AppBatteryModel   m2 )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									 float   c1   =   Float . parseFloat ( m1 . getConsumption ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									 float   c2   =   Float . parseFloat ( m2 . getConsumption ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									 return   Float . compare ( c2 ,   c1 ) ;   // 逆序(耗电从高到低) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								 } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							 } ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 重新应用“包名+名称”双维度过滤 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         filterAppsByPackageAndName ( etSearch . getText ( ) . toString ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 权限检查(仅操作系统服务,与包名无关) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 权限检查(逻辑不变 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     private   boolean   hasUsageStatsPermission ( Context   context )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if   ( Build . VERSION . SDK_INT   <   Build . VERSION_CODES . LOLLIPOP )   { 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -361,31 +367,43 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 数据模型(仅存储包名、耗电、时长,不存名称)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * 【核心修改】数据模型:明确字段含义  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * - consumption:  单次耗电(  两次电池广播间的消耗,  float类型便于计算)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * - totalConsumption:  累计耗电(  24小时初始化值+后续单次累加,显示用) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     public   static   class  AppBatteryModel   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   String   packageName ;   // 核心标识: 应用包名 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   String   consumption ;   // 电量消耗(  mAh )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   long    runTime ;         // 运行时长(  ms ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   String   packageName ;      // 应用包名(核心标识)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   float   consumption ;       // 单次耗电(  mAh,  float类型 )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   f loat   totalConsumption ; // 累计耗电(  mAh,  显示+排序用 ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   long   runTime ;            // 运行时长(  ms)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // Java7 显式构造(仅传入包名、初始耗电、初始时长)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         public   AppBatteryModel ( String   packageName ,   String   c onsumption,   long   runTime )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						 // Java7 显式构造:  初始化单次耗电、累计耗电为0 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         public   AppBatteryModel ( String   packageName ,   float   consumption ,   float   totalC onsumption,   long   runTime )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . packageName   =   packageName ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . consumption   =   consumption ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . consumption   =   consumption ;   // 单次耗电初始为0 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . totalConsumption   =   totalConsumption ;   // 累计耗电初始为0(  后续初始化时赋值)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . runTime   =   runTime ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // Getter/Setter(仅操作包名、耗电、时长)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // Getter/Setter:覆盖所有字段,确保数据操作正常  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         public   String   getPackageName ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             return   packageName ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         public   String   getConsumption ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             return   consumption ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         public   float   getConsumption ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             return   consumption ;   // 获取单次耗电 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         public   void   setConsumption ( String   consumption )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . consumption   =   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 ( )   { 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -398,37 +416,37 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * RecyclerView 适配器(支持从缓存获取名称,避免重复查询)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     * RecyclerView 适配器:  仅显示累计耗电(  totalConsumption) ,  逻辑适配模型修改 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     public   static   class  BatteryReportAdapter   extends   RecyclerView . Adapter < BatteryReportAdapter . ViewHolder >   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   Context   mContext ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   List < AppBatteryModel >   mDataList ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   PackageManager   mPm ;   // 兜底用:缓存无名称时查询 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   Map < String ,   String >   mPackageToNameCache ;   // 新增:名称缓存映射 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   PackageManager   mPm ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         private   Map < String ,   String >   mPackageToNameCache ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // Java7 显式构造(新增 名称缓存参数)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // Java7 显式构造:接收 名称缓存,确保显示时高效获取应用名  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         public   BatteryReportAdapter ( Context   context ,   List < AppBatteryModel >   dataList ,   
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     PackageManager   pm ,   Map < String ,   String >   packageToNameCache )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . mContext   =   context ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . mDataList   =   dataList ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . mPm   =   pm ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             this . mPackageToNameCache   =   packageToNameCache ;   // 接收名称缓存 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             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 显式非空判断(  避免空指针)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // Java7 显式非空判断:  避免空指针异常  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             if   ( mDataList   = =   null   | |   mDataList . isEmpty ( )   | |   position   > =   mDataList . size ( ) )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 holder . tvAppName . setText ( " 未知应用 " ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 holder . tvConsumption . setText ( " 耗电:  0.0 mAh | 运行时长:  0秒 " ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 holder . tvConsumption . setText ( " 累计 耗电:  0.0 mAh | 运行时长:  0秒" ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 return ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -436,66 +454,59 @@ public class BatteryReportActivity extends Activity {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   packageName   =   model . getPackageName ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   appName   =   " " ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // 优先从缓存获取名称(避免重复调用 PackageManager,  提升性能)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // 优先从缓存获取应用名:减少 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 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     appName   =   packageName ;   // 包名不存在时用包名兜底 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     LogUtils . e ( " Adapter " ,   " 包名 "   +   packageName   +   " 对应的应用未找到: "   +   e . getMessage ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 }   catch   ( Exception   e )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     appName   =   packageName ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     appName   =   packageName ;   // 其他异常时用包名兜底 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     LogUtils . e ( " Adapter " ,   " 查询应用名称失败(包名: "   +   packageName   +   " ) : "   +   e . getMessage ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // 显示应用名称(缓存/兜底结果)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // 显示逻辑:  仅展示累计耗电(  totalConsumption) ,  隐藏单次耗电  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             holder . tvAppName . setText ( appName ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // 格式化运行时长(调用 Activity 的工具方法) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // 格式化运行时长 + 累计耗电(  保留1位小数,  提升可读性)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   runTimeStr   =   ( ( BatteryReportActivity )   mContext ) . formatRunTime ( model . getRunTime ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // 显示耗电+运行时长(基于包名计算的结果) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   consumptionText   =   String . format ( " 耗电:%s mAh | 运行时长:%s " , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                                    mo del  . ge tConsumption( ) ,   runTimeStr ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             holder . tvConsumption . setText ( consumptionText ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             String   totalConsumptionText   =   String . format ( " 累计耗电:%.1f mAh | 运行时长:%s " , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
																		 model . getTotalConsumption ( ) ,   runTimeStr ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            hol der  . tv Consumption . 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 . setTextColor ( mContext . getResources ( ) . getColor ( android . R . color . holo_blue_dark ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							 holder . tvConsumption . setTextColor ( mContext . getResources ( ) . getColor ( android . R . color . holo_blue_dark ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							 //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 三元运算符)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // 获取列表长度:  Java7 三元运算符判断空值,避免空指针  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         @Override 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         public   int   getItemCount ( )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             return   mDataList   = =   null   ?   0   :   mDataList . size ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // ViewHolder(  绑定系统布局的两个 TextView)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         /** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         * ViewHolder:  绑定系统布局控件,  与显示逻辑对应 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         public   static   class  ViewHolder   extends   RecyclerView . ViewHolder   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             TextView   tvAppName ;       // 显示应用名称(缓存/兜底获取)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             TextView   tvConsumption ;   // 显示耗电+运行时长(包名计算结果)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             TextView   tvAppName ;       // 显示应用名称 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             TextView   tvConsumption ;   // 显示累计耗电 + 运行时长  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // Java7 显式构造 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             // Java7 显式构造:  绑定控件ID(  系统布局固定ID:  text1、text2)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             public   ViewHolder ( View   itemView )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 super ( itemView ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 // 强制类型转换(系统布局控件 ID:  text1 和 text2)  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 tvAppName   =   ( TextView )   itemView . findViewById ( android . R . id . text1 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 tvConsumption   =   ( TextView )   itemView . findViewById ( android . R . id . text2 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             }