Пользователь
0,0
рейтинг
9 июня 2013 в 02:26

Разработка → Модификация стоковых прошивок для Android. Часть 2

Здравствуй Хабр!

После написания первой части, в течение всей недели я размышлял о том, стоит ли писать о том что обещал или же по просьбе некоторых читателей дать разъяснения и объяснения по поводу некоторых, на мой взгляд базовых, вещей.
Не хотелось бы, но придется некоторых из вас расстроить. Писать самому — займет слишком много времени и сил, «копипастить» я не люблю больше всего, а делать из статьи кучу ссылок на разные ресурсы — будет моветон.

Например, описывать как происходит загрузка Android в данной статье будет не уместно. Если вы знаете принцип инициализации аппаратного обеспечения вашего компьютера в BIOSе, а затем его загрузка через ядро системы, то Android в этом плане ничем не отличается. Разница лишь в процессорной архитектуре. Структура файловой системы? Ну господа, это же чистой воды UNIX система, и писать где, что и как хранится — абсурдно! Править build.prop — это тюнинг системы. Да, это модификация, но большую часть этих параметров можно сделать сторонними приложениями, причем удобными для пользования, например System Tuner.

Понять самому принципы системы Android заняло у меня пару месяцев, столько же займет времени и писать статьи, чтобы осветить все базовые вещи. Так что давайте лучше будем писать о конкретных примерах как разбирать Dalvik код и создавать на телефоне удобства «пользования».

И так, поехали! Сегодня я расскажу как я реализовал функционал автоматической записи телефонных разговоров родными средствами.

Преамбула


Законодательство некоторых стран запрещает производить запись телефонных разговоров техническим средствами. Например в США запрещается записывать личные телефонные разговоры без предварительного согласия сторон. А на нашем пост-советском пространстве разрешено записывать беседу, в которой вы являетесь одной из сторон, без предупреждения других участников беседы. В том же самом Китае запись просто напросто приветствуется и «стучать» на соседа — идеологический принцип. И это касается не только записей разговоров. Пользование интернетом, отправка СМС сообщений, пользование соц сетями, алгоритмы шифрования, телефоны с двумя SIM картами и многое другое также индивидуально регламентируются законодательством разных стран. А теперь представьте, что вы владелец бизнеса и экспортируете свою IT продукцию по всему миру. Разумеется, свое программное обеспечение вы будете «писать» одной веткой, а не несколькими, но вот конфигурации будут отличаться от региона к региону. Для стран СНГ одно, для Европы — другое. Также и поступают производители телефонов. Операционная система Android дорабатывается только одной группой программистов и в основную ветку, а для каждого региона при компиляции финальных релизов используются специфичные конфигурационные файлы. Говорю это с уверенностью, так как работал в свое время у одного из вендоров.

В доказательство этому есть хорошее руководство как делать портирование прошивки на чужое устройство.

Поехали!


Читая дизассемблированый JAVA код Phone.apk я случайно наткнулся на занимательный флаг. Интересного, но скрытого от нас функционала на самом деле очень много. Буквально сегодня обнаружил, что на моем телефоне есть параметры для японского оператора KDDI. Специально сформированное СМС сообщение от провайдера может заставить мой телефон истошно издавать звуки и вибрировать несколько минут в случае землетрясения или цунами. Но вернемся к нашему флагу.
public static final boolean IS_INCALL_RECORDING_ENABLE = false;

Занимательно, подумал я. Если есть такой флаг, значит он где-то используется. Но вот где — не понятно. Тем не менее, я предположил, что кнопка записи звонка должна появляться во время звонка. Дело за малым! Я изменил FALSE на TRUE, перезаписал патченный Phone.apk, позвонил на домашний телефон, поднял трубку и увидел кнопку «Начать запись». А ведь раньше ее не было!!!


