Android 工程模块化设计注意事项

in 在路上 | No Comments »

在最新的一个项目里,因为遇到了多客户端的需求,是一个类似滴滴的项目,需要分货主端和车主端,互相有些差异也有一些共用的地方。那么怎么做是最便于维护与拓展的呢,我当时想了这样几个方案:
– 单 Project 单 Module,通过 gradle 进行差异化打包,而日常开发中对于能复用的页面添加 type 参数来区别。优点是简单方便。缺点是维护起来比较混乱。
– 单 Project 分主 Module 与次 Module,比如以车主端为主 Module,主要代码与资源都在该 Module 里面,而货主端引用该 Module,并进行定制化开发。优点是同样比较简单方便,也较为清晰。缺点是货主端会引入很多用不上的资源。
– 单 Project 基础 Module 两个客户端 Module,把基础控件和能共用的部分都封装到基础 Module 里,两个客户端 Module 各自引用它们。优点是清晰易维护。缺点是使用多 Module 本身存在的一些问题。
– 俩 Project,写完一个客户端后复制粘贴代码。优点是成本低难度最小,缺点是改起来恶心。

就观感而言应该是单 Project,分基础 Module 和 客户端 Module 最佳。但是多个 Module 协同开发之间还是存在一些问题的,因此写下此篇文章。由于文章还没竣工,不敢妄称指南,先取名为注意事项。

跨 Module 引用 kotlin 的代码异常,提示「Unresolved reference: xxx」

问题详情:在基础 Module 里写入的一些 Kotlin 方法,在客户端 Module 引用时编译不能通过,提示「Unresolved reference: xxx」,基础 Module 设置的 Application 在运行时会提示「Unable to instantiate application xxx.BaseApplication: java.lang.ClassNotFoundException」。
问题排查:创建了 Java 文件发现一切正常,因此判断是 kotlin 的问题。猜测是因为 kotlin 的作用域与 Java 不一样,但是设置了对应作用域修饰符后依旧无用。搜索结果里有很多干扰内容,最后 ‘Unresolved reference’ errors for android library module referenced in app module 解决了问题,因为作为 Library 的基础 Module 没有正确配置 kotlin。检查是否有以下内容:

apply plugin: 'kotlin-android'

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion:<version>"
}

我是遗漏了apply plugin: 'kotlin-android',但是假如客户端 Module 不调用对应方法的话是能正常运行的,而且也是通过 AS 的 new module创建的,所以这一块应该是属于 AS 的 bug 吧。
很多这样类似的问题有人喜欢称之为坑与踩坑,我不太喜欢这种说法,我觉得主要还是因为我蠢。

//后续内容待更新

惠普暗夜精灵4拆机/加装内存/拆后盖指南

in 在路上 | No Comments »

加装内存不是什么难事,也不是第一次了,但是刚换的这台暗影精灵4的后盖真TM难拆。用手机各种百度也没几个靠谱的,在友人的帮助下看了官方的拆机文档然后发现也没什么用,所以还是写下这篇文章供世人参考。

不过我写文章有个劣习就是不喜欢发图片,虽然我也知道这种拆机文章图多视频多才好理解。。。

官方文档:http://h10032.www1.hp.com/ctg/Manual/c06034959,拆机部分在35页。

拆后盖

第一步:卸掉8颗螺丝。
我很轻松地卸掉了7颗,但是有一颗拧得很紧(贴吧也有一个人和我一样的情况,不知道是不是普遍问题),我和同事都尝试失败后我便去电脑店找人用专业点的螺丝刀拧开了。注意电脑的螺丝拧不开请不要强行拧,不然把螺丝拧花了问题就比较麻烦了。通常拧不开只是螺丝刀质量不行。

第二步:打开卡扣。
不得不说现在的笔记本外壳真是进步了,缝隙极窄压根找不到下手的地方。建议有条件的去淘宝买些翘片,这样应该不会像我这么难受了。
官方文档标注的是有3处卡扣,弄开后摇动一下即可打开后盖,都是骗人的。

