?

Log in

Use NDK in Android Studio, part 2

Якщо у минулому пості мова йшлася здебільшого про оточення, зараз перейдемо до дійсно C++. Отже, припустимо, що вам потрібно піднести до квадрату, що буде виглядати таким приблизно чином у java (SquaredWrapper.java)

1. Create Java source

package com.anonym.myapplication;

public class SquaredWrapper {
// Declare native method (and make it public to expose directly)
public static native int squared(int base);
}

Ми навмисно починаємо з оголошення у java і залишаємо реалізацію на C++ на потім. Шлях навпаки, коли в нас вже є готові методи на C++ і треба викликати їх із java, буде розглянуто в подальшому.

2. Create C header

Зрозуміло, що подане оголошення існує виключно заради того, щоб дістатися "рідного" методу на C++, але ж як цій "рідний" метод треба декларувати? Щоб втямити це, JDK має утіліту під назвою javah. Вона отримує скомпільований java-код (наприклад, файл з розширенням class). Тож скомпілюємо його:

javac SquaredWrapper.java

та запустимо javah. Треба мати на увазі, що package, якого визначено на початку java файлу, впливає на поведінку javah. Найзручніше, на мою думку, запускати javah з діректорії 'java' під 'main' головного проекту. У цьому випадку треба визначити лише цілкове ім'я package з додатком ім'я класу.  У нашому випадку це буде виглядати

C:\Dev\Android\MyApplication\app\src\main\java>javah com.anonym.myapplication.SquaredWrapper

Побудований файл буде мати назву com_anonym_myapplication_SquaredWrapper.h, але ж його вартить перейменувати, наприклад, до SquaredWrapper.h та пересунити до діректорії, де будуть розташовані подальші C++ файли.

Роздивимось змісту файлу, що було побудовано:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_anonym_myapplication_SquaredWrapper */
#ifndef _Included_com_anonym_myapplication_SquaredWrapper
#define _Included_com_anonym_myapplication_SquaredWrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     com_anonym_myapplication_SquaredWrapper
* Method:    squared
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_anonym_myapplication_SquaredWrapper_squared
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif

Звернемо увагу до ім'я, яке отримав наш метод. Його побудовано таким чином:
1. текст "Java_"
2. ім'я пакету, де крапки змінені на символи підкреслення
3. ім'я класу, до якого належить метод
4. дійсно і'мя методу

Перші 2 параметри до будь-якого методу, створеного за допомогою javah, не змінні. Інші залежать від типов, декларованих у java-коді. Ось, наприклад, метод, якій отримує масив:

JNIEXPORT void JNICALL Java_com_example_montreuxclient_fastcv_SquaredWrapper_analize
(JNIEnv *, jclass, jintArray);

3. Create C source
Спираючись на побудований header, без труднощів можно реалізувати цільового метода:

#include "SquaredWrapper.h"
JNIEXPORT jint JNICALL Java_com_anonym_myapplication_SquaredWrapper_squared
(JNIEnv *je, jclass jc, jint base)
{
return (base*base);
}

4. Build Java & NDK project
Зараз ми маємо усе необхідне, щоб повернитися то інтеграціі побудованих файлів до NDK і Gradle з Android Studio. Android.mk буде виглядати, як очекується:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := squared
LOCAL_SRC_FILES := SquaredWrapper.c

include $(BUILD_SHARED_LIBRARY)


Інші зміни до Gradle також очікувані:

ndk {
moduleName "squared"
}
sourceSets{
main {
jni.srcDirs = []
}
}

та

task buildNative(type: Exec, description: 'Compile JNI') {
def ndkDir = 'C:\\Android\\ndk\\android-ndk-r10d'
commandLine "$ndkDir/ndk-build.cmd",
    '-C', file('src/main/jni').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}

Протягом того, як Gradle виконує tasks, звернемо увагу, як зветься і де буде розміщена побудована бібліотека

[armeabi] Install        : libsquared.so => libs/armeabi/libsquared.so

