программа виндовс для телефонатемы для телефона explay t350brain champ для телефонарисовать мультфильмы на андроид
Привет, Хабрапользователь. Кажется, ты используешь AdBlock. Хабрахабр
развивается и существует за счет доходов от рекламы. Добавь нас в исключения.
В конце данной статьи мною был озвучен план сделать порт под Android. Тут я попытаюсь описать проблемы, с которыми я столкнулся и методы их решения. Сразу хочу оговорится, что опыта работы с Android на данный момент ровно 2 месяца и возможно некоторые решения опасны или даже не приемлемы на данной платформе.
Движок хобби находится в разработке уже 10 лет.
Движок полностью написан на C/C, до начала портации на Android поддерживал iOS и Windows.
Логика, рендеринг, звук все на C/C.
Важная особенность которая сделала портацию на Android очень простой это файловая система движка.
class IStream void setNamestring name 0; open 0; write 0; 0; class FileStream: public IStream имплементация через POSIX API. class DataPackStream: public IStream имплементация для работы файлами Core::Meta mpackFileStreamMeta;;///mpackFileStreamMeta- Create IStream этого типа будет использован для работы непосредственно файлом
Итак: вся работа с файлами в движке основана на интерфейсе IStream, архитектура движка поддерживает фабрику объектов, и её кастомизацию.
Core::FileStream::Type- setFactoryMetaDataPack::DataPackStream::Type; FileStream filestream1 FileStream::Create;//тоже самое будет и при new FileStream FileStream filestream2 FileStream::CreateExact; filestream1 будет типа DataPackStream filestream2 будет типа FileStream
Ничего нового и все довольно стандартно.
Так как все ресурсы запрепроцесенны файл, то для Android системы пришлось написать свою реализацию IStream специально для работы с Java.
AssetFileDescriptor RawAssetsDescriptor 000; if RawAssetsDescriptor! null FileInputStream fis ; ; ; ;
Нейтив класс все вызовы open, read, seek транслирует опять в Java
class AndroidPackStream: public IStream //пример работы read sizet readvoid buffer, sizet size, sizet count if JavaHelpers::mpClass jmethodID mid JavaHelpers::GetEnv- GetStaticMethodIDJavaHelpers::mpClass, freadDataPack, II; int res JavaHelpers::GetEnv- CallStaticIntMethodJavaHelpers::mpClass, mid, intsizecount; jfieldID field JavaHelpers::GetEnv- GetStaticFieldIDJavaHelpers::mpClass, byteBuffer, Ljava/nio/MappedByteBuffer;; jobject obj JavaHelpers::GetEnv- GetStaticObjectFieldJavaHelpers::mpClass, field; uint8t pDatauint8tJavaHelpers::GetEnv- GetDirectBufferAddressobj; memcpybuffer, pData, sizecount; JavaHelpers::GetEnv- DeleteLocalRefobj; return res/size;
public static int freadDataPackint count long curPos ; int countReaded count; byteBuffer, count; ; curPoscountReaded; return countReaded;
Важный момент сборщик apk сжимает все ресурсы, а мы хотим читать файл как будто он просто лежит в файловой системе. Для того чтобы файл не сжимался внутри apk вы должны сменить ему расширение на одно из тех которые будут говорить упаковщику не сжимать данные файлы при упаковке детали /blog/2010/03/26/dealing-with-asset-compression-in-android-apps. Я
Загрузка ресуров таким способом очень быстра, например на Kindle Fire работает быстрее чем на iPad 1
Оговорю стразу что такой финт можно провернуть если у вас не очень много данных.
Для большого объема данных вы можете сами распаковать данные на внутрений носительнапример при первом запуске и напрямую их использовать посредством функций fopen fread в моем случае, через не подмененный FileStream и.т.д.
Для Windows и iOS был использован OpenAL. OpenAL для Android был собран благодаря /2010/12/14/openal-on-android. Заработал не сразу, а только после исправлений которые описаны в комментариях на вебсайте.
Сборка под Android собрана только для Arm v7 потому что сборка порта под Arm v6 OpenAL иногда приводила к лагам, в iOS OpenAL микшер работает быстрее и без лагов даже на ArmV6, например на iPod Touch 2G.
class IPlatfomCommandFeedback void onResponsestring ; class IPlatfomCommand string executestring ;
Для iOS своя реализация на Objective-C а для Android своя реализация на JNI- Java.
Нейтив часть работает с использованием OpenGL, для Android были сделаны минимальные изменения. Как в последствии оказалось этого было недостаточно. Дело в том что на Windows и на iOS текстуры не теряются когда приложение уходит в бакграунд, а вот для Android это происходит всегда. В движке уже был менеджер текстур в основном для отладки и добавить перезагрузку ресурсов оказалось не сложно.
В самой первой статье я писал о том, что изначально компилировал iOS с использованием toolchain и у меня были настроенные makefile. Вот тут то мне это и пригодилось. Были дописаны таргеты для сборки с использованием Android NDK, добавлен степ в билдеры Eclipse и все взлетело. Да, можно использовать билд систему из Android NDK samples. Её я использовал только для выяснения параметров которые используются для вызовов gcc.
Железо: Kindle Fire, и пару планшетов и мобильных телефонов друзейдля тестирования.
Android Market это не AppStore. Там все по другому. Там нет категории New.
Для сравнения на AppStore в первый день релиза было 800 скачек, во второй 2000, на Andoid Market официальная первая сотня скачек была получена только на третий день. Активность по раскрутке для обоих платформ была одинакова
Если ваше приложение бесплатное вы можете свободно распространять apk, любой человек может проинсталировать себе данное приложение с любого источника. Если это сделаете не вы, то за вас это сделают другие.
Бестиарий устройств велик. Количество проблем соответственно.
Процесс ревью на Amazon AppStore for Android занимает неделю, плюс еще несколько дней пока приложение появится в списке AppStore на Kindle Fire. Количество скачек и динамика соответствует Android Market
Лучи ненависти Корпорации Добра уже неделя как рекламный баннер был отправлен на апрув. До сих пор тишина.
На данный момент количество денег напомню в игре только реклама которые приносит iOS версия в 40 сорок раз больше чем версия для Android. Понятно, что сравнение не корректно и надо подождать как минимум еще пару месяцев пока не стабилизируется количество постоянных игроков в день.
UPDATE: В секции звука я описал причину сборки только для ArmV7 Android устройств.
Ссылки на App Store и Android Market в студию.
Замечание про win и текстуры.
потеря текстур для связки directX fullscreen вполне стандартное явление, с которым живут все игровые разработчики.
Я полностью понимаю данное поведение для мобильных устройств.
iOS такого не делает он тебе дает шанс сделать это самостоятельно при уходе в бакграунд.
Но, ты сможешь это не делать и за это тебя никто не накажет в худшем случае твое приложение будет первое на принудительную выгрузку если понадобится память
Особенность тематических блогов заключается в том что тут нельзя рекламировать.
Боюсь что наличие даже QR кода может быть расценено как пиар и за это можно получить ридондли.
В принципе даже приведя ссылки в ответах я теоретически могу словить бан.
На прошлой неделе тоже загрузил приложение на Android Market и был поражён полным отсутствием загрузок. Год назад приложения худшего качества там же скачивались в первые дни весьма активно.
Как мне объяснили, гугл убрал категорию Новые поэтому о новых релизах мало кто узнает сразу.
Это весьма печально. Есть кстати ещё ряд альтернативынх маркетов, например у opera, там возможно бесплатно опубликовать своё приложение насколько это имеет смысл пока непонятно.
Остаёться только продвижение за деньги. В статье упоминаеться рекламый банер? Речь о adworde? или admob.
Я имел ввиду что мне стоит подумать портировать свой app.
Понятно, если у вас приложение написано на С/C Android NDK, то больших сложностей быть не должно.
Нет, к сожелению на Java. Последний раз с C работал 10 лет назда. Видимо придёться отдавать в outsourcing.
Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.
Пометьте топик понятными вам метками, если хотите
Метки лучше разделять запятой. Например: общение, социальные сети, , подростки, мердок
Привет. Кажется, ты используешь AdBlock. Geektimes развивается
и существует за счет доходов от рекламы. Добавь нас в исключения.
Началось всё как в самом настоящем детективе: новогодние праздники, 31 декабря, родительский дом за много километров от москвы и что самое страшное полное отсутствие интернета и телеканала 2x2. Мозг может работать в двух режимах либо потреблять контент, либо создавать его. Так получилось, что у меня мозг в тот момент заработал во втором режиме. По случайному стечению обстоятельств, мне на глаза попалась давно забытая игра-головоломка Пифагор:
И я решил оцифровать её.
Головоломка Пифагор состоит из 7-ми геометрических фигурок, которые необходимо сложить таким образом, чтобы получилась фигура, указанная в задании. При решении задания необходимо использовать все 7 фигурок головоломки.
Ну и в довесок ко всему, я давно хотел написать что-нибудь под мобильник.
Так как на ноуте стоял Eclipse с необходимыми приблудами для Android, и было несколько книжек про него, скачанных про запас, то выбор был предопределён.
Итак, решено: будем писать игрушку Пифагор для Android. Так же отмечу, что я не являюсь программистом, в моём понимании этого слова.
Не буду описывать как устанавливать и настраивать Eclipse и как создавать проект, так как про это и так много всего написано, наконец-то перейду к сущности повествования.
Создаём проект с именем Pifagor.
package ; import ; import ; public class Pifagor extends Activity Override public void onCreateBundle savedInstanceState savedInstanceState; ; pifagorView PifagorView ;
Теперь создадим файл в котором и будет реализована наша игра. Определим класс PifagorDraw который дочерним для класса Thread. Для нашего класса определим методы обработки событий он экрана, сброс игры в начальное состояние и переопределим метод run:
package ; import ; import ; import ; import ; import ; import ; import ; import ; public class PifagorDraw extends Thread private SurfaceHolder appScreen; private boolean appRunning;//флаг работы потока private boolean appPaused;//флаг паузы потока private Paint appPaint;//private Bitmap clearScreen;//битмап для очистки экрана private PifagorPuzzle Puzzles;//массив фигур private int activePuzzle;//номер активной фигуры private long thisTime;//переменная для сохранения времени нажатия на экран private long downTime;//переменная для сохранения времени отжатия от экрана private PifagorTask Tasks;//массив заданий private PifagorTask ResetPiktogram;//пиктограмма для кнопки сброса private int activeTask;//номер активного задания private int maxTasks;//общее количество заданий private boolean prevButton, nextButton, resetButton;//флаги нажатия кнопок//Описание фигур//большой квадрат private int PuzzleTemplate1 ;//большой треугольник private int PuzzleTemplate2 ;//малый квадрат private int PuzzleTemplate3 ;//малый треугольник private int PuzzleTemplate4 ;//косой паралепипед private int PuzzleTemplate5 ;//Пиктограмма кнопки Сброс private int Pikto1 ;//Описание заданий private int Task1 ; private int Task2 ; private int Task3 ; private int Task4 ;//Конструктор public PifagorDrawSurfaceHolder surfaceHolder, Context context //определение начальных значений переменных appScreen surfaceHolder; appRunning false; appPaused false; activePuzzle 0; thisTime 0; downTime 0; prevButton false; nextButton false; resetButton false;//Стиль рисования appPaint new Paint; ; 2; ;//создание экрана для очистки изображения clearScreen screenWidth, screenHeight, 565;//определение и заполнение массива фигурок Puzzles new PifagorPuzzle7; Puzzles0 new ; Puzzles1 new ; Puzzles2 new ; Puzzles3 new ; Puzzles4 new ; Puzzles5 new ; Puzzles6 new ; PuzzlesReset;//определение и заполнение массива заданий maxTasks 4; activeTask 0; Tasks new PifagorTaskmaxTasks; Tasks0 new ; Tasks1 new ; Tasks2 new ; Tasks3 new ;//создание пиктограммы сброса ResetPiktogram new ; //установка флага работы процесса public void setRunningboolean status appRunning status; //обработка сбытий от экрана public boolean TouchMotionEvent event int mouseX ; int mouseY ; case MOVE://обработка break; case DOWN://обработка break; case UP://обработка break; return true;//возвращаем true, потому что события от экрана отработаны //Функция сброса в игры в начальное состояние public void PuzzlesReset Override public void run whileappRunning if !appPaused Canvas canvas null; try canvas ; synchronizedappScreen //здесь прописываем логику игры и отрисовку игровых объектов//Например://очистка изображения clearScreen, 0, 0, null;//рисование фигур задач forint i0;i 7;i ; canvas; sleep20; catch Exception e finally if canvas! null canvas;
Я прочитал про различные способы работы с графикой на Android, но более-менее пока разобрался с одним, его и буду использовать.
Теперь создадим в проекте файл с именем В этом файле объявляем класс PifagorView, который является дочерним для класса SurfaceView и добавляем наследование интерфейса этот класс будет связующим звеном.
В созданном классе нам необходимо переопределить три унаследованных от SurfaceView метода для реагирования на изменения состояния View, а так же один метод для обработки событий от экрананажатие, перетаскивание, отпускание:
package ; import ; import ; import ; import ; import ; public class PifagorView extends SurfaceView implements private SurfaceHolder appScreen; private PifagorDraw appThread; public boolean surfaceCreated;//конструктор public PifagorViewContext context, AttributeSet attrs supercontext, attrs; surfaceCreated false; appScreen getHolder; this; appThread new PifagorDrawappScreen, context; setFocusabletrue; Override public void surfaceChangedSurfaceHolder arg0, int arg1, int arg2, int arg3 //TODO Auto-generated method stub Override public void surfaceCreatedSurfaceHolder holder appThread new PifagorDrawholder, getContext, screenWidth, screenHeight; true; ; Override public void surfaceDestroyedSurfaceHolder arg0 boolean retry true; false; whileretry try ; retry false; catch InterruptedException e Override public boolean onTouchEventMotionEvent event return event;//так как вся логика игры у нас прописана в классе PifagorDraw, то мы просто перенаправляет туда полученные события
xml version1.0 encodingutf-8? LinearLayout /apk/res/android android:orientationvertical android:layoutwidthfillparent android:layoutheightfillparent android:idid/game android:orientationvertical android:layoutwidthfillparent android:layoutheightfillparent/LinearLayout
Так же в проекте есть ещё два класса PifagorPuzzle, в который описывает геометрические фигурки головоломки, и класс PifagorTask, описывающий задания. Их рассматривать не будем.
Приложение, в принципе, уже можно запускать, однако при сворачивании приложения и его последующем возобновлении, оно будет падать с критической ошибкой.
Для того, чтобы это исправить, сделаем следующее:
Во-первых, в классе PifagorView создадим методы CreateThread и TerminateThread из названия понятно для чего они будут использоваться, и несколько изменим переопределённые методы SurfaceCreated и SurfaceDestoryed:
public class PifagorView extends SurfaceView implements private SurfaceHolder appScreen; private PifagorDraw appThread; public boolean surfaceCreated; private int screenWidth; private int screenHeight;//конструктор public PifagorViewContext context, AttributeSet attrs supercontext, attrs; surfaceCreated false; appScreen getHolder; this; appThread new PifagorDrawappScreen, context, screenWidth, screenHeight; setFocusabletrue; //уничтожение процесса public void terminateThread boolean retry true; false; whileretry try ; retry false; catch InterruptedException e //создание процесса public void createThreadSurfaceHolder holder appThread new PifagorDrawholder, getContext; true; ; Override public void surfaceChangedSurfaceHolder arg0, int arg1, int arg2, int arg3 //TODO Auto-generated method stub Override public void surfaceCreatedSurfaceHolder holder if surfaceCreated false createThreadholder; surfaceCreated true; Override public void surfaceDestroyedSurfaceHolder arg0 terminateThread; Override public boolean onTouchEventMotionEvent event return event;
public class Pifagor extends Activity private PifagorView pifagorView; Override public void onCreateBundle savedInstanceState savedInstanceState; ; pifagorView PifagorView ; Override public void onPause ; ; Override public void onResume ; if true ;
Таким образом, при сворачивании приложения, игровой процесс описанный в классе PifagorDraw будет уничтожаться, а при возврату к приложению, запускаться вновь.
Полные исходники приводить не стал, если кому интересно, пишите в личку, вышлю.
Ну что ж, запускаем и смотрим что получилось:
Дизайнера для игрушки так и не нашёл. Если кто-то готов поучаствовать пишите в личку.
Игра написана, надо что-то делать дальше. Или убирать в архив, где она сгинет или попробовать выставить в Android Maket. Второе намного интереснее, по этому регистрируемся на /publish, регистрируем Google Checkout лучше регистрировать через IE, с остальными браузерами у меня были проблемы, платим 25 и как обычно в самый последний момент пытаемся понять куда мы опять вляпались, то есть ищем информацию как продвигать приложения в Android Market. Читаем статью и после этого составляем следующий план:
Публикуем бесплатную демо-версию игры, содержащую всего 5 заданий
Публикуем платную версию игры, с 30 заданиями
А так же параллельно составляем список функций, которые хотелось бы добавить в игру.
Так как данная статья является реализацией третьего пункта, то поделюсь результатами первых двух:
Демо-версию игры скачали чуть более 200 человек, активных установок около 100, что для первого приложения, на мой взгляд очень неплохо. Так же получил несколько советов по игре.
Через неделю, после публикации демо-версии, опубликовал первую редакцию платной версии игры. Демо-версия была удалена из-за того что потерял сертификат, которым подписывал приложение, и не смог загрузить обновление демо-версии так что будьте аккуратнее. За первые 24 часа нахождения игры в маркете её купили 2 человека, причём оба из штатов, судя по профилю в google checkout. В течении недели была ещё одна продажа.
Следуя плану, доработал и выложил обновлённую версию игры с дополнительными фичами.
Как будут развиваться события дальше, отпишусь позднее.
Времени потраченного на всё это абсолютно не жаль, так как получил определённый опыт и много удовольствия. Так что если кто ещё раздумывает, начать или нет, ребята, не раздумывайте! Дерзайте! Это того стоит!
В планах портировать игру под Windows Phone 7 и если не пропадёт запал то и под iOS.
Пометьте топик понятными вам метками, если хотите
Метки лучше разделять запятой. Например: общение, социальные сети, , подростки, мердок
РРРС РРРРС РСРРСРРРРёССРР Р РРРРРРС СРРСРРРССРёРРР Unity C, JavaScript.
РРёСРСРСР, РРСiС
РРР РСССРРёСРё РР РССРРё, РРР РРРРССРРР СРСРСРё.
РСРРРС РРСРРРР РР РРРРРР РРССРёСРРРРРёР РёРСС Gothic 2 Night of Raven РР РРРРёРСРСС РРРССРСРС РРРСРРёР.
РРСРРРёР РРРРРёССРёРРё, С РРС РСРРС РРССРРёР РСРРРёРР, РРРС РР РРРССРёСС РРР - РРССРССРРСРР СРРРРРРРСРССС РёС РСРСРёСРСС РРРРРРСРё
РСРСРёСРСС РСРРРёРР Рё РРРР.
РСРСРР РСРРСРСРРРРРРёР - РРР РР РРРРРС.
РРСРРРРРСРСР РРР РРСРР ССРССРРР РСРРСРСРРРРРРёС.
1.2 РРРРСРРРёС РР РР СРРР СРСР Рё РСССРР
1.3 РСРёСРёРР Р РСРРСРРРёРё РССРРС РРРРРР РРРРРРРРР. РСР РСРРС РРРРСРР - РССРРРССС РРРёСС Р РРСРРР СРРёСРР РРРРРРРР
1.4 РРРРСРРРёС, СРРРСРРСРёР РРРРРСРРРРРРСС РСРёСРёРС Рё РССРРРСРРРРёС, СРРРёР РРР РСРРРС РРССРССРРРРСР, РС РРР РР РРРРРСРёСР, Рё С.Р
1.5 РСРСРСРёРРРРёР РРёРРРР С РРРРёРРёСССРСРёРё, Р СР СРР РРРРР СРРРСРРРёС С РСРСРРРРёСРРё
1.6 РРРРРРСС РРРСРСС, РСРРСС РР РРСРССР РРРС Р РРРР.
РР РРСРРРРРР РСРРС РСРР РСРРРРРРР РРСРРРРС СРРРСР Р РРРРССРё РСРРСРРРРёСРРРРРёС. Р СРССРРССРё, РРРРё РСРР РРРРёСРРР СРРССРРРРРС СРёССРРР СРСРРРРРРёС, РР РСРРРР РРСРСРР РС Р РРРСРРРСРР РСРРР СРРРРРРСС РРССРРРРРР. РРР РСРёСРРСС С РСРС РРСРРРёСРСС РРРРСРССР СРёССРРС, ССРРС РРСРР РСРР РРРССР РРРРРРРРССРР РРС РРСРёРРёРРСРёРё. РРРСР РСРРС РРРССР РёРСРСРРСРёРё Рё СРСРёРСРСС.
РРРРССРё РСРСС Р СРСРРРёР РРРРРРё. РСР РРРСРРРРССРё РРРССРС РРРРСРРС РРРРССРР РСРСС РРРРР.
Р СРСРРё С РСРРРРР РРРССРСССС СРРСРРРССРёРРР, СРРРСР РРРРСС РСРРС РРРРРРРР Р СРСРРРёР РРСС РРСССРР.
Р СРРРРРССРРРР РРС РСРРР СРРРР РРСРСРёРРСС СРРРС. РСР РРРРССРё РСРСС РРСРРРёРРРРРС Р РРРРРС РРРС.
РРРСРёРР, ССР РС С РРРРё
РСРРС РРРРРСССС, ССР РР РРССРСРСРР СССРР. РССС РРёРР РСРёРРРРР СРРёСРР РРРРР, РР РРСРССР РР РСРРР РРСРСРСС РРРёРРРРёР.
Р РРРР С РРСССРС СРёССРСРёС. РРР РС Рё РРРРСРёРРё, РСРРРРРё РР СРРСРРРСРС РРСРСССРСРёСРСРРё РР СРРСРРС. РС РРСРРРРРё РСРРРС РР 5 РРССРёС Unity, Рё РРРРРР РСС РСРёРСССС РРССРРСРёСРРРСС. РРРРРРСРё РРСРСРР РР РРРСС РРССРёС РРРёРРР РРРРРРёСРРСРСР РРСРРРР СРРРСРРРССС РР FPS. РСРРРРРё РР СРРСРРРСРС РССРСССС РСР РРРССР, РР РС ССРРРРРёРСС РРССРРР Рё РССРРРРРРёРРСССС РРРССР РР РРРРРёССРР. РРР ССР РСРРё РРРРССРР РРРРР-СР РСРРС РР РСРРС - РР СРРСРёСР РРРРёРРРРСС, РРРё РРСРР РРСРРСРРСРР РРСРСССС.
РРСРРССРСС Рё СРРСРСС С РРРРРС.РРёСРР
Как вы помните, на конференции Build 2015 Microsoft объявила о новых и мощных инструментах, которые, по словам компании, позволят легко и быстро портировать iOS и Android приложения на Windows 10.
Эта новость, вместе с особенностями новой операционной системы, оказалась одной из самых интересных, дав пользователям надежду на быстрый рост приложений, а разработчикам возможность существенно расширить свою аудиторию учитывая десятки миллионов устройств по всему миру, которые будут обновлены до Windows 10, приложив небольшие усилия.
В теории это звучит прекрасно, но на практике все несколько иначе, поскольку ограничения все же имеют место быть. Так говорит Кевин Галло, программный менеджер Microsoft. В интервью для он сказал, что приложения с глубокой интеграцией с особенностями системы не будут работать должным образом на Windows 10. Речь идет, например, о приложениях для обмена сообщениями, которые используют службы уведомлений своей родной операционной системы, которые, по-видимому, отличаются в iOS, Android и Windows 10.
Мессенджеры и приложения, которые обладают глубокой интеграцией в фоновые задачи, вероятно, будут иметь проблемы с запуском.
Очевидно, что проблема может быть решена с помощью инструментария, предоставленного Microsoft, и путем реализации дальнейших изменений в исходном коде. Т.е. разработчики могут вручную сделать свои Android и iOS приложения полностью совместимыми с Windows 10, но это означает дополнительную работу, и не все будут заинтересованы или готовы сделать это.
Осложнения могут возникнуть при портировании приложений из Android, а в случае с iOS этот процесс обещает быть немного легче. Это потому, что архитектура системы Android имеет больше различий с внутренней архитектурой Windows 10, чем iOS. По этой причине перенесенные iOS приложения будут доступны для всех устройств ПК, Xbox, планшеты и смартфоны, в то время как портированные Android-приложения, похоже, будут доступны только для смартфонов.
Еще одна трудность, говорит Кевин Галло, может возникнуть при использовании iOS и Android приложений, предназначенных для небольших устройств, на ПК или планшете с Windows 10 с использованием функции Continuum.
Короче говоря, решение, разработанное Microsoft, безусловно интересное и достойно похвалы, но не может считаться окончательным. Оно может быть эффективным для того, чтобы сэкономить время и ресурсы разработчиков при первых шагах портирования, но не может обеспечить эффективный опыт в долгосрочной перспективе.
Нашли ошибку в тексте? Выделите ее мышью и нажмите Ctrl Enter.
2012-2015 При использовании любых материалов с сайта в безоговорочном порядке делайте ссылку на Наш сайт никак не связан с Microsoft Corp. или Майкрософт Россия. Официальный сайт Windows Phone расположен по адресу