一、什么是Android lint 检查

Android lint是一个静态代码分析工具,能够对项目中潜在的bug,可优化的代码,安全性,性能,可行性,可访问性,国际化等检查。

二、lint工作流程

针对我们的项目,通过lint.xml配置lint分析的选项,执行检查后,会针对要分析的issue生成报告。

lintTool 把源码和lint.xml配置文件 打包成lint output,并展现出具体的代码哪里有问题。

三、如何配置lint

lint工具提供了对代码的一系列不同方面的问题进行检查的功能。每一个问题(issue)都有它唯一的id。这些issue是分类的。
可以通过为工程配置lint.xml来指定要分析哪些方面的问题:
每个issue一个标签,可以指定它的严重性(severity)为ignore、error、warning等:

<?xml version="1.0" encoding="UTF-8"?>
<lint><!-- 忽略指定的检查 --><issue id="IconMissingDensityFolder" severity="ignore" /><!-- 忽略指定文件的指定检查 --><issue id="ObsoleteLayoutParam"><ignore path="res/layout/activation.xml" /><ignore path="res/layout-xlarge/activation.xml" /></issue><!-- 更改检查问题归属的严重性 --><issue id="HardcodedText" severity="error" />
</lint>

LintOptions配置

如果将 abortOnError 设置为true,自定义Lint很容易出现编译失败,此时检查message窗口将不必要的检查进行忽略禁用十分必要,例如 disable 'MissingTranslation' 此配置将忽略没有对strings.xml进行翻译报的错误。其他配置项查看下面各注释?

各个配置含义

