Android 代码混淆语法

指定代码的压缩级别

1
-optimizationpasses 5

包明不混合大小写

1
-dontusemixedcaseclassnames

不去忽略非公共的库类

1
-dontskipnonpubliclibraryclasses

优化不优化输入的类文件

1
-dontoptimize

预校验

1
-dontpreverify

混淆时是否记录日志

1
-verbose

混淆时所采用的算法

1
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

保护注解

1
-keepattributes *Annotation*

保持哪些类不被混淆

1
2
3
4
5
6
7
8
9
-keep public classextends android.app.Fragment
-keep public classextends android.app.Activity
-keep public classextends android.app.Application
-keep public classextends android.app.Service
-keep public classextends android.content.BroadcastReceiver
-keep public classextends android.content.ContentProvider
-keep public classextends android.app.backup.BackupAgentHelper
-keep public classextends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

如果有引用v4包可以添加下面这行

1
-keep public classextends android.support.v4.app.Fragment

apk 包内所有 class 的内部结构

1
-dump class_files.txt

未混淆的类和成员

1
-printseeds seeds.txt

列出从 apk 中删除的代码

1
-printusage unused.txt

混淆前后的映射

1
-printmapping mapping.txt

保持 native 方法不被混淆

1
2
3
-keepclasseswithmembernames class * {
native \<methods\>;

}

保持自定义控件类不被混淆

1
2
3
-keepclasseswithmembers class * {
public \<init\>(android.content.Context, android.util.AttributeSet);

}

保持自定义控件类不被混淆

1
2
3
-keepclasseswithmembers class{
public \<init\>(android.content.Context, android.util.AttributeSet, int);
}

保持自定义控件类不被混淆

1
2
3
-keepclassmembers classextends android.app.Activity {
public void *(android.view.View);
}

保持 Parcelable 不被混淆

1
2
3
-keep classimplements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

保持 Serializable 不被混淆

1
-keepnames classimplements java.io.Serializable

保持 Serializable 不被混淆并且enum 类也不被混淆

1
2
3
4
5
6
7
8
9
10
11
-keepclassmembers classimplements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[]() serialPersistentFields;
!static !transient \<fields\>;
!private \<fields\>;
!private \<methods\>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

不混淆资源类

1
2
3
4
5
6
7
8
9
10
11
-keepclassmembers class **.R$* {
public static \<fields\>;

}
-keep class **.R$* -keep class org.apache.http.** 
-keep class android.support.v7.widget.**{*;}
-keep class android.support.design.**{*;}
-keep public class android.support.v7.widget.LinearLayoutManager

-keep public classextends android.support.v7.widget.CardView$LayoutManager{
public \<init\>(...);

}

support-v4

1
2
3
-dontwarn android.support.v4.** 
-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }

support-v7

1
2
3
-dontwarn android.support.v7.** 
-keep class android.support.v7.internal.** { *; }
-keep interface android.support.v7.internal.** { *; }

运行 F8 2016 App 遇到的问题

运行F8 App时遇到下面的报错信息:
‘Invariant Violation:Application * has not been registered. This is either due to a require() error during initialization or failure to call AppRegistry.registerComponent.’

经过一番谷歌之后,发现可能是由于终端同时运行了两个React Native引起的,于是在关闭终端,重启F8 App之后,便不再报错了。
以Android为例,每次React Native项目运行的时候index.android.js最后都要执行AppRegistry.registerComponent,这是注册应用的入口,这个应用名称要与MainActivity中getMainComponentName返回的名称保持一致,否则就会报这个错误。这时候出现这个问题的原因就是同一个终端中运行两个React Native导致的。

vi快捷键

vi有三种基本的工作模式:一般模式(指令模式)、文本输入模式、末行模式

  • 一般模式->文本输入模式:输入a、i、o
  • 一般模式->末行模式:输入“:”(要英文输入法)
  • 文本输入模式->一般模式:按ESC
  • 末行模式->一般模式:输入错误指令

一般模式(指令模式):

撤销上一次的修改:u

取消最近一次“撤销”:ctrl+r

重复前一个操作:.

定位到配对的括号:%

定位到文件的末行:G

定位到文件的首行:gg

跳转到第x行:xG

删除光标所在的行:dd

连续删除x行:xdd

复制光标所在行:yy

连续复制x行:xyy

粘贴:p

向下新建一行:o

向上新建一行:O

删除光标所在的字符:x

绝对行首:0

行首的第一个非空白字符:shift+^

绝对行尾:shift+$

行首转换到编辑模式:I

行尾转换到编辑模式:A

移至下一个单词的词首:w

移至下一个单词的词尾:e

移至上一个单词的词首:b

打开光标处所指的文件:gf

关键字补齐:ctrl+n

按字符(行)选中文本:v|V(选择文本,按y进行复制,按d进行剪切,按p进行粘贴)

向后翻一屏:ctrl+f

向前翻一屏:ctrl+b

向前翻半屏:ctrl+u

向后翻半屏:ctrl+d

格式化代码:v或V选中=

全文格式化:gg=G

末行模式:

显示行号:set number

保存:w

退出:q

保存退出:wq

强制退出:q!

放弃所有未保存的修改,重新打开文件:e!

直接跳到第x行:x

查找与替换:1,$s/原来的字符串/新字符串/g

搜索关键字:/keyword(n向下查找;N向上查找)

多行注释使用:m,ns/^/#/

谷歌官方todo-mvp解析

导语

MVP模式有许多不同的版本,但这个范例是它的基础。这是一个对MVP模式的简单实现。它使用本地和远程数据,异步处理任务回调。

todo-mvp
项目地址

Fragments

作者认为Activity与Fragment的分离非常适合MVP:

  • Activity和Fragment的分离使得Activity可以专注于连接view和presenter
  • Fragment更适用于平板电脑的适配

概念

每个模块独立出来,并且有对应的Activity,Fragment,UI接口contract和presenter。

  • Activity负责初始化UI、Fragment以及presenter
  • Fragment负责实现contact的view接口
  • presenter实现contact的presenter接口
  • contract定义view的方法和presenter方法

一般情况下,业务逻辑在presenter中实现。view不包含逻辑,它监听用户的UI操作并且传递给presenter。contacts接口定义view和presenter之间的联系。

特点

架构清晰,轻量,可测

维护性

易于修改以及添加新功能模块。