Android Studio 打包Jar

本文介绍了如何在Android Studio中将项目模块打包成SDK供第三方使用。对比了几种打包方式后,选择了打包成Jar的方式,并详细说明了操作步骤。此外,还提供了处理资源文件和布局文件的解决方案。

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

晨鸣的博客–Android Studio 打包Jar

最近公司一个新需求,需要将项目中某一个模块打包成SDK提供给第三方公司使用。

打包SDK?我只会用啊!!没办法,硬着头皮也得上!

选择打包方式

说干就干,撸起袖子就Google。。。

通过Google可以确定常见的几种打包SDK的方式

直接以Library Module的方式引入

  • 优点

    简单方便,直接把模块抠出来放进一个Library中扔给第三方公司用就行了

  • 缺点

    只能适合于Android Studio开发的项目,假如第三方公司用的是Eclipse,那不就懵逼了.
    不安全,相当于把源码完全暴露给第三方。泄露资料事小,代码写的差被嘲笑事大啊!!

以aar包的方式引入

  • 优点

    生成简单,Android Studio的项目在编译完成后,Library Module 的build目录中会自动生成 aar包,不用做额外操作

  • 缺点

    还是比较适合Android Studio开发的项目,虽然Eclipse 也能引入aar包,但是比较复杂,我可不想写一堆接入文档,还不一定说的清。

以jar包的方式引入

  • 优点

    接入方便,是个Android开发应该都会引入jar包吧。。

  • 缺点

    打包比较麻烦,而且Jar包中关于一些资源文件的引用比较麻烦



经过一番比较,最终我选择以Jar包的形式提供一个对外的SDK。毕竟是给别人使用的东西,用户的使用体验最重要,通过jar包方式可以以最简单的方式集成SDK,减少接入SDK的成本以及时间。

打包Jar

相关知识

Android Studio 生成Jar包,还是需要借助 Library Module来操作。创建一个Library Module ,然后在主项目中依赖这个Module,当项目经过编译后,我们会发现在Library Module 的 build/intermediates/bundles/default/目录下会有一个class.jar文件

我们生成Jar文件就是需要将这个class.jar文件进行打包处理

操作

  • 将项目中需要生成SDK的模块分离出来,单独放入一个Module中,并将这个Module切换为Library,使主项目依赖这个Library。
  • 在Library Module 的build.gradle 文件的最后添加如下代码
//打jar包
def SDK_BASENAME = "*****";  //打包后的名称
def sdkJarPath = "build";  //打包输出目录
def zipFile = file('build/intermediates/bundles/default/classes.jar') //将编译生成的classes.jar文件打包

task makeJar(type: Jar) {
    from zipTree(zipFile)
    from fileTree(dir: 'src/main', includes: ['assets/**']) //需要保留的资源文件
    baseName = SDK_BASENAME
    destinationDir = file(sdkJarPath)
}
makeJar.dependsOn(build)
  • rebuild 项目,确保build/intermediates/bundles/default/目录下存在class.jar文件。
  • 打开Terminal命令行,或者直接用系统命令行进入项目目录,输入gradlew makeJar 回车,开始进行打包。第一次进行打包,可能会需要下载一些文件,需要一些时间,请耐心等待。
  • 当出现BUILD SUCCESSFUL时代表打包完成,打开输出目录就会有打包生成的jar包。

一些问题及注意事项

  1. 如果Jar包中包含Activity,在项目中引入这个Jar后,还需要在项目的AndroidManifest.xml中声明这个Activity,以及添加一些必要的权限声明。

  2. 打包时可以选择保留项目中的资源文件,但仅仅只有assets下的资源文件在jar包中可以正常使用。其他的资源文件,如drawable、layout等,都不可以用常见的方法引用。我们在正常使用某一个资源文件时,是通过R.**.**方法引用,而打包Jar时并不会保留资源文件id对应的映射R文件,所以这些资源文件就不能正常调用了。

  3. 如果Jar包中需要使用一些资源文件,可以将需要的资源文件,例如图片、布局等单独拿出来,项目中引入Jar时,同时添加这些必需的资源文件(类似友盟、腾讯等第三方jar的引入),这样Jar包中可以通过反射读取项目中资源文件。反射读取资源文件的代码如下:

/**
 * ****************************************************************
 * Author: LCM
 * Date: 2017/6/2 上午11:09
 * Desc: 通过反射获取资源文件
 * *****************************************************************
 */