android {
lintOptions {// 设置为 true时lint将不报告分析的进度quiet true// 如果为 true,则当lint发现错误时停止 gradle构建abortOnError false// 如果为 true,则只报告错误ignoreWarnings true// 如果为 true,则当有错误时会显示文件的全路径或绝对路径 (默认情况下为true)//absolutePaths true// 如果为 true,则检查所有的问题,包括默认不检查问题checkAllWarnings true// 如果为 true,则将所有警告视为错误warningsAsErrors true// 不检查给定的问题iddisable 'TypographyFractions','TypographyQuotes'// 检查给定的问题 idenable 'RtlHardcoded','RtlCompat', 'RtlEnabled'// * 仅 * 检查给定的问题 idcheck 'NewApi', 'InlinedApi'// 如果为true,则在错误报告的输出中不包括源代码行noLines true// 如果为 true,则对一个错误的问题显示它所在的所有地方,而不会截短列表,等等。showAll true// 重置 lint 配置(使用默认的严重性等设置)。lintConfig file("default-lint.xml")// 如果为 true,生成一个问题的纯文本报告(默认为false)textReport true// 配置写入输出结果的位置;它可以是一个文件或 “stdout”(标准输出)textOutput 'stdout'// 如果为真,会生成一个XML报告,以给Jenkins之类的使用xmlReport false// 用于写入报告的文件(如果不指定,默认为lint-results.xml)xmlOutput file("lint-report.xml")// 如果为真,会生成一个HTML报告(包括问题的解释,存在此问题的源码,等等)htmlReport true// 写入报告的路径,它是可选的(默认为构建目录下的 lint-results.html )htmlOutput file("lint-report.html")// 设置为 true, 将使所有release 构建都以issus的严重性级别为fatal(severity=false)的设置来运行lint// 并且,如果发现了致命(fatal)的问题,将会中止构建(由上面提到的 abortOnError 控制)checkReleaseBuilds true// 设置给定问题的严重级别(severity)为fatal (这意味着他们将会// 在release构建的期间检查 (即使 lint 要检查的问题没有包含在代码中)fatal 'NewApi', 'InlineApi'// 设置给定问题的严重级别为errorerror 'Wakelock', 'TextViewEdits'// 设置给定问题的严重级别为warningwarning 'ResourceAsColor'// 设置给定问题的严重级别(severity)为ignore (和不检查这个问题一样)ignore 'TypographyQuotes'}
}

四、java代码中和xml布局中使用

有时候会出现不准确的lint检查,如果你认为自己的java代码没有问题可以添加如下注解:

@SuppressLint 来抑制当前代码输出lint检查

xml中

抑制警告使用: tools:ignore.

要禁用多个 issue 时,用逗号把它们的 issue id 分隔开,比如:

tools:ignore="NewApi,StringFormatInvalid"

要在某个 XML 元素中对所有 issue 都禁用 lint 检查,可以使用 all 关键字,比如:

tools:ignore="all"

五、检查示意

#英文示意
"ContentDescription": Image without contentDescription
"AddJavascriptInterface": addJavascriptInterface Called
"ShortAlarm": Short or Frequent Alarm
"AllCaps": Combining textAllCaps and markup
"AllowAllHostnameVerifier": Insecure HostnameVerifier
"AlwaysShowAction": Usage of showAsAction=always
"InvalidUsesTagAttribute": Invalid name attribute for uses element.
"MissingIntentFilterForMediaSearch": Missing intent-filter with actionandroid.media.action.MEDIA_PLAY_FROM_SEARCH
"MissingMediaBrowserServiceIntentFilter": Missing intent-filter with actionandroid.media.browse.MediaBrowserService.
"MissingOnPlayFromSearch": Missing onPlayFromSearch.
"ImpliedTouchscreenHardware": Hardware feature touchscreen not explicitlymarked as optional
"MissingTvBanner": TV Missing Banner
"MissingLeanbackLauncher": Missing Leanback Launcher Intent Filter.
"MissingLeanbackSupport": Missing Leanback Support.
"PermissionImpliesUnsupportedHardware": Permission Implies UnsupportedHardware
"UnsupportedTvHardware": Unsupported TV Hardware Feature
"SupportAnnotationUsage": Incorrect support annotation usage
"ShiftFlags": Dangerous Flag Constant Declaration
"LocalSuppress": @SuppressLint on invalid element
"SwitchIntDef": Missing @IntDef in Switch
"UniqueConstants": Overlapping Enumeration Constants
"InlinedApi": Using inlined constants on older versions
"Override": Method conflicts with new inherited method
"ObsoleteSdkInt": Obsolete SDK_INT Version Check
"NewApi": Calling new methods on older versions
"UnusedAttribute": Attribute unused on older versions
"AppCompatMethod": Using Wrong AppCompat Method
"AppCompatCustomView": Appcompat Custom Widgets
"AppCompatResource": Menu namespace
"GoogleAppIndexingApiWarning": Missing support for Firebase App Indexing Api
"GoogleAppIndexingWarning": Missing support for Firebase App Indexing
"AppLinksAutoVerifyError": App Links Auto Verification Failure
"AppLinksAutoVerifyWarning": Potential App Links Auto Verification Failure
"AppLinkUrlError": URL not supported by app for Firebase App Indexing
"TestAppLink": Unmatched URLs
"InconsistentArrays": Inconsistencies in array element counts
"Assert": Assertions
"BadHostnameVerifier": Insecure HostnameVerifier
"BatteryLife": Battery Life Issues
"BackButton": Back button
"ButtonCase": Cancel/OK dialog button capitalization
"ButtonOrder": Button order
"ButtonStyle": Button should be borderless
"ByteOrderMark": Byte order mark inside files
"MissingSuperCall": Missing Super Call
"AdapterViewChildren": AdapterViews cannot have children in XML
"ScrollViewCount": ScrollViews can have only one child
"PermissionImpliesUnsupportedChromeOsHardware": Permission Implies UnsupportedChrome OS Hardware
"UnsupportedChromeOsHardware": Unsupported Chrome OS Hardware Feature
"GetInstance": Cipher.getInstance with ECB
"CommitTransaction": Missing commit() calls
"Recycle": Missing recycle() calls
"CommitPrefEdits": Missing commit() on SharedPreference editor
"ApplySharedPref": Use apply() on SharedPreferences
"ClickableViewAccessibility": Accessibility in Custom Views
"EasterEgg": Code contains easter egg
"StopShip": Code contains STOPSHIP marker
"MissingConstraints": Missing Constraints in ConstraintLayout
"VulnerableCordovaVersion": Vulnerable Cordova Version
"CustomViewStyleable": Mismatched Styleable/Custom View Name
"CutPasteId": Likely cut & paste mistakes
"SimpleDateFormat": Implied locale in date format
"SetTextI18n": TextView Internationalization
"Deprecated": Using deprecated resources
"MissingPrefix": Missing Android XML namespace
"MangledCRLF": Mangled file line endings
"DuplicateIncludedIds": Duplicate ids across layouts combined with includetags
"DuplicateIds": Duplicate ids within a single layout
"DuplicateDefinition": Duplicate definitions of resources
"ReferenceType": Incorrect reference types
"StringEscaping": Invalid string escapes
"UnpackedNativeCode": Missing android:extractNativeLibs=false
"UnsafeDynamicallyLoadedCode": load used to dynamically load code
"UnsafeNativeCodeLocation": Native code outside library directory
"EllipsizeMaxLines": Combining Ellipsize and Maxlines
"ExifInterface": Using android.media.ExifInterface
"ExtraText": Extraneous text in resource files
"FieldGetter": Using getter instead of field
"InvalidAnalyticsName": Invalid Analytics Name
"MissingFirebaseInstanceTokenRefresh": Missing Firebase Instance ID TokenRefresh
"FontValidationError": Validation of font files
"FontValidationWarning": Validation of font files
"FullBackupContent": Valid Full Backup Content File
"ValidFragment": Fragment not instantiatable
"GetContentDescriptionOverride": Overriding getContentDescription() on a View
"PackageManagerGetSignatures": Potential Multiple Certificate Exploit
"AccidentalOctal": Accidental Octal
"UseOfBundledGooglePlayServices": Use of bundled version of Google Playservices
"GradleCompatible": Incompatible Gradle Versions
"GradleDependency": Obsolete Gradle Dependency
"GradleDeprecated": Deprecated Gradle Construct
"DevModeObsolete": Dev Mode Obsolete
"DuplicatePlatformClasses": Duplicate Platform Classes
"GradleGetter": Gradle Implicit Getter Call
"GradlePluginVersion": Incompatible Android Gradle Plugin
"HighAppVersionCode": VersionCode too high
"GradleIdeError": Gradle IDE Support Issues
"GradlePath": Gradle Path Issues
"GradleDynamicVersion": Gradle Dynamic Version
"NotInterpolated": Incorrect Interpolation
"StringShouldBeInt": String should be int
"NewerVersionAvailable": Newer Library Versions Available
"MinSdkTooLow": API Version Too Low
"GridLayout": GridLayout validation
"HandlerLeak": Handler reference leaks
"HardcodedDebugMode": Hardcoded value of android:debuggable in the manifest
"HardcodedText": Hardcoded text
"HardwareIds": Hardware Id Usage
"IconDuplicatesConfig": Identical bitmaps across various configurations
"IconDuplicates": Duplicated icons under different names
"GifUsage": Using .gif format for bitmaps is discouraged
"IconColors": Icon colors do not follow the recommended visual style
"IconDensities": Icon densities validation
"IconDipSize": Icon density-independent size validation
"IconExpectedSize": Icon has incorrect size
"IconExtension": Icon format does not match the file extension
"IconLauncherShape": The launcher icon shape should use a distinct silhouette
"IconLocation": Image defined in density-independent drawable folder
"IconMissingDensityFolder": Missing density folder
"IconMixedNinePatch": Clashing PNG and 9-PNG files
"IconNoDpi": Icon appears in both -nodpi and dpi folders
"IconXmlAndPng": Icon is specified both as .xml file and as a bitmap
"ConvertToWebp": Convert to WebP
"WebpUnsupported": WebP Unsupported
"IncludeLayoutParam": Ignored layout params on include
"DisableBaselineAlignment": Missing baselineAligned attribute
"InefficientWeight": Inefficient layout weight
"NestedWeights": Nested layout weights
"Orientation": Missing explicit orientation
"Suspicious0dp": Suspicious 0dp dimension
"InstantApps": Instant App Issues
"DuplicateDivider": Unnecessary Divider Copy
"TrustAllX509TrustManager": Insecure TLS/SSL trust manager
"InvalidImeActionId": Invalid imeActionId declaration
"InvalidPackage": Package not included in Android
"DrawAllocation": Memory allocations within drawing code
"UseSparseArrays": HashMap can be replaced with SparseArray
"UseValueOf": Should use valueOf instead of new
"JavascriptInterface": Missing @JavascriptInterface on methods
"JobSchedulerService": JobScheduler problems
"KeyboardInaccessibleWidget": Keyboard inaccessible widget
"LabelFor": Missing labelFor attribute
"InconsistentLayout": Inconsistent Layouts
"InflateParams": Layout Inflation without a Parent
"StaticFieldLeak": Static Field Leaks
"DefaultLocale": Implied default locale in case conversion
"LocaleFolder": Wrong locale name
"GetLocales": Locale crash
"InvalidResourceFolder": Invalid Resource Folder
"WrongRegion": Suspicious Language/Region Combination
"UseAlpha2": Using 3-letter Codes
"LogConditional": Unconditional Logging Calls
"LongLogTag": Too Long Log Tags
"LogTagMismatch": Mismatched Log Tags
"AllowBackup": AllowBackup/FullBackupContent Problems
"MissingApplicationIcon": Missing application icon
"DeviceAdmin": Malformed Device Admin
"DuplicateActivity": Activity registered more than once
"DuplicateUsesFeature": Feature declared more than once
"GradleOverrides": Value overridden by Gradle build script
"IllegalResourceRef": Name and version must be integer or string, notresource
"MipmapIcons": Use Mipmap Launcher Icons
"MockLocation": Using mock location provider in production
"MultipleUsesSdk": Multiple <uses-sdk> elements in the manifest
"ManifestOrder": Incorrect order of elements in manifest
"MissingVersion": Missing application name/version
"OldTargetApi": Target SDK attribute is not targeting latest version
"UniquePermission": Permission names are not unique
"UsesMinSdkAttributes": Minimum SDK and target SDK attributes not defined
"WearableBindListener": Usage of Android Wear BIND_LISTENER is deprecated
"WrongManifestParent": Wrong manifest parent
"InvalidPermission": Invalid Permission Attribute
"ManifestResource": Manifest Resource References
"ManifestTypo": Typos in manifest tags
"FloatMath": Using FloatMath instead of Math
"MergeMarker": Code contains merge marker
"MergeRootFrame": FrameLayout can be replaced with <merge> tag
"IncompatibleMediaBrowserServiceCompatVersion": Obsolete version ofMediaBrowserServiceCompat
"InnerclassSeparator": Inner classes should use $ rather than .
"Instantiatable": Registered class is not instantiatable
"MissingRegistered": Missing registered class
"MissingId": Fragments should specify an id or tag
"LibraryCustomView": Custom views in libraries should use res-auto-namespace
"ResAuto": Hardcoded Package in Namespace
"NamespaceTypo": Misspelled namespace declaration
"UnusedNamespace": Unused namespace
"NegativeMargin": Negative Margins
"NestedScrolling": Nested scrolling widgets
"NetworkSecurityConfig": Valid Network Security Config File
"MissingBackupPin": Missing Backup Pin
"PinSetExpiry": Validate <pin-set> expiration attribute
"NfcTechWhitespace": Whitespace in NFC tech lists
"UnlocalizedSms": SMS phone number missing country code
"ObjectAnimatorBinding": Incorrect ObjectAnimator Property
"AnimatorKeep": Missing @Keep for Animated Properties
"ObsoleteLayoutParam": Obsolete layout params
"OnClick": onClick method does not exist
"Overdraw": Overdraw: Painting regions more than once
"DalvikOverride": Method considered overridden by Dalvik
"OverrideAbstract": Not overriding abstract methods on older platforms
"ParcelCreator": Missing Parcelable CREATOR field
"UnusedQuantity": Unused quantity translations
"MissingQuantity": Missing quantity translation
"ImpliedQuantity": Implied Quantities
"ExportedPreferenceActivity": PreferenceActivity should not be exported
"PrivateApi": Using Private APIs
"PackagedPrivateKey": Packaged private key
"PrivateResource": Using private resources
"ProguardSplit": Proguard.cfg file contains generic Android rules
"Proguard": Using obsolete ProGuard configuration
"PropertyEscape": Incorrect property escapes
"UsingHttp": Using HTTP instead of HTTPS
"SpUsage": Using dp instead of sp for text sizes
"InOrMmUsage": Using mm or in dimensions
"PxUsage": Using 'px' dimension
"SmallSp": Text size is too small
"ParcelClassLoader": Default Parcel Class Loader
"PendingBindings": Missing Pending Bindings
"RecyclerView": RecyclerView Problems
"Registered": Class is not registered in the manifest
"RelativeOverlap": Overlapping items in RelativeLayout
"RequiredSize": Missing layout_width or layout_height attributes
"AaptCrash": Potential AAPT crash
"ResourceCycle": Cycle in resource definitions
"ResourceName": Resource with Wrong Prefix
"ValidRestrictions": Invalid Restrictions Descriptor
"RtlCompat": Right-to-left text compatibility issues
"RtlEnabled": Using RTL attributes without enabling RTL support
"RtlSymmetry": Padding and margin symmetry
"RtlHardcoded": Using left/right instead of start/end attributes
"ScrollViewSize": ScrollView size validation
"SdCardPath": Hardcoded reference to /sdcard
"SecureRandom": Using a fixed seed with SecureRandom
"TrulyRandom": Weak RNG
"ExportedContentProvider": Content provider does not require permission
"ExportedReceiver": Receiver does not require permission
"ExportedService": Exported service does not require permission
"SetWorldReadable": File.setReadable() used to make file world-readable
"SetWorldWritable": File.setWritable() used to make file world-writable
"GrantAllUris": Content provider shares everything
"WorldReadableFiles": openFileOutput() or similar call passingMODE_WORLD_READABLE
"WorldWriteableFiles": openFileOutput() or similar call passingMODE_WORLD_WRITEABLE
"ServiceCast": Wrong system service casts
"WifiManagerLeak": WifiManager Leak
"WifiManagerPotentialLeak": WifiManager Potential Leak
"SetJavaScriptEnabled": Using setJavaScriptEnabled
"SignatureOrSystemPermissions": signatureOrSystem permissions declared
"SQLiteString": Using STRING instead of TEXT
"SSLCertificateSocketFactoryCreateSocket": Insecure call toSSLCertificateSocketFactory.createSocket()
"SSLCertificateSocketFactoryGetInsecure": Call toSSLCertificateSocketFactory.getInsecure()
"StateListReachable": Unreachable state in a <selector>
"AuthLeak": Code might contain an auth leak
"StringFormatCount": Formatting argument types incomplete or inconsistent
"StringFormatMatches": String.format string doesn't match the XML formatstring
"StringFormatInvalid": Invalid format string
"PluralsCandidate": Potential Plurals
"UseCheckPermission": Using the result of check permission calls
"CheckResult": Ignoring results
"ResourceAsColor": Should pass resolved color instead of resource id
"MissingPermission": Missing Permissions
"Range": Outside Range
"ResourceType": Wrong Resource Type
"RestrictedApi": Restricted API
"WrongThread": Wrong Thread
"WrongConstant": Incorrect constant
"VisibleForTests": Visible Only For Tests
"ProtectedPermissions": Using system app permission
"TextFields": Missing inputType or hint
"TextViewEdits": TextView should probably be an EditText instead
"SelectableText": Dynamic text should probably be selectable
"MenuTitle": Missing menu title
"ShowToast": Toast created but not shown
"TooDeepLayout": Layout hierarchy is too deep
"TooManyViews": Layout has too many views
"ExtraTranslation": Extra translation
"MissingTranslation": Incomplete translation
"Typos": Spelling error
"TypographyDashes": Hyphen can be replaced with dash
"TypographyEllipsis": Ellipsis string can be replaced with ellipsis character
"TypographyFractions": Fraction string can be replaced with fractioncharacter
"TypographyOther": Other typographical problems
"TypographyQuotes": Straight quotes can be replaced with curvy quotes
"UnsafeProtectedBroadcastReceiver": Unsafe Protected BroadcastReceiver
"UnprotectedSMSBroadcastReceiver": Unprotected SMS BroadcastReceiver
"UnusedResources": Unused resources
"UnusedIds": Unused id
"UseCompoundDrawables": Node can be replaced by a TextView with compounddrawables
"UselessLeaf": Useless leaf layout
"UselessParent": Useless parent layout
"EnforceUTF8": Encoding used in resource files is not UTF-8
"VectorRaster": Vector Image Generation
"VectorDrawableCompat": Using VectorDrawableCompat
"VectorPath": Long vector paths
"InvalidVectorPath": Invalid vector paths
"ViewConstructor": Missing View constructors for XML inflation
"ViewHolder": View Holder Candidates
"ViewTag": Tagged object leaks
"WrongViewCast": Mismatched view type
"FindViewByIdCast": Add Explicit Cast
"Wakelock": Incorrect WakeLock usage
"WakelockTimeout": Using wakeLock without timeout
"InvalidWearFeatureAttribute": Invalid attribute for Wear uses-feature
"WearStandaloneAppFlag": Invalid or missing Wear standalone app flag
"WebViewLayout": WebViews in wrap_content parents
"WrongCall": Using wrong draw/layout method
"WrongCase": Wrong case for view tag
"InvalidId": Invalid ID declaration
"NotSibling": RelativeLayout Invalid Constraints
"UnknownId": Reference to an unknown id
"UnknownIdInLayout": Reference to an id that is not in the current layout
"SuspiciousImport": 'import android.R' statement
"WrongFolder": Resource file in the wrong res folder
"WrongThreadInterprocedural": Wrong Thread (Interprocedural)#中文示意1. Correctness 1) Appcompat Custom WidgetsAppcompat自定义小部件一般会让你继承自 android.support.v7.widget.AppCompat...不要直接扩展android.widget类,而应该扩展android.support.v7.widget.AppCompat中的一个委托类。
2) Attribute unused on older versions旧版本未使用的属性  针对具有minSdkVersion这不是一个错误; 应用程序将简单地忽略该属性。可以选择在layout-vNN文件夹中创建一个布局的副本 将在API NN或更高版本上使用,您可以利用更新的属性。
3) Class is not registered in the manifest类未在清单中注册Activities, services and content providers should be registered in the AndroidManifest.xml file
4) Combining Ellipsize and MaxlinesEllipsize和Maxlines相结合结合ellipsize和maxLines = 1可能导致某些设备崩溃。 早期版本的lint建议用maxLines = 1替换singleLine = true,但在使用ellipsize时不应该这样做
5) Extraneous text in resource files资源文件中的无关文本
6) Hardcoded reference to /sdcard硬编码参考/ SD卡代码不应该直接引用/ sdcard路径; 而是使用:Environment.getExternalStorageDirectory().getPath()不要直接引用/ data / data /路径; 它可以在多用户场景中有所不同。
7) Implied default locale in case conversion在转换的情况下默认的默认语言环境
8) Implied locale in date format隐含的日期格式的区域设置调用者都应该使用getDateInstance(),getDateTimeInstance()或getTimeInstance()来获得适合用户语言环境的SimpleDateFormat的现成实例。
9) Likely cut & paste mistakes可能剪切和粘贴错误剪切和粘贴调用findViewById但忘记更新R.id字段的情况。 有可能你的代码只是(冗余)重复查找字段
10) Mismatched Styleable/Custom View Name不匹配的样式/自定义视图名称自定义视图的惯例是使用名称与自定义视图类名称相匹配的声明样式。
11) Missing Permissions缺少权限
12) Nested scrolling widgets嵌套的滚动小部件A scrolling widget such as a ScrollView should not contain any nested scrolling widgets since this has various usability issues
13) Obsolete Gradle Dependency    已过时的Gradle依赖关系
14) Target SDK attribute is not targeting latest version    目标SDK属性未定位到最新版本
15) Using 'px' dimension    使用“px”维度
16) Using android.media.ExifInterface    使用android.media.ExifInterface旧版的有一些漏洞,使用支持库中的
17) Using dp instead of sp for text sizes    使用dp代替文本大小的sp
18) Using Private APIs    使用私有API
19) Using private resources    使用私人资源2. Internationalization1) Hardcoded text  硬编码文本直接在布局文件中对文本属性进行硬编码是有缺陷的should use @string resource
2) Overlapping items in RelativeLayout  在RelativeLayout中重叠项目如果相对布局的文本或按钮项左右对齐,则由于本地化的文本扩展,它们可以相互重叠,除非它们具有toEndOf / toStartOf之类的相互约束。
3) Padding and margin symmetry   填充和边缘对称如果您在布局的左侧指定填充或边距,则应该也可以在右侧指定填充(反之亦然),以便从右到左布局对称。
4) TextView Internationalization   TextView国际化永远不要调用Number#toString()来格式化数字; 它不会正确处理分数分隔符和区域特定的数字使用具有适当格式规范(%d或%f)的String#格式不要传递字符串(例如“Hello”)来显示文本。 硬编码文本无法正确翻译成其他语言,考虑使用Android资源字符串不要通过连接文本块来构建消息。 这样的消息不能被正确翻译。
5) Using left/right instead of start/end attributes   使用左/右而不是开始/结束属性3. Performance1) Handler reference leakshandler导致的泄漏由于该Handler被声明为内部类,所以可以防止外部类被垃圾收集。 如果处理程序对主线程以外的线程使用Looper或MessageQueue,则不存在问题。 如果处理程序正在使用主线程的Looper或MessageQueue,则需要修复Handler声明,解决:将Handler声明为静态类; 在外部类中,实例化WeakReference到外部类,并在实例化Handler时将此对象传递给Handler; 使用WeakReference对象来引用外部类的所有成员。
2) HashMap can be replaced with SparseArrayHashMap可以用SparseArray替换对于键类型为integer的映射,使用Android SparseArray API通常效率更高。
3) Inefficient layout weight低效的布局权重当LinearLayout中只有一个控件定义了一个权重时,为它指定一个0dp的宽度/高度会更有效率,因为它将吸收所有的剩余空间。 如果声明的宽度/高度为0dp,则不必首先测量其自己的大小。
4) Layout has too many views布局有太多的意见在单个布局中使用太多的视图对性能不利。 考虑使用复合绘图或其他技巧来减少此布局中的视图数量。 最大视图数量默认为80,但可以使用环境变量ANDROID_LINT_MAX_VIEW_COUNT进行配置。
5) Layout hierarchy is too deep布局层次太深嵌套太多的布局对性能不利。 考虑使用更平坦的布局(比如RelativeLayout或GridLayout)。默认的最大深度是10,但可以使用环境变量ANDROID_LINT_MAX_DEPTH进行配置。
6) Memory allocations within drawing code内存分配在绘图代码应该避免在绘图或布局操作中分配对象。 这些被频繁地调用,所以平滑的UI可以被对象分配造成的垃圾收集暂停中断。 通常处理的方式是预先分配所需的对象,并为每个绘图操作重新使用它们。 有些方法代表您分配内存(如Bitmap.create),并且应该以相同的方式处理这些内存。
7) Missing @Keep for Animated Properties属性动画缺少@Keep当你使用属性动画师时,属性可以通过反射来访问。 这些方法应该使用@Keep注释,以确保在发布构建期间,这些方法不会被视为未被使用和删除,或者被视为内部的,并被重新命名为更短。 这个检查还会标记出其他可能遇到的反射问题,比如缺少属性,错误的参数类型等等。
8) Missing baselineAligned attribute    缺少baselineAligned属性当使用LinearLayout在嵌套布局之间按比例分配空间时,应关闭基线对齐属性以使布局计算速度更快。
9) Node can be replaced by a TextView with compound drawables节点可以用复合可绘制的TextView替换包含ImageView和TextView的LinearLayout可以更有效地处理为复合可绘制(单个TextView,使用drawableTop,drawableLeft,drawableRight和/或drawableBottom属性在文本旁边绘制一个或多个图像)。 如果这两个小部件彼此之间有空白,则可以用drawablePadding属性替换。
10) Obsolete layout params过时的布局参数
11) Obsolete SDK_INT Version Check已过时的SDK_INT版本检查此检查标志版本检查不是必需的,因为minSdkVersion(或周围已知的API级别)已经至少与检查的版本一样高。它还会在-vNN文件夹中查找资源,如版本限定符小于或等于minSdkVersion的values-v14,其中内容应合并到最佳文件夹中。
12) Static Field Leaks静态常量--持有fragment及activity的引用非静态内部类对其外部类具有隐式引用。如果该外部类是例如fragment或activity,如果长时间运行的处理程序/加载程序/任务将持有对该activity的引用,长时间没有被回收掉。
13) Useless parent layout无用的父母布局有没有兄弟的孩子的布局不是滚动视图或根布局,并且没有背景,可以被移除并且其子节点直接移动到父节点以获得更平坦和更高效的布局分层结构。
14) View Holder Candidates查看持有人候选人Should use View Holder pattern4. Security1) Cipher.getInstance with ECBCipher.getInstance与ECB不应使用ECB作为cipher mode或不设置cipher mode来调用Cipher#getInstance,因为android上的默认模式是ECB,这是不安全的。(加解密)
2) Content provider does not require permission内容提供者不需要权限内容提供程序默认导出,系统上的任何应用程序都可能使用它们来读取和写入数据。 如果内容提供者提供对敏感数据的访问,则应该通过在清单中指定export = false来保护它,或者通过可以授予其他应用程序的权限来保护它。
3) Exported service does not require permission导出的服务不需要权限导出的服务(设置了exported = true或者包含intent-filter并且不指定exported = false的服务)应该定义一个实体为了启动服务或绑定到服务而必须拥有的权限。 没有这个,任何应用程序都可以使用此服务。
4) Hardware Id Usage硬件ID使用情况不建议使用这些设备标识符,除了高价值欺诈预防和高级电话使用情况。getLine1Number获取手机号,getDeviceId设备IMEI,getMacAddressMAC地址
5) Incorrect constant不正确的常量
6) Insecure TLS/SSL trust manager不安全的TLS / SSL信任管理器
7) Missing @JavascriptInterface on methods缺少@JavascriptInterface方法
8) openFileOutput() or similar call passing MODE_WORLD_READABLEopenFileOutput()或类似的调用传递MODE_WORLD_READABLE
9) openFileOutput() or similar call passing MODE_WORLD_WRITEABLEopenFileOutput()或类似的调用传递MODE_WORLD_WRITEABLE在某些情况下,应用程序可以编写世界可写文件,但应仔细检查这些文件以确保它们不包含私人数据,并且如果文件被恶意应用程序修改,则不会欺骗或破坏应用程序。
10) Receiver does not require permission接收者不需要许可
11) Using setJavaScriptEnabled  使用setJavaScriptEnabled如果您不确定您的应用程序确实需要JavaScript支持,那么您的代码不应该调用setJavaScriptEnabled。5. Usability1) Button should be borderless按钮应该是无边界的两个 Buttons 放在一个布局里会被判断为按钮栏,需要添加样式取消它的边框在 Buttons 上添加属性 style="?android:attr/buttonBarButtonStyle" 。系统提示也可以在按钮的父布局上添加 style="? android:attr/buttonBarStyle" 属性
2) Ellipsis string can be replaced with ellipsis character省略号字符串可以用省略号字符替换Replace "..." with ellipsis character (…, …) ?
3) Hyphen can be replaced with dash连字符可以用短划线代替Replace "-" with an "en dash" character (–, –) ?
4) Missing View constructors for XML inflation缺少XML通货膨胀的视图构造函数
5) Text size is too small文字太小避免使用小于12sp的尺寸。小于12sp的字体会太小导致用户看不清二. 其他类型Class structure 类结构Code maturity issues 代码成熟度问题Code style issues 代码样式问题Compiler issues 编译器问题Control flow issues 控制流量问题Data flow issues 数据流问题Declaration redundancy 声明冗余Error handling 错误处理General 一般Imports 进口J2ME issues J2ME问题Java 5 Java 5Java 7 Java 7Java language level migration aids Java语言级别的迁移辅助Javadoc issues Javadoc问题Naming conventions 命名约定Numeric issues 数字问题Performance issues 性能问题Probable bugs 可能的错误Properties Files 属性文件Spelling 拼字Style 样式Verbose or redundant code constructs 详细或冗余的代码结构XML XML
1. Class structureField can be local字段可以是本地的Parameter can be local参数可以是本地的'private' method declared 'final''static' method declared 'final'
2. Code maturity issues 代码成熟度问题Deprecated API usage不推荐使用APIDeprecated member is still used不推荐使用的成员仍在使用
3. Code style issues 代码样式问题Unnecessary enum modifier不必要的枚举修饰符Unnecessary interface modifier不必要的界面修饰符Unnecessary semicolon不必要的分号private  public
4. Compiler issues 编译器问题Unchecked warning未经检查的警告
5. Control flow issues 控制流问题Double negation 双重否定Pointless boolean expression 无意义的布尔表达式Redundant 'if' statement 冗余“if”语句Redundant conditional expression 冗余的条件表达式Simplifiable boolean expression 简化布尔表达式Simplifiable conditional expression 简化条件表达式Unnecessary 'return' statement 不必要的“return”声明return;
6. Data flow issues 数据流问题Boolean method is always inverted布尔方法总是倒置的Redundant local variable冗余局部变量
7. Declaration redundancy 声明冗余Access static member via instance reference通过实例引用访问静态成员this.minsize = this.maxsize;Actual method parameter is the same constant实际的方法参数是相同的常量Actual value of parameter ''register'' is always ''true''Declaration access can be weaker声明访问权限可以再弱Can be privateDeclaration can have final modifier宣言可以有最终的修改Duplicate throws重复抛出Empty method空方法Method can be void方法可以是无效的Method returns the same value方法返回相同的值All implementations of this method always return '3'Redundant throws clause冗余抛出子句The declared exception 'UnsupportedEncodingException' is never thrownUnnecessary module dependency不必要的模块依赖Unused declaration未使用的声明(方法,变量)
8. Error handling 错误处理Caught exception is immediately rethrown捕获到的异常立即被重新抛出Empty 'catch' block空'catch'块'return' inside 'finally' block在'finally'块中'返回''throw' inside 'finally' block在“finally”块内“抛出”
9. GeneralAnnotator注解者Default File Template Usage默认文件模板的用法
10. Imports 导入Unused import没有用到的导入
11. J2ME issues J2ME问题'if'语句可以用&&或||代替 表达
12. Java 5 Java 5'for' loop replaceable with 'foreach''for'循环可替换为'foreach''indexOf()' expression is replaceable with 'contains()''indexOf()'表达式可以用'contains()'来替换'StringBuffer' may be 'StringBuilder''StringBuffer'可能是'StringBuilder'Unnecessary boxing不必要的装箱Unnecessary unboxing不必要的拆箱'while' loop replaceable with 'foreach''while'循环可以替换'foreach'
13. Java 7 Java 7Explicit type can be replaced with <>显式类型可以用<>来替换'试试最后'用资源替换'试用'
14. Java language level migration aids Java语言级别的迁移辅助'if' replaceable with 'switch'
15. Javadoc issues Javadoc问题Dangling Javadoc comment 摇摇晃晃的Javadoc评论Declaration has Javadoc problems 宣言有Javadoc问题Declaration has problems in Javadoc  声明在Javadoc引用中有问题
16. Naming conventions 命名约定
17. Numeric issues 数字问题数字溢出 Numeric overflow八进制整数 Octal integer无意义的算术表达式 Pointless arithmetic expression
18. Performance issues 性能问题Redundant 'String.toString()'  冗余'String.toString()'Redundant 'substring(0)' call  冗余'substring(0)'调用Redundant call to 'String.format()'  冗余调用'String.format()'String concatenation as argument to 'StringBuffer.append()' call  字符串连接  作为“StringBuffer.append()”调用的参数String concatenation in loop  循环中的字符串连接'StringBuffer' can be replaced with 'String'  'StringBuffer'可以替换为'String'
19. Probable bugs 可能的错误Collection added to self   Collection添加到自我Constant conditions & exceptions 不变的条件和例外Mismatched query and update of collection 不匹配的查询和集合更新Mismatched query and update of StringBuilder 不匹配的查询和更新的StringBuilder@NotNull/@Nullable problems @NotNull / @可空问题Result of method call ignored 方法调用的结果被忽略Statement with empty body 声明与空的实现String comparison using '==', instead of 'equals()' 使用'=='进行字符串比较,而不是'equals()'Suspicious collections method calls 可疑collections方法调用Suspicious variable/parameter name combination 可疑变量/参数名称组合Unused assignment 没用的赋值操作
20. Properties Files 属性文件Unused Property未使用的属性
21. Spelling 拼字
22. Style 样式Unnecessary semicolon没必要的分号
23. Verbose or redundant code constructs 详细或冗余的代码结构Redundant array creation创建冗余阵列Redundant type cast冗余类型转换
24. XML XMLDeprecated API usage in XML  在XML中不推荐使用APIUnbound XML namespace prefix  未绑定的XML名称空间前缀Unused XML schema declaration  未使用的XML模式声明XML highlighting  XML突出显示XML tag empty body  XML标签为空的正文

