引文:
最近在做sdk的事情。就是,我们这边提供一个库,给游戏提供登陆、用户中心的一些基础功能。那么问题来了,做出来的东西怎么提供给其他人用呢?
build的话,还是和普通的build的方法没区别,就是
./gradlew assembleRelease
会在output目录下生成aar
文件(想知道详细操作的话,拉倒最下面看,有详细步骤)
AndroidStudio用户怎么用呢?
首先需要将 aar 文件放入主项目的 libs 目录下
然后修改
app/build.gradle
repositories
flatDir {
dirs 'libs'
}
}
dependencies {
implementation (name: 'xxx', ext: 'aar')
}
Eclipse用户怎么用呢?
还是aar的包,里面的信息是全的。
step 1,把aar的包揭开来
参考:https://github.com/kennytm/aar-to-eclipse/blob/master/aar-to-eclipse.py
#!/usr/bin/env python3
#
# Copyright 2015 HiHex Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
import argparse
import pathlib
import zipfile
import subprocess
import shutil
import sys
import uuid
import xml.etree.ElementTree as xml
BUILD_XML = '''\
<?xml version="1.0" encoding="UTF-8"?>
<project name="." default="help">
<property file="local.properties"/>
<property file="ant.properties"/>
<property environment="env"/>
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME"/>
</condition>
<loadproperties srcFile="project.properties"/>
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update lib-project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<import file="custom_rules.xml" optional="true"/>
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml"/>
</project>
'''
PROJECT_PROPERTIES_TEMPLATE = '''\
proguard.config=${{sdk.dir}}/tools/proguard/proguard-android.txt:proguard.txt
android.library=true
target=android-{}
'''
def create_arg_parser():
parser = argparse.ArgumentParser(description='''
Convert *.aar to Eclipse library project
''')
parser.add_argument('-o', '--output', help='''
the directory to contain the Eclipse library project; by default it
will write to a directory having the same name as the *.aar file
''')
parser.add_argument('-f', '--force', action='store_true', help='''
force rewriting the output directory even if it already exists
''')
parser.add_argument('aar', help='''
the input *.aar file
''')
return parser
def merge_libs(output_dir):
'''Move all libraries back into the libs/ directory.'''
libs_dir = output_dir / 'libs'
try:
libs_dir.mkdir()
except FileExistsError:
pass
try:
jni_dir = output_dir / 'jni'
for child in jni_dir.iterdir():
target_path = libs_dir / child.relative_to(jni_dir)
child.rename(target_path)
jni_dir.rmdir()
except FileNotFoundError:
pass
target_path = libs_dir / 'classes.jar'
source_path = output_dir / 'classes.jar'
while True:
if target_path.exists():
target_path = libs_dir / 'classes.{}.jar'.format(uuid.uuid4())
else:
source_path.rename(target_path)
break
def write_eclipse_specific_files(output_dir):
# proguard.txt (required even if we don't run proguard)
(output_dir / 'proguard.txt').touch()
# project.properties
tree = xml.parse(str(output_dir / 'AndroidManifest.xml'))
target_sdk = tree.find('uses-sdk').get('{http://schemas.android.com/apk/res/android}targetSdkVersion')
with (output_dir / 'project.properties').open('w') as f:
f.write(PROJECT_PROPERTIES_TEMPLATE.format(target_sdk))
# build.xml
with (output_dir / 'build.xml').open('w') as f:
f.write(BUILD_XML)
(output_dir / 'src').touch()
def convert(aar, output_dir):
aar.extractall(str(output_dir))
merge_libs(output_dir)
write_eclipse_specific_files(output_dir)
try:
(output_dir / 'aapt/AndroidManifest.xml').unlink()
except FileNotFoundError:
pass
try:
subprocess.call(['android', 'update', 'lib-project', '-p', str(output_dir)])
except FileNotFoundError:
print('Warning: Cannot create "local.properties".',
'Please perform `android update lib-project` manually.', file=sys.stderr)
def main():
parser = create_arg_parser()
ns = parser.parse_args()
if ns.output is not None:
output_dir = pathlib.Path(ns.output)
else:
output_dir = pathlib.Path(ns.aar).with_suffix('')
try:
output_dir.mkdir()
except FileExistsError:
try:
output_dir.rmdir()
except OSError:
if ns.force:
shutil.rmtree(str(output_dir))
else:
print('Output folder "{}" already exists.'.format(output_dir),
'Please remove it or choose another name.', file=sys.stderr)
return 1
with zipfile.ZipFile(ns.aar) as aar:
convert(aar, output_dir)
print('Done.', file=sys.stderr)
return 0
if __name__ == '__main__':
sys.exit(main())
python -out BlogLibrary XXX.aar
step 2,在eclipse中引入
1,import -> other -> Android Existing Code -> copy to workspace -> 看到根目录多了一个项目的文件夹
2,主项目->property->Android->AddLibrary
3,在项目中愉快的使用
小结
做sdk的话,需要提供
1,library(AS、eclipse各一个)
2,demo(AS、eclipse各一个)
3,HTML接入文档
本文简单的介绍了下如何输出成library给其他人使用。最后问个问题,你知道aar是什么吗?
参考: https://developer.android.com/studio/projects/android-library
Android 库在结构上与 Android 应用模块相同。它可以提供构建应用所需的一切内容,包括源代码、资源文件和 Android 清单。不过,Android 库将编译到您可以用作 Android 应用模块依赖项的 Android 归档 (AAR) 文件,而不是在设备上运行的 APK。与 JAR 文件不同,AAR 文件可以包含 Android 资源和一个清单文件,这样,除了 Java 类与方法外,您还可以捆绑布局和可绘制对象等共享资源。
库模块在以下情况下非常有用:
构建使用某些相同组件(例如 Activity、服务或 UI 布局)的多个应用。
构建存在多个 APK 变体(例如免费版本和付费版本)的应用并且需要在两种版本中使用相同的核心组件。
在任何一种情况下,只需要将您希望重用的文件移动到库模块中,然后以依赖项的形式为每个应用模块添加库。本页面将说明如何执行这两个操作。
AAR 文件详解
AAR 文件的文件扩展名为 .aar,Maven 工件类型也应当是 aar。文件本身是一个包含以下强制性条目的 zip 文件:
/AndroidManifest.xml
/classes.jar
/res/
/R.txt
此外,AAR 文件可能包含以下可选条目中的一个或多个:
/assets/
/libs/名称.jar
/jni/abi 名称/名称.so(其中 abi 名称 是 Android 支持的 ABI 之一)
/proguard.txt
/lint.jar
尾声
看到项目中的eclipse部分出乎意料的冗长,还有个依靠idea才能继续下去的步骤。我严重怀疑方案是不是弄错了。后来问了下同事,同事说是为了把R.java打进classes.jar中,因为用的人是直接复制的,没有用library的方式引入。
那岂不是我们这边修改了一个Activity的名称,对方也要跟着修改他们的AndroidManifest.xml
吗?感觉对方是吃力不讨好。不理解。
从网上下了一个联想的sdk,好像也是复制资源来接入的。: (
把同事方案中依赖ide的步骤写成python脚本吧
玩~