android开发规范

这篇博客详细介绍了Android开发的规范,包括资源文件命名、基本组件使用、UI与布局设计、进程线程与消息通信、文件数据库操作、Bitmap和动画处理、安全措施等方面。强调了如避免在BroadcastReceiver中执行耗时操作、禁止隐式Intent广播敏感信息、正确处理Fragment的生命周期以及使用Toast和Adapter的注意事项等关键点。此外,还提出了UI性能优化、安全防护和代码质量提升的建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 资源文件

1,【强制】layout 文件的命名方式
Activity 的 layout 以 module_activity 开头

Fragment 的 layout 以 module_fragment 开头

Dialog 的 layout 以 module_dialog 开头

include 的 layout 以 module_include 开头

ListView 的行 layout 以 module_list_item 开头

RecyclerView 的 item layout 以 module_recycle_item 开头

GridView 的行 layout 以 module_grid_item 开头

2,【强制】drawable 资源名称以小写单词+下划线的方式命名。
模块名_业务功能描述_控件描述_控件状态限定词
如:module_login_btn_pressed,module_tabs_icon_home_normal

3,【强制】style 资源采用小写单词+下划线方式命名,写入 module_styles.xml 文件中,采用以下规则:
父 style 名称.当前 style 名称
4,【强制】string资源文件或者文本用到字符需要全部写入 module_strings.xml文件中,字符串以小写单词+下划线的方式命名,采用以下规则:
模块名_逻辑名称

5,【强制】Id 资源原则上以驼峰法命名,View 组件的资源 id 需要以 View 的缩写作为前缀。常用缩写表如下:
在这里插入图片描述

二 基本组件

Android 基本组件指 Activity、 Fragment、 Service、 BroadcastReceiver、ContentProvider 等等。

1.【强制】Activity#onSaveInstanceState()方法不是 Activity 生命周期方法,也不保证一定会被调用。它是用来在 Activity 被意外销毁时保存 UI 状态的,只能用于保存临时性数据,例如 UI 控件的属性等,不能跟数据的持久化存储混为一谈。持久化存储应该在 Activity#onPause()/onStop()中实行。

  1. 【强制】避免在 BroadcastReceiver#onReceive()中执行耗时操作,如果有耗时工作,应该创建 IntentService 完成,而不应该在 BroadcastReceiver 内创建子线程去做。

    说明:

    由于该方法是在主线程执行,如果执行耗时操作会导致 UI 不流畅。可以使用IntentService 、 创 建 HandlerThread 或 者 调 用 Context#registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)方法等方式,在其他 Wroker 线程执行 onReceive 方法。BroadcastReceiver#onReceive()方法耗时超过 10 秒钟,可能会被系统杀死。

  2. 【强制】禁止使用隐式 Intent 广播敏感信息,信息可能被其他注册了对应BroadcastReceiver 的 App 接收。

    说明:

    通过 Context#sendBroadcast()发送的隐式广播会被所有感兴趣的 receiver 接收,恶意应用注册监听该广播的 receiver 可能会获取到 Intent 中传递的敏感信息,并进行其他危险操作。如果发送的广播为使用 Context#sendOrderedBroadcast()方法发送的有序广播,优先级较高的恶意 receiver 可能直接丢弃该广播,造成服务不可用,或者向广播结果塞入恶意数据。

    如果广播仅限于应用内,则可以使用 LocalBroadcastManager#sendBroadcast()实现,避免敏感信息外泄和 Intent 拦截的风险。

4.【强制】添 加 Fragment 时 , 确 保 FragmentTransaction#commit() 在Activity#onPostResume()或者 FragmentActivity#onResumeFragments()内调用。不要随意使用 FragmentTransaction#commitAllowingStateLoss()来代替,任何commitAllowingStateLoss()的使用必须经过 code review,确保无负面影响。

