獲取安裝應用Apk包大小、緩存大小以及應用占用存儲總大小 可以通過 PackageManager類的getPackageSizeInfo方法獲取,但是這個方法被Google標記成隱藏方法,不能直接調用; 解決方法:可以通過反射調用,但在Android8.0及以上通過反射調用會報錯,不過Android8.0及以上可以通過StorageManager 獲取
Android8.0以下獲取Apk大小方法: 通過反射調用getPackageSizeInfo獲取
創建AIDL文件
創建文件 IPackageStatsObserver.aidl
package android. content. pm ; import android. content. pm. PackageStats ;
oneway
interface IPackageStatsObserver { void onGetStatsCompleted ( in
PackageStats pStats
, boolean succeeded
) ;
}
package android. content. pm ; parcelable
PackageStats ;
注意包名路徑創建正確
如下圖: 創建完成后依次點擊 Build --> Make Project 以生成AIDL文件
在AndroidManifest.xml 中添加權限
< uses-permission android: name= " android.permission.GET_PACKAGE_SIZE" />
代碼實現
public static void handlePackageSizeInfo ( Context context
, String packageName
) { PackageManager mPackageManager
= context
. getPackageManager ( ) ; Method getPackageSizeInfo
= null ; try { getPackageSizeInfo
= mPackageManager
. getClass ( ) . getMethod ( "getPackageSizeInfo" , String . class , IPackageStatsObserver . class ) ; } catch ( NoSuchMethodException e
) { e
. printStackTrace ( ) ; } MyPackageStatsObserver mSecurityPackageStatsObserver
= new MyPackageStatsObserver ( ) ; if ( getPackageSizeInfo
!= null ) { try { getPackageSizeInfo
. setAccessible ( true ) ; getPackageSizeInfo
. invoke ( mPackageManager
, packageName
, mSecurityPackageStatsObserver
) ; } catch ( IllegalAccessException | IllegalArgumentException | InvocationTargetException e
) { e
. printStackTrace ( ) ; } } } static class MyPackageStatsObserver extends IPackageStatsObserver. Stub { @Override public void onGetStatsCompleted ( PackageStats pStats
, boolean succeeded
) { long mCacheSize
= pStats
. cacheSize
; long mCodeSize
= pStats
. codeSize
; long mDataSize
= pStats
. dataSize
; long mTotalSize
= mCacheSize
+ mCodeSize
+ mDataSize
; Log . d ( "AppLog" , succeeded
+ " cacheSize = " + mCacheSize
+ "; appSize = " + mCodeSize
+ "; " + "dataSize = " + mDataSize
+ "; totalSize = " + mTotalSize
) ; } }
Android8.0及以上獲取Apk大小方法: 通過系統服務 StorageManager 獲取Apk大小,需要申請權限 PACKAGE_USAGE_STATS
在AndroidManifest.xml 中添加權限
< uses-permissionandroid: name= " android.permission.PACKAGE_USAGE_STATS" tools: ignore= " ProtectedPermissions" />
代碼實現
@RequiresApi ( api
= Build. VERSION_CODES. O ) public static void getAppSize ( Context context
, String packageName
) { if ( ! hasUsageStatsPermission ( context
) ) { requestAppUsagePermission ( context
) ; } else { new Thread ( ( ) -> { final StorageStatsManager storageStatsManager
= ( StorageStatsManager ) context
. getSystemService ( Context . STORAGE_STATS_SERVICE
) ; final StorageManager storageManager
= ( StorageManager ) context
. getSystemService ( Context . STORAGE_SERVICE
) ; final List < StorageVolume > storageVolumes
= storageManager
. getStorageVolumes ( ) ; final UserHandle user
= android. os. Process. myUserHandle ( ) ; try { for ( StorageVolume storageVolume
: storageVolumes
) { final String uuidStr
= storageVolume
. getUuid ( ) ; final UUID uuid
= uuidStr
== null ? StorageManager . UUID_DEFAULT
: UUID
. fromString ( uuidStr
) ; Log . d ( "AppLog" , "storage:" + uuid
+ " : " + storageVolume
. getDescription ( context
) + " : " + storageVolume
. getState ( ) ) ; Log . d ( "AppLog" , "getFreeBytes:" + Formatter . formatShortFileSize ( context
, storageStatsManager
. getFreeBytes ( uuid
) ) ) ; Log . d ( "AppLog" , "getTotalBytes:" + Formatter . formatShortFileSize ( context
, storageStatsManager
. getTotalBytes ( uuid
) ) ) ; StorageStats storageStats
= storageStatsManager
. queryStatsForPackage ( uuid
, packageName
, user
) ; Log . d ( "AppLog" , "storage stats for app of package name:" + packageName
+ " : " ) ; Log . d ( "AppLog" , "getAppBytes:" + Formatter . formatShortFileSize ( context
, storageStats
. getAppBytes ( ) ) + " getCacheBytes:" + Formatter . formatShortFileSize ( context
, storageStats
. getCacheBytes ( ) ) + " getDataBytes:" + Formatter . formatShortFileSize ( context
, storageStats
. getDataBytes ( ) ) ) ; } } catch ( PackageManager. NameNotFoundException e
) { e
. printStackTrace ( ) ; } catch ( IOException e
) { e
. printStackTrace ( ) ; } } ) . start ( ) ; } } public static boolean hasUsageStatsPermission ( Context context
) { UsageStatsManager usageStatsManager
= null ; if ( android. os. Build. VERSION
. SDK_INT
>= android. os. Build. VERSION_CODES
. LOLLIPOP_MR1
) { usageStatsManager
= ( UsageStatsManager ) context
. getSystemService ( Context . USAGE_STATS_SERVICE
) ; } if ( usageStatsManager
== null ) { return false ; } long currentTime
= System . currentTimeMillis ( ) ; List < UsageStats > stats
= usageStatsManager
. queryUsageStats ( UsageStatsManager . INTERVAL_DAILY
, currentTime
- 2 * 60 * 1000 , currentTime
) ; return stats
!= null && stats
. size ( ) > 0 ; } public static void requestAppUsagePermission ( Context context
) { Intent intent
= new Intent ( android. provider. Settings. ACTION_USAGE_ACCESS_SETTINGS
) ; intent
. addFlags ( Intent . FLAG_ACTIVITY_NEW_TASK
) ; try { context
. startActivity ( intent
) ; } catch ( ActivityNotFoundException e
) { Log . e ( "AppLog" , "Start usage access settings activity fail!" , e
) ; } }
總結
public static void getInstallApkSize ( Context context
, String packageName
) { if ( Build . VERSION
. SDK_INT
>= Build. VERSION_CODES. O ) { getAppSize ( context
, packageName
) ; } else { handlePackageSizeInfo ( context
, packageName
) ; } }
Android8.0以下可以通過反射getPackageSizeInfo方法獲取Apk大小; Android8.0及以上可以通過申請權限 PACKAGE_USAGE_STATS 獲取其他已安裝應用的Apk大小 還有一種比較復雜方法是 編譯一下的android2.3的Framework框架,把jar包拷出來,再把框架導入到library,之后就可以直接調用已經hide 的方法 getPackageSizeInfo() 了,具體操作可以搜一下
總結
以上是生活随笔 為你收集整理的Android获取安装应用Apk包大小 缓存大小 getPackageSizeInfo StorageManager 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。