一 . 背景
公司一直在做一个的项目,需要上架,因为某种原因上不上去.结果出了一个主意想把以前已死的项目作为马甲包,帮助新项目上架.这个任务给我了.我一时间想到的解决方案就是把老项目打包成aar包,放到新项目里.其中遇见了很多的坑,在此做一下记录.
一 .完整项目打包aar 的流程
aar包简单介绍
aar包含所有资源,class,xml布局文件以及res资源文件全部包含。但是他不含有你在项目里引用的三方库.
捎带解释下jar.jar只包含了class文件与清单文件,不包含资源文件,如图片等所有res中的文件。所以如果想打包整个工程到新项目里用aar还是比较方便的.
第一步 修改build.gradle(app)
首先先将项目中的apply plugin: 'com.android.application' 替换成apply plugin: 'com.android.library'.如下
//apply plugin: 'com.android.application'
apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'
android {
packagingOptions {
exclude 'META-INF/maven/com.belerweb/pinyin4j/pom.xml'
exclude 'META-INF/maven/com.belerweb/pinyin4j/pom.properties'
}
dexOptions {
//incremental true
javaMaxHeapSize "4g"
}
signingConfigs {
config {
storeFile file('/home/conf/com.cloudcns.debug.keystore')
}
}
第二步 修改manifests
将application里面的一些里的name,icon,label,theme等删掉 如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.saileikeji.sych">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
<!--android:name=".application.MyApplication"-->
<!--android:allowBackup="true"-->
<!--android:icon="@mipmap/ic_launcher"-->
<!--android:label="@string/app_name"-->
<!--android:roundIcon="@mipmap/ic_launcher_round"-->
<!--android:supportsRtl="true"-->
<!--android:theme="@style/AppTheme"-->
android:allowBackup="true"
android:supportsRtl="true">
然后再将manifests中的 主启动的intent-filter 删掉,如下:
<activity
android:name=".activity.SplashActivity"
android:screenOrientation="portrait"
android:theme="@style/AppWelcome">
<!--<intent-filter>-->
<!--<action android:name="android.intent.action.MAIN"/>-->
<!--<category android:name="android.intent.category.LAUNCHER"/>-->
<!--</intent-filter>-->
</activity>
如果项目中有加meta-data 也可以将meta-data 删掉 在你要引入的项目里重新加上.我这里直接注释掉了如下:
<!--<meta-data-->
<!--android:name="UMENG_APPKEY"-->
<!--android:value="596d9dbcf5ade420c8000e27" />-->
<!--<meta-data-->
<!--android:name="UMENG_MESSAGE_SECRET"-->
<!--android:value="7e05110fc72e6803e8adcf08f199b0d7" />-->
<!--<meta-data-->
<!--android:name="UMENG_CHANNEL"-->
<!--android:value="YingYongBao" />-->
第三步 如果你的项目里使用了butterknife,出现问题不要害怕
这个butterknife当时坑的我很惨,花了很长时间才解决掉.具体步骤如下:
之前测试了很多个butterknife 版本,只发现用8.4.0 好使.话不能说那么肯定.大家也可以用别的试试.首先在
buid.gradle(Project) 中增加
classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'.如下
image.png
其次在buid.gradle(app)中增加
apply plugin: 'com.jakewharton.butterknife'
在下面dependencies 中增加:
compile 'com.jakewharton:butterknife:8.4.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
之后,将项目里的R改成R2 因为R在library中报错.如下:
public class MainActivity extends BaseFragmentActivity implements MainHandler.UICallback, BaseHandler.UiCallback, View.OnClickListener, OtherHandler.PayCallback, OtherHandler.CommentCallback, NavigationView.OnNavigationItemSelectedListener {
@BindView(R2.id.main_pager)
NoSlidingViewPaper mainPager;
@BindView(R2.id.tab1)
LinearLayout tab1;
@BindView(R2.id.tab2)
RelativeLayout tab2;
@BindView(R2.id.tab3)
RelativeLayout tab3;
@BindView(R2.id.tab4)
LinearLayout tab4;
@BindView(R2.id.tv_new_people)
TextView tvNewPeople;
@BindView(R2.id.nav_view)
NavigationView navView;
@BindView(R2.id.drawer_layout)
DrawerLayout drawerLayout;
@BindView(R2.id.iv_1)
ImageView iv1;
@BindView(R2.id.ll_bottom)
LinearLayout llBottom;
@BindView(R2.id.main_back)
RelativeLayout mainBack;
@BindView(R2.id.imageView1)
ImageView imageView1;
@BindView(R2.id.imageView2)
ImageView imageView2;
@BindView(R2.id.load_image)
LinearLayout loadImage;
在就是很重要的
@OnClick({R2.id.textView, R2.id.button1, R2.id.button2, R2.id.button3, R2.id.image})
public void onViewClicked(View view) {
int i = view.getId();
if (i == R.id.textView) {
} else if (i == R.id.button1) {
} else if (i == R.id.button2) {
} else if (i == R.id.button3) {
} else if (i == R.id.tv) {
}
}
library中的 不可以使用switch case,必须要用if else来的代替,否则空指针等其他错误。这里switch case 转 if else 教给大家一个简单的快捷键 Ait+Enter 对准switch 可以转换..我的项目里我是将所有 onViewClicked里的switch case 转成 if else了
上面的OnClick 里必须为R2 不然回报错.再就是下面的R 必须为R 不然你项目里的所有点击事件会不好使.这里非常重要.我在这里困了一天多
第四步 Assert资源获取
内嵌在其他应用中,原本APK中的Assert目录内的资源可能找不到。解决方法是,可以将Assert目录内的资源打包成一个ZIP文件放在 /RAW目录下。在项目初始化的时候,解压到指定目录下。使用的时候在AssertManager中使用绝对路径获取资源在于前端页面交互上,JS相关代码及资源一般也存放在Assert目录下,在webview.load()时,可以通过 file:/ 绝对路径 ,来加载PS:Assert 目录与 /raw 目录的区别:访问方式,目录结构,大小写,压缩方式等。
第五步 Application参数的传递问题
每一个Android App都有一个application context,这个参数需要工程传递给我们,调试的时候可以在壳工程的Manifest.xml中指定默认的Application.并在默认的Application中初始化aar.如下:
public class MyApplication extends MultiDexApplication implements CrashProcessHandler.ICoprocessor {
public static AssetsDatabaseManager mg;
public static boolean isKFSDK;
public static Application app;
public static Handler handler;
@Override
public void onCreate() {
super.onCreate();
handler = new Handler(){
};
app = this;
}
public static Context setInstance(Application appa){
app=appa;
return app;
}
public static Context getInstance() {
return app;
}
MyApplication .setInstance 是在你主工程的Application 里写的
第六步 打成aar
双击右侧的assembleRelease,如下图位置
image.png
成功后会在这里看到.如下:
image.png然后就可以将app-release.aar 导入新工程里了!
到此为止完整项目打包aar算是完成了
二 .将aar 引到工程里
1.把aar文件放在一个文件目录内,比如就放在libs目录内 如下:
image.png想要生成jniLibs 可以添加下面代码在build.gradle(app) android中:
sourceSets{
main{
jniLibs.srcDirs=['libs']
}
}
2.build.gradle(app)里添加如下内容:
repositories {
flatDir {
dirs 'libs'
}
}
这样可以找到路径
3.dependencies 添加引用:
implementation (name: 'app-release',ext: 'aar')
aar 里面引用的三方库 在主项目上引用.比如:
implementation 'ca.barrenechea.header-decor:header-decor:0.2.6'
implementation 'com.timehop.stickyheadersrecyclerview:library:0.4.3@aar'
// implementation 'com.google.zxing:core:3.2.1'
implementation 'com.google.android.gms:play-services-gcm:9.4.0'
implementation 'com.umeng.analytics:analytics:latest.integration'
implementation 'com.jcodecraeer:xrecyclerview:1.3.2'
implementation 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar'
implementation 'com.android.support:cardview-v7:23.4.0'
implementation('com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30') {
exclude group: 'com.android.support'
}
发现重复的可以以这样的方式移除掉:
implementation('com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30') {
exclude group: 'com.android.support'
}
4.主项目的butterknife 需要跟aar 里面使用一样的版本.配置跟上面butterknife 一样.我就不重复写了.
5.manifests 设置
将原aar 项目里的activity ,service 等写在现在的manifests.不写的话会找不到activity/service .写的时候一定要带着包名,如下 :
<service
android:name="包名.service.QianguanService"
android:enabled="true"
android:exported="true" />
<activity
android:name="包名.ui.EaseBaiduMapActivity"
android:screenOrientation="portrait"
android:theme="@style/horizontal_slide" />
meta-data 等也在manifests 写上:
<meta-data
android:name="EASEMOB_APPKEY"
android:value="xxxxxxxx" />
6.Application 上的设置
1.在Application 上将原Application 里的三方sdk 设置参数.写在主项目的Application中.
2.在Application上初始化aar包里的application.如下:
这样在项目里就可以使用aar包里的东西了.
7.主工程调aar 里的activity:
如下:
@OnClick({R.id.btn_login, R.id.btn_tourist_preview})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn_login:
Intent in=new Intent();
in.setClassName(this,"包名.activity.StartActivity");
startActivity(in);
// start(LoginActivity.class);
finish();
break;
case R.id.btn_tourist_preview:
start(MainActivity.class);
finish();
break;
}
}
这样完整的项目打包成aar 引用到新项目里就完成了.
网友评论