1

我的应用程序设置为在 minSdk = 5 上运行,但绝大多数用户使用的是 SDK 8 (FroYo) 及更高版本。我希望能够将 android:configChanges="uiMode" 用于我的主要活动,但我不能这样做,因为直到 SDK 级别 8 才引入该模式。所以,我希望我能做到这一点runtime -- 检查设备上运行的是哪个 SDK 级别,然后使用反射添加该参数。

那可能吗?

编辑: 问题是每当用户的手机连接到扩展坞时,我的应用程序就会被终止,然后重新创建。我试图通过包含 android:configChanges="uiMode" 来避免这种情况。

4

2 回答 2

2

在仔细阅读Android 参考之后,您可以在运行时从清单中更改很少。这是出于安全考虑,因为通过PackageManager,人们可以获得有关设备上任何应用程序的非常具体的信息。虽然启用/禁用给定组件很容易,但在大多数其他情况下,您只能读取清单信息......而不是写入它。

备择方案

  • 您可能会创建一个单独的 APK,支持 API 级别 8。

  • 您可以手动检查配置状态并在更改时运行您的代码。配置的对象参考在这里

编辑:(新信息)

虽然您无法更改 configChanges,但我发现这个问题与您的问题密切相关。事实证明,您可能不必这样做。这意味着您可以在支持 new 时使用 Android 的向后兼容模式configChanges。如果上面的链接被破坏,这里是 URL:https ://stackoverflow.com/a/7893148/501932

为了将其用于您,它建议设置一个新的targetSdk同时保持您原来的minimumSdk. 它还要求您拥有更新的 SDK 本身。显然,这对于使用 AdMob API 的用户来说是一笔大买卖。

于 2012-06-11T08:53:58.440 回答
0

前向兼容性的应用程序配置

我提供的答案是一个简单的做什么,但没有太多或为什么,这应该更新答案,并作为对 SO 社区的道歉,因为与海报争吵,这是毫无意义的,也没有给对话增加任何内容。

我认为扩展这个问题很重要,因为这类问题经常出现,开发人员很着急(我们不是所有人),我们倾向于剪切/复制/粘贴并担心它的原因后来这主要解决了问题,但偶尔只会增加问题。

如果您了解 android 运行时的实际工作原理,您通常可以通过使用清单中的块应用简单的最佳实践模式来解决这些类型的问题,并在编译应用程序时充分利用构建目标,然后进行一些简单的在编译和运行时级别进行测试。

显现

minSdkVersion =

非常直接,它是您将在特定设备上支持的最低构建目标。如果你不设置它,它默认为 1。

这里唯一需要注意的是,如果您的构建目标高于您的 minSdkVersion,那么您可能会调用设备上不存在的 API,更多关于构建目标下的 API。

这将从具有较低操作系统支持的设备的各种市场/播放存储库中过滤您的应用程序。

你如何做出这个决定取决于你,如果你必须让你的应用程序在每台设备上都可以运行,但请查看Platform Distribution以做出明智的决定。

如果你愿意绕过 0.9% 的市场,那么目标是 2.1,这似乎是合理的,但这是开发商/公司做出的决定,如果你可以绕过 25% 的市场,那么选择 2.3,它具有显着优势但有点大多数通用应用程序都难以下咽。

链接图表会不时更新。

目标SDK =

如果您不应用此值,那么它默认为您设置的任何 minSdkVersion。这意味着,当您在具有更高操作系统支持的设备上运行时,某些新外观和/或已实现的行为将被绕过,以支持旧的处理方式。

例如,如果您将 10 应用于 minSdkVersion,然后您的应用程序在具有姜饼 (11) 的设备上运行,它将不会尝试使用全息主题或禁用屏幕兼容模式。一般来说,这可能会给您的应用带来“过时”的外观和感觉。

另一方面,如果您将其设置为更高的值,例如 11,那么系统将使用操作系统的本机外观,直至您设置的值。最佳做法是将其设置得尽可能高,然后在模拟器中的更高级别设备上进行测试,以确保这是可以接受的。

此处记录了影响操作系统跳转之间的兼容性行为的一些更改

这不会阻止您在早期设备上运行,或影响那些早期设备的外观或感觉(如果这是您的目标,请参阅 ActionBarSherlock 和 Android 支持库)

maxSdkVersion =

一般来说,这正如它所说的那样,它限制了应用程序在具有来自 Google 市场/播放的更高操作系统级别的设备上的可用性和部署。

在 android 2.0 上,它也会拒绝安装 apk,如果设备更新到高于此设置的级别,它甚至会删除您的应用程序,2.0.1+ 删除了此行为的第二部分,但市场仍将基于过滤在上面。

一般来说,通常没有理由设置此值,因此请将其留空。

构建目标 当您在 Eclipse(或其他)中设置构建目标时,您是在告诉编译器哪些 API、常量等应该对您的应用程序可见。

在此处输入图像描述

一般来说,它会添加一个 jar 文件,其中包含所有这些定义/声​​明,但当然不是实际的类/方法,这样您就可以为您想要的任何目标操作系统编译应用程序。

当您的应用程序在设备上运行时,它会链接到实际的 android 操作系统/支持 jar 文件(或者如果它们不存在,则将它们吹散)