5. Use NDK from Java
Все, що залишилось зробити - це завантажити побудовану дінамичну бібліотеку із java-коду та викликати відповідні методи. Перше робимо таким чином:

static {
  System.loadLibrary("squared");
}

Друге - таким:

    SquaredWrapper wrapper = new SquaredWrapper();
    int res = wrapper.squared(4);
    int[] array = new int[]{1,2,3};
    int size = wrapper.analyze(array);

Use NDK in Android Studio, part 1

Може даремно було сподіватися, втім ніхто й не обіцяв: остання версія Android Studio - 1.1 - знов залишає підтримку NDK до кращих часів: Current NDK support is deprecated.  Alternative will be provided in the future. Це означає, що хоча налагоджувати  C++ інтерактивно ви не будете здатні, але ж готові компоненти можно компилювати і, головне, сам як у минулій версії, їх можно викликати з java-коду. Це майже все, на що спроможна щойно випущена версія: ваш код на С ++ буде побудований за допомогую зовнішніх утіліт, що належать до NDK, Gradle буде лише заважати керувати процесом.

Тут вартить нагадати, як само NDK будує C++ код. Як повелося ще з часів Linux, кожна діректорія, що будується (вона припусково має бути розташована під діректорією "jni"), повинна мати Android.mk файлу (так званий build script) , у якому й викладено, що та яким чином, треба будувати. Наприклад, якщо увесь ваш код ся містить лише у корневої діректорії, Android.mk типово виглядає так:
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libfastcvUtils
LOCAL_CFLAGS    := -Werror
LOCAL_SRC_FILES := FastCVUtil.cpp
LOCAL_LDLIBS    := -llog 

include $(BUILD_SHARED_LIBRARY)


Зупинимось хвилину на цьому тексті. Його синтаксис трохи дивує, але він навмисно дуже близький до того, яким користуються у Android Open Source Project. Головне ж прозоре. Директива include $(BUILD_SHARED_LIBRARY) каже, що будемо робити shared library - .so file за назвою awesomeguy (LOCAL_MODULE := libfastcvUtils) , а щоб його зробити, треба компілювати лише один файл - FastCVUtil.cpp (LOCAL_SRC_FILES := FastCVUtil.cpp). Інші визначення (LOCAL_PATH:= $(call my-dir) та include $(CLEAR_VARS)) достатньо цікаві, але ж не дуже важливі до цієї дискусії. (Проте зауважимо, що всі визначення, які зроблені у мк-files, об'єднуються до єдиного контексту виконання, де усі змінні є глобальними. Оголошення include $(CLEAR_VARS), таким чином,  дозволяє очистити попередньо оголошені змінні, за винятком LOCAL_PATH).
Якщо потрібно скомпілювати кілька файлів, то їх назви треба помістити до одного рядку:
LOCAL_SRC_FILES := FastCVUtil.cpp FastCVSampleRenderer.cpp


або з такою варіацією:
LOCAL_SRC_FILES := \
                  FastCVUtil.cpp \
                  FastCVSampleRenderer.cpp \


Стасовно includes, це робиться приблизно так:
JNI_DIR := $(LOCAL_PATH)
LOCAL_C_INCLUDES    := $(JNI_DIR)/inc


Взагалі, краще роздивитися дещо дивний сінтакс Android.mk можно тут.

Ну, а зараз, з'ясував, як зроблено Android.mk, можно виконати головний cmd-file NDK ndk-build.cmd таким чином:
ndk-build -C <your_project_path>\jni
Це мусить знайти у визначеній діректорії Android.mk і побудувати проект згідно з ним.

Таким чином, повертаючись до Gradle, нашою метою, стане виклик ndk-build.cmd з усіма необхідними параметрами.
Для цього визначимо нову змінну оточення у файлі local.properties

sdk.dir=C\:\\Android\\sdk
ndk.dir=C\:\\Android\\ndk\\android-ndk-r10d

і попрохаємо Android Plugin до Gradle використувати ії таким чином (у build.grandle на рівні модуля) :

defaultConfig {
applicationId "<your package id>"
minSdkVersion 21
targetSdkVersion 21

      ndk {
moduleName "<your module name>"
cFlags "-D DEBUG" // Окрім обов'язкового moduleName, ви можете передати інші параметри до NDK
          stl "stlsupport_shared
}

sourceSets{
main {
jniLibs.srcDir 'src/main/libs' // <-- Set your libs (.so) folder here! This is Grrovy - just space delimeter between entries
                                                                // You may add ABI libraries under libs depending on the platform you are buiding for.
jni.srcDirs 'src/jni'
}
}
}

Проблема міститься у тому, що у цьому випадку Gradle буде створювати його власні файли Android.mk та викликати ndk-build невірно. Запобігти цього можно такою вказівкою:

        sourceSets{
main {
jniLibs.srcDir 'src/main/libs' //set .so files location to libs
jni.srcDirs = [] // This prevents the auto generation of Android.mk
}
}

Чудово, ми домоглися становища, що Gradle нічого взагалі не робить з NDK. Залишилость лише додати йому належний task:

import org.apache.tools.ant.taskdefs.condition.Os






task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
def ndkDir = 'D:\\android-ndk-r10d'
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine "$ndkDir\\ndk-build.cmd",
'-C', file('src/main/jni').absolutePath
} else {
commandLine "$ndkDir\\ndk-build",
'-C', file('src/main/jni').absolutePath
}
}
та долучити його до головного ланцюгу:

tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
Далі буде, якщо буде що.

Уроки YouHelp

1. Гибридные приложения никогда не смогут стать widgets, mini-applications или home screens для Android, живой плиткой для WP и т.д и и т.п. Выбирая гибрид, вы закрываете для себя все новые и самые красивые возможности операционной системы. Вы заранее ставите приложение в рамки производственной единицы, что может быть, и хорошо для банков, страховых компаний и проч., но никак не для приложений, которые собираются конкурировать на свободном рынке. Людям уже успели надоесть монотонные картинки с унылым текстом.
Само обсуждение гибрида связывает руки и голову, заставляя вас заниматься вопросами часто кажущейся быстроты разработки вместо ее качества. Например, вы можете никогда не узнать об AsyncTask в Android или await/async в .NET, размышляя, почему у вашего приложения так мало активных пользователей, хотя оно вышло в срок, установленный заказчиком. Помним, что Ахматова как-то заметила: «Какой же он пушкинист, если французского не знает?»
2. Выход приложения на рынок это только одна из фаз его жизни. Оно должно продолжать развиваться, включая все новые и новые возможности: если вы имеете дело с фотографиями, например, должер появиться 3D, если контакты, то добавьте NFC и т.д. С другой стороны, не надо стесняться убирать невостребованные возможности.
3. Гибридные приложения, однако, стоит писать, но только после того, как вы знаете возможности платформы и уверены, что гибрид будет функционоровать не хуже. С другой стороны, проверяйте возможности HTML5 до конца, ведь преимущества гибрида довольно велики, если ваша цель не пользователи, а заказчик.
4. Xamarin, PhoneGap и другие дают относительно быстрое решение, но нельзя расчитывать на них в долголсрочной перспективе. Если вы ставите на них, вы не узнаете прелестей Android, а  он очень красив. То же самое касается и WindowsPhone.
5. Первой реализацией концепции должна быть версия для Android. Не пишите одновренно версии для всех трех платформ: разработка для iOS приципиально отличается от остальных, вы потеряете драгоценное время там, где можно добиться концептуальных решений для Android.
6. iOS не поддерживает многое из того, что кажется разработчику Android почти тривиальным, например, NFC. По меньшей мере на бумаге, проверяйте можно ли реализовать идею на всех трех платформах.
7. Windows Azure зарекомендовал себя очень хорошо как backend для всех пратформ. Notification Hub, например, сократит время разработки очень существенно, WAMS откроет приложению дорогу к нереляционным таблицам, blobs и проч., о чем можно только мечтать в Amazon. На Azure можно и нужно ставить.
8. Тестируйте, тестируйте и тестируйте! Благодарите небо, если вам под руку попалась старая модель какой-нибудь моторолы, на которой никогда не было GPS. Тестируйте на всем, что может двигаться и дышать: телевизоры, китайские планшеты, часы (даже настенные с кукушкой). Включайте airplane mode, детский уголок и режим сохранерия батарейки. Тестируйте в машине на скорости и в туннеле, обязательно в лифте или в метро, в открытом море без интернета и в людных местах, где его не хватает на всех.

