android代码逻辑适配方案总结

总结android有多少种方式做逻辑区分适配。

    1. res/values/xxx.xml,res/values-xxx/xxx.xml

    这种方式类似代码适配,在不同的values文件夹放入相同的名称的字段,配上不同的值;通过屏幕尺寸、方向、语言等方式,不再赘述;

    1. SystemProperties反射

    这种方案常见于apk服役于自制的机器上,属于类似系统开发。通过系统集成的值,或者其他模块或者framework动态调整它,端上逻辑调用来区分代码逻辑。当然普通apk也可以。

    比如SystemUI上有一个开关,动态切换ro.xxx.data=1或者0,端上遇到某个代码执行的时候,就可以反射SystemProperties来区分;

    try {
      Class<?> c = Class.forName("android.os.SystemProperties");
      Method get = c.getMethod("get", String.class, String.class);
      String value = (String) (get.invoke(c, key, defValue));
      return value;
    } catch (Throwable e) {
      e.printStackTrace();
    }
    //类似的getBoolean,getInt有很多自行百度。
    

    备注:

    针对非 SDK 接口的限制 | Android 开发者 | Android Developers

    android9开始每个版本追加一些限制反射的名单。至少SystemProperties是可以使用的。

    查看了android12(别问我怎么就到12了?)的名单。

    屏蔽名单 (blacklist)	无论应用的目标 API 级别是什么,您都无法使用的非 SDK 接口。 如果您的应用尝试访问其中任何一个接口,系统就会抛出错误。
    有条件屏蔽 (greylist-max-x)	
    从 Android 9(API 级别 28)开始,当有应用以该 API 级别为目标平台时,我们会在每个 API 级别分别限制某些非 SDK 接口。
    
    这些名单会以应用无法再访问该名单中的非 SDK 接口之前可以作为目标平台的最高 API 级别 (max-target-x) 进行标记。例如,在 Android Pie 中未被屏蔽、但现在已被 Android 10 屏蔽的非 SDK 接口会列入 max-target-p (greylist-max-p) 名单,其中的“p”表示 Pie 或 Android 9(API 级别 28)。
    
    如果您的应用尝试访问受目标 API 级别限制的接口,系统就会将此 API 视为已列入屏蔽名单。
    
    不支持 (greylist)	当前不受限制且您的应用可以使用的非 SDK 接口。 但请注意,这些接口不受支持,可能会在未发出通知的情况下随时发生更改。预计这些接口在未来的 Android 版本中会被有条件地屏蔽,并列在 max-target-x 名单中。
    SDK (whitelist)	已在 Android 框架软件包索引中正式记录、受支持并且可以自由使用的接口。
    
    Landroid/os/SystemProperties;->get(Ljava/lang/String;)Ljava/lang/String;	sdk	system-api	test-api
    Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;	sdk	system-api	test-api
    Landroid/os/SystemProperties;->getBoolean(Ljava/lang/String;Z)Z	sdk	system-api	test-api
    Landroid/os/SystemProperties;->getInt(Ljava/lang/String;I)I	sdk	system-api	test-api
    Landroid/os/SystemProperties;->getLong(Ljava/lang/String;J)J	sdk	system-api	test-api
    

    说明我们可以放心的使用。

    1. productFlavor+productDimensions

    参考 https://blog.csdn.net/jzlhll123/article/details/116700023

    1. Compiler参数

在Perfercences->搜索Compiler,添加编译参数,-Dxxxx。

任意模块下的build.gradle都可以获取得到,通过build.gradle,android下defaultConfig下面,System.getProperty获取。也可以自定一个函数。在设置属性之前初始化一个环境参数,再行获取设置BuildConfigField即可。

最终该模块下面的BuildConfig.java就能得到这些参数。一定程度上,解决了第3种方式导致编译productflavor+dimens组合太多的尴尬境地。

// Fields from default config.
public static final String Balabala = "false";
public static final boolean USE_SN_MODE = true;

各大公司基本发布都有自带编译脚本,所以只需要如下类似的编译命令即可:

./gradlew assembleDimen1Dimen2Release -Dorg.gradle.java.home=/usr/xxx/jdk1.8.0_25 -Dmyid=10102 -DAPP_ENV=0 -DXXXX=jjj
  1. gradle Task copy

还有一种,就是建立不同的代码目录,通过拷贝的方式覆盖代码。

task myCustomCopyTask(type: Copy) {
    from 'src/customProduct/main'
    // 显式使用任务的 outputs 属性复制任务的输出文件
    into 'src/main'
}

实在迫不得已才使用,实在是不建议这种方式。
有如下几个弊端:

  • 别人或者自己,都容易忘记某个项目需要先执行这个脚本才能再编译;

  • 由于有多份代码,修改共性问题,容易忘记修改copy的那份代码;

  • 提交代码,容易把copy的代码传到主代码中去;

  • search code的时候,太多相同的,改了半天发现改到另外一个里面。
    我还是推荐通过编译属性或者flavor在代码中做硬性判断。

    备注:
    有多少种task:

    /数据源目录,多个目录
    public AbstractCopyTask from(Object... sourcePaths)  
    
    //目标目录,单一
    public AbstractCopyTask into(Object destDir) 
    
    //过滤文件 包含
    public AbstractCopyTask include(String... includes)
    
    //过滤文件 排除
    public AbstractCopyTask exclude(String... excludes)
    
    //重新命名,老名字 新名字
    public AbstractCopyTask rename(String sourceRegEx, String replaceWith)
    
    //删除文件 Project 接口
    boolean delete(Object... paths);
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值