package com.weishu.upf.receiver_management.app;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.util.Log;
/**
* @author weishu
* @date 16/4/7
*/
public final class ReceiverHelper {
private static final String TAG = "ReceiverHelper";
public static Map<ActivityInfo, List<? extends IntentFilter>> sCache =
new HashMap<ActivityInfo, List<? extends IntentFilter>>();
/**
* 解析Apk文件中的 <receiver>, 并存储起来
*
* @param apkFile
* @throws Exception
*/
private static void parserReceivers(File apkFile) throws Exception {
Class<?> packageParserClass = Class.forName("android.content.pm.PackageParser");
Method parsePackageMethod = packageParserClass.getDeclaredMethod("parsePackage", File.class, int.class);
Object packageParser = packageParserClass.newInstance();
// 首先调用parsePackage获取到apk对象对应的Package对象
Object packageObj = parsePackageMethod.invoke(packageParser, apkFile, PackageManager.GET_RECEIVERS);
// 读取Package对象里面的receivers字段,注意这是一个 List<Activity> (没错,底层把<receiver>当作<activity>处理)
// 接下来要做的就是根据这个List<Activity> 获取到Receiver对应的 ActivityInfo (依然是把receiver信息用activity处理了)
Field receiversField = packageObj.getClass().getDeclaredField("receivers");
List receivers = (List) receiversField.get(packageObj);
// 调用generateActivityInfo 方法, 把PackageParser.Activity 转换成
Class<?> packageParser$ActivityClass = Class.forName("android.content.pm.PackageParser$Activity");
Class<?> packageUserStateClass = Class.forName("android.content.pm.PackageUserState");
Class<?> userHandler = Class.forName("android.os.UserHandle");
Method getCallingUserIdMethod = userHandler.getDeclaredMethod("getCallingUserId");
int userId = (Integer) getCallingUserIdMethod.invoke(null);
Object defaultUserState = packageUserStateClass.newInstance();
Class<?> componentClass = Class.forName("android.content.pm.PackageParser$Component");
Field intentsField = componentClass.getDeclaredField("intents");
// 需要调用 android.content.pm.PackageParser#generateActivityInfo(android.content.pm.ActivityInfo, int, android.content.pm.PackageUserState, int)
Method generateReceiverInfo = packageParserClass.getDeclaredMethod("generateActivityInfo",
packageParser$ActivityClass, int.class, packageUserStateClass, int.class);
// 解析出 receiver以及对应的 intentFilter
for (Object receiver : receivers) {
ActivityInfo info = (ActivityInfo) generateReceiverInfo.invoke(packageParser, receiver, 0, defaultUserState, userId);
List<? extends IntentFilter> filters = (List<? extends IntentFilter>) intentsField.get(receiver);
sCache.put(info, filters);
}
}
public static void preLoadReceiver(Context context, File apk) throws Exception {
parserReceivers(apk);
ClassLoader cl = null;
for (ActivityInfo activityInfo : ReceiverHelper.sCache.keySet()) {
Log.i(TAG, "preload receiver:" + activityInfo.name);
List<? extends IntentFilter> intentFilters = ReceiverHelper.sCache.get(activityInfo);
if (cl == null) {
cl = CustomClassLoader.getPluginClassLoader(apk, activityInfo.packageName);
}
// 把解析出来的每一个静态Receiver都注册为动态的
for (IntentFilter intentFilter : intentFilters) {
BroadcastReceiver receiver = (BroadcastReceiver) cl.loadClass(activityInfo.name).newInstance();
context.registerReceiver(receiver, intentFilter);
}
}
}
}