说明:
Activity 可 能 因 为 各 种 原 因 被 销 毁 , Android 支 持 页 面 被 销 毁 前 通 过Activity#onSaveInstanceState() 保 存 自 己 的 状 态 。 但 如 果FragmentTransaction.commit()发生在 Activity 状态保存之后,就会导致 Activity 重建、恢复状态时无法还原页面状态,从而可能出错。为了避免给用户造成不好的体验,系统会抛出 IllegalStateExceptionStateLoss 异常。推荐的做法是在 Activity 的onPostResume() 或 onResumeFragments() ( 对 FragmentActivity ) 里 执 行FragmentTransaction.commit(),如有必要也可在 onCreate()里执行。不要随意改用FragmentTransaction.commitAllowingStateLoss() 或 者 直 接 使 用 try-catch 避 免crash,这不是问题的根本解决之道,当且仅当你确认 Activity 重建、恢复状态时,本次 commit 丢失不会造成影响时才可这么做。
  1. 【强制】不要在 Activity#onDestroy()内执行释放资源的工作,例如一些工作线程的销毁和停止,因为 onDestroy()执行的时机可能较晚。可根据实际需要,在Activity#onPause()/onStop()中结合 isFinishing()的判断来执行。

  2. 【建议】如非必须,避免使用嵌套的 Fragment。

    说明:

    嵌套 Fragment 是在 Android API 17 添加到 SDK 以及 Support 库中的功能,Fragment 嵌套使用会有一些坑,容易出现 bug,比较常见的问题有如下几种:

    1. onActivityResult()方法的处理错乱,内嵌的 Fragment 可能收不到该方法的回调,需要由宿主 Fragment 进行转发处理;

    2. 突变动画效果;

    3. 被继承的 setRetainInstance(),导致在 Fragment 重建时多次触发不必要的逻辑。

    非必须的场景尽可能避免使用嵌套 Fragment,如需使用请注意上述问题。

  3. 【强制】使用 Toast 时,建议定义一个全局的 ToastUtils 对象,这样可以避免连续显示Toast 时不能取消上一次 Toast 消息的情况(如果你有连续弹出 Toast 的情况,避免使用 Toast.makeText)。

  4. 【强制】Activity或者 Fragment 中动态注册 BroadCastReceiver 时, registerReceiver()和 unregisterReceiver()要成对出现。
    说明:

    如果 registerReceiver()和 unregisterReceiver()不成对出现,则可能导致已经注册的receiver 没有在合适的时机注销,导致内存泄漏,占用内存空间,加重 SystemService负担。

    部分华为的机型会对 receiver 进行资源管控,单个应用注册过多 receiver 会触发管控模块抛出异常,应用直接崩溃。

    Activity 的生命周期不对应,可能出现多次 onResume 造成 receiver 注册多个,但最终只注销一个,其余 receiver 产生内存泄漏。
    9. 在 Application 的业务初始化代码加入进程判断,确保只在自己需要的进程初始化。特别是后台进程减少不必要的业务初始化。
    10.【强制】使用 Adapter 的时候,如果你使用了 ViewHolder 做缓存,在 getView()的方法中无论这项 convertView 的每个子控件是否需要设置属性(比如某个 TextView设置的文本可能为 null,某个按钮的背景色为透明,某控件的颜色为透明等),都需要为其显式设置属性(Textview 的文本为空也需要设置 setText(""),背景透明也需要设置),否则在滑动的过程中,因为 adapter item 复用的原因,会出现内容的显示错乱。

四、UI与布局

  1. 【建议】布局中不得不使用 ViewGroup 多重嵌套时,不要使用 LinearLayout 嵌套,改用 RelativeLayout或ConstraintLayout,可以有效降低嵌套数.

  2. 【建议】在 Activity 中显示对话框或弹出浮层时,尽量使用 DialogFragment,而非Dialog/AlertDialog,这样便于随Activity生命周期管理对话框/弹出浮层的生命周期。

  3. 【强制】源文件统一采用 UTF-8 的形式进行编码。

  4. 【强制】禁止在非 ui 线程进行 view 相关操作。

  5. 【建议】文本大小使用单位 dp,view 大小使用单位 dp。对于 Textview,如果在文字大小确定的情况下推荐使用 wrap_content 布局避免出现文字显示不全的适配问题。

  6. 【强制】禁止在设计布局时多次设置子 view 和父 view 中为同样的背景造成页面过度绘制,推荐将不需要显示的布局进行及时隐藏。

  7. 【强制】不能使用 ScrollView 包裹 ListView/GridView/ExpandableListVIew;因为这样会把 ListView 的所有 Item 都加载到内存中,要消耗巨大的内存和 cpu 去绘制图面。

    说明:

    ScrollView 中嵌套 List 或 RecyclerView 的做法官方明确禁止。除了开发过程中遇到的各种视觉和交互问题,这种做法对性能也有较大损耗。 ListView 等 UI 组件自身有垂直滚动功能,也没有必要在嵌套一层 ScrollView。目前为了较好的 UI 体验,更贴近 Material Design 的设计,推荐使用 NestedScrollView。
    8,公共资源复用

五、进程、线程与消息通信

  1. 【强制】不要通过 Intent 在 Android 基础组件之间传递大数据 ,可能导致 OOM。

六、文件与数据库

  1. 【强制】任何时候不要硬编码文件路径,请使用 Android 文件系统 API 访问。

    说明:

    Android 应用提供内部和外部存储,分别用于存放应用自身数据以及应用产生的用户数据。可以通过相关 API 接口获取对应的目录,进行文件操作。

  2. 【强制】当使用外部存储时,必须检查外部存储的可用性。

  3. 【强制】应用间共享文件时,不要通过放宽文件系统权限的方式去实现,而应使用FileProvider。

  4. 【强制】使用统一封装的MMKV工具替换SP.

七、Bitmap、Drawable与动画

  1. 【强制】本地加载大图片或者一次性加载多张图片,应该在异步线程中进行。图片的加载,涉及到 IO 操作,以及 CPU 密集操作,很可能引起卡顿。

  2. 【强制】png 图片使用 tinypng 或者类似工具压缩处理,减少包体积,资源文件超过500k需要上级审核。

  3. 【强制】使用完毕的图片,应该及时回收,释放宝贵的内存。

  4. 【强制】在 Activity.onPause()或 Activity.onStop()回调中,关闭当前 activity 正在执行的的动画。

