示例#1
0
	def __init__(self, path, manifest):
		self.path = path
		self.manifest = manifest

		self.jar = None
		module_jar = self.get_resource(manifest.name + '.jar')
		if os.path.exists(module_jar):
			self.jar = module_jar
		else:
			# To account for Linux filename case-sensitivity,
			# we began to force our external module jars to be lower-case,
			# so give that a shot here.
			module_jar = self.get_resource(manifest.name.lower() + '.jar')
			if os.path.exists(module_jar):
				self.jar = module_jar
		self.lib = None

		module_lib = self.get_resource('lib%s.a' % manifest.moduleid)
		if os.path.exists(module_lib):
			self.lib = module_lib

		self.xml = None
		module_xml = self.get_resource('timodule.xml')
		if os.path.exists(module_xml):
			self.xml = TiAppXML(module_xml, parse_only=True)

		self.js = None
		module_js = self.get_resource('%s.js' % manifest.moduleid)
		if os.path.exists(module_js):
			self.js = module_js
示例#2
0
    def __init__(self, path, manifest):
        self.path = path
        self.manifest = manifest
        self.jar = None
        module_jar = self.get_resource(manifest.name + '.jar')
        if os.path.exists(module_jar):
            self.jar = module_jar

        self.xml = None
        module_xml = self.get_resource('timodule.xml')
        if os.path.exists(module_xml):
            self.xml = TiAppXML(module_xml, parse_only=True)
    def __init__(self, project_dir, type, ndk, useLogFile=False):
        self.top_dir = project_dir.rstrip(os.sep)
        self.type = type
        (self.variant, self.cpu) = Builder.type2variantCpu[type]
        self.ndk = ndk
        self.project_tiappxml = os.path.join(self.top_dir, 'tiapp.xml')
        self.tiappxml = TiAppXML(self.project_tiappxml)
        self.name = self.tiappxml.properties['name']
        self.buildDir = os.path.join(self.top_dir, 'build', 'blackberry')
        self.project_deltafy = Deltafy(self.top_dir)

        if useLogFile:
            self.tiappxml = TiAppXML(self.project_tiappxml)
        else:
            # hide property output
            with open(os.devnull, 'w') as nul:
                oldStdout = sys.stdout
                sys.stdout = nul
                self.tiappxml = TiAppXML(self.project_tiappxml)
                sys.stdout = oldStdout
        self.name = self.tiappxml.properties['name']
        self.buildDir = os.path.join(self.top_dir, 'build', 'blackberry')
示例#4
0
    def __init__(self, path, manifest):
        self.path = path
        self.manifest = manifest

        self.jar = None
        module_jar = self.get_resource(manifest.name + '.jar')
        if os.path.exists(module_jar):
            self.jar = module_jar
        self.lib = None

        module_lib = self.get_resource('lib%s.a' % manifest.moduleid)
        if os.path.exists(module_lib):
            self.lib = module_lib

        self.xml = None
        module_xml = self.get_resource('timodule.xml')
        if os.path.exists(module_xml):
            self.xml = TiAppXML(module_xml, parse_only=True)

        self.js = None
        module_js = self.get_resource('%s.js' % manifest.moduleid)
        if os.path.exists(module_js):
            self.js = module_js
