Начало истории
Пришел мне на доработку проект написанный на cocos2d. Игра для детей, в которой необходимо собирать пазлы и учить слова. Работа как работа, но главная проблема заключалась в том, что до меня над проектом работала некая девушка из Индии. И тут у меня начался очень веселый период. Пример того, на что мне пришлось смотреть, что делать и чем все это закончилось, будет под катом.
//SelectPuzzle.h - (void)imagePickerController:(UIImagePickerController *)pickerView didFinishPickingMediaWithInfo:(NSDictionary *)info { [[NSUserDefaults standardUserDefaults]setObject:nil forKey:@"cameraImage"]; UIImage *resiZedImage=[info objectForKey:UIImagePickerControllerOriginalImage]; UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; if (UIInterfaceOrientationIsPortrait(interfaceOrientation)) { isportrait=YES; resiZedImage=[self ImageResize:resiZedImage]; } else { isportrait=NO; resiZedImage=[self imageByCropping:resiZedImage toRect:CGRectMake(800,300,1006,1258)]; } [[NSUserDefaults standardUserDefaults]setInteger:preDefined6 forKey:imageIndex]; [[NSUserDefaults standardUserDefaults]setObject:[NSData dataWithData:UIImagePNGRepresentation(resiZedImage)] forKey:@"cameraImage"]; [[NSUserDefaults standardUserDefaults]synchronize]; [self performSelector:@selector(dismissCameraView:) withObject:pickerView afterDelay:1.0]; [[CCDirector sharedDirector]replaceScene:[PlayScene scene]]; } //PlayScene.m -(void)init{ self = [super init]; if(self){ //... //... camera = YES; NSData* imageData = [[NSUserDefaults standardUserDefaults] objectForKey:@"cameraImage"]; UIImage* cameraImage = [[[UIImage alloc] initWithData:imageData]autorelease]; puzzleObject=[CCSprite spriteWithCGImage:cameraImage.CGImage key:nil]; //... //... } return self; }
Однако пост не об ошибках, которые мне пришлось исправлять, а совсем о другой проблеме.
Через несколько месяцев работы над проектом, когда основные проблемы были решены, заказчик попросил собрать билд под его Android девайс. Далее шел удивительный разговор о том, что первый разработчик должен был писать под cocos2d-x и приложение должно легко запускаться на любом устройстве. Решать проблему пришлось уже мне и мой выбор пал на Apportable.
Собственно тема
Как утверждает официальный сайт, Apportable SDK — это система, которая позволяет запускать один и тот же xCode проект на iOS и Android устройствах. В первую очередь, это касается игр написаных на cocos2d. C портирование некоторых системных Core фреймворков есть проблемы.
Наша игра была написана практически на чистом кокосе и только в двух местах использовались UIKit элементы.
Ну что же. Приступим.
Первое, что необходимо сделать — установить SDK на Mac. Для этого, следуя инструкциям на сайте, необходимо просто ввести в терминале
(echo; echo PATH=~/.apportable/SDK/bin:$PATH) >> ~/.bash_profile; source ~/.bash_profile
SDK требует около 2гб свободного места на диске и установленного xCode 5.
Пока все это скачивается, можно дописать в наш проект необходимый код.
Сначала установим режим эммулирования экрана. Тут есть несколько варианта.
Например:
UIScreenIPhone3GEmulationMode — используется, если ваше приложение не будет поддерживать графику от retina устройств. Размер виртуального экрана 320px/480px, scale — 1.0
UIScreenScaledAspectFitEmulationMode — растягивает ваше приложение в соответсвии с размером экрана Android устройства. Использует не retina графику.
UIScreenBestEmulatedMode — растягивает ваше приложение в соответсвии с размером экрана Android устройства. Использует наиболее подходящую графику. Для корректной работы этого режима должна быть графика для всех вариантов iPhone и iPad экранов. Иначе может выглядеть совсем не best.
int main(int argc, char *argv[]) { @autoreleasepool { #ifdef ANDROID [UIScreen mainScreen].currentMode = [UIScreenMode emulatedMode:UIScreenAspectFitEmulationMode]; #endif int retVal = UIApplicationMain(argc, argv, nil, @"AppController"); return retVal; } }
typedef NS_ENUM(NSUInteger, UIScreenEmulationMode) { UIScreenIPhone3GEmulationMode, UIScreenIPhone4EmulationMode, UIScreenIPhone5EmulationMode, UIScreenIPadEmulationMode, UIScreenIPadRetinaEmulationMode, UIScreenAspectFitEmulationMode, UIScreenScaledAspectFitEmulationMode, UIScreenBestEmulationMode, UIScreenBestEmulatedMode = UIScreenBestEmulationMode, UIScreenNativeMode, UIScreenNativeRetinaMode, UIScreenBestNativeMode, };
Следующее что пришлось переделывать — позиции элементов.
[item setPosition:ccp(400, 600)];
на
[item setPosition:ccp(puzzle.contentSize.width * 0.2, puzzle.contentSize.height * 0.772)];
Тоже самое при отслеживании нажатий.
После этого надо перейти в терминале в папку с проектом и ввести:
apportable load
Эта команда создаст apk файл, загрузит его на подключенное устройство, установит и запустит. В идеальном варианте. Он бывает не всегда. Я не буду рассматривать ошибки линковки файлов, они очень индивидуальны. Однако бывает ситуация когда apportable не видит какой-то определенный девайс. На офисе из 7 устройств, на которых я тестировал приложение, не смог установить на 3.
Что делать в таком случае? Все очень просто. Apportable сначала создает apk файл и только потом пытается загрузить его на устройство. Значит этот файл где-то есть. Если более точно, то вот здесь:
/Users/username/.apportable/SDK/Build/android-armeabi-debug/ProjectName
В этой папке лежит apk файл и его можно просто перекинуть на девайс и установить. Для этого я использовал приложение Android File Transfer(в маке из коробки нельзя обращаться к памяти Android устройств).
Все? Профит? К сожалению нет.
Возникла проблема с фотокамерой. Камера вызывалась, делала фотографию, но при нажатии кнопки подтверждения, приложение падало. Проблема не гуглилась и обещала принести большие проблемы, но… Помощь пришла от наших android разработчиков. Я узнал, что такое манифест и пермишены.
И так. После создания билда с помощью apportable, в директории с проектом появилась папка ProjectName.aproj. В этой папке лежат конфигурационные файлы и файлы, которые не компилируются(например ресурсы).
Нас интересует файл configuration.json. В нем можно изменить настройки компиляции проекта для android. Например, добавить пермишены. Для работы фотокамеры нужны права на запись.
И изменение строки
"FEATURES": ["opengles2","landscape"]
на
"FEATURES": ["opengles2","landscape","write_external_storage"]
волшебным образом решило проблему.
Также есть нюанс с локализацией имени приложения на экране устройства. Для каждого языка необходимо добавить файл strings.xml и положить в папку ProjectName/java/res/values-[lang_description]
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Localization name</string> </resources>
И добавить в configuration.json:
//A list of java resource directories "java_res_dirs": ["java/res"]
Несколько моментов на последок:
- Рамеров экранов у Android устройств очень много, и кое-где приходилось использовать следующие вставки:
Скрытый текст#ifdef ANDROID CGRect frame = [UIScreen mainScreen].applicationFrame;//1.7031 - pad 1.778 - phone CGFloat ratio = frame.size.height / frame.size.width; if (ratio < 1.72) { x = 16; } else{ x = 29; } #endif
- Если в файле configuration.json не стоит флаг «portrait», а Device Orientation в настройках xCode проекта стоит галочка напротив «Portrait», то портретная ориентация поддерживаться будет. Будьте внимательны.
- Официальная документация docs.apportable.com/
- В Apportable дописаны многие системные фреймворки. Официальная документация содержит мало информации об этом. Новые .h файлы с новыми доступными для android методами можно посмотреть в папке
/Users/username/.apportable/SDK/sysroot/System/Library
ссылка на оригинал статьи http://habrahabr.ru/post/234439/
Добавить комментарий