Skip to content

Commit d21717e

Browse files
feat(weather): Add smart weather app launcher
This commit introduces a new function, `openFirstWeatherApp()`, to intelligently find and launch a weather application. The function attempts to locate a weather app using the following prioritized methods: 1. Searches for a list of known, popular weather app package names. 2. Tries a generic `weather://` intent to find any app that handles it. 3. Scans all installed applications for "weather" in their names. If no installed weather app is found, it falls back to opening `weather.com` in a web browser. The URL includes the user's saved coordinates and preferred temperature unit (`C` or `F`) to provide a localized forecast. Extensive logging has been added to trace the discovery process.
1 parent 09ace13 commit d21717e

File tree

1 file changed

+110
-0
lines changed
  • app/src/main/java/com/github/droidworksstudio/mlauncher/helper

1 file changed

+110
-0
lines changed

app/src/main/java/com/github/droidworksstudio/mlauncher/helper/SystemUtils.kt

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,116 @@ fun sortMessages(messages: List<Message>): List<Message> {
497497
)
498498
}
499499

500+
fun Context.openFirstWeatherApp() {
501+
val pm = this.packageManager
502+
AppLogger.d("WeatherAppLauncher", "Starting search for weather apps...")
503+
504+
// --- Option 1: Known weather apps ---
505+
val knownWeatherPackages = listOf(
506+
"com.accuweather.android", // AccuWeather
507+
"com.weather.Weather", // The Weather Channel
508+
"com.windyty.android", // Windy.com
509+
"co.windyapp.android", // Windy.app
510+
"com.aws.android", // WeatherBug
511+
"com.wunderground.android.weather", // Weather Underground
512+
"com.handmark.expressweather", // 1Weather
513+
"net.darksky.darksky", // Dark Sky (if still installed)
514+
"com.luckycatlabs.sunrisesunset", // (example: some weather apps embed this)
515+
"de.mdiener.rain.usa", // Rain Alarm (example)
516+
"com.noaa.weather", // Hypothetical NOAA-based app
517+
"com.yahoo.mobile.client.android.weather", // Yahoo Weather
518+
"org.breezyweather" // Breezy Weather
519+
)
520+
521+
val installedKnownApps = knownWeatherPackages.filter {
522+
try {
523+
pm.getPackageInfo(it, 0)
524+
AppLogger.d("WeatherAppLauncher", "Found known weather app: $it")
525+
true
526+
} catch (_: PackageManager.NameNotFoundException) {
527+
false
528+
}
529+
}
530+
531+
if (installedKnownApps.isNotEmpty()) {
532+
val intent = pm.getLaunchIntentForPackage(installedKnownApps.first())
533+
if (intent != null) {
534+
AppLogger.d("WeatherAppLauncher", "Launching known weather app: ${installedKnownApps.first()}")
535+
this.startActivity(intent)
536+
return
537+
} else {
538+
AppLogger.d("WeatherAppLauncher", "Launch intent null for: ${installedKnownApps.first()}")
539+
}
540+
} else {
541+
AppLogger.d("WeatherAppLauncher", "No known weather apps installed.")
542+
}
543+
544+
// --- Option 2: Try generic weather intent (rarely works) ---
545+
val genericIntent = Intent(Intent.ACTION_VIEW, "weather://".toUri())
546+
val resolvedApps = pm.queryIntentActivities(genericIntent, PackageManager.MATCH_DEFAULT_ONLY)
547+
if (resolvedApps.isNotEmpty()) {
548+
val packageName = resolvedApps.first().activityInfo.packageName
549+
val intent = pm.getLaunchIntentForPackage(packageName)
550+
if (intent != null) {
551+
AppLogger.d("WeatherAppLauncher", "Launching app via generic weather intent: $packageName")
552+
this.startActivity(intent)
553+
return
554+
} else {
555+
AppLogger.d("WeatherAppLauncher", "Launch intent null for generic weather app: $packageName")
556+
}
557+
} else {
558+
AppLogger.d("WeatherAppLauncher", "No apps found via generic weather intent.")
559+
}
560+
561+
// --- Option 3: Scan all installed apps for "weather" in name ---
562+
val weatherAppsByName = pm.getInstalledApplications(PackageManager.GET_META_DATA)
563+
.filter { app ->
564+
val name = pm.getApplicationLabel(app).toString().lowercase()
565+
val containsWeather = name.contains("weather")
566+
if (containsWeather) AppLogger.d("WeatherAppLauncher", "Found app by name: ${app.packageName} ($name)")
567+
containsWeather
568+
}
569+
570+
if (weatherAppsByName.isNotEmpty()) {
571+
val intent = pm.getLaunchIntentForPackage(weatherAppsByName.first().packageName)
572+
if (intent != null) {
573+
AppLogger.d("WeatherAppLauncher", "Launching first app found by name: ${weatherAppsByName.first().packageName}")
574+
this.startActivity(intent)
575+
return
576+
} else {
577+
AppLogger.d("WeatherAppLauncher", "Launch intent null for: ${weatherAppsByName.first().packageName}")
578+
}
579+
} else {
580+
AppLogger.d("WeatherAppLauncher", "No apps found by name containing 'weather'.")
581+
}
582+
583+
val prefs = Prefs(this)
584+
585+
// --- Fallback if no weather app is found ---
586+
val coords = prefs.loadLocation()
587+
if (coords != null) {
588+
val (lat, lon) = coords
589+
590+
// Use prefs.tempUnit to determine unit parameter for weather.com
591+
val unitParam = when (prefs.tempUnit) {
592+
Constants.TempUnits.Celsius -> "c" // Metric
593+
Constants.TempUnits.Fahrenheit -> "f" // Fahrenheit
594+
}
595+
596+
// Construct the URL with lat/lon and unit
597+
val url = "https://weather.com/weather/today/l/$lat,$lon?unit=$unitParam"
598+
599+
// Open in browser
600+
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
601+
this.startActivity(intent)
602+
603+
AppLogger.d("WeatherAppLauncher", "Opened weather.com for coordinates: $lat,$lon with unit: $unitParam")
604+
} else {
605+
AppLogger.d("WeatherAppLauncher", "No coordinates found in prefs.")
606+
}
607+
608+
}
609+
500610

501611
fun formatLongToCalendar(longTimestamp: Long): String {
502612
// Create a Calendar instance and set its time to the given timestamp (in milliseconds)

0 commit comments

Comments
 (0)