五、在Android Studio中使用

lint提供了命令行接口,所以可以作为单独工具被使用,或者集成到ide的构建流程中去。
在Android Studio中,通过菜单或者在Project视图以及代码视图中的右键菜单中选择Analyze > Inspect Code就可以打开lint检查的对话框Specify Inspection Scope,在这里设置好要进行代码分析的范围,确定后工具就开始对代码进行检查了,完成后会自动打开Inspection工具窗口。

六、自定义lint

原生Lint无法满足特有的需求,例如:编码规范。

  • id : 唯一值,应该能简短描述当前问题。利用Java注解或者XML属性进行屏蔽时,使用的就是这个id。
  • summary : 简短的总结,通常5-6个字符,描述问题而不是修复措施。
  • explanation : 完整的问题解释和修复建议。
  • category : 问题类别。详见下文详述部分。
  • priority : 优先级。1-10的数字,10为最重要/最严重。
  • severity : 严重级别:Fatal, Error, Warning, Informational, Ignore。
  • Implementation : 为Issue和Detector提供映射关系,Detector就是当前Detector。声明扫描检测的范围Scope,Scope用来描述Detector需要分析时需要考虑的文件集,包括:Resource文件或目录、Java文件、Class文件。

自定义Detector可以实现一个或多个Scanner接口,选择实现哪种接口取决于你想要的扫描范围
- Detector.XmlScanner - Detector.JavaScanner - Detector.ClassScanner - Detector.BinaryResourceScanner - Detector.ResourceFolderScanner - Detector.GradleScanner - Detector.OtherFileScanner