如果您选择的构建目标高于您愿意支持的水平,那么当您尝试调用不存在的方法,甚至是旧操作系统上不存在的类时,当然会发生坏事。

另一方面,如果您愿意仔细管理和测试它,那么您可以获得前向兼容性,因为您可以在较新的设备上使用新的 API,只要您不尝试在较早的设备上这样做。

最佳实践 - 简短版 这是发帖人试图完成的任务,如果遵循最佳实践,效果很好,这些都是一般性的

minSdkVersion    = lowest general API you will support
targetSdkVersion = highest behavioral model you are willing to allow
maxSdkVersion    = leave it blank
Build Target     = generally as high as is currently supported 

真正需要注意的是,您必须避免旧版本和新版本之间的 API 不匹配,并确保您的应用在更高版本上看起来和运行正常。

通常,应谨慎使用高于最低目标操作系统的方法/类,并在编译和运行时级别进行测试,因为需要付出一些努力才能安全地使用它们。

这是我的做法

minSdkVersion    = 7 ( I can live with a 0.9% clip again your choice ) 
targetSdkVersion =15 ( highest as of this writing ) 
maxSdkVersion    = ( blank )

Build Target = 15

在开发时,我从不使用 7 上不可用的 API,除非我真的需要这样做,在海报问题中,他本可以使用收到的广播将类似的功能恢复到 6/7 (2.0/2.1) 但他说他需要 API 3 支持,所以他必须支持前向兼容性。

您可以使用的一个工具,而且大多数不仅仅是为了让事情保持直截了当,就是将 developer.android.com 网站上的 API 级别设置为您的最低 SDK 级别,这在开发时为您提供了一个必须支持的提示前向兼容性。

在此处输入图像描述

它仍会显示其他 API 调用,但会显示为灰色,告诉您需要额外的努力来支持它们

如果您确实需要使用较新的 API,则需要执行 if then else 以便仅在较新的设备上调用它们,这将允许您支持新功能而无需在较旧的设备上强制关闭。

所以一般来说,如果你支持更高的 API 级别,这些调用应该用这样的东西包装(注意 .SDK_INT 是自 API 4 以来的测试)

If ( Build.VERSION.SDK_INT  >= API11_SUPPORT ) {
    switch(newConfig.uiMode) {
        case ...
}

测试——手动方法(CI 集成方法留给读者;-)

  1. 使用设置为 minSdkVersion 的构建目标进行编译——这将使您在正在使用的任何较新的 API 上编译错误,检查它们,如果您处理得很好,如果不是现在就是时候了。

对于我在步骤 1 中看到的每个问题,我都会在代码中添加两项(清单/xml)

// TODO Compatibility xxx 
if (DEBUG) Log.i(“MyApp”,” Compatibility xxx”); 

然后,我可以使用 eclipse TODO 窗格在发货前检查兼容性问题,并针对最低/最高以及操作系统版本之间的任何重要问题进行测试

  1. 在 minSDKVersion 设备/模拟器上进行测试,如果您不进行全面测试,这有点棘手,通常使用上面的步骤 1 来确保我练习了这些代码块

  2. 在构建目标设备/模拟器上进行测试,以确保外观和感觉按预期工作

如果您认为这有点工作,但当您需要它时,您应该正确地做,并确保您的应用程序不会中断。

希望这对试图找出类似情况的人有用,下面是我对海报的第二次回应,干杯。

更新:

我仍然不知道作者在问什么,但是如果他问是否有一种方法可以使用 onConfigurationChanged 处理程序检测 7 及以下版本中有关 uiMode (对接的东西)的配置更改,那么没有,因为这只是在API 8。

API 2.0+ 系统中发送了一个广播事件,但显然这有一些问题,似乎并不完全可靠

如果他询问是否有办法通过 onConfigurationChanged 处理程序在 API 8 及更高版本的设备上通过设置活动清单中的标志来支持它,那么当然有

当然,他可能会问一些完全不同的事情,鉴于他的职位,很难准确地说出他想要做什么,但本着合作的精神:

从项目属性中选择 >= 8 的 API,最佳实践是在创建应用程序时使用可用的最高 API,但必须注意不要调用设备上不可用的任何 API。

然后在清单中使用(duh)

<activity
            android:name=".myActivity"
             android:configChanges="uiMode|orientation|keyboardHidden"

这编译得很好(这确实是唯一的问题以及为什么需要在 eclipse 项目属性中设置更高的 api)这将在 7 及以下运行良好,它不会触发任何事件,因为当然 API 7 及以下设备不会' t 识别 uiMode 标志 (duh)

API 8 及更高版本当然会识别它并发送正确的事件,因此在 api 7 上将写入日志,在 api 8+ 上它将(如果停靠等)当然,如果确实发生了调用,则很可能是8+ 相关,因此在调用它们之前您需要一个操作系统检查块。

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    Log.i("myActivity","uiMode="+newConfig.uiMode);

}

如果您在 7 API 仿真器上编译和运行并触发停靠广播,则没有任何反应,更改为 8 API 仿真器即可

adb shell am broadcast -a android.intent.action.DOCK_EVENT --ei android.intent.extra.DOCK_STATE 2
于 2012-06-11T06:08:25.913 回答