关于『PassBox』的开发笔记

自从开发了『PassBox』之后,就有一种不详的预感可能以后要走Android开发的路子了,虽然现在还很菜,但总会一步一个脚印地走下去的。

毕竟是第一个Demo,有必要做些笔记,减少以后重复踩坑的几率。

笔记内容可能比较多,都是我踩过的坑,我也懒得整理,可能会比较乱,将就着看吧…

再提一次测试机型:

01

签名

其实网上也有许多修改签名的工具,可以自己设置签名。

『Android Studio』中「Build」菜单中可以「Generate Signed APK」,进行简单的设置即可,可以直接导入一个已经存在的签名,即JKS文件,也可以新建一个。

新建的时候需要填写的项有点多,虽然有些不是必填项。其中,「Validity」那一栏填写的是keystore文件的有效时长,单位是年,我填了70年。

「Organizational Unit」应该是所属机构或者公司的意思,我是个人开发者,所以填写了「Personal」,后面的那些非必填项我也懒得填了。

02

软件图标

之前提到『PassBox』的图标也是我自己设计的,下载到手机上我看到的图标是这样的:

但是我用『Photoshop』做出来的图是这样子的:

很明显,图标周围的黑边被砍了一圈,导致图标上的元素看上去有点拥挤。

我当时在『Photoshop』上设定的图像大小参照各大应用市场上的软件图标标准,采用256*256像素,上传到『Android Studio』后,它自动为各种设备裁剪图标。

另外,我也没有采用Google官方推荐的浮层图标设计,即主Logo和背景画布分层。

其实,Android O 引入了一种新的应用图标格式:自适应图标。自适应图标可以统一所有应用图标的形状,为用户展现有趣的视觉效果,从而使设备提供更为一致的体验。

自适应图标的大小为 108dp * 108dp,但最大只能遮盖 72dp * 72dp 的面积。不同的设备可以提供不同的遮盖,但必须是凸形的(不能凹进去),图标边缘距离中心不小于 33dp。

考虑到遮罩的最小面积,可以画一个66dp直径的圆来作为安全区域的参考,以保证图标不被剪裁。

自适应图标实际上由两层内容堆叠而成:前景和背景。两层图形的大小均为 108dp * 108dp; 背景必须完全不透明,而前景允许出现一定的透明度。

简单计算一下:由于 108dp * 108dp 图标被遮盖到了 72dp * 72dp 大小,每条边外部被切掉的 18dp 可以被认为是“额外的”内容,只在动效中显示。

具体参考来自「谷歌开发者」的文章『什么?Android O 图标能自适应了?!』。

03

随机密码

自动生成随机密码可以说是这个App的核心功能了。

通过弹出单选框的形式进行选择,目前有「6位数字密码」和「12位组合密码」两个选项,有想过再加入一个「18位混合密码」的选项,即数字+大小写字母+符号,因为懒,所以就没加了。

源码如下:

通过循环,利用StringBuffer类中的append方法将random出来的随机字符追加到字符串的末尾,从而得到一串随机密码。

04

不可编辑的 EditText

由于数据库中把名称设置为主键,所以在修改功能中必须把其设置为不可编辑状态。

一开始在XML布局文件中,设置了EditText的editable属性:

但是Google已不再推荐使用此属性并把它划掉了。

于是我又把它修改为focusable属性:

结果,EditText的确是失去了焦点,用户是无法对它进行编辑,输入法也弹不出来了。

这似乎问题就解决了,但是,当长按这个编辑框的时候,却发现可以通过粘贴的方式编辑EditText,这明显就没有把问题解决呀。

只能另辟蹊径了,可以考虑从Java文件中入手,即通过Acticity中的代码对其进行定义。

通过EditText的setEnabled方法即可设置其不可编辑。

05

键盘回车

EditText中按回车的话会出现换行的情况,如果用户每输入一个字符就摁一次回车的话那可就乱套了。

如何避免这种情况?两种方法。

一是在XML中设置其singleLine属性:

当其值为“true”则表示该编辑框只能以一行的方式显示。

二是设置其imeOptions属性:

望文生义,“actionNext”则是光标跳到下一项,“actionDone”则代表输入完成,并退出软键盘。

06

TableLayout 中的文字换行

为了整齐,我在Details页我使用了TableLayout布局,但是却发现在里面设置的TextView内容无法自动换行,当内容简短的情况下是没有问题的,但是当其长度超出屏幕的时候则会显得不知所谓。

我尝试将其singleLine设置为“false”,但还是没有办法自动换行。

后来发现了可以通过收缩列的方式对其换行:

值为列号,从0开始。

07

自定义 ListView

一开始为了方便,我把主页面上的ListView的内容用字符串的形式显示,即从数据库中抽取名称和账号,然后组合成字符串,直接放到ListView中显示。

到后来写详情页的时候,我才遇到问题,我要怎样响应这个ListView中的各个item呢?

获取字符串然后遇到'\n'后截止,似乎可行但是却是一段很糟糕的代码。

