《2017感动中国十大事件》

网贷公司一客户是个孤儿,今年在平台上借了几千块钱买了部iphone X,因为最近手头太紧钱一时还不上来。于是平台找到了他的父母将欠平台的几千块追了回来,而客户也找到了自己的父母,这是个感人的故事~~

好啦,按照惯例,先来看下效果图:

效果图

看到这个效果我的第一反应是用 WindowMananger 去做,但是实现起来发现以下不足:

  • WindowManager 会对底部内容进行遮挡;
  • 部分手机不支持小空间的显示;

其实最普通的做法当然是在每个 activity 底部放一个这样的布局,但是这种做法显得比较低级。于是果断调查了下其他 app 的实现思路,下面是对自己 copy 思路的记录,期间发现一些比较不错的工具,大家可以使用下;

这里有朋友可能会考虑反编译看下别人的代码,但是现在很多应用都进行了加固,源代码几乎无法查看(想知道具体原因欢迎查看我的另一篇文章)因此我们考虑采用其他方式:
思路

虽然通过 adb 命令也可以很快查看Android系统当前运行Activity

’‘’

adb shell dumpsys activity |grep “mFocusedActivity”

‘’‘

命令替代工具:

工具github

效果图:

网易调研

通过 DDMS 我们可以看到页面布局的结构:

工具使用

再通过此方法查看得到验证下自己的想法:每个 Activity 中实现。

到这里,我们只需要在每一页的 ScrollView 或者 ListView上加上收拾的坚挺判断,那么就可以实现上面的效果了~~

首先必须得承认如果通过反编译直接窃取别人的劳动成果是有那么点不道德!所以我们一定一定一定要学好反编译,这样我们就可以尽情地窃取别人的劳动成果,并且防止我们自己的技术不被反编译啦(开个玩笑啦,别当真)~~

好吧,下面单纯从技术的角度一起谈谈我们的android安全攻防大战吧:

如上图,迎面向我们走来的是本文的两大重要环节攻与防,也就是我们所说的反编译和混淆加固啦;反编译(攻)一般分为两种情况:

  • 1.资源反编译,针对喜欢高仿但是不会P图的广大程序员屌丝们;
  • 2.源代码反编译,可以看看别人的代码和实现手段;

混淆加固(防)也分为两种手法:

  • 1.混淆,这种情况比较麻烦,引入第三方还要避免混淆别人的代码,并且混淆后的代码还是可以看得出大致使用的技术和逻辑,所以不推荐使用;
  • 2.加固,360加固全部自动化打包,但是现在应用商店似乎对加固软件进行了限制,比如之前工作上传百度应用市场的时候居然提示我们要用百度加固~~,baidu,坑爹!

赛前准备

工欲善其事,必先利其器。选择一个好的工具可以使我们的工作:

问题一:apktool安装配置,作为mac盲的我展示下零基础怎么配置以及遇到的一些问题吧:

  • 1.右键保存链接为 apktool 所有格式文本wrapper script
  • 2.apktool.jar 下载地址打开可以看到历史版本列表,可以选择最新版本的,此教程使用的版本为:2.2.3 下载成功重命名为apktool.jar.

  • 3.将 apktool.jar 和 apktool 拷贝到 /usr/local/bin(需要 root 权限)

sudo cp apktool apktool.jar /usr/local/bin [此目录是 mac 中管理员可执行命令]

  • 4.修改这两个文件的权限: sudo chmod + x file名

  • 5.现在就可以在终端运行 apktool 命令了

验证安装 apktool 是否安装成功的时候发现错误:
Error: Invalid or corrupt jarfile /usr/local/bin/apktool.jar

Google了一下,检测jar包是否正常的命令:

java -jar jar包名

报出同样的错误,删除原本 /usr/local/bin/ 目录下的文件,重新配置,获得成功:

问题二:dex2jar 需要授权:

切换到 dex2jar 目录下,执行命令:chmod a+x *.sh

注:否则直接执行会提示:

