[Framework]系统jar包,sdk的制作及引用

栏目: Android · 发布时间: 7年前

内容简介:因为我是开发ROM的,所以系统的一些改动需要暴露给我们自己的APP。比如:之前在PowerManager里面添加过一个新接口,用来释放所有的wake lock,接口调用如下:现在我们的系统APK需要调用这个方法,但是因为SDK不包含该方法,导致APK编译不通过。所以需要我编译一个包含新接口方法的jar包交给APK编译。(生成jar包的方法见

因为我是开发ROM的,所以系统的一些改动需要暴露给我们自己的APP。比如:

之前在PowerManager里面添加过一个新接口,用来释放所有的wake lock,接口调用如下:

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
pm.releaseAll();

现在我们的系统APK需要调用这个方法,但是因为SDK不包含该方法,导致APK编译不通过。所以需要我编译一个包含新接口方法的jar包交给APK编译。(生成jar包的方法见 该文章

编译Jar包

其实编译系统jar包很简单

make framework

即可得到framework.jar。

这时候把jar包导入到项目里,发现缺找不到jar包里的方法。这是因为,Android N使用了Jack编译。所以编出来的jar包里面没有class文件,取而代之的是一个优化过的dex文件。

如果要得到包含class文件的jar包,只需要将Jack编译关闭即可。

#include $(BUILD_JAVA_LIBRARY)
include $(BUILD_STATIC_JAVA_LIBRARY)
LOCAL_JACK_ENABLED := disabled

这样再次编译出来的jar包就是包含class文件的jar包。

Android Studio导入framework.jar

  1. 拷贝framework.jar包到app/libs目录下

  2. 右键点击framework.jar,选择add as library,作为库添加到项目。此时看到我们的gradle里dependencies多了一行。

    implementation files('libs/framework.jar')
    
  3. 因为我们希望这个包只在编译时起作用,所以需要把implementation改为compileOnly,帮助通过编译,不打包到apk。

    compileOnly files('libs/framework.jar')
    

    也可以通过打开项目的File->Project structure,界面左侧选择 app ,右侧选择 Dependencies 。引用列表里找到libs/classes.jar,右侧scope选择compileOnly即可。

  4. 还在Project structure同样的界面,把

    {include=[*.jar], dir=libs}

    删掉。或者把dependencies中的一行删掉:

    // implementation fileTree(include: ['*.jar'], dir: 'libs')
    

    目的是明确classes.jar所在的libs目录不作为一般的库导入。

  5. 在build.gradle添加如下内容,使其加入编译

    allprojects {
        repositories {
            maven{url 'https://maven.aliyun.com/repository/public'}
            google()
            jcenter()
        }
        // 添加下面代码
        gradle.projectsEvaluated {
            tasks.withType(JavaCompile) {
                options.compilerArgs << '-Xbootclasspath/p:app/libs/framework.jar'
            }
        }
    
    }
    
  6. 在model的build.gradle里面加入自动更改model.iml文件的代码。这个代码的作用是将classes.jar放在索引的第一个,这样编译的时候就会先从我们的jar包查找API,而不是从SDK加载。

    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
            }
        }
    }
    

至此,需要的操作都已经完成。现在在Activity里使用我们的新接口:

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
pm.releaseAll();

此时, releaseAll 虽然显示为红色,但是编译时可以通过的。编译完成放在我们的系统里就可以运行了。

此方法也可以解决@hide方法无法访问的问题,自己做一个去掉@hide注解的jar包调用即可。但是你的App必须有系统签名。

SDK制作

前面的方法,虽然可以让App访问系统自定义的API,但是,有些APP做了很多的外部库引用,我们的jar包因为包含很多系统方法,会导致正常的类引用出现奇怪的错误。这些错误很难解决,所以就讨论了另外一个方案:做一个SDK,在SDK中调用系统的方法,然后让APP调用我的SDK。

下面是Android Studio制作SDK的步骤:

  1. 创建一个新项目

  2. 右键项目new module->Android Library->输入库名 mysdk

  3. 在module内创建一个新的class文件,尝试调用系统内部的方法

    public class MySDK {
    	public static void forceStopPackage(Context context, String packageName) {
            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            am.forceStopPackage(packageName);
        }
    }
    

    我在SDK暴露出来一个系统方法,这样App要杀掉应用就不需要使用反射,直接调用我的SDK就可以。

  4. 把framework.jar放到module的lib目录下,在module内的gradle添加以下代码以编译出module:

    dependencies {
    	compileOnly files('libs/framework.jar')
    	...
    }
    
    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            options.compilerArgs.add('-Xbootclasspath/p:libs/framework.jar')
        }
    }
    
    task makeJar(type: Copy){
        delete 'build/libs/MySdk.jar'
        from('build/intermediates/bundles/default/')
        into('build/libs/')
        include('classes.jar')
        rename('classes.jar','MySdk.jar')
    }
    
    makeJar.dependsOn(build)
    
  5. 在Gradle菜单双击makeJar进行模块编译,会在sdk里的build/outputs/aar出现

    mysdk-debug.aarmysdk-release.aar 两个库文件。

  6. 将aar文件拷贝到App项目的lib目录下,gradle添加

    android {
    	repositories {
            flatDir {
                dirs 'libs'
            }
        }
    }
        
    dependencies {
    	...
        compile(name:'mysdk', ext:'aar')
    }
    

    然后就可以在对应Activity里快乐地使用 MySDK.forceStopPackage() 调用系统方法了。而且这还有个好处,一些系统API调用需要在Manifest添加对应权限,这样调用后就不需要添加权限了。

问题

gradle版本变化报错:

Invoke-customs are only supported starting with android 0 --min-api 26

解决办法:在build.gradle下添加如下代码

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

https://stackoverflow.com/a/50198499/4522227

Ref: https://blog.csdn.net/zhonghe1114/article/details/80923730


以上所述就是小编给大家介绍的《[Framework]系统jar包,sdk的制作及引用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Rapid Web Applications with TurboGears

Rapid Web Applications with TurboGears

Mark Ramm、Kevin Dangoor、Gigi Sayfan / Prentice Hall PTR / 2006-11-07 / USD 44.99

"Dear PHP, It's over between us. You can keep the kitchen sink, but I want my MVC. With TurboGears, I was able to shed the most heinous FileMaker Pro legacy 'solu-tion' imaginable. It has relationshi......一起来看看 《Rapid Web Applications with TurboGears》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具