標籤:android apk
在擷取apk資源時候最重要的一個類就是PackageManager,我們可以通過這個類得到各種想要的東西,首先是得到已經安裝的apk的基本資料,包括label,和表徵圖等資源:
PackageManager pm = getPackageManager();List<PackageInfo> apkInfos = pm.getInstalledPackages(0);ArrayList<String> infos_name = new ArrayList<String>() ;//用來存放labelArrayList<Drawable> infos_icon = newArrayList<Drawable>();//用來儲存apk啟動表徵圖資源String name = ""; Drawable icon; PackageInfo apk; for (int i = 0; i < apkInfos.size(); ) { apk = apkInfos.get(i); i++; name = (String) pm.getApplicationLabel(apk.applicationInfo); icon = pm.getApplicationIcon(apk.applicationInfo); infos_icon.add(icon); infos_name.add(name); } 接下來我們利用PackageManager獲得已安裝apk中的activity,和service等
List<PackageInfo>packagesInfo = pm.getInstalledPackages(0);for (PackageInfo packageInfo : packagesInfo) {Log.d("TAG","packageInfo NAME IS :"+packageInfo.packageName);}PackageManager pm = getPackageManager();try { //獲得com.example.pertest包中的activity,service和broadcastreceiverPackageInfo packageInfo = pm.getPackageInfo("com.example.pertest",PackageManager.GET_PERMISSIONS| PackageManager.GET_SERVICES| PackageManager.GET_RECEIVERS);ActivityInfo[] activities = packageInfo.activities;if (activities != null) {for (ActivityInfo activityInfo : activities) {Log.d("TAG", "the activity " + activityInfo.toString()+ "==" + packageInfo.versionCode + "==="+ packageInfo.versionName);}} else {Log.d("TAG", "the activity is null");}ServiceInfo[] serviceInfos = packageInfo.services;for (ServiceInfo serviceInfo : serviceInfos) {Log.d("TAG", "service name is :" + serviceInfo.name);}activities = packageInfo.receivers;for (ActivityInfo activity : activities) {Log.d("TAG", "receiver is :" + activity.name);}} catch (NameNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}
上面就是擷取已經安裝的apk的基本資料,接下來看看如何擷取未安裝的apk檔案的基本資料,這對於android動態載入時很有用的,我們來看:
得到未安裝apk的表徵圖:
public static Drawable getAppIcon(Context context, String apkFilepath) { PackageManager pm = context.getPackageManager(); PackageInfo pkgInfo = getPackageInfo(context, apkFilepath); if (pkgInfo == null) { return null; } ApplicationInfo appInfo = pkgInfo.applicationInfo; if (Build.VERSION.SDK_INT >= 8) { appInfo.sourceDir = apkFilepath; appInfo.publicSourceDir = apkFilepath; } return pm.getApplicationIcon(appInfo); }得到未安裝apk的名稱:
public static CharSequence getAppLabel(Context context, String apkFilepath) { PackageManager pm = context.getPackageManager(); PackageInfo pkgInfo = getPackageInfo(context, apkFilepath); if (pkgInfo == null) { return null; } ApplicationInfo appInfo = pkgInfo.applicationInfo; if (Build.VERSION.SDK_INT >= 8) { appInfo.sourceDir = apkFilepath; appInfo.publicSourceDir = apkFilepath; } return pm.getApplicationLabel(appInfo); }如果還覺得不夠的話,我們可以得到:PackageInfo對象,通過該對象,我們就可以獲得該未安裝apk的activity,service,broadcastreceiver等,方法同"獲得已安裝apk中的activity,和service" ,代碼如下:
//得到PackageInfo對象,其中包含了該apk包含的activity和servicepublic static PackageInfo getPackageInfo(Context context, String apkFilepath) { PackageManager pm = context.getPackageManager(); PackageInfo pkgInfo = null; try { pkgInfo = pm.getPackageArchiveInfo(apkFilepath, PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES); } catch (Exception e) { // should be something wrong with parse e.printStackTrace(); } return pkgInfo; }
在android動態載入的時候,是通過DexClassLoader來實現的,通過這種方式來擷取未安裝程式的DexClassLoader對象:
String mNativeLibDir = mContext.getDir("pluginlib", Context.MODE_PRIVATE).getAbsolutePath(); private DexClassLoader createDexClassLoader(String dexPath) { File dexOutputDir = mContext.getDir("dex", Context.MODE_PRIVATE); dexOutputPath = dexOutputDir.getAbsolutePath(); DexClassLoader loader = new DexClassLoader(dexPath, dexOutputPath, mNativeLibDir, mContext.getClassLoader()); return loader; } 第一個參數dexPath就是我們apk的存放路徑。
第二個參數dexOutPath就是該apk檔案對應的dex檔案的存放路徑,不可以為null。
第三個參數是目標類中使用的C/C++庫的列表,每個目錄用File.pathSeparator間隔開; 可以為 null。
第四個參數是該類裝載器的父裝載器,一般用當前執行類的裝載器。
在獲得了該DexClassLoader對象以後,我們就可以實現動態載入該apk中的方法了,詳細的方法,請看我的另一篇文章:android動態載入
對於載入未安裝的apk中的資源,由於使用的是不同的context,所以,這裡先這樣做:
private AssetManager createAssetManager(String dexPath) { try { AssetManager assetManager = AssetManager.class.newInstance(); Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class); addAssetPath.invoke(assetManager, dexPath); return assetManager; } catch (Exception e) { e.printStackTrace(); return null; } }private Resources createResources(AssetManager assetManager) { Resources superRes = mContext.getResources(); Resources resources = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration()); return resources;} 此時的assetManager和resources就可以和平時一樣來用了。
android得到已安裝和未安裝apk的資訊