d2j-dex2jar.sh: line 36: ./d2j_invoke.sh: Permission denied

###反编译

为了能够更好地串联整个过程也本着尊重版权的原则,我们写了一个简易的demo:

好的,下面就围绕这个demo进行展开吧~~

出于文件整理的考虑,我们将apk文件和授权完成的dex2jar放入同一目录下:

####源代码反编译

思路:我们知道 android 的源代码是以 .dex 文件的形式存在的,也就是说我们要查看源码,我们需要将.dex -> java 代码;但是目前还没有找到比较好的直接转换工具,所以我们套用原有套路:.dex -> .jar->java源码;

说干就干,执行命令:

sh dex2jar-2.0/d2j-dex2jar.sh app-release.apk

通过dex2jar我们获得以下文件:

右击app-release-dex2jar.jar文件选择用JD-GUI打开查看源码即可,让我们来看看我们的成果吧:

做到这里大家不知道有没有好奇,没毛病啊~~图片什么的都有啦,源代码也有啦,打开 .xml 文件一看,目瞪口呆:

所以咋们都资源反编译也就应运而生啦~~

####资源反编译

正如上面提到的,资源反编译针对的主要是 xml 资源文件,我们使用的工具也就是 apktool ,切换到上图目录下废话不多说来行命令压压惊:

apktool d app-release.apk

xml完美呈现:

这个时候我们可以打开smali文件夹改些文本什么的,重新拿个证书打个包,就是一个添加了我们 tag 的 app 啦~~

切换目录到demo下,执行命令

apktool b app-release

兴冲冲装到自己手机上,结果发现安装不了,原来是没有证书,没有条件就去创造下条件从AS中生成一个自己的证书,然后用该证书给咋们的app打个包就OK啦。

执行命令:

jarsigner -verbose -keystore android.keystore -signedjar app-release-1.apk app-release.apk android.keystore

效果如下:

加固

好啦,我们成功破解所有套路之后,我们来看看如何反套路吧,目前市面上对代码进行混淆或者加固。本文选择运用加固技术对我们的app进行保护。如果需要加固助手的同学可以360官网下载到加固助手,另外它还需要注册账号,个人配置密钥证书和下载渠道,参考帮助手册进行操作即可。

如果你看到这个界面那么咋们就可以开始加固打我们的渠道包啦,暂时我们只添加了腾讯应用宝、百度手机助手和360市场打包成功后我们可以获取每个渠道的app。

下面我们还是用上面的方法对我们的渠道包进行反编译,我们会发现很安全因为整个逻辑根本就看不清楚啦~~

好啦,Android 攻防战到此结束,如果有朋友有更好玩的欢迎微博或者简书私信我偶~~

参考文章:

注意这些目录欧

xmind源文件下载

相信部分做 Android 的朋友经常会对内存、内部存储、外部存储这些概念有点含糊不清,也经常对下面这些操作:

  • 一键清理
  • 清除数据
  • 清除缓存

不太清楚从开发角度上代表的真正的意义。今天工作上遇到了需要一些缓存方面的问题,发现对这些概念理解并不是那么清晰,做下小结段友勿喷~~

从英文上去理解

  • 内存 memory

    类似于电脑的内存条,是设备进行逻辑和算术预算的重要部件;

  • 内部存储 Internal Storage

    如下图所示,手机里需要 root 才能够查看的部分 :/data/data/包名/…一般用来保存应用的一些配置和登录信息。在 apk 卸载之后包名下的文件会跟着清掉;

内部存储

  • 外部存储 External Storage

需要关注的常用的私有目录

  • /Android/data/data/caches :getExternalCacheDir()
  • /Android/data/data/files:getExternalStorageDir()

一般要将缓存的数据放在这两个目录下,在 apk 卸载之后这两个目录中的文件会跟着清掉;

外部存储

这里提供一个文件操作的工具类库 AndroidUtilCode

下面解析下三种操作:

一键清理:清除 memory,杀死进程

