如何在我的旧 Android 项目中添加生物识别支持 ​​API (AndroidX)

How to add Biometric support API (AndroidX) in my Old Android Project

SO 在成为 iOS 开发人员 8 年半之后,我在 4 个月前开始学习 andorid,并获得了一个 Cordova andorid 项目供我使用。任务是集成指纹和面容 ID 登录。

我目前的项目(非常老的项目):

构建gradle:2.3.3 gradle 版本:3.3 cordova-android 版本:5.1.4

我知道这些很旧了。

过去 10 天到目前为止我尝试了什么:

我尝试将上面的版本升级到最新版本 gradle 和 gradle 版本。一大堆错误接连出现。

我已经尝试在 build.gradle 和 build-extra.gradle 中一个接一个地添加生物识别支持库 .. 但没有任何效果...

我的问题:

  1. 为什么我不能添加生物识别支持库当我编译所有内容并在构建 gradle 2.3.3 和 gradle 3.3 上正常工作时?

  2. 我是否必须将 gradle 和每个支持库版本更新到最新版本?如果是,那么它会导致代码出现问题吗?假设我使用了任何旧的 UI 组件,当我尝试将旧的支持库与新的生物识别 API 合并时,它会产生编译时错误。我尝试过这个。

  3. 任何人都可以告诉我升级这个项目的步骤,这样即使有编译时错误我也可以删除它们,然后一旦一切正常我可以添加生物识别支持库。

  4. 最后,生物识别支持库可以集成到任何旧项目中,这就是它们被称为支持库的原因。如果我错了,请纠正我。

我在 MAC OSX

上使用 Android studio

以下是文件:

构建-extra.gradle :

 ext.postBuildExtras = {
    android {
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_7
            targetCompatibility JavaVersion.VERSION_1_7
        }
        useLibrary 'org.apache.http.legacy'
    }

    dependencies {
        //compile 'com.google.android.gms:play-services:8.4.0'
        compile 'com.android.support:appcompat-v7:23.3.0'
        compile "com.squareup.picasso:picasso:2.4.0"
        compile "com.android.support:design:25.0.0"
        compile "com.google.firebase:firebase-messaging:9.2.0" //FCM Config
        compile 'com.rmtheis:tess-two:6.0.2'
        compile 'com.github.bumptech.glide:glide:3.8.0'
        compile 'com.android.support:support-v4:19.1.0'
    }
}

build.gradle

// GENERATED FILE! DO NOT EDIT!

apply plugin: 'com.android.application'

buildscript {
    repositories {
        jcenter{ url "http://jcenter.bintray.com/" }
    }

    // Switch the Android Gradle plugin version requirement depending on the
    // installed version of Gradle. This dependency is documented at
    // http://tools.android.com/tech-docs/new-build-system/version-compatibility
    // and https://issues.apache.org/jira/browse/CB-8143
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath "com.google.gms:google-services:3.0.0" //FCM Config

    }
   }


// Allow plugins to declare Maven dependencies via build-extras.gradle.
repositories {
    mavenCentral()
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.8'
}

// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
ext {
    apply from: 'CordovaLib/cordova.gradle'
    // The value for android.compileSdkVersion.
    if (!project.hasProperty('cdvCompileSdkVersion')) {
        cdvCompileSdkVersion = null;
    }
    // The value for android.buildToolsVersion.
    if (!project.hasProperty('cdvBuildToolsVersion')) {
        cdvBuildToolsVersion = null;
    }
    // Sets the versionCode to the given value.
    if (!project.hasProperty('cdvVersionCode')) {
        cdvVersionCode = null
    }
    // Sets the minSdkVersion to the given value.
    if (!project.hasProperty('cdvMinSdkVersion')) {
        cdvMinSdkVersion = null
    }
    // Whether to build architecture-specific APKs.
    if (!project.hasProperty('cdvBuildMultipleApks')) {
        cdvBuildMultipleApks = null
    }
    // .properties files to use for release signing.
    if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) {
        cdvReleaseSigningPropertiesFile = null
    }
    // .properties files to use for debug signing.
    if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
        cdvDebugSigningPropertiesFile = null
    }
    // Set by build.js script.
    if (!project.hasProperty('cdvBuildArch')) {
        cdvBuildArch = null
    }

    // Plugin gradle extensions can append to this to have code run at the end.
    cdvPluginPostBuildExtras = []
}