这里因为我们是要针对Java代码扫描,所以选择使用JavaScanner

代码中getApplicableNodeTypes方法决定了什么样的类型能够被检测到。这里我们想看Log以及println的方法调用,选取MethodInvocation。对应的,我们在createJavaVisitor创建一个ForwardingAstVisitor通过visitMethodInvocation方法来接收被检测到的Node。
可以看到getApplicableNodeTypes返回值是一个List,也就是说可以同时检测多种类型的节点来帮助精确定位到代码,对应的ForwardingAstVisitor接受返回值进行逻辑判断就可以了。

可以看到JavaScanner中还有其他很多方法,getApplicableMethodNames(指定方法名)、visitMethod(接收检测到的方法),这种对于直接找寻方法名的场景会更方便。当然这种场景我们用最基础的方式也可以完成,只是比较繁琐。

例子:

public class ULogUsageDetector extends Detector implements Detector.JavaScanner {private static final Class<? extends Detector> DETECTOR_CLASS = ULogUsageDetector.class;private static final EnumSet<Scope> DETECTOR_SCOPE = Scope.JAVA_FILE_SCOPE;private static final Implementation IMPLEMENTATION = new Implementation(DETECTOR_CLASS,DETECTOR_SCOPE);private static final String ISSUE_ID = "ULogNotUsed";private static final String ISSUE_DESCRIPTION = "错误:你应该使用自定义的Log打印工具类{com.xiaohe.www.lib.tools.log.ULog}";private static final String ISSUE_EXPLANATION = "为了能够控制Log并统一输出,你不能直接使用{android.util.Log}或者{System.out.println}直接打印日志,你应该使用自定义的Log打印工具类{com.xiaohe.www.lib.tools.log.ULog}";private static final Category ISSUE_CATEGORY = Category.CORRECTNESS;private static final int ISSUE_PRIORITY = 9;private static final Severity ISSUE_SEVERITY = Severity.ERROR;public static final Issue ISSUE = Issue.create(ISSUE_ID,ISSUE_DESCRIPTION,ISSUE_EXPLANATION,ISSUE_CATEGORY,ISSUE_PRIORITY,ISSUE_SEVERITY,IMPLEMENTATION);private static final String SYSTEM_OUT_PRINT = "System.out.print";private static final String SYSTEM_OUT_PRINTLN = " System.out.println";private static final String SYSTEM_ERR_PRINT = "System.err.print";private static final String SYSTEM_ERR_PRINTLN = " System.err.println";private static final String CHECK_PACKAGE = "android.util.Log";/*** JavaScanner* @return*/@Overridepublic List<String> getApplicableMethodNames() {return Arrays.asList("v", "d", "i", "w", "e", "wtf");}/*** ClassScanner* @return*/
//    public List getApplicableCallNames() {
//        return Arrays.asList("v", "d", "i", "w", "e", "wtf");
//    }@Overridepublic List<Class<? extends Node>> getApplicableNodeTypes() {return Collections.<Class<? extends Node>>singletonList(MethodInvocation.class);}@Overridepublic AstVisitor createJavaVisitor(final JavaContext context) {return new ForwardingAstVisitor() {@Overridepublic boolean visitMethodInvocation(MethodInvocation node) {String nodeString = node.toString();if (nodeString.startsWith(SYSTEM_OUT_PRINT)|| nodeString.startsWith(SYSTEM_OUT_PRINTLN)|| nodeString.startsWith(SYSTEM_ERR_PRINT)|| nodeString.startsWith(SYSTEM_ERR_PRINTLN)) {context.report(ISSUE, node, context.getLocation(node),ISSUE_DESCRIPTION+",请使用ULog,不要使用System.out.println等");return true;}JavaParser.ResolvedNode resolve = context.resolve(node);if (resolve instanceof JavaParser.ResolvedMethod) {JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolve;// 方法所在的类校验JavaParser.ResolvedClass containingClass = method.getContainingClass();if (resolve.getName().equals("v")||resolve.getName().equals("d")||resolve.getName().equals("i")||resolve.getName().equals("w")||resolve.getName().equals("e")||resolve.getName().equals("wtf")){if (containingClass.matches(CHECK_PACKAGE)) {context.report(ISSUE, node, context.getLocation(node),ISSUE_DESCRIPTION+",请使用ULog,避免使用Log");return true;}}}return super.visitMethodInvocation(node);}};}}

Android lint检查相关推荐

