【我的Android进阶之旅】Android 混淆文件资源分类整理
来源:互联网 发布:人工智能百度网盘 编辑:程序博客网 时间:2024/06/15 19:37
之前将所有的混淆都配置在一个
proguard-rules.pro
这个Android Studio新建项目时自动生成的文件里面,而随着项目功能迭代越来越多,代码量越来越多,引用的第二方库、第三方库都越来越多,导致proguard-rules.pro
越来越臃肿,而且随着开发人员增多导致proguard-rules.pro
文件里面的配置越来越混乱。
一、拆分proguard-rules.pro
混淆文件
因此今天我将
proguard-rules.pro
混淆文件进行拆分整理,大概拆分为以下4个文件:第三方混淆文件、第二份混淆文件、系统默认混淆文件、module单独混淆文件 。
如上图所示,四个文件分别为 'proguard-system-common.pro'
, 'proguard-module.pro'
, 'proguard-second-party.pro'
, 'proguard-third-party.pro'
二、配置混淆时候 proguardFiles 所引用的混淆文件
原来的混淆文件配置代码如下:
//混淆文件proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro',
改为下面的将四个混淆文件都加入到混淆配置文件列表中
//混淆文件 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-system-common.pro', 'proguard-module.pro', 'proguard-second-party.pro', 'proguard-third-party.pro'
如下图所示:
三、四个拆分的混淆文件具体代码
proguard-system-common.pro
proguard-system-common.pro 是Android系统通用的一些混淆配置,配置的内容大致如下:
# 指定代码的压缩级别-optimizationpasses 5-ignorewarnings # 抑制警告-verbose # 混淆时是否记录日志(混淆后生产映射文件 map 类名 -> 转化后类名的映射-dontpreverify # 不预校验-dontoptimize #不优化输入的类文件-dontshrink #该选项 表示 不启用压缩 混淆时是否做预校验(可去掉加快混淆速度)-dontusemixedcaseclassnames # 混淆时不会产生形形色色的类名 是否使用大小写混合-dontskipnonpubliclibraryclasses #不跳过(混淆) jars中的 非public classes 默认选项-keepattributes Exceptions # 解决AGPBI警告-keepattributes Exceptions,InnerClasses,...-keepattributes EnclosingMethod-keepattributes SourceFile,LineNumberTable #运行抛出异常时保留代码行号#过滤泛型-keepattributes Signature#过滤注解-keepattributes *Annotation*-keep class * extends java.lang.annotation.Annotation { *; }-keep interface * extends java.lang.annotation.Annotation { *; }#继承自activity,application,service,broadcastReceiver,contentprovider....不进行混淆-keep public class * extends android.app.Fragment-keep public class * extends android.app.Activity-keep public class * extends android.app.Application-keep public class * extends android.app.Service-keep public class * extends android.content.BroadcastReceiver-keep public class * extends android.content.ContentProvider-keep public class * extends android.app.backup.BackupAgentHelper-keep public class * extends android.preference.Preference-keep public class * extends android.support.v4.**-keep public class com.android.vending.licensing.ILicensingService-keep public class * extends android.support.multidex.MultiDexApplication-keep public class * extends android.view.View-keep class android.support.** {*;}# keep setters in Views so that animations can still work.# see http://proguard.sourceforge.net/manual/examples.html#beans-keepclassmembers public class * extends android.view.View { void set*(***); *** get*();}# 所有View的子类及其子类的get、set方法都不进行混淆-keep public class * extends android.view.View { #保持自定义控件指定规则的方法不被混淆 *** get*(); void set*(***); public <init>(android.content.Context); public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int);}#保持指定规则的方法不被混淆(Android layout 布局文件中为控件配置的onClick方法不能混淆)-keepclassmembers class * extends android.app.Activity { public void *(android.view.View);}# 对于带有回调函数onXXEvent的,不能被混淆-keepclassmembers class * { void *(*Event);} #保持R文件不被混淆,否则,你的反射是获取不到资源id的-keep class **.R$* { *; }# 不混淆R类里及其所有内部static类中的所有static变量字段,$是用来分割内嵌类与其母体的标志-keep public class **.R$*{ public static final int *;}-keepclassmembers class **.R$* { public static <fields>;}#过滤js-keepattributes *JavascriptInterface*#保护WebView对HTML页面的API不被混淆-keep class **.Webview2JsInterface { *; }-keepclassmembers class * extends android.webkit.WebViewClient { #如果你的项目中用到了webview的复杂操作 ,最好加入 public void *(android.webkit.WebView,java.lang.String,android.graphics.Bitmap); public boolean *(android.webkit.WebView,java.lang.String);}-keepclassmembers class * extends android.webkit.WebChromeClient { #如果你的项目中用到了webview的复杂操作 ,最好加入 public void *(android.webkit.WebView,java.lang.String);}#对WebView的简单说明下:经过实战检验,做腾讯QQ登录,如果引用他们提供的jar,若不加防止WebChromeClient混淆的代码,oauth认证无法回调,#反编译基代码后可看到他们有用到WebChromeClient,加入此代码即可。-keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); #保持自定义控件类不被混淆,指定格式的构造方法不去混淆}-keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int);}# 保持枚举 enum 类不被混淆-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String);}# 保持 native 方法不被混淆-keepclasseswithmembernames class * { native <methods>;}# 保持 Parcelable 不被混淆-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *;}#-keep public class * {# public protected *;#}#需要序列化和反序列化的类不能被混淆(注:Java反射用到的类也不能被混淆)-keep public class * implements java.io.Serializable { public *;}#不混淆Serializable接口的子类中指定的某些成员变量和方法-keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; !static !transient <fields>; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve();}-keepclassmembers class * { public <init> (org.json.JSONObject);}-keep class org.** {*;}-keep class com.android.**{*;}#-assumenosideeffects class_specification#v7 不混淆-keep class android.support.v7.** { *; }-keep interface android.support.v7.** { *; }-dontwarn android.support.v7.**# support-design-dontwarn android.support.design.**-keep class android.support.design.** { *; }-keep interface android.support.design.** { *; }-keep public class android.support.design.R$* { *; }# support-v7-appcompat-dontwarn android.support.v7.**-keep class android.support.v7.** { *; }-keep class android.support.v7.internal.** { *; }-keep interface android.support.v7.internal.** { *; }-keep public class android.support.v7.widget.** { *; }-keep public class android.support.v7.internal.widget.** { *; }-keep public class android.support.v7.internal.view.menu.** { *; }# support-v4-dontwarn android.support.v4.**-keep class android.support.v4.app.** { *; }-keep interface android.support.v4.app.** { *; }-keep class android.support.v4.** { *; }-keep public class * extends android.support.v4.view.ActionProvider { public <init>(android.content.Context);}# support-v7-cardview.pro# http://stackoverflow.com/questions/29679177/cardview-shadow-not-appearing-in-lollipop-after-obfuscate-with-proguard/29698051-keep class android.support.v7.widget.RoundRectDrawable { *; }-dontwarn android.net.http.**-keep class org.apache.http.** { *;}
proguard-third-party.pro
proguard-third-party.pro 是通用的第三方AAR库的混淆配置
# >>>>>>>>>>>>>>>>>>>>>>>> Facebook Fresco Start >>>>>>>>>>>>>>>>>>>>>>>># Keep our interfaces so they can be used by other ProGuard rules.# See http://sourceforge.net/p/proguard/bugs/466/-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip# Do not strip any method/class that is annotated with @DoNotStrip-keep @com.facebook.common.internal.DoNotStrip class *-keepclassmembers class * { @com.facebook.common.internal.DoNotStrip *;}# Keep native methods-keepclassmembers class * { native <methods>;}-dontwarn okio.**-dontwarn javax.annotation.**-dontwarn com.android.volley.toolbox.**-dontwarn com.squareup.okhttp.**-dontwarn okhttp3.**# >>>>>>>>>>>>>>>>>>>>>>>> Facebook Fresco End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> Glide Start >>>>>>>>>>>>>>>>>>>>>>>># Glide specific rules ## https://github.com/bumptech/glide-dontwarn com.bumptech.**-keep public class * implements com.bumptech.glide.module.GlideModule-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *;}# >>>>>>>>>>>>>>>>>>>>>>>> Glide End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> Picasso Start >>>>>>>>>>>>>>>>>>>>>>>>## Square Picasso specific rules #### https://square.github.io/picasso/ ##-dontwarn com.squareup.okhttp.**# >>>>>>>>>>>>>>>>>>>>>>>> Picasso End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> Jackson Start >>>>>>>>>>>>>>>>>>>>>>>>-dontwarn com.fasterxml.jackson.databind.**-keep class com.fasterxml.jackson.core.** {*;}-keep interface com.fasterxml.jackson.core { *; }-keep public class * extends com.fasterxml.jackson.core.**-keep class com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std.<clinit>-keep class com.fasterxml.jackson.databind.ObjectMapper.<clinit>-keep class com.fasterxml.jackson.databind.** {*;}-keep class com.fasterxml.jackson.databind.introspect.VisibilityChecker$*{*;}-keep interface com.fasterxml.jackson.databind { *; }-keep public class * extends com.fasterxml.jackson.databind.**# >>>>>>>>>>>>>>>>>>>>>>>> Jackson End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> GSON Start >>>>>>>>>>>>>>>>>>>>>>>>## GSON 2.2.4 specific rules ### Gson uses generic type information stored in a class file when working with fields. Proguard# removes such information by default, so configure it to keep all of it.-keepattributes Signature# For using GSON @Expose annotation-keepattributes *Annotation*-keepattributes EnclosingMethod# Gson specific classes-keep class sun.misc.Unsafe { *; }-keep class com.google.gson.** { *; }-keep class com.google.gson.stream.** { *; }-keep class com.google.**{*;}-keep class com.google.gson.examples.android.model.** { *; }# >>>>>>>>>>>>>>>>>>>>>>>> GSON End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> zxing Start >>>>>>>>>>>>>>>>>>>>>>>>-dontwarn com.google.zxing.**-dontwarn com.google.zxing.client.android.**-keep class com.google.zxing.**{*;}# >>>>>>>>>>>>>>>>>>>>>>>> zxing End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> EventBus 2 Start >>>>>>>>>>>>>>>>>>>>>>>>## GreenRobot EventBus specific rules ### https://github.com/greenrobot/EventBus/blob/master/HOWTO.md#proguard-configuration-keepclassmembers class ** { public void onEvent*(***);}# Only required if you use AsyncExecutor-keepclassmembers class * extends de.greenrobot.event.util.ThrowableFailureEvent { public <init>(java.lang.Throwable);}# Don't warn for missing support classes-dontwarn de.greenrobot.event.util.*$Support-dontwarn de.greenrobot.event.util.*$SupportManagerFragment# >>>>>>>>>>>>>>>>>>>>>>>> EventBus 2 End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> EventBus 3 Start >>>>>>>>>>>>>>>>>>>>>>>>## New rules for EventBus 3.0.x ### http://greenrobot.org/eventbus/documentation/proguard/-keepattributes *Annotation*-keepclassmembers class ** { @org.greenrobot.eventbus.Subscribe <methods>;}-keep enum org.greenrobot.eventbus.ThreadMode { *; }# Only required if you use AsyncExecutor-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { <init>(java.lang.Throwable);}# >>>>>>>>>>>>>>>>>>>>>>>> EventBus 3 End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> Rxjava Start >>>>>>>>>>>>>>>>>>>>>>>>-dontwarn sun.misc.**-dontwarn org.apache.http.**-keep class rx.**.-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { long producerIndex; long consumerIndex;}-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { rx.internal.util.atomic.LinkedQueueNode producerNode;}-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { rx.internal.util.atomic.LinkedQueueNode consumerNode;}# >>>>>>>>>>>>>>>>>>>>>>>> Rxjava End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> OkHttp Start >>>>>>>>>>>>>>>>>>>>>>>># OkHttp-keepattributes Signature-keepattributes *Annotation*-keep class com.squareup.okhttp.** { *; }-keep interface com.squareup.okhttp.** { *; }-dontwarn com.squareup.okhttp.**# OkHttp3-dontwarn okhttp3.**-keepattributes Signature-keepattributes *Annotation*-keep class okhttp3.** { *; }-keep interface okhttp3.** { *; }# Okio-keep class sun.misc.Unsafe { *; }-dontwarn java.nio.file.*-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement-dontwarn okio.**-keep class okio.** {*;}# >>>>>>>>>>>>>>>>>>>>>>>> OkHttp End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> Retrofit2 Start >>>>>>>>>>>>>>>>>>>>>>>># Platform calls Class.forName on types which do not exist on Android to determine platform.-dontnote retrofit2.Platform# Platform used when running on RoboVM on iOS. Will not be used at runtime.-dontnote retrofit2.Platform$IOS$MainThreadExecutor# Platform used when running on Java 8 VMs. Will not be used at runtime.-dontwarn retrofit2.Platform$Java8# Retain generic type information for use by reflection by converters and adapters.-keepattributes Signature# Retain declared checked exceptions for use by a Proxy instance.-keepattributes Exceptions-dontwarn retrofit2.adapter.**# Retrofit 2.X-dontwarn retrofit2.**-keep class retrofit2.** { *; }-keepattributes Signature-keepattributes Exceptions-keepclasseswithmembers class * { @retrofit2.http.* <methods>;}# >>>>>>>>>>>>>>>>>>>>>>>> Retrofit2 End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> Ormlite Start >>>>>>>>>>>>>>>>>>>>>>>>-keep class com.j256.ormlite.** {*;}# >>>>>>>>>>>>>>>>>>>>>>>> Ormlite End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> Butterknife Start >>>>>>>>>>>>>>>>>>>>>>>># ButterKnife 7-keep class butterknife.** { *; }-dontwarn butterknife.internal.**-keep class **$$ViewBinder { *; }-keep class **$$ViewInjector { *; }-keepnames class * { @butterknife.InjectView *;}-keepclasseswithmembernames class * { @butterknife.* <fields>;}-keepclasseswithmembernames class * { @butterknife.* <methods>;}# >>>>>>>>>>>>>>>>>>>>>>>> Butterknife End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> 热修复框架rocoofix Start >>>>>>>>>>>>>>>>>>>>>>>>-keep class com.dodola.rocoofix.** {*;}-keep class com.lody.legend.** {*;}# >>>>>>>>>>>>>>>>>>>>>>>> 热修复框架rocoofix End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> 数据库加密不混淆 Start >>>>>>>>>>>>>>>>>>>>>>>>-dontwarn com.google.common.**-keep class net.sqlcipher.** {*;}-keep class net.sqlcipher.database.** {*;}# >>>>>>>>>>>>>>>>>>>>>>>> 数据库加密不混淆 End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> 七牛 Start >>>>>>>>>>>>>>>>>>>>>>>>-keep class com.qiniu.** {*;}-dontwarn com.qiniu.**# >>>>>>>>>>>>>>>>>>>>>>>> 七牛 End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> UMeng大数据分析sdk混淆配置 Start >>>>>>>>>>>>>>>>>>>>>>>>-keepclassmembers class * { public <init> (org.json.JSONObject);}-dontwarn org.apache.http.**-keep class org.apache.http.** { *;}-keep class com.umeng.analytics.** {*;}-dontwarn com.umeng.analytics.**# >>>>>>>>>>>>>>>>>>>>>>>> UMeng大数据分析sdk混淆配置 End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> 高德相关混淆文件 Start >>>>>>>>>>>>>>>>>>>>>>>>-keep class com.amap.api.** {*;}-keep class com.autonavi.** {*;}-keep class com.a.a.** {*;}-keep class com.loc.** {*;}-dontwarn com.amap.api.**-dontwarn com.autonavi.**-dontwarn com.a.a.**-dontwarn com.loc.**# >>>>>>>>>>>>>>>>>>>>>>>> 高德相关混淆文件 End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> 百度定位 End >>>>>>>>>>>>>>>>>>>>>>>>-keep class com.baidu.** {*;}-keep class vi.com.** {*;}-dontwarn com.baidu.**# >>>>>>>>>>>>>>>>>>>>>>>> 百度定位 End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> pinyin4j Start >>>>>>>>>>>>>>>>>>>>>>>>-dontwarn net.soureceforge.pinyin4j.**-dontwarn demo.**-keep class net.sourceforge.pinyin4j.** { *;}-keep class demo.** { *;}-keep class com.hp.** { *;}# >>>>>>>>>>>>>>>>>>>>>>>> pinyin4j End >>>>>>>>>>>>>>>>>>>>>>>># >>>>>>>>>>>>>>>>>>>>>>>> httpclient Start >>>>>>>>>>>>>>>>>>>>>>>>-dontwarn android.net.compatibility.**-dontwarn android.net.http.**-dontwarn com.android.internal.http.multipart.**-dontwarn org.apache.commons.**-dontwarn org.apache.http.**-dontwarn org.apache.http.protocol.**-keep class android.net.compatibility.**{*;}-keep class android.net.http.**{*;}-keep class com.android.internal.http.multipart.**{*;}-keep class org.apache.commons.**{*;}-keep class org.apache.org.**{*;}-keep class org.apache.harmony.**{*;}# >>>>>>>>>>>>>>>>>>>>>>>> pinyin4j End >>>>>>>>>>>>>>>>>>>>>>>>-dontwarn net.sf.json.**-keep class net.sf.json.** {*;}# 动画库-keep class com.nineoldandroids.** {*;}
一个可以快速生成对应第三方库的链接:http://proguard.herokuapp.com/
打开连接:http://proguard.herokuapp.com/
输入第三方库的名字,如下所示:
输入完后,点击Generate按钮,即可自动生成相应的混淆代码,如下所示:
# Created by https://proguard.herokuapp.com/api/# Retrofit 1.X-keep class com.squareup.okhttp.** { *; }-keep class retrofit.** { *; }-keep interface com.squareup.okhttp.** { *; }-dontwarn com.squareup.okhttp.**-dontwarn okio.**-dontwarn retrofit.**-dontwarn rx.**-keepclasseswithmembers class * { @retrofit.http.* <methods>;}# If in your rest service interface you use methods with Callback argument.-keepattributes Exceptions# If your rest service methods throw custom exceptions, because you've defined an ErrorHandler.-keepattributes Signature# Also you must note that if you are using GSON for conversion from JSON to POJO representation, you must ignore those POJO classes from being obfuscated.# Here include the POJO's that have you have created for mapping JSON response to POJO for example.
proguard-second-party.pro
proguard-second-party.pro 是我们自己开发的一些存在Maven私服的AAR库的混淆配置
# themeLib-keep class com.xxx.theme.**{*;}-dontwarn com.xxx.theme.**-keep class com.xxx.md5.** {*;}-keep class com.xxx.widget.**{*;}-dontwarn com.xxx.widget.**-keep class com.xxx.http.**{*;}
proguard-module.pro
其中 proguard-module.pro 文件是你们自己模块的单独混淆文件,主要配置下你们项目中所引用到的一些网络和数据库的bean,防止json解析的时候出现解析出null的情况
#所有jackson对应实体类不能混淆-keep class com.netease.cloudmusic.net.bean.** {*;}#数据库实体类-keep class com.netease.cloudmusic.dao.bean.** {*;}
参考链接:
- http://blog.csdn.net/ouyang_peng/article/details/51277332
- https://github.com/yongjhih/android-proguards
- 一个可以快速生成对应第三方库的链接:http://proguard.herokuapp.com/
作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!转载请保留原文地址:http://blog.csdn.net/ouyang_peng/article/details/73088090如果本文对您有所帮助,欢迎您扫码下图所示的支付宝和微信支付二维码对本文进行打赏。
- 【我的Android进阶之旅】Android 混淆文件资源分类整理
- 【我的Android进阶之旅】Android 混淆文件资源分类整理
- 我的Android进阶之旅------>Android资源文件string.xml中\u2026的意思
- Android资源文件混淆
- 我的Android进阶之旅------>Android中Drawable分类汇总详解
- 我的Android进阶之旅------>Android中Drawable分类汇总详解
- Android的资源文件分类
- 我的Android进阶之旅------>Android Studio 快捷键整理分享
- 【我的Android进阶之旅】Android Studio如何轻松整理字符串到string.xml中
- 【我的Android进阶之旅】Android使用getIdentifier()方法根据资源名来获取资源id
- Android资源文件分类
- Android资源文件分类
- 我的Android进阶之旅------>Android SDK支持的配置标识符(有用的参考文件)
- 我的Android进阶之旅------>Android中使用HTML作布局文件以及调用Javascript
- 【我的Android进阶之旅】Android 如何防止 so库文件被未知应用盗用?
- 我的Android进阶之旅------>Android字符串资源中的单引号问题error: Apostrophe not preceded by 的解决办法
- 我的Android进阶之旅------>android:drawableLeft的用法
- 我的Android进阶之旅------>Android ListView优化详解
- Maven创建一个Java项目
- 基于HTML5 自定义编辑器
- Android Unable to delete file/directory 错误
- ssm通讯录管理系统--3
- 我的Android说
- 【我的Android进阶之旅】Android 混淆文件资源分类整理
- android kitkat(4.4以上)各个版本的特性解析
- error: could not install *smartsocket* listener: cannot bind to 127.0.0.1:5037
- SSM-MyBatis框架关联查询实例二
- 苹果支付成功后,JAVA服务端二次验证
- vim的使用
- QT读写XML文件之DOM方式解析XML
- [Unity&]缺少引用空间CrossPlatformInput的解决办法
- c++向main函数传递参数