清除缓存:清除 app 缓存的页面数据

清除数据:清除内部存储和外部存储中 files 和 caches 下的文件。

同志们,晚上好~~
明天又要开始新的一周的工作啦!
本周双休和飞飞讨论下咋们项目这个版本的功能模块具体工作报告如下:

  • 版本的迭代计划意见上传至tower.im,大家有空可以看下有啥意见可以提提意见。
  • 交互原型飞飞已经完成大致框架,预计在下周三可以完成。在这之前大家有什么比较好的交互的点都可以提给飞飞,具体的建议提交方式因为tower.im不方便支持,所以暂时以github issue 的形式提给飞飞,这个项目希望飞飞可以花时间维护下。

  • 由于我们使用到的数据比较敏感,我对市面上常见的开源协议进行了调研,具体的理解在Listen1专栏中有,这里大家如果疑问欢迎沟通~~

本周任务建议:

  • 交互和UI设计
  • 后端/数据端:接口文档
  • Android前端框架(网路,图片,音频播放器)

推荐一个接口文档书写平台,有什么更好的平台欢迎大家推荐

另:本次开源项目本着大家一起成长的目的开启,体验全栈开发模式。希望大家可以通过博客记录咋们开发过程中的点点滴滴,这里在简书开了一个专栏:Listen1,希望大家可以通过总结和分享的方式获得更多的成长。

最后祝大家平安夜快乐~~

因为受到github上江清清的FastDev4Android项目的启发,正巧又要负责公司新项目的启动,所以准备写个类似的库,争取做到write once,run AnyWhere(哈哈,开玩笑,方便以后快速开发啦~~)

随着Android项目业务量的迅速增长,原本的项目结构已经远远不能满足我们的需求来。因为直线上涨的代码量让我们花在编译项目上的时间由原来的一分钟左右到现在的五分钟甚至更长的时间。虽然谷歌官方提出instant run的解决方案,但是由于种种问题,还是没能很好的解决这个问题。

题外话:这里在网上看到有一种比较好玩的方案,通过编写gradle来计算每个task的执行时间,从而对整个项目的编译时间进行优化。有兴趣的朋友可以试下~~

Gradle插件编写

好吧,回到我们的主题:由于组件化采取的是在开发过程中将每一个业务模块都作为一个application,并伴随着一个壳工程,这样就大大缩减了我们开发时的编译时间;当项目上线的时候,只要将这些application变成第三方Lib,然后让壳工程依赖于这些Libs,进行打包,这样就完美的结局了编译时间上的问题。由于之前已经有大神总结了比较好的实践过程,这里就不赘述啦,直接看大神的文章吧~~

Android组件化开发实践

相信朋友们一定听过插件化这个概念,这里可以通过下面这篇文章稍稍科普下:

Android 组件化和插件化开发

下面来介绍下接下来我们要完成的项目的结构吧:

通过图中我们可以看到,对我们来说比较重要的突破点就是:

  • 路由工程
  • BaseLibrary

其中,路由工程我们可以直接引用下ActivityRouter这个工程;

接下来,就是根据我们的业务需要去完成最重要的baseLibrary啦~~
从图中我们可以看到,我们需要在接下来的日子里面完成:

  • 网络请求的封装

  • 图片加载的封装

  • 加密库的封装

  • UI的封装

…….

不知道这里你是不是和我有着一样的疑问:github上有那么多现成的第三方框架,例如Square全家桶,facebook等(PS:移动端技术更新太过频繁啦,向大家推荐一个站可以看看最近出来哪些比较稳定的技术吧Android 流行框架查速表),为什么还要封装自己的框架呢?

实际上我们的封装也是建立在这些第三方库的基础上的,只是随着业务量的不断扩大,我们可能会切换项目所引用的第三方库,这个时候我们只需要更改自己的封装类就可以啦,是不是很方便。其实我也是借鉴stormzhang的观点的啦,有兴趣深入了解这样做的原因可以看看这篇文章,如何正确使用开源项目?