示例#5
0
class Android(object):
    def __init__(self, name, myid, sdk, deploy_type, java):
        self.name = name
        # android requires at least one dot in packageid
        if len(re.findall(r'\.', myid)) == 0:
            myid = 'com.%s' % myid

        self.id = myid
        self.sdk = sdk

        # Used in templating
        self.config = {
            'appid': self.id,
            'appname': self.name,
            'appversion': '1',
            'apiversion': '7',  #Android 2.1
            'deploy_type': deploy_type,
            'compile_js': False
        }
        self.config['classname'] = Android.strip_classname(self.name)
        self.deploy_type = deploy_type
        self.java = java

    @classmethod
    def strip_classname(cls, name):
        classname = ''.join(
            [str.capitalize() for str in re.split('[^A-Za-z0-9_]', name)])
        if re.search("^[0-9]", classname) != None:
            classname = "_" + classname
        return classname

    def newdir(self, *segments):
        path = os.path.join(*segments)
        if not os.path.exists(path):
            os.makedirs(path)
        return path

    def copyfile(self, file, src, dest):
        shutil.copy(os.path.join(src, file), os.path.join(dest, file))

    def load_template(self, template):
        return Template(filename=template,
                        output_encoding='utf-8',
                        encoding_errors='replace')

    def render_android_manifest(self):
        template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename)
        tmpl = self.load_template(
            os.path.join(template_dir, 'templates', 'AndroidManifest.xml'))
        return tmpl.render(config=self.config)

    def render(self, template_dir, template_file, dest, dest_file, **kwargs):
        tmpl = self.load_template(
            os.path.join(template_dir, 'templates', template_file))
        f = None
        try:
            print "[TRACE] Generating %s" % os.path.join(dest, dest_file)
            f = open(os.path.join(dest, dest_file), "w")
            f.write(tmpl.render(config=self.config, **kwargs))
        finally:
            if f != None: f.close

    def build_app_info(self, project_dir):
        tiapp = ElementTree()
        assets_tiappxml = os.path.join(project_dir, 'build', 'android', 'bin',
                                       'assets', 'tiapp.xml')

        self.app_info = {'fullscreen': 'false', 'navbar-hidden': 'false'}
        self.app_properties = {}
        if not os.path.exists(assets_tiappxml):
            shutil.copy(os.path.join(project_dir, 'tiapp.xml'),
                        assets_tiappxml)

        tiapp.parse(open(assets_tiappxml, 'r'))
        for key in [
                'id', 'name', 'version', 'publisher', 'url', 'copyright',
                'description', 'icon', 'analytics', 'guid', 'navbar-hidden',
                'fullscreen'
        ]:
            el = tiapp.find(key)
            if el != None:
                self.app_info[key] = el.text

        for property_el in tiapp.findall("property"):
            name = property_el.get("name")
            type = property_el.get("type")
            value = property_el.text
            if name == None: continue
            if type == None: type = "string"
            if value == None: value = ""
            self.app_properties[name] = {"type": type, "value": value}

    def generate_activities(self, app_package_dir):
        if not 'activities' in self.tiapp.android: return
        for key in self.tiapp.android['activities'].keys():
            activity = self.tiapp.android['activities'][key]
            print '[DEBUG] generating activity class: ' + activity['classname']

            self.render(template_dir,
                        'JSActivity.java',
                        app_package_dir,
                        activity['classname'] + '.java',
                        activity=activity)

    def generate_services(self, app_package_dir):
        if not 'services' in self.tiapp.android: return
        for key in self.tiapp.android['services'].keys():
            service = self.tiapp.android['services'][key]
            service_type = service['service_type']
            print '[DEBUG] generating service type "%s", class "%s"' % (
                service_type, service['classname'])
            if service_type == 'interval':
                self.render(template_dir,
                            'JSIntervalService.java',
                            app_package_dir,
                            service['classname'] + '.java',
                            service=service)
            else:
                self.render(template_dir,
                            'JSService.java',
                            app_package_dir,
                            service['classname'] + '.java',
                            service=service)

    def build_modules_info(self,
                           resources_dir,
                           app_bin_dir,
                           include_all_ti_modules=False):
        self.app_modules = []
        (modules, external_child_modules) = bindings.get_all_module_bindings()

        compiler = Compiler(self.tiapp,
                            resources_dir,
                            self.java,
                            app_bin_dir,
                            None,
                            os.path.dirname(app_bin_dir),
                            include_all_modules=include_all_ti_modules)
        compiler.compile(compile_bytecode=False, info_message=None)
        for module in compiler.modules:
            module_bindings = []
            # TODO: we should also detect module properties
            for method in compiler.module_methods:
                if method.lower().startswith(module +
                                             '.') and '.' not in method:
                    module_bindings.append(method[len(module) + 1:])

            module_onAppCreate = None
            module_class = None
            module_apiName = None
            for m in modules.keys():
                if modules[m]['fullAPIName'].lower() == module:
                    module_class = m
                    module_apiName = modules[m]['fullAPIName']
                    if 'onAppCreate' in modules[m]:
                        module_onAppCreate = modules[m]['onAppCreate']
                    break

            if module_apiName == None: continue  # module wasn't found
            ext_modules = []
            if module_class in external_child_modules:
                for child_module in external_child_modules[module_class]:
                    if child_module['fullAPIName'].lower() in compiler.modules:
                        ext_modules.append(child_module)
            self.app_modules.append({
                'api_name': module_apiName,
                'class_name': module_class,
                'bindings': module_bindings,
                'external_child_modules': ext_modules,
                'on_app_create': module_onAppCreate
            })

        # discover app modules
        detector = ModuleDetector(self.project_dir)
        missing, detected_modules = detector.find_app_modules(
            self.tiapp, 'android', self.deploy_type)
        for missing_module in missing:
            print '[WARN] Couldn\'t find app module: %s' % missing_module['id']

        self.custom_modules = []
        for module in detected_modules:
            if module.jar == None: continue
            module_jar = zipfile.ZipFile(module.jar)
            module_bindings = bindings.get_module_bindings(module_jar)
            if module_bindings is None: continue

            for module_class in module_bindings['modules'].keys():
                module_apiName = module_bindings['modules'][module_class][
                    'apiName']
                module_proxy = module_bindings['proxies'][module_class]
                module_id = module_proxy['proxyAttrs']['id']
                module_proxy_class_name = module_proxy['proxyClassName']
                module_onAppCreate = None
                if 'onAppCreate' in module_proxy:
                    module_onAppCreate = module_proxy['onAppCreate']

                print '[DEBUG] module_id = %s' % module_id
                if module_id == module.manifest.moduleid:
                    # make sure that the module was not built before 1.8.0.1
                    try:
                        module_api_version = int(module.manifest.apiversion)
                        if module_api_version < 2:
                            print "[ERROR] The 'apiversion' for '%s' in the module manifest is less than version 2.  The module was likely built against a Titanium SDK pre 1.8.0.1.  Please use a version of the module that has 'apiversion' 2 or greater" % module_id
                            touch_tiapp_xml(
                                os.path.join(self.project_dir, 'tiapp.xml'))
                            sys.exit(1)

                    except (TypeError, ValueError):
                        print "[ERROR] The 'apiversion' for '%s' in the module manifest is not a valid value.  Please use a version of the module that has an 'apiversion' value of 2 or greater set in it's manifest file" % module_id
                        touch_tiapp_xml(
                            os.path.join(self.project_dir, 'tiapp.xml'))
                        sys.exit(1)

                    is_native_js_module = (hasattr(module.manifest, 'commonjs')
                                           and module.manifest.commonjs)
                    print '[DEBUG] appending module: %s' % module_class
                    self.custom_modules.append({
                        'module_id':
                        module_id,
                        'module_apiName':
                        module_apiName,
                        'proxy_name':
                        module_proxy_class_name,
                        'class_name':
                        module_class,
                        'manifest':
                        module.manifest,
                        'on_app_create':
                        module_onAppCreate,
                        'is_native_js_module':
                        is_native_js_module
                    })
                    if is_native_js_module:
                        # Need to look at the app modules used in this external js module
                        metadata_file = os.path.join(module.path,
                                                     "metadata.json")
                        metadata = None
                        try:
                            f = open(metadata_file, "r")
                            metadata = f.read()
                        finally:
                            f.close()

                        if metadata:
                            metadata = simplejson.loads(metadata)
                            if metadata.has_key("exports"):
                                exported_module_ids = metadata["exports"]
                                already_included_module_ids = [
                                    m["api_name"].lower()
                                    for m in self.app_modules
                                ]
                                need_to_add = [
                                    m for m in exported_module_ids
                                    if m not in already_included_module_ids
                                ]
                                if need_to_add:
                                    for to_add in need_to_add:
                                        module_onAppCreate = None
                                        module_class = None
                                        module_apiName = None
                                        for m in modules.keys():
                                            if modules[m]['fullAPIName'].lower(
                                            ) == to_add:
                                                module_class = m
                                                module_apiName = modules[m][
                                                    'fullAPIName']
                                                if 'onAppCreate' in modules[m]:
                                                    module_onAppCreate = modules[
                                                        m]['onAppCreate']
                                                break

                                        if module_apiName == None:
                                            continue  # module wasn't found
                                        ext_modules = []
                                        if module_class in external_child_modules:
                                            for child_module in external_child_modules[
                                                    module_class]:
                                                if child_module[
                                                        'fullAPIName'].lower(
                                                        ) in compiler.modules:
                                                    ext_modules.append(
                                                        child_module)
                                        self.app_modules.append({
                                            'api_name':
                                            module_apiName,
                                            'class_name':
                                            module_class,
                                            'bindings': [],
                                            'external_child_modules':
                                            ext_modules,
                                            'on_app_create':
                                            module_onAppCreate
                                        })

    def create(self,
               dir,
               build_time=False,
               project_dir=None,
               include_all_ti_modules=False):
        template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename)

        # Build up output directory tree
        if project_dir is None:
            project_dir = self.newdir(dir, self.name)

        self.project_dir = project_dir
        # Paths to Titanium assets that need to be linked into eclipse structure
        self.config['ti_tiapp_xml'] = os.path.join(project_dir, 'tiapp.xml')
        self.tiapp = TiAppXML(self.config['ti_tiapp_xml'])
        resource_dir = os.path.join(project_dir, 'Resources')
        self.config['ti_resources_dir'] = resource_dir

        json_contents = open(os.path.join(template_dir,
                                          'dependency.json')).read()
        depends_map = simplejson.loads(json_contents)
        runtime = depends_map['runtimes']['defaultRuntime']
        if self.tiapp.has_app_property("ti.android.runtime"):
            requested_runtime = self.tiapp.get_app_property(
                "ti.android.runtime")
            if requested_runtime == "rhino" or requested_runtime == "v8":
                runtime = requested_runtime
            else:
                print "[ERROR] invalid runtime \"" + requested_runtime + "\" requested, must be 'v8' or 'rhino'"
                sys.exit(1)

        app_build_dir = self.newdir(project_dir, 'build')
        app_dir = self.newdir(app_build_dir, 'android')

        #if os.path.exists(os.path.join(app_dir,'bin')):
        #	shutil.rmtree(os.path.join(app_dir,'bin'))

        if os.path.exists(os.path.join(app_dir, 'src')):
            shutil.rmtree(os.path.join(app_dir, 'src'))

        if os.path.exists(os.path.join(app_dir, 'res')):
            shutil.rmtree(os.path.join(app_dir, 'res'))

        app_bin_dir = self.newdir(app_dir, 'bin')
        app_lib_dir = self.newdir(app_dir, 'lib')
        app_src_dir = self.newdir(app_dir, 'src')
        app_res_dir = self.newdir(app_dir, 'res')
        app_gen_dir = self.newdir(app_dir, 'gen')
        app_bin_classes_dir = self.newdir(app_bin_dir, 'classes')

        app_res_drawable_dir = self.newdir(app_res_dir, 'drawable')
        app_assets_dir = self.newdir(app_dir, 'assets')
        app_package_dir = self.newdir(app_gen_dir, *self.id.split('.'))
        app_bin_assets_dir = self.newdir(app_bin_dir, 'assets')
        app_bin_assets_resources_dir = self.newdir(app_bin_assets_dir,
                                                   'Resources')

        self.build_app_info(project_dir)
        self.build_modules_info(app_bin_assets_resources_dir,
                                app_bin_dir,
                                include_all_ti_modules=include_all_ti_modules)

        # Create android source
        self.render(template_dir,
                    'AppInfo.java',
                    app_package_dir,
                    self.config['classname'] + 'AppInfo.java',
                    app_properties=self.app_properties,
                    app_info=self.app_info)

        self.render(template_dir, 'AndroidManifest.xml', app_dir,
                    'AndroidManifest.xml')
        self.render(template_dir,
                    'App.java',
                    app_package_dir,
                    self.config['classname'] + 'Application.java',
                    app_modules=self.app_modules,
                    custom_modules=self.custom_modules,
                    runtime=runtime)
        self.render(template_dir, 'Activity.java', app_package_dir,
                    self.config['classname'] + 'Activity.java')
        self.generate_activities(app_package_dir)
        self.generate_services(app_package_dir)
        self.render(template_dir, 'classpath', app_dir, '.classpath')
        self.render(template_dir, 'project', app_dir, '.project')
        self.render(template_dir, 'default.properties', app_dir,
                    'default.properties')
        print "[TRACE] Generating app.json"
        f = None
        try:
            f = open(os.path.join(app_bin_assets_dir, "app.json"), "w")
            f.write(simplejson.dumps({"app_modules": self.app_modules}))
        finally:
            if f is not None:
                f.close()
        # Don't override a pre-existing .gitignore in case users have their own preferences
        # for what should be in it. (LH #2446)
        if not os.path.exists(os.path.join(app_dir, '.gitignore')):
            self.render(template_dir, 'gitignore', app_dir, '.gitignore')
        else:
            print "[TRACE] Skipping copying gitignore -> .gitignore because already exists"

        android_project_resources = os.path.join(project_dir, 'Resources',
                                                 'android')

        if build_time == False and os.path.exists(android_project_resources):
            shutil.rmtree(android_project_resources)

        if not os.path.exists(android_project_resources):
            copy_resources(os.path.join(template_dir, 'resources'),
                           android_project_resources)
