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

为什么要区分两种模式

许多开发者(包括博主在内)都是闷骚的程序员,为了开发调试方便,常常在代码里加上日志,还经常在页面上各种弹窗提示。这固然有利于发现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,log,toast,开发模式,上线模式)