Из истории Флоренции

Небо Италиит слишком синее, чтобы обеспечить спокойное состояние под ним обитающих. Особенно когда тебе меньше двадцати и собственная тень есть всего лишь силуэт самого себя. А если ты при этом чувствуешь себя еще и меньше единицы, то и не поднимая глаз, у тебя останется на земле город, в котором не хочется умирать и тот человек, от которого ты об этом узнал.Read more...Collapse )

Бродский в Риме

Судя по всему, Роберто Калассо был первым издателем Бродского в Италии (миланское издательство Адельфи).
Один из первых приездов Бродского в Рим состоялся благодаря стипендии Американской академии искусств и наук, в 1979 г. Он жил несколько месяцев на Villa Aurelia (в здании самой Академии, у ворот Сан-Панкрацио. На воротах имеется барельеф, на барельефе три пчелы в гербе Барберини, которые и до сих пор никуда не улетели) под патронажем Бенедетты Кравиери, внучке Бенедетто Кроче, которая занималась французской литераторой ХVII века.

В 1981 г. Бродский приезжает в Рим еще раз. Его приятельница того времени - Микелина (Микела Продан?), подруга Бенедетты Кравиери - жила на Виа деи Фунари, рядом с Пьяцца Матеи, возле дома, где нашли Альдо Моро ( "Memento Moro" ), "В  центре того, что в Риме называется гетто". Граф с павлинами тоже реальный персонаж. Тогда же были написаны и и опубликованы "Римские элегии". "Две молодых брюнетки" это Микелина и Бенедетта в библиотеке мужа Бенедетты, a начинается стихотворения с описания квартиры Микелины, отец которой был торговцем антиквариатом.
Название из Гёте подбрано Бродским специально ("Если это вызов, пусть будет вызов, но только я не знаю, кому. Это правда Рим и это правда элегии.")

Бюст Тиберия находится в одном из залов Капитолия. написан тоже около 1981 г.

"...И за уши не удержать уже
взбесившегося волка. "

"Держать волка за уши" ( Auribus teneo lupum ) - быть между двух огней. Встречается у Светония, который описывает этой фразой колебания Тиберия перед объявлением о принятии власти.

"...Ах, Тиберий,
тебе здесь нет и тридцати. "
Тиберий стал императором в возрасте 56 лет.

"На Виа Джулия" посвящено Теодоре - американке, работавшей в одном из римских издательств примерно в 1985 г.

Стихотворение "На виа Фунари" относится к совершенно другому периоду - 1995 г.
В то же время - осенью 1995 г. - Бродский обсуждал идею создания Русской академии в Риме с тогдашним мэром Франческо Рутелли.

http://lib.rtg.su/drama/230/297.html

NFC Terminology

You can easily filter your activity to TECH_DISCOVERED action and then your app will participate in Android choiser for the applications popped up to actually handle the NFC message. The problem is the second time when the tag is approached. Instead of remains on foreground your application is picked up again instead of delivering tag directly. Somehow remind the focus on windows control: once set, the second launch will remain on the the focus on this control. In other words, the application that already handled NFC message should not yield the further NFC messages to NFC dispach sub-system. Here is where Foreground Dispatch mechanism is applied.

