com.brainasylum.andruid.UniqueIdentifierManager.java Source code

Java tutorial

Introduction

Here is the source code for com.brainasylum.andruid.UniqueIdentifierManager.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright 2014 Marco Lizza (marco.lizza@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission 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.brainasylum.andruid;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.UUID;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
import android.os.Process;
import android.util.Log;

public class UniqueIdentifierManager {

    private final static String TAG = "IdentifierManager";

    private final static String FILE_DIR = "Android";

    private final static String FILE_NAME = "UniqueIdentifiers.json";

    private final UniqueIdentifier _identifier;

    private String _udid = null;

    public UniqueIdentifierManager(UniqueIdentifier identifier) {
        _identifier = identifier;
    }

    public synchronized UUID getUdid(Context context) {
        if (_udid == null) {
            // we are using the shared-preferences as a "cache" to
            // store the current UDID. This value doesn't persist
            // across application uninstall, so we fall back to the
            // external storage.
            // we (re)serialized always in order to keep the
            // preferences and external storage synched.
            if ((_udid = getPreferencesUdid(context)) != null) {
                Log.d(TAG, "UDID from preferences: " + _udid);
            } else if ((_udid = getSdCardUdid(context)) != null) {
                Log.d(TAG, "UDID from sd-card: " + _udid);
            }
            if ((_udid = _identifier.getId(context)) != null) {
                Log.d(TAG, "UDID from instance: " + _udid);
            } else {
                _udid = getGeneratedUdid();
                Log.d(TAG, "UDID auto-generated: " + _udid);
            }
            serializeUdid(context, _udid);
            Log.d(TAG, "UDID serialized");
        }
        try {
            return UUID.nameUUIDFromBytes(_udid.getBytes("utf8"));
        } catch (UnsupportedEncodingException e) {
            clearUdid(context);
            return null;
        }
    }

    public synchronized void clearUdid(Context context) {
        // if permissions are granted, remove the identifier from
        // the storage bundle...
        if (canWriteExternalStorage(context)) {
            File file = new File(Environment.getExternalStorageDirectory() + "/" + FILE_DIR, FILE_NAME);
            if (file.exists()) {
                try {
                    //
                    FileInputStream fis = new FileInputStream(file);
                    byte[] buffer = new byte[(int) file.length()];
                    fis.read(buffer);
                    fis.close();
                    JSONObject root = new JSONObject(new String(buffer));
                    //
                    String applicationName = context.getApplicationInfo().packageName;
                    //
                    if (root.has(applicationName)) {
                        JSONObject values = root.getJSONObject(applicationName);
                        if (values.has(_identifier.getKey())) {
                            // remove the identifier value and if it's the
                            // last one in the object remove the application
                            // node itself
                            values.remove(_identifier.getKey());
                            if (values.length() == 0) {
                                root.remove(applicationName);
                            }
                            //
                            FileOutputStream fos = new FileOutputStream(file);
                            fos.write(root.toString().getBytes());
                            fos.close();
                        }
                    }
                } catch (IOException e) {
                    Log.e(TAG, "I/O error with file " + file.getAbsolutePath(), e);
                    e.printStackTrace();
                } catch (JSONException e) {
                    Log.e(TAG, "JSON error with file " + file.getAbsolutePath(), e);
                    e.printStackTrace();
                }
            }
        }
        // ... then remove it from the shared preferences...
        SharedPreferences prefs = context.getSharedPreferences(_identifier.getTag(), Context.MODE_PRIVATE);
        prefs.edit().remove(_identifier.getKey()).commit();
        // ... and clear the instance cached value.
        _udid = null;
    }

    private String getSdCardUdid(Context context) {
        if (canReadExternalStorage(context)) {
            File file = new File(Environment.getExternalStorageDirectory() + "/" + FILE_DIR, FILE_NAME);
            if (file.exists()) {
                try {
                    //
                    FileInputStream fis = new FileInputStream(file);
                    byte[] buffer = new byte[(int) file.length()];
                    fis.read(buffer);
                    fis.close();
                    JSONObject root = new JSONObject(new String(buffer));
                    //
                    String applicationName = context.getApplicationInfo().packageName;
                    //
                    if (root.has(applicationName)) {
                        JSONObject values = root.getJSONObject(applicationName);
                        if (values.has(_identifier.getKey())) {
                            return values.getString(_identifier.getKey());
                        } else {
                            return null;
                        }
                    }
                } catch (IOException e) {
                    Log.e(TAG, "I/O error with file " + file.getAbsolutePath(), e);
                    e.printStackTrace();
                } catch (JSONException e) {
                    Log.e(TAG, "JSON error with file " + file.getAbsolutePath(), e);
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    private String getPreferencesUdid(Context context) {
        SharedPreferences prefs = context.getSharedPreferences(_identifier.getTag(), Context.MODE_PRIVATE);
        return prefs.getString(_identifier.getKey(), null);
    }

    private static String getGeneratedUdid() {
        SecureRandom secureRandom = new SecureRandom();
        return new BigInteger(64, secureRandom).toString(16);
    }

    private static boolean canWriteExternalStorage(Context context) {
        return (context.checkPermission("android.permission.WRITE_EXTERNAL_STORAGE", Process.myPid(),
                Process.myUid()) == 0) && (isSdCardMounted());
    }

    private static boolean canReadExternalStorage(Context context) {
        return (context.checkPermission("android.permission.READ_EXTERNAL_STORAGE", Process.myPid(),
                Process.myUid()) == 0) && ((isSdCardMountedReadOnly()) || (isSdCardMounted()));
    }

    private static boolean isSdCardMounted() {
        return "mounted".equals(Environment.getExternalStorageState());
    }

    private static boolean isSdCardMountedReadOnly() {
        return "mounted_ro".equals(Environment.getExternalStorageState());
    }

    private void serializeUdid(Context context, String udid) {
        // if the external storage is writable (according to the current
        // application manifest settings) write to file
        if (canWriteExternalStorage(context)) {
            File dir = new File(Environment.getExternalStorageDirectory() + "/" + FILE_DIR);
            if (!dir.exists()) {
                dir.mkdir();
            }
            //
            File file = new File(dir, FILE_NAME);
            //
            String applicationName = context.getApplicationInfo().packageName;
            //
            try {
                //
                JSONObject root;
                if (file.exists()) {
                    FileInputStream fis = new FileInputStream(file);
                    byte[] buffer = new byte[(int) file.length()];
                    fis.read(buffer);
                    fis.close();
                    root = new JSONObject(new String(buffer));
                } else {
                    root = new JSONObject();
                }
                JSONObject values;
                if (root.has(applicationName)) {
                    values = root.getJSONObject(applicationName);
                } else {
                    values = new JSONObject();
                    root.put(applicationName, values);
                }
                //
                values.put(_identifier.getKey(), udid);
                //
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(root.toString().getBytes());
                fos.close();
            } catch (JSONException e) {
                Log.e(TAG, "JSON error with file " + file.getAbsolutePath(), e);
                e.printStackTrace();
            } catch (IOException e) {
                Log.e(TAG, "I/O error with file " + file.getAbsolutePath(), e);
                e.printStackTrace();
            }
        }
        // ... then store the value in the preference file, too...
        SharedPreferences prefs = context.getSharedPreferences(_identifier.getTag(), Context.MODE_PRIVATE);
        prefs.edit().putString(_identifier.getKey(), udid.toString()).commit();
    }

}