八、安全

  1. 【强制】使用 PendingIntent 时,禁止使用空 intent,同时禁止使用隐式 Intent

    说明:

    1. 使用 PendingIntent 时,使用了空 Intent,会导致恶意用户劫持修改 Intent 的内容。禁止使用一个空 Intent 去构造 PendingIntent,构造 PendingIntent 的 Intent一定要设置 ComponentName 或者 action。

    2. PendingIntent 可以让其他 APP 中的代码像是运行自己 APP 中。 PendingIntent的intent接收方在使用该intent时与发送方有相同的权限。在使用PendingIntent时,PendingIntent 中包装的 intent 如果是隐式的 Intent,容易遭到劫持,导致信息泄露。

  2. 【强制】将 android:allowbackup 属性设置为 false,防止 adb backup 导出数据。

    说明:

    在 AndroidManifest.xml 文件中为了方便对程序数据的备份和恢复在 Android APIlevel 8 以后增加了 android:allowBackup 属性值。默认情况下这个属性值为 true,故当 allowBackup 标志值为 true 时,即可通过 adb backup 和 adb restore 来备份和恢复应用程序数据。

  3. 【强制】Receiver/Provider 不能在毫无权限控制的情况下,将 android:export 设置为 true。

4.【强制】 阻止 webview 通过 file:schema 方式访问本地敏感数据。

  1. 【强制】不要广播敏感信息,只能在本应用使用 LocalBroadcast,避免被别的应用收到,或者 setPackage 做限制。

  2. 【强制】对于内部使用的组件,显示设置组件的"android:exported"属性为 false。

    说明:

    Android 应用使用 Intent 机制在组件之间传递数据,如果应用在使用 getIntent(),getAction(),Intent.getXXXExtra()获取到空数据、异常或者畸形数据时没有进行异常捕获,应用就会发生 Crash,应用不可使用(本地拒绝服务)。恶意应用可通过向受害者应用发送此类空数据、异常或者畸形数据从而使应用产生本地拒绝服务。

  3. 【强制】应用发布前确保 android:debuggable 属性设置为 false。

  4. 【强制】使用 Intent Scheme URL 需要做过滤。

    说明:

    如果浏览器支持 Intent Scheme Uri 语法,如果过滤不当,那么恶意用户可能通过浏览器 js 代码进行一些恶意行为,比如盗取 cookie 等。如果使用了 Intent.parseUri函 数 , 获 取 的 intent 必 须 严 格 过 滤 , intent 至 少 包 含addCategory(“android.intent.category.BROWSABLE”) , setComponent(null) ,setSelector(null)3 个策略。

  5. 【强制】密钥加密存储或者经过变形处理后用于加解密运算,切勿硬编码到代码中。

    说明:

    应用程序在加解密时,使用硬编码在程序中的密钥,攻击者通过反编译拿到密钥可以轻易解密 APP 通信数据。

10.【强制】 将所需要动态加载的文件放置在 apk 内部,或应用私有目录中,如果应用必须要把所加载的文件放置在可被其他应用读写的目录中(比如 sdcard),建议对不可信的加载源进行完整性校验和白名单处理,以保证不被恶意代码注入。

11.【强制】 除非 min API level >=17,请注意 addJavascriptInterface 的使用。

说明:

API level>=17,允许 js 被调用的函数必须以@JavascriptInterface 进行注解,因此不受影响; 对于 API level < 16,尽量不要使用 addJavascriptInterface,如果一定要用,那么:

1) 使用 https 协议加载 URL,使用证书校验,防止访问的页面被篡改挂马;

2) 对加载 URL 做白名单过滤、完整性校验等防止访问的页面被篡改;

3) 如果加载本地 html,应该会 HTML 内置在 APK 中,以及对 HTML 页面进行完整性校验。

12.【强制】 对于不需要使用 File 协议的应用,禁用 File 协议,显式设置 webView.getSettings().setAllowFileAccess(false),对于需要使用 File 协议的应用,禁止 File协议调用 JavaScript,显式设置 webView.getSettings().setJavaScriptEnabled(false)。

  1. Android APP 在 HTTPS 通信中,验证策略需要改成严格模式。

    说明: AndroidAPP 在 HTTPS 通信中,使用ALLOW_ALL_HOSTNAME_VERIFIER,表示允许和所有的 HOST 建立 SSL 通信,这会存在中间人攻击的风险,最终导致敏感信息可能会被劫持,以及其他形式的攻击。

  2. 【强制】开放的 activity/service/receiver 等需要对传入的 intent 做合法性校验。

九、其他

  1. 【强制】不要通过 Msg 传递大的对象,会导致内存问题。

  2. 【强制】不能使用 System.out.println 打印 log。

  3. 使用公共的LogUtils 方法进行打印日志

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值