export.cpp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498
  1. #include "version.h"
  2. #include "export.h"
  3. #include "tools/editor/editor_settings.h"
  4. #include "tools/editor/editor_import_export.h"
  5. #include "tools/editor/editor_node.h"
  6. #include "io/zip_io.h"
  7. #include "io/marshalls.h"
  8. #include "globals.h"
  9. #include "os/file_access.h"
  10. #include "os/os.h"
  11. #include "platform/android/logo.h"
  12. static const char* android_perms[]={
  13. "ACCESS_CHECKIN_PROPERTIES",
  14. "ACCESS_COARSE_LOCATION",
  15. "ACCESS_FINE_LOCATION",
  16. "ACCESS_LOCATION_EXTRA_COMMANDS",
  17. "ACCESS_MOCK_LOCATION",
  18. "ACCESS_NETWORK_STATE",
  19. "ACCESS_SURFACE_FLINGER",
  20. "ACCESS_WIFI_STATE",
  21. "ACCOUNT_MANAGER",
  22. "ADD_VOICEMAIL",
  23. "AUTHENTICATE_ACCOUNTS",
  24. "BATTERY_STATS",
  25. "BIND_ACCESSIBILITY_SERVICE",
  26. "BIND_APPWIDGET",
  27. "BIND_DEVICE_ADMIN",
  28. "BIND_INPUT_METHOD",
  29. "BIND_NFC_SERVICE",
  30. "BIND_NOTIFICATION_LISTENER_SERVICE",
  31. "BIND_PRINT_SERVICE",
  32. "BIND_REMOTEVIEWS",
  33. "BIND_TEXT_SERVICE",
  34. "BIND_VPN_SERVICE",
  35. "BIND_WALLPAPER",
  36. "BLUETOOTH",
  37. "BLUETOOTH_ADMIN",
  38. "BLUETOOTH_PRIVILEGED",
  39. "BRICK",
  40. "BROADCAST_PACKAGE_REMOVED",
  41. "BROADCAST_SMS",
  42. "BROADCAST_STICKY",
  43. "BROADCAST_WAP_PUSH",
  44. "CALL_PHONE",
  45. "CALL_PRIVILEGED",
  46. "CAMERA",
  47. "CAPTURE_AUDIO_OUTPUT",
  48. "CAPTURE_SECURE_VIDEO_OUTPUT",
  49. "CAPTURE_VIDEO_OUTPUT",
  50. "CHANGE_COMPONENT_ENABLED_STATE",
  51. "CHANGE_CONFIGURATION",
  52. "CHANGE_NETWORK_STATE",
  53. "CHANGE_WIFI_MULTICAST_STATE",
  54. "CHANGE_WIFI_STATE",
  55. "CLEAR_APP_CACHE",
  56. "CLEAR_APP_USER_DATA",
  57. "CONTROL_LOCATION_UPDATES",
  58. "DELETE_CACHE_FILES",
  59. "DELETE_PACKAGES",
  60. "DEVICE_POWER",
  61. "DIAGNOSTIC",
  62. "DISABLE_KEYGUARD",
  63. "DUMP",
  64. "EXPAND_STATUS_BAR",
  65. "FACTORY_TEST",
  66. "FLASHLIGHT",
  67. "FORCE_BACK",
  68. "GET_ACCOUNTS",
  69. "GET_PACKAGE_SIZE",
  70. "GET_TASKS",
  71. "GET_TOP_ACTIVITY_INFO",
  72. "GLOBAL_SEARCH",
  73. "HARDWARE_TEST",
  74. "INJECT_EVENTS",
  75. "INSTALL_LOCATION_PROVIDER",
  76. "INSTALL_PACKAGES",
  77. "INSTALL_SHORTCUT",
  78. "INTERNAL_SYSTEM_WINDOW",
  79. "INTERNET",
  80. "KILL_BACKGROUND_PROCESSES",
  81. "LOCATION_HARDWARE",
  82. "MANAGE_ACCOUNTS",
  83. "MANAGE_APP_TOKENS",
  84. "MANAGE_DOCUMENTS",
  85. "MASTER_CLEAR",
  86. "MEDIA_CONTENT_CONTROL",
  87. "MODIFY_AUDIO_SETTINGS",
  88. "MODIFY_PHONE_STATE",
  89. "MOUNT_FORMAT_FILESYSTEMS",
  90. "MOUNT_UNMOUNT_FILESYSTEMS",
  91. "NFC",
  92. "PERSISTENT_ACTIVITY",
  93. "PROCESS_OUTGOING_CALLS",
  94. "READ_CALENDAR",
  95. "READ_CALL_LOG",
  96. "READ_CONTACTS",
  97. "READ_EXTERNAL_STORAGE",
  98. "READ_FRAME_BUFFER",
  99. "READ_HISTORY_BOOKMARKS",
  100. "READ_INPUT_STATE",
  101. "READ_LOGS",
  102. "READ_PHONE_STATE",
  103. "READ_PROFILE",
  104. "READ_SMS",
  105. "READ_SOCIAL_STREAM",
  106. "READ_SYNC_SETTINGS",
  107. "READ_SYNC_STATS",
  108. "READ_USER_DICTIONARY",
  109. "REBOOT",
  110. "RECEIVE_BOOT_COMPLETED",
  111. "RECEIVE_MMS",
  112. "RECEIVE_SMS",
  113. "RECEIVE_WAP_PUSH",
  114. "RECORD_AUDIO",
  115. "REORDER_TASKS",
  116. "RESTART_PACKAGES",
  117. "SEND_RESPOND_VIA_MESSAGE",
  118. "SEND_SMS",
  119. "SET_ACTIVITY_WATCHER",
  120. "SET_ALARM",
  121. "SET_ALWAYS_FINISH",
  122. "SET_ANIMATION_SCALE",
  123. "SET_DEBUG_APP",
  124. "SET_ORIENTATION",
  125. "SET_POINTER_SPEED",
  126. "SET_PREFERRED_APPLICATIONS",
  127. "SET_PROCESS_LIMIT",
  128. "SET_TIME",
  129. "SET_TIME_ZONE",
  130. "SET_WALLPAPER",
  131. "SET_WALLPAPER_HINTS",
  132. "SIGNAL_PERSISTENT_PROCESSES",
  133. "STATUS_BAR",
  134. "SUBSCRIBED_FEEDS_READ",
  135. "SUBSCRIBED_FEEDS_WRITE",
  136. "SYSTEM_ALERT_WINDOW",
  137. "TRANSMIT_IR",
  138. "UNINSTALL_SHORTCUT",
  139. "UPDATE_DEVICE_STATS",
  140. "USE_CREDENTIALS",
  141. "USE_SIP",
  142. "VIBRATE",
  143. "WAKE_LOCK",
  144. "WRITE_APN_SETTINGS",
  145. "WRITE_CALENDAR",
  146. "WRITE_CALL_LOG",
  147. "WRITE_CONTACTS",
  148. "WRITE_EXTERNAL_STORAGE",
  149. "WRITE_GSERVICES",
  150. "WRITE_HISTORY_BOOKMARKS",
  151. "WRITE_PROFILE",
  152. "WRITE_SECURE_SETTINGS",
  153. "WRITE_SETTINGS",
  154. "WRITE_SMS",
  155. "WRITE_SOCIAL_STREAM",
  156. "WRITE_SYNC_SETTINGS",
  157. "WRITE_USER_DICTIONARY",
  158. NULL};
  159. class EditorExportPlatformAndroid : public EditorExportPlatform {
  160. OBJ_TYPE( EditorExportPlatformAndroid,EditorExportPlatform );
  161. enum {
  162. MAX_USER_PERMISSIONS=20,
  163. SCREEN_SMALL=0,
  164. SCREEN_NORMAL=1,
  165. SCREEN_LARGE=2,
  166. SCREEN_XLARGE=3,
  167. SCREEN_MAX=4
  168. };
  169. String custom_release_package;
  170. String custom_debug_package;
  171. int version_code;
  172. String version_name;
  173. String package;
  174. String name;
  175. String icon;
  176. bool _signed;
  177. int orientation;
  178. String release_keystore;
  179. String release_username;
  180. struct APKExportData {
  181. zipFile apk;
  182. EditorProgress *ep;
  183. };
  184. struct Device {
  185. String id;
  186. String name;
  187. String description;
  188. };
  189. Vector<Device> devices;
  190. bool devices_changed;
  191. Mutex *device_lock;
  192. Thread *device_thread;
  193. Ref<ImageTexture> logo;
  194. Set<String> perms;
  195. String user_perms[MAX_USER_PERMISSIONS];
  196. bool screen_support[SCREEN_MAX];
  197. volatile bool quit_request;
  198. static void _device_poll_thread(void *ud);
  199. String get_project_name() const;
  200. void _fix_manifest(Vector<uint8_t>& p_manifest);
  201. void _fix_resources(Vector<uint8_t>& p_manifest);
  202. static Error save_apk_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
  203. protected:
  204. bool _set(const StringName& p_name, const Variant& p_value);
  205. bool _get(const StringName& p_name,Variant &r_ret) const;
  206. void _get_property_list( List<PropertyInfo> *p_list) const;
  207. public:
  208. virtual String get_name() const { return "Android"; }
  209. virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_ETC1; }
  210. virtual Ref<Texture> get_logo() const { return logo; }
  211. virtual bool poll_devices();
  212. virtual int get_device_count() const;
  213. virtual String get_device_name(int p_device) const;
  214. virtual String get_device_info(int p_device) const;
  215. virtual Error run(int p_device);
  216. virtual bool requieres_password(bool p_debug) const { return !p_debug; }
  217. virtual String get_binary_extension() const { return "apk"; }
  218. virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
  219. virtual bool can_export(String *r_error=NULL) const;
  220. EditorExportPlatformAndroid();
  221. ~EditorExportPlatformAndroid();
  222. };
  223. bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& p_value) {
  224. String n=p_name;
  225. if (n=="version/code")
  226. version_code=p_value;
  227. else if (n=="version/name")
  228. version_name=p_value;
  229. else if (n=="package/unique_name")
  230. package=p_value;
  231. else if (n=="package/name")
  232. name=p_value;
  233. else if (n=="package/icon")
  234. icon=p_value;
  235. else if (n=="package/signed")
  236. _signed=p_value;
  237. else if (n=="screen/orientation")
  238. orientation=p_value;
  239. else if (n=="screen/support_small")
  240. screen_support[SCREEN_SMALL]=p_value;
  241. else if (n=="screen/support_normal")
  242. screen_support[SCREEN_NORMAL]=p_value;
  243. else if (n=="screen/support_large")
  244. screen_support[SCREEN_LARGE]=p_value;
  245. else if (n=="screen/support_xlarge")
  246. screen_support[SCREEN_XLARGE]=p_value;
  247. else if (n=="keystore/release")
  248. release_keystore=p_value;
  249. else if (n=="keystore/release_user")
  250. release_username=p_value;
  251. else if (n.begins_with("permissions/")) {
  252. String what = n.get_slice("/",1).to_upper();
  253. bool state = p_value;
  254. if (state)
  255. perms.insert(what);
  256. else
  257. perms.erase(what);
  258. } else if (n.begins_with("user_permissions/")) {
  259. int which = n.get_slice("/",1).to_int();
  260. ERR_FAIL_INDEX_V(which,MAX_USER_PERMISSIONS,false);
  261. user_perms[which]=p_value;
  262. } else
  263. return false;
  264. return true;
  265. }
  266. bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) const{
  267. String n=p_name;
  268. if (n=="version/code")
  269. r_ret=version_code;
  270. else if (n=="version/name")
  271. r_ret=version_name;
  272. else if (n=="package/unique_name")
  273. r_ret=package;
  274. else if (n=="package/name")
  275. r_ret=name;
  276. else if (n=="package/icon")
  277. r_ret=icon;
  278. else if (n=="package/signed")
  279. r_ret=_signed;
  280. else if (n=="screen/orientation")
  281. r_ret=orientation;
  282. else if (n=="screen/support_small")
  283. r_ret=screen_support[SCREEN_SMALL];
  284. else if (n=="screen/support_normal")
  285. r_ret=screen_support[SCREEN_NORMAL];
  286. else if (n=="screen/support_large")
  287. r_ret=screen_support[SCREEN_LARGE];
  288. else if (n=="screen/support_xlarge")
  289. r_ret=screen_support[SCREEN_XLARGE];
  290. else if (n=="keystore/release")
  291. r_ret=release_keystore;
  292. else if (n=="keystore/release_user")
  293. r_ret=release_username;
  294. else if (n.begins_with("permissions/")) {
  295. String what = n.get_slice("/",1).to_upper();
  296. r_ret = perms.has(what);
  297. } else if (n.begins_with("user_permissions/")) {
  298. int which = n.get_slice("/",1).to_int();
  299. ERR_FAIL_INDEX_V(which,MAX_USER_PERMISSIONS,false);
  300. r_ret=user_perms[which];
  301. } else
  302. return false;
  303. return true;
  304. }
  305. void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list) const{
  306. p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_FILE,"apk"));
  307. p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_FILE,"apk"));
  308. p_list->push_back( PropertyInfo( Variant::INT, "version/code", PROPERTY_HINT_RANGE,"1,65535,1"));
  309. p_list->push_back( PropertyInfo( Variant::STRING, "version/name") );
  310. p_list->push_back( PropertyInfo( Variant::STRING, "package/unique_name") );
  311. p_list->push_back( PropertyInfo( Variant::STRING, "package/name") );
  312. p_list->push_back( PropertyInfo( Variant::STRING, "package/icon",PROPERTY_HINT_FILE,"png") );
  313. p_list->push_back( PropertyInfo( Variant::BOOL, "package/signed") );
  314. p_list->push_back( PropertyInfo( Variant::INT, "screen/orientation",PROPERTY_HINT_ENUM,"Landscape,Portrait") );
  315. p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_small") );
  316. p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_normal") );
  317. p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_large") );
  318. p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_xlarge") );
  319. p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release",PROPERTY_HINT_FILE,"keystore") );
  320. p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_user" ) );
  321. const char **perms = android_perms;
  322. while(*perms) {
  323. p_list->push_back( PropertyInfo( Variant::BOOL, "permissions/"+String(*perms).to_lower()));
  324. perms++;
  325. }
  326. for(int i=0;i<MAX_USER_PERMISSIONS;i++) {
  327. p_list->push_back( PropertyInfo( Variant::STRING, "user_permissions/"+itos(i)));
  328. }
  329. //p_list->push_back( PropertyInfo( Variant::INT, "resources/pack_mode", PROPERTY_HINT_ENUM,"Copy,Single Exec.,Pack (.pck),Bundles (Optical)"));
  330. }
  331. static String _parse_string(const uint8_t *p_bytes,bool p_utf8) {
  332. uint32_t offset=0;
  333. uint32_t len = decode_uint16(&p_bytes[offset]);
  334. if (p_utf8) {
  335. //don't know how to read extended utf8, this will have to be for now
  336. len>>=8;
  337. }
  338. offset+=2;
  339. printf("len %i, unicode: %i\n",len,int(p_utf8));
  340. if (p_utf8) {
  341. Vector<uint8_t> str8;
  342. str8.resize(len+1);
  343. for(int i=0;i<len;i++) {
  344. str8[i]=p_bytes[offset+i];
  345. }
  346. str8[len]=0;
  347. String str;
  348. str.parse_utf8((const char*)str8.ptr());
  349. return str;
  350. } else {
  351. String str;
  352. for(int i=0;i<len;i++) {
  353. CharType c = decode_uint16(&p_bytes[offset+i*2]);
  354. if (c==0)
  355. break;
  356. str += String::chr(c);
  357. }
  358. return str;
  359. }
  360. }
  361. void EditorExportPlatformAndroid::_fix_resources(Vector<uint8_t>& p_manifest) {
  362. const int UTF8_FLAG = 0x00000100;
  363. print_line("*******************GORRRGLE***********************");
  364. uint32_t header = decode_uint32(&p_manifest[0]);
  365. uint32_t filesize = decode_uint32(&p_manifest[4]);
  366. uint32_t string_block_len = decode_uint32(&p_manifest[16]);
  367. uint32_t string_count = decode_uint32(&p_manifest[20]);
  368. uint32_t string_flags = decode_uint32(&p_manifest[28]);
  369. const uint32_t string_table_begins = 40;
  370. Vector<String> string_table;
  371. printf("stirng block len: %i\n",string_block_len);
  372. printf("stirng count: %i\n",string_count);
  373. printf("flags: %x\n",string_flags);
  374. for(int i=0;i<string_count;i++) {
  375. uint32_t offset = decode_uint32(&p_manifest[string_table_begins+i*4]);
  376. offset+=string_table_begins+string_count*4;
  377. String str = _parse_string(&p_manifest[offset],string_flags&UTF8_FLAG);
  378. if (str.begins_with("godot-project-name")) {
  379. if (str=="godot-project-name") {
  380. //project name
  381. str = get_project_name();
  382. } else {
  383. String lang = str.substr(str.find_last("-")+1,str.length()).replace("-","_");
  384. String prop = "application/name_"+lang;
  385. if (Globals::get_singleton()->has(prop)) {
  386. str = Globals::get_singleton()->get(prop);
  387. } else {
  388. str = get_project_name();
  389. }
  390. }
  391. }
  392. string_table.push_back(str);
  393. }
  394. //write a new string table, but use 16 bits
  395. Vector<uint8_t> ret;
  396. ret.resize(string_table_begins+string_table.size()*4);
  397. for(int i=0;i<string_table_begins;i++) {
  398. ret[i]=p_manifest[i];
  399. }
  400. int ofs=0;
  401. for(int i=0;i<string_table.size();i++) {
  402. encode_uint32(ofs,&ret[string_table_begins+i*4]);
  403. ofs+=string_table[i].length()*2+2+2;
  404. }
  405. ret.resize(ret.size()+ofs);
  406. uint8_t *chars=&ret[ret.size()-ofs];
  407. for(int i=0;i<string_table.size();i++) {
  408. String s = string_table[i];
  409. encode_uint16(s.length(),chars);
  410. chars+=2;
  411. for(int j=0;j<s.length();j++) {
  412. encode_uint16(s[j],chars);
  413. chars+=2;
  414. }
  415. encode_uint16(0,chars);
  416. chars+=2;
  417. }
  418. //pad
  419. while(ret.size()%4)
  420. ret.push_back(0);
  421. //change flags to not use utf8
  422. encode_uint32(string_flags&~0x100,&ret[28]);
  423. //change length
  424. encode_uint32(ret.size()-12,&ret[16]);
  425. //append the rest...
  426. int rest_from = 12+string_block_len;
  427. int rest_to = ret.size();
  428. int rest_len = (p_manifest.size() - rest_from);
  429. ret.resize(ret.size() + (p_manifest.size() - rest_from) );
  430. for(int i=0;i<rest_len;i++) {
  431. ret[rest_to+i]=p_manifest[rest_from+i];
  432. }
  433. //finally update the size
  434. encode_uint32(ret.size(),&ret[4]);
  435. p_manifest=ret;
  436. printf("end\n");
  437. }
  438. String EditorExportPlatformAndroid::get_project_name() const {
  439. String aname;
  440. if (this->name!="") {
  441. aname=this->name;
  442. } else {
  443. aname = Globals::get_singleton()->get("application/name");
  444. }
  445. if (aname=="") {
  446. aname=_MKSTR(VERSION_NAME);
  447. }
  448. return aname;
  449. }
  450. void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest) {
  451. const int CHUNK_AXML_FILE = 0x00080003;
  452. const int CHUNK_RESOURCEIDS = 0x00080180;
  453. const int CHUNK_STRINGS = 0x001C0001;
  454. const int CHUNK_XML_END_NAMESPACE = 0x00100101;
  455. const int CHUNK_XML_END_TAG = 0x00100103;
  456. const int CHUNK_XML_START_NAMESPACE = 0x00100100;
  457. const int CHUNK_XML_START_TAG = 0x00100102;
  458. const int CHUNK_XML_TEXT = 0x00100104;
  459. const int UTF8_FLAG = 0x00000100;
  460. Vector<String> string_table;
  461. uint32_t ofs=0;
  462. uint32_t header = decode_uint32(&p_manifest[ofs]);
  463. uint32_t filesize = decode_uint32(&p_manifest[ofs+4]);
  464. ofs+=8;
  465. // print_line("FILESIZE: "+itos(filesize)+" ACTUAL: "+itos(p_manifest.size()));
  466. uint32_t string_count;
  467. uint32_t styles_count;
  468. uint32_t string_flags;
  469. uint32_t string_data_offset;
  470. uint32_t styles_offset;
  471. uint32_t string_table_begins;
  472. uint32_t string_table_ends;
  473. Vector<uint8_t> stable_extra;
  474. while(ofs < p_manifest.size()) {
  475. uint32_t chunk = decode_uint32(&p_manifest[ofs]);
  476. uint32_t size = decode_uint32(&p_manifest[ofs+4]);
  477. switch(chunk) {
  478. case CHUNK_STRINGS: {
  479. int iofs=ofs+8;
  480. uint32_t string_count=decode_uint32(&p_manifest[iofs]);
  481. uint32_t styles_count=decode_uint32(&p_manifest[iofs+4]);
  482. uint32_t string_flags=decode_uint32(&p_manifest[iofs+8]);
  483. uint32_t string_data_offset=decode_uint32(&p_manifest[iofs+12]);
  484. uint32_t styles_offset=decode_uint32(&p_manifest[iofs+16]);
  485. /*
  486. printf("string count: %i\n",string_count);
  487. printf("flags: %i\n",string_flags);
  488. printf("sdata ofs: %i\n",string_data_offset);
  489. printf("styles ofs: %i\n",styles_offset);
  490. */
  491. uint32_t st_offset=iofs+20;
  492. string_table.resize(string_count);
  493. uint32_t string_end=0;
  494. string_table_begins=st_offset;
  495. for(int i=0;i<string_count;i++) {
  496. uint32_t string_at = decode_uint32(&p_manifest[st_offset+i*4]);
  497. string_at+=st_offset+string_count*4;
  498. ERR_EXPLAIN("Unimplemented, can't read utf8 string table.");
  499. ERR_FAIL_COND(string_flags&UTF8_FLAG);
  500. if (string_flags&UTF8_FLAG) {
  501. } else {
  502. uint32_t len = decode_uint16(&p_manifest[string_at]);
  503. Vector<CharType> ucstring;
  504. ucstring.resize(len+1);
  505. for(int j=0;j<len;j++) {
  506. uint16_t c=decode_uint16(&p_manifest[string_at+2+2*j]);
  507. ucstring[j]=c;
  508. }
  509. string_end=MAX(string_at+2+2*len,string_end);
  510. ucstring[len]=0;
  511. string_table[i]=ucstring.ptr();
  512. }
  513. // print_line("String "+itos(i)+": "+string_table[i]);
  514. }
  515. for(int i=string_end;i<(ofs+size);i++) {
  516. stable_extra.push_back(p_manifest[i]);
  517. }
  518. // printf("stable extra: %i\n",int(stable_extra.size()));
  519. string_table_ends=ofs+size;
  520. // print_line("STABLE SIZE: "+itos(size)+" ACTUAL: "+itos(string_table_ends));
  521. } break;
  522. case CHUNK_XML_START_TAG: {
  523. int iofs=ofs+8;
  524. uint32_t line=decode_uint32(&p_manifest[iofs]);
  525. uint32_t nspace=decode_uint32(&p_manifest[iofs+8]);
  526. uint32_t name=decode_uint32(&p_manifest[iofs+12]);
  527. uint32_t check=decode_uint32(&p_manifest[iofs+16]);
  528. String tname=string_table[name];
  529. // printf("NSPACE: %i\n",nspace);
  530. //printf("NAME: %i (%s)\n",name,tname.utf8().get_data());
  531. //printf("CHECK: %x\n",check);
  532. uint32_t attrcount=decode_uint32(&p_manifest[iofs+20]);
  533. iofs+=28;
  534. //printf("ATTRCOUNT: %x\n",attrcount);
  535. for(int i=0;i<attrcount;i++) {
  536. uint32_t attr_nspace=decode_uint32(&p_manifest[iofs]);
  537. uint32_t attr_name=decode_uint32(&p_manifest[iofs+4]);
  538. uint32_t attr_value=decode_uint32(&p_manifest[iofs+8]);
  539. uint32_t attr_flags=decode_uint32(&p_manifest[iofs+12]);
  540. uint32_t attr_resid=decode_uint32(&p_manifest[iofs+16]);
  541. String value;
  542. if (attr_value!=0xFFFFFFFF)
  543. value=string_table[attr_value];
  544. else
  545. value="Res #"+itos(attr_resid);
  546. String attrname = string_table[attr_name];
  547. String nspace;
  548. if (attr_nspace!=0xFFFFFFFF)
  549. nspace=string_table[attr_nspace];
  550. else
  551. nspace="";
  552. printf("ATTR %i NSPACE: %i\n",i,attr_nspace);
  553. printf("ATTR %i NAME: %i (%s)\n",i,attr_name,attrname.utf8().get_data());
  554. printf("ATTR %i VALUE: %i (%s)\n",i,attr_value,value.utf8().get_data());
  555. printf("ATTR %i FLAGS: %x\n",i,attr_flags);
  556. printf("ATTR %i RESID: %x\n",i,attr_resid);
  557. //replace project information
  558. if (tname=="manifest" && attrname=="package") {
  559. print_line("FOUND PACKAGE");
  560. string_table[attr_value]=package;
  561. }
  562. //print_line("tname: "+tname);
  563. //print_line("nspace: "+nspace);
  564. //print_line("attrname: "+attrname);
  565. if (tname=="manifest" && /*nspace=="android" &&*/ attrname=="versionCode") {
  566. print_line("FOUND versioncode");
  567. encode_uint32(version_code,&p_manifest[iofs+16]);
  568. }
  569. if (tname=="manifest" && /*nspace=="android" &&*/ attrname=="versionName") {
  570. print_line("FOUND versionname");
  571. if (attr_value==0xFFFFFFFF) {
  572. WARN_PRINT("Version name in a resource, should be plaintext")
  573. } else
  574. string_table[attr_value]=version_name;
  575. }
  576. if (tname=="activity" && /*nspace=="android" &&*/ attrname=="screenOrientation") {
  577. print_line("FOUND screen orientation");
  578. if (attr_value==0xFFFFFFFF) {
  579. WARN_PRINT("Version name in a resource, should be plaintext")
  580. } else {
  581. string_table[attr_value]=(orientation==0?"landscape":"portrait");
  582. }
  583. }
  584. if (tname=="application" && /*nspace=="android" &&*/ attrname=="label") {
  585. print_line("FOUND application");
  586. if (attr_value==0xFFFFFFFF) {
  587. WARN_PRINT("Application name in a resource, should be plaintext.")
  588. } else {
  589. String aname = get_project_name();
  590. string_table[attr_value]=aname;
  591. }
  592. }
  593. if (tname=="activity" && /*nspace=="android" &&*/ attrname=="label") {
  594. print_line("FOUND activity name");
  595. if (attr_value==0xFFFFFFFF) {
  596. WARN_PRINT("Activity name in a resource, should be plaintext")
  597. } else {
  598. String aname;
  599. if (this->name!="") {
  600. aname=this->name;
  601. } else {
  602. aname = Globals::get_singleton()->get("application/name");
  603. }
  604. if (aname=="") {
  605. aname=_MKSTR(VERSION_NAME);
  606. }
  607. print_line("APP NAME IS..."+aname);
  608. string_table[attr_value]=aname;
  609. }
  610. }
  611. if (tname=="uses-permission" && /*nspace=="android" &&*/ attrname=="name") {
  612. if (value.begins_with("godot.custom")) {
  613. int which = value.get_slice(".",2).to_int();
  614. if (which>=0 && which<MAX_USER_PERMISSIONS && user_perms[which].strip_edges()!="") {
  615. string_table[attr_value]=user_perms[which].strip_edges();
  616. }
  617. } else if (value.begins_with("godot.")) {
  618. String perm = value.get_slice(".",1);
  619. if (perms.has(perm)) {
  620. string_table[attr_value]="android.permission."+perm;
  621. }
  622. }
  623. }
  624. if (tname=="supports-screens" ) {
  625. if (attr_value==0xFFFFFFFF) {
  626. WARN_PRINT("Screen res name in a resource, should be plaintext")
  627. } else if (attrname=="smallScreens") {
  628. print_line("SMALLSCREEN");
  629. string_table[attr_value]=screen_support[SCREEN_SMALL]?"true":"false";
  630. } else if (attrname=="mediumScreens") {
  631. print_line("MEDSCREEN");
  632. string_table[attr_value]=screen_support[SCREEN_NORMAL]?"true":"false";
  633. } else if (attrname=="largeScreens") {
  634. print_line("LARGECREEN");
  635. string_table[attr_value]=screen_support[SCREEN_LARGE]?"true":"false";
  636. } else if (attrname=="xlargeScreens") {
  637. print_line("XLARGECREEN");
  638. string_table[attr_value]=screen_support[SCREEN_XLARGE]?"true":"false";
  639. }
  640. }
  641. iofs+=20;
  642. }
  643. } break;
  644. }
  645. printf("chunk %x: size: %d\n",chunk,size);
  646. ofs+=size;
  647. }
  648. printf("end\n");
  649. //create new andriodmanifest binary
  650. Vector<uint8_t> ret;
  651. ret.resize(string_table_begins+string_table.size()*4);
  652. for(int i=0;i<string_table_begins;i++) {
  653. ret[i]=p_manifest[i];
  654. }
  655. ofs=0;
  656. for(int i=0;i<string_table.size();i++) {
  657. encode_uint32(ofs,&ret[string_table_begins+i*4]);
  658. ofs+=string_table[i].length()*2+2+2;
  659. print_line("ofs: "+itos(i)+": "+itos(ofs));
  660. }
  661. ret.resize(ret.size()+ofs);
  662. uint8_t *chars=&ret[ret.size()-ofs];
  663. for(int i=0;i<string_table.size();i++) {
  664. String s = string_table[i];
  665. print_line("savint string :"+s);
  666. encode_uint16(s.length(),chars);
  667. chars+=2;
  668. for(int j=0;j<s.length();j++) { //include zero?
  669. encode_uint16(s[j],chars);
  670. chars+=2;
  671. }
  672. encode_uint16(0,chars);
  673. chars+=2;
  674. }
  675. ret.resize(ret.size()+stable_extra.size());
  676. while(ret.size()%4)
  677. ret.push_back(0);
  678. for(int i=0;i<stable_extra.size();i++) {
  679. chars[i]=stable_extra[i];
  680. }
  681. uint32_t new_stable_end=ret.size();
  682. uint32_t extra = (p_manifest.size()-string_table_ends);
  683. ret.resize(new_stable_end + extra);
  684. for(int i=0;i<extra;i++)
  685. ret[new_stable_end+i]=p_manifest[string_table_ends+i];
  686. while(ret.size()%4)
  687. ret.push_back(0);
  688. encode_uint32(ret.size(),&ret[4]); //update new file size
  689. encode_uint32(new_stable_end-8,&ret[12]); //update new string table size
  690. print_line("file size: "+itos(ret.size()));
  691. p_manifest=ret;
  692. #if 0
  693. uint32_t header[9];
  694. for(int i=0;i<9;i++) {
  695. header[i]=decode_uint32(&p_manifest[i*4]);
  696. }
  697. print_line("STO: "+itos(header[3]));
  698. uint32_t st_offset=9*4;
  699. //ERR_FAIL_COND(header[3]!=0x24)
  700. uint32_t string_count=header[4];
  701. string_table.resize(string_count);
  702. for(int i=0;i<string_count;i++) {
  703. uint32_t string_at = decode_uint32(&p_manifest[st_offset+i*4]);
  704. string_at+=st_offset+string_count*4;
  705. uint32_t len = decode_uint16(&p_manifest[string_at]);
  706. Vector<CharType> ucstring;
  707. ucstring.resize(len+1);
  708. for(int j=0;j<len;j++) {
  709. uint16_t c=decode_uint16(&p_manifest[string_at+2+2*j]);
  710. ucstring[j]=c;
  711. }
  712. ucstring[len]=0;
  713. string_table[i]=ucstring.ptr();
  714. }
  715. #endif
  716. }
  717. Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
  718. APKExportData *ed=(APKExportData*)p_userdata;
  719. String dst_path=p_path;
  720. dst_path=dst_path.replace_first("res://","assets/");
  721. zipOpenNewFileInZip(ed->apk,
  722. dst_path.utf8().get_data(),
  723. NULL,
  724. NULL,
  725. 0,
  726. NULL,
  727. 0,
  728. NULL,
  729. Z_DEFLATED,
  730. Z_DEFAULT_COMPRESSION);
  731. zipWriteInFileInZip(ed->apk,p_data.ptr(),p_data.size());
  732. zipCloseFileInZip(ed->apk);
  733. ed->ep->step("File: "+p_path,3+p_file*100/p_total);
  734. return OK;
  735. }
  736. Error EditorExportPlatformAndroid::export_project(const String& p_path,bool p_debug,const String& p_password) {
  737. String src_apk;
  738. EditorProgress ep("export","Exporting for Android",104);
  739. String apk_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
  740. if (p_debug) {
  741. src_apk=custom_debug_package!=""?custom_debug_package:apk_path+"android_debug.apk";
  742. } else {
  743. src_apk=custom_release_package!=""?custom_release_package:apk_path+"android_release.apk";
  744. }
  745. FileAccess *src_f=NULL;
  746. zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
  747. ep.step("Creating APK",0);
  748. unzFile pkg = unzOpen2(src_apk.utf8().get_data(), &io);
  749. if (!pkg) {
  750. EditorNode::add_io_error("Could not find template APK to export:\n"+src_apk);
  751. return ERR_FILE_NOT_FOUND;
  752. }
  753. ERR_FAIL_COND_V(!pkg, ERR_CANT_OPEN);
  754. int ret = unzGoToFirstFile(pkg);
  755. zlib_filefunc_def io2=io;
  756. FileAccess *dst_f=NULL;
  757. io2.opaque=&dst_f;
  758. zipFile apk=zipOpen2(p_path.utf8().get_data(),APPEND_STATUS_CREATE,NULL,&io2);
  759. while(ret==UNZ_OK) {
  760. //get filename
  761. unz_file_info info;
  762. char fname[16384];
  763. ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
  764. String file=fname;
  765. Vector<uint8_t> data;
  766. data.resize(info.uncompressed_size);
  767. //read
  768. unzOpenCurrentFile(pkg);
  769. unzReadCurrentFile(pkg,data.ptr(),data.size());
  770. unzCloseCurrentFile(pkg);
  771. //write
  772. if (file=="AndroidManifest.xml") {
  773. _fix_manifest(data);
  774. }
  775. if (file=="resources.arsc") {
  776. _fix_resources(data);
  777. }
  778. if (file=="res/drawable/icon.png") {
  779. bool found=false;
  780. if (this->icon!="" && this->icon.ends_with(".png")) {
  781. FileAccess *f = FileAccess::open(this->icon,FileAccess::READ);
  782. if (f) {
  783. data.resize(f->get_len());
  784. f->get_buffer(data.ptr(),data.size());
  785. memdelete(f);
  786. found=true;
  787. }
  788. }
  789. if (!found) {
  790. String appicon = Globals::get_singleton()->get("application/icon");
  791. if (appicon!="" && appicon.ends_with(".png")) {
  792. FileAccess*f = FileAccess::open(appicon,FileAccess::READ);
  793. if (f) {
  794. data.resize(f->get_len());
  795. f->get_buffer(data.ptr(),data.size());
  796. memdelete(f);
  797. }
  798. }
  799. }
  800. }
  801. print_line("ADDING: "+file);
  802. zipOpenNewFileInZip(apk,
  803. file.utf8().get_data(),
  804. NULL,
  805. NULL,
  806. 0,
  807. NULL,
  808. 0,
  809. NULL,
  810. Z_DEFLATED,
  811. Z_DEFAULT_COMPRESSION);
  812. zipWriteInFileInZip(apk,data.ptr(),data.size());
  813. zipCloseFileInZip(apk);
  814. ret = unzGoToNextFile(pkg);
  815. }
  816. ep.step("Adding Files..",1);
  817. APKExportData ed;
  818. ed.ep=&ep;
  819. ed.apk=apk;
  820. Error err = export_project_files(save_apk_file,&ed,false);
  821. zipClose(apk,NULL);
  822. unzClose(pkg);
  823. if (err) {
  824. return err;
  825. }
  826. if (_signed) {
  827. String jarsigner=EditorSettings::get_singleton()->get("android/jarsigner");
  828. if (!FileAccess::exists(jarsigner)) {
  829. EditorNode::add_io_error("'jarsigner' could not be found.\nPlease supply a path in the editor settings.\nResulting apk is unsigned.");
  830. return OK;
  831. }
  832. String keystore;
  833. String password;
  834. String user;
  835. if (p_debug) {
  836. keystore=EditorSettings::get_singleton()->get("android/debug_keystore");
  837. password=EditorSettings::get_singleton()->get("android/debug_keystore_pass");
  838. user=EditorSettings::get_singleton()->get("android/debug_keystore_user");
  839. ep.step("Signing Debug APK..",103);
  840. } else {
  841. keystore=release_keystore;
  842. password=p_password;
  843. user=release_username;
  844. ep.step("Signing Release APK..",103);
  845. }
  846. if (!FileAccess::exists(keystore)) {
  847. EditorNode::add_io_error("Could not find keytore, unable to export.");
  848. return ERR_FILE_CANT_OPEN;
  849. }
  850. List<String> args;
  851. args.push_back("-digestalg");
  852. args.push_back("SHA1");
  853. args.push_back("-sigalg");
  854. args.push_back("MD5withRSA");
  855. args.push_back("-verbose");
  856. args.push_back("-keystore");
  857. args.push_back(keystore);
  858. args.push_back("-storepass");
  859. args.push_back(password);
  860. args.push_back(p_path);
  861. args.push_back(user);
  862. int retval;
  863. int err = OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval);
  864. if (retval) {
  865. EditorNode::add_io_error("'jarsigner' returned with error #"+itos(retval));
  866. return ERR_CANT_CREATE;
  867. }
  868. ep.step("Verifying APK..",104);
  869. args.clear();
  870. args.push_back("-verify");
  871. args.push_back(p_path);
  872. args.push_back("-verbose");
  873. err = OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval);
  874. if (retval) {
  875. EditorNode::add_io_error("'jarsigner' verificaiton of APK failed. Make sure to use jarsigner from Java 6.");
  876. return ERR_CANT_CREATE;
  877. }
  878. }
  879. return OK;
  880. }
  881. bool EditorExportPlatformAndroid::poll_devices() {
  882. bool dc=devices_changed;
  883. devices_changed=false;
  884. return dc;
  885. }
  886. int EditorExportPlatformAndroid::get_device_count() const {
  887. device_lock->lock();
  888. int dc=devices.size();
  889. device_lock->unlock();
  890. return dc;
  891. }
  892. String EditorExportPlatformAndroid::get_device_name(int p_device) const {
  893. ERR_FAIL_INDEX_V(p_device,devices.size(),"");
  894. device_lock->lock();
  895. String s=devices[p_device].name;
  896. device_lock->unlock();
  897. return s;
  898. }
  899. String EditorExportPlatformAndroid::get_device_info(int p_device) const {
  900. ERR_FAIL_INDEX_V(p_device,devices.size(),"");
  901. device_lock->lock();
  902. String s=devices[p_device].description;
  903. device_lock->unlock();
  904. return s;
  905. }
  906. void EditorExportPlatformAndroid::_device_poll_thread(void *ud) {
  907. EditorExportPlatformAndroid *ea=(EditorExportPlatformAndroid *)ud;
  908. while(!ea->quit_request) {
  909. String adb=EditorSettings::get_singleton()->get("android/adb");
  910. if (!FileAccess::exists(adb)) {
  911. OS::get_singleton()->delay_usec(3000000);
  912. continue; //adb not configured
  913. }
  914. String devices;
  915. List<String> args;
  916. args.push_back("devices");
  917. int ec;
  918. Error err = OS::get_singleton()->execute(adb,args,true,NULL,&devices,&ec);
  919. Vector<String> ds = devices.split("\n");
  920. Vector<String> ldevices;
  921. for(int i=1;i<ds.size();i++) {
  922. String d = ds[i];
  923. int dpos = d.find("device");
  924. if (dpos==-1)
  925. continue;
  926. d=d.substr(0,dpos).strip_edges();
  927. // print_line("found devuce: "+d);
  928. ldevices.push_back(d);
  929. }
  930. ea->device_lock->lock();
  931. bool different=false;
  932. if (devices.size()!=ldevices.size()) {
  933. different=true;
  934. } else {
  935. for(int i=0;i<ea->devices.size();i++) {
  936. if (ea->devices[i].id!=ldevices[i]) {
  937. different=true;
  938. break;
  939. }
  940. }
  941. }
  942. if (different) {
  943. Vector<Device> ndevices;
  944. for(int i=0;i<ldevices.size();i++) {
  945. Device d;
  946. d.id=ldevices[i];
  947. for(int j=0;j<ea->devices.size();j++) {
  948. if (ea->devices[j].id==ldevices[i]) {
  949. d.description=ea->devices[j].description;
  950. d.name=ea->devices[j].name;
  951. }
  952. }
  953. if (d.description=="") {
  954. //in the oven, request!
  955. args.clear();
  956. args.push_back("-s");
  957. args.push_back(d.id);
  958. args.push_back("shell");
  959. args.push_back("cat");
  960. args.push_back("/system/build.prop");
  961. int ec;
  962. String dp;
  963. Error err = OS::get_singleton()->execute(adb,args,true,NULL,&dp,&ec);
  964. print_line("RV: "+itos(ec));
  965. Vector<String> props = dp.split("\n");
  966. String vendor;
  967. String device;
  968. d.description+"Device ID: "+d.id+"\n";
  969. for(int j=0;j<props.size();j++) {
  970. String p = props[j];
  971. if (p.begins_with("ro.product.model=")) {
  972. device=p.get_slice("=",1).strip_edges();
  973. } else if (p.begins_with("ro.product.brand=")) {
  974. vendor=p.get_slice("=",1).strip_edges().capitalize();
  975. } else if (p.begins_with("ro.build.display.id=")) {
  976. d.description+="Build: "+p.get_slice("=",1).strip_edges()+"\n";
  977. } else if (p.begins_with("ro.build.version.release=")) {
  978. d.description+="Release: "+p.get_slice("=",1).strip_edges()+"\n";
  979. } else if (p.begins_with("ro.product.cpu.abi=")) {
  980. d.description+="CPU: "+p.get_slice("=",1).strip_edges()+"\n";
  981. } else if (p.begins_with("ro.product.manufacturer=")) {
  982. d.description+="Manufacturer: "+p.get_slice("=",1).strip_edges()+"\n";
  983. } else if (p.begins_with("ro.board.platform=")) {
  984. d.description+="Chipset: "+p.get_slice("=",1).strip_edges()+"\n";
  985. } else if (p.begins_with("ro.opengles.version=")) {
  986. uint32_t opengl = p.get_slice("=",1).to_int();
  987. d.description+="OpenGL: "+itos(opengl>>16)+"."+itos((opengl>>8)&0xFF)+"."+itos((opengl)&0xFF)+"\n";
  988. }
  989. }
  990. d.name=vendor+" "+device;
  991. // print_line("name: "+d.name);
  992. // print_line("description: "+d.description);
  993. }
  994. ndevices.push_back(d);
  995. }
  996. ea->devices=ndevices;
  997. ea->devices_changed=true;
  998. }
  999. ea->device_lock->unlock();
  1000. OS::get_singleton()->delay_usec(3000000);
  1001. }
  1002. }
  1003. Error EditorExportPlatformAndroid::run(int p_device) {
  1004. ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
  1005. device_lock->lock();
  1006. EditorProgress ep("run","Running on "+devices[p_device].name,3);
  1007. String adb=EditorSettings::get_singleton()->get("android/adb");
  1008. if (adb=="") {
  1009. EditorNode::add_io_error("ADB executable not configured in settings, can't run.");
  1010. device_lock->unlock();
  1011. return ERR_UNCONFIGURED;
  1012. }
  1013. //export_temp
  1014. ep.step("Exporting APK",0);
  1015. String export_to=EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpexport.apk";
  1016. Error err = export_project(export_to,true);
  1017. if (err) {
  1018. device_lock->unlock();
  1019. return err;
  1020. }
  1021. ep.step("Uninstalling..",1);
  1022. print_line("Uninstalling previous version: "+devices[p_device].name);
  1023. List<String> args;
  1024. args.push_back("-s");
  1025. args.push_back(devices[p_device].id);
  1026. args.push_back("uninstall");
  1027. args.push_back(package);
  1028. int rv;
  1029. err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
  1030. #if 0
  1031. if (err || rv!=0) {
  1032. EditorNode::add_io_error("Could not install to device.");
  1033. device_lock->unlock();
  1034. return ERR_CANT_CREATE;
  1035. }
  1036. #endif
  1037. print_line("Installing into device (please wait..): "+devices[p_device].name);
  1038. ep.step("Installing to Device (please wait..)..",2);
  1039. args.clear();
  1040. args.push_back("-s");
  1041. args.push_back(devices[p_device].id);
  1042. args.push_back("install");
  1043. args.push_back(export_to);
  1044. rv;
  1045. err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
  1046. if (err || rv!=0) {
  1047. EditorNode::add_io_error("Could not install to device.");
  1048. device_lock->unlock();
  1049. return ERR_CANT_CREATE;
  1050. }
  1051. ep.step("Running on Device..",3);
  1052. args.clear();
  1053. args.push_back("-s");
  1054. args.push_back(devices[p_device].id);
  1055. args.push_back("shell");
  1056. args.push_back("am");
  1057. args.push_back("start");
  1058. args.push_back("-a");
  1059. args.push_back("android.intent.action.MAIN");
  1060. args.push_back("-n");
  1061. args.push_back(package+"/com.android.godot.Godot");
  1062. err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
  1063. if (err || rv!=0) {
  1064. EditorNode::add_io_error("Could not execute ondevice.");
  1065. device_lock->unlock();
  1066. return ERR_CANT_CREATE;
  1067. }
  1068. device_lock->unlock();
  1069. return OK;
  1070. }
  1071. EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
  1072. version_code=1;
  1073. version_name="1.0";
  1074. package="com.android.noname";
  1075. name="";
  1076. _signed=true;
  1077. device_lock = Mutex::create();
  1078. quit_request=false;
  1079. orientation=0;
  1080. device_thread=Thread::create(_device_poll_thread,this);
  1081. devices_changed=true;
  1082. Image img( _android_logo );
  1083. logo = Ref<ImageTexture>( memnew( ImageTexture ));
  1084. logo->create_from_image(img);
  1085. for(int i=0;i<4;i++)
  1086. screen_support[i]=true;
  1087. }
  1088. bool EditorExportPlatformAndroid::can_export(String *r_error) const {
  1089. bool valid=true;
  1090. String adb=EditorSettings::get_singleton()->get("android/adb");
  1091. String err;
  1092. if (!FileAccess::exists(adb)) {
  1093. valid=false;
  1094. err+="ADB executable not configured in editor settings.\n";
  1095. }
  1096. String js = EditorSettings::get_singleton()->get("android/jarsigner");
  1097. if (!FileAccess::exists(js)) {
  1098. valid=false;
  1099. err+="OpenJDK 6 jarsigner not configured in editor settings.\n";
  1100. }
  1101. String dk = EditorSettings::get_singleton()->get("android/debug_keystore");
  1102. if (!FileAccess::exists(dk)) {
  1103. valid=false;
  1104. err+="Debug Keystore not configured in editor settings.\n";
  1105. }
  1106. String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
  1107. if (!FileAccess::exists(exe_path+"android_debug.apk") || !FileAccess::exists(exe_path+"android_release.apk")) {
  1108. valid=false;
  1109. err+="No export templates found.\nDownload and install export templates.\n";
  1110. }
  1111. if (custom_debug_package!="" && !FileAccess::exists(custom_debug_package)) {
  1112. valid=false;
  1113. err+="Custom debug package not found.\n";
  1114. }
  1115. if (custom_release_package!="" && !FileAccess::exists(custom_release_package)) {
  1116. valid=false;
  1117. err+="Custom release package not found.\n";
  1118. }
  1119. if (r_error)
  1120. *r_error=err;
  1121. return valid;
  1122. }
  1123. EditorExportPlatformAndroid::~EditorExportPlatformAndroid() {
  1124. quit_request=true;
  1125. Thread::wait_to_finish(device_thread);
  1126. }
  1127. void register_android_exporter() {
  1128. String exe_ext=OS::get_singleton()->get_name()=="Windows"?"exe":"";
  1129. EDITOR_DEF("android/adb","");
  1130. EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/adb",PROPERTY_HINT_GLOBAL_FILE,exe_ext));
  1131. EDITOR_DEF("android/jarsigner","");
  1132. EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/jarsigner",PROPERTY_HINT_GLOBAL_FILE,exe_ext));
  1133. EDITOR_DEF("android/debug_keystore","");
  1134. EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/debug_keystore",PROPERTY_HINT_GLOBAL_FILE,"keystore"));
  1135. EDITOR_DEF("android/debug_keystore_user","androiddebugkey");
  1136. EDITOR_DEF("android/debug_keystore_pass","android");
  1137. //EDITOR_DEF("android/release_keystore","");
  1138. //EDITOR_DEF("android/release_username","");
  1139. //EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/release_keystore",PROPERTY_HINT_GLOBAL_FILE,"*.keystore"));
  1140. Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>( memnew(EditorExportPlatformAndroid) );
  1141. EditorImportExport::get_singleton()->add_export_platform(exporter);
  1142. }