我的应用程序设置为在minSdk = 5上运行,但绝大多数用户使用的是SDK 8(FroYo)及更高版本。我希望能够使用android:configChanges =“uiMode”作为我的主要活动,但我不能这样做,因为直到SDK级别8才引入该模式。所以,我希望我能在运行时 - 检查设备上正在运行的SDK级别,然后使用反射添加该参数。
这可能吗?
修改 问题是,只要用户的手机连接到扩展坞,我的应用就会终止,然后重新创建。我试图通过包含android:configChanges =“uiMode”来避免这种情况。
答案 0 :(得分:2)
经过Android Reference的深入研究后,很少有人可以在运行时从清单中进行更改。这是因为安全性,因为通过PackageManager
,可以获得有关设备上任何应用程序的非常具体的信息。虽然很容易启用/禁用给定的组件,但在大多数其他情况下,您只能读取清单信息...而不是写入。
<强>替代强>
您可以创建一个支持API Level 8的单独APK。
您可以手动检查配置状态,并在更改时运行代码。配置的对象参考是here。
编辑:(新信息)
虽然您无法更改configChanges,但我发现this question与您的密切相关。事实证明,你可能没有。这意味着您可以在支持新configChanges
时使用Android的向后兼容模式。如果上面的链接被破坏,请输入以下网址:https://stackoverflow.com/a/7893148/501932
要将此功能用于您,建议您在保留原始targetSdk
的同时设置新的minimumSdk
。它还要求您拥有更新的SDK本身。显然,对于使用该AdMob API的用户来说,这是一个巨大的交易。
答案 1 :(得分:0)
用于向前兼容的应用配置
我提供的答案是一个简单的做什么,但没有多少或为什么,这应该更新答案,并作为道歉与SO社区争吵海报,这是毫无意义的,并没有添加任何东西会话。
我认为扩展这个问题是一个重点,因为这些问题出现了很多,开发人员匆忙(不是我们所有人),我们倾向于削减/复制/粘贴并担心为什么以后这种情况大部分都会解决,但偶尔会增加问题。
如果您了解Android运行时的实际工作方式,您可以通过在清单中使用块来应用简单的最佳实践模式,并在编译应用程序时充分利用Build Target,从而解决这些类型的问题,通过编译和运行时级别的一些简单测试。
清单
minSdkVersion =
非常简单,它是您在特定设备上支持的最低构建目标。如果未设置此值,则默认为1.
唯一需要注意的是,如果您的Build Target高于您的minSdkVersion,那么您可能会调用设备上不存在的API,更多内容是Build Target下的。
这将针对OS支持较低的设备从各种市场/播放存储库中过滤您的应用。
如果您必须让每个设备上的应用运行正常,那么您如何做出此决定取决于您,但请查看Platform Distribution以做出明智的决定。
如果你愿意绕过0.9%的市场然后目标2.1,这似乎是合理的,但这是开发商/公司做出的决定,如果你可以绕过25%的市场,那么选择2.3具有显着的优势但是对于大多数通用应用来说,有点难以接受。
链接图表会不时更新。
targetSdk =
如果您不应用此值,则默认为您设置的任何minSdkVersion。这意味着当您在具有更高操作系统支持的设备上运行时,某些新外观和/或已实现的行为将被绕过,以支持旧的操作方式。
例如,如果您将10应用于minSdkVersion然后您的应用程序在具有姜饼(11)的设备上运行,则它将不会尝试使用holo主题,或禁用屏幕兼容模式。一般来说,这可能会给你的应用程序一个“Dated”的外观和感觉。
另一方面,如果将其设置为更高的值,例如11,那么系统将使用操作系统的本机外观,直到您设置的值。最佳实践是将其设置为尽可能高,然后在模拟器中的更高级别设备上进行测试,以确保这是可接受的。
此处记录了影响操作系统跳转之间兼容性行为的一些更改Differences between OS's
这不会阻止您在早期设备上运行,也不会影响早期设备的外观或感觉(如果这是您的目标,请参阅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 if else,以便仅在较新的设备上调用它们,这将允许您支持新功能,而无需在旧设备上强制关闭。
所以一般来说,如果你支持更高的API级别,那些调用应该包含这样的东西(注意.SDK_INT是自API 4测试以来)
If ( Build.VERSION.SDK_INT >= API11_SUPPORT ) {
switch(newConfig.uiMode) {
case ...
}
测试 - 手动方法(CI集成方法留给读者; - )
对于我在步骤1中看到的每个问题,我在代码中添加两个项目(manifests / xml)
// TODO Compatibility xxx
if (DEBUG) Log.i(“MyApp”,” Compatibility xxx”);
然后我可以使用eclipse TODO窗格在发布之前检查兼容性问题,并针对操作系统版本之间的最低/最高和任何重要性进行测试
在minSDKVersion设备/模拟器上测试,如果您没有进行全面测试,这有点棘手,一般情况下使用上面的步骤1来确保我运用这些代码块
在构建目标设备/模拟器上进行测试,以确保外观按预期工作
如果您认为它有点工作,但是当您需要时,您应该正确行事并确保您的应用不会中断。
希望这对试图找出类似情况的人有用,下面是我对海报的第二次回应,干杯。
更新:
我仍然不知道作者在问什么,但如果他问是否有办法在7及以下使用onConfigurationChanged处理程序检测uiMode(对接内容)的配置更改,那么之后没有仅在API 8中引入。
在API 2.0+系统中发送广播事件,但显然存在一些问题,似乎并不完全可靠
如果他通过onConfigurationChanged处理程序询问是否有办法通过onConfigurationChanged处理程序在API 8及更高版本的设备上支持它,那么当然有
当然,他可能会问一些完全不同的事情,但是根据合作的精神,很难准确地说出他想要做的事情:
从项目属性中选择一个&gt; = 8的API,最佳做法是在创建应用时使用可用的最高API,但出于这个原因,必须注意不要调用任何API。在设备上不可用。
然后在清单使用(duh)
<activity
android:name=".myActivity"
android:configChanges="uiMode|orientation|keyboardHidden"
这编译很好(这实际上是唯一的问题,为什么你需要在eclipse项目属性中设置更高的api)这将在7及以下运行正常,因为当然API 7及以下不会触发任何事件设备无法识别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