Common rules and macros for Grab's Android projects built with Bazel.

Overview

Grab Bazel Common Android

Common rules and macros for Grab's Android projects built with Bazel. This repo provides rules and macros to support some of Android Gradle Plugin features in Bazel.

The repo also hosts a patched Bazel Android Tools jar with fixes for build reproducibility and databinding applied. See /patches for details.

The rules are used by Grazel - Gradle plugin to automate migration to Bazel.

Usage

In WORKSPACE file,

load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")

git_repository(
    name = "grab_bazel_common",
    commit = "",
    remote = "https://github.com/grab/grab-bazel-common.git",
)

# Optional patched Android Tools
load("@grab_bazel_common//:workspace_defs.bzl", "android_tools")

android_tools(
    commit = "",
    remote = "https://github.com/grab/grab-bazel-common.git",
)

# Maven dependencies
load("@grab_bazel_common//:workspace_defs.bzl", "GRAB_BAZEL_COMMON_ARTIFACTS")

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    artifacts = GRAB_BAZEL_COMMON_ARTIFACTS + [
        # ... 
    ],
    ...
)

Features

Build Config Fields

Build Config support for android projects

 load("@grab_bazel_common//tools/build_config:build_config.bzl", "build_config")

 build_config(
     name = "feature-toggle-build-config",
     package_name = "com.grab.featuretoggle",
     strings = {
         "ID": "Hello",
     },
     ints = {},
     longs = {},
     strings = {},
 )

Res values

resValue strings support for Android Projects

 load("@grab_bazel_common//tools/res_value:res_value.bzl", "res_value")
 # Define resValues
 res_value(
     name = "app-res-value",
     custom_package = "com.grab.playground",
     manifest = "src/main/AndroidManifest.xml",
     strings = {
         "prefix": "app",
         "field": "debug"
     },
 )
 
 # Usage of defined resValues
 android_library(
     deps = [
         ":app-res-value",
         ...
     ],
 )

Databinding

Provides a macro which in most cases can be used as a drop-in replacement to kt_android_library to enable support for Kotlin code when using databinding. Details.

load("@grab_bazel_common//tools/databinding:databinding.bzl", "kt_db_android_library")

kt_db_android_library(
    name = "module",
    srcs = glob([
        "src/main/java/com/grab/module/**/*.kt",
    ]),
    assets = glob([
        "src/main/assets/empty_file.txt",
    ]),
    assets_dir = "src/main/assets",
    custom_package = "com.grab.module",
    manifest = "src/main/AndroidManifest.xml",
    resource_files = glob([
        "src/main/res/**",
    ]),
    visibility = [
        "//visibility:public",
    ],
    deps = [
        "@maven//:io_reactivex_rxjava2_rxjava",
    ],
)

Custom Resource Sets

Bazel expects certain Android resource folder structure (should start with res/) and this can conflict with Android Gradle plugin's custom resource source set feature which does not have this validation. This macro helps to adapt the folder to Bazel expected structure so both build systems can function.

In Gradle, if you have:

sourceSets {
    debug {
        res.srcDirs += "src/main/res-debug"
    }
}

the Bazel equivalent would be:

load("@grab_bazel_common//tools/custom_res:custom_res.bzl", "custom_res")

android_binary(
    name = "app",
    custom_package = "com.grab.playground",
    manifest = "src/main/AndroidManifest.xml",
    resource_files = glob([
        "src/main/res/**",
    ]) + custom_res( # Wrap the folder with custom_res macro
        dir_name = "res-debug",
        resource_files = glob([
            "src/main/res-debug/**",
        ]),
        target = "app",
    ),
)

License

