0

我有一个EditTextPreference允许用户输入一些结构化文本的子类,并在关闭对话框之前对其进行验证。我想让用户在首选项对话框打开时通过扫描 NFC 标签来输入此文本。扫描标签将填充EditText接收到的文本。在首选项的对话框未打开时扫描标签不会产生任何效果(即它会让任何其他注册的应用程序处理ACTION_NDEF_DISCOVERED Intent)。

我已经在相关领域有非常相似的工作Activity,所以我不需要 NFC 部分本身的任何帮助。问题是通过PreferenceNFC API 以下列Activity方式将所有内容连接到主机时:-

  1. enableForegroundDispatch()接受一个Activity论点
  2. 结果通过Activity.onNewIntent()

我对如何进行有两个想法,但有不同的缺点:-

  1. 要求Activity包含 myPreference为我完成所有设置。它需要在首次创建时告诉Preference'Activity的身份,以允许稍后Preference在正确的时间调用。它还需要将呼叫转发到. 这似乎很脆弱——尤其是考虑到通常会在 a 内,并且不需要知道任何关于个人偏好的信息——但如果能够找出托管它的内容会更合理。enableForegroundDispatchdisableForegroundDispatchonNewIntent()PreferencePreferencePreferenceFragmentActivityPreferenceActivity
  2. 停止成为一个DialogPreference并用私人Activity主题(如对话)替换对话。创建布局没有问题,这会将所有与 NFC 相关的代码保留在特殊的Activity. 但接下来的问题是如何startActivityForResultPreference. Intent在中设置 anPreference是不够的,因为它使用startActivity并且没有机制来获取结果。即使我设法做到了startActivityForResult,我也遇到了与上面相同的问题,那就是它会被传递到Activity主机上Preference,这使得机制再次变得脆弱。如果我可以使用其他渠道从 中获取文本,则Activity此选项会更合适。

你能帮助克服这些问题吗?获得任一替代工作就足够了,但我更喜欢选项 2,因为它可以帮助我解决另一个类似的问题。

4

3 回答 3

1

使用 1) 并创建两个接口:

  1. 用于接收意图(或更好的 NFC 数据,如 NDEF 记录等)
  2. B 用于设置或删除 A 的实例

让活动实现 B 并将 A 存储在字段中。在 NFC 事件中,如果设置了 A 字段,则调用接口。

让 UI 类实现 A 并将 B 存储在构造函数的字段中。

并根据 A 字段是对象还是空来切换 nfc 前台模式。

于 2013-04-04T20:15:34.263 回答
1

除非我忽略了一些明显的东西,否则实现想法 #2 似乎不难。

您可能想查看框架中RingtonePreferencestartActivityForResult()的源代码,该框架从其方法调用onClick()并处理它作为结果接收的意图,这与您的想法非常相似。

于 2013-04-04T22:14:27.713 回答
1

我最终能够通过一些技巧的使用来解决这个问题。我从选项 2 开始:

  • 我把我的对话变成了一个新的Activity,带有对话主题的。新活动具有所有 NFC 代码:它将自身传递给enableForegroundDispatch,并且具有在onNewIntent扫描标签时更新其文本的方法。
  • 对话活动不是使用setResult将其结果返回给调用者,而是使用Intent一些识别信息、是否按下 OK 或取消对话的指示以及新文本来构造一个。它从 发送意图onPause,受 保护if (isFinishing()),以确保即使它因外部触摸或后退键而关闭,也能发送意图。
  • EditTextPreference用一个新的子类替换了我的子类Preference。新类看起来非常相似,EditTextPreference但不需要太多的灵活性。
  • 我的 newPreference包含一个匿名BroadcastReceiver子类,它从它接收的结构化文本中获取Intent并设置首选项的值,更新 GUI 并触发onPreferenceChange侦听器。
  • 我的onClick()偏好调用方法getContext().registerReceiver,传递匿名BroadcastReceiver和意图过滤器,该过滤器与对话活动设置的识别信息相匹配。然后它调用getContext().startActivity( not startActivityForResult ) 来启动对话活动。

还有一个额外的复杂性:如果在对话框打开时发生配置更改(例如重新定向),则首选项将与其托管活动一起销毁并重新创建。因为我使用了activity的上下文,而不是应用上下文来注册receiver,旧的receiver会被注销,新的preference需要注册receiver。(使用应用程序上下文会泄露旧的活动及其所有首选项,并且可能会在旧首选项更新时导致崩溃。)所以首选项还有一些事情要做:

  • onClick还设置一个标志,以便它知道接收器已注册。接收器清除标志。
  • 首选项SavedState获取“接收者已注册”标志的副本。
  • 首选项onRestoreInstanceState检查此标志,如果设置,则getContext().registerBroadcastReceiver使用与以前相同的接收器和意图过滤器进行调用。

结果是,从 aPreference中,我可以拥有与 a 相同的功能startActivityForResult,但实现这一点的所有代码都保留在它所调用的内部Preference和内部Activity:包含PreferenceActivityPreferenceFragment不需要任何代码。由于我在几个屏幕上都有相同类型的偏好,这是一个巨大的代码重用胜利,当然还有更好的封装。

相同的技术可用于其他想要使用在 中难以实现的功能的偏好AlertDialog,例如 GL、视频、声音或嵌入地图片段。

于 2013-05-16T11:35:16.753 回答