https://semicolon.codes/weather-app-android-studio-java/
Weather App Android Studio Java [With Project Files]
Weather App Android Studio with Project Files
This weather app is an android studio project developed using java programming language. Android studio is android app development environment offically created by google. This software provides whole set of tool kits and environment which makes the app development process more efficient , easy and reliable. This software is used by professional developer all around the work and the good part is its free of cost. So, you get to use the software which is used by pro app developers.
Short Overview on what App does:
Clima weather app is a simple weather forecast app that uses api to get json the openweather.org website. The openweather website is a weather forecast website and allows user to integrate weather apis into your app. These api requries to send parameters to get the weather data which is usually in json format. The data can be fetched using api’s given by the openwaeather website itself by which we can send parameters to get weather data. However, to get access to api. you have to sign in and request for app_key to openweather.org website.
In my case, i used longitude and latitude and city name as parameter for api to get the result from the open weather database. The app displays current temperature and weather status in image as weather forecast for specifice city. When the app starts, user will get a toast message “”fetching location” which get your current longitude and latitude data and send those params to get weather for your current area.
Things to remeber while learning this app tutorial:
Insert uses-permission to AndroidManifest.xml file to get internet, gps address and cell tower location. These permission are mandatory to the project. Hence, internet permissions allows app to use interner, access fine location allows device to use GPS location and access coarse location allows ap to use cell network location.
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
XML layout for Main Weather Activity: This activity xml file contains a textview for location name and temperature, image for weather details , image button for changing city.
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/relativeLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/weather_background" tools:context="com.londonappbrewery.climapm.WeatherController"> <TextView android:id="@+id/locationTV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:shadowColor="@android:color/background_dark" android:shadowDx="1" android:shadowDy="1" android:shadowRadius="4" android:text="@string/default_location" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/white" android:textSize="30sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.258" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/weatherSymbolIV" app:layout_constraintVertical_bias="0.572" /> <TextView android:id="@+id/tempTV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginEnd="16dp" android:layout_marginLeft="8dp" android:layout_marginRight="16dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:shadowColor="@color/black" android:text="@string/default_temp" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/white" android:textSize="50sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.948" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.201" /> <ImageButton android:id="@+id/changeCityButton" android:layout_width="40dp" android:layout_height="60dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:layout_marginTop="20dp" android:background="@null" android:contentDescription="@string/change_city_description" android:scaleType="fitCenter" android:src="@drawable/change_city_symbol_small" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ImageView android:id="@+id/weatherSymbolIV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" android:contentDescription="@string/weather_description" android:src="@drawable/dunno" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.473" /> <ImageButton android:id="@+id/refresh" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginLeft="16dp" android:layout_marginStart="16dp" android:layout_marginTop="28dp" android:background="@android:color/transparent" android:scaleType="fitCenter" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/cloud_refresh" /> </android.support.constraint.ConstraintLayout>
XML Layout for Change City Activity: An edittext where you type city name and it will intent to main class.
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/relativeLayout2" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/city_background" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <ImageButton android:id="@+id/backButton" android:layout_width="30dp" android:layout_height="50dp" android:background="@null" android:contentDescription="@string/back_button_description" android:scaleType="fitCenter" android:src="@drawable/left" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/queryET" android:layout_width="match_parent" android:layout_height="50dp" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" android:background="@color/white" android:gravity="center_vertical|center_horizontal" android:hint="@string/default_query" android:imeOptions="actionGo" android:inputType="textAutoCorrect" android:textColor="@color/black" android:textSize="24sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.541" /> <TextView android:id="@+id/getWeatherTV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:shadowColor="@android:color/background_dark" android:shadowDx="1" android:shadowDy="1" android:shadowRadius="4" android:text="@string/get_weather" android:textAppearance="@style/TextAppearance.AppCompat" android:textColor="@color/white" android:textSize="36sp" app:layout_constraintBottom_toTopOf="@+id/queryET" app:layout_constraintHorizontal_bias="0.503" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.811" /> </android.support.constraint.ConstraintLayout>
Main WeatherController Activity Java Code: This activity has most of the codes and logic. The activity fetches the json data and show to the screen depending upon data.
package com.londonappbrewery.climapm; import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.JsonHttpResponseHandler; import com.loopj.android.http.RequestParams; import org.json.JSONObject; import cz.msebera.android.httpclient.Header; public class WeatherController extends AppCompatActivity // Constants: final int REQUEST_CODE = 123; final String WEATHER_URL = "http://api.openweathermap.org/data/2.5/weather"; // App ID to use OpenWeather data final String APP_ID = "passte_your_app_key/id"; // Time between location updates (5000 milliseconds or 5 seconds) final long MIN_TIME = 5000; // Distance between location updates (1000m or 1km) final float MIN_DISTANCE = 1000; // TODO: Set LOCATION_PROVIDER here: final String LOCATION_PROVIDER = LocationManager.NETWORK_PROVIDER; // Member Variables: TextView mCityLabel; ImageView mWeatherImage; TextView mTemperatureLabel; // TODO: Declare a LocationManager and a LocationListener here: LocationManager mLocationManager; LocationListener mLocationListener; @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.weather_controller_layout); // Linking the elements in the layout to Java code mCityLabel = findViewById(R.id.locationTV); mWeatherImage = findViewById(R.id.weatherSymbolIV); mTemperatureLabel = findViewById(R.id.tempTV); ImageButton changeCityButton = findViewById(R.id.changeCityButton); ImageButton refreshWeather = findViewById(R.id.refresh); // TODO: Add an OnClickListener to the changeCityButton here: changeCityButton.setOnClickListener(new View.OnClickListener() @Override public void onClick(View v) Intent changeCity = new Intent(getApplicationContext(), ChangeCityController.class); startActivity(changeCity); ); refreshWeather.setOnClickListener(new View.OnClickListener() @Override public void onClick(View v) Toast.makeText(getApplicationContext(), "Refetching..",Toast.LENGTH_LONG).show(); onResume(); ); // TODO: Add onResume() here: @Override protected void onResume() super.onResume(); Log.d("Clima","onResume() is started"); Intent cityData = getIntent(); String cityName = cityData.getStringExtra("City"); if(cityName != null) getWeatherForNewCity(cityName); else getWeatherForCurrentLocation(); // TODO: Add getWeatherForNewCity(String city) here: public void getWeatherForNewCity(String cityName) RequestParams params = new RequestParams(); params.put("q",cityName); params.put("appid",APP_ID); letsDoSomeNetworking(params); // TODO: Add getWeatherForCurrentLocation() here: private void getWeatherForCurrentLocation() Log.d("Clima","getWeatherForCurrentLocation()"); mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); mLocationListener = new LocationListener() @Override public void onLocationChanged(Location location) Log.d("Clima","onLocationChanged() is started"); String Longitude = String.valueOf(location.getLongitude()); String Latitude = String.valueOf(location.getLatitude()); Log.d("Clima","The longitude is"+ Longitude); Log.d("Clima","The latitude is"+ Latitude); RequestParams params = new RequestParams(); params.put("lat",Latitude); params.put("lon",Longitude); params.put("appid",APP_ID); letsDoSomeNetworking(params); @Override public void onStatusChanged(String provider, int status, Bundle extras) @Override public void onProviderEnabled(String provider) @Override public void onProviderDisabled(String provider) Log.d("Clima","onProviderDisabled() is called"); ; if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. ActivityCompat.requestPermissions(this, new String[]Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_CODE); return; mLocationManager.requestLocationUpdates(LOCATION_PROVIDER, MIN_TIME, MIN_DISTANCE, mLocationListener); @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode == REQUEST_CODE) grantResults[0]== PackageManager.PERMISSION_GRANTED) Log.d("Clima","Permission Granted"); getWeatherForCurrentLocation(); else Log.d("Clima","Permsission Denied"); // TODO: Add letsDoSomeNetworking(RequestParams params) here public void letsDoSomeNetworking(RequestParams params) AsyncHttpClient client = new AsyncHttpClient(); client.get(WEATHER_URL, params, new JsonHttpResponseHandler() @Override public void onSuccess(int statusCode, Header[] header, JSONObject response) Log.d("Clima","Success"+response.toString()); WeatherDataModel weatherdata = WeatherDataModel.fromJSON(response); updateUI(weatherdata); Toast.makeText(WeatherController.this, "Location Fetched", Toast.LENGTH_SHORT).show(); @Override public void onFailure(int statuscode, Header[] header, Throwable e , JSONObject response) Log.d("Clima","Status code"+statuscode); Log.d("Clima","Fail"+e.toString()); Toast.makeText(WeatherController.this, "Invalid Location", Toast.LENGTH_SHORT).show(); getWeatherForCurrentLocation(); ); // TODO: Add updateUI() here: public void updateUI(WeatherDataModel data) mTemperatureLabel.setText(data.getTemperature()); mCityLabel.setText(data.getCity()); int resourceId = getResources().getIdentifier(data.getIconName(),"drawable",getPackageName()); mWeatherImage.setImageResource(resourceId); // TODO: Add onPause() here: @Override protected void onPause() super.onPause(); if(mLocationManager != null) mLocationManager.removeUpdates(mLocationListener);
WeatherData Model Class: This activity_class get weather json data from the main activity, creates an object of json data and returns it.
package com.londonappbrewery.climapm; import org.json.JSONException; import org.json.JSONObject; public class WeatherDataModel // TODO: Declare the member variables here private String mTemperature; private int condition; private String mCity; private String mIconName; // TODO: Create a WeatherDataModel from a JSON: public static WeatherDataModel fromJSON(JSONObject jsonObject) try WeatherDataModel weatherdata = new WeatherDataModel(); weatherdata.mCity = jsonObject.getString("name"); weatherdata.condition = jsonObject.getJSONArray("weather").getJSONObject(0).getInt("id"); weatherdata.mIconName = updateWeatherIcon(weatherdata.condition); double temp = jsonObject.getJSONObject("main").getDouble("temp") - 273.15; int roundValue = (int) Math.rint(temp); weatherdata.mTemperature = (""+roundValue); return weatherdata; catch(JSONException e) e.printStackTrace(); return null; // TODO: Uncomment to this to get the weather image name from the condition: private static String updateWeatherIcon(int condition) if (condition >= 0 && condition < 300) return "tstorm1"; else if (condition >= 300 && condition < 500) return "light_rain"; else if (condition >= 500 && condition < 600) return "shower3"; else if (condition >= 600 && condition <= 700) return "snow4"; else if (condition >= 701 && condition <= 771) return "fog"; else if (condition >= 772 && condition < 800) return "tstorm3"; else if (condition == 800) return "sunny"; else if (condition >= 801 && condition <= 804) return "cloudy2"; else if (condition >= 900 && condition <= 902) return "tstorm3"; else if (condition == 903) return "snow5"; else if (condition == 904) return "sunny"; else if (condition >= 905 && condition <= 1000) return "tstorm3"; return "dunno"; // TODO: Create getter methods for temperature, city, and icon name: public String getTemperature() return mTemperature +"°C"; public String getCity() return mCity; public String getIconName() return mIconName;
Change City Controller Class:
package com.londonappbrewery.climapm; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.widget.EditText; import android.widget.ImageButton; import android.widget.TextView; public class ChangeCityController extends AppCompatActivity @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.change_city_layout); final EditText edittext = findViewById(R.id.queryET); ImageButton imageButton = findViewById(R.id.backButton); imageButton.setOnClickListener(new View.OnClickListener() @Override public void onClick(View v) finish(); ); edittext.setOnEditorActionListener(new TextView.OnEditorActionListener() @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) String city = edittext.getText().toString(); Intent goToMainActivity = new Intent(getApplicationContext(),WeatherController.class); goToMainActivity.putExtra("City",city); startActivity(goToMainActivity); return false; );
Basically, this is a simple weather app which you can use your self or use it as a project. So, you also can download the project source files from link down below of you want to take a look at the project.
Please follow and like us: