为什么要区分两种模式

许多开发者(包括博主在内)都是闷骚的程序员,为了开发调试方便,常常在代码里加上日志,还经常在页面上各种弹窗提示。这固然有利于发现bug、提高软件质量,但过多的调试信息往往容易泄露敏感信息,如用户的账号密码、业务流程的逻辑。所以从保密需要考虑,app在上线前都得去掉多余的调试信息,也就形成了上线模式。
建立上线模式的好处有:
1、保护用户的敏感账户信息不被泄露;
2、保护业务逻辑与流程处理信息不被泄露;
3、把异常信息转换为更友好的提示信息,改善用户体验;

上线模式不是简单的把调试代码删掉,而是通过某个开关来控制是否显示调试信息,因为app后续还得修改、更新、重新发布,这个迭代的过程也要不断调试来实现新功能。具体地说,就是建立几个公共类,代码中涉及到输入调试信息的地方,都改为调用公共类的方法;然后在公共类定义几个布尔变量作为开关,在开发时打开调试,在上线时关闭调试,如此便实现了开发模式和上线模式的切换。

Log

Log类用于打印调试日志,调试APP时,日志信息会输出到控制台console窗口。因为最终用户看不到APP日志,所以除非特殊情况,发布上线的APP应屏蔽所有日志信息。

Log类对日志信息做了优先级分类,一般来说对输出日志没什么区别,姑且了解一下这些打印日志的方法:
v : 对应VERBOSE,来源。
d : 对应DEBUG,调试。
i : 对应INFO,信息。
w : 对应WARN,警告。
e : 对应ERROR,错误。
wtf : 对应ASSERT,致命错误。

下面是日志工具的代码例子:

