背景

有时候在开发APK时需要一些特殊权限的API或者hide的方法,比如打开WIFI热点等,
可以调用通过系统源码编译出来的系统Jar包来解决

导入系统Jar包

  1. framework_all.jar添加进工程,一般为app/libs目录
    右击选择Add As Library,或在Project Structure中添加导入相关依赖,也可直接修改文件。

  2. 根目录下的build.gradle中设置

    allprojects {
    	repositories {
    		jcenter()
    		google()
    	}
    
    	gradle.projectsEvaluated {
    		tasks.withType(JavaCompile) {
    			options.compilerArgs.add('-Xbootclasspath/p:app/libs/framework_all.jar')
    		}
    	}
    }
  3. module下的build.gradle添加设置来更改引用库的优先级,优先引用自己添加的jar

    preBuild {
    	doLast {
    		def imlFile = file(project.name + ".iml")
    		println 'Change ' + project.name + '.iml order'
    		try {
    			def parsedXml = (new XmlParser()).parse(imlFile)
    			def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
    			parsedXml.component[1].remove(jdkNode)
    			def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
    			new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
    			groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
    		} catch (FileNotFoundException e) {
    			// nop, iml not found
    		}
    	}
    }
  4. 编译gradle,打开app.iml发现顺序果然换过来了

  5. 在Module下的build.gradle下的android->defaultConfig里面添加

    multiDexEnabled = true

    注意gradle版本

删除jar包的某些class

jar重命名为zip,即xxx.jar->xxx.zip
解压
删除需要删除的文件
重新打包jar(需安装java环境):
进入文件夹,

jar cvf xxx.jar .

问题

对findViewById的引用不明确

错误: 对findViewById的引用不明确
Activity 中的方法 findViewById(int) 和 AppCompatActivity 中的方法 findViewById(int) 都匹配,其中, T是类型变量

常见主流解决:
1.网上最常见的办法是统一各个module的compileSdkVersion,向高版本看齐
2.Android Studio->File-Invalidate Caches / Restart
3.升级AS和Gradle版本

AS工程的build.gradle设置了framework.jar包优先编译,去掉设置优先顺序
我的工程引入了framework.jar,习惯性按照以前的方式设置了优先顺序。神坑,最近因为调试需要,将Activity改为继承自androidx.appcompat.app.AppCompatActivity结果意外暴露出问题,之前一直继承自android.app.Activity。

	//以下代码的作用: 让framework.jar优先参与编译
	//副作用: 在使用AppCompatActivity的时候findViewById无法正常使用
	//错误: 对findViewById的引用不明确,Activity 中的方法 findViewById(int) 和 AppCompatActivity 中的方法 <T>findViewById(int) 都匹配
	//其中, T是类型变量:
	//屏蔽之后运行正常
	//如果必须设置gradle.projectsEvaluated,那么在实例化View的时候,把findViewById改为getDelegate().findViewById,这样就可以避免歧义
//    gradle.projectsEvaluated {
//        tasks.withType(JavaCompile) {
//            options.compilerArgs.add('-Xbootclasspath/p:readme/framework.jar')
//        }
//    }

参考

https://www.jianshu.com/p/54ff6389ddef
https://blog.csdn.net/u010725171/article/details/106357735/