示例#6
0
    def create(self,
               dir,
               build_time=False,
               project_dir=None,
               include_all_ti_modules=False):
        template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename)

        # Build up output directory tree
        if project_dir is None:
            project_dir = self.newdir(dir, self.name)

        self.project_dir = project_dir
        # Paths to Titanium assets that need to be linked into eclipse structure
        self.config['ti_tiapp_xml'] = os.path.join(project_dir, 'tiapp.xml')
        self.tiapp = TiAppXML(self.config['ti_tiapp_xml'])
        resource_dir = os.path.join(project_dir, 'Resources')
        self.config['ti_resources_dir'] = resource_dir

        json_contents = open(os.path.join(template_dir,
                                          'dependency.json')).read()
        depends_map = simplejson.loads(json_contents)
        runtime = depends_map['runtimes']['defaultRuntime']
        if self.tiapp.has_app_property("ti.android.runtime"):
            requested_runtime = self.tiapp.get_app_property(
                "ti.android.runtime")
            if requested_runtime == "rhino" or requested_runtime == "v8":
                runtime = requested_runtime
            else:
                print "[ERROR] invalid runtime \"" + requested_runtime + "\" requested, must be 'v8' or 'rhino'"
                sys.exit(1)

        app_build_dir = self.newdir(project_dir, 'build')
        app_dir = self.newdir(app_build_dir, 'android')

        #if os.path.exists(os.path.join(app_dir,'bin')):
        #	shutil.rmtree(os.path.join(app_dir,'bin'))

        if os.path.exists(os.path.join(app_dir, 'src')):
            shutil.rmtree(os.path.join(app_dir, 'src'))

        if os.path.exists(os.path.join(app_dir, 'res')):
            shutil.rmtree(os.path.join(app_dir, 'res'))

        app_bin_dir = self.newdir(app_dir, 'bin')
        app_lib_dir = self.newdir(app_dir, 'lib')
        app_src_dir = self.newdir(app_dir, 'src')
        app_res_dir = self.newdir(app_dir, 'res')
        app_gen_dir = self.newdir(app_dir, 'gen')
        app_bin_classes_dir = self.newdir(app_bin_dir, 'classes')

        app_res_drawable_dir = self.newdir(app_res_dir, 'drawable')
        app_assets_dir = self.newdir(app_dir, 'assets')
        app_package_dir = self.newdir(app_gen_dir, *self.id.split('.'))
        app_bin_assets_dir = self.newdir(app_bin_dir, 'assets')
        app_bin_assets_resources_dir = self.newdir(app_bin_assets_dir,
                                                   'Resources')

        self.build_app_info(project_dir)
        self.build_modules_info(app_bin_assets_resources_dir,
                                app_bin_dir,
                                include_all_ti_modules=include_all_ti_modules)

        # Create android source
        self.render(template_dir,
                    'AppInfo.java',
                    app_package_dir,
                    self.config['classname'] + 'AppInfo.java',
                    app_properties=self.app_properties,
                    app_info=self.app_info)

        self.render(template_dir, 'AndroidManifest.xml', app_dir,
                    'AndroidManifest.xml')
        self.render(template_dir,
                    'App.java',
                    app_package_dir,
                    self.config['classname'] + 'Application.java',
                    app_modules=self.app_modules,
                    custom_modules=self.custom_modules,
                    runtime=runtime)
        self.render(template_dir, 'Activity.java', app_package_dir,
                    self.config['classname'] + 'Activity.java')
        self.generate_activities(app_package_dir)
        self.generate_services(app_package_dir)
        self.render(template_dir, 'classpath', app_dir, '.classpath')
        self.render(template_dir, 'project', app_dir, '.project')
        self.render(template_dir, 'default.properties', app_dir,
                    'default.properties')
        print "[TRACE] Generating app.json"
        f = None
        try:
            f = open(os.path.join(app_bin_assets_dir, "app.json"), "w")
            f.write(simplejson.dumps({"app_modules": self.app_modules}))
        finally:
            if f is not None:
                f.close()
        # Don't override a pre-existing .gitignore in case users have their own preferences
        # for what should be in it. (LH #2446)
        if not os.path.exists(os.path.join(app_dir, '.gitignore')):
            self.render(template_dir, 'gitignore', app_dir, '.gitignore')
        else:
            print "[TRACE] Skipping copying gitignore -> .gitignore because already exists"

        android_project_resources = os.path.join(project_dir, 'Resources',
                                                 'android')

        if build_time == False and os.path.exists(android_project_resources):
            shutil.rmtree(android_project_resources)

        if not os.path.exists(android_project_resources):
            copy_resources(os.path.join(template_dir, 'resources'),
                           android_project_resources)
