NFC: async enabling/disabling, ala Bluewooth & Wifi.
Don't ANR when toggling.
Bug: 3097279
Change-Id: Ief09a5a4d023f32b02b2f3b72ac701e8089254c8
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 27b9ceb..e4ef11c 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -784,6 +784,7 @@
<string name="nfc_quick_toggle_title">NFC</string>
<!-- Used in the 1st-level settings screen as the turn-on summary -->
<string name="nfc_quick_toggle_summary">Use Near Field Communication to read and exchange tags</string>
+ <string name="nfc_toggle_error" msgid="8998642457947607263">An error occurred.</string>
<!-- Wi-Fi Settings --> <skip />
<!-- Used in the 1st-level settings screen to turn on Wi-Fi -->
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index 1facab9..14e8b52 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -17,10 +17,15 @@
package com.android.settings.nfc;
import com.android.settings.R;
+
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.nfc.NfcAdapter;
-import android.preference.Preference;
+import android.os.Handler;
import android.preference.CheckBoxPreference;
+import android.preference.Preference;
import android.provider.Settings;
import android.util.Log;
@@ -35,6 +40,20 @@
private final Context mContext;
private final CheckBoxPreference mCheckbox;
private final NfcAdapter mNfcAdapter;
+ private final IntentFilter mIntentFilter;
+ private final Handler mHandler = new Handler();
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGE.equals(action)) {
+ handleNfcStateChanged(intent.getBooleanExtra(
+ NfcAdapter.EXTRA_NEW_BOOLEAN_STATE,
+ false));
+ }
+ }
+ };
private boolean mNfcState;
@@ -47,49 +66,66 @@
// NFC is not supported
mCheckbox.setEnabled(false);
}
+
+ mIntentFilter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
+
}
public void resume() {
if (mNfcAdapter == null) {
return;
}
- mCheckbox.setOnPreferenceChangeListener(this);
- mNfcState = Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.NFC_ON, 0) != 0;
- updateUi();
+ mContext.registerReceiver(mReceiver, mIntentFilter);
+ mCheckbox.setOnPreferenceChangeListener(this);
+ mNfcState = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.NFC_ON, 0) != 0;
+ mCheckbox.setChecked(mNfcState);
}
public void pause() {
if (mNfcAdapter == null) {
return;
}
+ mContext.unregisterReceiver(mReceiver);
mCheckbox.setOnPreferenceChangeListener(null);
}
public boolean onPreferenceChange(Preference preference, Object value) {
- // Turn on/off Nfc
- mNfcState = (Boolean) value;
- setEnabled();
+ // Turn NFC on/off
+ final boolean desiredState = (Boolean) value;
+ mCheckbox.setEnabled(false);
+
+ // Start async update of the NFC adapter state, as the API is
+ // unfortunately blocking...
+ new Thread("toggleNFC") {
+ public void run() {
+ Log.d(TAG, "Setting NFC enabled state to: " + desiredState);
+ boolean success = false;
+ if (desiredState) {
+ success = mNfcAdapter.enableTagDiscovery();
+ } else {
+ success = mNfcAdapter.disableTagDiscovery();
+ }
+ if (success) {
+ Log.d(TAG, "Successfully changed NFC enabled state to " + desiredState);
+ // UI will be updated by BroadcastReceiver, above.
+ } else {
+ Log.w(TAG, "Error setting NFC enabled state to " + desiredState);
+ mHandler.post(new Runnable() {
+ public void run() {
+ mCheckbox.setEnabled(true);
+ mCheckbox.setSummary(R.string.nfc_toggle_error);
+ }
+ });
+ }
+ }
+ }.start();
return false;
}
- private void setEnabled() {
- if (mNfcState) {
- if (!mNfcAdapter.enableTagDiscovery()) {
- Log.w(TAG, "NFC enabling failed");
- mNfcState = false;
- }
- } else {
- if (!mNfcAdapter.disableTagDiscovery()) {
- Log.w(TAG, "NFC disabling failed");
- mNfcState = true;
- }
- }
- updateUi();
- }
-
- private void updateUi() {
- mCheckbox.setChecked(mNfcState);
+ private void handleNfcStateChanged(boolean newState) {
+ mCheckbox.setChecked(newState);
+ mCheckbox.setEnabled(true);
}
}