不能访问的类或者接口
Android 有两种类型的 API 不能通过 SDK 访问。一种是在 com.android.internal
包中的 API(源码路径为framework/base/core/)。另一种是被标记为 @hide 属性的类和接口。
对于internal API来说,从来都没有计划将其开放出来。它就是Android的“内部厨房”,对开发者来说,应该将其视作黑盒。
Hidden API之所以被隐藏,是想阻止开发者使用SDK中那些未完成或不稳定的部分(接口或类),因为其可能会在后续的版本中被修改或者移除。
当使用 Android SDK 进行开发的时候,应用默认引用了 android.jar,它位于 sdk-platform-{android版本}-android.jar。SDK 中默认移除了所有的被@hide标识的接口或者类以及 internal 包下的类。
反射
// 当需要实现的功能比较多的时候,需要反射的类和方法就会变得很复杂和繁琐,除非实在没办法,尽量不选择该方式
// 此处跳过
原始android.jar
我们需要修改android.jar,这样它才能包含所有的*.class文件,包括internal和hidden API类,这里我们使用比较简单的方式
github上已经有提供了众多版本完整的android.jar包https://github.com/anggrayudi/android-hidden-api
下载地址转移到谷歌硬盘了
https://drive.google.com/drive/folders/17oMwQ0xBcSGn159mgbqxcXXEcneUmnph
下载android.jar后,替换掉 Android SDK (<SDK location>/platforms/
)下面的 jar ,例如android-30/android.jar
,build.gradle文件中compileSdkVersion , targetSdkVersion修改为30(因为这里是android-30),最好先备份一下原始的 jar,重新编译工程或者重启 Studio 就行了
可以看到这里就不再爆红了
也能够点击进去查看internal源代码
进行系统签名
我们的APP还需要有系统权限,由于我的测试设备已经ROOT了,所以现在还需要让APK进行系统签名,获取系统级权限,不然我们还是用不了internal方法
设置sharedUserId
通过设置同一个User id使得多个应用可以运行在同一个进程中,这里我们将sharedUserId设置成android.uid.system则可以将该应用和系统应用运行在同一进程中,则拥有了系统权限
AndroidManifest.xml添加sharedUserId
android:sharedUserId="android.uid.system"
如果现在直接编译生成APK安装会出现一个报错
INSTALL_FAILED_SHARED_USER_INCOMPATIBLE: Reconciliation failed
这是由Android的安全机制导致的错误,因为不可能我们随便写一个sharedUserId,就能够和另外的APK在一个进程中了,这样进程之间的隔离又会出现安全隐患,所以在Android中
使用同一个sharedUserId的应用,需要使用同一个签名文件
Android原生签名文件
这里我们是想和系统应用运行在同一个进程中,所以需要找到android原生应用相同的签名
访问https://android.googlesource.com/platform/build/+/donut-release/target/product/security
我们需要的是这两个签名文件
点击tgz就能够对这些文件进行下载
另外我们还需要下载keytool签名工具: https://github.com/getfatday/keytool-importkeypair
都搞定之后,为了方便查看,创建一个signAPK文件夹来放置这些签名文件
生成签名文件
再编写一个shell脚本signature文件来方便直接生成签名,文件内容为
./keytool-importkeypair -k test.jks -p 123456 -pk8 platform.pk8 -cert platform.x509.pem -alias test
- test.jks 生成签名文件的名称
- 123456 是签名的密码
- test 是签名的别名
双击脚本生成签名文件
AndroidStudio引入签名文件
在AndroidStudio中引入签名文件
先把test.jks丢到项目根目录下
build.gradle进行引入
signingConfigs {
debug {
keyAlias 'test'
keyPassword '123456'
storeFile file('../test.jks')
storePassword '123456'
}
release {
keyAlias 'test'
keyPassword '123456'
storeFile file('../test.jks')
storePassword '123456'
}
}
然后Sync一下,现在Build APK生成的APK文件就是拥有系统签名的了,同时我们可以调用internal相关文件了
检查功能
当然口说无凭,所以我们还是想检查一下是不是真的可以调用internal文件,这里写了一个小demo,主要功能调用查看一些com.android.internal.os.PowerProfile
获取的值
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button testbutton = findViewById(R.id.testbutton);
testbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
BatteryStatsHelper mStatsHelper = new BatteryStatsHelper(MainActivity.this, true);
Bundle nall=null;
mStatsHelper.create(nall);
mStatsHelper.clearStats();
final PowerProfile powerProfile = mStatsHelper.getPowerProfile();
Log.i(TAG,"powerProfile is "+powerProfile.toString());
Log.i(TAG,"powerProfile is "+powerProfile.getBatteryCapacity());
final double averagePower = powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
Log.i(TAG,"averagePower is "+averagePower);
// Toast.makeText(MainActivity.this, (int) averagePower, Toast.LENGTH_LONG).show();
}
});
}
编译之后安装到手机上
adb install app-debug.apk
点击运行测试,adb连接电脑之后输出日志
运行成功并输出结果
整个过程中的一些报错解决
编译的时候出现了报错,部分错误如下:
Failed to transform file 'android.jar' to match attributes {artifactType=android-mockable-jar
搜索之后发现是gradle plugin插件版本过高的原因,原来我是3.4.1,现在降到3.0.0试试
修改之后出现新报错
ERROR: Unable to find method 'org.gradle.api.tasks.compile.CompileOptions.setBootClasspath
原来gradle和插件版本是有对应关系的
https://developer.android.google.cn/studio/releases/gradle-plugin#updating-plugin
我这里的插件用的是3.0.0,所以对应的gradle版本应该需要降到4.1以下,(当然也可以选择升级插件版本来解决报错)
修改gradle-wrapper.properties
文件
出现新报错
Caused by: com.android.builder.dexing.DexArchiveBuilderException: Error while dexing META-INF/versions/9/module-info.class
解决方法
- 使用JDK9
- 删除
module-info.class
文件。(这个方法应该不是对每个人都有效,报错日志里明确指出了该文件报错,可以使用 WinRAR 打开 jar 包,进入对应的目录删除报错的文件,再重新在项目中依赖,如果编译不报错就可行)
我选择第二种方法
然后编译就没问题了,成功打出apk包
END
建了一个微信的安全交流群,欢迎添加我微信备注进群
,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注