package com.cusnews.utils; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import android.content.Context; import android.net.wifi.WifiManager; import android.provider.Settings.Secure; import android.support.annotation.Nullable; import android.telephony.TelephonyManager; import android.text.TextUtils; /** * Three different methods to get unique identifier on Android, they are all not the perfect solutions however could be used under project restriction * limit. * * @author Xinyue Zhao */ public class DeviceUniqueUtil { /** * Get device unique identifier. */ @Nullable public static String getDeviceIdent( Context c ) throws NoSuchAlgorithmException { Prefs prefs = Prefs.getInstance(); if( TextUtils.isEmpty( prefs.getDeviceIdent() ) ) { String code = DeviceId.getDeviceId( c ); prefs.setDeviceIdent( code ); } return prefs.getDeviceIdent(); } /** * Fetch a MD5-Hash by getting IMEI or MAC or ANDROID's Secure-ID. */ private static class DeviceId { /** * requires permissions TELEPHONY_SERVICE on cell phones and WIFI_SERVICE on WiFi-only devices * * @return String * * @throws Exception * when there is no unique ID */ @Nullable private static String getDeviceId( Context _cxt ) throws NoSuchAlgorithmException { String readableId; // Requires READ_PHONE_STATE TelephonyManager tm = (TelephonyManager) _cxt.getSystemService( Context.TELEPHONY_SERVICE ); // gets the imei (GSM) or MEID/ESN (CDMA) String imei = null; try { imei = tm.getDeviceId(); } catch( SecurityException e ) { //Ignore... } if( null != imei && imei.length() > 0 && Long.parseLong( imei ) > 0 ) { // 000000000000000 for emulator readableId = imei; } else { // devices without SIM card (e.g. WiFi-only tablets) // requires ACCESS_WIFI_STATE WifiManager wm = (WifiManager) _cxt.getSystemService( Context.WIFI_SERVICE ); // gets the MAC address String mac = wm.getConnectionInfo().getMacAddress(); if( null != mac && mac.length() > 0 ) { readableId = mac; } else { // gets the android-assigned id // unfortunately, this is not unique on some devices: // http://groups.google.com/group/android-developers/browse_thread/thread/53898e508fab44f6/84e54feb28272384?pli=1 // so it's only a fallback for emulators String androidId = Secure.getString( _cxt.getContentResolver(), Secure.ANDROID_ID ); if( null != androidId && androidId.length() > 0 ) { readableId = androidId; } else { return null; } } } return md5( readableId ); } private static String md5( String _plaintext ) throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance( "MD5" ); digest.update( _plaintext.getBytes() ); byte[] hash = digest.digest(); BigInteger bigInt = new BigInteger( 1, hash ); return String.format( "%1$032X", bigInt ).toLowerCase(); } } }