Packages
mob_dev
0.5.7
0.6.23
0.6.22
0.6.21
0.6.20
0.6.19
0.6.18
0.6.17
0.6.16
0.6.15
0.6.14
0.6.13
0.6.12
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.17
0.5.16
0.5.15
0.5.14
0.5.13
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.0
0.3.37
0.3.35
0.3.34
0.3.33
0.3.28
0.3.26
0.3.23
0.3.21
0.3.19
0.3.18
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.18
0.2.17
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
Development tooling for the Mob mobile framework
Current section
Files
Jump to
Current section
Files
lib/mob_dev/config.ex
defmodule MobDev.Config do
@moduledoc false
# Shared config helpers used across deployer, connector, native_build, and
# battery bench tasks.
@doc """
Returns the app's bundle ID / Android package name.
Resolution order:
1. `mob.exs` — `config :mob_dev, bundle_id: "..."` (opt-in override;
not required — projects work fine without it)
2. `ios/Info.plist` — `CFBundleIdentifier`
3. `android/app/build.gradle` — `applicationId`
4. Generated default: `"<MOB_BUNDLE_PREFIX or com.example>.<app_name>"`
The four-level fallback exists so cross-platform tasks (e.g. `mix mob.deploy`)
always have a value to work with, regardless of which platform's manifest is
authoritative for the project. For most users, the value resolved at step 2
or 3 is what `mix mob.new` wrote there at generation time; mob.exs is
reserved for explicit overrides.
"""
@spec bundle_id() :: String.t()
def bundle_id do
load_mob_config()[:bundle_id] ||
detect_from_ios_plist() ||
detect_from_android_gradle() ||
"#{bundle_prefix()}.#{app_name()}"
end
@doc """
Default reverse-DNS prefix when no platform manifest is available.
Honors `MOB_BUNDLE_PREFIX` so users with a corporate prefix can set
it once. Mirrors `MobNew.ProjectGenerator.bundle_prefix/0` so the
generator's default and the runtime fallback agree.
Also used by `mix mob.uninstall --all-apps` to compute the prefix
match (e.g. uninstall every `com.example.*` package on a device).
"""
@spec bundle_prefix() :: String.t()
def bundle_prefix do
case System.get_env("MOB_BUNDLE_PREFIX") do
nil -> "com.example"
"" -> "com.example"
raw -> String.trim(raw)
end
end
@doc """
Reads the `mob_dev` section from `mob.exs` in the current directory.
Returns an empty keyword list if the file does not exist.
"""
@spec load_mob_config() :: keyword()
def load_mob_config do
config_file = Path.join(File.cwd!(), "mob.exs")
if File.exists?(config_file),
do: Config.Reader.read!(config_file) |> Keyword.get(:mob_dev, []),
else: []
end
# ── Private ──────────────────────────────────────────────────────────────────
defp detect_from_ios_plist do
plist = Path.join([File.cwd!(), "ios", "Info.plist"])
with true <- File.exists?(plist),
{:ok, content} <- File.read(plist),
[_, id] <-
Regex.run(
Regex.compile!("<key>CFBundleIdentifier</key>\\s*<string>([^<]+)</string>"),
content
) do
id
else
_ -> nil
end
end
defp detect_from_android_gradle do
gradle = Path.join([File.cwd!(), "android", "app", "build.gradle"])
with true <- File.exists?(gradle),
{:ok, content} <- File.read(gradle),
match when match != nil <-
Regex.run(Regex.compile!("applicationId\\s+[\"']([^\"']+)[\"']"), content) ||
Regex.run(Regex.compile!("applicationId\\s*=\\s*[\"']([^\"']+)[\"']"), content) do
Enum.at(match, 1)
else
_ -> nil
end
end
defp app_name, do: Mix.Project.config()[:app] |> to_string()
end