Samstag, 13 September 2025

Top 5 diese Woche

Ähnliche Tutorials

Wetter App

Mit dieser Android App kannst du dir das aktuelle Wetter sowie eine Vorhersage für die nächsten sieben Tage direkt auf dein Smartphone holen. Über ein einfaches Formular gibst du den Namen deiner Stadt ein und erhältst sofort übersichtliche Wetterkarten im modernen Material-Design. Jede Tageskarte zeigt dir Temperatur, Wetterbeschreibung und ein passendes Symbol wie Sonne, Wolken oder Regen. Die App nutzt die OpenWeatherMap API, um echte Wetterdaten abzurufen, und setzt dabei auf eine klare Benutzeroberfläche mit RecyclerView und CardView.

Wir zeigen dir Schritt für Schritt, wie man diese App erstellt.

Schritt 1 Vorbereitung und Berechtigungen

Zunächst legst du ein neues Android Studio Projekt an mit Empty Activity und Kotlin. Hole dir einen OpenWeatherMap API Key unter home.openweathermap.org. Danach fügst du die Internet Berechtigung in die Manifest Datei ein damit die App Netzwerkanfragen durchführen kann.

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.weatherapp">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:label="@string/app_name"
        android:supportsRtl="true">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

Schritt 2 Gradle Abhängigkeiten

Ergänze die Modul Ebene build.gradle Datei mit folgenden Bibliotheken. OkHttp sorgt für die HTTP Anfragen. Picasso lädt die Icons. RecyclerView und Material sorgen für die UI Komponenten. CardView sorgt für MaterialCardView Unterstützung.

build.gradle (Module: app) innerhalb von dependencies

implementation "com.squareup.okhttp3:okhttp:4.12.0"
implementation "com.squareup.picasso:picasso:2.8"
implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation "com.google.android.material:material:1.12.0"
implementation "androidx.cardview:cardview:1.0.0"

Sync die Gradle Dateien nach dem Einfügen.


Schritt 3 Layout Dateien

Hier erstellst du das Hauptlayout mit einem Eingabefeld und einer RecyclerView. Danach legst du das Item Layout an das als Karte das Tageswetter darstellt.

activity_main.xml
Das Layout enthält ein TextInput Feld, einen Button und die RecyclerView für die 7 Tages Karten.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    android:background="#E3F2FD">

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Stadt eingeben">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/editCity"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </com.google.android.material.textfield.TextInputLayout>

    <Button
        android:id="@+id/buttonSearch"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Wetter anzeigen"
        android:layout_marginTop="12dp"
        android:backgroundTint="@color/purple_500"
        android:textColor="#FFFFFF"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerViewWeather"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:layout_marginTop="16dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
</LinearLayout>

item_weather.xml
Jede Karte zeigt Datum, Icon, Beschreibung und Temperatur.

<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    android:padding="12dp"
    android:backgroundTint="#FFFFFF"
    android:elevation="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center_vertical">

        <ImageView
            android:id="@+id/imageWeather"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginEnd="16dp"/>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textDate"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Datum"
                android:textStyle="bold"
                android:textSize="16sp"/>

            <TextView
                android:id="@+id/textDescription"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Wetterbeschreibung"/>
        </LinearLayout>

        <TextView
            android:id="@+id/textTemp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="20°C"
            android:textStyle="bold"
            android:textSize="18sp"/>
    </LinearLayout>
</com.google.android.material.card.MaterialCardView>

Schritt 4 Datenmodell und Adapter

Erstelle ein kleines Datenmodell für die Einträge. Der Adapter bindet die Daten an die Karten. Die Icons werden von OpenWeatherMap geliefert und mit Picasso geladen.

WeatherData.kt

package com.example.weatherapp

data class WeatherData(
    val date: String,
    val description: String,
    val temperature: Double,
    val icon: String
)

WeatherAdapter.kt
Der Adapter nimmt eine veränderbare Liste. Picasso lädt das Icon von openweathermap.

package com.example.weatherapp

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.squareup.picasso.Picasso

class WeatherAdapter(private val items: List<WeatherData>) :
    RecyclerView.Adapter<WeatherAdapter.WeatherViewHolder>() {

    class WeatherViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val textDate: TextView = view.findViewById(R.id.textDate)
        val textDescription: TextView = view.findViewById(R.id.textDescription)
        val textTemp: TextView = view.findViewById(R.id.textTemp)
        val imageWeather: ImageView = view.findViewById(R.id.imageWeather)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_weather, parent, false)
        return WeatherViewHolder(view)
    }

    override fun onBindViewHolder(holder: WeatherViewHolder, position: Int) {
        val item = items[position]
        holder.textDate.text = item.date
        holder.textDescription.text = item.description.replaceFirstChar {
            if (it.isLowerCase()) it.titlecase() else it.toString()
        }
        holder.textTemp.text = "${item.temperature.toInt()}°C"

        val iconUrl = "https://openweathermap.org/img/wn/${item.icon}@2x.png"
        Picasso.get().load(iconUrl).into(holder.imageWeather)
    }

    override fun getItemCount() = items.size
}

Schritt 5 MainActivity mit zwei API Aufrufen und Datenverarbeitung

