Class: Mysigner::Build::AndroidParser

Inherits:
Object
  • Object
show all
Defined in:
lib/mysigner/build/android_parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_info) ⇒ AndroidParser

Returns a new instance of AndroidParser.



8
9
10
11
12
# File 'lib/mysigner/build/android_parser.rb', line 8

def initialize(project_info)
  @project_info = project_info
  @gradle_content = read_gradle_file
  @manifest_content = read_manifest_file
end

Instance Attribute Details

#project_infoObject (readonly)

Returns the value of attribute project_info.



6
7
8
# File 'lib/mysigner/build/android_parser.rb', line 6

def project_info
  @project_info
end

Instance Method Details

#aab_output_path(variant = 'release') ⇒ Object

Get AAB output path for a variant



180
181
182
183
# File 'lib/mysigner/build/android_parser.rb', line 180

def aab_output_path(variant = 'release')
  # Standard output location
  File.join(android_directory, "app/build/outputs/bundle/#{variant}/app-#{variant}.aab")
end

#android_directoryObject

Get Android directory



191
192
193
# File 'lib/mysigner/build/android_parser.rb', line 191

def android_directory
  @project_info[:android_directory] || @project_info[:path]
end

#apk_output_path(variant = 'release') ⇒ Object

Get APK output path for a variant



186
187
188
# File 'lib/mysigner/build/android_parser.rb', line 186

def apk_output_path(variant = 'release')
  File.join(android_directory, "app/build/outputs/apk/#{variant}/app-#{variant}.apk")
end

#app_nameObject

Get the app name from strings.xml or manifest



134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/mysigner/build/android_parser.rb', line 134

def app_name
  # Try strings.xml first
  strings_path = File.join(android_directory, 'app/src/main/res/values/strings.xml')
  if File.exist?(strings_path)
    content = File.read(strings_path)
    return ::Regexp.last_match(1) if content =~ %r{<string\s+name="app_name"[^>]*>([^<]+)</string>}
  end

  # Fallback to manifest label
  return ::Regexp.last_match(1) if @manifest_content && @manifest_content =~ /android:label="([^"]+)"/

  # Fallback to directory name
  File.basename(@project_info[:directory])
end

#application_idObject Also known as: package_name

Get the application ID (package name)



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/mysigner/build/android_parser.rb', line 15

def application_id
  # Try to extract from build.gradle
  app_id = extract_from_gradle('applicationId')
  return app_id if app_id

  # Try namespace (newer Gradle)
  namespace = extract_from_gradle('namespace')
  return namespace if namespace

  # Try Expo app.json (for Expo projects)
  expo_package = extract_from_expo_config
  return expo_package if expo_package

  # Fallback to AndroidManifest.xml
  extract_package_from_manifest
end

#build_typesObject

Get all build types (debug, release, etc.)



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/mysigner/build/android_parser.rb', line 60