于是将前面显示部分的代码重构,不能单纯的用字符串来显示内容,需要用一个Map对象进行封装。

然后在响应事件中,通过getItemAtPosition方法获取其中的元素,再从数据库中进行查询操作。

最后再通过Intent传到Details页即可。

08

SQLite 操作

开发过程中,SQLite的语句操作可谓是浪费了我挺多时间的。

其中我使用SQL语句进行数据库操作的时候经常『Android Studio』会报错,而我也不知道为什么会报错。

但是,如果把SQL语句提出来,用字符串的形式写好再导进去则没有问题。

其实,还可以用更简单的方法对数据库进行操作,下面是SQLiteDatabase的常用方法:

其中,查询数据是通过Cursor类来实现的,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。

本来想下载一个『SQLite Studio』对数据库进行可视化操作,但安装完后一直跟『Android Studio』连接不上,具体什么原因我也不了解,只能将手机root后下载『RE文件管理器』进行查看,数据库在『RE文件管理器』中「/data/data」目录下。

09

显示内容刷新

当添加完成后,编辑内容的Activity执行了finish()方法,随即跳转到主Activity进行显示,但是实际上它并不会重新从数据库获取新的数据。

这就需要了解Activity的生命周期了,当Activity从后台回到前台的时候,会调用onResume()方法,因此,只需要Override这个Activity的onResume(),方法,使其执行跟onCreate()方法中相同的代码即可。

但不可以直接调用onCreate()方法:

最好是把复用的代码封装成一个方法,直接再次调用即可。

10

Activity 管理

在修改操作中,修改完成后由于也是要更新数据的,而详情页的数据是通过ListView中的对象传过来的,如果要更新详情页也是比较麻烦的。

于是,我便考虑修改完成后直接跳转到主页面,而不是详情页,但是如果直接跳转的话详情页的Activity还未销毁,按返回键的话还是会将它调回前台;而如果直接finish的话若用户不想修改而选择返回,则无法回到详情页。

因此,需要创建一个Activity的管理类来对其进行管理,只在必要的时候才销毁指定的Activity。

在详情页跳转到编辑页的时候,将要销毁的详情页Activity添加到队列,如果用户点击返回键,因为详情页未销毁,所以仍可正常返回,当用户编辑完成并提交的时候,则销毁这个队列中的详情页Activity以及编辑页本身的Activity,然后回到主页面。

而主页面因为之前已经重写好onResume()方法,因此会自动更新修改的数据。

11

App Bar

AppBar应该是 Google Material Design 的主要体现了。

以前的ActionBar的引入最初没有很好的考虑兼容问题,随着不同系统版本逐渐增加特性完善起来,在不同主题会有不同的显示效果。简而言之,就是兼容性不好,API的设计也比较散乱。

而Toolbar的推出,以独立纯净的支持库的形式提供了AppBar需要的所有特性,这样,可以在最大范围的设备上表现出这一最新的UI设计,API得到统一,而且提供更好的定制。

我使用的『Android Studio』默认使用的AppBar颜色为蓝色(#303F9F),而我更加喜欢黑色(#000000)。因此需要到「values」文件夹下的「style.xml」文件中进行修改,主要参照下图:

主页面我是通过『Android Studio』直接创建一个 Basic Activity 得到的,它默认是在一个AppBarLayout内放置Toolbar,而其他的页面都是通过创建 Empty Activity 得到的,由于功能的不同则需要为每个页面创建不同的Toolbar。

『Android Studio』自带有icon库,直接从其中导入即可,功能按钮排在右侧,通过设置layout_gravity属性实现:

还需要设置好ImageButton的背景颜色,包括background和backgroundTint属性。

12

应用锁

之前提到这是一个本来打算加上去的功能,后来时间原因,就没有加上去,大概说一下我的思路。

通过SharedPreferences来记录这个锁的密码,然后监听手机的状态,当熄屏或者重新打开应用的时候则要求输入密码。

具体我没有实现,思路大概是对的…吧。

13

数据加密

也是没有加进去的功能,可以参考网上的加密解密算法比如DES之类的,但是比如MD5这种只加密的算法就不适合应用了。

但是这些算法似乎比较复杂我也没有详细看,于是自己想了一个加密算法,安全性当然也是比较低的啦。

算法大致是通过跳子的方式向字符中插入字符,比如密码为“ABCDE”,那可以随机向这个字符中插入其他字符,比如“AaaBbbCccDddE”,然后解密的时候则同样通过跳子的方式读取字符串完成解密。

至于网上有没有其他比较简单但安全性又高一点点的算法我也没去深究了。

做这个项目的时候,我的参考资料是我们的教材,但是由于其版本太过老旧,很多被Google抛弃的东西,教材上还有,很多新的特性,它却也没介绍,所以一路摸爬滚打,靠着万能的Baidu和Google才砌成了这个毛胚。

当我码完这篇笔记的时候,我买的《第一行代码——Android》第2版也刚刚到货。

准备好好啃啃这本书,入门Android开发。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180218G00D2900?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券