Upstream version 10.39.233.0
[platform/framework/web/crosswalk.git] / src / xwalk / app / tools / android / customize.py
index 40fb647..eb2d7b6 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-# Copyright (c) 2013 Intel Corporation. All rights reserved.
+# Copyright (c) 2013,2014 Intel Corporation. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -14,33 +14,39 @@ import shutil
 import stat
 import sys
 
+# get xwalk absolute path so we can run this script from any location
+xwalk_dir = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(xwalk_dir)
+
+from app_info import AppInfo
 from customize_launch_screen import CustomizeLaunchScreen
 from handle_xml import AddElementAttribute
 from handle_xml import AddElementAttributeAndText
 from handle_xml import EditElementAttribute
 from handle_xml import EditElementValueByNodeName
 from handle_permissions import HandlePermissions
+from util import CleanDir, CreateAndCopyDir, GetBuildDir
 from xml.dom import minidom
 
 
-def VerifyAppName(value, mode='default'):
-  descrpt = 'The app'
-  sample = 'helloworld, hello world, hello_world, hello_world1'
-  regex = r'[a-zA-Z][\w ]*$'
+TEMPLATE_DIR_NAME = 'template'
+
+
+def VerifyPackageName(value):
+  regex = r'^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$'
+  descrpt = 'Each part of package'
+  sample = 'org.xwalk.example, org.xwalk.example_'
 
   if len(value) >= 128:
     print('To be safe, the length of package name or app name '
           'should be less than 128.')
     sys.exit(6)
-  if mode == 'packagename':
-    regex = r'^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$'
-    descrpt = 'Each part of package'
-    sample = 'org.xwalk.example, org.xwalk.example_'
 
   if not re.match(regex, value):
     print('Error: %s name should be started with letters and should not '
           'contain invalid characters.\n'
-          'It may contain letters, numbers, blank spaces and underscores\n'
+          'It may contain lowercase letters, numbers, blank spaces and '
+          'underscores\n'
           'Sample: %s' % (descrpt, sample))
     sys.exit(6)
 
@@ -61,7 +67,7 @@ def ReplaceInvalidChars(value, mode='default'):
     invalid_chars = '\/:.*?"<>|- '
   for c in invalid_chars:
     if mode == 'apkname' and c in value:
-      print("Illegal character: '%s' is replaced with '_'" % c)
+      print('Illegal character: "%s" replaced with "_"' % c)
     value = value.replace(c, '_')
   return value
 
@@ -108,40 +114,74 @@ def CompressSourceFiles(app_root, compressor):
     compress_js_and_css.CompressCss(css_list)
 
 
-def Prepare(name, package, app_root, compressor):
-  if os.path.exists(name):
-    shutil.rmtree(name)
-  shutil.copytree('app_src', name)
-  shutil.rmtree(os.path.join(name, 'src'))
-  src_root = os.path.join('app_src', 'src', 'org', 'xwalk', 'app', 'template')
-  src_activity = os.path.join(src_root, 'AppTemplateActivity.java')
-  if not os.path.isfile(src_activity):
-    print ('Please make sure that the java file'
-           ' of activity does exist.')
+def Prepare(app_info, compressor):
+  """Copy the Android template project to a new app project
+     named app_info.app_name
+  """
+  # create new app_dir in temp dir
+  app_name = app_info.android_name
+  app_dir = GetBuildDir(app_name)
+  app_package = app_info.package
+  app_root = app_info.app_root
+  template_app_dir = os.path.join(xwalk_dir, TEMPLATE_DIR_NAME)
+
+  # 1) copy template project to app_dir
+  CleanDir(app_dir)
+  if not os.path.isdir(template_app_dir):
+    print('Error: The template directory could not be found (%s).' %
+          template_app_dir)
     sys.exit(7)