示例#7
0
                            key = "%s_%s" % (relative, f)
                        else:
                            key = f
                        key = key.replace('.js', '').replace(
                            '\\',
                            '_').replace('/',
                                         '_').replace(' ',
                                                      '_').replace('.', '_')
                        self.js_files[fullpath] = (key, js_contents)
        if compile_bytecode:
            self.compile_into_bytecode(self.js_files)


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print "Usage: %s <projectdir>" % sys.argv[0]
        sys.exit(1)

    project_dir = os.path.expanduser(sys.argv[1])
    resources_dir = os.path.join(project_dir, 'Resources')
    root_dir = os.path.join(project_dir, 'build', 'android')
    destdir = os.path.join(root_dir, 'bin', 'classes')
    sys.path.append("..")
    from tiapp import TiAppXML
    tiapp = TiAppXML(os.path.join(project_dir, 'tiapp.xml'))

    c = Compiler(tiapp, resources_dir, 'java', destdir, root_dir)
    project_deltafy = Deltafy(resources_dir)
    project_deltas = project_deltafy.scan()
    c.compile()
示例#8
0
	def create(self, dir, build_time=False, project_dir=None):
		template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename)
		
		# Build up output directory tree
		if project_dir is None:
			project_dir = self.newdir(dir, self.name)

		self.project_dir = project_dir
		# Paths to Titanium assets that need to be linked into eclipse structure
		self.config['ti_tiapp_xml'] = os.path.join(project_dir, 'tiapp.xml')
		self.tiapp = TiAppXML(self.config['ti_tiapp_xml'])
		resource_dir = os.path.join(project_dir, 'Resources')
		self.config['ti_resources_dir'] = resource_dir

		app_build_dir = self.newdir(project_dir, 'build')
		app_dir = self.newdir(app_build_dir, 'android')

		#if os.path.exists(os.path.join(app_dir,'bin')):
		#	shutil.rmtree(os.path.join(app_dir,'bin'))
			
		if os.path.exists(os.path.join(app_dir,'src')):
			shutil.rmtree(os.path.join(app_dir,'src'))

		if os.path.exists(os.path.join(app_dir,'res')):
			shutil.rmtree(os.path.join(app_dir,'res'))
			
		app_bin_dir = self.newdir(app_dir, 'bin')
		app_lib_dir = self.newdir(app_dir, 'lib')
		app_src_dir = self.newdir(app_dir, 'src')
		app_res_dir = self.newdir(app_dir, 'res')
		app_gen_dir = self.newdir(app_dir, 'gen')
		app_bin_classes_dir = self.newdir(app_bin_dir, 'classes')
		
		app_res_drawable_dir = self.newdir(app_res_dir, 'drawable')
		app_assets_dir = self.newdir(app_dir, 'assets')
		app_package_dir = self.newdir(app_gen_dir, *self.id.split('.'))
		app_bin_assets_dir = self.newdir(app_bin_dir, 'assets')
		
		self.build_app_info(project_dir)
		self.build_modules_info(resource_dir, app_bin_dir)
		
		# Create android source
		self.render(template_dir, 'AppInfo.java', app_package_dir, self.config['classname'] + 'AppInfo.java',
			app_properties = self.app_properties, app_info = self.app_info)
		
		self.render(template_dir, 'AndroidManifest.xml', app_dir, 'AndroidManifest.xml')
		self.render(template_dir, 'App.java', app_package_dir, self.config['classname'] + 'Application.java',
			app_modules = self.app_modules, custom_modules = self.custom_modules)
		self.render(template_dir, 'Activity.java', app_package_dir, self.config['classname'] + 'Activity.java')
		self.generate_activities(app_package_dir)
		self.generate_services(app_package_dir)
		self.render(template_dir, 'classpath', app_dir, '.classpath')
		self.render(template_dir, 'project', app_dir, '.project')
		self.render(template_dir, 'default.properties', app_dir, 'default.properties')
		# Don't override a pre-existing .gitignore in case users have their own preferences
		# for what should be in it. (LH #2446)
		if not os.path.exists(os.path.join(app_dir, '.gitignore')):
			self.render(template_dir, 'gitignore', app_dir, '.gitignore')
		else:
			print "[TRACE] Skipping copying gitignore -> .gitignore because already exists"

		android_project_resources = os.path.join(project_dir,'Resources','android')

		if build_time==False and os.path.exists(android_project_resources):
			shutil.rmtree(android_project_resources)
		
		if not os.path.exists(android_project_resources):
			copy_resources(os.path.join(template_dir,'resources'),android_project_resources)
