Mark的私人博客

数风流人物,还看今朝

1
2
3
graph TB
A0[进入系统偏好设置] --> B0[打印机与扫描仪] --> C0[添加打印机] --> D0[选择IP]
D0[选择IP] --> E0[ 输入IP地址,协议选择行式打印机监控程序-LPD,使用那选择普通PCL打印机,然后系统会自动添加打印机驱动] --> F0[OK开始打印吧]
  1. 进入系统偏好设置。
  2. 打印机与扫描仪
  3. 添加打印机
  4. 选择IP
  5. 输入IP地址,协议选择“行式打印机监控程序-LPD”,使用那选择“普通PCL打印机”,然后系统会自动添加打印机驱动。
  6. OK开始打印吧

就是这么简单

原文简书


对比 Java 中的可变参数

先看下 Java 的可变参数,用我们最熟悉的 main 函数

1
2
public static void main(String... args) {
}

从 Java5 开始引入了可变参数(varargs)
对应的 Kotlin 的代码,参数为可变参数:

1
2
fun main(vararg args: String) {
}
阅读全文 »

应用场景:当我们的业务需要对已经存在的表进行表结构修改时,我们需要使用 ALERT 语句进行修改。

增加表列:

1
2
3
4
5
6
ALERT TABLE tablenamme ADD
(
column dataType [DEFAULT expr][NOT NULL],
column dataType [DEFAULT expr][NOT NULL],
....
);

修改表列:

1
2
3
4
5
6
ALERT TABLE tablenamme MODIFY
(
column dataType [DEFAULT expr][NOT NULL],
column dataType [DEFAULT expr][NOT NULL],
....
);

注意事项

  • 修改表列时,可以增加 NOT NULL及默认值约束,不能增加其他约束
  • 增加的默认值只会影响到后来插入的值
  • 若是要缩小列的宽度时,只有表中该列为空后者表里没有记录
  • 如若这列有空值,则不能添加非空约束
  • 若是改变该列的类型,只有表中该列为空后者表里没有记录

删除表中的列

ALERT TABLE tablenamme DROP column col_name;

增加约束

1
2
ALERT TABLE tablenamme 
ADD [CONSTRAINT constraint] type (column);
  • 增加 NOT NULL约束只能在增加列和修改列的时候添加

现在业务上出现客户要求如若生产环境出现紧急事件,需要版本回退的情况下,我这边的代码又没做版本分之处理,那么只能更改之前的版本号来实现。
不敢夺他人之功,原文在此处

我之前的文章:android反编译apktool—dex2jar—jdgui

一、反编译apk并修改版本号

在apk所在目录控制台输入下面指令,即可将文件名为source的apk反编译到outDir目录

  • 开始反编译apk

    apktool d -o outDir source.apk
    或者
    apktool d source.apk -o outDir

二、修改版本号

打开输入目录outDir找到apktool.yml文件,编辑修改versionCode

三、重新打包

通过以下命令就可以将目录outDir中的文件重新打包为no_sign_result.apk

  • apktool b -o no_sign_result.apk outDir

或者

  • apktool b outDir -o no_sign_result.apk

四、重新签名

使用如下命令进行签名
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore demostore.jks -signedjar result-signed.apk no_sign_result.apk yourkey
注:

  • demostore.jks为签名文件
  • no_sign_result.apk为要签名的源文件
  • result-signed.apk为签名后的目标文件
  • yourkey为签名的key

实现的效果能将json字符串以格式化的方式显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* $desc$ Log日志工具类
*
* @Author mark
* @Date 2018/11/26
*/
public class LogUtils {
//是否Debug
public static final boolean isMarkDebug = true;

public static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static void printLog(String name,String strContent){
if (isMarkDebug){
Log.d(name,strContent);
}
}
public static void printLine(String tag, boolean isTop) {
if (isTop) {
Log.d(tag, "╔═══════════════════════════════════════════════════════════════════════════════════════");
} else {
Log.d(tag, "╚═══════════════════════════════════════════════════════════════════════════════════════");
}
}
public static void printJson(String tag, String msg, String headString) {

String message;

try {
if (msg.startsWith("{")) {
JSONObject jsonObject = new JSONObject(msg);
message = jsonObject.toString(4);//最重要的方法,就一行,返回格式化的json字符串,其中的数字4是缩进字符数
} else if (msg.startsWith("[")) {
JSONArray jsonArray = new JSONArray(msg);
message = jsonArray.toString(4);
} else {
message = msg;
}
} catch (JSONException e) {
message = msg;
}

printLine(tag, true);
message = headString + LINE_SEPARATOR + message;
String[] lines = message.split(LINE_SEPARATOR);
for (String line : lines) {
Log.d(tag, "║ " + line);
}
printLine(tag, false);
}
}

根据传入的字符串跳转Activity

1
2
Intent intent = new Intent(context,Class.forName("com.packname.Activity"));
startActivity(intent);

根据传入的字符加载资源

1
int icon = getResources().getIdentifier(“imageid”, "drawable",getPackageName());

优化:

1
2
3
4
5
6
7
8
9
public static int getDrawableId(Context context, String var) {

try {
int imageId = context.getResources().getIdentifier(var, "drawable", context.getPackageName());
return imageId;
} catch (Exception e) {
return 0;
}
}

getIdentifier的函数签名如下:

1
public int getIdentifier (String name, String defType, String defPackage)

Android 事件分发总是遵循 Activity => ViewGroup => View 的传递顺序;
从按下开始依次从Activity开始处理,然后向下分发到ViewGroup,再到最下面的View。

一般情况下,事件列都是从用户按下(ACTION_DOWN)的那一刻产生的,
负责对事件进行分发的方法主要有三个,分别是:

  • dispatchTouchEvent()
  • onTouchEvent()
  • onInterceptTouchEvent()

事件:事件就是Event
事件类型分为四种

  • DOWN是按下
  • UP是抬起
  • MOVE是滑动
  • CANCEL是取消事件

它们并不存在于所有负责分发的组件中,其具体情况总结于下面的表格中:
dispatchTouchEvent,onTouchEvent方法存在于上文的三个组件中。而onInterceptTouchEvent为ViewGroup独有。
ViewGroup类中,实际是没有onTouchEvent方法的,但是由于ViewGroup继承自View,而View拥有onTouchEvent方法,故ViewGroup的对象也是可以调用onTouchEvent方法的。

使用 Gradle 工具检查此项目的依赖,进入项目目录,执行如下指令进行依赖检查:

1
2
3
cd app
gradle dependencies

打印出如下图所示的依赖树,依赖树显示了你 build 脚本声明的顶级依赖和它们的传递依赖:

1
2
3
4
5
6
7
8
9
10
11
+--- androidx.test.ext:junit:1.1.1
| +--- junit:junit:4.12
| | \--- org.hamcrest:hamcrest-core:1.3
| +--- androidx.test:core:1.2.0
| | +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
| | +--- androidx.test:monitor:1.2.0
| | | \--- androidx.annotation:annotation:1.0.0 -> 1.1.0
| | \--- androidx.lifecycle:lifecycle-common:2.0.0 -> 2.1.0
| | \--- androidx.annotation:annotation:1.1.0
| +--- androidx.test:monitor:1.2.0 (*)

反编译的工具(MAC环境下)

下载地址:

  • apkTool:一款用于反编译apk资源文件

  • dex2jar:是用于将class.dex 转换成classes-dex2jar.jar的工具

  • jdgui:这个用于查看classes-dex2jar.jar 源码工具

    阅读全文 »