На днях я сделал приложение для обхода блокировки rutracker, однако уже дважды получил от Google отбой по разным надуманным причинам. Это очень огорчило, и возник вопрос — что делать? Поиск по хабру показал, что такие проблемы возникли очень у многих (пруфы: один, два, три, четыре… Тысячи их).
А помимо бана есть ещё много причин, по которым ваше приложение может оказаться «за бортом» Google Play — например, если оно предназначено для использования только в компании, для друзей или для другого круга лиц. Так же возможно, что ваше приложение по определению не может быть выложено на Google Play — например, если оно является само по себе установщиком приложений.

Готовой статьи на эту тему я не нашёл, так что решил, что верным решением будет разобраться и написать свою. Итак, принципиальных варианта есть всего два.

1. Используем альтернативный магазин приложений


Тут довольно богато. Amazon App Shop, Samsung Apps, Yandex.Store, blackmart, humble bundle, F-Droid… В общем-то неплохо. Я из них пока попробовал только Yandex.Store. Получилось зарегистрироваться и опубликовать приложение минут за 5 — оно там уже доступно. Правда, недоумение вызывает полная невозможность как-либо дать ссылку на установку приложения в Yandex.Store. Может, я слепой, но кнопочки «Share» там просто нет. Ну и никакого веб интерфейса — только мобильный. Кстати, вопрос к представителям Yandex — а Yandex.Store вообще живой? Последний пост в твиттере датируется 2014 годом.

Плюсы:


  • Наличие некоторых возможностей, к которым мы привыкли в Google Play — включая автоматическое обновление, статистику и биллинг (есть не во всех указанных, конечно).
  • Хотя бы какой-то авторитет издателя — хуже, чем если бы приложение было на Google Play, но лучше, чем ничего.
  • Индивидуальные фичи — например, F-Droid публикует только приложения с открытым кодом.


Минусы:


  • Потеря в имидже. Все пользователи привыки, что приложение должно качаться с google play. Если его там нет — значит, что-то не так. Хотя вот, например, Yandex.Store на Google Play нету. И качать его приходится очень стрёмным методом...
  • Пользователю придётся устанавливать некий «левый» магазин приложений. У меня вот ничего кроме google play не было с момента появления Android, и ставить я не собирался. Устанавливать себе ещё одного «большого брата» с полными возможностями по манипуляции твоим устройством — довольно стрёмно.
  • Кажется, ни у одного из них нет информации о сбоях. Плюс другие возможности Google Play включая биллинг.


2. Самостоятельное решение


Как ни страшно это звучит, на самом деле здесь мы приходим к аналогу обычного десктопного софта. Сама программа знает, когда и как ей обновляться, рассказывает об этом, в ней интегрированы платёжные возможности и монетизация. Рекламой и продвижением занимаетесь вы сами. Ужас, ужас! Но на самом деле, мы просто избаловались. Нужно просто находить правильные пути. Продвигать приложение можно, например, на тематических блогах и форумах — в том числе на 4pda с очень неплохим объёмом аудитории. Или прямо на хабре.

Кстати, даже если ваше приложение успешно опубликовано на Google Play — имеет смысл подстраховаться и как минимум сделать в нём свой алгоритм обновления, который активизируется, если, например, приложение давно не обновлялось. Или по проверке бана на вашем сервере или прямо на Google Play. Иначе, если вас на какое-то время забанят, пользователи не смогут обновить приложение. А если есть запасной вариант — вреда будет заметно меньше.

Плюсы


Ваше приложение практически невозможно заблокировать — только вместе с ресурсом, на котором вы держите обновление и информацию.

Минусы


  • Всё, что только можно — приходится делать вручную.
  • Потеря в имидже, о которой уже было сказано ранее. Как ни странно, возможно что меньшая, чем в случае использования некоего магазина приложений.


Итак, что же вам придётся делать:

Размещение приложения для скачивания


На самом деле, это всего лишь означает, что вам нужно выложить APK куда-то в доверенное место. Их не так уж мало — можно использовать всё тот же 4pda, можно класть релизы прямо в github, можно на свой сайт… Вариантов уйма.

Отладка ошибок