示例#9
0
class Android(object):

	def __init__(self, name, myid, sdk, deploy_type, java):
		self.name = name
		# android requires at least one dot in packageid
		if len(re.findall(r'\.',myid))==0:
			myid = 'com.%s' % myid

		self.id = myid
		self.sdk = sdk

		# Used in templating
		self.config = {
			'appid': self.id,
			'appname' : self.name,
			'appversion' : '1',
			'apiversion' : '7', #Android 2.1
			'deploy_type': deploy_type
		}
		self.config['classname'] = Android.strip_classname(self.name)
		self.deploy_type = deploy_type
		self.java = java
	
	@classmethod
	def strip_classname(cls, name):
		classname = ''.join([str.capitalize() for str in re.split('[^A-Za-z0-9_]', name)])
		if re.search("^[0-9]", classname) != None:
			classname = "_" + classname
		return classname
		
	def newdir(self, *segments):
		path = os.path.join(*segments)
		if not os.path.exists(path):
			os.makedirs(path)
		return path

	def copyfile(self, file, src, dest):
		shutil.copy(os.path.join(src, file), os.path.join(dest, file))

	def load_template(self, template):
		return Template(filename=template, output_encoding='utf-8', encoding_errors='replace')

	def render_android_manifest(self):
		template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename)
		tmpl = self.load_template(os.path.join(template_dir, 'templates', 'AndroidManifest.xml'))
		return tmpl.render(config = self.config)

	def render(self, template_dir, template_file, dest, dest_file, **kwargs):
		tmpl = self.load_template(os.path.join(template_dir, 'templates', template_file))
		f = None
		try:
			print "[TRACE] Generating %s" % os.path.join(dest, dest_file)
			f = open(os.path.join(dest, dest_file), "w")
			f.write(tmpl.render(config = self.config, **kwargs))
		finally:
			if f!=None: f.close

	def build_app_info(self, project_dir):
		tiapp = ElementTree()
		assets_tiappxml = os.path.join(project_dir, 'build', 'android', 'bin', 'assets', 'tiapp.xml')
		
		self.app_info = {'fullscreen':'false','navbar-hidden':'false'}
		self.app_properties = {}
		if not os.path.exists(assets_tiappxml):
			shutil.copy(os.path.join(project_dir, 'tiapp.xml'), assets_tiappxml)
		
		tiapp.parse(open(assets_tiappxml, 'r'))
		for key in ['id', 'name', 'version', 'publisher', 'url', 'copyright',
			'description', 'icon', 'analytics', 'guid', 'navbar-hidden', 'fullscreen']:
			el = tiapp.find(key)
			if el != None:
				self.app_info[key] = el.text

		for property_el in tiapp.findall("property"):
			name = property_el.get("name")
			type = property_el.get("type")
			value = property_el.text
			if name == None: continue
			if type == None: type = "string"
			if value == None: value = ""
			self.app_properties[name] = {"type": type, "value": value}
	
	def generate_activities(self, app_package_dir):
		if not 'activities' in self.tiapp.android: return
		for key in self.tiapp.android['activities'].keys():
			activity = self.tiapp.android['activities'][key]
			print '[DEBUG] generating activity class: ' + activity['classname']
			
			self.render(template_dir, 'JSActivity.java', app_package_dir, activity['classname']+'.java', activity=activity)
	
	def generate_services(self, app_package_dir):
		if not 'services' in self.tiapp.android: return
		for key in self.tiapp.android['services'].keys():
			service = self.tiapp.android['services'][key]
			service_type = service['service_type']
			print '[DEBUG] generating service type "%s", class "%s"' %(service_type, service['classname'])
			if service_type == 'interval':
				self.render(template_dir, 'JSIntervalService.java', app_package_dir, service['classname']+'.java', service=service)
			else:
				self.render(template_dir, 'JSService.java', app_package_dir, service['classname']+'.java', service=service)

	def build_modules_info(self, resources_dir, app_bin_dir, include_all_ti_modules=False):
		self.app_modules = []
		(modules, external_child_modules) = bindings.get_all_module_bindings()
		
		compiler = Compiler(self.tiapp, resources_dir, self.java, app_bin_dir, os.path.dirname(app_bin_dir),
				include_all_modules=include_all_ti_modules)
		compiler.compile(compile_bytecode=False, info_message=None)
		for module in compiler.modules:
			module_bindings = []
			# TODO: we should also detect module properties
			for method in compiler.module_methods:
				if method.lower().startswith(module+'.') and '.' not in method:
					module_bindings.append(method[len(module)+1:])

			module_onAppCreate = None
			module_class = None
			module_apiName = None
			for m in modules.keys():
				if modules[m]['fullAPIName'].lower() == module:
					module_class = m
					module_apiName = modules[m]['fullAPIName']
					if 'onAppCreate' in modules[m]:
						module_onAppCreate = modules[m]['onAppCreate']
					break
			
			if module_apiName == None: continue # module wasn't found
			ext_modules = []
			if module_class in external_child_modules:
				for child_module in external_child_modules[module_class]:
					if child_module['fullAPIName'].lower() in compiler.modules:
						ext_modules.append(child_module)
			self.app_modules.append({
				'api_name': module_apiName,
				'class_name': module_class,
				'bindings': module_bindings,
				'external_child_modules': ext_modules,
				'on_app_create': module_onAppCreate
			})
		
		# discover app modules
		detector = ModuleDetector(self.project_dir)
		missing, detected_modules = detector.find_app_modules(self.tiapp, 'android')
		for missing_module in missing: print '[WARN] Couldn\'t find app module: %s' % missing_module['id']
		
		self.custom_modules = []
		for module in detected_modules:
			if module.jar == None: continue
			module_jar = zipfile.ZipFile(module.jar)
			module_bindings = bindings.get_module_bindings(module_jar)
			if module_bindings is None: continue
			
			for module_class in module_bindings['modules'].keys():
				module_apiName = module_bindings['modules'][module_class]['apiName']
				module_proxy = module_bindings['proxies'][module_class]
				module_id = module_proxy['proxyAttrs']['id']
				module_proxy_class_name = module_proxy['proxyClassName']
				module_onAppCreate = None
				if 'onAppCreate' in module_proxy:
					module_onAppCreate = module_proxy['onAppCreate']

				print '[DEBUG] module_id = %s' % module_id
				if module_id == module.manifest.moduleid:
					# make sure that the module was not built before 1.8.0.1
					try:
						module_api_version = int(module.manifest.apiversion)
						if module_api_version < 2:
							print "[ERROR] The 'apiversion' for '%s' in the module manifest is less than version 2.  The module was likely built against a Titanium SDK pre 1.8.0.1.  Please use a version of the module that has 'apiversion' 2 or greater" % module_id
							touch_tiapp_xml(os.path.join(self.project_dir, 'tiapp.xml'))
							sys.exit(1)

					except(TypeError, ValueError):
						print "[ERROR] The 'apiversion' for '%s' in the module manifest is not a valid value.  Please use a version of the module that has an 'apiversion' value of 2 or greater set in it's manifest file" % module_id
						touch_tiapp_xml(os.path.join(self.project_dir, 'tiapp.xml'))
						sys.exit(1)
 

					print '[DEBUG] appending module: %s' % module_class
					self.custom_modules.append({
						'module_id': module_id,
						'module_apiName': module_apiName,
						'proxy_name': module_proxy_class_name,
						'class_name': module_class,
						'manifest': module.manifest,
						'on_app_create': module_onAppCreate
					})

		
	def create(self, dir, build_time=False, project_dir=None, include_all_ti_modules=False):
		template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename)
		
		# Build up output directory tree
		if project_dir is None:
			project_dir = self.newdir(dir, self.name)

		self.project_dir = project_dir
		# Paths to Titanium assets that need to be linked into eclipse structure
		self.config['ti_tiapp_xml'] = os.path.join(project_dir, 'tiapp.xml')
		self.tiapp = TiAppXML(self.config['ti_tiapp_xml'])
		resource_dir = os.path.join(project_dir, 'Resources')
		self.config['ti_resources_dir'] = resource_dir

		json_contents = open(os.path.join(template_dir,'dependency.json')).read()
		depends_map = simplejson.loads(json_contents)
		runtime = depends_map['runtimes']['defaultRuntime']
		if self.tiapp.has_app_property("ti.android.runtime"):
			requested_runtime = self.tiapp.get_app_property("ti.android.runtime")
			if requested_runtime == "rhino" or requested_runtime == "v8":
				runtime = requested_runtime
			else:
				print "[ERROR] invalid runtime \"" + requested_runtime + "\" requested, must be 'v8' or 'rhino'"
				sys.exit(1);

		app_build_dir = self.newdir(project_dir, 'build')
		app_dir = self.newdir(app_build_dir, 'android')

		#if os.path.exists(os.path.join(app_dir,'bin')):
		#	shutil.rmtree(os.path.join(app_dir,'bin'))
			
		if os.path.exists(os.path.join(app_dir,'src')):
			shutil.rmtree(os.path.join(app_dir,'src'))

		if os.path.exists(os.path.join(app_dir,'res')):
			shutil.rmtree(os.path.join(app_dir,'res'))
			
		app_bin_dir = self.newdir(app_dir, 'bin')
		app_lib_dir = self.newdir(app_dir, 'lib')
		app_src_dir = self.newdir(app_dir, 'src')
		app_res_dir = self.newdir(app_dir, 'res')
		app_gen_dir = self.newdir(app_dir, 'gen')
		app_bin_classes_dir = self.newdir(app_bin_dir, 'classes')
		
		app_res_drawable_dir = self.newdir(app_res_dir, 'drawable')
		app_assets_dir = self.newdir(app_dir, 'assets')
		app_package_dir = self.newdir(app_gen_dir, *self.id.split('.'))
		app_bin_assets_dir = self.newdir(app_bin_dir, 'assets')
		
		self.build_app_info(project_dir)
		self.build_modules_info(resource_dir, app_bin_dir, include_all_ti_modules=include_all_ti_modules)
		
		# Create android source
		self.render(template_dir, 'AppInfo.java', app_package_dir, self.config['classname'] + 'AppInfo.java',
			app_properties = self.app_properties, app_info = self.app_info)
		
		self.render(template_dir, 'AndroidManifest.xml', app_dir, 'AndroidManifest.xml')
		self.render(template_dir, 'App.java', app_package_dir, self.config['classname'] + 'Application.java',
			app_modules = self.app_modules, custom_modules = self.custom_modules, runtime = runtime)
		self.render(template_dir, 'Activity.java', app_package_dir, self.config['classname'] + 'Activity.java')
		self.generate_activities(app_package_dir)
		self.generate_services(app_package_dir)
		self.render(template_dir, 'classpath', app_dir, '.classpath')
		self.render(template_dir, 'project', app_dir, '.project')
		self.render(template_dir, 'default.properties', app_dir, 'default.properties')
		print "[TRACE] Generating app.json"
		f = None
		try:
			f = open(os.path.join(app_bin_assets_dir, "app.json"), "w")
			f.write(simplejson.dumps({"app_modules":self.app_modules}))
		finally:
			if f is not None:
				f.close()
		# Don't override a pre-existing .gitignore in case users have their own preferences
		# for what should be in it. (LH #2446)
		if not os.path.exists(os.path.join(app_dir, '.gitignore')):
			self.render(template_dir, 'gitignore', app_dir, '.gitignore')
		else:
			print "[TRACE] Skipping copying gitignore -> .gitignore because already exists"

		android_project_resources = os.path.join(project_dir,'Resources','android')

		if build_time==False and os.path.exists(android_project_resources):
			shutil.rmtree(android_project_resources)
		
		if not os.path.exists(android_project_resources):
			copy_resources(os.path.join(template_dir,'resources'),android_project_resources)
