NFC: async enabling/disabling, ala Bluewooth & Wifi.

Don't ANR when toggling.

Bug: 3097279
Change-Id: Ief09a5a4d023f32b02b2f3b72ac701e8089254c8
This commit is contained in:
Brad Fitzpatrick
2010-10-18 14:04:24 -07:00
committed by Android Git Automerger
parent 98f3aff3c5
commit 17001cea9e
2 changed files with 62 additions and 25 deletions

View File

@@ -786,6 +786,7 @@
<string name="nfc_quick_toggle_title">NFC</string> <string name="nfc_quick_toggle_title">NFC</string>
<!-- Used in the 1st-level settings screen as the turn-on summary --> <!-- 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_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 /> <!-- Wi-Fi Settings --> <skip />
<!-- Used in the 1st-level settings screen to turn on Wi-Fi --> <!-- Used in the 1st-level settings screen to turn on Wi-Fi -->

View File

@@ -17,10 +17,15 @@
package com.android.settings.nfc; package com.android.settings.nfc;
import com.android.settings.R; import com.android.settings.R;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.preference.Preference; import android.os.Handler;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log; import android.util.Log;
@@ -35,6 +40,20 @@ public class NfcEnabler implements Preference.OnPreferenceChangeListener {
private final Context mContext; private final Context mContext;
private final CheckBoxPreference mCheckbox; private final CheckBoxPreference mCheckbox;
private final NfcAdapter mNfcAdapter; 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; private boolean mNfcState;
@@ -47,49 +66,66 @@ public class NfcEnabler implements Preference.OnPreferenceChangeListener {
// NFC is not supported // NFC is not supported
mCheckbox.setEnabled(false); mCheckbox.setEnabled(false);
} }
mIntentFilter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
} }
public void resume() { public void resume() {
if (mNfcAdapter == null) { if (mNfcAdapter == null) {
return; return;
} }
mContext.registerReceiver(mReceiver, mIntentFilter);
mCheckbox.setOnPreferenceChangeListener(this); mCheckbox.setOnPreferenceChangeListener(this);
mNfcState = Settings.System.getInt(mContext.getContentResolver(), mNfcState = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.NFC_ON, 0) != 0; Settings.System.NFC_ON, 0) != 0;
updateUi(); mCheckbox.setChecked(mNfcState);
} }
public void pause() { public void pause() {
if (mNfcAdapter == null) { if (mNfcAdapter == null) {
return; return;
} }
mContext.unregisterReceiver(mReceiver);
mCheckbox.setOnPreferenceChangeListener(null); mCheckbox.setOnPreferenceChangeListener(null);
} }
public boolean onPreferenceChange(Preference preference, Object value) { public boolean onPreferenceChange(Preference preference, Object value) {
// Turn on/off Nfc // Turn NFC on/off
mNfcState = (Boolean) value;
setEnabled();
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; return false;
} }
private void setEnabled() { private void handleNfcStateChanged(boolean newState) {
if (mNfcState) { mCheckbox.setChecked(newState);
if (!mNfcAdapter.enableTagDiscovery()) { mCheckbox.setEnabled(true);
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);
} }
} }