Copyright 2021 Grabtaxi Holdings PTE LTE (GRAB)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Replace styleable parent name separator from dot to underscore

    Replace styleable parent name separator from dot to underscore

    To handle parent name with dot.

    XML:

    <declare-styleable name="BaseTheme.AppTheme">
            <attr name="CheckboxDefaultStyle" format="reference"/>
    </declare-styleable>
    

    error message:

    r-classes/com/albertjanuar/android/arjuna/R.java:7659: error: unexpected token: .
        public static int BaseTheme.AppTheme_CheckboxDefaultStyle = 0;
    
    bug 
    opened by ajanuar 4
  • Initial work to support non transitive R class with Databinding 7.1.0

    Initial work to support non transitive R class with Databinding 7.1.0

    • Rebase with Databinding 7.1.0
    • Implement package aware R.txt in Bazel
    • No longer need to pass R.txt to generate stubs since once non transitive R class is enabled, each target's Kotlin code can only contain local module R imports.
    • Make R.txt more lenient to allow parsing package-aware R.txt
    enhancement 
    opened by arunkumar9t2 3
  • Fix class_info.to_list()

    Fix class_info.to_list()

    The first commit addresses a crash. On master, with Bazel 4.2.2 (I'm not sure if this was a change stemming from Bazel 4):

    $ bazel build //...
    DEBUG: /private/var/tmp/_bazel_p/a48d838470da09ddcc3c8b96c3b3efad/external/io_bazel_rules_kotlin/kotlin/kotlin.bzl:116:10: kt_jvm_library should be loaded from //kotlin:jvm.bzl
    DEBUG: /private/var/tmp/_bazel_p/a48d838470da09ddcc3c8b96c3b3efad/external/io_bazel_rules_kotlin/kotlin/kotlin.bzl:116:10: kt_jvm_library should be loaded from //kotlin:jvm.bzl
    DEBUG: /private/var/tmp/_bazel_p/a48d838470da09ddcc3c8b96c3b3efad/external/io_bazel_rules_kotlin/kotlin/kotlin.bzl:116:10: kt_jvm_library should be loaded from //kotlin:jvm.bzl
    ERROR: /Users/p/Code/examples/bazel-kt-databinding-crash/BUILD:17:22: in databinding_stubs rule //:app_lib-stubs:
    Traceback (most recent call last):
    	File "/private/var/tmp/_bazel_p/a48d838470da09ddcc3c8b96c3b3efad/external/grab_bazel_common/tools/databinding/databinding_stubs.bzl", line 54, column 68, in _databinding_stubs_impl
    		for class_info in target[DataBindingV2Info].class_infos.to_list():
    Error: 'list' value has no field or method 'to_list'
    ERROR: Analysis of target '//:r-classes' failed; build aborted: Analysis of target '//:app_lib-stubs' failed
    INFO: Elapsed time: 15.201s
    INFO: 0 processes.
    FAILED: Build did NOT complete successfully (12 packages loaded, 721 targets configured)
    

    This PR also changes the import path for kt_jvm_library to remove the debug messages from rules_kotlin. LMK if you'd rather have that in a separate PR—happy to split it out.

    enhancement 
    opened by pswaminathan 2
  • style attribute not found (kt_db_android_library)

    style attribute not found (kt_db_android_library)

    Hello guys, I am using Bazel rule kt_db_android_library and found broken compilation. Any idea how to fix this?

    load("@grab_bazel_common//tools/build_config:build_config.bzl", "build_config")
    load("@grab_bazel_common//tools/databinding:databinding.bzl", "kt_db_android_library")
    
    build_config(
        name = "arjuna-build-config",
        package_name = "com.albertjanuar.android.arjuna",
        strings = {
            "VERSION_CODE": "250",
            "VERSION_NAME": "3.37.0",
        },
    )
    
    kt_db_android_library(
        name = "arjuna",
        srcs = glob([
            "src/main/java/**/*.kt",
            "src/main/java/**/*.java"
        ]),
        manifest = "src/main/AndroidManifest.xml",
        custom_package = "com.albertjanuar.android.arjuna",
        resource_files = glob([
            "src/main/res/**",
        ]),
        visibility = [
            "//visibility:public", 
        ],
        deps = [
            ":arjuna-build-config",
            "//bazel:parceler",
            "//icons:icons",
            "@maven//:androidx_appcompat_appcompat", 
            "@maven//:androidx_recyclerview_recyclerview",
            "@maven//:com_google_android_material_material",
            "@maven//:org_apache_commons_commons_lang3",
        ]
    )
    

    output:

    Output:
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:46: error: style attribute 'attr/accentDark (aka com.albertjanuar.android.arjuna:attr/accentDark)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:47: error: style attribute 'attr/accentLight (aka com.albertjanuar.android.arjuna:attr/accentLight)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:44: error: style attribute 'attr/accentPrimary (aka com.albertjanuar.android.arjuna:attr/accentPrimary)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:76: error: style attribute 'attr/accentPrimaryTranslucent (aka com.albertjanuar.android.arjuna:attr/accentPrimaryTranslucent)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:45: error: style attribute 'attr/accentSecondary (aka com.albertjanuar.android.arjuna:attr/accentSecondary)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:71: error: style attribute 'attr/borderDivide (aka com.albertjanuar.android.arjuna:attr/borderDivide)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:70: error: style attribute 'attr/borderSubtle (aka com.albertjanuar.android.arjuna:attr/borderSubtle)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:37: error: style attribute 'attr/brand (aka com.albertjanuar.android.arjuna:attr/brand)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:56: error: style attribute 'attr/darkNeutral (aka com.albertjanuar.android.arjuna:attr/darkNeutral)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:80: error: style attribute 'attr/darkNeutralTranslucent (aka com.albertjanuar.android.arjuna:attr/darkNeutralTranslucent)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:54: error: style attribute 'attr/darkPrimary (aka com.albertjanuar.android.arjuna:attr/darkPrimary)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:57: error: style attribute 'attr/darkSecondary (aka com.albertjanuar.android.arjuna:attr/darkSecondary)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:55: error: style attribute 'attr/darkStain (aka com.albertjanuar.android.arjuna:attr/darkStain)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:51: error: style attribute 'attr/lightNeutral (aka com.albertjanuar.android.arjuna:attr/lightNeutral)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:78: error: style attribute 'attr/lightNeutralTranslucent (aka com.albertjanuar.android.arjuna:attr/lightNeutralTranslucent)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:49: error: style attribute 'attr/lightPrimary (aka com.albertjanuar.android.arjuna:attr/lightPrimary)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:77: error: style attribute 'attr/lightPrimaryTranslucent (aka com.albertjanuar.android.arjuna:attr/lightPrimaryTranslucent)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:52: error: style attribute 'attr/lightSecondary (aka com.albertjanuar.android.arjuna:attr/lightSecondary)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:79: error: style attribute 'attr/lightSecondaryOpaque (aka com.albertjanuar.android.arjuna:attr/lightSecondaryOpaque)' not found.
    bazel-out/darwin-fastbuild/bin/arjuna/databinding-processed-resources/arjuna/arjuna/src/main/res/values/core-styles.xml:50: error: style attribute 'attr/lightStain (aka com.albertjanuar.android.arjuna:attr/lightStain)' not found.
    
    	at com.google.devtools.build.android.CommandHelper.execute(CommandHelper.java:42)
    	at com.google.devtools.build.android.AaptCommandBuilder.execute(AaptCommandBuilder.java:297)
    	at com.google.devtools.build.android.aapt2.ResourceLinker.linkStatically(ResourceLinker.java:251)
    	at com.google.devtools.build.android.ValidateAndLinkResourcesAction.main(ValidateAndLinkResourcesAction.java:207)
    	at com.google.devtools.build.android.ResourceProcessorBusyBox$Tool$7.call(ResourceProcessorBusyBox.java:105)
    	at com.google.devtools.build.android.ResourceProcessorBusyBox.processRequest(ResourceProcessorBusyBox.java:234)
    	at com.google.devtools.build.android.ResourceProcessorBusyBox.main(ResourceProcessorBusyBox.java:177)
    

    thanks!

    needs info 
    opened by ajanuar 2
  • Add R type for navigation

    Add R type for navigation

    It isn't part of the spec, but this type is used in androidx.navigation. Without this, modules using androidx.navigation won't build.

    (Feel free to reject if you aren't interested in supporting this as a use case; it's easy enough to keep as a fork.)

    enhancement 
    opened by pswaminathan 1
  • List of custom type not imported in generated binding

    List of custom type not imported in generated binding

    Repro here. I see in bazel-out/android-armeabi-v7a-fastbuild/bin/app/_javac/app_lib-kotlin/app_lib-kotlin-java_tmp/com/example/databinding/lib/databinding (note the lack of imports):

    package com.example.databinding.lib.databinding;
    
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.databinding.Bindable;
    import androidx.databinding.ViewDataBinding;
    import java.lang.Object;
    
    public abstract class ActivityMainBinding extends ViewDataBinding {
      @Bindable
      protected int mItem;
    
      @Bindable
      protected Object mItemContext;
    
      @Bindable
      protected List<MyModel> mMyObjects;
    
      @Bindable
      protected int mPosition;
    
      @Bindable
      protected int mVisibility;
    
      protected ActivityMainBinding(Object _bindingComponent, View _root, int _localFieldCount) {
        super(_bindingComponent, _root, _localFieldCount);
      }
    
      @NonNull
      public static ActivityMainBinding bind(View view) {
        throw new RuntimeException("Stub!");
      }
    
      @NonNull
      public static ActivityMainBinding bind(View view, Object component) {
        throw new RuntimeException("Stub!");
      }
    
      @Nullable
      public int getItem() {
        throw new RuntimeException("Stub!");
      }
    
      @Nullable
      public Object getItemContext() {
        throw new RuntimeException("Stub!");
      }
    
      @Nullable
      public List<MyModel> getMyObjects() {
        throw new RuntimeException("Stub!");
      }
    
      @Nullable
      public int getPosition() {
        throw new RuntimeException("Stub!");
      }
    
      @Nullable
      public int getVisibility() {
        throw new RuntimeException("Stub!");
      }
    
      @NonNull
      public static ActivityMainBinding inflate(LayoutInflater inflater) {
        throw new RuntimeException("Stub!");
      }
    
      @NonNull
      public static ActivityMainBinding inflate(LayoutInflater inflater, ViewGroup root,
          boolean attachToRoot) {
        throw new RuntimeException("Stub!");
      }
    
      @NonNull
      public static ActivityMainBinding inflate(LayoutInflater inflater, ViewGroup root,
          boolean attachToRoot, Object component) {
        throw new RuntimeException("Stub!");
      }
    
      public abstract void setItem(int var1);
    
      public abstract void setItemContext(Object var1);
    
      public abstract void setMyObjects(List<MyModel> var1);
    
      public abstract void setPosition(int var1);
    
      public abstract void setVisibility(int var1);
    }
    
    opened by pswaminathan 1
  • Add buildifier_binary that is configured via toolchains

    Add buildifier_binary that is configured via toolchains

    Add buildifier_binary rule for executing buildifier where it's binary is downloaded using toolchains which selects the correct os type and arch.

    Usage

    in WORKSPACE add the following

    load("@grab_bazel_common//tools/buildifier:defs.bzl", "buildifier_register_toolchains")
    buildifier_register_toolchains(version = "5.0.0")
    

    followed by executing the following

    bazelisk run @grab_bazel_common//:buildifier -- {ARGS}
    

    Another alternative is to add the following in the BUILD.bazel in the root directory where WORKSPACE file is

    load("@grab_bazel_common//tools/buildifier:rules.bzl", "buildifier_binary")
    
    buildifier_binary(
      name = "buildifier",
    )
    

    this will allow you to execute the following command

    bazelisk run //:buildifier -- {ARGS}
    
    opened by minkuan88 1
  • Prefix R classes with name to avoid conflicts

    Prefix R classes with name to avoid conflicts

    Without this, using two kt_db_android_library targets in the same package fails with:

    	File "/mypath/app/BUILD.bazel", line 251, column 22, in <toplevel>
    		kt_db_android_library(
    	File "/private/var/tmp/_bazel_p/c1a9d93c5d307e720ae1d0573bce325b/external/grab_bazel_common/tools/databinding/databinding.bzl", line 89, column 24, in kt_db_android_library
    		native.java_library(
    Error in java_library: java_library rule 'r-classes' in package 'app' conflicts with existing java_library rule, defined at /mypath/app/BUILD.bazel:230:22
    
    opened by pswaminathan 1
  • Issue using Kotlin BindingAdapters

    Issue using Kotlin BindingAdapters

    Sample code here. Without this change, the project builds. Looks like there are two things:

    1. Stubs compilation failing
    2. Moshi Kotlin Codegen plugin not running

    Build output:

    ERROR: /Users/p/Code/examples/bazel-kt-databinding-crash/app/BUILD:32:22: KotlinCompile //app:app_lib-kotlin { kt: 9, java: 0, srcjars: 1 } for darwin_arm64 failed: (Exit 1): build failed: error executing command bazel-out/host/bin/external/io_bazel_rules_kotlin/src/main/kotlin/build '--flagfile=bazel-out/darwin_arm64-fastbuild/bin/app/app_lib-kotlin-kt-java.jar-0.params'
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                      ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                    ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                     ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                         ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                           ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                     ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                       ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                                  ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                                    ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                                         ^
    app/src/main/java/com/example/databinding/Api.kt:5:19: error: unresolved reference: UpdatesJsonAdapter
    fun dealWith(uja: UpdatesJsonAdapter) {}
                      ^
    Jan 01, 2022 10:20:03 PM worker request 0
    SEVERE: Compilation failure: compile phase failed:
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                      ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                    ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                     ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                         ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                           ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                     ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                       ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                                  ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                                    ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                                         ^
    /private/var/tmp/_bazel_p/a48d838470da09ddcc3c8b96c3b3efad/execroot/__main__/app/src/main/java/com/example/databinding/Api.kt:5:19: error: unresolved reference: UpdatesJsonAdapter
    fun dealWith(uja: UpdatesJsonAdapter) {}
                      ^
    io.bazel.kotlin.builder.toolchain.CompilationStatusException: compile phase failed:
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                      ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                    ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                     ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                         ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                           ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                     ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                       ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                                  ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: not a statement
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                                    ^
    error: /private/var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd13981900757377101490/_kotlinc/app-app_lib-kotlin_jvm/generated_java_sources/com/example/databinding/com_example_databinding_Binding_Adapter_Stub.java:22: error: ';' expected
        DataBindingPagedListAdapter<T>.setPagedItems(view, itemLayout, itemContext, items);
                                                                                         ^
    /private/var/tmp/_bazel_p/a48d838470da09ddcc3c8b96c3b3efad/execroot/__main__/app/src/main/java/com/example/databinding/Api.kt:5:19: error: unresolved reference: UpdatesJsonAdapter
    fun dealWith(uja: UpdatesJsonAdapter) {}
                      ^
    	at io.bazel.kotlin.builder.toolchain.CompilationTaskContext.executeCompilerTask(CompilationTaskContext.kt:130)
    	at io.bazel.kotlin.builder.toolchain.CompilationTaskContext.executeCompilerTask$default(CompilationTaskContext.kt:114)
    	at io.bazel.kotlin.builder.tasks.jvm.Compilation_taskKt$runPlugins$1.invoke(compilation_task.kt:182)
    	at io.bazel.kotlin.builder.tasks.jvm.Compilation_taskKt$runPlugins$1.invoke(compilation_task.kt:166)
    	at io.bazel.kotlin.builder.toolchain.CompilationTaskContext.execute(CompilationTaskContext.kt:148)
    	at io.bazel.kotlin.builder.toolchain.CompilationTaskContext.execute(CompilationTaskContext.kt:140)
    	at io.bazel.kotlin.builder.tasks.jvm.Compilation_taskKt.runPlugins(compilation_task.kt:166)
    	at io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor.execute(KotlinJvmTaskExecutor.kt:54)
    	at io.bazel.kotlin.builder.tasks.KotlinBuilder.executeJvmTask(KotlinBuilder.kt:232)
    	at io.bazel.kotlin.builder.tasks.KotlinBuilder.build(KotlinBuilder.kt:130)
    	at io.bazel.kotlin.builder.tasks.CompileKotlin.invoke(CompileKotlin.kt:27)
    	at io.bazel.worker.PersistentWorker$compileWork$2$result$1.invoke(PersistentWorker.kt:96)
    	at io.bazel.worker.PersistentWorker$compileWork$2$result$1.invoke(PersistentWorker.kt:94)
    	at io.bazel.worker.WorkerContext$TaskContext.resultOf(WorkerContext.kt:128)
    	at io.bazel.worker.WorkerContext.doTask(WorkerContext.kt:156)
    	at io.bazel.worker.PersistentWorker$compileWork$2.invokeSuspend(PersistentWorker.kt:94)
    	at io.bazel.worker.PersistentWorker$compileWork$2.invoke(PersistentWorker.kt)
    	at io.bazel.worker.PersistentWorker$compileWork$2.invoke(PersistentWorker.kt)
    	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
    	at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:165)
    	at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)
    	at io.bazel.worker.PersistentWorker.compileWork(PersistentWorker.kt:93)
    	at io.bazel.worker.PersistentWorker.access$compileWork(PersistentWorker.kt:45)
    	at io.bazel.worker.PersistentWorker$start$1$1$1$1$2$1.invokeSuspend(PersistentWorker.kt:71)
    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)Target //app:app_lib failed to build
    Use --verbose_failures to see the command lines of failed build steps.
    INFO: Elapsed time: 31.103s, Critical Path: 4.31s
    INFO: 7 processes: 2 internal, 4 darwin-sandbox, 1 worker.
    FAILED: Build did NOT complete successfully
    
    bug 
    opened by pswaminathan 1
  • Duplicate declaration of field in R.java

    Duplicate declaration of field in R.java

    $ bazel build //...
    INFO: Analyzed 8 targets (55 packages loaded, 1551 targets configured).
    INFO: Found 8 targets...
    ERROR: /Users/p/Code/examples/bazel-kt-databinding-crash/BUILD:17:22: Compiling Java headers libr-classes-hjar.jar (1 source jar) failed: (Exit 1): java failed: error executing command external/remotejdk11_macos_aarch64/bin/java -Xverify:none -XX:+UseParallelOldGC -XX:-CompactStrings '--patch-module=java.compiler=external/remote_java_tools_darwin/java_tools/java_compiler.jar' ... (remaining 35 argument(s) skipped)
    
    Use --sandbox_debug to see verbose messages from the sandbox
    com/example/databinding/lib/R.java:4757: error: duplicate declaration of field: Spinner_android_entries
        public static int Spinner_android_entries = 0;
                          ^
    INFO: Elapsed time: 43.073s, Critical Path: 11.77s
    INFO: 298 processes: 43 internal, 254 darwin-sandbox, 1 worker.
    FAILED: Build did NOT complete successfully
    

    This is after applying the patch in #14 . Files at this PR, this commit

    opened by pswaminathan 1
  • Accept names with colon for XML namespace

    Accept names with colon for XML namespace

    It is not uncommon to have attrs defined on a custom view that are in the Android XML NS, e.g.

    <resources>
        <declare-styleable name="IconToggleButton">
            <attr name="android:drawableTint" format="reference" />
            <attr name="icon" format="reference" />
            <attr name="colorTheme" format="enum">
                <enum name="DEFAULT" value="0" />
                <enum name="DARK" value="1" />
                <enum name="CREAM" value="2" />
            </attr>
            <attr name="themeCream" format="boolean" />
            <attr name="themeDark" format="boolean" />
        </declare-styleable>
    </resources>
    

    android:drawableTint here lets users set familiar attributes on custom views.

    In order to support this, Gradle converts it to, in R.txt:

    int styleable IconToggleButton_android_drawableTint 5
    

    This suggests that the right way to account for it is to replace invalid characters with an underscore. It is possible there are more than this that should be allowed, but colon at least is probably indicative of an XML namespace, so it should be valid.

    Fixes #13

    opened by pswaminathan 1
  • Fix compatibility with Bazel 6.0

    Fix compatibility with Bazel 6.0

    ERROR: Traceback (most recent call last):
            File "/Users/mohammad.khaleghi/StudioProjects/grab/grab-bazel-common/WORKSPACE", line 21, column 20, in <toplevel>
                    kotlin_repositories()
            File "/private/var/tmp/_bazel_mohammad.khaleghi/5dd2ed53bdcf2520d3af415e6cc5931f/external/io_bazel_rules_kotlin/src/main/starlark/core/repositories/initialize.bzl", line 96, column 21, in kotlin_repositories
                    rules_repository(
    Error in repository_rule: invalid user-provided repo name '': valid names may contain only A-Z, a-z, 0-9, '-', '_', '.', and must start with a letter
    ERROR: Error computing the main repository mapping: at /private/var/tmp/_bazel_mohammad.khaleghi/5dd2ed53bdcf2520d3af415e6cc5931f/external/io_bazel_rules_kotlin/kotlin/core.bzl:2:5: at /private/var/tmp/_bazel_mohammad.khaleghi/5dd2ed53bdcf2520d3af415e6cc5931f/external/io_bazel_rules_kotlin/kotlin/internal/opts. 
    
    • [ ] Update rules kotlin
    • [ ] Remote deprecated bazelrc entries
    bug 
    opened by arunkumar9t2 1
  • Deferred files causing stochastic build failures

    Deferred files causing stochastic build failures

    We have a project with 317 layout .xml files (maybe the large number is relevant).

    In CI and occasionally locally, the build fails because the generated stubs source jar for layout bindings has an empty file at the root instead of the valid generate file.

    For example:

     unzip -l bazel-bin/path/to/app/lib_dev-stubs_binding.srcjar | grep FragmentFoo
            0  1980-02-01 00:00   FragmentFooBinding.java
         1715  1980-02-01 00:00   com/ourcompany/databinding/FragmentFoo2Binding.java
    

    In the above example, you'll see that FragmentFoo2Binding.java is in the correct spot and has a valid size. But FragmentFooBinding.java is empty and isn't at the proper path.

    If I set verbose=true for the SourceJarCreator, I'll see that we're hitting this line: https://github.com/grab/grab-bazel-common/blob/987bb4ef56aa331ca0b3c10233baef99def7b7b3/tools/db-compiler-lite/src/main/java/com/grab/databinding/stub/util/jars/SourceJarCreator.kt#L163

    for FragmentFooBinding. And the body will be empty.

    One workaround I see is to re-read the file when visiting deferred files.

    For example:

            filenameHelper.visitDeferredEntries { path, jarFilename, bytes ->
                if (jarFilename == null) {
                    val newBytes = Files.readAllBytes(path) // ADDED THIS
                    if (verbose) {
                        val body = newBytes.toString(Charset.defaultCharset())
                        System.err.println("""could not determine jar entry name for $path. Body:\n$body}""")
                        addEntry(path.fileName.toString(), path, newBytes)
                    } else {
                        // if not verbose silently add files at the root.
                        addEntry(path.fileName.toString(), path, newBytes)
                    }
                } else {
                    System.err.println("adding deferred source file $path -> $jarFilename")
                    addEntry(jarFilename, path, bytes)
                }
            }
    

    Perhaps something about bazel causes this file not to be available yet in the first go around? If it's not the sheer number of layout files, maybe it is something in my .bazelrc?

    bug 
    opened by aptenodytes-forsteri 6
  • Explore if non databinding modules can also use the stub compiler approach

    Explore if non databinding modules can also use the stub compiler approach

    rules_kotlin currently deploys a sandwich library to allow for Kotlin + android resources compilation which is bit of an atypical setup that involves exporting as well. Since our own kt_db_android_library is able to use stubs to compile Kotlin classes successfully with small bit of work we could use it for non databinding modules as well. The new approach might also allow us to compile actual resources processing from android_library and our stub R class + kt_jvm_library in parallel.

    We might only see proper benefits if we implement #5 worker support but worth a try.

    enhancement 
    opened by arunkumar9t2 0
  • Consider generating R class bytecode directly.

    Consider generating R class bytecode directly.

    Currently stub compiler generates R.java and other databinding classes for Kotlin compilation to work. The R.java in particular is compiled independently to allow not link it in runtime using never_link. This can be avoided by simply generating the R class as .class file using Java bytecode manipulation and pass it to Kotlin target via a JavaInfo provider.

    On large modules R class compilation will not be a botteneck.

    enhancement 
    opened by arunkumar9t2 0
  • Publishing compatibility

    Publishing compatibility

    Two relatively small changes that were needed to integrate with our project. Feel free to close this PR if these changes divert from your strategy, but figured I'd contribute back what was necessary for me.

    1. Add JVM resources as parameter to the kt_db_android_library macro and pass to the underlying kt_jvm_library.

    2. Only apply tags to the final target to ensure that intermediate targets are bundled properly when capturing the transitive closure.

    This is a consequence of how the vaticle/bazel-distribution publishing rules capture the transitive closure. If the dependency has a maven_coordinates tag, then it will be added to the POM, otherwise it will be bundled into the artifact to publish. So, when the tags are applied to the intermediate targets, they won't be properly bundled into the artifact.

    https://github.com/vaticle/bazel-distribution/blob/a4ff3778d65d6f4c563b70c096d150f7028800ce/maven/rules.bzl#L189-L199

    opened by sugarmanz 2
Owner
Grab
Driving South-east Asia forward!
Grab
Android Template to accelerate the creation of new projects.

Stack What How User Interface Compose Dependency Injection Hilt State Management Mavericks Caching Room Networking Retrofit Information This project i

André Ramon 9 Jan 23, 2022
Built and Tested with emulator

Built and Tested with emulator "Nexus 5". Libraries Used: Volley : For webservices GSON : For saving and retrieving data in shared preferences Picasso

null 0 Nov 2, 2021
Vanced Manager built with official vanced source & my API

Vanced Manager (mirrored) This is a version of Vanced Manager using mirrors that I did myself, since the official APIs were disabled along with the di

Mahin Ahmed 4 Jul 31, 2022
****. Use the native and support library variants instead - https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html. An android library that makes it easy to add custom fonts to edittexts and textviews

Add to your project Add this line to your dependencies in build.gradle compile 'in.workarounds.typography:typography:0.0.8' Using the views There are

Workarounds 43 Nov 6, 2021
SL4A brings scripting languages to Android by allowing you to edit and execute scripts and interactive interpreters directly on the Android device.

#Scripting Layer for Android (SL4A) SL4A brings scripting languages to Android by allowing you to edit and execute scripts and interactive interpreter

Damon Kohler 2.3k Dec 23, 2022
An application for runners and cyclists. Allows you to monitor your physical activity, weight and receive reminders about workouts.

An application for runners and cyclists. Allows you to monitor your physical activity, weight and receive reminders about workouts.

Just_Amalll 3 Feb 7, 2022
A curated list of standards, tests and benchmarks that can be used for testing and evaluating dev-tools

A curated list of standards, tests and benchmarks that can be used for testing and evaluating dev tools Contribution Add the description of the benchm

null 13 Dec 16, 2022
A gradle plugin for getting java lambda support in java 6, 7 and android

Gradle Retrolambda Plugin This plugin will automatically build your java or android project with retrolambda, giving you lambda goodness on java 6 or

Evan Tatarka 5.3k Jan 5, 2023
A Job Queue specifically written for Android to easily schedule jobs (tasks) that run in the background, improving UX and application stability.

Development in this repository is stopped. Future development continues on https://github.com/yigit/android-priority-jobqueue ========================

Path Mobile Inc Pte. Ltd. 2.4k Dec 9, 2022
An android library for displaying fps from the choreographer and percentage of time with two or more frames dropped

DEPRECATED TinyDancer is deprecated. No more development will be taking place. Check out the Google Android developer documentation for UI performance

Friendly Robot 1.9k Jan 3, 2023
📄The reliable, generic, fast and flexible logging framework for Android

logback-android v2.0.0 Overview logback-android brings the power of logback to Android. This library provides a highly configurable logging framework

Tony Trinh 1.1k Jan 8, 2023
It makes a preview from an url, grabbing all the information such as title, relevant texts and images. This a version for Android of my web link preview https://github.com/LeonardoCardoso/Link-Preview

LeoCardz Link Preview for Android It makes a preview from an url, grabbing all the information such as title, relevant texts and images. Visual Exampl

Leonardo Cardoso 420 Nov 19, 2022
A plug and play ;) android library for displaying a "rate this app" dialog

