android-MNC 项目不会 运行 在 API 级别 'android-MNC' 之前的设备上

android-MNC project won’t run on devices prior to API level 'android-MNC'

在 Google I/O 主题演讲和关于 Android M 功能的连续讨论之后不久,我开始尝试新的 SDK 功能,例如 运行time权限。对于 it is necessary to set compileSdkVersion 以及 targetSdkVersionandroid-mnc。 运行在安装了 Android M Developer Preview 的 Nexus 5 上安装项目时,Android Studio 会安装该应用程序并且它在设备上运行良好。

如果我将 minSdkVersion 设置为 10 以在 2.3.6 设备上测试它或设置为 21 以在 5.0 设备上测试它,它仍然可以在 M-Nexus5 上运行但不能在上述低于 M API 版本的设备。

apply plugin: 'com.android.application'

android {
    buildToolsVersion "22.0.1"
    compileSdkVersion 'android-MNC'

    defaultConfig {
        applicationId "de.FOOBAR.permtestproject"
        minSdkVersion 10
        targetSdkVersion 21
        versionCode 23
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:design:22.2.0'
    compile 'com.android.support:appcompat-v7:22.2.0'
}

正如您在下面的屏幕截图中看到的,即使我将 minSdkVersion 设置为 10 而不是声称的 22 级别,我的 21 级设备仍显示为不兼容。

targetSdkVersion 降低到 21 并没有什么不同。更改 compileSdkVersion 不是一个选项,因为权限请求调用在 M(NC) 之前的 SDK 中不可用。

尝试 运行 在 M 之前的设备上应用程序总是失败并出现错误 INSTALL_FAILED_OLDER_SDK

Quoting myself:

In the case of the M Developer Preview, the compileSdkVersion value of android-MNC causes the build process to put MNC in as the minSdkVersion and targetSdkVersion in the generated manifest.

Fortunately, manifests are text files.

So, here is an android closure that can build an app module that compiles against MNC but will run on API Level 15+ devices:

android {
    compileSdkVersion 'android-MNC'
    buildToolsVersion "23.0.0 rc1"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 15
    }

    // based on 

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.processManifest.doLast {
                def manifestOutFile = output.processManifest.manifestOutputFile
                def newFileContents = manifestOutFile.getText('UTF-8').replace("MNC", "15")
                manifestOutFile.write(newFileContents, 'UTF-8')
            }
        }
    }
}

This takes a very “caveman” approach to the problem, reading in the generated manifest, replacing all occurrences of MNC with 15, and writing the adjusted manifest back out. This will fail on projects that have MNC somewhere else, like an activity’s class name. It also sets both minSdkVersion and targetSdkVersion to the same value. A more sophisticated script would replace those individual attributes — the proof of this is left as an exercise for the reader. Similarly, a more powerful script would read the desired values out of defaultConfig and apply them. And, a safety-conscious edition of this would only apply this for debuggable variants, thereby helping to reduce the impact of a drooling idiot trying to ship a release build that performs this override. This is merely a proof of concept, not implementing all possible bells and whistles.

Again, doing this and releasing the results to the Play Store or elsewhere is monumentally idiotic. Use this for testing only.