NDEF - NFC Data Exchange Format. A data format to store information like plain text, URIs in a data container that could be stored on an NFC tag or exchanged over NFC. One NDEF may contain multiple Record Type Definitions anf therefore it is also referred as NDEF container. In Android realm, NDEF Message is a container for one or more NDEF records. Each NdefRecord consists of 3-bit TNF (Type Name Field : NdefRecord.TNF_UNKNOWN, NdefRecord.TNF_WELL_KNOWN etc.) and followed by
1. type: NdefRecord.RTD_TEXT and others
2. id:
3. payload:
Here is an example of creating NdefRecord :
new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
and the exampl of creating NdefMessage:
new NdefMessage(new NdefRecord[] { newTextRecord(
"Message from NFC Reader :-)", Locale.ENGLISH, true) });

APDU - Application Protocol Data Unit. Data exchange format specified in ISO7896 to exchange data between a reader and smartcard chips.
LLCP - Logical Link Control Protocol. Protocol used in NFC peer to peer transactions for a smooth establishment of communication.
Mifare - a product of NXP Semiconductors. It's a smartcard based on ISO14443A.
FeliCa - a competing smartcard of Sony. Not comaptible with ISO14443A.

Some phone models supporting NFC:
Samsing Galaxy Note II - comes with PN65 NXP chip, includes an embedded SE used by Google Wallet.
Samsung Galaxy S III  - the sames NFC chip as Note II.
Samsung Galaxy S II - PN544, upgradable to Android 4.1.
Google Nexus 4 - manufactured by LG and has a Broadcom BCM20793 chip embedded with SE.
HTC Windows Phone 8 - has PN544 NXP NFC chip

Usual frequency for NFC 13.56 Mhz

Android. Beam (aka NDEF Push)
Beam is a mechanism build-in into Android devices at least starting from version 4.1. The sending activity should prepare the NDEF Message that will be transmitted to another device when they come close. In particular, in onCreate() method the NDEF Message is prepared (and obviously, NDEF Adapter is initialized). In onResume() method the NDEF adapter is turned to enableForegroundNdefPush mode, and in OnPause() it turned back to disableForegroundNdefPush mode. When the user tap on Android beam screen, the prepared message is transferred to another device. This procedure is called NFC foreground dispatch. The second device DON'T have the Beam turned on!

Android. Readring NFC.
1. When NFC Tag is discovered, Android tries to start an Intent based on the information parsed from the tag, i.e. firstly it sends ACTION_NDEF_DISCOVERED and ACTION_TECH_DISCOVERED.
2. If no activities filter for these intents, Android NFC Dispatcher tries ACTION_TAG_DISCOVERED.
3. If no activities with no one of these filters, do nothing.

Android. Emulating smart card. HCE.

Ромео и Джульетта