Im folgenden Code ist die komplette Logik enthalten. Ablauf Erklärung vor dem Code Block

  1. Der Nutzer gibt eine Stadt ein und tippt auf den Button.
  2. Zuerst wird die Geocoding API aufgerufen um Latitude und Longitude zu bekommen.
  3. Anschließend wird die One Call API angefragt um aktuelle Daten und das tägliche Array zu erhalten.
  4. Die ersten sieben Tage werden extrahiert und in die Liste geschrieben.
  5. UI Updates erfolgen im Main Thread.

MainActivity.kt

package com.example.weatherapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import androidx.recyclerview.widget.RecyclerView
import okhttp3.*
import org.json.JSONArray
import org.json.JSONObject
import java.io.IOException
import java.net.URLEncoder
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList

class MainActivity : AppCompatActivity() {

    // Bitte hier deinen OpenWeatherMap API Key eintragen
    private val apiKey = "DEIN_API_KEY_HIER"
    private val client = OkHttpClient()

    private lateinit var recyclerView: RecyclerView
    private lateinit var adapter: WeatherAdapter
    private val weatherList = ArrayList<WeatherData>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val editCity: EditText = findViewById(R.id.editCity)
        val buttonSearch: Button = findViewById(R.id.buttonSearch)
        recyclerView = findViewById(R.id.recyclerViewWeather)

        adapter = WeatherAdapter(weatherList)
        recyclerView.adapter = adapter

        buttonSearch.setOnClickListener {
            val city = editCity.text.toString().trim()
            if (city.isNotEmpty()) {
                fetchCoordinates(city)
            } else {
                runOnUiThread {
                    editCity.error = "Bitte Stadt eingeben"
                }
            }
        }
    }

    // Schritt 1: Stadt in Koordinaten auflösen
    private fun fetchCoordinates(city: String) {
        val encodedCity = URLEncoder.encode(city, "UTF-8")
        val url = "http://api.openweathermap.org/geo/1.0/direct?q=$encodedCity&limit=1&appid=$apiKey"

        val request = Request.Builder().url(url).build()
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                runOnUiThread {
                    showError("Netzwerkfehler: ${e.message}")
                }
            }

            override fun onResponse(call: Call, response: Response) {
                response.use {
                    if (!response.isSuccessful) {
                        runOnUiThread {
                            showError("Fehler beim Ort suchen: ${response.message}")
                        }
                        return
                    }

                    val body = response.body?.string() ?: ""
                    val arr = JSONArray(body)
                    if (arr.length() == 0) {
                        runOnUiThread {
                            showError("Stadt nicht gefunden")
                        }
                        return
                    }

                    val obj = arr.getJSONObject(0)
                    val lat = obj.getDouble("lat")
                    val lon = obj.getDouble("lon")
                    val name = obj.optString("name", city)

                    fetchOneCall(lat, lon, name)
                }
            }
        })
    }

    // Schritt 2: One Call API aufrufen und tägliche Vorhersage parsen
    private fun fetchOneCall(lat: Double, lon: Double, cityName: String) {
        val url =
            "https://api.openweathermap.org/data/2.5/onecall?lat=$lat&lon=$lon&exclude=minutely,hourly,alerts&units=metric&appid=$apiKey&lang=de"

        val request = Request.Builder().url(url).build()
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                runOnUiThread {
                    showError("Netzwerkfehler: ${e.message}")
                }
            }

            override fun onResponse(call: Call, response: Response) {
                response.use {
                    if (!response.isSuccessful) {
                        runOnUiThread {
                            showError("Fehler beim Laden der Wetterdaten: ${response.message}")
                        }
                        return
                    }

                    val body = response.body?.string() ?: ""
                    val json = JSONObject(body)

                    val daily = json.getJSONArray("daily")
                    parseDaily(daily, cityName)
                }
            }
        })
    }

    // Schritt 3: Daily Array verarbeiten und Liste aktualisieren
    private fun parseDaily(daily: JSONArray, cityName: String) {
        val sdf = SimpleDateFormat("EEE, dd.MM.yyyy", Locale.getDefault())

        weatherList.clear()
        val count = minOf(7, daily.length())

        for (i in 0 until count) {
            val dayObj = daily.getJSONObject(i)
            val dt = dayObj.getLong("dt")
            val temp = dayObj.getJSONObject("temp").getDouble("day")
            val weatherArr = dayObj.getJSONArray("weather")
            val weatherObj = weatherArr.getJSONObject(0)
            val description = weatherObj.getString("description")
            val icon = weatherObj.getString("icon")

            val date = sdf.format(Date(dt * 1000L))
            val entry = WeatherData(date, description, temp, icon)
            weatherList.add(entry)
        }

        runOnUiThread {
            adapter.notifyDataSetChanged()
        }
    }

    // Kleine Helfer Funktion für Fehlerausgabe
    private fun showError(message: String) {
        // Einfaches Feedback im RecyclerView Kopf oder per Toast
        weatherList.clear()
        weatherList.add(WeatherData("Fehler", message, 0.0, "01d"))
        adapter.notifyDataSetChanged()
    }
}

Schritt 6 App starten und testen

Trage zunächst deinen API Key in der MainActivity in die Variable apiKey ein. Starte anschließend die App im Emulator oder direkt auf einem echten Gerät. Gib nun eine Stadt ein, zum Beispiel Frankfurt, und tippe auf Wetter anzeigen. Daraufhin erscheint eine Liste mit den täglichen Karten für sieben Tage. Die passenden Icons für Sonne, Wolken oder Regen werden automatisch geladen.

Das wars. Du hast nun eine Wetter App erstellt.

Vorheriges Tutorial

Hier etwas für dich dabei?