Да, привыкли мы к хорошему — Google сам поймает ошибку, всё расскажет о её месте, устройстве пользователя и так далее. Но… Никак проблем это реализовать самостоятельно. Как простейший вариант — ловим все эксепшны и отсылаем куда-то на сервер по HTTP или даже на почту.

Сбор статистики


К сожалению, никогда не интересовался статистикой приложений, но вам с очевидностью придётся реализовать как минимум статистику по скачиваниям.

Сложные библиотеки


Собственно придётся забыть о всех сложных и хороших вещах, которые даёт Google Play. Впрочем, то же самое касается, пускай и в чуть меньшей степени, любых магазинов приложений.

Обновление


По обновлению есть принципиально три варианта:
  1. Автоматическое обновление при наличии прав SuperUser. Это довольно стрёмно, но понятно — не будем рассматривать подробно.
  2. Обновление вручную после автоматического скачивания. Неплохо, однако требует разрешения на запись данных. Если его у вашего приложения не запланировано, то ставить лишние разрешения — зло. Требует от пользователя разрешения на установку программ из сторонних источников.
  3. Обновление вручную при переходе по ссылке. Простой вариант, однако требует от пользователя скачать и открыть APK файл. Ну и так же как второй вариант — требует от пользователя разрешения на установку программ из сторонних источников.


Чтобы показать, как всё просто — покажу примитивную реализацию третьего варианта,
которую я сделал для своего приложения за час времени.
1. Добавляем куда-то свою актуальную версию приложения. Я засунул прямо в исходники на Github в build.gradle:
//        releaseVersionCode 5


2. Публикуем где-то релизы приложения. У меня они так же лежат на github, в формате
String url="https://github.com/jehy/rutracker-free/releases/download/" + version+"/app-release.apk";


3. Пишем собственно алгоритм обновления:

3.1 в MainActivity.OnCreate добавляем вызов проверки:

        new Updater().execute(this);


3.2 Пишем простенький класс для проверки:

        class Updater extends AsyncTask<MainActivity, Void, Void> {

    private Exception exception;

    protected Void doInBackground(MainActivity... activity) {
        checkUpdates(activity[0]);
        return null;
    }

    Integer getLastAppVersion() {
        try {
            // Create a URL for the desired page
            URL url = new URL("https://raw.githubusercontent.com/jehy/rutracker-free/master/app/build.gradle");
            // Read all the text returned by the server
            BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
            String str;
            while ((str = in.readLine()) != null) {
                int f = str.indexOf("releaseVersionCode");
                if (f != -1) {
                    str = str.substring(f + ("releaseVersionCode").length()).trim();
                    Log.d("Rutracker free", "Last release version: " + str);
                    return Integer.parseInt(str);
                }
            }
            in.close();
            Log.d("Rutracker free", "Failed to get last release version!");
        } catch (Exception e) {
            Log.d("Rutracker free", "Failed to get last release version:");
            e.printStackTrace();
        }
        return null;
    }

    void checkUpdates(final MainActivity activity) {
        final Integer lastAppVersion = getLastAppVersion();
        if (lastAppVersion == null)
            return;
        if (lastAppVersion <= BuildConfig.VERSION_CODE) {
            Log.d("Rutracker free", "App version is okay, skipping update");
            return;
        }
        String li = SettingsManager.get(activity, "LastIgnoredUpdateVersion");
        if (li != null) {
            Integer liInt = Integer.parseInt(li);
            if (liInt >= lastAppVersion)
                return;
        }

        activity.Update(lastAppVersion);
    }

}


3.3 Добавляем класс для хранения информации о том, что пользователь решил проигнорировать этот релиз:

public class SettingsManager {
    static String get(Context mContext, String key) {
        SharedPreferences settings = PreferenceManager
                .getDefaultSharedPreferences(mContext);
        String data = settings.getString(key, null);
        if (data == null)
            Log.d("SettingsManager", "No settings " + key + " is stored! ");
        else
            Log.d("SettingsManager", "Got settings " + key + " equal to " + data);
        return data;
    }

    @SuppressLint("CommitPrefEdits")
    static void put(Context mContext, String key, String value) {
        SharedPreferences settings = PreferenceManager
                .getDefaultSharedPreferences(mContext);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(key, value);
        Log.d("SettingsManager", "Saved setting " + key + " equal to " + value);
        editor.commit();
    }
}


