summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/wifi
diff options
context:
space:
mode:
authorAndres Morales <anmorales@google.com>2014-04-16 17:19:05 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-04-16 17:19:05 +0000
commita298f077c8e1a73e1c17c444845da7dd650443bc (patch)
tree173a1103cbccd5b09c933d640137c18131532833 /src/com/android/settings/wifi
parentd7adb25e8757ce072c470889f31b4f6bc361b3b4 (diff)
parentef7a40a0d65a4d3e43d454273c6334448158e555 (diff)
downloadpackages_apps_Settings-a298f077c8e1a73e1c17c444845da7dd650443bc.tar.gz
packages_apps_Settings-a298f077c8e1a73e1c17c444845da7dd650443bc.tar.bz2
packages_apps_Settings-a298f077c8e1a73e1c17c444845da7dd650443bc.zip
Merge "Write wifi config to NFC tag"
Diffstat (limited to 'src/com/android/settings/wifi')
-rw-r--r--src/com/android/settings/wifi/WifiSettings.java25
-rw-r--r--src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java264
2 files changed, 285 insertions, 4 deletions
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 21efc39d5..15a184c97 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -94,6 +94,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class WifiSettings extends RestrictedSettingsFragment
implements DialogInterface.OnClickListener, Indexable {
+
private static final String TAG = "WifiSettings";
private static final int MENU_ID_WPS_PBC = Menu.FIRST;
private static final int MENU_ID_WPS_PIN = Menu.FIRST + 1;
@@ -104,12 +105,14 @@ public class WifiSettings extends RestrictedSettingsFragment
private static final int MENU_ID_CONNECT = Menu.FIRST + 6;
private static final int MENU_ID_FORGET = Menu.FIRST + 7;
private static final int MENU_ID_MODIFY = Menu.FIRST + 8;
+ private static final int MENU_ID_WRITE_NFC = Menu.FIRST + 9;
private static final int WIFI_DIALOG_ID = 1;
private static final int WPS_PBC_DIALOG_ID = 2;
private static final int WPS_PIN_DIALOG_ID = 3;
private static final int WIFI_SKIPPED_DIALOG_ID = 4;
private static final int WIFI_AND_MOBILE_SKIPPED_DIALOG_ID = 5;
+ private static final int WRITE_NFC_DIALOG_ID = 6;
// Combo scans can take 5-6s to complete - set to 10s.
private static final int WIFI_RESCAN_INTERVAL_MS = 10 * 1000;
@@ -141,6 +144,7 @@ public class WifiSettings extends RestrictedSettingsFragment
private final AtomicBoolean mConnected = new AtomicBoolean(false);
private WifiDialog mDialog;
+ private WriteWifiConfigToNfcDialog mWifiToNfcDialog;
private TextView mEmptyView;
@@ -205,13 +209,13 @@ public class WifiSettings extends RestrictedSettingsFragment
public void onCreate(Bundle icicle) {
// Set this flag early, as it's needed by getHelpResource(), which is called by super
mSetupWizardMode = getActivity().getIntent().getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
-
super.onCreate(icicle);
}
@Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
+
if (mSetupWizardMode) {
View view = inflater.inflate(R.layout.setup_preference, container, false);
View other = view.findViewById(R.id.other_network);
@@ -471,6 +475,7 @@ public class WifiSettings extends RestrictedSettingsFragment
if (mWifiEnabler != null) {
mWifiEnabler.pause();
}
+
getActivity().unregisterReceiver(mReceiver);
mScanner.pause();
}
@@ -599,6 +604,11 @@ public class WifiSettings extends RestrictedSettingsFragment
if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
menu.add(Menu.NONE, MENU_ID_FORGET, 0, R.string.wifi_menu_forget);
menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify);
+
+ if (mSelectedAccessPoint.security != AccessPoint.SECURITY_NONE) {
+ // Only allow writing of NFC tags for password-protected networks.
+ menu.add(Menu.NONE, MENU_ID_WRITE_NFC, 0, "Write to NFC Tag");
+ }
}
}
}
@@ -632,6 +642,10 @@ public class WifiSettings extends RestrictedSettingsFragment
showDialog(mSelectedAccessPoint, true);
return true;
}
+ case MENU_ID_WRITE_NFC:
+ showDialog(WRITE_NFC_DIALOG_ID);
+ return true;
+
}
return super.onContextItemSelected(item);
}
@@ -681,7 +695,7 @@ public class WifiSettings extends RestrictedSettingsFragment
mAccessPointSavedState = null;
}
}
- // If it's still null, fine, it's for Add Network
+ // If it's null, fine, it's for Add Network
mSelectedAccessPoint = ap;
mDialog = new WifiDialog(getActivity(), this, ap, mDlgEdit);
return mDialog;
@@ -727,6 +741,10 @@ public class WifiSettings extends RestrictedSettingsFragment
}
})
.create();
+ case WRITE_NFC_DIALOG_ID:
+ mWifiToNfcDialog =new WriteWifiConfigToNfcDialog(
+ getActivity(), mSelectedAccessPoint, mWifiManager);
+ return mWifiToNfcDialog;
}
return super.onCreateDialog(dialogId);
@@ -991,8 +1009,7 @@ public class WifiSettings extends RestrictedSettingsFragment
mRetry = 0;
Activity activity = getActivity();
if (activity != null) {
- Toast.makeText(activity, R.string.wifi_fail_to_scan,
- Toast.LENGTH_LONG).show();
+ Toast.makeText(activity, R.string.wifi_fail_to_scan, Toast.LENGTH_LONG).show();
}
return;
}
diff --git a/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java b/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java
new file mode 100644
index 000000000..7515f5c5a
--- /dev/null
+++ b/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java
@@ -0,0 +1,264 @@
+package com.android.settings.wifi;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.wifi.WifiManager;
+import android.nfc.FormatException;
+import android.nfc.NdefMessage;
+import android.nfc.NdefRecord;
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.nfc.tech.Ndef;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+import java.io.IOException;
+
+class WriteWifiConfigToNfcDialog extends AlertDialog
+ implements TextWatcher, View.OnClickListener, CompoundButton.OnCheckedChangeListener {
+
+ private static final String NFC_TOKEN_MIME_TYPE = "application/vnd.wfa.wsc";
+
+ private static final String TAG = WriteWifiConfigToNfcDialog.class.getName().toString();
+ private static final String PASSWORD_FORMAT = "102700%s%s";
+
+ private final PowerManager.WakeLock mWakeLock;
+
+ private AccessPoint mAccessPoint;
+ private View mView;
+ private Button mSubmitButton;
+ private Button mCancelButton;
+ private Handler mOnTextChangedHandler;
+ private TextView mPasswordView;
+ private TextView mLabelView;
+ private CheckBox mPasswordCheckBox;
+ private ProgressBar mProgressBar;
+ private WifiManager mWifiManager;
+ private String mWpsNfcConfigurationToken;
+ private Context mContext;
+
+ WriteWifiConfigToNfcDialog(Context context, AccessPoint accessPoint,
+ WifiManager wifiManager) {
+ super(context);
+ this.mContext = context;
+ this.mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE))
+ .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WriteWifiConfigToNfcDialog:wakeLock");
+ this.mAccessPoint = accessPoint;
+ this.mOnTextChangedHandler = new Handler();
+ this.mWifiManager = wifiManager;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ mView = getLayoutInflater().inflate(R.layout.write_wifi_config_to_nfc, null);
+
+ setView(mView);
+ setInverseBackgroundForced(true);
+ setTitle(R.string.setup_wifi_nfc_tag);
+ setCancelable(true);
+ setButton(DialogInterface.BUTTON_NEUTRAL,
+ mContext.getResources().getString(R.string.write_tag), (OnClickListener) null);
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ mContext.getResources().getString(com.android.internal.R.string.cancel),
+ (OnClickListener) null);
+
+ mPasswordView = (TextView) mView.findViewById(R.id.password);
+ mLabelView = (TextView) mView.findViewById(R.id.password_label);
+ mPasswordView.addTextChangedListener(this);
+ mPasswordCheckBox = (CheckBox) mView.findViewById(R.id.show_password);
+ mPasswordCheckBox.setOnCheckedChangeListener(this);
+ mProgressBar = (ProgressBar) mView.findViewById(R.id.progress_bar);
+
+ super.onCreate(savedInstanceState);
+
+ mSubmitButton = getButton(DialogInterface.BUTTON_NEUTRAL);
+ mSubmitButton.setOnClickListener(this);
+ mSubmitButton.setEnabled(false);
+
+ mCancelButton = getButton(DialogInterface.BUTTON_NEGATIVE);
+ }
+
+ @Override
+ public void onClick(View v) {
+ mWakeLock.acquire();
+
+ String password = mPasswordView.getText().toString();
+ String wpsNfcConfigurationToken
+ = mWifiManager.getWpsNfcConfigurationToken(mAccessPoint.networkId);
+ String passwordHex = byteArrayToHexString(password.getBytes());
+
+ String passwordLength = password.length() >= 16
+ ? "" + Character.forDigit(password.length(), 16)
+ : "0" + Character.forDigit(password.length(), 16);
+
+ passwordHex = String.format(PASSWORD_FORMAT, passwordLength, passwordHex).toUpperCase();
+
+ if (wpsNfcConfigurationToken.contains(passwordHex)) {
+ mWpsNfcConfigurationToken = wpsNfcConfigurationToken;
+
+ Activity activity = getOwnerActivity();
+ NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
+
+ nfcAdapter.enableReaderMode(activity, new NfcAdapter.ReaderCallback() {
+ @Override
+ public void onTagDiscovered(Tag tag) {
+ handleWriteNfcEvent(tag);
+ }
+ }, NfcAdapter.FLAG_READER_NFC_A |
+ NfcAdapter.FLAG_READER_NFC_B |
+ NfcAdapter.FLAG_READER_NFC_BARCODE |
+ NfcAdapter.FLAG_READER_NFC_F |
+ NfcAdapter.FLAG_READER_NFC_V,
+ null);
+
+ mPasswordView.setVisibility(View.GONE);
+ mPasswordCheckBox.setVisibility(View.GONE);
+ mSubmitButton.setVisibility(View.GONE);
+ InputMethodManager imm = (InputMethodManager)
+ getOwnerActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(mPasswordView.getWindowToken(), 0);
+
+ mLabelView.setText(R.string.status_awaiting_tap);
+
+ mView.findViewById(R.id.password_layout).setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
+ mProgressBar.setVisibility(View.VISIBLE);
+ } else {
+ mLabelView.setText(R.string.status_invalid_password);
+ }
+ }
+
+ private void handleWriteNfcEvent(Tag tag) {
+ Ndef ndef = Ndef.get(tag);
+
+ if (ndef != null) {
+ if (ndef.isWritable()) {
+ NdefRecord record = NdefRecord.createMime(
+ NFC_TOKEN_MIME_TYPE,
+ hexStringToByteArray(mWpsNfcConfigurationToken));
+ try {
+ ndef.connect();
+ ndef.writeNdefMessage(new NdefMessage(record));
+ getOwnerActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mProgressBar.setVisibility(View.GONE);
+ }
+ });
+ setViewText(mLabelView, R.string.status_write_success);
+ setViewText(mCancelButton, com.android.internal.R.string.done_label);
+ } catch (IOException e) {
+ setViewText(mLabelView, R.string.status_failed_to_write);
+ Log.e(TAG, "Unable to write WiFi config to NFC tag.", e);
+ return;
+ } catch (FormatException e) {
+ setViewText(mLabelView, R.string.status_failed_to_write);
+ Log.e(TAG, "Unable to write WiFi config to NFC tag.", e);
+ return;
+ }
+ } else {
+ setViewText(mLabelView, R.string.status_tag_not_writable);
+ Log.e(TAG, "Tag is not writable");
+ }
+ } else {
+ setViewText(mLabelView, R.string.status_tag_not_writable);
+ Log.e(TAG, "Tag does not support NDEF");
+ }
+ }
+
+ @Override
+ public void dismiss() {
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+
+ super.dismiss();
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ mOnTextChangedHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ enableSubmitIfAppropriate();
+ }
+ });
+ }
+
+ private void enableSubmitIfAppropriate() {
+
+ if (mPasswordView != null) {
+ if (mAccessPoint.security == AccessPoint.SECURITY_WEP) {
+ mSubmitButton.setEnabled(mPasswordView.length() > 0);
+ } else if (mAccessPoint.security == AccessPoint.SECURITY_PSK) {
+ mSubmitButton.setEnabled(mPasswordView.length() >= 8);
+ }
+ } else {
+ mSubmitButton.setEnabled(false);
+ }
+
+ }
+
+ private void setViewText(final TextView view, final int resid) {
+ getOwnerActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ view.setText(resid);
+ }
+ });
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ mPasswordView.setInputType(
+ InputType.TYPE_CLASS_TEXT |
+ (isChecked
+ ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
+ : InputType.TYPE_TEXT_VARIATION_PASSWORD));
+ }
+
+ private static byte[] hexStringToByteArray(String s) {
+ int len = s.length();
+ byte[] data = new byte[len / 2];
+
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ + Character.digit(s.charAt(i + 1), 16));
+ }
+
+ return data;
+ }
+
+ final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
+ private static String byteArrayToHexString(byte[] bytes) {
+ char[] hexChars = new char[bytes.length * 2];
+ for ( int j = 0; j < bytes.length; j++ ) {
+ int v = bytes[j] & 0xFF;
+ hexChars[j * 2] = hexArray[v >>> 4];
+ hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+ }
+ return new String(hexChars);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ @Override
+ public void afterTextChanged(Editable s) {}
+}