第一章:常用技巧 1.1 常用adb命令 查看当前Activity
1 2 3 4 5 6 8.1之前 window 通过adb shell dumpsys activity | findstr “mFocus” Linux 通过adb shell dumpsys activity | grep “mFocus” 8.1之后 window 通过adb shell dumpsys activity | findstr “mResume” Linux 通过adb shell dumpsys activity | grep “mResume”
连接模拟器
1 2 3 4 5 adb connect 127.0.0.1:21503 //逍遥浏览器 //网易木木浏览器 adb connect 127.0.0.1:7555 (Windows上) adb connect 127.0.0.1:5555 (Mac上)
指定设备安装apk
1 adb -s 设备id install xxx.apk
第二章 基础知识
在本章节,主要包括如下内容
2.1 shape 基础属性
属性
说明
shape
定义形状:如 rectangle,ring,oval
corners
定义圆角
solid
定义内部填充色
stroke
定义边框
gradient
渐变色
常用shape
1 2 3 4 5 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="8dp"/> <solid android:color="#F2F2F2"/> </shape>
2.2 layer-list图层
layer-list和shape不同的是,layer-list可以放多个item,每个item下可以放shape等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="rectangle"> <corners android:radius="8dp"/> <solid android:color="#FF4C00"/> </shape> </item> <item android:left="2dp" android:right="2dp" android:top="2dp" android:bottom="2dp"> <shape android:shape="rectangle"> <corners android:radius="6dp"/> <stroke android:color="@color/color_white" android:width="1dp"/> </shape> </item> </layer-list>
2.3 Android studio 2.3.1 阿里云仓库 替换jcenter(),修改成
1 jcenter(){ url 'https://maven.aliyun.com/repository/jcenter'}
2.3.2 编译速度优化 gradle离线模式
初次打开的时候不让它连接谷歌进行更新
1 2 找到studio安装目录,找到idea.properties文件,打开,加上下面一行配置,作用是在初次打开的时候不让它连接谷歌进行更新 disable.android.first.run=true
更改studio的VM大小
1 2 -Xms 是JVM启动的起始堆内存,堆内存是分配给对象的内存 -Xmx 是 Java 虚拟机启动时的参数,用于限制最大堆内存
2.4版本更新记录 迁移AndroidX 记录一下迁移后遇到的一些问题
问题一:构建release包失败,错误提示如下,
1 R8: Unknown option "-ignorewarning"
解决方法: pogard文件中,将-ignorewarning 修改为-ignorewarnings
同时添加AndroidX相关混淆
1 2 3 4 5 6 7 8 #/*------------------androidX混淆------------------------*/ -keep class com.google.android.material.** {*;} -keep class androidx.** {*;} -keep public class * extends androidx.** -keep interface androidx.** {*;} -dontwarn com.google.android.material.** -dontnote com.google.android.material.** -dontwarn androidx.**
参考博客:
https://www.jianshu.com/p/81805f026d93
https://foreachi.com/android/androidx-proguard/
第三章 Android实战开发 2.1RecyclerView相关 RecyclerView嵌套滑动卡顿
1 2 3 4 粗暴解决方式: rv.setItemViewCacheSize(200); //继续粗暴 rv.setHasFixedSize(true); rv.setNestedScrollingEnabled(false);
RecyclerView 网格布局,分割线
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration { private int spanCount; private int spacing; private boolean includeEdge; public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) { this.spanCount = spanCount; this.spacing = spacing; this.includeEdge = includeEdge; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { int position = parent.getChildAdapterPosition(view); int column = position % spanCount; if (includeEdge) { outRect.left = spacing - column * spacing / spanCount; outRect.right = (column + 1) * spacing / spanCount; if (position < spanCount) { outRect.top = spacing; } outRect.bottom = spacing; } else { outRect.left = column * spacing / spanCount; outRect.right = spacing - (column + 1) * spacing / spanCount; if (position < spanCount) { outRect.top = spacing; } outRect.bottom = spacing; } } }
2.2 自定义view 自定义长宽比ViewGroup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //长宽比1.4 class RatioLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)) val childWidthSize = measuredWidth val mWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY) val mHeightMeasureSpec = MeasureSpec.makeMeasureSpec((childWidthSize * 1.4).toInt(), MeasureSpec.EXACTLY) super.onMeasure(mWidthMeasureSpec, mHeightMeasureSpec); } }
2.3 AAR 打包AAR
当我们代码写好后,如何打包AAR呢?找到右侧gradle,找到library-> Tasks -> build -> assemble
AAR包生成目录:library->build->outputs->aar下
AAR引用第三方库
如果在aar中引用了第三方库,那么需要在APP中手动引入aar,因为aar中并不能依赖传递
AAR发布
AAR可以发布到Jcenter或者国内仓库,如阿里云maven(云效)
2.4 XML转JSON 1 2 https://github.com/smart-fun/XmlToJson implementation 'com.github.smart-fun:XmlToJson:1.4.5'
注意:如果xml中要解析list数据,必须设置强制解析成list,因为当list只有一条数据的时候,框架根本不知道xml里面,是解析成对象,还是list,所以必须手动指定
参考:https://github.com/smart-fun/XmlToJson#force-a-tag-to-be-a-list
第四章 APP常用开发功能 4.1版本适配 7.0 fileProvider适配 主要分为以下几步:
1.创建file_paths文件,配置共享目录,注意命名不要和其他三方的冲突
2.在aplication节点下添加Provider,指定file_paths
3.根据版本获取不同的URI
实战:打开文件
首先配置file_paths
1 2 3 4 5 6 7 <?xml version="1.0" encoding="utf-8"?> <resources> <paths> <!--ppt存放路径--> <external-files-path name="resource" path="ppt/" /> </paths> </resources>
这里的external-files-path,对应getExternalFilesDir()
name是取一个别名,只要唯一字符串即可,path是真实目录,可以看出,这里使用resource隐藏了真实目录ppt
1 content://com.yijieyuanyoutongllyfeng1.app.fileProvider/resource/xxx.ppt
然后配置provider
1 2 3 4 5 6 7 8 9 10 11 <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileProvider" android:exported="false" android:grantUriPermissions="true" tools:replace="name,authorities,exported,grantUriPermissions"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_provider" tools:replace="name,resource"/> </provider>
根据版本获取不同的URI
1 2 3 4 5 6 7 8 fun getUriFromFile(ctx: Context,file:File):Uri{ return if (Build.VERSION.SDK_INT >= 24){ //provider authorities FileProvider.getUriForFile(ctx, ctx.packageName + ".fileProvider", file) }else{ Uri.fromFile(file) } }
使用URI打开文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun openFile(ctx:Context,file:File){ val intent = Intent(ACTION_GET_CONTENT) val uri = getUriFromFile(ctx,file) Log.d("uri:",uri.toString()) intent.setDataAndType(uri,"file/*") intent.action = Intent.ACTION_VIEW intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) intent.addCategory(Intent.CATEGORY_DEFAULT) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) try { ctx.startActivity(intent) }catch (e:Exception){ e.printStackTrace() } }
4.2 友盟统计 添加仓库和依赖
1 2 3 maven { url 'https://dl.bintray.com/umsdk/release' }//友盟 api "com.umeng.umsdk:common:9.3.0" //(必选) api "com.umeng.umsdk:asms:1.1.3" // asms包依赖(必选)
初始化
1 2 3 4 5 6 7 private fun initUmeng() { val chanel = WalleChannelReader.getChannel(this) UMConfigure.init(this,Constant.UMENG_KEY,chanel?:"测试",UMConfigure.DEVICE_TYPE_PHONE,null) MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO) //友盟日志 UMConfigure.setLogEnabled(Constant.UMENG_LOG) }
注意:这里渠道使用的美团walle渠道包技术,关于walle,在下一节walle渠道包讲解
4.3 多渠道打包 使用美团walle + python 实现多渠道打包
美团walle
第一步:添加插件依赖
1 2 3 4 5 buildscript { dependencies { classpath 'com.meituan.android.walle:plugin:1.1.7' } }
第二步:在build.gradle中应用插件,添加读取渠道号的依赖
1 2 3 4 5 apply plugin: 'walle' dependencies { compile 'com.meituan.android.walle:library:1.1.7' }
第三步:配置walle
1 2 3 4 5 6 7 8 walle { // 指定渠道包的输出路径 apkOutputFolder = new File("${project.buildDir}/outputs/channels"); // 定制渠道包的APK的文件名称 apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk'; // 渠道配置文件 channelFile = new File("${project.getProjectDir()}/channel") }
感觉这个可要可不要,因为我们主要是打未加固的包,然后使用360加固,然后使用python打渠道包
美团walle+python多渠道打包
4.4 多module集中管理
1.在项目的根目录下新建extraModule文件夹
2.把所需要依赖的module都放在该目录下
3.在setting.gradle中将原有的所有的moduleName改为:extraModule:moduleName,点击同步,即可
第五章 开源项目 4.1 日历 Android-CalendarView-master :实现方式 GridView