/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
* copy, modify, and distribute this software in source code or binary form for use
* in connection with the web services and APIs provided by Facebook.
*
* As with any software that integrates with the Facebook platform, your use of
* this software is subject to the Facebook Developer Principles and Policies
* [http://developers.facebook.com/policy/]. This copyright notice shall be
* included in all copies or substantial portions of the software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.facebook.devicerequests.internal;
import android.annotation.TargetApi;
import android.content.Context;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.os.Build;
import com.facebook.FacebookSdk;
import com.facebook.internal.FetchedAppSettingsManager;
import com.facebook.internal.SmartLoginOption;
import com.facebook.internal.Utility;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
/**
* com.facebook.devicerequests.internal is solely for the use of other packages within the
* Facebook SDK for Android. Use of any of the classes in this package is
* unsupported, and they may be modified or removed without warning at any time.
*/
public class DeviceRequestsHelper {
public static final String DEVICE_INFO_PARAM = "device_info";
static final String DEVICE_INFO_DEVICE = "device";
static final String DEVICE_INFO_MODEL = "model";
static final String SDK_HEADER = "fbsdk";
static final String SDK_FLAVOR = "android";
static final String SERVICE_TYPE = "_fb._tcp.";
private static HashMap<String, NsdManager.RegistrationListener> deviceRequestsListeners =
new HashMap<>();
public static String getDeviceInfo() {
// Device info
// We don't need all the information in Utility.setAppEventExtendedDeviceInfoParameters
// We only want the model so we can show it to the user, so they know which device
// the login request comes from
JSONObject deviceInfo = new JSONObject();
try {
deviceInfo.put(DEVICE_INFO_DEVICE, Build.DEVICE);
deviceInfo.put(DEVICE_INFO_MODEL, Build.MODEL);
} catch (JSONException ignored) {
}
return deviceInfo.toString();
}
public static boolean startAdvertisementService(String userCode) {
if (isAvailable()) {
return startAdvertisementServiceImpl(userCode);
}
return false;
}
/*
returns true if smart login is enabled and the android api level is supported.
*/
public static boolean isAvailable() {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) &&
FetchedAppSettingsManager.getAppSettingsWithoutQuery(FacebookSdk.getApplicationId()).
getSmartLoginOptions().contains(SmartLoginOption.Enabled);
}
public static void cleanUpAdvertisementService(String userCode) {
cleanUpAdvertisementServiceImpl(userCode);
}
@TargetApi(16)
private static boolean startAdvertisementServiceImpl(final String userCode) {
if (deviceRequestsListeners.containsKey(userCode)) {
return true;
}
// Dots in the version will mess up the Bonjour DNS record parsing
String sdkVersion = FacebookSdk.getSdkVersion().replace('.', '|');
// Other SDKs that adopt this feature should use different flavor name
// The whole name should not exceed 60 characters
final String nsdServiceName = String.format("%s_%s_%s",
// static identifier
SDK_HEADER,
// sdk type and version
// client app parses the string based on this version
String.format("%s-%s",
SDK_FLAVOR,
sdkVersion
),
// Additional fields should be added here
// short code for the login flow
userCode
);
NsdServiceInfo nsdLoginAdvertisementService = new NsdServiceInfo();
nsdLoginAdvertisementService.setServiceType(SERVICE_TYPE);
nsdLoginAdvertisementService.setServiceName(nsdServiceName);
nsdLoginAdvertisementService.setPort(80);
NsdManager nsdManager = (NsdManager)FacebookSdk
.getApplicationContext()
.getSystemService(Context.NSD_SERVICE);
NsdManager.RegistrationListener nsdRegistrationListener =
new NsdManager.RegistrationListener() {
@Override
public void onServiceRegistered(NsdServiceInfo NsdServiceInfo) {
// Android may have changed the service name in order to resolve a conflict
if (!nsdServiceName.equals(NsdServiceInfo.getServiceName())) {
cleanUpAdvertisementService(userCode);
}
}
@Override
public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
}
@Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
cleanUpAdvertisementService(userCode);
}
@Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
}
};
deviceRequestsListeners.put(userCode, nsdRegistrationListener);
nsdManager.registerService(nsdLoginAdvertisementService,
NsdManager.PROTOCOL_DNS_SD,
nsdRegistrationListener);
return true;
}
@TargetApi(16)
private static void cleanUpAdvertisementServiceImpl(String userCode) {
NsdManager.RegistrationListener nsdRegistrationListener =
deviceRequestsListeners.get(userCode);
if (nsdRegistrationListener != null) {
NsdManager nsdManager = (NsdManager)FacebookSdk
.getApplicationContext()
.getSystemService(Context.NSD_SERVICE);
nsdManager.unregisterService(nsdRegistrationListener);
deviceRequestsListeners.remove(userCode);
}
}
}