好啦,接下来就让我们一起开启Android快速开发之旅吧,一起加油吧~~

待会儿,在没开始之前,咋们还是要确立注意点规范,还有就是工具啦,工欲善其事,必先利其器嘛~~

Android中view的绘制和动画效果的制作是常见的两大难点,前段时间正好在优化项目的时候做了一些动画。现在对于它们进行个归纳总结,如果有其他看法的同学欢迎给我留言,或者微博私信我~~

以敝人粗浅的理解,Android中交互是通过手势触摸屏幕中的view而产生的一系列动作,那么在view过程中我们可以理解为在一个数学坐标系上去判断触碰点击的位置和view点关系;动画我们可以理解为让view在坐标系做坐标运算从而产生动画效果。所以,了解坐标系也就成了我们把握view点绘制,动画制作等一系列动作等基础。

下面我们就一起探讨下Android中的哪些坐标系:

在讨论这个问题之前我们需要明确两点:

  1. 一般情况下,我们只关心我们应用开发人员可以操纵的区域,下面让我们一起看看android屏幕的大致划分吧:

    • 状态栏
    • [ActionBar]
    • 应用布局区域

在这样一个前提下,我们应用开发人员可以操纵的区域分为两种情况:

有ActionBar
在这种情况下,程序员可操纵区域的范围则是以ActionBar左下角为原点,水平向右为X轴正方向,垂直向下为Y轴正方向。如下图所示:

无ActionBar,那么我们的标题栏也会包含在应用布局中,一般的做法是会用一个公用的布局来作为标题。程序员可操纵区域的范围则是以ActionBar左下角为原点,水平向右为X轴正方向,垂直向下为Y轴正方向。如下图所示:

具体原因可以通过查看源码得知,这里就不再赘述啦,感兴趣的朋友可以看下两篇博客:

  1. View在屏幕中都是以矩形的形式存在的。

好啦,在这两个前提的基础上,我们一起给坐标分分类吧:

  1. View的坐标系

    • 屏幕坐标

      以可操纵区域的左上角为原点,水平向右为X轴正方向,垂直向下为Y轴正方向。

    • 视图坐标

      以可操纵区域的左上角为原点,水平向右为X轴正方向,垂直向下为Y轴正方向。在这个时候View被视为一个矩形,通过API可以获得View的坐标:

      对应API:

      | View中的方法 | 含义 |
      | ————- |————-|
      | getTop() | 获取View自身顶边到其父布局顶边的距离 |
      | getLeft() | 获取View自身左边到其父布局左边的距离|
      | getRight() | 获取View自身右边到其父布局左边的距离|
      | getBottom() | 获取View自身底边到其父布局顶边的距离|

| View中的方法       | 含义          | 
| ------------- |-------------| 
| getX()     |     在当前父View坐标系中对应的坐标X的值 |
| getY()     |     在当前父View坐标系中对应的坐标Y的值|
从Android3.0以后,引入transitionX和transitionY

- X = transitionX + getLeft()
- Y = transitionY + getTop()

**注:这里的getLeft()和getTop()是不变的,当view在父View中移动是改变的是transitionX和transitionY的值,因此X和Y的值也会跟着改变**
  1. 触摸点的坐标系
  • 绝对坐标

    触摸点在屏幕坐标的坐标值;具体如图所示:

对应API:

| View中的方法   | 含义          | 
| ------------- |:-------------:| 
| getRawX()     |     在屏幕坐标系中对应的坐标X的值 |
| getRawY()     |     在屏幕坐标系中对应的坐标Y的值 |
  • 相对坐标

    以当前View的左上角为坐标原点建立的坐标系,触摸点在此坐标系中对应的坐标值;具体如图所示:

对应API:

| View中的方法       | 含义          | 
| ------------- |:-------------:| 
| getX()     |     在当前View坐标系中对应的坐标X的值 |
| getY()     |     在当前View坐标系中对应的坐标Y的值|