3.4 Добавляем функцию, которая покажет пользователю диалог с предложением перехода:

    public void Update(final Integer lastAppVersion) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setMessage("Доступно обновление приложения rutracker free до версии " +
                        lastAppVersion + " - желаете обновиться? " +
                        "Если вы согласны - вы будете перенаправлены к скачиванию APK файла,"
                        +" который затем нужно будет открыть.")
                        .setCancelable(true)
                        .setPositiveButton("Да", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                Intent intent = new Intent(Intent.ACTION_VIEW);
                                String apkUrl = "https://github.com/jehy/rutracker-free/releases/download/" +
                                        lastAppVersion + "/app-release.apk";
                                //intent.setDataAndType(Uri.parse(apkUrl), "application/vnd.android.package-archive");
                                intent.setData(Uri.parse(apkUrl));

                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                startActivity(intent);
                                dialog.dismiss();
                            }
                        })
                        .setNegativeButton("Нет", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                SettingsManager.put(MainActivity.this, "LastIgnoredUpdateVersion", lastAppVersion.toString());
                                dialog.cancel();
                            }
                        });
                AlertDialog alert = builder.create();
                alert.show();
            }
        });
    }



Вуаля! Всё, теперь у нас обновляемое приложение. А если оно когда-нибудь появится в Google Play или в другом магазине приложений, который есть у пользователя, то оно сможет обновляться ещё и оттуда.

Выводы


Что есть в сухом остатке — думаю, что без Google Play жить можно. И не только можно — нужно, минусы наличия монополиста на рынке очевидны. В том числе, если бы была хоть какая-то осмысленная конкуренция — возможно, общение с технической поддержкой было бы хоть какое-то адекватное, а не отписка пустыми шаблонами.

Так же хочу получить мнения от читателей.
  1. А как вы решаете проблемы бана приложения?
  2. Пользуетесь ли альтернативными магазинами приложений?
  3. Ставите ли приложения с каких-то других сайтов через apk?
  4. Как думаете, как мы будем ставить приложения на свои устройства лет через пять?


Ссылки


