written on Tuesday, June 4, 2013
Телефонний додаток успішно звалив у яблуний аппстор.
Там його ніхто особливо не ставить, окрім тридцяти трьох китаєзів, бо опис у аппсторі майже пустий, а по скріншотах ніхуя не зрозуміло. Зараз я роблю наступний шмат роботи — порт на андроїд.
Додаток розбито на дві частини — юзерський інтерфейс та евентлуп на libre, який займається асинхронним вводом-виводом, реалізує протокол, всю логіку і смикає вкомпілені кодеки.
Фактично, це окремий демон, який для зручності прикидається бібліотекою. У нормальному лінуксі він може працювати як демон, що слухає локальний сокет, на яблучній платформі — статична бібліотека, яка працює в окремому потоці, а замість локального сокета юзає пайпи. На андроїді бібліотека вийшла динамічна, дані ганятимуться по локальному сокету, але в принципі принцип той самий — окремий шматок коду, в який можна пиздякати текстовими командами і який не шарить ніяких даних з інтерфейсом.
Оскільки вся логіка винесена в окремий шмат на сішечці, він мав би легко портуватися. В теорії.
На практиці вилазить купа противних нюансів, починаючи з кривих шляхів усередині сендбоксу і до відсутності в андроїдовій libc потрібних функцій та хедерів.
Наприклад, в андроїді нема ifaddrs.h, але скрипти збірки libre цього в сраку не бачать — доводиться ставити криві хаки, які потім окультурювати.
При цьому андроїдів тулчейн цілком собі детектиться як linux — і треба ставити додаткові іфдефи, щоб відрізнити правильний лінукс від неправильного.
Зі шляхами взагалі смішна історія. Для чотирьох платформ (OSX, iOS, великий лінукс і андроїд) треба різні шляхи для бази даних, сертифіката та підвантаження ресурсів. В iOS ресурси треба шукати всередині $HOME (який пісочниця), на великій макосі — шукати по тому шляху, куди засунуто додаток. В андроїді теж пісочниця, але шлях до неї не прописано в $HOME, а дістається якимось дуже дебільним кодом із жаби, а на великому лінуксі ресурси можуть валятися де завгодно.
Очевидна проблема — звук. Для iOS і OSX у мене майже універсальний код, для великого лінукса є ALSA, а на андроїді стається "ой" — замість альси доводиться юзати OpenAL.
Якщо на яблучних платформах все достатньо просто — досить кросскомпілювати сішний код, підключити статичну лібу (ну, мішок ліб), то на андроїді треба танцювати з NDK/JNI. Оскільки мені треба зовсім мало — смикнути одну єдину функцію — все пройшло досить гладко, якщо таке слово взагалі можна прикласти до кросскомпіляції кривої хуйні під наркоманський таргет. Всього-то один день убив, та й то не весь. Можна сказати, легко відбувся.
В результаті — дві динамічні ліби: сам драйвер, який збирається окремо, і JNI-прослойка, яка з ним лінкується і доступна для смикання з жаби.
Зараз це все на стадії пруф-оф-концепта. Є андроїдівський додаток, який взагалі ніхуя не робить, є драйвер, втикнутий туди через JNI, який успішно крутить свій евентлуп, грузить сертифікат і реєструється на сервері.
Тепер треба настроїти IPC між жаба-частиною та сішним модулем, причесати хвости накшталт захардкоджених шляхів до пісочниці та "зайвих" функцій, які андроїд не вміє, зробити сам UI і зробити звук. Ну всього-нічого, да.
Паралельно я планую всунути в сішну частину більше пекла — наприклад, генерацію приватного ключа і взагалі цикл сігнап-логін-релогін, який зараз працює тільки на яблучній платформі і стирчить в "інтерфейсній" частині.
Пекельну систему зберігання логів та контактів теж треба засунути всередину і смикати через IPC, але це вже після того, як в UI запрацює логінілка і кнопка "дзвонити".