Pull to refresh

Отслеживание установок приложений

Reading time 3 min
Views 15K
В официальной Google-группе, посвященной Android'у, время от времени появляются жалобы разработчиков о том, что трудно найти уникальные, надежные и стабильные идентификаторы для Android-устройств.
В блоге android-developers был опубликован небольшой топик, посвященный тому, как отслеживать индивидуальные установки приложений. Думаю, кому-то это будет полезно.


Отслеживание установок


Существует немало причин, по которым разработчики хотят отслеживать отдельные установки своих приложений. Некоторые просто вызывают метод TelephonyManager.getDeviceId() и используют это значение для идентификации отдельной установки. С этим есть некоторые проблемы: Во-первых, уникальность ID не гарантируется. Во-вторых, даже если это работает, то значение может пережить так называемый «Factory Reset» (сброс всех установок к начальным), что в конечном итоге может привести к неприятной ошибке, если один из покупателей/установщиков очистит свой девайс, и потом передаст его кому-то другому.

Чтобы отслеживать установки можно использовать UUID как идентификатор, и затем просто каждый раз создавать новый, при первом запуске приложения. Ниже набросок класса «Installation» (установка) с одним статическим методом Installation.id(Context context). Дальше всё зависит от вашей фантазии — можно дописывать различную специфичную для устройства информацию в файл INSTALLATION.

public class Installation {
    private static String sID = null;
    private static final String INSTALLATION = "INSTALLATION";

    public synchronized static String id(Context context) {
        if (sID == null) {  
            File installation = new File(context.getFilesDir(), INSTALLATION);
            try {
                if (!installation.exists())
                    writeInstallationFile(installation);
                sID = readInstallationFile(installation);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return sID;
    }

    private static String readInstallationFile(File installation) throws IOException {
        RandomAccessFile f = new RandomAccessFile(installation, "r");
        byte[] bytes = new byte[(int) f.length()];
        f.readFully(bytes);
        f.close();
        return new String(bytes);
    }

    private static void writeInstallationFile(File installation) throws IOException {
        FileOutputStream out = new FileOutputStream(installation);
        String id = UUID.randomUUID().toString();
        out.write(id.getBytes());
        out.close();
    }
}


Идентификация устройств


Представим себе, что вы хотите получить уникальный идентификатор отдельного устройства. Так или иначе, эта задача непростая.

Ранее, когда каждое Android-устройство было телефоном, то всё было просто: метод TelephonyManager.getDeviceId() возвращал IMEI, MEID, или ESN телефона, который гарантированно был уникален.
Однако, при этом подходе возникает ряд проблем:
  • Не телефоны. Wi-Fi устройства и музыкальные плейеры не имеют на борту телефонного оборудования, поэтому просто не в состоянии обеспечить эти идентификаторы.
  • Постоянность. На устройствах, которые обеспечены телефонным модулем, эти идентификаторы не изменяются при сбросе всех настроек. Так что и приложение будет считать, что повторную установку подсчитывать не нужно.
  • Дополнительные права. Требуется READ_PHONE_STATE, что раздражает клиентов, особенно, если приложение не использует телефонию.
  • Баги. Бывает, что производители телефонов не следят за идентификаторами и вышеозначенный метод возвращает абракадабру.

Mac адрес


Можно попробовать возвращать mac адрес для устройств, у которых есть Bluetooth или Wi-Fi. Это также не рекомендуется, потому что, во-первых, далеко не все устройства имеют Wi-Fi. Во-вторых, если модуль Wi-Fi не включен, то получить mac адрес не удастся.

Серийный номер


С версии Android 2.3 (Gingerbread) можно получить серийный номер через android.os.Build.SERIAL. Для версий ниже 2.3, lopatoid описал способ в комментариях.

ANDROID_ID


Более точно, это Settings.Secure.ANDROID_ID. Это 64-битное значение, которое генерируется при первой загрузке устройства, оно сбрасывается при очистке устройства (Factory Reset, etc.)

В принципе, ANDROID_ID неплохо подходит для идентификации устройства. Однако, у него есть некоторые недостатки: во-первых, он не на 100% надежен на версиях Android до 2.2 (Froyo). Во-вторых, существует один широко известный баг одного из производителей телефонов, из-за которого для всех устройств генерировался один и тот же ANDROID_ID.

Вывод


Для большинства приложений главное — уникально идентифицировать отдельную установку, а не устройство. К счастью, это не трудно.

Есть много причин для того, чтобы избежать идентификации отдельных устройств. Для тех, кто всё-таки хочет попробовать, лучшим выбором, возможно, будет ANDROID_ID, с небольшой эвристикой для устаревших устройств.
Tags:
Hubs:
+34
Comments 6
Comments Comments 6

Articles