Комментарии (33)


  1. alltiptop
    17.03.2016 19:00
    -16

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

    Нет, не знает и не её это дело.


    1. jehy
      17.03.2016 19:08
      +12

      Вот даже не знаю, что ответить на ваше категоричное утверждение. Наверное, порекомендую прочитать эту статью ещё раз.


  1. keysi
    17.03.2016 23:03
    +1

    1. Я не пишу приложений под Android, но по скольку не вижу в этом ни чего сложного — в будущем это вполне возможно, вобщем-то давно хотел попробовать.
    2. Как пользователь, пробовал пользоваться Yandex.Store около полу года (года два назад) — при всём моём положительном отношении к Яндексу — результат оказался скорее отрицательным, он очень сырой (были ошибки и вылеты), много "заброшенных" приложений (обновления есть, но из Яндекса не обновляются), тёмная тема — специфично. Поиск слабоват. Плюсы были, но они померкли. Я вобще, не понимаю, какие у Яндекса могут быть притенении к Гуглу, если они свой магазин даже допилить толком не могут. Будет хорошее приложение, пользователи сами потянуться, раньше чтобы поставить Аскьу в телефон — в мастерские ходили и у всех смартфоноводов она была.
      Монополия гугл конечно не гуд, поэтому жду надеюсь и верю, что они таки допишут Store. Пробовал ещё какой-то китайский магазин, но без толковой локализации там делать нечего.
    3. Бывает, с 4pda.
    4. Ну например, через Телеграмм, скоро кажется через него вообще всё можно будет делать )


  1. BlackRaven86
    17.03.2016 23:40
    +1

    По поводу 4pda — хорошая идея. Еще сюда стоит добавить xda.


    1. cjmaxik
      18.03.2016 02:19
      +1

      В этом плане практически идеален App&Game 4PDA


  1. placebokid
    18.03.2016 03:32
    +1

    Ваше приложение практически невозможно заблокировать

    это не так. у гугла есть все механизмы для принудительного удаления любого приложения на девайсе пользователя. уже были прецеденты.


    1. powerman
      18.03.2016 04:48

      Ну, это на так смертельно, как кажется — на рутованном телефоне вполне можно заблокировать файрволом доступ в инет для "сервисов гугл" и "play market", открывать доступ последнему только в тот момент, когда его запустили ручками чтобы обновить приложения, а первому только в тот момент, когда этого потребует последний для периодической авторизации и буквально на минуту.


      1. powerman
        18.03.2016 04:49

        Да, даже если он успеет что-то удалить за эту минуту — TitaniumBackup всё восстановит.


        1. TheShock
          18.03.2016 05:21
          +3

          Главное, чтоб ТитаниумБекап не удалили)


      1. Alexeyslav
        18.03.2016 12:21

        Он первым же делом и удалит приложения помеченные на удаление. А если есть рут, то в чем проблемы перекрыть доступ маркета к конкретным файлам приложений на перезапись/удаление? а в целом пусть себе работает…
        К тому же, включать постоянно и отключать ему доступ убивает на корню всю затею с автоматизацией и ставит жирный минус на удобстве пользования.


        1. powerman
          18.03.2016 16:13

          Так я-ж не вручную файрвол переключаю — на то есть Tasker, он меняет профиль файрвола автоматом когда я ручками запускаю Play Market.


    1. Fury
      18.03.2016 09:32

      И это тоже не совсем так. Гугл может удалить любое приложение, установленное из Google Play — это прописано в пользовательском соглашении. Именно такие приложения он и удалил в прошлом, когда выяснилось, что через Google Play распространялось фишинговое приложение. К приложениям, установленным вручную, это не относится.


      1. jehy
        18.03.2016 11:10

        Да, всё так. Если мы полностью отказываемся от Google Play, то он даже не знает о нашем приложении.


  1. Snowly
    18.03.2016 03:51

    Без гугла становятся не доступны некоторые приложения. Например тот же Убер :(


  1. AdmAlexus
    18.03.2016 06:37

    По поводу ссылок на приложения в Yandex.Store.
    Попробуйте дать ссылку на приложение в таком виде:

    http://market://search/?q=pname:ххххх
    или
    https://market.android.com/details?id=ххххх

    Где xxxxx — имя пакета.
    Должен будет открыться диалог выбора маркета, в котором нужно открыть ссылку (при наличии нескольких маркетов на устройстве).
    Конечно костыль, но все же.
    Проверить к сожалению не могу. Устройств на андроиде под рукой нет.


    1. jehy
      18.03.2016 11:09

      Мне нужно не открыть приложение выбранным маркетом, а послать на установку приложения в выбранном маркете. В Google Play приложения просто нет.


  1. petrovichtim
    18.03.2016 09:32

    1. никак, её не решить
      2.нет
      3.нет
      4.также как и сегодня


  1. Alexko
    18.03.2016 11:26
    -1

    1. Про бан: соблюдайте правила и бана не будет.
    2. Про магазины: пробовал Яндекс, Samsung, Amazon и 4PDA. Распределение пользователей примерно следующее (в порядке убывания): Google Play — 88%, Samsung Apps — 9.5%, 4PDA — 1.8%, Яндекс — 0.4%, Amazon — 0.3%. Поэтому из альтернатив я бы выделил Samsung Apps и 4PDA.
    3. Сторонние APK стараюсь не ставить. Очень редко скачиваю с 4PDA.
    4. Останутся только лидеры среди магазинов.


    1. jehy
      18.03.2016 11:55

      Спасибо за ответ. По первому пункту — вот у меня не получилось.

      А почему стараетесь не ставить сторонние APK? Боитесь недокументированного превышения полномочий, или перехвата введённых данных? Или ещё чего-то?


      1. Alexko
        18.03.2016 13:39

        Во-первых, там может быть malware. Зачем лишний раз подвергать смартфон опасности? Можно, конечно, натравливать на APK-файл антивирусы, но на 100% гарантии защиты это не даёт.
        Во-вторых, нет возможности посмотреть оценки/отзывы других пользователей о приложении. Непонятно какого качества приложение будет кушать ресурсы смартфона и как часто вылетать.
        Ну и, наконец, возможность обновиться тоже является немаловажной.


        1. jehy
          18.03.2016 14:17

          Понял, в случае, если приложение совсем левое — полностью согласен. Но что если приложение с исходниками опубликовано на гитхабе и есть отзывы людей? И статьи на авторитетных ресурсах? И если там есть возможность полуавтоматического обновления с релизов в гихабе?
          Скажем, поставили бы вы моё приложение для просмотра рутрекера?


          1. Alexko
            18.03.2016 16:14

            Но что если приложение с исходниками опубликовано на гитхабе и есть отзывы людей?

            В этом случае доверия, естественно, больше. Но я лучше соберу проект у себя, чем буду скармливать непонятный APK.


  1. akalend
    18.03.2016 11:44

    Нужно научиться выживать без Гугль-Плай и других альтернативных сервисов. А ни кто не рассматривал версию, что завтра США под очередным предлогом введет новые санкции и отрежут нам все сервисы Гугля, как отрезали Яблочники все свои сервисы для жителей Крыма. А мы так привязались к сервисам корпорации Добра


    1. jehy
      18.03.2016 11:54
      +1

      Согласен. Но дело здесь не только и не столько в санциях, сколько в том, что полная монополия на распространение Android приложений это плохо. Сильно хуже становится качество сервиса при отсутствии конкурентов.


  1. nikitasius
    18.03.2016 12:07

    Мне вот что интересно… мобильная платформа, ресурсы:

    "Доступно обновление приложения rutracker free до версии " +
                            lastAppVersion + " - желаете обновиться? " +
                            "Если вы согласны - вы будете перенаправлены к скачиванию APK файла,"
                            +" который затем нужно будет открыть."

    Этж создание целых 5 стрингов в памяти. Не проще использовать для этого дела StringBuilder с его .toString() и быть виновным в создании всего 1-й строки?


    1. jehy
      18.03.2016 13:13
      +1

      Оно создаётся и сразу уходит из памяти, как только показан диалог. Ресурсы вы недооцениваете — на Arduino это было бы критично, а для приложения на андроид — никакого значения. Экономить на строках довольно бессмысленно — лучше писать быстро и понятно.
      Хотя в целом вы возможно и правы.


    1. withoutuniverse
      18.03.2016 13:14
      +2

      Так 5 стрингов в памяти там всегда будут.
      Вы наверное не поняли, почему лучше использовать стрингбилдер.
      Даже AndroidStudio предложит стрингбилдер заменить на сложение — под капотом всё будет оптимизировано в таких случаях.

      String result = "1" + "2" + "3";
      // под капотом без оптимизаций (но тут всегда оптимизация будет) превращается в
      String temp = "1" + "2";
      String result = temp + "3";

      В примере создается промежуточная строка. Если бы был вот такой цикл:

      String result = "";
      for (int i=0; i< 100; ++i){
          // тут проблема, так как оптимизировать работу со строками компилятор не сможет
          // постоянно создаются промежуточные строки и будет бессмысленная нагрузка на GC
          // и лучше заменить на StringBuilder, но в нем будет 100 элементов
          result = result + i;
      }

      Конкретно по вашему вопросу — строка создалась, строка удалилась после вызова GC — экономия на спичках, не то место для оптимизаций.


    1. lavelas
      18.03.2016 14:53
      +1

      Конкатенацию строковых литералов (типа "a" + "b" + "c") компилятор сам преобразует в StringBuilder.

      Однако, например, в циклах стоит использовать StringBuilder, как правильно подметил jehy

      Но лично я бы написал вообще так:

      String message = String.format(getString(R.id.new_update_message), lastAppVersion);

      И ресурс строковый

      <string name="new_update_message" formatter=true>"Доступно обновление приложения rutracker free до версии %s - желаете обновиться? Если вы согласны - вы будете перенаправлены к скачиванию APK файла, который затем нужно будет открыть.</string>

      Пишите приложения правильно


  1. gluck59
    18.03.2016 15:22
    +3

    Мы со своим Moto Helplist изначально пошли по пути отказа от Google Play / App Store — сделали все на HTML5 (у нас нет таких задач, которые требуют написания нативного приложения, возможностей HTML5 вполне хватает). Никаких левых сторов, никаких apk, superuser, jailbreak итд итп. На глаз все выглядит как обычный сайт: один раз зашел, все что под капотом установилось на устройство юзера, далее можно отключать интернет и работать. Ну и иконку на экран сохранить чтобы браузер не ругался на отсутствие интернета.

    Плюсы понимаете сами: практически полная кросс-платформенность (да и десктопы еще никто не отменял), проблема обновлений не стоит вообще, нет никаких цензоров, да и $125 в год для полностью некоммерческого проекта да еще и по сегодняшним курсам… В общем одни сплошные преимущества.

    Но задница пришла оттуда, откуда не ждали.

    Для 80% пользователей оказалось не под силу сохранить иконку на экран. Несмотря на три инструкции: текстовую, скриншоты и видео. Они просто этого не осилили. «Ну нишмогла я»© и все тут.

    Примерно 10% Стоящих на Страже возбудились на тему «вас нет в плей-маркете? значит у вас там вирус который украдет у меня сапоги и мотоцикл». Вот так просто, безапелляционно и железно, никакие аргументы не работают.
    Оставшиеся 10% спокойно установились, заходят и пользуются.

    Такая вот статистика…


  1. lavelas
    18.03.2016 15:23

    Выражу свое мнение по вопросу.

    Если приложение нарушает какие-то правила Play Store и его не пропускают, это совершенно не значит, что нужно отказываться от Play Store вовсе.
    Вы можете:

    • исправить замечания.
    • использовать альтернативные источники, как Вы и пишите в статье.

    Аналитика, crashreports — Flurry?

    Ручное автообновление приобретает смысл только, если Вы распространяете свое приложение исключительно через публикацию apk. Я бы как пользователь не понял, почему приложение, скаченное с Play (Yahho, Yandex не важно) Store вдруг перекинуло меня ан apk файл.

    Отдельно автору ссылка https://google.github.io/styleguide/javaguide.html. У Вас есть проблемы с оформлением кода. Например нельзя использовать UpperCamelCase для названия методов.

    activity.Update(lastAppVersion); // это воспринимается как статический класс у activity.

    Или имя пакета Вашего приложения должно было бы быть таким ru.jehy.rutrackerfree, но никак не ru.jehy.rutracker_free.


  1. magicstream
    20.03.2016 11:23
    +1

    Как web разработчик из крыма, могу констатировать одно — без google play жизнь есть, но она довольно тяжелая. Перекочевал на все перечисленные сторы — не срослось. Как уже было замечено, альтернативные сторы не дотягивают по функционалу, актуальностью приложений и стабильностью. Единственное место для доступа к актуальным приложениям без гугла для меня остается 4pda.ru. Но чаще использую VPN тунель для тоступа к google play. Но и офтоп: google play это пол беды, жизнь без google — вот ЭТО действительно проблема — привет из партизанской VPN-овой жизни


  1. woobinda
    22.03.2016 12:48

    Мне кажется, что пользователи, заинтересованные в доступе к пиратскому контенту, будут менее требовательны к происхождению клиента, который позволяет им это сделать. Так что установки с незнакомого сайта не будут опасаться. Не говоря уже о том, что на 4pda это сайт для многих знакомый.

    Другое дело, что "витрины" к rutracker будет недостаточно, просмотрщик со встроенным торрентом показался бы более интересным продуктом (есть же какие-то торренты с открытым кодом, которые вы могли бы интегрировать?). Ну, и тогда можно будет не ограничиваться одним рутрекером.


    1. jehy
      22.03.2016 12:53

      Торрент клиентов под android есть в количестве — можно выбрать на вкус и цвет. Уверен, что у всех, кому актуально — уже стоят.
      Интегрировать что-то своё, пусть даже на основе открытого кода — это просто получить головную боль по поводу поддержки.
      Ну и практика пока что показывает, что интерес к моему клиенту — ниже плинтуса. Есть звёздочки и форки на гитхабе, но отзывов и коммитов нет. Видимо, кому нужно — уже давно нашли свои способы обхода. Но что же — у меня была цель немного "поиграть" в приложение, а не делать что-то коммерчески успешное — эту цель приложение выполнило с лихвой.