Implement Wi-Fi QR code scanner flow.
1. Implements WifiNetworkConfig Wi-Fi connection method 2. Shows error message when the QR code is not valid and hides it after 2s 3. In configurator mode, launchs AddDeviceFragment for a valid QR code 4. In enrollee mode, connects Wi-Fi for a valid QR code Bug: 118794978 Test: manual test atest WifiQrCodetest atest WifiDppConfiguratorActivityTest atest WifiDppEnrolleeActivityTest atest WifiDppQrCodeScannerFragmentTest Change-Id: Ie4731b22df295c60906156d33ea28dad9c084ce4
This commit is contained in:
@@ -25,6 +25,8 @@ import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Size;
|
||||
import android.view.Menu;
|
||||
@@ -41,16 +43,40 @@ import com.android.settings.wifi.qrcode.QrDecorateView;
|
||||
public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
|
||||
SurfaceTextureListener,
|
||||
QrCamera.ScannerCallback {
|
||||
private static final String TAG = "WifiDppQrCodeScannerFragment";
|
||||
|
||||
/** Message sent to hide error message */
|
||||
private static final int MESSAGE_HIDE_ERROR_MESSAGE = 1;
|
||||
|
||||
/** Message sent to show error message */
|
||||
private static final int MESSAGE_SHOW_ERROR_MESSAGE = 2;
|
||||
|
||||
/** Message sent to manipulate Wi-Fi DPP QR code */
|
||||
private static final int MESSAGE_SCAN_WIFI_DPP_SUCCESS = 3;
|
||||
|
||||
/** Message sent to manipulate ZXing Wi-Fi QR code */
|
||||
private static final int MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS = 4;
|
||||
|
||||
private static final long SHOW_ERROR_MESSAGE_INTERVAL = 2000;
|
||||
private static final long SHOW_SUCCESS_SQUARE_INTERVAL = 1000;
|
||||
|
||||
// Keys for Bundle usage
|
||||
private static final String KEY_PUBLIC_KEY = "key_public_key";
|
||||
private static final String KEY_INFORMATION = "key_information";
|
||||
|
||||
private QrCamera mCamera;
|
||||
private TextureView mTextureView;
|
||||
private QrDecorateView mDecorateView;
|
||||
|
||||
/** true if the fragment working for configurator, false enrollee*/
|
||||
private final boolean mConfiguratorMode;
|
||||
private final boolean mIsConfiguratorMode;
|
||||
|
||||
/** The SSID of the Wi-Fi network which the user specify to enroll */
|
||||
private String mSsid;
|
||||
|
||||
/** QR code data scanned by camera */
|
||||
private WifiQrCode mWifiQrCode;
|
||||
|
||||
@Override
|
||||
protected int getLayout() {
|
||||
return R.layout.wifi_dpp_qrcode_scanner_fragment;
|
||||
@@ -58,20 +84,32 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
if (mConfiguratorMode) {
|
||||
if (mIsConfiguratorMode) {
|
||||
return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR;
|
||||
} else {
|
||||
return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_ENROLLEE;
|
||||
}
|
||||
}
|
||||
|
||||
// Container Activity must implement this interface
|
||||
public interface OnScanWifiDppSuccessListener {
|
||||
public void onScanWifiDppSuccess(String publicKey, String information);
|
||||
}
|
||||
OnScanWifiDppSuccessListener mScanWifiDppSuccessListener;
|
||||
|
||||
// Container Activity must implement this interface
|
||||
public interface OnScanZxingWifiFormatSuccessListener {
|
||||
public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig);
|
||||
}
|
||||
OnScanZxingWifiFormatSuccessListener mScanScanZxingWifiFormatSuccessListener;
|
||||
|
||||
/**
|
||||
* Configurator container activity of the fragment should create instance with this constructor.
|
||||
*/
|
||||
public WifiDppQrCodeScannerFragment() {
|
||||
super();
|
||||
|
||||
mConfiguratorMode = true;
|
||||
mIsConfiguratorMode = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +119,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
|
||||
public WifiDppQrCodeScannerFragment(String ssid) {
|
||||
super();
|
||||
|
||||
mConfiguratorMode = false;
|
||||
mIsConfiguratorMode = false;
|
||||
mSsid = ssid;
|
||||
}
|
||||
|
||||
@@ -91,7 +129,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
|
||||
|
||||
setHeaderIconImageResource(R.drawable.ic_scan_24dp);
|
||||
|
||||
if (mConfiguratorMode) {
|
||||
if (mIsConfiguratorMode) {
|
||||
setTitle(getString(R.string.wifi_dpp_add_device_to_network));
|
||||
|
||||
WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
|
||||
@@ -112,11 +150,30 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
|
||||
setDescription(description);
|
||||
}
|
||||
|
||||
ActionBar actionBar = getActivity().getActionBar();
|
||||
final ActionBar actionBar = getActivity().getActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.show();
|
||||
}
|
||||
|
||||
setErrorMessage(getString(R.string.wifi_dpp_could_not_detect_valid_qr_code));
|
||||
showErrorMessage(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
mScanWifiDppSuccessListener = (OnScanWifiDppSuccessListener) context;
|
||||
mScanScanZxingWifiFormatSuccessListener = (OnScanZxingWifiFormatSuccessListener) context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
mScanWifiDppSuccessListener = null;
|
||||
mScanScanZxingWifiFormatSuccessListener = null;
|
||||
|
||||
super.onDetach();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -172,11 +229,76 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
|
||||
mTextureView.setTransform(transform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(String qrCode) {
|
||||
try {
|
||||
mWifiQrCode = new WifiQrCode(qrCode);
|
||||
} catch (IllegalArgumentException e) {
|
||||
mHandler.sendEmptyMessage(MESSAGE_SHOW_ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
|
||||
final String scheme = mWifiQrCode.getScheme();
|
||||
|
||||
// When SSID is specified for enrollee, avoid to connect to the Wi-Fi of different SSID
|
||||
if (!mIsConfiguratorMode && WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG.equals(scheme)) {
|
||||
final String ssidQrCode = mWifiQrCode.getWifiNetworkConfig().getSsid();
|
||||
if (!TextUtils.isEmpty(mSsid) && !mSsid.equals(ssidQrCode)) {
|
||||
mHandler.sendEmptyMessage(MESSAGE_SHOW_ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// It's impossible to provision other device with ZXing Wi-Fi Network config format
|
||||
if (mIsConfiguratorMode && WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG.equals(scheme)) {
|
||||
mHandler.sendEmptyMessage(MESSAGE_SHOW_ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only called when QrCamera.ScannerCallback.isValid returns true;
|
||||
*/
|
||||
@Override
|
||||
public void handleSuccessfulResult(String qrCode) {
|
||||
switch (mWifiQrCode.getScheme()) {
|
||||
case WifiQrCode.SCHEME_DPP:
|
||||
handleWifiDpp(mWifiQrCode.getPublicKey(), mWifiQrCode.getInformation());
|
||||
break;
|
||||
|
||||
case WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG:
|
||||
handleZxingWifiFormat(mWifiQrCode.getWifiNetworkConfig());
|
||||
break;
|
||||
|
||||
default:
|
||||
// continue below
|
||||
}
|
||||
}
|
||||
|
||||
private void handleWifiDpp(String publicKey, String information) {
|
||||
destroyCamera();
|
||||
mDecorateView.setFocused(true);
|
||||
// TODO(b/120243131): Add a network by Wi-Fi Network config shared via QR code.
|
||||
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putString(KEY_PUBLIC_KEY, publicKey);
|
||||
bundle.putString(KEY_INFORMATION, information);
|
||||
|
||||
Message message = mHandler.obtainMessage(MESSAGE_SCAN_WIFI_DPP_SUCCESS);
|
||||
message.setData(bundle);
|
||||
|
||||
mHandler.sendMessageDelayed(message, SHOW_SUCCESS_SQUARE_INTERVAL);
|
||||
}
|
||||
|
||||
private void handleZxingWifiFormat(WifiNetworkConfig wifiNetworkConfig) {
|
||||
destroyCamera();
|
||||
mDecorateView.setFocused(true);
|
||||
|
||||
Message message = mHandler.obtainMessage(MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS);
|
||||
message.obj = wifiNetworkConfig;
|
||||
|
||||
mHandler.sendMessageDelayed(message, SHOW_SUCCESS_SQUARE_INTERVAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,4 +320,52 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showErrorMessage(boolean show) {
|
||||
super.showErrorMessage(show);
|
||||
|
||||
if (show) {
|
||||
mHandler.removeMessages(MESSAGE_HIDE_ERROR_MESSAGE);
|
||||
mHandler.sendEmptyMessageDelayed(MESSAGE_HIDE_ERROR_MESSAGE,
|
||||
SHOW_ERROR_MESSAGE_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MESSAGE_HIDE_ERROR_MESSAGE:
|
||||
showErrorMessage(false);
|
||||
break;
|
||||
|
||||
case MESSAGE_SHOW_ERROR_MESSAGE:
|
||||
showErrorMessage(true);
|
||||
break;
|
||||
|
||||
case MESSAGE_SCAN_WIFI_DPP_SUCCESS:
|
||||
if (mScanWifiDppSuccessListener == null) {
|
||||
return;
|
||||
}
|
||||
final Bundle bundle = msg.getData();
|
||||
final String publicKey = bundle.getString(KEY_PUBLIC_KEY);
|
||||
final String information = bundle.getString(KEY_INFORMATION);
|
||||
|
||||
mScanWifiDppSuccessListener.onScanWifiDppSuccess(publicKey, information);
|
||||
break;
|
||||
|
||||
case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS:
|
||||
if (mScanScanZxingWifiFormatSuccessListener == null) {
|
||||
return;
|
||||
}
|
||||
mScanScanZxingWifiFormatSuccessListener.onScanZxingWifiFormatSuccess(
|
||||
(WifiNetworkConfig)msg.obj);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user