def PrintPackageInfo(options, name, packaged_archs): package_name_version = os.path.join(options.target_dir, name) if options.app_version: package_name_version += '_' + options.app_version if len(packaged_archs) == 0: print('\nA non-platform specific APK for the web application "%s" was ' 'generated successfully at:\n %s.apk.\nIt requires a shared ' 'Crosswalk Runtime to be present.' % (name, package_name_version)) return all_archs = set(AllArchitectures()) if len(packaged_archs) != len(all_archs): missed_archs = all_archs - set(packaged_archs) print('\nNote: This APK will only work on %s-based Android devices.' ' Consider building\nfor %s as well.' % (', '.join(packaged_archs), ', '.join(missed_archs))) else: print("\nApplication apk's were created for %d architectures (%s)." % (len(all_archs), (','.join(all_archs)))) print( 'If you submit this application to an application ' 'store, please submit both\npackages. Instructions ' 'for submitting multiple APKs to Google Play Store are\navailable ' 'here:') print(' https://software.intel.com/en-us/html5/articles/submitting' '-multiple-crosswalk-apk-to-google-play-store')
def PrintPackageInfo(options, name, packaged_archs): package_name_version = os.path.join(options.target_dir, name) if options.app_version: package_name_version += '_' + options.app_version if len(packaged_archs) == 0: print( 'A non-platform specific APK for the web application "%s" was ' 'generated successfully at\n%s.apk. It requires a shared Crosswalk ' 'Runtime to be present.' % (name, package_name_version)) return for arch in packaged_archs: print('An APK for the web application "%s" including the Crosswalk ' 'Runtime built for %s was generated successfully, which can be ' 'found at\n%s_%s.apk.' % (name, arch, package_name_version, arch)) all_archs = set(AllArchitectures()) if len(packaged_archs) != len(all_archs): missed_archs = all_archs - set(packaged_archs) print('\n\nWARNING: ') print('This APK will only work on %s based Android devices. Consider ' 'building for %s as well.' % (', '.join(packaged_archs), ', '.join(missed_archs))) else: print('\n\n%d APKs were created for %s devices. ' % (len(all_archs), ', '.join(all_archs))) print('Please install the one that matches the processor architecture ' 'of your device.\n\n') print( 'If you are going to submit this application to an application ' 'store, please make sure you submit both packages.\nInstructions ' 'for submitting multiple APKs to Google Play Store are available ' 'here:\nhttps://software.intel.com/en-us/html5/articles/submitting' '-multiple-crosswalk-apk-to-google-play-store')
def main(argv): parser = optparse.OptionParser() parser.add_option('-v', '--version', action='store_true', dest='version', default=False, help='The version of this python tool.') parser.add_option('--verbose', action="store_true", dest='verbose', default=False, help='Print debug messages.') info = ( 'The packaging mode of the web application. The value \'shared\' ' 'means that the runtime is shared across multiple application ' 'instances and that the runtime needs to be distributed separately. ' 'The value \'embedded\' means that the runtime is embedded into the ' 'application itself and distributed along with it.' 'Set the default mode as \'embedded\'. For example: --mode=embedded') parser.add_option('--mode', choices=('embedded', 'shared'), default='embedded', help=info) info = ( 'The target architecture of the embedded runtime. Supported values: ' '%s. If not specified, APKs for all available architectures will be ' 'generated.' % ', '.join(AllArchitectures())) parser.add_option('--arch', choices=AllArchitectures(), help=info) group = optparse.OptionGroup( parser, 'Application Source Options', 'This packaging tool supports 3 kinds of web application source: ' '1) XPK package; 2) manifest.json; 3) various command line options, ' 'for example, \'--app-url\' for website, \'--app-root\' and ' '\'--app-local-path\' for local web application.') info = ( 'The path of the XPK package. For example, --xpk=/path/to/xpk/file') group.add_option('--xpk', help=info) info = ( 'The manifest file with the detail description of the application. ' 'For example, --manifest=/path/to/your/manifest/file') group.add_option('--manifest', help=info) info = ('The url of application. ' 'This flag allows to package website as apk. For example, ' '--app-url=http://www.intel.com') group.add_option('--app-url', help=info) info = ('The root path of the web app. ' 'This flag allows to package local web app as apk. For example, ' '--app-root=/root/path/of/the/web/app') group.add_option('--app-root', help=info) info = ( 'The relative path of entry file based on the value from ' '\'app_root\'. This flag should work with \'--app-root\' together. ' 'For example, --app-local-path=/relative/path/of/entry/file') group.add_option('--app-local-path', help=info) parser.add_option_group(group) # Mandatory options group group = optparse.OptionGroup( parser, 'Mandatory arguments', 'They are used for describing the APK information through ' 'command line options.') info = ('The apk name. For example, --name="Your Application Name"') group.add_option('--name', help=info) info = ('The package name. For example, ' '--package=com.example.YourPackage') group.add_option('--package', help=info) parser.add_option_group(group) # Optional options group (alphabetical) group = optparse.OptionGroup( parser, 'Optional arguments', 'They are used for various settings for applications through ' 'command line options.') info = ('The version name of the application. ' 'For example, --app-version=1.0.0') group.add_option('--app-version', help=info) info = ('The version code of the application. ' 'For example, --app-versionCode=24') group.add_option('--app-versionCode', type='int', help=info) info = ('The version code base of the application. Version code will ' 'be made by adding a prefix based on architecture to the version ' 'code base. For example, --app-versionCodeBase=24') group.add_option('--app-versionCodeBase', type='int', help=info) info = ('The description of the application. For example, ' '--description=YourApplicationDescription') group.add_option('--description', help=info) group.add_option('--enable-remote-debugging', action='store_true', dest='enable_remote_debugging', default=False, help='Enable remote debugging.') group.add_option('--use-animatable-view', action='store_true', dest='use_animatable_view', default=False, help='Enable using animatable view (TextureView).') info = ('The list of external extension paths splitted by OS separators. ' 'The separators are \':\' , \';\' and \':\' on Linux, Windows and ' 'Mac OS respectively. For example, ' '--extensions=/path/to/extension1:/path/to/extension2.') group.add_option('--extensions', help=info) group.add_option('-f', '--fullscreen', action='store_true', dest='fullscreen', default=False, help='Make application fullscreen.') group.add_option('--keep-screen-on', action='store_true', default=False, help='Support keeping screen on') info = ('The path of application icon. ' 'Such as: --icon=/path/to/your/customized/icon') group.add_option('--icon', help=info) info = ('The orientation of the web app\'s display on the device. ' 'For example, --orientation=landscape. The default value is ' '\'unspecified\'. The permitted values are from Android: ' 'http://developer.android.com/guide/topics/manifest/' 'activity-element.html#screen') group.add_option('--orientation', help=info) info = ( 'The list of permissions to be used by web application. For example, ' '--permissions=geolocation:webgl') group.add_option('--permissions', help=info) info = ( 'Create an Android project directory with Crosswalk at this location.' ' (See project-only option below)') group.add_option('--project-dir', help=info) info = ('Must be used with project-dir option. Create an Android project ' 'directory with Crosswalk but do not build the APK package') group.add_option('--project-only', action='store_true', default=False, dest='project_only', help=info) info = ('Packaging tool will move the output APKs to the target directory') group.add_option('--target-dir', default=os.getcwd(), help=info) info = ( 'Use command lines.' 'Crosswalk is powered by Chromium and supports Chromium command line.' 'For example, ' '--xwalk-command-line=\'--chromium-command-1 --xwalk-command-2\'') group.add_option('--xwalk-command-line', default='', help=info) parser.add_option_group(group) # Keystore options group group = optparse.OptionGroup( parser, 'Keystore Options', 'The keystore is a signature from web developer, it\'s used when ' 'developer wants to distribute the applications.') info = ('The path to the developer keystore. For example, ' '--keystore-path=/path/to/your/developer/keystore') group.add_option('--keystore-path', help=info) info = ('The alias name of keystore. For example, --keystore-alias=name') group.add_option('--keystore-alias', help=info) info = ('The passcode of keystore. For example, --keystore-passcode=code') group.add_option('--keystore-passcode', help=info) info = ('Passcode for alias\'s private key in the keystore, ' 'For example, --keystore-alias-passcode=alias-code') group.add_option('--keystore-alias-passcode', help=info) info = ('Minify and obfuscate javascript and css.' '--compressor: compress javascript and css.' '--compressor=js: compress javascript.' '--compressor=css: compress css.') group.add_option('--compressor', dest='compressor', action='callback', callback=ParseParameterForCompressor, type='string', nargs=0, help=info) parser.add_option_group(group) options, _ = parser.parse_args() if len(argv) == 1: parser.print_help() return 0 if options.version: if os.path.isfile('VERSION'): print(GetVersion('VERSION')) return 0 else: parser.error( 'VERSION was not found, so Crosswalk\'s version could not ' 'be determined.') xpk_temp_dir = '' if options.xpk: xpk_name = os.path.splitext(os.path.basename(options.xpk))[0] xpk_temp_dir = tempfile.mkdtemp(prefix="%s-" % xpk_name + '_xpk') CleanDir(xpk_temp_dir) ParseXPK(options, xpk_temp_dir) if options.manifest: options.manifest = os.path.abspath(options.manifest) if not os.path.isfile(options.manifest): print('Error: The manifest file does not exist.') sys.exit(8) if options.app_root and not options.manifest: manifest_path = os.path.join(options.app_root, 'manifest.json') if os.path.exists(manifest_path): print('Using manifest.json distributed with the application.') options.manifest = manifest_path app_info = AppInfo() manifest = None if not options.manifest: # The checks here are really convoluted, but at the moment make_apk # misbehaves any of the following conditions is true. if options.app_url: # 1) --app-url must be passed without either --app-local-path or # --app-root. if options.app_root or options.app_local_path: parser.error( 'You must pass either "--app-url" or "--app-local-path" ' 'with "--app-root", but not all.') else: # 2) --app-url is not passed but only one of --app-local-path and # --app-root is set. if bool(options.app_root) != bool(options.app_local_path): parser.error('You must specify both "--app-local-path" and ' '"--app-root".') # 3) None of --app-url, --app-local-path and --app-root are passed. elif not options.app_root and not options.app_local_path: parser.error( 'You must pass either "--app-url" or "--app-local-path" ' 'with "--app-root".') if options.permissions: permission_list = options.permissions.split(':') else: print( 'Warning: all supported permissions on Android port are added. ' 'Refer to https://github.com/crosswalk-project/' 'crosswalk-website/wiki/Crosswalk-manifest') permission_list = permission_mapping_table.keys() options.permissions = HandlePermissionList(permission_list) options.icon_dict = {} else: try: manifest = ParseManifest(options) except SystemExit as ec: return ec.code if not options.name: parser.error( 'An APK name is required. Please use the "--name" option.') if not options.package: parser.error('A package name is required. Please use the "--package" ' 'option.') VerifyPackageName(options.package) if (options.app_root and options.app_local_path and not os.path.isfile( os.path.join(options.app_root, options.app_local_path))): print('Please make sure that the local path file of launching app ' 'does exist.') sys.exit(7) if options.target_dir: target_dir = os.path.abspath(os.path.expanduser(options.target_dir)) options.target_dir = target_dir if not os.path.isdir(target_dir): os.makedirs(target_dir) if options.project_only and not options.project_dir: print('\nmake_apk.py error: Option --project-only must be used ' 'with --project-dir') sys.exit(8) try: MakeApk(options, app_info, manifest) except SystemExit as ec: return ec.code finally: CleanDir(GetBuildDir(app_info.android_name)) CleanDir(xpk_temp_dir) return 0
def MakeApk(options, app_info, manifest): CheckSystemRequirements() Customize(options, app_info, manifest) name = app_info.android_name app_dir = GetBuildDir(name) packaged_archs = [] if options.mode == 'shared': # Copy xwalk_shared_library into app folder target_library_path = os.path.join(app_dir, SHARED_LIBRARY) shutil.copytree(os.path.join(xwalk_dir, SHARED_LIBRARY), target_library_path) Execution(options, app_info) elif options.mode == 'embedded': # Copy xwalk_core_library into app folder and move the native libraries # out. # When making apk for specified CPU arch, will only include the # corresponding native library by copying it back into xwalk_core_library. target_library_path = os.path.join(app_dir, EMBEDDED_LIBRARY) shutil.copytree(os.path.join(xwalk_dir, EMBEDDED_LIBRARY), target_library_path) library_lib_path = os.path.join(target_library_path, 'libs') native_lib_path = os.path.join(app_dir, 'native_libs') os.makedirs(native_lib_path) available_archs = [] for dir_name in os.listdir(library_lib_path): lib_dir = os.path.join(library_lib_path, dir_name) if ContainsNativeLibrary(lib_dir): shutil.move(lib_dir, os.path.join(native_lib_path, dir_name)) available_archs.append(dir_name) if options.arch: Execution(options, app_info) packaged_archs.append(options.arch) else: # If the arch option is unspecified, all of available platform APKs # will be generated. for arch in AllArchitectures(): if ConvertArchNameToArchFolder(arch) in available_archs: options.arch = arch Execution(options, app_info) packaged_archs.append(options.arch) else: print('Warning: failed to create package for arch "%s" ' 'due to missing native library' % arch) if len(packaged_archs) == 0: print('No packages created, aborting') sys.exit(13) # if project_dir, save build directory if options.project_dir: print('\nCreating project directory') save_dir = os.path.join(options.project_dir, name) if CreateAndCopyDir(app_dir, save_dir, True): print(' A project directory was created successfully in:\n %s' % os.path.abspath(save_dir)) print(' To manually generate an APK, run the following in that ' 'directory:') print(' ant release -f build.xml') print(' For more information, see:\n' ' http://developer.android.com/tools/building/' 'building-cmdline.html') else: print( 'Error: Unable to create a project directory during the build. ' 'Please check the directory passed in --project-dir, ' 'available disk space, and write permission.') if not options.project_only: PrintPackageInfo(options, name, packaged_archs)