// PLUGIN GRADLE EXTENSIONS START
// PLUGIN GRADLE EXTENSIONS END

def hasBuildExtras = file('build-extras.gradle').exists()
if (hasBuildExtras) {
    apply from: 'build-extras.gradle'
}

// Set property defaults after extension .gradle files.
if (ext.cdvCompileSdkVersion == null) {
    ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget()
}
if (ext.cdvBuildToolsVersion == null) {
    ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
}
if (ext.cdvDebugSigningPropertiesFile == null && file('debug-signing.properties').exists()) {
    ext.cdvDebugSigningPropertiesFile = 'debug-signing.properties'
}
if (ext.cdvReleaseSigningPropertiesFile == null && file('release-signing.properties').exists()) {
    ext.cdvReleaseSigningPropertiesFile = 'release-signing.properties'
}

// Cast to appropriate types.
ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? null : Integer.parseInt('' + cdvMinSdkVersion)
ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)

def computeBuildTargetName(debugBuild) {
    def ret = 'assemble'
    if (cdvBuildMultipleApks && cdvBuildArch) {
        def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch
        ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1);
    }
    return ret + (debugBuild ? 'Debug' : 'Release')
}

// Make cdvBuild a task that depends on the debug/arch-sepecific task.
task cdvBuildDebug
cdvBuildDebug.dependsOn {
    return computeBuildTargetName(true)
}

task cdvBuildRelease
cdvBuildRelease.dependsOn {
    return computeBuildTargetName(false)
}

task cdvPrintProps << {
    println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
    println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
    println('cdvVersionCode=' + cdvVersionCode)
    println('cdvMinSdkVersion=' + cdvMinSdkVersion)
    println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
    println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
    println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
    println('cdvBuildArch=' + cdvBuildArch)
    println('computedVersionCode=' + android.defaultConfig.versionCode)
    android.productFlavors.each { flavor ->
        println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
    }
}