  1. Android Lint 检查规则的定制(基本篇)

    本人博客原文 英文原文: http://tools.android.com/tips/lint/suppressing-lint-warnings http://tools.android.com/r ...

  2. android lint 安全检测,Android Lint检查

    1.检查原理 定制自己的lint.jar,放置到 build/intermediates/lint文件夹下或者放置到.android/lint文件夹下,后续执行的lint检查都会自动包含自定义lint ...

  3. Android 系统(174)---Android代码分析lint检查篇

    Android代码分析lint检查篇 1.什么是lint检查?   Android lint检查是一个静态代码分析工具,它能够对你的Android项目中潜在的bug,可优化的代码,安全性,性能,可用性 ...

  4. 【Android】lint检查

    1 Android lint 检查 Android lint是一个静态代码分析工具. 它会对我们的代码进行扫描和检查,提前发现问题,通过lint tool工具输出一个文件,告诉我们哪行代码有问题. 具 ...

  5. Android Lint简介

    本人博客原文 英文原文:http://tools.android.com/tips/lint 参照文章:http://blog.csdn.net/thl789/article/details/8037 ...

  6. 【Android 安装包优化】移除无用资源 ( 自动移除无用资源 | 直接引用资源 | 动态获取资源 id | Lint 检查资源 )

    文章目录 一.自动移除无用资源 ( 不推荐使用 ) 二.直接引用资源与动态获取资源 1.直接引用资源 2.动态获取资源 id 三.Lint 检查资源 四.参考资料 一.自动移除无用资源 ( 不推荐使用 ...

  7. 美团外卖Android Lint代码检查实践

    概述 Lint是Google提供的Android静态代码检查工具,可以扫描并发现代码中潜在的问题,提醒开发人员及早修正,提高代码质量.除了Android原生提供的几百个Lint规则,还可以开发自定义L ...

  8. Android自定义Lint检查-CustomLint

    仓库地址 背景 1.大多代码规范都浮于表面,全靠开发自觉和Code Review来保障导致很多遗留的老大难问题. 2.基础模块很多规范只能通过注释或者文档来约束. 相关文档 安卓自定义lint实现 L ...

  9. Android Lint代码检查实践

    1. 为啥用Lint 平时开发中我们在提mr的时候都会进行review,但有些问题通过人眼去看很难发现,比如Fragment必须有空参构造函数,因为在内存不足的时候Fragment恢复默认是通过反射调 ...

最新文章

  1. linux搭建markdown服务,Markdown新手快速入门基础教程及Ubuntu下的安装
  2. 组件Refs(操作DOM的2⃣️两种方法)
  3. 全国计算机等级考试题库二级C操作题100套(第07套)
  4. java gc堆中的分区_jvm内存各个区域详解
  5. python split 正则_Python 正则表达式:split
  6. Winform开发之SqlCommand常用属性和方法
  7. [原]android解析pdf文件muPdf
  8. 既然谭浩强的C语言教材不好,那应该选什么书作C语言教材?
  9. 【深度学习环境搭建<三>】Ubuntu 中Anaconda + Pycharm 开发环境安装
  10. D - Molar mass
  11. win10升级工具_win10系统易升的卸载技巧
  12. xgboost输出模型解释
  13. [贴装专题] 基于halcon的最小二乘法计算吸嘴或机械轴旋转中心
  14. 记一次DllNotFoundException(缺少vs C++ 环境导致)
  15. taglib.class.php,thinkphp5 taglib标签库自定义
  16. 梦三花重金修改服务器,B站梦花BILIBILI挂机助手 – 9.10更新
  17. 关于HP WebInspect 9.1
  18. 基于计算机视觉的水果分级检测系统的设计
  19. 『转』卡巴斯基2014 安装使用小技巧
  20. 虚函数表 以及 虚函数表的继承过程

热门文章

  1. java自动化分页_Python+Selenium自动化实现分页(pagination)处理
  2. 深度学习项目四: 实现自己的中文分词模型,基于双向的LSTM(含数据和所需源码)
  3. 年前最后一趟车,来年要少开车、慎开车
  4. 我们如何提升自己的数据洞察力?
  5. 听说大家都在用这个TikTok数据分析工具...
  6. 计算机在学前教育和美术绘画中的应用,版画在学前教育专业美术课中的运用
  7. php面试常问的题目2
  8. xftp连接ftp出现乱码问题
  9. Python实现骰子作画算法
  10. 软件质量保证与测试 实验一:白盒测试用例设计 实验报告,白盒测试和黑盒测试实验报告.doc...