可能原始海报有维护实例状态的问题的原因是因为Android的默认行为是为每个新的意图启动一项新的活动。这就是为什么GrkEngineer在web回调之后没有看到onRestoreInstanceState被调用的原因。
将您的请求令牌存储为共享首选项是一种解决方案,以便它可以从OAuth Web回调后启动的新活动中获得。
我最初尝试使用共享首选项,它似乎工作正常。但是,我不认为这是最好的解决方案。理想情况下,您希望强制Android将回调传递给您的原始活动(我将在下面解释原因)。
我试过使用singleTask和singleInstance启动模式来完成这个部分成功,但它感觉不对,而且Android文档暗示这些模式不推荐用于一般用途。
经过对文档和测试的深入研究,我发现在创建意图时使用以下标志会导致Android将意图传递给活动的现有实例(如果它已被杀死,则重新创建它)。
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
为什么我需要让回调被原始活动处理的原因是我可以与android AccountManager集成。我用下面的示例让我开始:
http://developer.android.com/resources/samples/SampleSyncAdapter/index.html
一个用的AccountManager认证机制相结合的关键部分是传递到您的活动启动认证过程中AccountAuthenticatorResponse。
我发现实现这个最大的问题是保持对AccountAuthenticatorResponse对象的引用。这将传递到您的AuthenticatorActivity中,并且您需要在完成身份验证后调用它上的方法,以便标准帐户UI保持正确的状态。但是,我遇到了GrkEngineer最初碰到的同样的问题。当我在OAuth回调之后尝试重新启动OAuth身份验证器活动时,我总是收到一个新的实例,该实例已经失去对AccountAuthenticatorResponse对象的引用,并且我看不到任何方式来保留该对象。
关键是要使用上述的意图标志。
AuthenticatorActivity使用我的AbstractAccountAuthenticator的FLAG_ACTIVITY_NEW_TASK启动。它获取请求令牌(使用AsyncTask)并启动浏览器以要求用户进行授权。
OAuthCallbackHandlerActivity被注册来处理我的自定义回调方案。在用户授予访问权限后被调用时,它将使用标志Intent.FLAG_ACTIVITY_NEW_TASK |调用AuthenticatorActivity。 Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP意图。
这会导致我的原始AuthenticatorActivity被重新激活。 AccountAuthenticatorResponse对象仍然可用(就像我在OnSaveInstanceState中保存的请求令牌/秘密一样)。该活动现在可以获取访问令牌(再次使用AsyncTask),然后调用AccountAuthenticatorResponse对象的完成方法。
使这项工作的关键是使用我提到的意图标志,并确保AuthenticatorActivity在应用程序任务中启动,而不是在帐户管理器任务中启动。 FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP只会导致活动的现有实例重用,如果它们在同一个任务中。因此,如果您想要返回的活动在其他任务中启动,那么原始实例将不会被重新使用。
我在一个使用开发工具的模拟器上测试了这个,立即终止了我的AuthenticatorActivity,这样我就可以测试娱乐过程了。它使用onSaveInstanceState/onRestoreInstanceState来处理请求令牌/秘密。而且我甚至不必担心恢复AccountAuthenticatorResponse对象。这是由Android本身恢复 - 魔术!
我实际上是从你的旧帖开始的。很有帮助。我可能会尝试你的解决方案,但我想尝试一些其他的东西来帮助我更好地理解一些OAuth的东西。 我遇到了这个例子,http://code.google.com/p/jpoco/source/browse/trunk/jpoco-android-app/src/jpoco/android/MainActivity.java?r=346其中他将各种令牌存储为应用程序的SharedPreferences。如果我想做类似的事情,那么我需要保存哪些消费者和提供商的部分?我也认为这可能有助于在每次运行应用程序时不必重新进行身份验证。 – GrkEngineer 2009-12-28 02:56:03
您不必重新进行身份验证,只需保存令牌并重新使用即可。 Twitter不会过期。你是对的 - 在我的例子中,我没有试图理解签名是如何完成的(例如),而仅仅是如何使用它。从我与DroidIn的经验以及我得到的反馈 - 它工作得很好。 另外,我看到有人使用密钥生成解决方案,其中用户身份验证后提供的密钥,他需要在应用程序签名页面输入回来,但感觉更痛苦 – Bostone 2009-12-28 05:13:08
是的,你的例子真的很有帮助。我想我很想知道提供者/消费者字段是否可以使用SharedPreferences保存到磁盘。然后当回调返回时,您可以使用保存的字段重新填充提供者/消费者。 – GrkEngineer 2009-12-28 19:59:37