android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }
    }

    defaultConfig {
        //versionCode cdvVersionCode ?: Integer.parseInt("" + privateHelpers.extractIntFromManifest("versionCode") + "0")
        versionCode  Integer.parseInt("" + privateHelpers.extractIntFromManifest("versionCode"))
        applicationId privateHelpers.extractStringFromManifest("package")

        if (cdvMinSdkVersion != null) {
            minSdkVersion cdvMinSdkVersion
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////



    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////

    lintOptions {
        abortOnError false;
        disable "ResourceType"
    }

    compileSdkVersion cdvCompileSdkVersion
    buildToolsVersion cdvBuildToolsVersion

    if (Boolean.valueOf(cdvBuildMultipleApks)) {
        productFlavors {
            armv7 {
                //versionCode defaultConfig.versionCode + 2
                ndk {
                    abiFilters "armeabi-v7a", ""
                }
            }
            x86 {
                //versionCode defaultConfig.versionCode + 4
                ndk {
                    abiFilters "x86", ""
                }
            }
            all {
                ndk {
                    abiFilters "all", ""
                }
            }
        }
    } else if (!cdvVersionCode) {
      def minSdkVersion = cdvMinSdkVersion ?: privateHelpers.extractIntFromManifest("minSdkVersion")
      // Vary versionCode by the two most common API levels:
      // 14 is ICS, which is the lowest API level for many apps.
      // 20 is Lollipop, which is the lowest API level for the updatable system webview.
      if (minSdkVersion >= 20) {
        //defaultConfig.versionCode += 9
      } else if (minSdkVersion >= 14) {
        //defaultConfig.versionCode += 8
      }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_6
        targetCompatibility JavaVersion.VERSION_1_6
    }

   if (cdvReleaseSigningPropertiesFile) {
        signingConfigs {
            release {
                // These must be set or Gradle will complain (even if they are overridden).
                keyAlias = ""
                keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
                storeFile = null
                storePassword = "__unset"
            }
        }
        buildTypes {
            release {
                signingConfig signingConfigs.release
            }
        }
        addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
    }
    if (cdvDebugSigningPropertiesFile) {
        addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    // SUB-PROJECT DEPENDENCIES START
    debugCompile project(path: "CordovaLib", configuration: "debug")
    releaseCompile project(path: "CordovaLib", configuration: "release")
    // SUB-PROJECT DEPENDENCIES END

    compile 'com.android.support:design:25.0.0'

}

def promptForReleaseKeyPassword() {
    if (!cdvReleaseSigningPropertiesFile) {
        return;
    }
    if ('__unset'.equals(android.signingConfigs.release.storePassword)) {
        android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ')
    }
    if ('__unset'.equals(android.signingConfigs.release.keyPassword)) {
        android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: ');
    }
}

gradle.taskGraph.whenReady { taskGraph ->
    taskGraph.getAllTasks().each() { task ->
        if (task.name == 'validateReleaseSigning') {
            promptForReleaseKeyPassword()
        }
    }
}

def addSigningProps(propsFilePath, signingConfig) {
    def propsFile = file(propsFilePath)
    def props = new Properties()
    propsFile.withReader { reader ->
        props.load(reader)
    }

    def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile'))
    if (!storeFile.isAbsolute()) {
        storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
    }
    if (!storeFile.exists()) {
        throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
    }
    signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
    signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword))
    signingConfig.storeFile = storeFile
    signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword))
    def storeType = props.get('storeType', props.get('key.store.type', ''))
    if (!storeType) {
        def filename = storeFile.getName().toLowerCase();
        if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
            storeType = 'pkcs12'
        } else {
            storeType = signingConfig.storeType // "jks"
        }
    }
    signingConfig.storeType = storeType
}

for (def func : cdvPluginPostBuildExtras) {
    func()
}

// This can be defined within build-extras.gradle as:
//     ext.postBuildExtras = { ... code here ... }
if (hasProperty('postBuildExtras')) {
    postBuildExtras()
}

apply plugin: "com.google.gms.google-services" //FCM Config

allprojects {
    repositories {
        jcenter{ url "http://jcenter.bintray.com/" }
    }
}

Build.gradle(模块:CordovaLib)

buildscript {
    repositories {
        jcenter{ url "http://jcenter.bintray.com/" }
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
    }

}

apply plugin: 'com.android.library'

ext {
    apply from: 'cordova.gradle'
    cdvCompileSdkVersion = privateHelpers.getProjectTarget()
    cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
}

android {
    compileSdkVersion cdvCompileSdkVersion
    buildToolsVersion cdvBuildToolsVersion
    publishNonDefault true

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_6
        targetCompatibility JavaVersion.VERSION_1_6
    }

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }
    }
    buildToolsVersion '25.0.0'
}

gradle-wrapper.properties

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

是它是一个混合应用程序。使用 Cordova-android.

我试过在 google 上搜索任何东西,但找不到使用最新生物识别支持库的简单演示 android (Cordova android) 项目。

好的,以上 link 是一个工作演示 android 应用程序。

只有一个问题困扰我:为什么我不能在 build.gradle 中添加这一行(或者我需要添加它的地方)或者我如何添加它我当前在 AS 中的项目开始使用生物识别 API 进行人脸 ID 登录。 依赖关系{ 实施 'androidx.biometric:biometric:1.0.0-alpha03'

注意:赏金将授予那些将逐步解决我如何在我当前使用旧支持库的项目中集成生物识别支持 ​​API 的解决方案,如中所示我的构建-extra.gradle 文件 .

您需要在根项目的 build.gradle:

中定义存储库
allprojects {
    repositories {
        google()
    }
}

这些版本 a) 完全过时,b) 不要将 com.android.supportandroidx 混用。并且您不能将 Java 依赖项添加到 buildscript 依赖项中,因为这会产生错误消息 Could not find method implementation().

