export.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636
  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. String cmdline;
  177. bool _signed;
  178. bool apk_expansion;
  179. bool remove_prev;
  180. String apk_expansion_salt;
  181. String apk_expansion_pkey;
  182. int orientation;
  183. String release_keystore;
  184. String release_password;
  185. String release_username;
  186. struct APKExportData {
  187. zipFile apk;
  188. EditorProgress *ep;
  189. };
  190. struct Device {
  191. String id;
  192. String name;
  193. String description;
  194. };
  195. Vector<Device> devices;
  196. bool devices_changed;
  197. Mutex *device_lock;
  198. Thread *device_thread;
  199. Ref<ImageTexture> logo;
  200. Set<String> perms;
  201. String user_perms[MAX_USER_PERMISSIONS];
  202. bool screen_support[SCREEN_MAX];
  203. volatile bool quit_request;
  204. static void _device_poll_thread(void *ud);
  205. String get_project_name() const;
  206. void _fix_manifest(Vector<uint8_t>& p_manifest);
  207. void _fix_resources(Vector<uint8_t>& p_manifest);
  208. static Error save_apk_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
  209. protected:
  210. bool _set(const StringName& p_name, const Variant& p_value);
  211. bool _get(const StringName& p_name,Variant &r_ret) const;
  212. void _get_property_list( List<PropertyInfo> *p_list) const;
  213. public:
  214. virtual String get_name() const { return "Android"; }
  215. virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_ETC1; }
  216. virtual Ref<Texture> get_logo() const { return logo; }
  217. virtual bool poll_devices();
  218. virtual int get_device_count() const;
  219. virtual String get_device_name(int p_device) const;
  220. virtual String get_device_info(int p_device) const;
  221. virtual Error run(int p_device,bool p_dumb=false);
  222. virtual bool requieres_password(bool p_debug) const { return !p_debug; }
  223. virtual String get_binary_extension() const { return "apk"; }
  224. virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
  225. virtual bool can_export(String *r_error=NULL) const;
  226. EditorExportPlatformAndroid();
  227. ~EditorExportPlatformAndroid();
  228. };
  229. bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& p_value) {
  230. String n=p_name;
  231. if (n=="one_click_deploy/clear_previous_install")
  232. remove_prev=p_value;
  233. else if (n=="custom_package/debug")
  234. custom_debug_package=p_value;
  235. else if (n=="custom_package/release")
  236. custom_release_package=p_value;
  237. else if (n=="version/code")
  238. version_code=p_value;
  239. else if (n=="version/name")
  240. version_name=p_value;
  241. else if (n=="command_line/extra_args")
  242. cmdline=p_value;
  243. else if (n=="package/unique_name")
  244. package=p_value;
  245. else if (n=="package/name")
  246. name=p_value;
  247. else if (n=="package/icon")
  248. icon=p_value;
  249. else if (n=="package/signed")
  250. _signed=p_value;
  251. else if (n=="screen/orientation")
  252. orientation=p_value;
  253. else if (n=="screen/support_small")
  254. screen_support[SCREEN_SMALL]=p_value;
  255. else if (n=="screen/support_normal")
  256. screen_support[SCREEN_NORMAL]=p_value;
  257. else if (n=="screen/support_large")
  258. screen_support[SCREEN_LARGE]=p_value;
  259. else if (n=="screen/support_xlarge")
  260. screen_support[SCREEN_XLARGE]=p_value;
  261. else if (n=="keystore/release")
  262. release_keystore=p_value;
  263. else if (n=="keystore/release_user")
  264. release_username=p_value;
  265. else if (n=="keystore/release_password")
  266. release_password=p_value;
  267. else if (n=="apk_expansion/enable")
  268. apk_expansion=p_value;
  269. else if (n=="apk_expansion/SALT")
  270. apk_expansion_salt=p_value;
  271. else if (n=="apk_expansion/public_key")
  272. apk_expansion_pkey=p_value;
  273. else if (n.begins_with("permissions/")) {
  274. String what = n.get_slice("/",1).to_upper();
  275. bool state = p_value;
  276. if (state)
  277. perms.insert(what);
  278. else
  279. perms.erase(what);
  280. } else if (n.begins_with("user_permissions/")) {
  281. int which = n.get_slice("/",1).to_int();
  282. ERR_FAIL_INDEX_V(which,MAX_USER_PERMISSIONS,false);
  283. user_perms[which]=p_value;
  284. } else
  285. return false;
  286. return true;
  287. }
  288. bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) const{
  289. String n=p_name;
  290. if (n=="one_click_deploy/clear_previous_install")
  291. r_ret=remove_prev;
  292. else if (n=="custom_package/debug")
  293. r_ret=custom_debug_package;
  294. else if (n=="custom_package/release")
  295. r_ret=custom_release_package;
  296. else if (n=="version/code")
  297. r_ret=version_code;
  298. else if (n=="version/name")
  299. r_ret=version_name;
  300. else if (n=="command_line/extra_args")
  301. r_ret=cmdline;
  302. else if (n=="package/unique_name")
  303. r_ret=package;
  304. else if (n=="package/name")
  305. r_ret=name;
  306. else if (n=="package/icon")
  307. r_ret=icon;
  308. else if (n=="package/signed")
  309. r_ret=_signed;
  310. else if (n=="screen/orientation")
  311. r_ret=orientation;
  312. else if (n=="screen/support_small")
  313. r_ret=screen_support[SCREEN_SMALL];
  314. else if (n=="screen/support_normal")
  315. r_ret=screen_support[SCREEN_NORMAL];
  316. else if (n=="screen/support_large")
  317. r_ret=screen_support[SCREEN_LARGE];
  318. else if (n=="screen/support_xlarge")
  319. r_ret=screen_support[SCREEN_XLARGE];
  320. else if (n=="keystore/release")
  321. r_ret=release_keystore;
  322. else if (n=="keystore/release_user")
  323. r_ret=release_username;
  324. else if (n=="keystore/release_password")
  325. r_ret=release_password;
  326. else if (n=="apk_expansion/enable")
  327. r_ret=apk_expansion;
  328. else if (n=="apk_expansion/SALT")
  329. r_ret=apk_expansion_salt;
  330. else if (n=="apk_expansion/public_key")
  331. r_ret=apk_expansion_pkey;
  332. else if (n.begins_with("permissions/")) {
  333. String what = n.get_slice("/",1).to_upper();
  334. r_ret = perms.has(what);
  335. } else if (n.begins_with("user_permissions/")) {
  336. int which = n.get_slice("/",1).to_int();
  337. ERR_FAIL_INDEX_V(which,MAX_USER_PERMISSIONS,false);
  338. r_ret=user_perms[which];
  339. } else
  340. return false;
  341. return true;
  342. }
  343. void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list) const{
  344. p_list->push_back( PropertyInfo( Variant::BOOL, "one_click_deploy/clear_previous_install"));
  345. p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE,"apk"));
  346. p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE,"apk"));
  347. p_list->push_back( PropertyInfo( Variant::STRING, "command_line/extra_args"));
  348. p_list->push_back( PropertyInfo( Variant::INT, "version/code", PROPERTY_HINT_RANGE,"1,65535,1"));
  349. p_list->push_back( PropertyInfo( Variant::STRING, "version/name") );
  350. p_list->push_back( PropertyInfo( Variant::STRING, "package/unique_name") );
  351. p_list->push_back( PropertyInfo( Variant::STRING, "package/name") );
  352. p_list->push_back( PropertyInfo( Variant::STRING, "package/icon",PROPERTY_HINT_FILE,"png") );
  353. p_list->push_back( PropertyInfo( Variant::BOOL, "package/signed") );
  354. p_list->push_back( PropertyInfo( Variant::INT, "screen/orientation",PROPERTY_HINT_ENUM,"Landscape,Portrait") );
  355. p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_small") );
  356. p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_normal") );
  357. p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_large") );
  358. p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_xlarge") );
  359. p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release",PROPERTY_HINT_GLOBAL_FILE,"keystore") );
  360. p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_user" ) );
  361. p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_password" ) );
  362. p_list->push_back( PropertyInfo( Variant::BOOL, "apk_expansion/enable" ) );
  363. p_list->push_back( PropertyInfo( Variant::STRING, "apk_expansion/SALT" ) );
  364. p_list->push_back( PropertyInfo( Variant::STRING, "apk_expansion/public_key",PROPERTY_HINT_MULTILINE_TEXT ) );
  365. const char **perms = android_perms;
  366. while(*perms) {
  367. p_list->push_back( PropertyInfo( Variant::BOOL, "permissions/"+String(*perms).to_lower()));
  368. perms++;
  369. }
  370. for(int i=0;i<MAX_USER_PERMISSIONS;i++) {
  371. p_list->push_back( PropertyInfo( Variant::STRING, "user_permissions/"+itos(i)));
  372. }
  373. //p_list->push_back( PropertyInfo( Variant::INT, "resources/pack_mode", PROPERTY_HINT_ENUM,"Copy,Single Exec.,Pack (.pck),Bundles (Optical)"));
  374. }
  375. static String _parse_string(const uint8_t *p_bytes,bool p_utf8) {
  376. uint32_t offset=0;
  377. uint32_t len = decode_uint16(&p_bytes[offset]);
  378. if (p_utf8) {
  379. //don't know how to read extended utf8, this will have to be for now
  380. len>>=8;
  381. }
  382. offset+=2;
  383. //printf("len %i, unicode: %i\n",len,int(p_utf8));
  384. if (p_utf8) {
  385. Vector<uint8_t> str8;
  386. str8.resize(len+1);
  387. for(int i=0;i<len;i++) {
  388. str8[i]=p_bytes[offset+i];
  389. }
  390. str8[len]=0;
  391. String str;
  392. str.parse_utf8((const char*)str8.ptr());
  393. return str;
  394. } else {
  395. String str;
  396. for(int i=0;i<len;i++) {
  397. CharType c = decode_uint16(&p_bytes[offset+i*2]);
  398. if (c==0)
  399. break;
  400. str += String::chr(c);
  401. }
  402. return str;
  403. }
  404. }
  405. void EditorExportPlatformAndroid::_fix_resources(Vector<uint8_t>& p_manifest) {
  406. const int UTF8_FLAG = 0x00000100;
  407. print_line("*******************GORRRGLE***********************");
  408. uint32_t header = decode_uint32(&p_manifest[0]);
  409. uint32_t filesize = decode_uint32(&p_manifest[4]);
  410. uint32_t string_block_len = decode_uint32(&p_manifest[16]);
  411. uint32_t string_count = decode_uint32(&p_manifest[20]);
  412. uint32_t string_flags = decode_uint32(&p_manifest[28]);
  413. const uint32_t string_table_begins = 40;
  414. Vector<String> string_table;
  415. printf("stirng block len: %i\n",string_block_len);
  416. printf("stirng count: %i\n",string_count);
  417. printf("flags: %x\n",string_flags);
  418. for(int i=0;i<string_count;i++) {
  419. uint32_t offset = decode_uint32(&p_manifest[string_table_begins+i*4]);
  420. offset+=string_table_begins+string_count*4;
  421. String str = _parse_string(&p_manifest[offset],string_flags&UTF8_FLAG);
  422. if (str.begins_with("godot-project-name")) {
  423. if (str=="godot-project-name") {
  424. //project name
  425. str = get_project_name();
  426. } else {
  427. String lang = str.substr(str.find_last("-")+1,str.length()).replace("-","_");
  428. String prop = "application/name_"+lang;
  429. if (Globals::get_singleton()->has(prop)) {
  430. str = Globals::get_singleton()->get(prop);
  431. } else {
  432. str = get_project_name();
  433. }
  434. }
  435. }
  436. string_table.push_back(str);
  437. }
  438. //write a new string table, but use 16 bits
  439. Vector<uint8_t> ret;
  440. ret.resize(string_table_begins+string_table.size()*4);
  441. for(int i=0;i<string_table_begins;i++) {
  442. ret[i]=p_manifest[i];
  443. }
  444. int ofs=0;
  445. for(int i=0;i<string_table.size();i++) {
  446. encode_uint32(ofs,&ret[string_table_begins+i*4]);
  447. ofs+=string_table[i].length()*2+2+2;
  448. }
  449. ret.resize(ret.size()+ofs);
  450. uint8_t *chars=&ret[ret.size()-ofs];
  451. for(int i=0;i<string_table.size();i++) {
  452. String s = string_table[i];
  453. encode_uint16(s.length(),chars);
  454. chars+=2;
  455. for(int j=0;j<s.length();j++) {
  456. encode_uint16(s[j],chars);
  457. chars+=2;
  458. }
  459. encode_uint16(0,chars);
  460. chars+=2;
  461. }
  462. //pad
  463. while(ret.size()%4)
  464. ret.push_back(0);
  465. //change flags to not use utf8
  466. encode_uint32(string_flags&~0x100,&ret[28]);
  467. //change length
  468. encode_uint32(ret.size()-12,&ret[16]);
  469. //append the rest...
  470. int rest_from = 12+string_block_len;
  471. int rest_to = ret.size();
  472. int rest_len = (p_manifest.size() - rest_from);
  473. ret.resize(ret.size() + (p_manifest.size() - rest_from) );
  474. for(int i=0;i<rest_len;i++) {
  475. ret[rest_to+i]=p_manifest[rest_from+i];
  476. }
  477. //finally update the size
  478. encode_uint32(ret.size(),&ret[4]);
  479. p_manifest=ret;
  480. printf("end\n");
  481. }
  482. String EditorExportPlatformAndroid::get_project_name() const {
  483. String aname;
  484. if (this->name!="") {
  485. aname=this->name;
  486. } else {
  487. aname = Globals::get_singleton()->get("application/name");
  488. }
  489. if (aname=="") {
  490. aname=_MKSTR(VERSION_NAME);
  491. }
  492. return aname;
  493. }
  494. void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest) {
  495. const int CHUNK_AXML_FILE = 0x00080003;
  496. const int CHUNK_RESOURCEIDS = 0x00080180;
  497. const int CHUNK_STRINGS = 0x001C0001;
  498. const int CHUNK_XML_END_NAMESPACE = 0x00100101;
  499. const int CHUNK_XML_END_TAG = 0x00100103;
  500. const int CHUNK_XML_START_NAMESPACE = 0x00100100;
  501. const int CHUNK_XML_START_TAG = 0x00100102;
  502. const int CHUNK_XML_TEXT = 0x00100104;
  503. const int UTF8_FLAG = 0x00000100;
  504. Vector<String> string_table;
  505. uint32_t ofs=0;
  506. uint32_t header = decode_uint32(&p_manifest[ofs]);
  507. uint32_t filesize = decode_uint32(&p_manifest[ofs+4]);
  508. ofs+=8;
  509. // print_line("FILESIZE: "+itos(filesize)+" ACTUAL: "+itos(p_manifest.size()));
  510. uint32_t string_count;
  511. uint32_t styles_count;
  512. uint32_t string_flags;
  513. uint32_t string_data_offset;
  514. uint32_t styles_offset;
  515. uint32_t string_table_begins;
  516. uint32_t string_table_ends;
  517. Vector<uint8_t> stable_extra;
  518. while(ofs < p_manifest.size()) {
  519. uint32_t chunk = decode_uint32(&p_manifest[ofs]);
  520. uint32_t size = decode_uint32(&p_manifest[ofs+4]);
  521. switch(chunk) {
  522. case CHUNK_STRINGS: {
  523. int iofs=ofs+8;
  524. uint32_t string_count=decode_uint32(&p_manifest[iofs]);
  525. uint32_t styles_count=decode_uint32(&p_manifest[iofs+4]);
  526. uint32_t string_flags=decode_uint32(&p_manifest[iofs+8]);
  527. uint32_t string_data_offset=decode_uint32(&p_manifest[iofs+12]);
  528. uint32_t styles_offset=decode_uint32(&p_manifest[iofs+16]);
  529. /*
  530. printf("string count: %i\n",string_count);
  531. printf("flags: %i\n",string_flags);
  532. printf("sdata ofs: %i\n",string_data_offset);
  533. printf("styles ofs: %i\n",styles_offset);
  534. */
  535. uint32_t st_offset=iofs+20;
  536. string_table.resize(string_count);
  537. uint32_t string_end=0;
  538. string_table_begins=st_offset;
  539. for(int i=0;i<string_count;i++) {
  540. uint32_t string_at = decode_uint32(&p_manifest[st_offset+i*4]);
  541. string_at+=st_offset+string_count*4;
  542. ERR_EXPLAIN("Unimplemented, can't read utf8 string table.");
  543. ERR_FAIL_COND(string_flags&UTF8_FLAG);
  544. if (string_flags&UTF8_FLAG) {
  545. } else {
  546. uint32_t len = decode_uint16(&p_manifest[string_at]);
  547. Vector<CharType> ucstring;
  548. ucstring.resize(len+1);
  549. for(int j=0;j<len;j++) {
  550. uint16_t c=decode_uint16(&p_manifest[string_at+2+2*j]);
  551. ucstring[j]=c;
  552. }
  553. string_end=MAX(string_at+2+2*len,string_end);
  554. ucstring[len]=0;
  555. string_table[i]=ucstring.ptr();
  556. }
  557. // print_line("String "+itos(i)+": "+string_table[i]);
  558. }
  559. for(int i=string_end;i<(ofs+size);i++) {
  560. stable_extra.push_back(p_manifest[i]);
  561. }
  562. // printf("stable extra: %i\n",int(stable_extra.size()));
  563. string_table_ends=ofs+size;
  564. // print_line("STABLE SIZE: "+itos(size)+" ACTUAL: "+itos(string_table_ends));
  565. } break;
  566. case CHUNK_XML_START_TAG: {
  567. int iofs=ofs+8;
  568. uint32_t line=decode_uint32(&p_manifest[iofs]);
  569. uint32_t nspace=decode_uint32(&p_manifest[iofs+8]);
  570. uint32_t name=decode_uint32(&p_manifest[iofs+12]);
  571. uint32_t check=decode_uint32(&p_manifest[iofs+16]);
  572. String tname=string_table[name];
  573. // printf("NSPACE: %i\n",nspace);
  574. //printf("NAME: %i (%s)\n",name,tname.utf8().get_data());
  575. //printf("CHECK: %x\n",check);
  576. uint32_t attrcount=decode_uint32(&p_manifest[iofs+20]);
  577. iofs+=28;
  578. //printf("ATTRCOUNT: %x\n",attrcount);
  579. for(int i=0;i<attrcount;i++) {
  580. uint32_t attr_nspace=decode_uint32(&p_manifest[iofs]);
  581. uint32_t attr_name=decode_uint32(&p_manifest[iofs+4]);
  582. uint32_t attr_value=decode_uint32(&p_manifest[iofs+8]);
  583. uint32_t attr_flags=decode_uint32(&p_manifest[iofs+12]);
  584. uint32_t attr_resid=decode_uint32(&p_manifest[iofs+16]);
  585. String value;
  586. if (attr_value!=0xFFFFFFFF)
  587. value=string_table[attr_value];
  588. else
  589. value="Res #"+itos(attr_resid);
  590. String attrname = string_table[attr_name];
  591. String nspace;
  592. if (attr_nspace!=0xFFFFFFFF)
  593. nspace=string_table[attr_nspace];
  594. else
  595. nspace="";
  596. printf("ATTR %i NSPACE: %i\n",i,attr_nspace);
  597. printf("ATTR %i NAME: %i (%s)\n",i,attr_name,attrname.utf8().get_data());
  598. printf("ATTR %i VALUE: %i (%s)\n",i,attr_value,value.utf8().get_data());
  599. printf("ATTR %i FLAGS: %x\n",i,attr_flags);
  600. printf("ATTR %i RESID: %x\n",i,attr_resid);
  601. //replace project information
  602. if (tname=="manifest" && attrname=="package") {
  603. print_line("FOUND PACKAGE");
  604. string_table[attr_value]=package;
  605. }
  606. //print_line("tname: "+tname);
  607. //print_line("nspace: "+nspace);
  608. //print_line("attrname: "+attrname);
  609. if (tname=="manifest" && /*nspace=="android" &&*/ attrname=="versionCode") {
  610. print_line("FOUND versioncode");
  611. encode_uint32(version_code,&p_manifest[iofs+16]);
  612. }
  613. if (tname=="manifest" && /*nspace=="android" &&*/ attrname=="versionName") {
  614. print_line("FOUND versionname");
  615. if (attr_value==0xFFFFFFFF) {
  616. WARN_PRINT("Version name in a resource, should be plaintext")
  617. } else
  618. string_table[attr_value]=version_name;
  619. }
  620. if (tname=="activity" && /*nspace=="android" &&*/ attrname=="screenOrientation") {
  621. print_line("FOUND screen orientation");
  622. if (attr_value==0xFFFFFFFF) {
  623. WARN_PRINT("Version name in a resource, should be plaintext")
  624. } else {
  625. string_table[attr_value]=(orientation==0?"landscape":"portrait");
  626. }
  627. }
  628. if (tname=="application" && /*nspace=="android" &&*/ attrname=="label") {
  629. print_line("FOUND application");
  630. if (attr_value==0xFFFFFFFF) {
  631. WARN_PRINT("Application name in a resource, should be plaintext.")
  632. } else {
  633. String aname = get_project_name();
  634. string_table[attr_value]=aname;
  635. }
  636. }
  637. if (tname=="activity" && /*nspace=="android" &&*/ attrname=="label") {
  638. print_line("FOUND activity name");
  639. if (attr_value==0xFFFFFFFF) {
  640. WARN_PRINT("Activity name in a resource, should be plaintext")
  641. } else {
  642. String aname;
  643. if (this->name!="") {
  644. aname=this->name;
  645. } else {
  646. aname = Globals::get_singleton()->get("application/name");
  647. }
  648. if (aname=="") {
  649. aname=_MKSTR(VERSION_NAME);
  650. }
  651. print_line("APP NAME IS..."+aname);
  652. string_table[attr_value]=aname;
  653. }
  654. }
  655. if (tname=="uses-permission" && /*nspace=="android" &&*/ attrname=="name") {
  656. if (value.begins_with("godot.custom")) {
  657. int which = value.get_slice(".",2).to_int();
  658. if (which>=0 && which<MAX_USER_PERMISSIONS && user_perms[which].strip_edges()!="") {
  659. string_table[attr_value]=user_perms[which].strip_edges();
  660. }
  661. } else if (value.begins_with("godot.")) {
  662. String perm = value.get_slice(".",1);
  663. if (perms.has(perm)) {
  664. string_table[attr_value]="android.permission."+perm;
  665. }
  666. }
  667. }
  668. if (tname=="supports-screens" ) {
  669. if (attr_value==0xFFFFFFFF) {
  670. WARN_PRINT("Screen res name in a resource, should be plaintext")
  671. } else if (attrname=="smallScreens") {
  672. print_line("SMALLSCREEN");
  673. string_table[attr_value]=screen_support[SCREEN_SMALL]?"true":"false";
  674. } else if (attrname=="mediumScreens") {
  675. print_line("MEDSCREEN");
  676. string_table[attr_value]=screen_support[SCREEN_NORMAL]?"true":"false";
  677. } else if (attrname=="largeScreens") {
  678. print_line("LARGECREEN");
  679. string_table[attr_value]=screen_support[SCREEN_LARGE]?"true":"false";
  680. } else if (attrname=="xlargeScreens") {
  681. print_line("XLARGECREEN");
  682. string_table[attr_value]=screen_support[SCREEN_XLARGE]?"true":"false";
  683. }
  684. }
  685. iofs+=20;
  686. }
  687. } break;
  688. }
  689. printf("chunk %x: size: %d\n",chunk,size);
  690. ofs+=size;
  691. }
  692. printf("end\n");
  693. //create new andriodmanifest binary
  694. Vector<uint8_t> ret;
  695. ret.resize(string_table_begins+string_table.size()*4);
  696. for(int i=0;i<string_table_begins;i++) {
  697. ret[i]=p_manifest[i];
  698. }
  699. ofs=0;
  700. for(int i=0;i<string_table.size();i++) {
  701. encode_uint32(ofs,&ret[string_table_begins+i*4]);
  702. ofs+=string_table[i].length()*2+2+2;
  703. print_line("ofs: "+itos(i)+": "+itos(ofs));
  704. }
  705. ret.resize(ret.size()+ofs);
  706. uint8_t *chars=&ret[ret.size()-ofs];
  707. for(int i=0;i<string_table.size();i++) {
  708. String s = string_table[i];
  709. print_line("savint string :"+s);
  710. encode_uint16(s.length(),chars);
  711. chars+=2;
  712. for(int j=0;j<s.length();j++) { //include zero?
  713. encode_uint16(s[j],chars);
  714. chars+=2;
  715. }
  716. encode_uint16(0,chars);
  717. chars+=2;
  718. }
  719. ret.resize(ret.size()+stable_extra.size());
  720. while(ret.size()%4)
  721. ret.push_back(0);
  722. for(int i=0;i<stable_extra.size();i++) {
  723. chars[i]=stable_extra[i];
  724. }
  725. uint32_t new_stable_end=ret.size();
  726. uint32_t extra = (p_manifest.size()-string_table_ends);
  727. ret.resize(new_stable_end + extra);
  728. for(int i=0;i<extra;i++)
  729. ret[new_stable_end+i]=p_manifest[string_table_ends+i];
  730. while(ret.size()%4)
  731. ret.push_back(0);
  732. encode_uint32(ret.size(),&ret[4]); //update new file size
  733. encode_uint32(new_stable_end-8,&ret[12]); //update new string table size
  734. print_line("file size: "+itos(ret.size()));
  735. p_manifest=ret;
  736. #if 0
  737. uint32_t header[9];
  738. for(int i=0;i<9;i++) {
  739. header[i]=decode_uint32(&p_manifest[i*4]);
  740. }
  741. print_line("STO: "+itos(header[3]));
  742. uint32_t st_offset=9*4;
  743. //ERR_FAIL_COND(header[3]!=0x24)
  744. uint32_t string_count=header[4];
  745. string_table.resize(string_count);
  746. for(int i=0;i<string_count;i++) {
  747. uint32_t string_at = decode_uint32(&p_manifest[st_offset+i*4]);
  748. string_at+=st_offset+string_count*4;
  749. uint32_t len = decode_uint16(&p_manifest[string_at]);
  750. Vector<CharType> ucstring;
  751. ucstring.resize(len+1);
  752. for(int j=0;j<len;j++) {
  753. uint16_t c=decode_uint16(&p_manifest[string_at+2+2*j]);
  754. ucstring[j]=c;
  755. }
  756. ucstring[len]=0;
  757. string_table[i]=ucstring.ptr();
  758. }
  759. #endif
  760. }
  761. Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
  762. APKExportData *ed=(APKExportData*)p_userdata;
  763. String dst_path=p_path;
  764. dst_path=dst_path.replace_first("res://","assets/");
  765. zipOpenNewFileInZip(ed->apk,
  766. dst_path.utf8().get_data(),
  767. NULL,
  768. NULL,
  769. 0,
  770. NULL,
  771. 0,
  772. NULL,
  773. Z_DEFLATED,
  774. Z_DEFAULT_COMPRESSION);
  775. zipWriteInFileInZip(ed->apk,p_data.ptr(),p_data.size());
  776. zipCloseFileInZip(ed->apk);
  777. ed->ep->step("File: "+p_path,3+p_file*100/p_total);
  778. return OK;
  779. }
  780. Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_debug, bool p_dumb) {
  781. String src_apk;
  782. EditorProgress ep("export","Exporting for Android",104);
  783. String apk_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
  784. if (p_debug) {
  785. src_apk=custom_debug_package!=""?custom_debug_package:apk_path+"android_debug.apk";
  786. } else {
  787. src_apk=custom_release_package!=""?custom_release_package:apk_path+"android_release.apk";
  788. }
  789. FileAccess *src_f=NULL;
  790. zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
  791. ep.step("Creating APK",0);
  792. unzFile pkg = unzOpen2(src_apk.utf8().get_data(), &io);
  793. if (!pkg) {
  794. EditorNode::add_io_error("Could not find template APK to export:\n"+src_apk);
  795. return ERR_FILE_NOT_FOUND;
  796. }
  797. ERR_FAIL_COND_V(!pkg, ERR_CANT_OPEN);
  798. int ret = unzGoToFirstFile(pkg);
  799. zlib_filefunc_def io2=io;
  800. FileAccess *dst_f=NULL;
  801. io2.opaque=&dst_f;
  802. zipFile apk=zipOpen2(p_path.utf8().get_data(),APPEND_STATUS_CREATE,NULL,&io2);
  803. while(ret==UNZ_OK) {
  804. //get filename
  805. unz_file_info info;
  806. char fname[16384];
  807. ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
  808. String file=fname;
  809. Vector<uint8_t> data;
  810. data.resize(info.uncompressed_size);
  811. //read
  812. unzOpenCurrentFile(pkg);
  813. unzReadCurrentFile(pkg,data.ptr(),data.size());
  814. unzCloseCurrentFile(pkg);
  815. //write
  816. if (file=="AndroidManifest.xml") {
  817. _fix_manifest(data);
  818. }
  819. if (file=="resources.arsc") {
  820. _fix_resources(data);
  821. }
  822. if (file=="res/drawable/icon.png") {
  823. bool found=false;
  824. if (this->icon!="" && this->icon.ends_with(".png")) {
  825. FileAccess *f = FileAccess::open(this->icon,FileAccess::READ);
  826. if (f) {
  827. data.resize(f->get_len());
  828. f->get_buffer(data.ptr(),data.size());
  829. memdelete(f);
  830. found=true;
  831. }
  832. }
  833. if (!found) {
  834. String appicon = Globals::get_singleton()->get("application/icon");
  835. if (appicon!="" && appicon.ends_with(".png")) {
  836. FileAccess*f = FileAccess::open(appicon,FileAccess::READ);
  837. if (f) {
  838. data.resize(f->get_len());
  839. f->get_buffer(data.ptr(),data.size());
  840. memdelete(f);
  841. }
  842. }
  843. }
  844. }
  845. print_line("ADDING: "+file);
  846. zipOpenNewFileInZip(apk,
  847. file.utf8().get_data(),
  848. NULL,
  849. NULL,
  850. 0,
  851. NULL,
  852. 0,
  853. NULL,
  854. Z_DEFLATED,
  855. Z_DEFAULT_COMPRESSION);
  856. zipWriteInFileInZip(apk,data.ptr(),data.size());
  857. zipCloseFileInZip(apk);
  858. ret = unzGoToNextFile(pkg);
  859. }
  860. ep.step("Adding Files..",1);
  861. Error err=OK;
  862. Vector<String> cl = cmdline.strip_edges().split(" ");
  863. for(int i=0;i<cl.size();i++) {
  864. if (cl[i].strip_edges().length()==0) {
  865. cl.remove(i);
  866. i--;
  867. }
  868. }
  869. if (p_dumb) {
  870. String host = EditorSettings::get_singleton()->get("file_server/host");
  871. int port = EditorSettings::get_singleton()->get("file_server/post");
  872. String passwd = EditorSettings::get_singleton()->get("file_server/password");
  873. cl.push_back("-rfs");
  874. cl.push_back(host+":"+itos(port));
  875. if (passwd!="") {
  876. cl.push_back("-rfs_pass");
  877. cl.push_back(passwd);
  878. }
  879. } else {
  880. //all files
  881. if (apk_expansion) {
  882. String apkfname="main."+itos(version_code)+"."+package+".obb";
  883. String fullpath=p_path.get_base_dir().plus_file(apkfname);
  884. FileAccess *pf = FileAccess::open(fullpath,FileAccess::WRITE);
  885. if (!pf) {
  886. EditorNode::add_io_error("Could not write expansion package file: "+apkfname);
  887. return OK;
  888. }
  889. err = save_pack(pf);
  890. memdelete(pf);
  891. cl.push_back("-use_apk_expansion");
  892. cl.push_back("-apk_expansion_md5");
  893. cl.push_back(FileAccess::get_md5(fullpath));
  894. cl.push_back("-apk_expansion_key");
  895. cl.push_back(apk_expansion_pkey.strip_edges());
  896. } else {
  897. APKExportData ed;
  898. ed.ep=&ep;
  899. ed.apk=apk;
  900. err = export_project_files(save_apk_file,&ed,false);
  901. }
  902. }
  903. if (cl.size()) {
  904. //add comandline
  905. Vector<uint8_t> clf;
  906. clf.resize(4);
  907. encode_uint32(cl.size(),&clf[0]);
  908. for(int i=0;i<cl.size();i++) {
  909. CharString txt = cl[i].utf8();
  910. int base = clf.size();
  911. clf.resize(base+4+txt.length());
  912. encode_uint32(txt.length(),&clf[base]);
  913. copymem(&clf[base+4],txt.ptr(),txt.length());
  914. print_line(itos(i)+" param: "+cl[i]);
  915. }
  916. zipOpenNewFileInZip(apk,
  917. "assets/_cl_",
  918. NULL,
  919. NULL,
  920. 0,
  921. NULL,
  922. 0,
  923. NULL,
  924. Z_DEFLATED,
  925. Z_DEFAULT_COMPRESSION);
  926. zipWriteInFileInZip(apk,clf.ptr(),clf.size());
  927. zipCloseFileInZip(apk);
  928. }
  929. zipClose(apk,NULL);
  930. unzClose(pkg);
  931. if (err) {
  932. return err;
  933. }
  934. if (_signed) {
  935. String jarsigner=EditorSettings::get_singleton()->get("android/jarsigner");
  936. if (!FileAccess::exists(jarsigner)) {
  937. EditorNode::add_io_error("'jarsigner' could not be found.\nPlease supply a path in the editor settings.\nResulting apk is unsigned.");
  938. return OK;
  939. }
  940. String keystore;
  941. String password;
  942. String user;
  943. if (p_debug) {
  944. keystore=EditorSettings::get_singleton()->get("android/debug_keystore");
  945. password=EditorSettings::get_singleton()->get("android/debug_keystore_pass");
  946. user=EditorSettings::get_singleton()->get("android/debug_keystore_user");
  947. ep.step("Signing Debug APK..",103);
  948. } else {
  949. keystore=release_keystore;
  950. password=release_password;
  951. user=release_username;
  952. ep.step("Signing Release APK..",103);
  953. }
  954. if (!FileAccess::exists(keystore)) {
  955. EditorNode::add_io_error("Could not find keytore, unable to export.");
  956. return ERR_FILE_CANT_OPEN;
  957. }
  958. List<String> args;
  959. args.push_back("-digestalg");
  960. args.push_back("SHA1");
  961. args.push_back("-sigalg");
  962. args.push_back("MD5withRSA");
  963. args.push_back("-verbose");
  964. args.push_back("-keystore");
  965. args.push_back(keystore);
  966. args.push_back("-storepass");
  967. args.push_back(password);
  968. args.push_back(p_path);
  969. args.push_back(user);
  970. int retval;
  971. int err = OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval);
  972. if (retval) {
  973. EditorNode::add_io_error("'jarsigner' returned with error #"+itos(retval));
  974. return ERR_CANT_CREATE;
  975. }
  976. ep.step("Verifying APK..",104);
  977. args.clear();
  978. args.push_back("-verify");
  979. args.push_back(p_path);
  980. args.push_back("-verbose");
  981. err = OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval);
  982. if (retval) {
  983. EditorNode::add_io_error("'jarsigner' verificaiton of APK failed. Make sure to use jarsigner from Java 6.");
  984. return ERR_CANT_CREATE;
  985. }
  986. }
  987. return OK;
  988. }
  989. bool EditorExportPlatformAndroid::poll_devices() {
  990. bool dc=devices_changed;
  991. devices_changed=false;
  992. return dc;
  993. }
  994. int EditorExportPlatformAndroid::get_device_count() const {
  995. device_lock->lock();
  996. int dc=devices.size();
  997. device_lock->unlock();
  998. return dc;
  999. }
  1000. String EditorExportPlatformAndroid::get_device_name(int p_device) const {
  1001. ERR_FAIL_INDEX_V(p_device,devices.size(),"");
  1002. device_lock->lock();
  1003. String s=devices[p_device].name;
  1004. device_lock->unlock();
  1005. return s;
  1006. }
  1007. String EditorExportPlatformAndroid::get_device_info(int p_device) const {
  1008. ERR_FAIL_INDEX_V(p_device,devices.size(),"");
  1009. device_lock->lock();
  1010. String s=devices[p_device].description;
  1011. device_lock->unlock();
  1012. return s;
  1013. }
  1014. void EditorExportPlatformAndroid::_device_poll_thread(void *ud) {
  1015. EditorExportPlatformAndroid *ea=(EditorExportPlatformAndroid *)ud;
  1016. while(!ea->quit_request) {
  1017. String adb=EditorSettings::get_singleton()->get("android/adb");
  1018. if (!FileAccess::exists(adb)) {
  1019. OS::get_singleton()->delay_usec(3000000);
  1020. continue; //adb not configured
  1021. }
  1022. String devices;
  1023. List<String> args;
  1024. args.push_back("devices");
  1025. int ec;
  1026. Error err = OS::get_singleton()->execute(adb,args,true,NULL,&devices,&ec);
  1027. Vector<String> ds = devices.split("\n");
  1028. Vector<String> ldevices;
  1029. for(int i=1;i<ds.size();i++) {
  1030. String d = ds[i];
  1031. int dpos = d.find("device");
  1032. if (dpos==-1)
  1033. continue;
  1034. d=d.substr(0,dpos).strip_edges();
  1035. // print_line("found devuce: "+d);
  1036. ldevices.push_back(d);
  1037. }
  1038. ea->device_lock->lock();
  1039. bool different=false;
  1040. if (devices.size()!=ldevices.size()) {
  1041. different=true;
  1042. } else {
  1043. for(int i=0;i<ea->devices.size();i++) {
  1044. if (ea->devices[i].id!=ldevices[i]) {
  1045. different=true;
  1046. break;
  1047. }
  1048. }
  1049. }
  1050. if (different) {
  1051. Vector<Device> ndevices;
  1052. for(int i=0;i<ldevices.size();i++) {
  1053. Device d;
  1054. d.id=ldevices[i];
  1055. for(int j=0;j<ea->devices.size();j++) {
  1056. if (ea->devices[j].id==ldevices[i]) {
  1057. d.description=ea->devices[j].description;
  1058. d.name=ea->devices[j].name;
  1059. }
  1060. }
  1061. if (d.description=="") {
  1062. //in the oven, request!
  1063. args.clear();
  1064. args.push_back("-s");
  1065. args.push_back(d.id);
  1066. args.push_back("shell");
  1067. args.push_back("cat");
  1068. args.push_back("/system/build.prop");
  1069. int ec;
  1070. String dp;
  1071. Error err = OS::get_singleton()->execute(adb,args,true,NULL,&dp,&ec);
  1072. print_line("RV: "+itos(ec));
  1073. Vector<String> props = dp.split("\n");
  1074. String vendor;
  1075. String device;
  1076. d.description+"Device ID: "+d.id+"\n";
  1077. for(int j=0;j<props.size();j++) {
  1078. String p = props[j];
  1079. if (p.begins_with("ro.product.model=")) {
  1080. device=p.get_slice("=",1).strip_edges();
  1081. } else if (p.begins_with("ro.product.brand=")) {
  1082. vendor=p.get_slice("=",1).strip_edges().capitalize();
  1083. } else if (p.begins_with("ro.build.display.id=")) {
  1084. d.description+="Build: "+p.get_slice("=",1).strip_edges()+"\n";
  1085. } else if (p.begins_with("ro.build.version.release=")) {
  1086. d.description+="Release: "+p.get_slice("=",1).strip_edges()+"\n";
  1087. } else if (p.begins_with("ro.product.cpu.abi=")) {
  1088. d.description+="CPU: "+p.get_slice("=",1).strip_edges()+"\n";
  1089. } else if (p.begins_with("ro.product.manufacturer=")) {
  1090. d.description+="Manufacturer: "+p.get_slice("=",1).strip_edges()+"\n";
  1091. } else if (p.begins_with("ro.board.platform=")) {
  1092. d.description+="Chipset: "+p.get_slice("=",1).strip_edges()+"\n";
  1093. } else if (p.begins_with("ro.opengles.version=")) {
  1094. uint32_t opengl = p.get_slice("=",1).to_int();
  1095. d.description+="OpenGL: "+itos(opengl>>16)+"."+itos((opengl>>8)&0xFF)+"."+itos((opengl)&0xFF)+"\n";
  1096. }
  1097. }
  1098. d.name=vendor+" "+device;
  1099. // print_line("name: "+d.name);
  1100. // print_line("description: "+d.description);
  1101. }
  1102. ndevices.push_back(d);
  1103. }
  1104. ea->devices=ndevices;
  1105. ea->devices_changed=true;
  1106. }
  1107. ea->device_lock->unlock();
  1108. OS::get_singleton()->delay_usec(3000000);
  1109. }
  1110. }
  1111. Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) {
  1112. ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
  1113. device_lock->lock();
  1114. EditorProgress ep("run","Running on "+devices[p_device].name,3);
  1115. String adb=EditorSettings::get_singleton()->get("android/adb");
  1116. if (adb=="") {
  1117. EditorNode::add_io_error("ADB executable not configured in settings, can't run.");
  1118. device_lock->unlock();
  1119. return ERR_UNCONFIGURED;
  1120. }
  1121. //export_temp
  1122. ep.step("Exporting APK",0);
  1123. String export_to=EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpexport.apk";
  1124. Error err = export_project(export_to,true,p_dumb);
  1125. if (err) {
  1126. device_lock->unlock();
  1127. return err;
  1128. }
  1129. List<String> args;
  1130. int rv;
  1131. if (remove_prev) {
  1132. ep.step("Uninstalling..",1);
  1133. print_line("Uninstalling previous version: "+devices[p_device].name);
  1134. args.push_back("-s");
  1135. args.push_back(devices[p_device].id);
  1136. args.push_back("uninstall");
  1137. args.push_back(package);
  1138. err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
  1139. #if 0
  1140. if (err || rv!=0) {
  1141. EditorNode::add_io_error("Could not install to device.");
  1142. device_lock->unlock();
  1143. return ERR_CANT_CREATE;
  1144. }
  1145. #endif
  1146. }
  1147. print_line("Installing into device (please wait..): "+devices[p_device].name);
  1148. ep.step("Installing to Device (please wait..)..",2);
  1149. args.clear();
  1150. args.push_back("-s");
  1151. args.push_back(devices[p_device].id);
  1152. args.push_back("install");
  1153. args.push_back(export_to);
  1154. err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
  1155. if (err || rv!=0) {
  1156. EditorNode::add_io_error("Could not install to device.");
  1157. device_lock->unlock();
  1158. return ERR_CANT_CREATE;
  1159. }
  1160. ep.step("Running on Device..",3);
  1161. args.clear();
  1162. args.push_back("-s");
  1163. args.push_back(devices[p_device].id);
  1164. args.push_back("shell");
  1165. args.push_back("am");
  1166. args.push_back("start");
  1167. args.push_back("-a");
  1168. args.push_back("android.intent.action.MAIN");
  1169. args.push_back("-n");
  1170. args.push_back(package+"/com.android.godot.Godot");
  1171. err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
  1172. if (err || rv!=0) {
  1173. EditorNode::add_io_error("Could not execute ondevice.");
  1174. device_lock->unlock();
  1175. return ERR_CANT_CREATE;
  1176. }
  1177. device_lock->unlock();
  1178. return OK;
  1179. }
  1180. EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
  1181. version_code=1;
  1182. version_name="1.0";
  1183. package="com.android.noname";
  1184. name="";
  1185. _signed=true;
  1186. apk_expansion=false;
  1187. device_lock = Mutex::create();
  1188. quit_request=false;
  1189. orientation=0;
  1190. remove_prev=false;
  1191. device_thread=Thread::create(_device_poll_thread,this);
  1192. devices_changed=true;
  1193. Image img( _android_logo );
  1194. logo = Ref<ImageTexture>( memnew( ImageTexture ));
  1195. logo->create_from_image(img);
  1196. for(int i=0;i<4;i++)
  1197. screen_support[i]=true;
  1198. }
  1199. bool EditorExportPlatformAndroid::can_export(String *r_error) const {
  1200. bool valid=true;
  1201. String adb=EditorSettings::get_singleton()->get("android/adb");
  1202. String err;
  1203. if (!FileAccess::exists(adb)) {
  1204. valid=false;
  1205. err+="ADB executable not configured in editor settings.\n";
  1206. }
  1207. String js = EditorSettings::get_singleton()->get("android/jarsigner");
  1208. if (!FileAccess::exists(js)) {
  1209. valid=false;
  1210. err+="OpenJDK 6 jarsigner not configured in editor settings.\n";
  1211. }
  1212. String dk = EditorSettings::get_singleton()->get("android/debug_keystore");
  1213. if (!FileAccess::exists(dk)) {
  1214. valid=false;
  1215. err+="Debug Keystore not configured in editor settings.\n";
  1216. }
  1217. String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
  1218. if (!FileAccess::exists(exe_path+"android_debug.apk") || !FileAccess::exists(exe_path+"android_release.apk")) {
  1219. valid=false;
  1220. err+="No export templates found.\nDownload and install export templates.\n";
  1221. }
  1222. if (custom_debug_package!="" && !FileAccess::exists(custom_debug_package)) {
  1223. valid=false;
  1224. err+="Custom debug package not found.\n";
  1225. }
  1226. if (custom_release_package!="" && !FileAccess::exists(custom_release_package)) {
  1227. valid=false;
  1228. err+="Custom release package not found.\n";
  1229. }
  1230. if (apk_expansion) {
  1231. //if (apk_expansion_salt=="") {
  1232. // valid=false;
  1233. // err+="Invalid SALT for apk expansion.\n";
  1234. //}
  1235. if (apk_expansion_pkey=="") {
  1236. valid=false;
  1237. err+="Invalid public key for apk expansion.\n";
  1238. }
  1239. }
  1240. if (r_error)
  1241. *r_error=err;
  1242. return valid;
  1243. }
  1244. EditorExportPlatformAndroid::~EditorExportPlatformAndroid() {
  1245. quit_request=true;
  1246. Thread::wait_to_finish(device_thread);
  1247. }
  1248. void register_android_exporter() {
  1249. String exe_ext=OS::get_singleton()->get_name()=="Windows"?"exe":"";
  1250. EDITOR_DEF("android/adb","");
  1251. EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/adb",PROPERTY_HINT_GLOBAL_FILE,exe_ext));
  1252. EDITOR_DEF("android/jarsigner","");
  1253. EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/jarsigner",PROPERTY_HINT_GLOBAL_FILE,exe_ext));
  1254. EDITOR_DEF("android/debug_keystore","");
  1255. EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/debug_keystore",PROPERTY_HINT_GLOBAL_FILE,"keystore"));
  1256. EDITOR_DEF("android/debug_keystore_user","androiddebugkey");
  1257. EDITOR_DEF("android/debug_keystore_pass","android");
  1258. //EDITOR_DEF("android/release_keystore","");
  1259. //EDITOR_DEF("android/release_username","");
  1260. //EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/release_keystore",PROPERTY_HINT_GLOBAL_FILE,"*.keystore"));
  1261. Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>( memnew(EditorExportPlatformAndroid) );
  1262. EditorImportExport::get_singleton()->add_export_platform(exporter);
  1263. }