暗影精灵4后盖的风扇靠后部分的缝隙大一些,找你觉得合适的工具把这两部分撬开卡扣,然后一路划过来,那么前面两侧以及背面的两端都松开了。然后此时我本以为差不多了,官方文档与网上的大部分资料都说用力掰开或者往前面拉,甚至我还在思考这个后盖是不是凹形状的,因为背面接口的那部分实在是紧。但是事实就是那部分很紧,有翘片的人可能比较幸福,我是死活才把信用卡塞进去了一部分然后很用力才拆开了这部分。然后风扇到接口处应该也有两个卡扣,这也是最后的两个卡扣了,弄开来就可以很轻松地掀开后盖了。

加装内存条

内存的位置是被一个黑色的防尘塑料遮住了,你需要把塑料撕开来才能弄,按贴吧人的说法是不会失去保修的。然后装内存条也很简单,我们把有磁针的一段称为前面,步骤是先前面与机箱的插口对接好,然后再把后面按下去。而不是像以前我们玩小霸王那样的把内存条与另一根内存条以平行的方式插进去。(这样理论上也行但是毕竟麻烦)

其他好像没啥可以说的了。

Android 编译 FFmpeg 产生「error undefined reference to ‘av_register_all()」等错误的多种原因

in 在路上 | No Comments »

本文主要内容:讲述遇到集成 NDK 时遇到的「error: undefined reference to」的解决方案

集成 NDK 有很多方式,比如 ndk-build 后把 so 库直接链接使用,或者通过 CMake 的方式链接,通常推荐后者,因为这样编写调用 native 方法方便,不需要像前者每次需要重新打包。
在实现 FFmpeg 播放视频功能时,我参考 Android Studio FFmpeg视频解码播放 该文章操作后,始终无法成功编译,按照网上的种种解决方案(比如用 C 的方式引入头文件)都无法解决,最后一步一步跟能成功运行的项目对照后终于解决。

具体报错情况为一堆 FFmpeg 相关的方法提示 「error: undefined reference to XXXX」。网上的解决方案基本都为用「extern “C”{}」包裹,原因是 FFmpeg 是一共纯 C 的项目,C++ 想正确调用 C 代码则需使用这样的方式,具体示例如下:

extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
}

该方案能解决一部分人问题,于我却无用,随后我检查了各种引入方式,以及 NDK 的语法后,确定问题其实是出在 CMakelists.txt 文件上。
(更多…)

Windows 交叉编译 Android 版 FFmpeg 心得

in 在路上 | No Comments »

本文主要内容:介绍一些在 win10 系统下打包出 Android 需要的 FFmpeg so 库的注意事项。

最近需要写一个短视频 Android 项目,经与领导讨论后决定不用市面上的短视频 SDK,采用 FFmpeg 实现。如何集成我选定了一篇质量不错叙述详细的教程 Android 集成 FFmpeg (一) 基础知识及简单调用 ,本以为照着来可以很轻松集成好的,没想到居然花了两天时间。现把注意事项分享给大家,供后人查阅。

假如你也有交叉编译 FFmpeg 的需求,推荐你参考上面那篇文章,遇到问题了再看看我这是否有解决方案。教程作者(后面将用该词称呼上面文章的作者)与大部分交叉编译 FFmpeg 教程的作者使用的都是 Mac,能省很多事,这让我煞是羡慕。然而我并没 Linux 环境,因此我使用了 win10 的 Linux 子系统,选择了 Ubuntu。大致步骤为「设置里开启开发者选项」→「程序和功能里启用 适用于 Linux 的 Windows 子系统」→「应用市场里安装 Ubuntu」,这个步骤很简单,网上有很多指导,我就不详细描述了。然后在命令行输入「bash」即可进入 Ubuntu,在这里 C 盘映射到了「mnt/c」目录下(其他盘类推),因此我将所有相关资料都放到了 D 盘的「Share」文件夹下,方便使用。

sh 脚本报错各种 not found

我对 sh 脚本不熟悉,因此此处尝试过其他人的编译脚本才发现问题所在,教程作者的注释影响了脚本的正常运行,你需要将所有「\」后的空格与注释都删掉才可正常运行。
同时,还有一个可能导致这个错误,就是你使用了 Windows 的换行符,假如你用的是 vscode,直接右下角将「CRLF」改成「LF」即可,其他编辑器解决方案可自行搜索。

ERROR: libmp3lame >= 3.98.3 not found