,也许 read the manual,以便提供程序员所期望的输入。仅仅因为您有 Mac 并不会将您排除在这些准则之外......这些准则确实存在是有原因的。

DO NOT post images of code, data, error messages, etc. - copy or type the text into the question. Please reserve the use of images for diagrams or demonstrating rendering bugs, things that are impossible to describe accurately via text.

我也可以简单地修复依赖项...但我太懒了,无法从屏幕截图中输入内容。

您使用的 implementation 关键字不受您的 Gradle 插件 (2.3.3) 支持

你绝对可以将它添加到你的 gradle 你只需要使用 compile 而不是 implementation compile "androidx.biometric:biometric:1.0.0-alpha03"

如果您想使用实现,您需要更新您的 Gradle 插件。这将允许您使用更新的 android 工作室,但需要您将一些东西迁移到新的 gradle.

经过 14 天的努力,我终于让我 3 岁的代码运行良好。

以下是详细步骤,以防有人在寻找相同的东西。

  1. 所以我有一个 Cordova android 混合应用程序旧代码。使用 Android 工作室 3.2。构建 gradle 版本很旧,2.8 和 gradle 版本是 3.3。

  2. 我首先升级了Android studio 到最新版本3.3.2

  3. 现在我决定将整个项目迁移到 androidX。请记住,它甚至不允许我使用以前版本的 Android studio 执行此操作,我不知道为什么。

  4. 当我点击重构 -> 迁移到 AndroidX 时。出现一个弹出窗口说“升级 gradle 版本。所以现在我将 gradle 版本更新到 4.10.1,如果我将它升级到 5.2,它仍然给我错误(我不知道为什么,我是Android 仍然是新手。还将构建 gradle 更新为 3.3.2

5.My build.gradle(模块:App)看起来像这样:

apply plugin: 'com.android.application'

buildscript {
    repositories {
        jcenter{ url "http://jcenter.bintray.com/" }
        google()
    }

    // Switch the Android Gradle plugin version requirement depending on the
    // installed version of Gradle. This dependency is documented at
    // http://tools.android.com/tech-docs/new-build-system/version-compatibility
    // and https://issues.apache.org/jira/browse/CB-8143
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.2'
        classpath "com.google.gms:google-services:3.0.0" //FCM Config

    }
   }
  1. 现在应用程序同步正常,构建正常。我再次尝试重构 -> 迁移到 androidX。这次Androidstudio开始重构代码,给我提供了70条改码建议。

  2. 这些代码更改主要是头文件更改,例如:import ""。所以我打开这个 link - https://developer.android.com/jetpack/androidx/migrate 并将每个导入语句更改为相等的 androidx 语句。

  3. 复制粘贴所有更改后,我再次编译并同步了代码。在 3 个资源和代码编译错误之后,我能够构建代码。整个过程耗时1.2小时.

  4. 我终于能够在 build-extras.gradle(模块:app)中导入生物识别支持 ​​API,查看文件:

        dependencies {
            api 'androidx.appcompat:appcompat:1.0.2'
            api "com.squareup.picasso:picasso:2.4.0"
            api "com.google.android.material:material:1.1.0-alpha04"
            api "com.google.firebase:firebase-messaging:9.2.0" //FCM Config
            api 'com.rmtheis:tess-two:6.0.2'
            api 'com.github.bumptech.glide:glide:3.8.0'
            api 'androidx.legacy:legacy-support-v4:1.0.0'
    
            api "androidx.biometric:biometric:1.0.0-alpha03"
        }
    }
    
  5. 最后,我能够构建完整的代码并同步它。很高兴终于做到了。现在我只需要使用生物识别 API 函数将其集成到我的代码中(请注意,这段代码是 3 年前编写的,是为了集成最新的生物识别 API 而提供给我的)。

是的,我需要像这样的一步步回答。

还是感谢所有帮助过的人。