В 1965 г. Кеннет Макмиллан поставил современную постановку "Ромео и Джульетты" в Ковент-Гарден на Нуриева и Марго Фонтейн, а уже через несколько лет сам Нуриев сделал свою версию этого балета в Лондоне. В 1984 г., уже будучи директором балетной труппы Гранд-Опера, он перенес ее в Париж. Его постановка отличается несколькими новинками : во-первых, в ней, как и любил Нуриев, используется практически вся музыка Прокофьева, без каких-либо купюр, а танцы написаны буквально на каждую ноту. Во-вторых, образ Джульетты выведен как активной противницы кровопролития: известная сцена похорон Тибальда исполняется ею, а не матерью. Исполняется она сольным танцем, во время которого вся остальная сцена замирает, а Джульетта всеми силами пытается избавится от захлестнувшего ее насилия. Кроме того, Тибальд представлен так, что он во время боя насмехается над смертью и даже после его падения никто из присутсвующих не верит в его настоящую смерть.
Традиционно в репертуаре Ла-Скалы "Ромео и Джульетта" была представлена в версии Джона Кранко, и только в нынешнем сезоне (премьера 10-го октября) впервые на сцене будет поставлена версия Макмиллана. Роль Джульетты отводилась Светлане Захаровой из Большого, но что-то не получилось с ее контрактом, и в последний момент партия была отдана Алине Сомовой из Мариинского. В партии Ромео Роберто Болль (Roberto Bolle) - итальянец, работающий в Нью-Йорке, но часто приглашаемый в Ла-Скала. Дирижирует оркестром знаменитая Чжан Сянь.
Realease before about 2 years ago, the NodeJS module for Azure Table Storage recenly was updates and now it provides the comprehensive model of almost all aspects of the techlology. Than said, this model is very different from others SDK provided for Java and C#, but such a difference mostly stem from a asynchronous nature of Node JS.
The module is provided as open source, hosted at GitHub and available to npm witn name 'azure-sorage'. For now, the current version of the product is 0.3.3. Several introductionary papers may be found here and here. The lead developer of the product, Joe Giardino, also wrote, as expected, some kindly articles about this topic. Add his work, some interesting blogs from his collegue Matt Harrington and others, don't miss criticism and you will discover the landscape of the NoSQL in Azure at time of writting.
Regardng Android, almost all you need to know is explained in this excellent blog post by Joe Giardino.
About a month ago Microsoft released the Azure Stogare SDK for Android to GitHub and published the guide document and deep dive post of how to use it from Java. This is incredible work exposing Azure technology to Android word in open source manner, but unfortunatelly I'm not Java-man. I not heard before about Maven repositories, Gradle and other great Java projects come to Redmond before they reached the Microsoft developers audience. My skills are barely enought for importing SDK project into Eclipse workspace, but - ops! - it depends on Jackson : yet another JSON parser also supplied as open source from GitHub. (My udesrstanding is the SDK is just a wrapper around REST API, the since REST talks JSON, the some kind of parser is needed). The Azure Storage SDK comes with "simple" aar  for Maven and Gradle insructions, but, believe me, the last thing in my life I want to do is learn how to use them. Once again - I have no serious background in Java and I don't understand how other MS folks are expected to give it. All I need is working copy of the SDK - already compiled and ready to use.
It takes a hours to find the solution : thanks to Maven, the latest Jackson bits are available at their repository. The  mentioned version of SDK needs Jackson core 2.1.0. Just add its jar to the libs directory of SDK source and you've done.
You may continue with the guide and leave the questions about the open source aside.
Jackson

Update 27.12.2014. As for new Android Studio, since Azure Storage SDK was published to Maven, the simplest way to use it is to mention it in gradle.build:
dependencies {
  compile 'com.microsoft.azure.android:azure-storage-android:0.3.0@aar'
}

Гоголь

До Т. Шевченко, т.е. до 40-х годов ХХ, века вряд ли вообще можно было вести речь о национальном сознании украинцев или сформировавщемся самостоятельном украинском языке. "Вечера на хуторе близ Диканьки" и "Миргород" (1835) это не украинская литература, а скоморошное заигрывание с туземцами, тем только и привлекательное, что опирается исключительно на фольклор, а не литературную традицию. И. Франко узаконил то, что только открыл Шевченко - с него украинский язык начал свой путь в прозу. Дорогу в поэзию ему открыла Леся Украинка.
....
Я никогда не разделял мнения тех, кому нравятся книги только за то, что они написаны на диалекте, или за то, что действие в них просходит в экзотических странах. Немало похвал было порождено местным колоритом, а местный колорит быстро выцветает...
Надо поблагодарить судьбу (и жажду писателя обрести мировую славу ) за то, что он не обратился к украинским диалектизмам как средству выражения, ибо тогда бы он пропал. Когда я хочу, чтобы мне приснился настоящий кошмар, я преставляю себе Гоголя, строчащего на малороссийском том за томом "Диканьки" и "Миргороды" - о призраках, которые бродят по берегу Днепра, водевильных евреях и лихих козаках.
....
Русские, которые считают Тургенева великим писателем или судят о Пушкине по гнусным либретто опер Чайковского, лишь скользят по поверхности таинственного гоголевского мира и довольствуются тем, что им кажется несмешкой, юмором и броской игрой слов. Но водолаз, искатель черного жемчуга, тот, кто предпочитает чудовищ морских глубин зонтикам на пляже, найдет в "Шинели" тени, сцепляющие нашу форму бытия с другими формами и состояниями, которые мы смутно ощущаем в редкие минуты сверхсознательного восприятия.