示例#10
0
	def create(self, dir, build_time=False, project_dir=None, include_all_ti_modules=False):
		template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename)
		
		# Build up output directory tree
		if project_dir is None:
			project_dir = self.newdir(dir, self.name)

		self.project_dir = project_dir
		# Paths to Titanium assets that need to be linked into eclipse structure
		self.config['ti_tiapp_xml'] = os.path.join(project_dir, 'tiapp.xml')
		self.tiapp = TiAppXML(self.config['ti_tiapp_xml'])
		resource_dir = os.path.join(project_dir, 'Resources')
		self.config['ti_resources_dir'] = resource_dir

		json_contents = open(os.path.join(template_dir,'dependency.json')).read()
		depends_map = simplejson.loads(json_contents)
		runtime = depends_map['runtimes']['defaultRuntime']
		if self.tiapp.has_app_property("ti.android.runtime"):
			requested_runtime = self.tiapp.get_app_property("ti.android.runtime")
			if requested_runtime == "rhino" or requested_runtime == "v8":
				runtime = requested_runtime
			else:
				print "[ERROR] invalid runtime \"" + requested_runtime + "\" requested, must be 'v8' or 'rhino'"
				sys.exit(1);

		app_build_dir = self.newdir(project_dir, 'build')
		app_dir = self.newdir(app_build_dir, 'android')

		#if os.path.exists(os.path.join(app_dir,'bin')):
		#	shutil.rmtree(os.path.join(app_dir,'bin'))
			
		if os.path.exists(os.path.join(app_dir,'src')):
			shutil.rmtree(os.path.join(app_dir,'src'))

		if os.path.exists(os.path.join(app_dir,'res')):
			shutil.rmtree(os.path.join(app_dir,'res'))
			
		app_bin_dir = self.newdir(app_dir, 'bin')
		app_lib_dir = self.newdir(app_dir, 'lib')
		app_src_dir = self.newdir(app_dir, 'src')
		app_res_dir = self.newdir(app_dir, 'res')
		app_gen_dir = self.newdir(app_dir, 'gen')
		app_bin_classes_dir = self.newdir(app_bin_dir, 'classes')
		
		app_res_drawable_dir = self.newdir(app_res_dir, 'drawable')
		app_assets_dir = self.newdir(app_dir, 'assets')
		app_package_dir = self.newdir(app_gen_dir, *self.id.split('.'))
		app_bin_assets_dir = self.newdir(app_bin_dir, 'assets')
		
		self.build_app_info(project_dir)
		self.build_modules_info(resource_dir, app_bin_dir, include_all_ti_modules=include_all_ti_modules)
		
		# Create android source
		self.render(template_dir, 'AppInfo.java', app_package_dir, self.config['classname'] + 'AppInfo.java',
			app_properties = self.app_properties, app_info = self.app_info)
		
		self.render(template_dir, 'AndroidManifest.xml', app_dir, 'AndroidManifest.xml')
		self.render(template_dir, 'App.java', app_package_dir, self.config['classname'] + 'Application.java',
			app_modules = self.app_modules, custom_modules = self.custom_modules, runtime = runtime)
		self.render(template_dir, 'Activity.java', app_package_dir, self.config['classname'] + 'Activity.java')
		self.generate_activities(app_package_dir)
		self.generate_services(app_package_dir)
		self.render(template_dir, 'classpath', app_dir, '.classpath')
		self.render(template_dir, 'project', app_dir, '.project')
		self.render(template_dir, 'default.properties', app_dir, 'default.properties')
		print "[TRACE] Generating app.json"
		f = None
		try:
			f = open(os.path.join(app_bin_assets_dir, "app.json"), "w")
			f.write(simplejson.dumps({"app_modules":self.app_modules}))
		finally:
			if f is not None:
				f.close()
		# Don't override a pre-existing .gitignore in case users have their own preferences
		# for what should be in it. (LH #2446)
		if not os.path.exists(os.path.join(app_dir, '.gitignore')):
			self.render(template_dir, 'gitignore', app_dir, '.gitignore')
		else:
			print "[TRACE] Skipping copying gitignore -> .gitignore because already exists"

		android_project_resources = os.path.join(project_dir,'Resources','android')

		if build_time==False and os.path.exists(android_project_resources):
			shutil.rmtree(android_project_resources)
		
		if not os.path.exists(android_project_resources):
			copy_resources(os.path.join(template_dir,'resources'),android_project_resources)