import android.util.Log;public class LogTool {public static boolean isShow = false;//上线模式//public static boolean isShow = true;//开发模式public static void v(String tag, String msg){if(isShow == true){Log.v(tag, msg);}}public static void d(String tag, String msg){if(isShow == true){Log.d(tag, msg);}}public static void i(String tag, String msg){if(isShow == true){Log.i(tag, msg);}}public static void w(String tag, String msg){if(isShow == true){Log.w(tag, msg);}}public static void e(String tag, String msg){if(isShow == true){Log.e(tag, msg);}}public static void wtf(String tag, String msg){if(isShow == true){Log.wtf(tag, msg);}}}

Toast

Toast类用于在界面下方弹出小窗,给用户一两句话的提示,小窗短暂停留一会儿后消失。Toast窗口无交互动作,样式也基本固定,因此除了少数弹窗可予以保留(如“再按一次返回键退出”),其他弹窗都应在发布时屏蔽。

查看Toast的源码,会发现它的本质是把文本框放入INotificationManager的消息队列,由INotificationManager在界面上逐个展示。所以Log可以连续打印,但Toast不能连续显示,因为每个弹窗都要停留个几秒,几十上百个弹窗至少得耗时几分钟才会全部显示完毕。
Toast虽然有好些个公开方法,可是常用的也就makeText和show两个方法,实际开发中一般都是下面一行代码就完事了。

     Toast.makeText(this, "再按一次返回键退出!", Toast.LENGTH_SHORT).show();

上面那行Toast代码显然不够简洁,我们还是重写一个消息提示类,同时加入上线模式的开关控制,代码示例如下:

import android.content.Context;
import android.widget.Toast;public class ToastTool {public static boolean isShow = false;//上线模式//public static boolean isShow = true;//开发模式public static void showShort(Context ctx, String msg) {if (isShow == true) {Toast.makeText(ctx, msg, Toast.LENGTH_SHORT).show();}}public static void showLong(Context ctx, String msg) {if (isShow == true) {Toast.makeText(ctx, msg, Toast.LENGTH_LONG).show();}}public static void showQuit(Context ctx) {Toast.makeText(ctx, "再按一次返回键退出!", Toast.LENGTH_SHORT).show();}}

Dialog

对话框常用于各种与用户交互的操作,如果是业务逻辑需要,则该对话框无需区分不同模式;如果是提示错误信息,则对话框应就两种模式做不同处理。若是开发模式,则对话框消息展示完整的异常信息,包括输入参数、异常代码、异常描述等等;若是上线模式,则对话框消息展示相对友好的提示文字,如“当前网络连接失败,请检查网络设置是否开启”等等。

下面是异常消息提示对话框的代码例子:

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;@SuppressLint("DefaultLocale")
public class DialogTool {public static boolean isShow = false;//上线模式//public static boolean isShow = true;//开发模式public static int SYSTEM = 0;public static int IO = 1;public static int NETWORK = 2;private static String[] mError = {"系统异常,请稍候再试","读写失败,请清理内存空间后再试","网络连接失败,请检查网络设置是否开启"};public static void showError(Context ctx, int type, String title, Exception e) {AlertDialog.Builder builder = new AlertDialog.Builder(ctx);builder.setTitle(title);if (isShow == true) {String desc = String.format("%s\n异常描述:%s", mError[type], e.getMessage());builder.setMessage(desc);} else {builder.setMessage(mError[type]);}builder.setPositiveButton("确定", null);builder.create().show();}public static void showError(Context ctx, int type, String title, int code, String msg) {AlertDialog.Builder builder = new AlertDialog.Builder(ctx);builder.setTitle(title);if (isShow == true) {String desc = String.format("%s\n异常代码:%d\n异常描述:%s", mError[type], code, msg);builder.setMessage(desc);} else {builder.setMessage(mError[type]);}builder.setPositiveButton("确定", null);builder.create().show();}}

AndroidManifest.xml

除了代码之外,AndroidManifest也要区分开发模式与上线模式,几点注意事项如下:
1、application标签中加上属性“android:debuggable="true"”表示调试模式,默认是false表示上线模式。但若在模拟器上调试,或者通过ADT直接把app安装到手机上,则不管debuggable的值,直接切换到调试模式。发布时要把该属性设置为false。
2、APP发布之后,如无特殊情况,我们都不希望activity和service对外开放。但默认是开放的,所以我们要在activity和service标签下分别加上属性“android:exported="false"”,表示该组件不对外开放。
3、APP默认是安装到内部存储,可是移动设备的存储空间有限,我们要尽量让app选择安装到SD卡,避免占用用户的内部存储。这时要在manifest标签下加上属性android:installLocation,该属性的取值说明如下:
internalOnly : 默认值,只能装在内部存储。无法通过安全软件的应用搬家功能将其挪到SD卡。
auto : 优先装在内部存储,但若内部存储空间不足,则会装在SD卡。安装之后,用户可通过安全软件选择是否将其挪到SD卡。推荐设为该值。
preferExternal : 安装在SD卡上。但若SD卡不存在或SD卡空间不足,则仍会装在内部存储。

点此查看Android开发笔记的完整目录

Android开发笔记(七十一)区分开发模式和上线模式相关推荐

  1. windows内核开发笔记七:内核开发OVERLAPPED结构体详解

    windows内核开发笔记七:内核开发OVERLAPPED结构体详解 typedef struct _OVERLAPPED {   DWORD Internal;   DWORD InternalHi ...

  2. ATECC508A芯片开发笔记(十一):NXP 平台移植ATECCx08 CryptoAuthLib库(I2C)

    目录 ATECC508A芯片开发笔记(十一):NXP 平台移植x08库(I2C) 一.CryptoAuthLib 二.Nxp RT10xx平台上移植CryptoAuthLib 2.1.在官网下载最新的 ...

  3. RISC-V IDE MRS使用笔记(七) :常用开发技巧汇总

    RISC-V IDE MRS使用笔记(七) :常用开发技巧汇总 Q1: MRS调试时如何查看外设寄存器内容? A1: 在调试配置界面添加相应的.svd文件. Q2: MRS如何调用数学库? A2: # ...

  4. qml开发笔记(七):输入元素鼠标输入MouseArea和键盘输入Keys

    若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/ ...

  5. [推荐]OpenERP开发笔记(5) -- 自定义模块开发之一

    http://www.jeffzhang.cn/OpenERP-DEV-Notes-Custom-Module-Development1/ OpenERP开发笔记(5) -- 自定义模块开发之一 发表 ...

  6. NRF51822开发笔记-1.搭建NRF51822开发环境

    NRF51822开发笔记-1.搭建NRF51822开发环境 一.准备软件包 二.安装keil MDK并破解 三.安装NRF SDK 四.安装nRFgo studio 五.安装Jlink驱动 一.准备软 ...

  7. Android开发笔记(十一)自定义视图的构造方法

    自定义视图的用法 Android自带的视图常常不能满足实际开发的需求,这种情况下我们就得自定义视图(View). 首先在res\values目录下找到attrs.xml(如没有则创建之),在该属性定义 ...

  8. 【Visual C++】游戏开发笔记四十一 浅墨DirectX教程之九 为三维世界添彩:纹理映射技术(一)...

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8523341 作者:毛星云(浅墨 ...

  9. JNI开发笔记(七)--aar库的生成和调用

    aar库的生成和调用 引 前言 1. 新建一个空工程 2. 新建一个Module 3. 移植JNI工程到Module中 4. 生成aar库与so库 5. 在另一个工程中调用aar库 引 JNI开发笔记 ...

最新文章

  1. shell中判断空字符串和有趣的空字符串
  2. ProtoBuf协议
  3. hdu 4506(快速幂+找规律)
  4. 陆奇给工程师们的5个建议
  5. L1/L2/smooth_l1_loss/center_loss+Dice Loss+focal loss+各种IOU loss+kl散度
  6. mysql定义条件和处理_mysql sql存储过程条件定义与处理
  7. Spring Batch 批量处理策略
  8. mysql-索引操作
  9. 计算机毕设 ai_2020年计算机人工智能方向保研经历分享(南大,复旦,中科院计算所)...
  10. Sftp中文件名乱码
  11. PCB板设计流程总结
  12. C | 运算符、表达式和语句
  13. 基于JAVA小微企业人事管理系统计算机毕业设计源码+数据库+lw文档+系统+部署
  14. 如何在 Windows 上查看 HEIC 格式照片
  15. sprintf, snprintf, _snprintf, sprintf_s 等的区别
  16. 零基础小白应该怎么入门编程开发
  17. 打字测试的手机软件,手机上有什么软件可以练习打字
  18. Git pull单个文件
  19. springboot中集成servlet
  20. 微信小程序开发(五):小程序中的事件

热门文章

  1. 吴恩达机器学习7——支持向量机SVM
  2. 反向传播算法的详细解释(下)
  3. c语言b20等于多少,C语言程序:温度DS19B20显示
  4. 将python程序打包成可执行文件exe
  5. css html 语法,CSS基础语法
  6. python中的装饰器、装饰器模式_浅析Python装饰器以及装饰器模式
  7. python查看内置模块,python快速查看内置模块函数
  8. 成都东软学院php期末考试题,求大神。。。C语言期末项目答案。。。题在一楼。。。...
  9. Spring Data Jpa的@Temporal注解
  10. Tomcat8.5.40启动后一直卡在日志At least one JAR was scanned for TLDs yet contained no TLDs