Android:利用Java反射调用@hide的API

本文介绍了如何在Android中通过Java反射技术调用被@hide注解的API,以实现设置3G数据功能。同时,提供了利用反射解析APK包信息的代码示例,强调需要添加相应的权限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设置使用3G数据功能:

从源代码看到隐藏的API(ConnectivityManager.java):

 /**
     * Sets the persisted value for enabling/disabling Mobile data.
     *
     * @param enabled Whether the mobile data connection should be
     *            used or not.
     * @hide
     */
    public void setMobileDataEnabled(boolean enabled) {
        try {
            mService.setMobileDataEnabled(enabled);
        } catch (RemoteException e) {
        }
    }

通过java reflection功能来实现该功能,即调用
 mService.setMobileDataEnabled(enabled);

代码如下:

private void EnableMobileData(boolean enable)
	{
		ConnectivityManager connectivitymanager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

		try
		{
			// Get mService
			// android.net.ConnectivityManager.mService;
			Field field = Class.forName(ConnectivityManager.class.getName())
					.getDeclaredField("mService");
			field.setAccessible(true);
			/*
			// 权限修饰符
			int mo = field.getModifiers();
			String priv = Modifier.toString(mo);
			// 属性类型
			Class<?> type = field.getType();
			Log.i(TAG, priv + " " + type.getName() + " " + field.getName()
					+ ";");
            */
			// get Object of mService
			Object obj = field.get(connectivitymanager);// connectivitymanager.mService
			// get IConnectivityManager class
			Class myClass = Class.forName(obj.getClass().getName());
			Log.i(TAG, "class3:" + obj.getClass().getName());// IConnectivityManager
			// get android.net.IConnectivityManager
			// public void setMobileDataEnabled(boolean enabled) throws
			// android.os.RemoteException;
			Method method = myClass.getDeclaredMethod("setMobileDataEnabled",
					boolean.class);

			/*
			String pstr = "";
			Class<?>[] parameters = method.getParameterTypes();
			int count = parameters.length;
			Log.i(TAG, "count:" + count);
			if (count > 0)
			{
				for (Class<?> p : parameters)
				{
					pstr += p.getName() + ",";
				}
				pstr = pstr.substring(0, pstr.length() - 1);
				Log.i(TAG, "pstr:" + pstr);
			}
			Log.i(TAG, Modifier.toString(method.getModifiers()) + " "
					+ method.getReturnType().getName() + " " + method.getName()
					+ "(" + pstr + ");");
			*/
			method.setAccessible(true);
			method.invoke(obj, enable);

		}
		catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

注意添加相应的permission:

   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />


补充一个网上利用java reflection解析APK软件包信息的代码:

// Ref:http://blog.youkuaiyun.com/sodino/article/details/6215224
	// 利用反射机制调用android @hide的API进行解析
	public static void ExtractApkInfoExt(String apkPath, DownloadTask task)
	{
		String PATH_PackageParser = "android.content.pm.PackageParser";
		String PATH_AssetManager = "android.content.res.AssetManager";
		try
		{
			// apk包的文件路径
			// 这是一个Package 解释器, 是隐藏的
			// 构造函数的参数只有一个, apk文件的路径
			// PackageParser packageParser = new PackageParser(apkPath);
			Class pkgParserCls = Class.forName(PATH_PackageParser);
			Class[] typeArgs = new Class[1];
			typeArgs[0] = String.class;
			Constructor pkgParserCt = pkgParserCls.getConstructor(typeArgs);
			Object[] valueArgs = new Object[1];
			valueArgs[0] = apkPath;
			Object pkgParser = pkgParserCt.newInstance(valueArgs);
			if (Constants.DEBUG_MODE)
				Log.d(TAG, "pkgParser:" + pkgParser.toString());
			// 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况
			DisplayMetrics metrics = new DisplayMetrics();
			metrics.setToDefaults();
			// PackageParser.Package mPkgInfo = packageParser.parsePackage(new
			// File(apkPath), apkPath,
			// metrics, 0);
			typeArgs = new Class[4];
			typeArgs[0] = File.class;
			typeArgs[1] = String.class;
			typeArgs[2] = DisplayMetrics.class;
			typeArgs[3] = Integer.TYPE;
			Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod(
					"parsePackage", typeArgs);
			valueArgs = new Object[4];
			valueArgs[0] = new File(apkPath);
			valueArgs[1] = apkPath;
			valueArgs[2] = metrics;
			valueArgs[3] = 0;
			Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser,
					valueArgs);
			if (pkgParserPkg == null)
			{
				return;
			}
			// 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开
			// ApplicationInfo info = mPkgInfo.applicationInfo;
			Field appInfoFld = pkgParserPkg.getClass().getDeclaredField(
					"applicationInfo");
			ApplicationInfo info = (ApplicationInfo) appInfoFld
					.get(pkgParserPkg);

			// get VersionCode
			Field versionCodeFld = pkgParserPkg.getClass().getDeclaredField(
					"mVersionCode");
			int versionCode = ((Integer) versionCodeFld.get(pkgParserPkg))
					.intValue();

			// get VersionName
			Field versionNameFld = pkgParserPkg.getClass().getDeclaredField(
					"mVersionName");

			String versionName = (String) versionNameFld.get(pkgParserPkg);

			// uid 输出为"-1",原因是未安装,系统未分配其Uid。
			if (Constants.DEBUG_MODE)
				Log.d(TAG, "pkg:" + info.packageName + " uid=" + info.uid);
			// Resources pRes = getResources();
			// AssetManager assmgr = new AssetManager();
			// assmgr.addAssetPath(apkPath);
			// Resources res = new Resources(assmgr, pRes.getDisplayMetrics(),
			// pRes.getConfiguration());

			Class assetMagCls = Class.forName(PATH_AssetManager);
			Constructor assetMagCt = assetMagCls.getConstructor((Class[]) null);
			Object assetMag = assetMagCt.newInstance((Object[]) null);
			typeArgs = new Class[1];
			typeArgs[0] = String.class;
			Method assetMag_addAssetPathMtd = assetMagCls.getDeclaredMethod(
					"addAssetPath", typeArgs);
			valueArgs = new Object[1];
			valueArgs[0] = apkPath;
			assetMag_addAssetPathMtd.invoke(assetMag, valueArgs);
			Resources res = mContext.getResources();
			typeArgs = new Class[3];
			typeArgs[0] = assetMag.getClass();
			typeArgs[1] = res.getDisplayMetrics().getClass();
			typeArgs[2] = res.getConfiguration().getClass();
			Constructor resCt = Resources.class.getConstructor(typeArgs);
			valueArgs = new Object[3];
			valueArgs[0] = assetMag;
			valueArgs[1] = res.getDisplayMetrics();
			valueArgs[2] = res.getConfiguration();
			res = (Resources) resCt.newInstance(valueArgs);
			CharSequence label = null;
			if (info.labelRes != 0)
			{
				label = res.getText(info.labelRes);
				// if (label == null) {
				// label = (info.nonLocalizedLabel != null) ?
				// info.nonLocalizedLabel
				// : info.packageName;
				// }
				task.setTitle(String.valueOf(label));
			}

			if (Constants.DEBUG_MODE)
				Log.d(TAG, "label=" + label);
			// 这里就是读取一个apk程序的图标
			if (info.icon != 0)
			{
				Drawable icon = res.getDrawable(info.icon);
				task.setIcon(((BitmapDrawable) icon).getBitmap());
				// ImageView image = (ImageView) findViewById(R.id.appicon);
				// image.setVisibility(View.VISIBLE);
				// image.setImageDrawable(icon);
			}
			if (versionName != null)
			{
				task.setVersionName(versionName);
			}
			task.setVersionCode(versionCode);
			task.setPackageName(info.packageName);
			if (info.processName == null)
			{
				info.processName = info.packageName;
			}
			task.setProcessName(info.processName);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值