Android更整洁的接入Sonarquebe | initscript 拓展

我们Android工程pipeline阶段需要进行静态扫描或者是资源归属检查之类的gradle任务。这些插件开发同学是不需要感知到。但是由于是用gradle插件实现的,这样就会对build.gradle进行不可避免的侵入,也会不可避免的出现一些条件判断语句。

作者:究极逮虾户
链接:https://juejin.cn/post/7248534178827780154

尤其是sonarquebe这种插件,配置项又贼多,而且一般开发也完全不需要明白是做啥的,万一插件被执行到之后还会拖慢同步时间。有没有什么好的手段来避免掉这些胶水代码呢?

案发现场

如果用标准代码接入工程代码大概如下,我会在根节点的build.gradle内插入如下逻辑。

buildscript {
    repositories {
        mavenCenterl()
    }


    dependencies {
        classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.5.0.2730"
    }
}
// 根据环境配置来区分是不是ci环境
if(System.env.containsKey('CI')){
  pluginManager.apply("org.sonarqube")
  sonarqube {
      properties {
          property "sonar.sourceEncoding", "UTF-8"
          /* if (projectVersion != null) {


               logger.info "${project.path} set sonar.projectVersion=${projectVersion}"
           }*/
          //  property "sonar.projectVersion", projectVersion
          // if (debuggable) {
          property "sonar.verbose", "true"
          property "sonar.cpd.kotlin.minimumLines", 15
          property "sonar.cpd.java.minimumLines", 20
          property "sonar.projectName", sonar.get("projectName")
          property "sonar.projectKey", sonar.get("projectKey")
      }
  }
  subprojects {
      def unittest = project.hasProperty("unittest") ? project.ext["unittest"] : ""
      tasks.whenTaskAdded { task ->
          if (task.name.contains("TestKotlin") || task.name.contains("UnitTest") || task.name.contains("AndroidTest")) {
              enabled = unittest == "true"
              logger.log(LogLevel.INFO, "Temporarily disable test related task: $task")
          }
          if (task.name == "lintDebug") {
              def sonarTask = rootProject.tasks.findByName("sonar")
              if (sonarTask != null) {
                  sonarTask.dependsOn(task)
              }
          }
      }


      afterEvaluate {
          sonarqube {
              properties {
                  property "sonar.androidLint.reportPaths", "${project.buildDir}/reports/lint-results-debug.xml"
                  // detekt.reportPaths
                  // property "sonar.kotlin.detekt.reportPaths", "build/reports/detekt.xml"
                  property "sonar.exclusions", "build/**/*," + "src/main/assets/**/*," + "src/**/*.png,src/**/*.jpg,src/**/*.webp," + "src/**/*.so"
              }
          }
      }
  }
}
xxxxxxxx

这么一大段代码呢就需要存放在build.gradle内,就是非常脏的代码。而且大部分开发同学是完全不需要这些代码的。sonar不仅需要apply一个plugin,同时还有大量的配置文件,同时还需要加入很多环境变量来进行控制。

另外,由于我们工程大概40+的复合构建,需要对每个复合构建进行同样的buildscript导入classpath,我们需要对每个根build.gradle进行调整, 改动量实在是过于可观了。

initscript