-  root_path = os.path.join(name, 'src', package.replace('.', os.path.sep))
-  if not os.path.exists(root_path):
-    os.makedirs(root_path)
-  dest_activity = name + 'Activity.java'
-  shutil.copyfile(src_activity, os.path.join(root_path, dest_activity))
+  shutil.copytree(template_app_dir, app_dir)
+
+  # 2) replace app_dir 'src' dir with template 'src' dir
+  CleanDir(os.path.join(app_dir, 'src'))
+  template_src_root = os.path.join(template_app_dir, 'src', 'org', 'xwalk',
+                                   'app', 'template')
+
+  # 3) Create directory tree from app package (org.xyz.foo -> src/org/xyz/foo)
+  #    and copy AppTemplateActivity.java to <app_name>Activity.java
+  template_activity_file = os.path.join(template_src_root,
+                                        'AppTemplateActivity.java')
+  if not os.path.isfile(template_activity_file):
+    print ('Error: The template file %s was not found. '
+           'Please make sure this file exists.' % template_activity_file)
+    sys.exit(7)
+  app_pkg_dir = os.path.join(app_dir, 'src',
+                             app_package.replace('.', os.path.sep))
+  if not os.path.exists(app_pkg_dir):
+    os.makedirs(app_pkg_dir)
+  app_activity_file = app_name + 'Activity.java'
+  shutil.copyfile(template_activity_file,
+                  os.path.join(app_pkg_dir, app_activity_file))
+
+  # 4) Copy all HTML source from app_root to app_dir
   if app_root:
-    assets_path = os.path.join(name, 'assets')
-    shutil.rmtree(assets_path)
-    os.makedirs(assets_path)
-    app_src_path = os.path.join(assets_path, 'www')
-    shutil.copytree(app_root, app_src_path)
+    app_assets_dir = os.path.join(app_dir, 'assets', 'www')
+    CleanDir(app_assets_dir)
+    shutil.copytree(app_root, app_assets_dir)
     if compressor:
-      CompressSourceFiles(app_src_path, compressor)
+      CompressSourceFiles(app_assets_dir, compressor)
+
+
+def EncodingUnicodeValue(value):
+  try:
+    if isinstance(value, unicode):
+      value = value.encode("utf-8")
+  except NameError:
+    pass
+  return value
 
 
 def CustomizeStringXML(name, description):
-  strings_path = os.path.join(name, 'res', 'values', 'strings.xml')
+  strings_path = os.path.join(GetBuildDir(name), 'res', 'values',
+                              'strings.xml')
   if not os.path.isfile(strings_path):
     print ('Please make sure strings_xml'
-           ' exists under app_src folder.')
+           ' exists under template folder.')
     sys.exit(6)
 
   if description:
+    description = EncodingUnicodeValue(description)
     xmldoc = minidom.parse(strings_path)
     AddElementAttributeAndText(xmldoc, 'string', 'name', 'description',
                                description)
@@ -150,8 +190,8 @@ def CustomizeStringXML(name, description):
     strings_file.close()
 
 
-def CustomizeThemeXML(name, fullscreen, app_manifest):
-  theme_path = os.path.join(name, 'res', 'values', 'theme.xml')
+def CustomizeThemeXML(name, fullscreen, manifest):
+  theme_path = os.path.join(GetBuildDir(name), 'res', 'values-v14', 'theme.xml')
   if not os.path.isfile(theme_path):
     print('Error: theme.xml is missing in the build tool.')
     sys.exit(6)
@@ -160,7 +200,7 @@ def CustomizeThemeXML(name, fullscreen, app_manifest):
   if fullscreen:
     EditElementValueByNodeName(theme_xmldoc, 'item',
                                'android:windowFullscreen', 'true')
-  has_background = CustomizeLaunchScreen(app_manifest, name)
+  has_background = CustomizeLaunchScreen(manifest, name)
   if has_background:
     EditElementValueByNodeName(theme_xmldoc, 'item',
                                'android:windowBackground',
@@ -170,17 +210,30 @@ def CustomizeThemeXML(name, fullscreen, app_manifest):
   theme_file.close()
 
 
-def CustomizeXML(package, app_versionCode, app_version, description, name,
-                 orientation, icon_dict, fullscreen, icon, app_manifest,
-                 permissions, app_root):
-  manifest_path = os.path.join(name, 'AndroidManifest.xml')
+def CustomizeXML(app_info, description, icon_dict, manifest, permissions):
+  app_version = app_info.app_version
+  app_versionCode = app_info.app_versionCode
+  name = app_info.android_name
+  orientation = app_info.orientation
+  package = app_info.package
+  app_name = app_info.app_name
+  app_dir = GetBuildDir(name)
+  # Chinese character with unicode get from 'manifest.json' will cause
+  # 'UnicodeEncodeError' when finally wrote to 'AndroidManifest.xml'.
+  app_name = EncodingUnicodeValue(app_name)
+  # If string start with '@' or '?', it will be treated as Android resource,
+  # which will cause 'No resource found' error,
+  # append a space before '@' or '?' to fix that.
+  if app_name.startswith('@') or app_name.startswith('?'):
+    app_name = ' ' + app_name
+  manifest_path = os.path.join(app_dir, 'AndroidManifest.xml')
   if not os.path.isfile(manifest_path):
     print ('Please make sure AndroidManifest.xml'
-           ' exists under app_src folder.')
+           ' exists under template folder.')
     sys.exit(6)
 
   CustomizeStringXML(name, description)