Еще раз расскажу как делать подобные вещи для усвоения материала:

  1. Создаем отельную папку и кладем туда Phone.apk файл и к нему smali и backsmali
  2. Потрошим файлик, чтобы разобрать до Dalvik кода командой java -Xmx512m -jar baksmali.jar -a -d -o Phone -x Phone.apk

    — это API вашей версии Android. Для JB — это 16
    — папка, где находятся все фреймворки прошивки.

    Открываем в текстовом редакторе файл, в котором нашли флаг Phone\com\android\phone\util\VoiceRecorderHelper.smali
    Заменяем
    .field public static final IS_INCALL_RECORDING_ENABLE:Z = false
    
    на
    .field public static final IS_INCALL_RECORDING_ENABLE:Z = true
    

    Собираем наш файл обратно: java -Xmx512m -jar smali.jar -a 16 Phone -o classes.dex
    Заменяем полученный classes.dex в оригинальном файле любым архиватором
    Перезаписываем Phone.apk в телефоне

    Протестировав запись нескольких звонков, я обнаружил, что телефон записывает разговоры стандартным встроенным диктофоном и при чем в очень и очень хорошем качестве. Название файлов формируется автоматически и содержит номер или имя собеседника, а также дату и длительность звонка. Формат сохранения файлов также можно настроить в родном приложении. А зачем вы спросите мне вообще нужны эти записи звонков?

    Ну, во-первых, очень удобно. Позвонила супруга и наговорила список продуктов для покупки, а записать некуда, тут-то и поможет диктофон.
    Во-вторых, по телефону мне приходится разговаривать с клиентами и заказчиками и порой нужная и важная информация может ускользнуть или быть не расслышана. Или, допустим, состоялся важный разговор, который надо прослушать и проанализировать и принять своевременные решения иди действия вместе с партнером по бизнесу или кем-то еще.
    В-третьих, очень удобная доказательная база в работе и быту.

    Вы также можете спросить а почему бы не пользоваться сторонними приложениями, коих полно в открытом и бесплатном доступе?
    • Я не доверяю сторонним и не проверенным приложениям. Зачастую, из-за них садится батарейка, так как каждое подобное приложение висит постоянно в памяти телефона и отжирает процессорное время.
    • Качество записи не всегда соответствует обещанному.
    • Я привередлив к интерфейсу. Приложением может быть богато функционалом, но если мне не удобен GUI, я его не буду использовать. Этим хромают многие отечественные разработки, к сожалению.

    Как это вообще работает?


    Всем разработчикам под Android известно, что в системе полно различных стандартных широковещательных сообщений. Что бы ни произошло в системе, любое приложение его может получить, если реализовать "своего" получателя такого сообщения. Можно сделать свои широковещательные сообщения, только получатель этого сообщения будет само приложение или все приложении, которые сделали вы сами и они это сообщение как-то обрабатывают. Я такое в практике видел в GoDialer и GoSMSPro.

    Таким же образом работают и сторонние приложения записи звонков. Как только прошло сообщение, что был установлен звонок, включается запись. Как только звонок прекратился, запись останавливается и буфер записывается в файл.

    Моя задача состояла в том, чтобы найти то место, где формируется это самое сообщение или обрабатывается и принудительно начинать запись звонка без лишних телодвижений. Ведь часто бывает, что или забываешь включать или просто-напросто не успеваешь. Как вообще искать нужное место в тонне кода прошивки - тема следующей статьи, а пока перейдем сразу к "нашему месту".

    Обработчик, а точнее два, оказались в файле \com\android\phone\CallNotifier.java

    Декомпилированный код (здесь показана только часть кода) из Dalvik в Java оказался следующим:

      private void onCallConnected(AsyncResult paramAsyncResult)
      {
        Connection localConnection = (Connection)paramAsyncResult.result;
        String str = ((IfConnection)localConnection).getDialString();
        VLog.d("onCallConnected() dialed number:" + str);
        removeMessages(120000);
        removeMessages(120001);
        this.mIsEccNeedRetry = false;
        this.mEccIsSwitchingForRetrying = false;
        // много много кода
      }
    
    и
      private void onDisconnect(AsyncResult paramAsyncResult)
      {
        Phone.State localState = this.mCM.getState();
        if (CallNotifier.VDBG)
          super.log("onDisconnect()...  CallManager state: " + this.mCM.getState());
        VLog.d(this, "onDisconnect()");
        removeMessages(120000);
        removeMessages(120001);
        // много много кода
      }
    

    Задача усложняется, по сравнению с прежней статьей. Если в прошлый раз нам надо было исправить простую функцию, то здесь мы ее исправить не сможем, так как у нас нет исходного кода, чтобы его переписать. Здесь нам нужно вживить свой код.

    Что такое Dalvik?


    Об этом кратко написано здесь и здесь. Если говорить на еще более простым языком - байт код виртуальной машины основан на регистрах (выделенная область памяти для оперирования переменными) и множества инструкций и операторов. Смысл и принцип работы довольно прост: вы записываете в регистр какое-то значение и затем совершаете над ним операции, результат операции возвращаете туда, от куда за действиями обращались. Более подробно обо всех операторах и инструкциях можно подсмотреть здесь: Bytecode for the Dalvik VM.

    Вживляем наш код


    Для того чтобы что-то вписать, нам надо знать что туда вписывать. Слизать код можно с обработчика кнопки "Начать запись".
    Найти где хранится обработчик даже начинающим программистам для Android это не составит труда. Мы потом еще вернемся к тому что и как искать в будущих статьях. Суть первых статей объяснить принципы.

    При нажатии кнопки, срабатывает следующий код:
         VoiceRecorderHelper localVoiceRecorderHelper = VoiceRecorderHelper.getInstance();
          if (!localVoiceRecorderHelper.isRecording())
          {
            localVoiceRecorderHelper.start();
          }
    
    То есть чтобы автоматизировать запись всех звонков, надо этот код добавить в обработчик onCallConnected.

    Dalvik код этой записи выглядит как

        invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper;
    
        move-result-object v1
    
        invoke-virtual/range {v1 .. v1}, Lcom/android/phone/util/VoiceRecorderHelper;->isRecording()Z
    
        move-result v2
    
        const/4 v3, 0x0
    
        if-ne v3, v2, :cond_a9
    
        invoke-virtual/range {v1 .. v1}, Lcom/android/phone/util/VoiceRecorderHelper;->start()Z
    
        :cond_a9
    

    Разберем код построчно:
    1. invoke-static вызывает экземпляр класса VoiceRecorderHelper
    2. сохраняем экземпляр в регистр v1
    3. вызываем метод этого класса под названием isRecording, который возвращает true или false
    4. Результат записываем в регистр v2
    5. Записываем в регистр v3 значение 0
    6. Делаем сравнение между двумя регистрами v2 и v3. Логика: v2 != v3. Если isRecording вернет TRUE, значит v2 будет иметь значение 1 и если FALSE то наоборот. Если условие НЕ срабатывает, то прыгаем на маркер cond_a9. Если нет, то
    7. Вызывается метод start экземпляра класса, который хранится в регистре v1
    8. Наш разговор начал записываться.


    Возвращаемся к нашему onCallConnected. Его dalvik код выглядит следующим образом:
    .method private onCallConnected(Landroid/os/AsyncResult;)V
        .registers 8
        .parameter "r"
    
        .prologue
    
        .line 2302
        iget-object v0, p1, Landroid/os/AsyncResult;->result:Ljava/lang/Object;
    
        check-cast v0, Lcom/android/internal/telephony/Connection;
    
        .local v0, c:Lcom/android/internal/telephony/Connection;
    
        move-object v2, v0
    

    Давайте и этот код разберем, чтобы было понятно что к чему относится

    • .registers 8 - количество регистров памяти, необходимое и используемое для данной функции
    • parameter "r" - название параметра, которое было использовано в исходном коде. Нас оно редко интересует.
    • prologue - начало алгоритма функции
    • .line 2302 - номер строки в исходном коде. Это только для отладки.
    • iget-object v0, p1, Landroid/os/AsyncResult;->result:Ljava/lang/Object; следующая строка соответствует (Connection)paramAsyncResult.result;
    • check-cast v0, Lcom/android/internal/telephony/Connection; соответствует Connection
    • .local v0, c:Lcom/android/internal/telephony/Connection; соответствует localConnection
    • move-object v2, v0 - клонирование локальной переменной v0 в регистр v2
    • и т.д.

    Разбирать код не так уж и сложно, если обращаться к описанию и сравнивать с Java кодом.

    Казалось бы, нам нужно всего лишь скопировать код из обработчика нажатия кнопки и вставить в начало нашего обработчика звонка и готово. Не тут то было. Иногда это работает, но большей частью нет. Дело в том, что регистры, куда мы записываем данные, могут использоваться в дальнейшем коде программы и если в начале мы возьмем неправильный регистр и запишем в него что-то, то по ходу исполнения программы могут вылезть ошибки и поломаться весь алгоритм. Наш случай прост в том, что мы вписываем в начало функции и можем использовать любые регистры, которые не инициализированы в начале, потому как они будут перезаписаны в дальнейшем. Но часто код приходится вживлять где-то в середине программы и с регистрами нужно быть осторожным. Об этом тоже в будущих статьях.

    Модификация регистров

    Наши первые две строки вживляемого кода имеют следующее:

        invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper;
    
        move-result-object v1
    
    Самый простой способ искать подходящие номера регистра - это поискать в самом методе какие виды данных записываются в необходимые номера регистров. Если поискать в коде, то обнаружим, что move-result-object у нас записывается и в v2 и v 3.
    Соответственно все наши v1 во вживляемом кода заменим на v2 или v3

    Проделав все операции по замене номеров регистров во вживляемом кода получаем следующую картину:

        invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper;
    
        move-result-object v3
    
        invoke-virtual/range {v3 .. v3}, Lcom/android/phone/util/VoiceRecorderHelper;->isRecording()Z
    
        move-result v4
    
        const/4 v5, 0x0
    
        if-ne v5, v4, :cond_27
    
        invoke-virtual/range {v3 .. v3}, Lcom/android/phone/util/VoiceRecorderHelper;->start()Z
    
        :cond_27
    
    Стоит отметить, что маркер cond_a9 мы изменили на cond_27. Дело в том, что маркер cond_a9 уже имелся в том файле, куда мы вживляли код и второй раз такой маркер не может быть использован. Номер маркера - шестнадцатиричный код и может быть любым, главное уникальным.

    Теперь в исходном файле заменяем строку .line 2302 на наш вживляемый код и получаем
    .method private onCallConnected(Landroid/os/AsyncResult;)V
        .registers 8
        .parameter "r"
    
        .prologue
    
        invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper;
    
        move-result-object v3
    
        invoke-virtual/range {v3 .. v3}, Lcom/android/phone/util/VoiceRecorderHelper;->isRecording()Z
    
        move-result v4
    
        const/4 v5, 0x0
    
        if-ne v5, v4, :cond_27
    
        invoke-virtual/range {v3 .. v3}, Lcom/android/phone/util/VoiceRecorderHelper;->start()Z
    
        :cond_27
        .line 2302
    
        iget-object v0, p1, Landroid/os/AsyncResult;->result:Ljava/lang/Object;
    
        check-cast v0, Lcom/android/internal/telephony/Connection;
    
        .local v0, c:Lcom/android/internal/telephony/Connection;
    
        move-object v2, v0
    


    Осталось теперь собрать наш код с помощью команды java -Xmx512m -jar smali.jar -a 16 Phone -o classes.dex, заменить в Phone.apk и протестировать.

    В Java варианте наша работа стала выглядеть следующим образом:
      private void onCallConnected(AsyncResult paramAsyncResult)
      {
         VoiceRecorderHelper localVoiceRecorderHelper = VoiceRecorderHelper.getInstance();
         if (!localVoiceRecorderHelper.isRecording())
         {
           localVoiceRecorderHelper.start();
         }
        Connection localConnection = (Connection)paramAsyncResult.result;
        String str = ((IfConnection)localConnection).getDialString();
        VLog.d("onCallConnected() dialed number:" + str);
        removeMessages(120000);
        removeMessages(120001);
    


    Все хорошо, все работает, но единственная проблема, после завершения разговора, запись звонка продолжается бесконечно.
    Для этого нам надо прописать подобный код и в начале функции (метода) onDisconnect, только с обратной логикой.

         VoiceRecorderHelper localVoiceRecorderHelper = VoiceRecorderHelper.getInstance();
         if (localVoiceRecorderHelper.isRecording())
         {
           localVoiceRecorderHelper.stop();
         }
    


    По аналогии с началом записи, мы пишем небольшую процедуру, заменяя номера регистров

    .method private onDisconnect(Landroid/os/AsyncResult;)V
        .registers 41
        .parameter "r"
    
        .prologue
    
        invoke-static {}, Lcom/android/phone/util/VoiceRecorderHelper;->getInstance()Lcom/android/phone/util/VoiceRecorderHelper;
    
        move-result-object v34
    
        invoke-virtual/range {v34 .. v34}, Lcom/android/phone/util/VoiceRecorderHelper;->isRecording()Z
    
        move-result v4
    
        if-eqz v4, :cond_33
    
        invoke-virtual/range {v34 .. v34}, Lcom/android/phone/util/VoiceRecorderHelper;->stop()Z
    
        .line 2487
        :cond_33
    

    собираем наши изменения, заменяем в телефоне и вуаля - все работает так как должно.

    Эпилог


    Уверен, данный материал по сравнению с предыдущей статьей оказался в несколько раз сложнее и запутанней. Какие-то регистры, операторы, модификаторы... Похоже на бред. Я сам в первый раз когда увидел Dalvik - ужаснулся, закрыл страничку и не открывал ее в течение полу года. Когда прижало к стенке, в течение двух недель быстро разобрался что к чему и как это реализовать на практике. Что радует, за всю практику ни разу не получал кирпич.

    Не для рекламы ради, хочу посоветовать два ресурса, на которых можно почерпнуть много информации:

    Русскоязычный и Англоязычный
    На обоих ресурсах я присутствую с тем же ником.

    А пока до следующей статьи, надеюсь через неделю.
Нурлан Муханов @Falseclock
карма
59,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

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

  • 0
    интересно, а почему не брать исходники из AOSP? если патчить стоковую, то сырки андроида отлично для этого дела подойдут.
    • 0
      Ну я уже отвечал на подобный вопрос в предыдущей статье. AOSP берется только за основу и в течение нескольких месяцев допиливается производителем до нужного функционала. В финале код большей частью отличается от того, что было в оригинале.
  • –3
    В США запрещается записывать личные телефонные разговоры без предварительного согласия сторон
    Не понимаю зачем выпиливать эту функцию. Есть стандартное решение, которое применялось с незапамятных времен — писк каждые 20 секунд. Добавить к этому воспроизведение фразы «Производится запись разговора» при старте записи и порядок.

    Вообще интересно было бы заиметь твикер под рутованый андроид, который в автоматическом режиме скачивает последнюю версию приложения, делает изменения в исходниках на основании выбранных настроек, компилирует и обновляет apk
    • 0
      Меня бы и моих собеседников сильно не то чтобы раздражало, а напрягало, если бы был писк и еще чей-то голос говорил что разговор записывается.

      А вот то что вы предлагаете — вещь хорошая. Единственное, требует разработки и поддержки. Но все разработчики делают и публикуют свою тяжелую работу бесплатно и в большой противовес и конфликт их личной жизни. На XDA я выкладываю все патчи в открытом доступе, чтобы их могли применить на других прошивках.
      • +1
        напрягало, если бы был писк и еще чей-то голос говорил что разговор записывается
        По этому мы вообще спрячем такую возможность. Это лишь один из вариантов оставить возможность записи разговора без рутования и сторонних приложений. Те, кого будет раздражать сигнал могут рутовать устройство и удалить звуковые файла, как это успешно происходит сейчас.
        • 0
          Прежде чем телефон появляется на прилавках наших магазинов, он проходит сертификацию. Если тот или иной функционал противоречит законодательству, то производителя принуждают изменять его или удалять. В России этим занимается РОСКОМНАДЗОР.

          Не знаю как в России, но допустим у нас в Казахстане Комитет Национальной Безопасности (аналог российского ФСБ), запрещает ввозить на территорию страны устройства шифрования с ключами более 128 бит.
          • 0
            Как же у вас Wi-Fi с WPA2 работает?
            • +1
              а вот так вот и работает. Все эти правила только для того, чтобы развиваться взяткодательство.
    • 0
      Компилировать и декомпилировать даже smali код на устройстве — это довольно глупая затея. У кросс-компиляторов это выходит гораздо быстрее и лучше.
      • 0
        Пример покажете?
        • 0
          В смысле пример чего? Я обычно черпаю вдохновение тут, а собираю-разбираю этим набором. Но все это для китайцев на медиатек.
          • –1
            Разбирать — собирать я тоже могу разными наборами, это и ApkManager и APK-Multi-Tool и Apk_OneClick и Virtuous Ten Studio (VTS) и многие другие.
            Разрешите еще раз объяснить смысл статьи. Я не пытаюсь научить пользоваться готовыми тулзами, я хочу рассказать на основе чего и как эти приложения работают.
            • 0
              Тогда хотел бы почитать еще про bootclasspath, манифест и подпись сертификатами. И ссылку на часть первую в текст этой части.
              • 0
                bootclasspath — список JAR библиотек, необходимых для нормального запуска всех системных приложений.
                manifest — определитель разрешений и компонентов приложения.
                подпись — это вообще краеугольный камень Андроида. Многие задаются вопросами зачем оно нужно, если можно подписать самопальной подписью. В тематику данных статей описывать не планирую.
                Ссылка добавлена. Спасибо.
  • +2
    Статья интересная, но на какой же дряни вы разместили одну единственную картинку…
    • +1
      Мне говорят там, что у меня опера на JB устарела.
      • –4
        Не страшно, обновитесь. Но каким образом это касается статьи?
        • +4
          Здесь намекают на вредоносные приложения :) на некоторых сайтах предлагают обновится даже если оперы нет
          • 0
            Только теперь понял )
          • 0
            Мой случай)
    • +2
      Извините, я новичок на Хабре, и не знал что есть есть хранилище. Мне тут в привате уже подсказали. Я исправил. В будущем такого не повторится.
  • 0
    А вот так эту задачу приходится решать обычным людям в американском сериале Elementary.
    nerdophiles.files.wordpress.com/2013/05/elementary-s01e22.jpg
    На первом телефоне включается громкая связь, а разговор записывается на второй телефон.

    Интересно, можно ли такое провернуть с Google Glass или очки не смогут сохранить звук на телефон, находящийся в режиме разговора.
    • 0
      Точно! Буквально вчера краем глаза увидел эту сцену, когда супруга смотрела сериал.

      В Google Glass, я так подозреваю, это тоже можно будет делать. Ведь там есть и камера и диктофон, соответственно их можно будет задействовать и при записи разговоров.
  • –8
    Я все-все знаю, но вам ничего рассказывать не буду. Жалкие людишки, проникнитесь моей крутостью!!!
  • 0
    Спасибо за статью, есть пару вопросов. Первый по теме — обязательно ли модифицировать Phone.apk из родной прошивки, или можно взять любой пропатченный для данной версии андроида?

    И второй уже оффтоп — может быть Вы в курсе, какой есть кошерный способ по управлению пермишнами установленых приложений? В свое время я сильно удивился, что на айфоне можно практически на ходу менять, какие из запрошенных разрешений можно удовлетворять, а какие заблокировать. На андроиде же из стока можно лишь посмотреть список запрашиваемых разрешений, и либо отклонить установку, либо разрешить все сразу. Из приложений для управления пока нашел только PermissionManager, который после настройки пермишнов переустанавливает приложение, при этом обнуляя данные — их приходится предварительно бекапить и восстанавливать, а ещё ломается обновление приложение через стор. Как быть?
    • +2
      LBE Privacy Guard работает как фильтр.
      При выполнении действия, которое сконфигурировано как фильтруемое, всплывает сообщение: программа XXX пытается определить ваше местоположение (выйти в интернет, прочитать контакты, совершить звонок, посласть СМС). Разрешить? Да/Нет/Всегда для этой программы.
      • 0
        Огромное спасибо, удивительно, что в поиске по «permission» не находит его, а программа — то что надо.
    • 0
      обязательно ли модифицировать Phone.apk из родной прошивки, или можно взять любой пропатченный для данной версии андроида?

      Чужой Phone.apk должен запуститься в вашей прошивке, он завязан много на что. Абы какой просто не появится в меню.
      • 0
        НЕ должен. Многие приложения пользуются системными ресурсами, как например изображения, layout, xml файлы и прочее. Каждый ресурс имеет свой идентификатор. Запуститься Phone.apk он может, но работать он будет 99% не корректно.

        Исключением являются стоковые прошивки для одной серии телефонов.
        Например у HTC есть такие девайсы как HTC One S, HTC One SU, HTC One SC, HTC One SV.
        Системные приложения между этими прошивками будут работать всегда. Тестировали, работает.
        • 0
          мое сообщение следует читать как «должен еще как минимум запуститься»
    • 0
      Я так понял вы хотите взять мой Phone.apk и запустить на своем телефоне? Не получится. Все приложения при компиляции автоматически генерируют идентификаторы ресурсов, которые hardcoded внутри байт кода.

      Стандартными средствами нельзя, все разрешения записаны в манифесте приложения. Есть приложения, которые мониторят те или иные действия других приложений и предупреждают пользователя. Если приложение имеет больше системных прав, оно может блокировать действия другого. Так устроены перехватички замены системным приложениям, допустим набиратели номеров, отправители СМС и т.п.
      • 0
        Понятно, жаль, хотел немного времени сєкономить )
        • 0
          Если у вас есть DEODEXED вариант Phone.apk, дайте мне ссылку, я с удовольствием гляну на код
    • 0
      Сторонние прошивки, типа Cyanogenmod, вполне позволяют менять разрешения на лету, и нативно, без доп. приложений. Хотя LBE и крут.
      • 0
        Не нашёл в Cyanogenmod такого функционала, не подскажете где искать?
        • +1
          Открываете свойства любого приложения — там, где список разрешений внизу. Тыкаете по этим разрешениям, они зачёркиваются.
        • +1
          Да, мне тут из яндекса подсказывают, что предварительно надо галку в настройках поставить. Вот, коллаж — слева галка, справа разрешения приложения.

          • 0
            Судя по всему это в ветке Cyanogenmod 7 (в Cyanogenmod 9-10 такой галочки не нашёл). А может просто особенности сборки под Desire HD, хотя вряд ли.
            • 0
              В 9 и 10 тоже вполне есть, игрался.
  • 0
    Например в США запрещается записывать личные телефонные разговоры без предварительного согласия сторон


    Это не так. Только 12 штатов требуют согласия всех сторон для записи разговора. В остальных 38 плюс ДиСи вторая сторона может записывать разговор без уведомления первой.
    • 0
      Да, вы совершенно правы, но для производителей телефонов это все равно что запрещено.
  • +2
    Это вам ещё повезло, что в ядре запись с линии присутствует.
    Для моего HTC Desire Z на 4pda сначала искали разработчика, который бы добавил в ядро аудио-девайс «линия», потом его краудфандили, потом ждали полгода результата и наконец-то, получили ядро с записью (через надцать бета-версий, зависающих и глючащих, пропускающих звонки) и программу Call Recorder (в phone.apk вообще функционала записи нет)
    • 0
      Call Recorder — на моем телефон тоже не умеет писать с линии. Связывался с разработчиком, он меня упорно убеждал что мне надо компилировать ядро. Но вот все же как-то получается с линии записывать. Чудеса?

      Во многих стоковых прошивка диктофон есть, только в манифесте приложения отсутствуют интенты.
                  <intent-filter>
                      <category android:name="android.intent.category.LAUNCHER" />
                  </intent-filter>
      
      , соответственно запустить в оболочке приложение нет возможности, так как нет ярлыка. Но никто не мешает запустить его сторонним приложением или создать собственный ярлык.
      • 0
        У вас посвежее телефон. Мой — старичок на Android 2.3
        Возможно, в 4-й ветке сам гугл сделал этот функционал.
  • +1
    Уверен, данный материал по сравнению с предыдущей статьей оказался в несколько раз сложнее и запутанней. Какие-то регистры, операторы, модификаторы…

    По-моему, эта статья получилась более понятной.

    Не знаю как других, а меня всегда раздражало, когда в институте препод, пытаясь что-то объяснить, сначала пытался привести аналоги и примеры, и только потом начинал рассказывать «сложно» (с формулами и т.д.). Он тогда сначала запутывал аналогиями и «сложный» материал воспринимался уже не так.
    Я считаю, что материал надо давать сначала сложный, а потом объяснять и приводить аналогии!
    Это я к чему? К тому, что за счёт именно такой подачи материала — он усваивается лучше. Как и было в этой статье!
    Так держать!
    • 0
      Согласен, имея очень небольшой опыт, все понятно. Автору спасибо за что что раскладывает все по полочкам на простом языке.
      У меня, к сожалению, папки Phone\com\android\phone\util нет, так бы потренировался.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.