package org.OpenUDID; import java.math.BigInteger; import java.security.SecureRandom; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.TreeMap; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.IBinder; import android.os.RemoteException; import android.provider.Settings.Secure; import android.util.Log; public class OpenUDID_manager implements ServiceConnection{ public final static String PREF_KEY = "openudid"; public final static String PREFS_NAME = "openudid_prefs"; public final static String TAG = "OpenUDID"; private final static boolean LOG = true; //Display or not debug message private final Context mContext; //Application context private List<ResolveInfo> mMatchingIntents; //List of available OpenUDID Intents private Map<String, Integer> mReceivedOpenUDIDs; //Map of OpenUDIDs found so far private final SharedPreferences mPreferences; //Preferences to store the OpenUDID private final Random mRandom; private OpenUDID_manager(Context context) { mPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); mContext = context; mRandom = new Random(); mReceivedOpenUDIDs = new HashMap<String, Integer>(); } @Override public void onServiceConnected(ComponentName className, IBinder service) { //Get the OpenUDID from the remote service try { //Send a random number to the service android.os.Parcel data = android.os.Parcel.obtain(); data.writeInt(mRandom.nextInt()); android.os.Parcel reply = android.os.Parcel.obtain(); service.transact(1, android.os.Parcel.obtain(), reply, 0); if (data.readInt() == reply.readInt()) //Check if the service returns us this number { final String _openUDID = reply.readString(); if (_openUDID != null) { //if valid OpenUDID, save it if (LOG) Log.d(TAG, "Received " + _openUDID); if (mReceivedOpenUDIDs.containsKey(_openUDID)) mReceivedOpenUDIDs.put(_openUDID, mReceivedOpenUDIDs.get(_openUDID) + 1); else mReceivedOpenUDIDs.put(_openUDID, 1); } } } catch (RemoteException e) {if (LOG) Log.e(TAG, "RemoteException: " + e.getMessage());} mContext.unbindService(this); startService(); //Try the next one } @Override public void onServiceDisconnected(ComponentName className) {} private void storeOpenUDID() { final Editor e = mPreferences.edit(); e.putString(PREF_KEY, OpenUDID); e.commit(); } /* * Generate a new OpenUDID */ private void generateOpenUDID() { if (LOG) Log.d(TAG, "Generating openUDID"); //Try to get the ANDROID_ID OpenUDID = Secure.getString(mContext.getContentResolver(), Secure.ANDROID_ID); if (OpenUDID == null || OpenUDID.equals("9774d56d682e549c") || OpenUDID.length() < 15 ) { //if ANDROID_ID is null, or it's equals to the GalaxyTab generic ANDROID_ID or bad, generates a new one final SecureRandom random = new SecureRandom(); OpenUDID = new BigInteger(64, random).toString(16); } } /* * Start the oldest service */ private void startService() { if (mMatchingIntents.size() > 0) { //There are some Intents untested if (LOG) Log.d(TAG, "Trying service " + mMatchingIntents.get(0).loadLabel(mContext.getPackageManager())); final ServiceInfo servInfo = mMatchingIntents.get(0).serviceInfo; final Intent i = new Intent(); i.setComponent(new ComponentName(servInfo.applicationInfo.packageName, servInfo.name)); mContext.bindService(i, this, Context.BIND_AUTO_CREATE); mMatchingIntents.remove(0); } else { //No more service to test getMostFrequentOpenUDID(); //Choose the most frequent if (OpenUDID == null) //No OpenUDID was chosen, generate one generateOpenUDID(); if (LOG) Log.d(TAG, "OpenUDID: " + OpenUDID); storeOpenUDID();//Store it locally mInitialized = true; } } private void getMostFrequentOpenUDID() { if (mReceivedOpenUDIDs.isEmpty() == false) { final TreeMap<String,Integer> sorted_OpenUDIDS = new TreeMap(new ValueComparator()); sorted_OpenUDIDS.putAll(mReceivedOpenUDIDs); OpenUDID = sorted_OpenUDIDS.firstKey(); } } private static String OpenUDID = null; private static boolean mInitialized = false; /** * The Method to call to get OpenUDID * @return the OpenUDID */ public static String getOpenUDID() { if (!mInitialized) Log.e("OpenUDID", "Initialisation isn't done"); return OpenUDID; } /** * The Method to call to get OpenUDID * @return the OpenUDID */ public static boolean isInitialized() { return mInitialized; } /** * The Method the call at the init of your app * @param context you current context */ public static void sync(Context context) { //Initialise the Manager OpenUDID_manager manager = new OpenUDID_manager(context); //Try to get the openudid from local preferences OpenUDID = manager.mPreferences.getString(PREF_KEY, null); if (OpenUDID == null) //Not found { //Get the list of all OpenUDID services available (including itself) manager.mMatchingIntents = context.getPackageManager().queryIntentServices(new Intent("org.OpenUDID.GETUDID"), 0); if (LOG) Log.d(TAG, manager.mMatchingIntents.size() + " services matches OpenUDID"); if (manager.mMatchingIntents != null) //Start services one by one manager.startService(); } else {//Got it, you can now call getOpenUDID() if (LOG) Log.d(TAG, "OpenUDID: " + OpenUDID); mInitialized = true; } } /* * Used to sort the OpenUDIDs collected by occurrence */ private class ValueComparator implements Comparator { public int compare(Object a, Object b) { if(mReceivedOpenUDIDs.get(a) < mReceivedOpenUDIDs.get(b)) { return 1; } else if(mReceivedOpenUDIDs.get(a) == mReceivedOpenUDIDs.get(b)) { return 0; } else { return -1; } } } }