请先确保你下载了教程作者编译好的 libmp3lame,并在 sh 脚本里修改了对应路径。如果你跟我一样不方便下载 CSDN 积分内容的话,我把它传到了我的百度网盘 链接(密码:5jm6)的 lame 文件夹。
同时,你很有可能跟我一样下载且更改路径之后依然存在这个问题,当你搜索该问题时可能很多人会建议你安装 libmp3lame,Ubuntu 的话命令是「apt-get install libmp3lame-dev」,假如找不到请「apt-get update」一下。虽然我对该操作是否有效持怀疑态度(我们需要的是交叉编译出 Android 端的 FFmpeg,而不是在你的 Ubuntu 上使用 FFmpeg),但是似乎是因此解决了该问题。

make -j4 的时候各种提示 「fatal error: stdlib.h: No such file or directory」等头文件缺失

这是个很蛋疼的问题,在此时(2018年6月),我使用的都是最新版(ndk 17,FFmpeg 4.0),居然会有兼容问题而且似乎还是由来已久的,相关介绍:Unified Headers,我尝试使用它说的「-D__ANDROID_API__=$API」并没有成功(很可能是我姿势不对),最后把 NDK 版本换成了 15 解决(注意你应该下载 Linux 版的 NDK)。

如果你成功解决这些问题,你应该成功生成了动态库,如果你遇到了暂时没法解决的问题想绕过,那么同样可以直接下载我编译好的版本:百度网盘 链接(密码:5jm6)的 arm 文件夹。剩下的内容就不需要 Linux 相关了,只需要你使用 ndk 即可。(注意此时你应该使用 Windows 的 ndk)

ndk-build 时报错 「make: *** No rule to make target jni_FFmpegJni.c', needed byobj/local/armeabi-v7a/objs/ffmpeg/com_jni_FFmpegJni.o’. Stop.」

不用怀疑了,不是网上说的那些什么缓存问题,就是你的 Android.mk 写错了,仔细检查。注意教程作者贴的 Android.mk 里的 「libpostproc」我们是没有的,以及对应的版本也都更新了,其实你可以在 Android.mk 里写「libavcodec-*.so」来忽略版本问题,或者链接到目录底下的快捷方式。

然后是一个比较严重的问题,按照教程作者的第二篇文章修改 ffmpeg.c 等相关内容后,ndk-build 始终无法成功。此处我尝试过很多方法都没有解决,最后采用了其他人的实现方式,而且我觉得 CMake 的方案其实优于教程作者介绍的这种,该部分可以参考在Mac下编译 FFmpeg ,并在Android中使用

以及后续 FFmpeg 相关学习推荐参考雷神的FFMPEG视音频编解码零基础学习方法

真正的 Android 冷启动长时间白屏原因与解决方案

in 垃圾文章 | No Comments »

注:本文属于 垃圾文章补完计划

近期在 Android 开发过程中发现 App 每次启动时白屏事件特别长(大概 3s),检查了首屏 Activity 与 Application 都没发现问题,并且新建了一个空的项目问题依旧,遂谷歌之,发现一大把的文章都是介绍如何把主题的白色背景色改为透明来达到显得没有白屏。

实际产生原因是新版 Android Studio 自带的 Instant Run 功能。大概解释就是 Instant Run 为了能快速运行做了一系列操作,这部分时间就体现到了启动白屏的时间上了。

那么是否我们应该关闭 Instant Run 呢?我并不推荐,诚然在 Android Studio2.0 时代这个功能一堆 bug,连页面都没法正常渲染好,那时候毫无疑问关闭了这个功能,不过现在 Instant Run 已经改进了很多了,甚至在 Android Studio3.0 发布的时候还呼吁大家重新试试,现在的体验确实不错,缩短了很多编译时间。

那么怎么解决这个白屏时间过长的问题呢?把 apk 打包成 release 版即可。

详细介绍可以阅读郭霖大神的Android 冷启动白屏解析,带你一步步分析和解决问题。我之所以又写一篇与郭霖大神内容几乎相同的短文,是希望将来其他人遇到该问题时能得到正确的原因,而不是那漫山遍野的修改 style 方案。

© 2019 一隅 - Powered by Wordpress / Theme: Tabinikki