package com.example.weishu.contentprovider_management;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.util.Log;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* @author weishu
* @date 16/7/8.
*/
public class ProviderHelper {
/**
* 解析Apk文件中的 <provider>, 并存储起来
* 主要是调用PackageParser类的generateProviderInfo方法
*
* @param apkFile 插件对应的apk文件
* @throws Exception 解析出错或者反射调用出错, 均会抛出异常
*/
public static List<ProviderInfo> parseProviders(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_PROVIDERS);
// 读取Package对象里面的services字段
// 接下来要做的就是根据这个List<Provider> 获取到Provider对应的ProviderInfo
Field providersField = packageObj.getClass().getDeclaredField("providers");
List providers = (List) providersField.get(packageObj);
// 调用generateProviderInfo 方法, 把PackageParser.Provider转换成ProviderInfo
Class<?> packageParser$ProviderClass = Class.forName("android.content.pm.PackageParser$Provider");
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();
// 需要调用 android.content.pm.PackageParser#generateProviderInfo
Method generateProviderInfo = packageParserClass.getDeclaredMethod("generateProviderInfo",
packageParser$ProviderClass, int.class, packageUserStateClass, int.class);
List<ProviderInfo> ret = new ArrayList<>();
// 解析出intent对应的Provider组件
for (Object service : providers) {
ProviderInfo info = (ProviderInfo) generateProviderInfo.invoke(packageParser, service, 0, defaultUserState, userId);
ret.add(info);
}
return ret;
}
/**
* 在进程内部安装provider, 也就是调用 ActivityThread.installContentProviders方法
*
* @param context you know
* @param apkFile
* @throws Exception
*/
public static void installProviders(Context context, File apkFile) throws Exception {
List<ProviderInfo> providerInfos = parseProviders(apkFile);
for (ProviderInfo providerInfo : providerInfos) {
providerInfo.applicationInfo.packageName = context.getPackageName();
}
Log.d("test", providerInfos.toString());
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
Object currentActivityThread = currentActivityThreadMethod.invoke(null);
Method installProvidersMethod = activityThreadClass.getDeclaredMethod("installContentProviders", Context.class, List.class);
installProvidersMethod.setAccessible(true);
installProvidersMethod.invoke(currentActivityThread, context, providerInfos);
}
}