def build_types
  types = []

  # Match buildTypes block
  if @gradle_content =~ /buildTypes\s*\{(.*?)\n\s*\}/m
    block = ::Regexp.last_match(1)
    # Find all type names (e.g., "release {" or "debug {")
    block.scan(/(\w+)\s*\{/) do |match|
      types << match[0] unless %w[debug release].include?(match[0]) && types.include?(match[0])
      types << match[0]
    end
  end

  # Default build types if none found
  types = %w[debug release] if types.empty?
  types.uniq
end

#build_variantsObject

Get available build variants (build type + flavor combinations)



166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/mysigner/build/android_parser.rb', line 166

def build_variants
  flavors = product_flavors
  types = build_types

  if flavors.empty?
    types.map { |t| t }
  else
    flavors.flat_map do |flavor|
      types.map { |type| "#{flavor}#{type.capitalize}" }
    end
  end
end

#compile_sdk_versionObject

Get compile SDK version



55
56
57
# File 'lib/mysigner/build/android_parser.rb', line 55

def compile_sdk_version
  extract_from_gradle('compileSdk') || extract_from_gradle('compileSdkVersion')
end

#gradle_commandObject

Get the gradle wrapper command



155
156
157
158
# File 'lib/mysigner/build/android_parser.rb', line 155

def gradle_command
  wrapper_path = File.join(android_directory, 'gradlew')
  File.exist?(wrapper_path) ? './gradlew' : 'gradle'
end

#gradle_wrapper_exists?Boolean

Check if gradle wrapper exists

Returns:

  • (Boolean)


161
162
163
# File 'lib/mysigner/build/android_parser.rb', line 161

def gradle_wrapper_exists?
  File.exist?(File.join(android_directory, 'gradlew'))
end

#keystore_alias(config_name = 'release') ⇒ Object

Get keystore alias from signing config



127
128
129
130
131
# File 'lib/mysigner/build/android_parser.rb', line 127

def keystore_alias(config_name = 'release')
  return ::Regexp.last_match(1).strip if @gradle_content =~ /#{config_name}\s*\{[^}]*keyAlias\s*(?:=\s*)?["']?([^"'\n]+)["']?/m

  nil
end

#keystore_path(config_name = 'release') ⇒ Object

Get keystore path from signing config



120
121
122
123
124
# File 'lib/mysigner/build/android_parser.rb', line 120

def keystore_path(config_name = 'release')
  return ::Regexp.last_match(1) if @gradle_content =~ /#{config_name}\s*\{[^}]*storeFile\s*(?:=\s*)?(?:file\()?"?([^")\n]+)"?\)?/m

  nil
end

#kotlin_dsl?Boolean

Check if project uses Kotlin DSL

Returns:

  • (Boolean)


150
151
152
# File 'lib/mysigner/build/android_parser.rb', line 150

def kotlin_dsl?
  @project_info[:app_build_gradle]&.end_with?('.kts')
end

#min_sdk_versionObject

Get minimum SDK version



45
46
47
# File 'lib/mysigner/build/android_parser.rb', line 45

def min_sdk_version
  extract_from_gradle('minSdk') || extract_from_gradle('minSdkVersion')
end

#product_flavorsObject

Get all product flavors



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/mysigner/build/android_parser.rb', line 79

def product_flavors
  flavors = []

  if @gradle_content =~ /productFlavors\s*\{(.*?)\n\s{4}\}/m
    block = ::Regexp.last_match(1)
    block.scan(/(\w+)\s*\{/) do |match|
      flavors << match[0]
    end
  end

  flavors
end

#signing_config(build_type = 'release') ⇒ Object

Get signing config for a build type



93
94
95
96
97
98
# File 'lib/mysigner/build/android_parser.rb', line 93

def signing_config(build_type = 'release')
  # Look for signingConfig in the build type block
  return ::Regexp.last_match(1) if @gradle_content =~ /#{build_type}\s*\{[^}]*signingConfig\s*(?:=\s*)?signingConfigs\.(\w+)/m

  nil
end

#signing_configsObject

Get signing configs defined in the project



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/mysigner/build/android_parser.rb', line 106

def signing_configs
  configs = []

  if @gradle_content =~ /signingConfigs\s*\{(.*?)\n\s{4}\}/m
    block = ::Regexp.last_match(1)
    block.scan(/(\w+)\s*\{/) do |match|
      configs << match[0]
    end
  end

  configs
end

#signing_configured?(build_type = 'release') ⇒ Boolean

Check if signing is configured for release builds

Returns:

  • (Boolean)


101
102
103
# File 'lib/mysigner/build/android_parser.rb', line 101

def signing_configured?(build_type = 'release')
  signing_config(build_type) != nil
end

#summaryObject

Get project summary



196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/mysigner/build/android_parser.rb', line 196

def summary
  {
    application_id: application_id,
    version_code: version_code,
    version_name: version_name,
    min_sdk: min_sdk_version,
    target_sdk: target_sdk_version,
    build_types: build_types,
    product_flavors: product_flavors,
    signing_configured: signing_configured?,
    kotlin_dsl: kotlin_dsl?,
    gradle_wrapper: gradle_wrapper_exists?
  }
end

#target_sdk_versionObject

Get target SDK version



50
51
52
# File 'lib/mysigner/build/android_parser.rb', line 50

def target_sdk_version
  extract_from_gradle('targetSdk') || extract_from_gradle('targetSdkVersion')
end

#version_codeObject

Get version code



35
36
37
# File 'lib/mysigner/build/android_parser.rb', line 35

def version_code
  extract_from_gradle('versionCode')&.to_i
end

#version_nameObject

Get version name



40
41
42
# File 'lib/mysigner/build/android_parser.rb', line 40

def version_name
  extract_from_gradle('versionName')
end