-  CustomizeThemeXML(name, fullscreen, app_manifest)
+  CustomizeThemeXML(name, app_info.fullscreen_flag, manifest)
   xmldoc = minidom.parse(manifest_path)
   EditElementAttribute(xmldoc, 'manifest', 'package', package)
   if app_versionCode:
@@ -193,19 +246,19 @@ def CustomizeXML(package, app_versionCode, app_version, description, name,
     EditElementAttribute(xmldoc, 'manifest', 'android:description',
                          "@string/description")
   HandlePermissions(permissions, xmldoc)
-  EditElementAttribute(xmldoc, 'application', 'android:label', name)
+  EditElementAttribute(xmldoc, 'application', 'android:label', app_name)
   activity_name = package + '.' + name + 'Activity'
   EditElementAttribute(xmldoc, 'activity', 'android:name', activity_name)
-  EditElementAttribute(xmldoc, 'activity', 'android:label', name)
+  EditElementAttribute(xmldoc, 'activity', 'android:label', app_name)
   if orientation:
     EditElementAttribute(xmldoc, 'activity', 'android:screenOrientation',
                          orientation)
-  icon_name = CustomizeIcon(name, app_root, icon, icon_dict)
+  icon_name = CustomizeIcon(name, app_info.app_root, app_info.icon, icon_dict)
   if icon_name:
     EditElementAttribute(xmldoc, 'application', 'android:icon',
                          '@drawable/%s' % icon_name)
 
-  file_handle = open(os.path.join(name, 'AndroidManifest.xml'), 'w')
+  file_handle = open(os.path.join(app_dir, 'AndroidManifest.xml'), 'w')
   xmldoc.writexml(file_handle, encoding='utf-8')
   file_handle.close()
 
@@ -222,7 +275,7 @@ def ReplaceString(file_path, src, dest):
 
 def SetVariable(file_path, string_line, variable, value):
   function_string = ('%sset%s(%s);\n' %
-                    ('        ', variable, value))
+                     ('        ', variable, value))
   temp_file_path = file_path + '.backup'
   file_handle = open(temp_file_path, 'w+')
   for line in open(file_path):
@@ -233,14 +286,15 @@ def SetVariable(file_path, string_line, variable, value):
   shutil.move(temp_file_path, file_path)
 
 
-def CustomizeJava(name, package, app_url, app_local_path,
-                  enable_remote_debugging, display_as_fullscreen,
-                  keep_screen_on):
-  root_path = os.path.join(name, 'src', package.replace('.', os.path.sep))
-  dest_activity = os.path.join(root_path, name + 'Activity.java')
+def CustomizeJava(app_info, app_url, app_local_path, keep_screen_on):
+  name = app_info.android_name
+  package = app_info.package
+  app_dir = GetBuildDir(name)
+  app_pkg_dir = os.path.join(app_dir, 'src', package.replace('.', os.path.sep))
+  dest_activity = os.path.join(app_pkg_dir, name + 'Activity.java')
   ReplaceString(dest_activity, 'org.xwalk.app.template', package)
   ReplaceString(dest_activity, 'AppTemplate', name)