public class MResource {
    /**
     * 
     * @param context 上下文
     * @param className 资源文件的类型 layout、id、drawable
     * @param name 资源文件的名字
     * @return
     */
    public static int getIdByName(Context context, String className, String name) {
        String packageName = context.getPackageName();
        Class r = null;
        int id = 0;
        try {
            r = Class.forName(packageName + ".R");
            Class[] classes = r.getClasses();
            Class desireClass = null;
            for (int i = 0; i < classes.length; ++i) {
                if (classes[i].getName().split("\\$")[1].equals(className)) {
                    desireClass = classes[i];
                    break;
                }
            }
            if (desireClass != null)
                id = desireClass.getField(name).getInt(desireClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return id;
    }

     /**
     * 从Assets中读取图片
     */
    public static Bitmap getImageFromAssetsFile(Context context, String fileName) {
        Bitmap image = null;
        AssetManager am = context.getResources().getAssets();
        try {
            InputStream is = am.open(fileName);
            image = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return image;

    }
}
//代码中调用
setContentView(MResource.getIdByName(getApplicationContext(), "layout", "layout_demo"));

tvTitle = (TextView) findViewById(MResource.getIdByName(getApplicationContext(), "id", "demo_tv_title"));

额外发现

生成一个Jar,还需要另外提供一些资源文件给别人,对我这种有代码洁癖的人来说是不能忍的。我的理想状态是,就一个jar包,你想用的都在里面,干净简洁。

本着不作死就不会死的精神,竟然真的被我发现了一种从assets中加载布局文件的方式!!!!!!

我们知道生成布局文件一般有两种方式

  • findViewById
  • 直接new一个布局文件,代码中添加属性

其实还有一种容易被我们忽略的方法 LayoutInflater,我们常在ListView或者RecyclerView 的Adapter中通过Layoutinflater加载Item项的布局,那么能不能通过它来加载一个Activity的布局呢?

我们通常使用的是这两个
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root)
方法来加载布局

但其实LayoutInflater还有两个重载的方法
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)
public View inflate(XmlPullParser parser, @Nullable ViewGroup root)

看见XmlPullParser是不是感觉到希望了呢?

没错!XmlPullParser可以用来解析Xml文件,这样我们就不用通过R文件来映射资源文件,而是直接通过解析Xml文件来加载布局。

解析资源布局文件需要用XmlResourceParser

public static XmlResourceParser getIsFromAssetsFile(Context context, String fileName) {
        AssetManager am = context.getResources().getAssets();

        XmlResourceParser xmlResourceParser = null;
        try {
            xmlResourceParser = am.openXmlResourceParser("assets/" + fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return xmlResourceParser;
    }
LinearLayout layout = (LinearLayout) LayoutInflater.from(this).inflate(MResource.getIsFromAssetsFile(this, "layout_demo.xml"), null,false);
setContentView(layout);

把布局文件扔进assets目录,来来来!接下来就是见证奇迹的时刻!


f**k ………

淡定淡定。。发现问题还是要解决问题嘛。。。
经过一番艰苦卓越的google ,发现这里XmlResourceParser解析的布局必需是编译过后的布局文件。
那么怎么获取编译后的布局文件呢,很简单也很无脑,把你需要的布局文件放到任意一个正常项目的layout目录下,编译项目,在build/output/apk文件夹中会有一个 apk包,解压就可在layout目录下获得编译后的布局文件
重新将编译后的布局文件扔到assets目录中,运行


布局文件能找到,那么布局中的控件呢,肯定不能findViewById了,别担心,android中还有另一个findview的方法 findViewByTag,你可以在布局中给每一个控件添加一个android:tag=""属性,然后你就可以通过findViewByTag方法来找到指定的控件了。

终于我成功的将SDK封装的只剩一个Jar包!!

然鹅!!我最终还是放弃了这种方式!!!因为这种方式打包的jar包在Android Studio中可以正常使用,但是在Eclipse中不能使用!!!解析不了这个布局!!!!网上关于这方面的资料又比较少,我只能猜测这是因为Eclipse 与Android Studio 的加载机制不同导致的。。

### 回答1: 在Android Studio打包jar文件,可以按照以下步骤操作: 1. 在项目的build.gradle文件中添加以下代码: ``` android { ... } // 添加以下代码 task createJar(type: Copy) { from('build/intermediates/bundles/release/') into('release/') include('classes.jar') rename('classes.jar', 'your_jar_name.jar') } // 添加以下代码 artifacts { archives createJar } ``` 2. 点击菜单栏中的Build -> Make Project,等待编译完成。 3. 在项目根目录下会生成一个release文件夹,里面包含了生成的jar文件。 4. 如果想要修改生成的jar文件名字,可以在build.gradle文件中修改rename('classes.jar', 'your_jar_name.jar')中的your_jar_name为自己想要的名字。 希望对你有帮助! ### 回答2: Android Studio 是一款非常流行的 Android 应用程序开发工具,其内置了许多有用的工具和功能,其中包括打包 JAR 文件的功能。下面是打包 JAR 的详细步骤。 步骤 1:创建 Java Library Module 在 Android Studio 中创建一个新项目或打开现有项目并使用以下步骤创建一个 Java Library Module: 1. 选择 File -> New -> New Module。 2. 在弹出窗口中,选择 Java Library,并单击 Next。 3. 输入模块名称,例如 mylibrary,并单击 Finish。 这将创建一个名为 mylibrary 的新 Java Library Module。 步骤 2:编写 Java 代码 在 mylibrary 模块中编写您的 Java 代码。请确保类和方法公开,以便使用该库时可以从您的应用程序中调用。 步骤 3:配置 Gradle 1. 在 Project 面板中,打开 build.gradle(Module: mylibrary)文件。 2. 将以下代码添加到文件的末尾: ``` task createJar(type: Jar) { from('build/classes/main/') archiveName = "mylibrary.jar" } ``` 此代码指定 Gradle 任务,该任务将创建名为 mylibrary.jarJAR 文件,并将其保存在 build/libs 目录下。 3. 在菜单栏中,选择 Build -> Build Module 'mylibrary'以将项目编译为 JAR 文件。 步骤 4:使用您的 JAR 文件 1. 打开您的 Android 应用程序项目。 2. 将生成的 mylibrary.jar 文件复制到您的应用程序项目的 libs 目录中。 3. 在 Project 面板中,右键单击您的应用程序项目,并选择 Open Module Settings。 4. 在左侧面板中,选择您的应用程序模块。 5. 在右侧面板中,选择 Dependencies 标签。 6. 单击加号图标,然后选择 File dependency。 7. 选择您刚刚复制到 libs 目录的 mylibrary.jar 文件,并单击 OK。 8. 现在,您可以使用您的 JAR 文件中定义的任何类和方法来开发您的 Android 应用程序了。 总结 使用 Android Studio 打包 JAR 文件非常简单,只需要创建一个 Java Library Module、编写您的 Java 代码、配置 Gradle 和使用您的 JAR 文件。遵循上面的步骤,您可以轻松地将自己的库添加到 Android 应用程序中。 ### 回答3: Android Studio 是一个基于 IntelliJ IDEA 的 Android 应用程序开发工具,它提供了一系列的工具,用于方便应用程序的开发、测试和部署。Android Studio 可以打包.jar 文件。 打包.jar 是为了把编写的 Java 代码作为一个独立并可重用的代码库发布并运行在不同的平台上。而jar包具有高的可重用性和可扩展性,会出现在很多项目中。下面介绍如何在 Android Studio打包.jar: 第一步,配置 build.gradle。在 app 目录下,打开 build.gradle 文件,配置以下代码: ``` apply plugin: 'com.android.library' android { compileSdkVersion 26 defaultConfig { minSdkVersion 17 targetSdkVersion 26 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) } task deleteOldJar(type: Delete) { delete 'libs/your_project.jar' } task exportJar(type: Exec) { workingDir "${project.buildDir}/intermediates/classes/release/"//.class 文件所在目录 def jarName = "your_project.jar" // Jar 包名称 commandLine 'jar', 'cvf', "../../../../../libs/'$jarName'", "."//manifest 和 class 所在目录,"."意为当前目录 } exportJar.dependsOn(deleteOldJar, build) ``` 其中, apply plugin: 'com.android.library' 这句话意味着当前工程看做一个 library,而不是一个 application。 dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) } 这句话意味着查找 libs 文件夹中的所有.jar 文件,并引用其中的类。 task deleteOldJar(type: Delete) { delete 'libs/your_project.jar' } 这里的任务名叫做 deleteOldJar,它的作用是在执行 exportJar 任务之前,删除之前的 Jar 包,避免重复。 task exportJar(type: Exec) { workingDir "${project.buildDir}/intermediates/classes/release/" def jarName = "your_project.jar" commandLine 'jar', 'cvf', "../../../../../libs/'$jarName'", "." } 这里的任务名叫做 exportJar,它的作用是在将编译后的.class 文件打包Jar 包,具体实现关键在于 commandLine、workingDir 和 jarName。其中: commandLine 表示之后要执行的命令,'jar' 表示要打包Jar 包,'cvf' 表示创建新文件、给文件注释、打成压缩包的格式。 workingDir 表示在执行命令之前,切换到的目录。这里是指切换到编译好的.class 文件所在的目录。 jarName 表示要生成的 Jar 文件名称。 第二步,执行任务。这时,在 Android Studio 中,打开 Terminal(快捷键为 Alt + F12),然后执行以下命令: ``` ./gradlew exportJar ``` 运行完成后,在 app 目录下的 libs 文件夹中,就可以看到生成的.jar 文件。 总结一下,以上就是在 Android Studio打包.jar 的全部步骤,如需更多细节请阅读 Configuring Gradle Builds 文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值