示例#11
0
class Android(object):
    def __init__(self, name, myid, sdk, deploy_type, java):
        self.name = name
        # android requires at least one dot in packageid
        if len(re.findall(r"\.", myid)) == 0:
            myid = "com.%s" % myid

        self.id = myid
        self.sdk = sdk

        # Used in templating
        self.config = {
            "appid": self.id,
            "appname": self.name,
            "appversion": "1",
            "apiversion": "7",  # Android 2.1
            "deploy_type": deploy_type,
            "compile_js": False,
        }
        self.config["classname"] = Android.strip_classname(self.name)
        self.deploy_type = deploy_type
        self.java = java

    @classmethod
    def strip_classname(cls, name):
        classname = "".join([str.capitalize() for str in re.split("[^A-Za-z0-9_]", name)])
        if re.search("^[0-9]", classname) != None:
            classname = "_" + classname
        return classname

    def newdir(self, *segments):
        path = os.path.join(*segments)
        if not os.path.exists(path):
            os.makedirs(path)
        return path

    def copyfile(self, file, src, dest):
        shutil.copy(os.path.join(src, file), os.path.join(dest, file))

    def load_template(self, template):
        return Template(filename=template, output_encoding="utf-8", encoding_errors="replace")

    def render_android_manifest(self):
        template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename)
        tmpl = self.load_template(os.path.join(template_dir, "templates", "AndroidManifest.xml"))
        return tmpl.render(config=self.config)

    def render(self, template_dir, template_file, dest, dest_file, **kwargs):
        tmpl = self.load_template(os.path.join(template_dir, "templates", template_file))
        f = None
        try:
            print "[TRACE] Generating %s" % os.path.join(dest, dest_file)
            f = open(os.path.join(dest, dest_file), "w")
            f.write(tmpl.render(config=self.config, **kwargs))
        finally:
            if f != None:
                f.close

    def build_app_info(self, project_dir):
        tiapp = ElementTree()
        assets_tiappxml = os.path.join(project_dir, "build", "android", "bin", "assets", "tiapp.xml")

        self.app_info = {"fullscreen": "false", "navbar-hidden": "false"}
        self.app_properties = {}
        if not os.path.exists(assets_tiappxml):
            shutil.copy(os.path.join(project_dir, "tiapp.xml"), assets_tiappxml)

        tiapp.parse(open(assets_tiappxml, "r"))
        for key in [
            "id",
            "name",
            "version",
            "publisher",
            "url",
            "copyright",
            "description",
            "icon",
            "analytics",
            "guid",
            "navbar-hidden",
            "fullscreen",
        ]:
            el = tiapp.find(key)
            if el != None:
                self.app_info[key] = el.text

        for property_el in tiapp.findall("property"):
            name = property_el.get("name")
            type = property_el.get("type")
            value = property_el.text
            if name == None:
                continue
            if type == None:
                type = "string"
            if value == None:
                value = ""
            self.app_properties[name] = {"type": type, "value": value}

    def generate_activities(self, app_package_dir):
        if not "activities" in self.tiapp.android:
            return
        for key in self.tiapp.android["activities"].keys():
            activity = self.tiapp.android["activities"][key]
            print "[DEBUG] generating activity class: " + activity["classname"]

            self.render(
                template_dir, "JSActivity.java", app_package_dir, activity["classname"] + ".java", activity=activity
            )

    def generate_services(self, app_package_dir):
        if not "services" in self.tiapp.android:
            return
        for key in self.tiapp.android["services"].keys():
            service = self.tiapp.android["services"][key]
            service_type = service["service_type"]
            print '[DEBUG] generating service type "%s", class "%s"' % (service_type, service["classname"])
            if service_type == "interval":
                self.render(
                    template_dir,
                    "JSIntervalService.java",
                    app_package_dir,
                    service["classname"] + ".java",
                    service=service,
                )
            else:
                self.render(
                    template_dir, "JSService.java", app_package_dir, service["classname"] + ".java", service=service
                )

    def build_modules_info(self, resources_dir, app_bin_dir, include_all_ti_modules=False):
        self.app_modules = []
        (modules, external_child_modules) = bindings.get_all_module_bindings()

        compiler = Compiler(
            self.tiapp,
            resources_dir,
            self.java,
            app_bin_dir,
            None,
            os.path.dirname(app_bin_dir),
            include_all_modules=include_all_ti_modules,
        )
        compiler.compile(compile_bytecode=False, info_message=None)
        for module in compiler.modules:
            module_bindings = []
            # TODO: we should also detect module properties
            for method in compiler.module_methods:
                if method.lower().startswith(module + ".") and "." not in method:
                    module_bindings.append(method[len(module) + 1 :])

            module_onAppCreate = None
            module_class = None
            module_apiName = None
            for m in modules.keys():
                if modules[m]["fullAPIName"].lower() == module:
                    module_class = m
                    module_apiName = modules[m]["fullAPIName"]
                    if "onAppCreate" in modules[m]:
                        module_onAppCreate = modules[m]["onAppCreate"]
                    break

            if module_apiName == None:
                continue  # module wasn't found
            ext_modules = []
            if module_class in external_child_modules:
                for child_module in external_child_modules[module_class]:
                    if child_module["fullAPIName"].lower() in compiler.modules:
                        ext_modules.append(child_module)
            self.app_modules.append(
                {
                    "api_name": module_apiName,
                    "class_name": module_class,
                    "bindings": module_bindings,
                    "external_child_modules": ext_modules,
                    "on_app_create": module_onAppCreate,
                }
            )

            # discover app modules
        detector = ModuleDetector(self.project_dir)
        missing, detected_modules = detector.find_app_modules(self.tiapp, "android")
        for missing_module in missing:
            print "[WARN] Couldn't find app module: %s" % missing_module["id"]

        self.custom_modules = []
        for module in detected_modules:
            if module.jar == None:
                continue
            module_jar = zipfile.ZipFile(module.jar)
            module_bindings = bindings.get_module_bindings(module_jar)
            if module_bindings is None:
                continue

            for module_class in module_bindings["modules"].keys():
                module_apiName = module_bindings["modules"][module_class]["apiName"]
                module_proxy = module_bindings["proxies"][module_class]
                module_id = module_proxy["proxyAttrs"]["id"]
                module_proxy_class_name = module_proxy["proxyClassName"]
                module_onAppCreate = None
                if "onAppCreate" in module_proxy:
                    module_onAppCreate = module_proxy["onAppCreate"]

                print "[DEBUG] module_id = %s" % module_id
                if module_id == module.manifest.moduleid:
                    # make sure that the module was not built before 1.8.0.1
                    try:
                        module_api_version = int(module.manifest.apiversion)
                        if module_api_version < 2:
                            print "[ERROR] The 'apiversion' for '%s' in the module manifest is less than version 2.  The module was likely built against a Titanium SDK pre 1.8.0.1.  Please use a version of the module that has 'apiversion' 2 or greater" % module_id
                            touch_tiapp_xml(os.path.join(self.project_dir, "tiapp.xml"))
                            sys.exit(1)

                    except (TypeError, ValueError):
                        print "[ERROR] The 'apiversion' for '%s' in the module manifest is not a valid value.  Please use a version of the module that has an 'apiversion' value of 2 or greater set in it's manifest file" % module_id
                        touch_tiapp_xml(os.path.join(self.project_dir, "tiapp.xml"))
                        sys.exit(1)

                    is_native_js_module = hasattr(module.manifest, "commonjs") and module.manifest.commonjs
                    print "[DEBUG] appending module: %s" % module_class
                    self.custom_modules.append(
                        {
                            "module_id": module_id,
                            "module_apiName": module_apiName,
                            "proxy_name": module_proxy_class_name,
                            "class_name": module_class,
                            "manifest": module.manifest,
                            "on_app_create": module_onAppCreate,
                            "is_native_js_module": is_native_js_module,
                        }
                    )
                    if is_native_js_module:
                        # Need to look at the app modules used in this external js module
                        metadata_file = os.path.join(module.path, "metadata.json")
                        metadata = None
                        try:
                            f = open(metadata_file, "r")
                            metadata = f.read()
                        finally:
                            f.close()

                        if metadata:
                            metadata = simplejson.loads(metadata)
                            if metadata.has_key("exports"):
                                exported_module_ids = metadata["exports"]
                                already_included_module_ids = [m["api_name"].lower() for m in self.app_modules]
                                need_to_add = [m for m in exported_module_ids if m not in already_included_module_ids]
                                if need_to_add:
                                    for to_add in need_to_add:
                                        module_onAppCreate = None
                                        module_class = None
                                        module_apiName = None
                                        for m in modules.keys():
                                            if modules[m]["fullAPIName"].lower() == to_add:
                                                module_class = m
                                                module_apiName = modules[m]["fullAPIName"]
                                                if "onAppCreate" in modules[m]:
                                                    module_onAppCreate = modules[m]["onAppCreate"]
                                                break

                                        if module_apiName == None:
                                            continue  # module wasn't found
                                        ext_modules = []
                                        if module_class in external_child_modules:
                                            for child_module in external_child_modules[module_class]:
                                                if child_module["fullAPIName"].lower() in compiler.modules:
                                                    ext_modules.append(child_module)
                                        self.app_modules.append(
                                            {
                                                "api_name": module_apiName,
                                                "class_name": module_class,
                                                "bindings": [],
                                                "external_child_modules": ext_modules,
                                                "on_app_create": module_onAppCreate,
                                            }
                                        )

    def create(self, dir, build_time=False, project_dir=None, include_all_ti_modules=False):
        template_dir = os.path.dirname(sys._getframe(0).f_code.co_filename)

        # Build up output directory tree
        if project_dir is None:
            project_dir = self.newdir(dir, self.name)

        self.project_dir = project_dir
        # Paths to Titanium assets that need to be linked into eclipse structure
        self.config["ti_tiapp_xml"] = os.path.join(project_dir, "tiapp.xml")
        self.tiapp = TiAppXML(self.config["ti_tiapp_xml"])
        resource_dir = os.path.join(project_dir, "Resources")
        self.config["ti_resources_dir"] = resource_dir

        json_contents = open(os.path.join(template_dir, "dependency.json")).read()
        depends_map = simplejson.loads(json_contents)
        runtime = depends_map["runtimes"]["defaultRuntime"]
        if self.tiapp.has_app_property("ti.android.runtime"):
            requested_runtime = self.tiapp.get_app_property("ti.android.runtime")
            if requested_runtime == "rhino" or requested_runtime == "v8":
                runtime = requested_runtime
            else:
                print '[ERROR] invalid runtime "' + requested_runtime + "\" requested, must be 'v8' or 'rhino'"
                sys.exit(1)

        app_build_dir = self.newdir(project_dir, "build")
        app_dir = self.newdir(app_build_dir, "android")

        # if os.path.exists(os.path.join(app_dir,'bin')):
        # 	shutil.rmtree(os.path.join(app_dir,'bin'))

        if os.path.exists(os.path.join(app_dir, "src")):
            shutil.rmtree(os.path.join(app_dir, "src"))

        if os.path.exists(os.path.join(app_dir, "res")):
            shutil.rmtree(os.path.join(app_dir, "res"))

        app_bin_dir = self.newdir(app_dir, "bin")
        app_lib_dir = self.newdir(app_dir, "lib")
        app_src_dir = self.newdir(app_dir, "src")
        app_res_dir = self.newdir(app_dir, "res")
        app_gen_dir = self.newdir(app_dir, "gen")
        app_bin_classes_dir = self.newdir(app_bin_dir, "classes")

        app_res_drawable_dir = self.newdir(app_res_dir, "drawable")
        app_assets_dir = self.newdir(app_dir, "assets")
        app_package_dir = self.newdir(app_gen_dir, *self.id.split("."))
        app_bin_assets_dir = self.newdir(app_bin_dir, "assets")

        self.build_app_info(project_dir)
        self.build_modules_info(resource_dir, app_bin_dir, include_all_ti_modules=include_all_ti_modules)

        # Create android source
        self.render(
            template_dir,
            "AppInfo.java",
            app_package_dir,
            self.config["classname"] + "AppInfo.java",
            app_properties=self.app_properties,
            app_info=self.app_info,
        )

        self.render(template_dir, "AndroidManifest.xml", app_dir, "AndroidManifest.xml")
        self.render(
            template_dir,
            "App.java",
            app_package_dir,
            self.config["classname"] + "Application.java",
            app_modules=self.app_modules,
            custom_modules=self.custom_modules,
            runtime=runtime,
        )
        self.render(template_dir, "Activity.java", app_package_dir, self.config["classname"] + "Activity.java")
        self.generate_activities(app_package_dir)
        self.generate_services(app_package_dir)
        self.render(template_dir, "classpath", app_dir, ".classpath")
        self.render(template_dir, "project", app_dir, ".project")
        self.render(template_dir, "default.properties", app_dir, "default.properties")
        print "[TRACE] Generating app.json"
        f = None
        try:
            f = open(os.path.join(app_bin_assets_dir, "app.json"), "w")
            f.write(simplejson.dumps({"app_modules": self.app_modules}))
        finally:
            if f is not None:
                f.close()
                # Don't override a pre-existing .gitignore in case users have their own preferences
                # for what should be in it. (LH #2446)
        if not os.path.exists(os.path.join(app_dir, ".gitignore")):
            self.render(template_dir, "gitignore", app_dir, ".gitignore")
        else:
            print "[TRACE] Skipping copying gitignore -> .gitignore because already exists"

        android_project_resources = os.path.join(project_dir, "Resources", "android")

        if build_time == False and os.path.exists(android_project_resources):
            shutil.rmtree(android_project_resources)

        if not os.path.exists(android_project_resources):
            copy_resources(os.path.join(template_dir, "resources"), android_project_resources)