-  manifest_file = os.path.join(name, 'assets/www', 'manifest.json')
+  manifest_file = os.path.join(app_dir, 'assets', 'www', 'manifest.json')
   if os.path.isfile(manifest_file):
     ReplaceString(
         dest_activity,
@@ -252,7 +306,7 @@ def CustomizeJava(name, package, app_url, app_local_path,
         ReplaceString(dest_activity, 'file:///android_asset/www/index.html',
                       app_url)
     elif app_local_path:
-      if os.path.isfile(os.path.join(name, 'assets/www', app_local_path)):
+      if os.path.isfile(os.path.join(app_dir, 'assets', 'www', app_local_path)):
         ReplaceString(dest_activity, 'file:///android_asset/www/index.html',
                       'app://' + package + '/' + app_local_path)
       else:
@@ -260,11 +314,15 @@ def CustomizeJava(name, package, app_url, app_local_path,
                ' is correct.')
         sys.exit(8)
 
-  if enable_remote_debugging:
+  if app_info.remote_debugging:
     SetVariable(dest_activity,
                 'public void onCreate(Bundle savedInstanceState)',
                 'RemoteDebugging', 'true')
-  if display_as_fullscreen:
+  if app_info.use_animatable_view:
+    SetVariable(dest_activity,
+                'public void onCreate(Bundle savedInstanceState)',
+                'UseAnimatableView', 'true')
+  if app_info.fullscreen_flag:
     SetVariable(dest_activity,
                 'super.onCreate(savedInstanceState)',
                 'IsFullscreen', 'true')
@@ -281,7 +339,7 @@ def CopyExtensionFile(extension_name, suffix, src_path, dest_path):
   dest_extension_path = os.path.join(dest_path, extension_name)
   if os.path.exists(dest_extension_path):
     # TODO: Refine it by renaming it internally.
-    print('Error: duplicated extension names "%s" are found. Please rename it.'
+    print('Error: duplicate extension names were found (%s). Please rename it.'
           % extension_name)
     sys.exit(9)
   else:
@@ -291,13 +349,13 @@ def CopyExtensionFile(extension_name, suffix, src_path, dest_path):
   src_file = os.path.join(src_path, file_name)
   dest_file = os.path.join(dest_extension_path, file_name)
   if not os.path.isfile(src_file):
+    print('Error: %s was not found in %s.' % (file_name, src_path))
     sys.exit(9)
-    print('Error: %s is not found in %s.' % (file_name, src_path))
   else:
     shutil.copyfile(src_file, dest_file)
 
 
-def CustomizeExtensions(name, extensions):
+def CustomizeExtensions(app_info, extensions):
   """Copy the files from external extensions and merge them into APK.
 
   The directory of one external extension should be like:
@@ -315,12 +373,13 @@ def CustomizeExtensions(name, extensions):
   """
   if not extensions:
     return
-  apk_path = name
-  apk_assets_path = os.path.join(apk_path, 'assets')
+  name = app_info.android_name
+  app_dir = GetBuildDir(name)
+  apk_assets_path = os.path.join(app_dir, 'assets')
   extensions_string = 'xwalk-extensions'
 
   # Set up the target directories and files.
-  dest_jar_path = os.path.join(apk_path, extensions_string)
+  dest_jar_path = os.path.join(app_dir, extensions_string)
   os.mkdir(dest_jar_path)
   dest_js_path = os.path.join(apk_assets_path, extensions_string)
   os.mkdir(dest_js_path)
@@ -332,7 +391,7 @@ def CustomizeExtensions(name, extensions):
   extension_json_list = []
   for source_path in extension_paths:
     if not os.path.exists(source_path):
-      print('Error: can\'t find the extension directory \'%s\'.' % source_path)
+      print('Error: can not find the extension directory \'%s\'.' % source_path)
       sys.exit(9)
     # Remove redundant separators to avoid empty basename.
     source_path = os.path.normpath(source_path)
@@ -348,10 +407,10 @@ def CustomizeExtensions(name, extensions):
     file_name = extension_name + '.json'
     src_file = os.path.join(source_path, file_name)
     if not os.path.isfile(src_file):
-      print('Error: %s is not found in %s.' % (file_name, source_path))
+      print('Error: %s was not found in %s.' % (file_name, source_path))
       sys.exit(9)
     else:
-      src_file_handle = file(src_file)
+      src_file_handle = open(src_file)
       src_file_content = src_file_handle.read()
       json_output = json.JSONDecoder().decode(src_file_content)
       # Below 3 properties are used by runtime. See extension manager.
@@ -367,7 +426,7 @@ def CustomizeExtensions(name, extensions):
       json_output['jsapi'] = js_path_prefix + json_output['jsapi']
       extension_json_list.append(json_output)
       # Merge the permissions of extensions into AndroidManifest.xml.
-      manifest_path = os.path.join(name, 'AndroidManifest.xml')
+      manifest_path = os.path.join(app_dir, 'AndroidManifest.xml')
       xmldoc = minidom.parse(manifest_path)
       if ('permissions' in json_output):
         # Get used permission list to avoid repetition as "--permissions"
@@ -397,16 +456,17 @@ def CustomizeExtensions(name, extensions):
     extension_json_file.close()
 
 
-def GenerateCommandLineFile(name, xwalk_command_line):
+def GenerateCommandLineFile(app_info, xwalk_command_line):
   if xwalk_command_line == '':
     return
-  assets_path = os.path.join(name, 'assets')
+  assets_path = os.path.join(GetBuildDir(app_info.android_name), 'assets')
   file_path = os.path.join(assets_path, 'xwalk-command-line')
   command_line_file = open(file_path, 'w')
   command_line_file.write('xwalk ' + xwalk_command_line)
 
 
 def CustomizeIconByDict(name, app_root, icon_dict):
+  app_dir = GetBuildDir(name)
   icon_name = None
   drawable_dict = {'ldpi': [1, 37], 'mdpi': [37, 72], 'hdpi': [72, 96],
                    'xhdpi': [96, 120], 'xxhdpi': [120, 144],
@@ -420,11 +480,11 @@ def CustomizeIconByDict(name, app_root, icon_dict):
     print('The key of icon in the manifest file should be a number.')
 
   if len(icon_dict) > 0:
-    icon_list = sorted(icon_dict.iteritems(), key=lambda d: d[0])
-    for kd, vd in drawable_dict.iteritems():
+    icon_list = sorted(icon_dict.items(), key=lambda d: d[0])
+    for kd, vd in drawable_dict.items():
       for item in icon_list:
         if item[0] >= vd[0] and item[0] < vd[1]:
-          drawable_path = os.path.join(name, 'res', 'drawable-' + kd)
+          drawable_path = os.path.join(app_dir, 'res', 'drawable-' + kd)
           if not os.path.exists(drawable_path):
             os.makedirs(drawable_path)
           icon = os.path.join(app_root, item[1])
@@ -435,7 +495,7 @@ def CustomizeIconByDict(name, app_root, icon_dict):
                                                'icon.' + icon_suffix))
             icon_name = 'icon'
           elif icon and (not os.path.isfile(icon)):
-            print ('Error: Please make sure \"' + icon + '\" does exist!')
+            print('Error: "%s" does not exist.' % icon)
             sys.exit(6)
           break
   return icon_name
@@ -443,7 +503,7 @@ def CustomizeIconByDict(name, app_root, icon_dict):
 
 def CustomizeIconByOption(name, icon):
   if os.path.isfile(icon):
-    drawable_path = os.path.join(name, 'res', 'drawable')
+    drawable_path = os.path.join(GetBuildDir(name), 'res', 'drawable')
     if not os.path.exists(drawable_path):
       os.makedirs(drawable_path)
     icon_file = os.path.basename(icon)
@@ -452,7 +512,7 @@ def CustomizeIconByOption(name, icon):
     icon_name = os.path.splitext(icon_file)[0]
     return icon_name
   else:
-    print ('Error: Please make sure \"' + icon + '\" is a file!')
+    print('Error: "%s" does not exist.' % icon)
     sys.exit(6)
 
 
@@ -465,23 +525,15 @@ def CustomizeIcon(name, app_root, icon, icon_dict):
   return icon_name
 
 
-def CustomizeAll(app_versionCode, description, icon_dict, permissions, app_url,
-                 app_root, app_local_path, enable_remote_debugging,
-                 display_as_fullscreen, keep_screen_on, extensions,
-                 app_manifest, icon, package='org.xwalk.app.template',
-                 name='AppTemplate', app_version='1.0.0',
-                 orientation='unspecified', xwalk_command_line='',
-                 compressor=None):
+def CustomizeAll(app_info, description, icon_dict, permissions, app_url,
+                 app_local_path, keep_screen_on, extensions, manifest,
+                 xwalk_command_line='', compressor=None):
   try:
-    Prepare(name, package, app_root, compressor)
-    CustomizeXML(package, app_versionCode, app_version, description, name,
-                 orientation, icon_dict, display_as_fullscreen, icon,
-                 app_manifest, permissions, app_root)
-    CustomizeJava(name, package, app_url, app_local_path,
-                  enable_remote_debugging, display_as_fullscreen,
-                  keep_screen_on)
-    CustomizeExtensions(name, extensions)
-    GenerateCommandLineFile(name, xwalk_command_line)
+    Prepare(app_info, compressor)
+    CustomizeXML(app_info, description, icon_dict, manifest, permissions)
+    CustomizeJava(app_info, app_url, app_local_path, keep_screen_on)
+    CustomizeExtensions(app_info, extensions)
+    GenerateCommandLineFile(app_info, xwalk_command_line)
   except SystemExit as ec:
     print('Exiting with error code: %d' % ec.code)
     sys.exit(ec.code)
@@ -520,6 +572,9 @@ def main():
   parser.add_option('--enable-remote-debugging', action='store_true',
                     dest='enable_remote_debugging', default=False,
                     help='Enable remote debugging.')
+  parser.add_option('--use-animatable-view', action='store_true',
+                    dest='use_animatable_view', default=False,
+                    help='Enable using animatable view (TextureView).')
   parser.add_option('-f', '--fullscreen', action='store_true',
                     dest='fullscreen', default=False,
                     help='Make application fullscreen.')
@@ -540,6 +595,8 @@ def main():
           'Crosswalk is powered by Chromium and supports Chromium command line.'
           'For example, '
           '--xwalk-command-line=\'--chromium-command-1 --xwalk-command-2\'')
+  info = ('Create an Android project directory at this location. ')
+  parser.add_option('--project-dir', help=info)
   parser.add_option('--xwalk-command-line', default='', help=info)
   info = ('Minify and obfuscate javascript and css.'
           '--compressor: compress javascript and css.'
@@ -554,28 +611,41 @@ def main():
                  72: 'icons/icon_72.png',
                  96: 'icons/icon_96.png',
                  48: 'icons/icon_48.png'}
-    if options.name is None:
-      options.name = 'Example'
+    app_info = AppInfo()
+    if options.name is not None:
+      app_info.android_name = options.name
     if options.app_root is None:
-      options.app_root = os.path.join('test_data', 'manifest')
-    if options.package is None:
-      options.package = 'org.xwalk.app.template'
-    if options.orientation is None:
-      options.orientation = 'unspecified'
-    if options.app_version is None:
-      options.app_version = '1.0.0'
-    icon = os.path.join('test_data', 'manifest', 'icons', 'icon_96.png')
-    CustomizeAll(options.app_versionCode, options.description, icon_dict,
-                 options.permissions, options.app_url, options.app_root,
-                 options.app_local_path, options.enable_remote_debugging,
-                 options.fullscreen, options.keep_screen_on,
-                 options.extensions, options.manifest,
-                 icon, options.package, options.name,
-                 options.app_version, options.orientation,
+      app_info.app_root = os.path.join(xwalk_dir, 'test_data', 'manifest')
+    else:
+      app_info.app_root = options.app_root
+    if options.package is not None:
+      app_info.package = options.package
+    if options.orientation is not None:
+      app_info.orientation = options.orientation
+    if options.app_version is not None:
+      app_info.app_version = options.app_version
+    if options.enable_remote_debugging is not None:
+      app_info.remote_debugging = options.enable_remote_debugging
+    if options.fullscreen is not None:
+      app_info.fullscreen_flag = options.fullscreen
+    app_info.icon = os.path.join('test_data', 'manifest', 'icons',
+                                 'icon_96.png')
+    CustomizeAll(app_info, options.description, icon_dict,
+                 options.permissions, options.app_url, options.app_local_path,
+                 options.keep_screen_on, options.extensions, None,
                  options.xwalk_command_line, options.compressor)
+
+    # build project is now in /tmp/<name>. Copy to project_dir
+    if options.project_dir:
+      src_dir = GetBuildDir(app_info.android_name)
+      dest_dir = os.path.join(options.project_dir, app_info.android_name)
+      CreateAndCopyDir(src_dir, dest_dir, True)
+
   except SystemExit as ec:
     print('Exiting with error code: %d' % ec.code)
     return ec.code
+  finally:
+    CleanDir(GetBuildDir(app_info.android_name))
   return 0