diff --git a/android/jni/com/mapswithme/platform/Platform.cpp b/android/jni/com/mapswithme/platform/Platform.cpp index c1e8d5f576..9e7834423a 100644 --- a/android/jni/com/mapswithme/platform/Platform.cpp +++ b/android/jni/com/mapswithme/platform/Platform.cpp @@ -28,6 +28,16 @@ std::string Platform::UniqueClientId() const return result; } +string Platform::MacAddress(bool md5Decoded) const +{ + JNIEnv * env = jni::GetEnv(); + static jmethodID const getMacAddressMethod = jni::GetStaticMethodID(env, g_utilsClazz, "getMacAddress", + "(Z)Ljava/lang/String;"); + jstring const macAddr = static_cast(env->CallStaticObjectMethod(g_utilsClazz, getMacAddressMethod, + static_cast(md5Decoded))); + return jni::ToNativeString(env, macAddr); +} + std::string Platform::GetMemoryInfo() const { JNIEnv * env = jni::GetEnv(); diff --git a/android/src/com/mapswithme/util/Utils.java b/android/src/com/mapswithme/util/Utils.java index 5c5df8e6b1..cf8b6da3c1 100644 --- a/android/src/com/mapswithme/util/Utils.java +++ b/android/src/com/mapswithme/util/Utils.java @@ -10,6 +10,8 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.Uri; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; import android.os.Build; import android.provider.Settings; import android.support.annotation.DimenRes; @@ -40,8 +42,12 @@ import com.mapswithme.util.statistics.AlohaHelper; import java.io.Closeable; import java.io.IOException; import java.lang.ref.WeakReference; +import java.net.NetworkInterface; +import java.security.MessageDigest; import java.text.NumberFormat; +import java.util.Collections; import java.util.Currency; +import java.util.List; import java.util.Locale; import java.util.Map; @@ -313,6 +319,77 @@ public class Utils return installationId; } + @NonNull + public static String getMacAddress(boolean md5Decoded) + { + final Context context = MwmApplication.get(); + byte[] macBytes = null; + String address = ""; + try + { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) + { + WifiManager manager = (WifiManager) context.getApplicationContext(). + getSystemService(Context.WIFI_SERVICE); + if (manager == null) + return ""; + WifiInfo info = manager.getConnectionInfo(); + address = info.getMacAddress(); + macBytes = address.getBytes(); + } + else + { + List all = Collections.list(NetworkInterface.getNetworkInterfaces()); + for (NetworkInterface nif : all) + { + if (!nif.getName().equalsIgnoreCase("wlan0")) + continue; + + macBytes = nif.getHardwareAddress(); + if (macBytes == null) + return ""; + + StringBuilder result = new StringBuilder(); + for (int i = 0; i < macBytes.length; i++) + { + result.append(String.format("%02X", (0xFF & macBytes[i]))); + if (i + 1 != macBytes.length) + result.append(":"); + } + address = result.toString(); + } + } + } + catch (Exception exc) + { + return ""; + } + return md5Decoded ? decodeMD5(macBytes) : address; + } + + @NonNull + private static String decodeMD5(@Nullable byte[] bytes) + { + if (bytes == null || bytes.length == 0) + return ""; + + try + { + MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); + digest.update(bytes); + byte[] messageDigest = digest.digest(); + + StringBuilder hexString = new StringBuilder(); + for (int i = 0; i < messageDigest.length; i++) + hexString.append(String.format("%02X", (0xFF & messageDigest[i]))); + return hexString.toString(); + } + catch (Exception e) + { + return ""; + } + } + public static boolean isAppInstalled(@NonNull Context context, @NonNull String packageName) { try diff --git a/local_ads/statistics.cpp b/local_ads/statistics.cpp index 7c7e4e1c40..4ec9529b91 100644 --- a/local_ads/statistics.cpp +++ b/local_ads/statistics.cpp @@ -197,6 +197,8 @@ std::vector SerializeForServer(std::list const & even ASSERT(!events.empty(), ()); auto root = my::NewJSONObject(); ToJSONObject(*root, "userId", userId); + static std::string offlineId = GetPlatform().MacAddress(true /* md5Decoded */); + ToJSONObject(*root, "offlineId", offlineId); ToJSONObject(*root, "countryId", events.front().m_countryId); ToJSONObject(*root, "mwmVersion", events.front().m_mwmVersion); auto eventsNode = my::NewJSONArray(); diff --git a/platform/platform.hpp b/platform/platform.hpp index 51f012ffa1..3c9433a270 100644 --- a/platform/platform.hpp +++ b/platform/platform.hpp @@ -251,6 +251,8 @@ public: std::string UniqueClientId() const; + std::string MacAddress(bool md5Decoded) const; + /// @return url for clients to download maps //@{ std::string MetaServerUrl() const; diff --git a/platform/platform_ios.mm b/platform/platform_ios.mm index 5d30f542ac..bf12cb12dc 100644 --- a/platform/platform_ios.mm +++ b/platform/platform_ios.mm @@ -124,6 +124,13 @@ int Platform::PreCachingDepth() const { return 2; } string Platform::UniqueClientId() const { return [Alohalytics installationId].UTF8String; } +string Platform::MacAddress(bool md5Decoded) const +{ + // Not implemented. + UNUSED_VALUE(md5Decoded); + return {}; +} + string Platform::GetMemoryInfo() const { struct task_basic_info info; diff --git a/platform/platform_linux.cpp b/platform/platform_linux.cpp index 5eb42689f9..91895da355 100644 --- a/platform/platform_linux.cpp +++ b/platform/platform_linux.cpp @@ -214,6 +214,13 @@ string Platform::UniqueClientId() const return "n0dbus0n0lsb00000000000000000000"; } +string Platform::MacAddress(bool md5Decoded) const +{ + // Not implemented. + UNUSED_VALUE(md5Decoded); + return {}; +} + string Platform::DeviceName() const { return OMIM_OS_NAME; diff --git a/platform/platform_mac.mm b/platform/platform_mac.mm index 8f3c8d0eca..40bd2c614c 100644 --- a/platform/platform_mac.mm +++ b/platform/platform_mac.mm @@ -114,6 +114,13 @@ Platform::Platform() string Platform::UniqueClientId() const { return [Alohalytics installationId].UTF8String; } +string Platform::MacAddress(bool md5Decoded) const +{ + // Not implemented. + UNUSED_VALUE(md5Decoded); + return {}; +} + string Platform::DeviceName() const { return OMIM_OS_NAME; diff --git a/platform/platform_win.cpp b/platform/platform_win.cpp index bbb70ae8ca..11c5cfdd3b 100644 --- a/platform/platform_win.cpp +++ b/platform/platform_win.cpp @@ -136,6 +136,13 @@ string Platform::UniqueClientId() const return "@TODO"; } +string Platform::MacAddress(bool md5Decoded) const +{ + // Not implemented. + UNUSED_VALUE(md5Decoded); + return {}; +} + string Platform::DeviceName() const { return OMIM_OS_NAME;