Gradle 奇淫技巧之initscript pluginManagement(https://juejin.cn/post/7075671230468063239)

之前有篇文章介绍过这个东西,其实对于sonar我觉得这个真的就完全足够了。而且由于initscript的特殊性,可以给所有的复合构建都添加这部分初始化配置。

首先我们在pipeline阶段会主动执行gradlew sonar这个任务,那么我们也能插入--initscript之后带入这个gradle脚本。

其次因为initscript的代码执行的优先级是最高的,所以我们可以在其提供的dsl中执行rootProject的代码,插入一些buildscript插件。

rootProject {
    buildscript {
        repositories {
            mavenCenterl()
        }


        dependencies {
            classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.5.0.2730"
        }
    }
    // 测试结果告诉我,如果加的太早会导致classloader不是同一个,然后安卓工程就无法被识别
    afterEvaluate {
         pluginManager.apply("org.sonarqube")
         sonarqube {
             properties {
                 property "sonar.sourceEncoding", "UTF-8"
                 /* if (projectVersion != null) {


                      logger.info "${project.path} set sonar.projectVersion=${projectVersion}"
                  }*/
                 //  property "sonar.projectVersion", projectVersion
                 // if (debuggable) {
                 property "sonar.verbose", "true"
                 property "sonar.cpd.kotlin.minimumLines", 15
                 property "sonar.cpd.java.minimumLines", 20
                 property "sonar.projectName", sonar.get("projectName")
                 property "sonar.projectKey", sonar.get("projectKey")
             }
         }
         subprojects {
             def unittest = project.hasProperty("unittest") ? project.ext["unittest"] : ""
             tasks.whenTaskAdded { task ->
                 if (task.name.contains("TestKotlin") || task.name.contains("UnitTest") || task.name.contains("AndroidTest")) {
                     enabled = unittest == "true"
                     logger.log(LogLevel.INFO, "Temporarily disable test related task: $task")
                 }
                 if (task.name == "lintDebug") {
                     def sonarTask = rootProject.tasks.findByName("sonar")
                     if (sonarTask != null) {
                         sonarTask.dependsOn(task)
                     }
                 }
             }


             afterEvaluate {
                 sonarqube {
                     properties {
                         property "sonar.androidLint.reportPaths", "${project.buildDir}/reports/lint-results-debug.xml"
                         // detekt.reportPaths
                         // property "sonar.kotlin.detekt.reportPaths", "build/reports/detekt.xml"
                         property "sonar.exclusions", "build/**/*," + "src/main/assets/**/*," + "src/**/*.png,src/**/*.jpg,src/**/*.webp," + "src/**/*.so"
                     }
                 }
             }
         }
     }
  }

这个就是我们重新生成的一份非常干净的sonar.gradle文件,我们可以在这个gradle很轻松的给工程配置上一些我们所需要的插件,而且这部分代码也仅有pipeline阶段会被执行。

./gradlew --init-script  sonar.gradle sonar

通过上述手段我们就可以把所有逻辑都收在一个sonar.gradle中,然后在initscript中插入就行了。其中sonar.gradle是指相对路径,最后一个sonar则代表着执行的taskname。

这部分调整核心还是按照代码的整洁度角度出发来考虑这个问题的。可以让我们去把一些非开发环境下的配置通过init-script形式插入到工程内去。

还能做些啥

我其实还用--init-script完成了我们pipeline中的增量的UnitTest的逻辑,根据当前的git diff之后,判断变更的模块中是否包含UnitTest然后执行UnitTest

这里的代码也比较脏,但是恰巧因为了--init-script的生命周期最靠前,而且能拿到大部分的回调,另外对于复合构建也是支持的,所以我们就采取了这种手段去开发。

关注我获取更多知识或者投稿

5309ae330dffc5944477ece7fa74fa47.jpeg

0fed8d782d17d7012eee835f97611985.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Studio是一款用于开发Android应用程序的集成开发环境(IDE)。接入穿山甲广告可以通过以下步骤完成: 1. 在项目的build.gradle文件中添加穿山甲广告SDK的依赖: ``` dependencies { implementation 'com.bytedance.sdk:openadsdk:x.x.x' // 替换为最新版本号 } ``` 2. 在AndroidManifest.xml文件中添加穿山甲广告SDK的权限和配置: ```xml <manifest> <!-- 添加网络权限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 添加穿山甲广告SDK的AppID和权限 --> <application> <meta-data android:name="PANGLE_APP_ID" android:value="YOUR_APP_ID" /> <!-- 替换为你的AppID --> <!-- 添加穿山甲广告SDK的Activity --> <activity android:name="com.bytedance.sdk.openadsdk.activity.TTLandingPageActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> </application> </manifest> ``` 3. 在需要展示广告的Activity中,初始化穿山甲广告SDK: ```java import com.bytedance.sdk.openadsdk.TTAdSdk; import com.bytedance.sdk.openadsdk.TTAdConfig; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final String APP_ID = "YOUR_APP_ID"; // 替换为你的AppID @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化穿山甲广告SDK TTAdSdk.init(this, new TTAdConfig.Builder() .appId(APP_ID) .build()); } } ``` 4. 在需要展示广告的位置,加载并展示穿山甲广告: ```java import com.bytedance.sdk.openadsdk.TTAdNative; import com.bytedance.sdk.openadsdk.TTAdNative.NativeExpressAdListener; import com.bytedance.sdk.openadsdk.TTAdNative.NativeExpressAd; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final String AD_SLOT_ID = "YOUR_AD_SLOT_ID"; // 替换为你的广告位ID private TTAdNative mTTAdNative; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化穿山甲广告SDK TTAdSdk.init(this, new TTAdConfig.Builder() .appId(APP_ID) .build()); // 创建TTAdNative对象 mTTAdNative = TTAdSdk.getAdManager().createAdNative(this); // 加载并展示广告 mTTAdNative.loadNativeExpressAd(AD_SLOT_ID, new NativeExpressAdListener() { @Override public void onError(int code, String message) { Log.e(TAG, "onError: " + code + ", " + message); } @Override public void onNativeExpressAdLoad(List<NativeExpressAd> ads) { if (ads != null && ads.size() > 0) { NativeExpressAd ad = ads.get(0); ad.render(); // 渲染广告 // 将广告展示到指定的View中 ViewGroup container = findViewById(R.id.ad_container); container.addView(ad.getExpressAdView()); } } }); } } ``` 以上是使用Android Studio编写接入穿山甲广告的基本步骤。你可以根据自己的需求和穿山甲广告SDK的文档进一步调整和优化广告的展示效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值