| 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; |
| } |
| } |
| } |
| } |
| |