Easy Rating Dialog This lib provides a simple way to display an alert dialog for rating app. Default conditions to show: User opened the app more than

Fernando Martínez 111 Dec 30, 2022
AudioPlayerView is an Android view that loads audio from an url and have basic playback tools.

AudioPlayerView AudioPlayerView is an Android view that loads audio from an url and have basic playback tools. It makes use of the Android MediaPlayer

Hugo Matilla 86 Nov 29, 2022
transai is a localization tool on Android and iOS.

transai transai is a command line tool to help you do Android and iOS translation management. You can extract string files to csv format, or generate

Jintin 56 Nov 12, 2022
This was developed with Android studio and firebase Realtime database

This was developed with Android studio and firebase Realtime database. In this application users are able to see their old result list semester wise. Also they able to pass get analyze about all subject in university. User can predict the GPA value by adding future semester subjects and expected results. Java was used for backend development and XML used for frontend development.

Milinda Ruberu 3 Jul 25, 2021
The QuickJS embeddable Javascript engine packaged for Android and the JVM

The QuickJS embeddable Javascript engine packaged for Android and the JVM

Cash App 1.5k Dec 31, 2022
Android development recommendation for outdated libraries and current libraries preferred as of 2021

GADS21-Android-Recomendation-For currently used libraries and dependencies Android development recommendation for outdated libraries and current libra

Timz Owen 6 Nov 22, 2021
Tutorial For openJDK 11 and AGP 7.0.0+ | Tutorial Multi Library Android in 1 Project | Groovy

jitpack-library-guide For openJDK 11 and AGP 7.0.0 + Please read every single note for detail Tutorial Click Here Kotlin DSL Click Here Repository for

Faisal Amir 7 Dec 10, 2022