diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1780484..7fd9275 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -15,6 +15,12 @@
android:supportsRtl="true"
android:theme="@style/Theme.AirQuality"
tools:targetApi="31">
+
+
diff --git a/app/src/main/java/com/example/airquality/DetailsActivity.java b/app/src/main/java/com/example/airquality/DetailsActivity.java
index 8a846e8..f13f711 100644
--- a/app/src/main/java/com/example/airquality/DetailsActivity.java
+++ b/app/src/main/java/com/example/airquality/DetailsActivity.java
@@ -5,12 +5,6 @@ import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
-import androidx.activity.EdgeToEdge;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.graphics.Insets;
-import androidx.core.view.ViewCompat;
-import androidx.core.view.WindowInsetsCompat;
-
import com.android.volley.RequestQueue;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.Volley;
@@ -18,16 +12,10 @@ import com.bumptech.glide.Glide;
import com.example.airquality.api.ForecastAPIRequest;
import com.example.airquality.databinding.ActivityDetailsBinding;
import com.example.airquality.types.City;
-import com.example.airquality.types.FormattedTemp;
+import com.example.airquality.types.FormattedTemperature;
import com.example.airquality.types.Weather3h;
import com.example.airquality.utils.PreferencesManager;
import com.example.airquality.utils.ToolbarCompatActivity;
-import com.example.airquality.utils.Weather3hAdapter;
-import com.example.airquality.utils.Weather3hParser;
-
-import org.json.JSONObject;
-
-import java.util.Arrays;
public class DetailsActivity extends ToolbarCompatActivity {
@@ -54,7 +42,7 @@ public class DetailsActivity extends ToolbarCompatActivity {
}
protected void updateData() {
- FormattedTemp formattedTemp = weather3h.formattedTemp(this);
+ FormattedTemperature formattedTemperature = weather3h.formattedTemp(this);
if(checkInternet())
{
@@ -70,10 +58,10 @@ public class DetailsActivity extends ToolbarCompatActivity {
binding.iconCode.setText(weather3h.getIconCode());
}
- binding.cityText.setText(city.name);
+ binding.cityText.setText(city.toString());
binding.datetimeText.setText(weather3h.getDateTime());
- binding.tempWeatherText.setText(formattedTemp.tempText + " | " + weather3h.getDescription());
- binding.tempText.setText(formattedTemp.tempMinText + " ~ " + formattedTemp.tempMaxText);
+ binding.tempWeatherText.setText(formattedTemperature.tempText + " | " + weather3h.getDescription());
+ binding.tempText.setText(formattedTemperature.tempMinText + " ~ " + formattedTemperature.tempMaxText);
binding.pressureText.setText(weather3h.getPressure() + " hPa");
binding.humidityText.setText(weather3h.getHumidity() + "%");
binding.windSpeedText.setText(weather3h.getWindSpeed() + " m/s");
@@ -81,6 +69,11 @@ public class DetailsActivity extends ToolbarCompatActivity {
@Override
protected void onRefreshOptionToolbar() {
+ if(!checkInternet()) {
+ Toast.makeText(this, "You can't load data from internet on offline mode", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
String units = PreferencesManager.getUnits(this);
RequestQueue queue = Volley.newRequestQueue(this);
diff --git a/app/src/main/java/com/example/airquality/FavoritesActivity.java b/app/src/main/java/com/example/airquality/FavoritesActivity.java
new file mode 100644
index 0000000..45c5485
--- /dev/null
+++ b/app/src/main/java/com/example/airquality/FavoritesActivity.java
@@ -0,0 +1,81 @@
+package com.example.airquality;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.activity.EdgeToEdge;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.graphics.Insets;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+import com.example.airquality.databinding.ActivityFavoritesBinding;
+import com.example.airquality.types.City;
+import com.example.airquality.utils.BaseCompatActivity;
+import com.example.airquality.utils.CityAdapter;
+import com.example.airquality.utils.PreferencesManager;
+import com.example.airquality.utils.Weather3hAdapter;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class FavoritesActivity extends BaseCompatActivity {
+
+ private ActivityFavoritesBinding binding;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ EdgeToEdge.enable(this);
+
+ binding = ActivityFavoritesBinding.inflate(getLayoutInflater());
+ View view = binding.getRoot();
+ setContentView(view);
+
+ binding.cityFavoriteList.setLayoutManager(new LinearLayoutManager(this));
+ }
+ public void onSearchActivityBtn(View view) {
+ Intent intent = new Intent(this, SearchCityActivity.class);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ loadFavoriteList();
+ }
+ private City[] getFavoriteList()
+ {
+ // Get from db
+ City[] cities = new City[] {
+ new City("Belgrade", "RS", 44.7866, 20.4489, "2025-07-04 12:30"),
+ new City("Novi Sad", "RS", 45.2671, 19.8335, "2025-07-03 09:15"),
+ new City("Niš", "RS", 43.3209, 21.8958, "2025-07-02 18:45"),
+ new City("Subotica", "RS", 46.1000, 19.6667, "2025-07-01 14:10"),
+ new City("Kragujevac", "RS", 44.0128, 20.9110, "2025-06-30 07:50")
+ };
+
+ return cities;
+ }
+ private void setEnteredDateTime(City city) {
+ // Search one item by city.name and change for him enteredAt to now()
+
+ }
+
+ private void loadFavoriteList() {
+ List cities = Arrays.asList(getFavoriteList());
+
+ CityAdapter adapter = new CityAdapter(this, cities) {
+ @Override
+ public void onSelectCity(City city) {
+ PreferencesManager.setCity(FavoritesActivity.this, city);
+ setEnteredDateTime(city);
+ finish();
+ }
+ };
+ binding.cityFavoriteList.setAdapter(adapter);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/airquality/MainActivity.java b/app/src/main/java/com/example/airquality/MainActivity.java
index ebeca17..ed1273b 100644
--- a/app/src/main/java/com/example/airquality/MainActivity.java
+++ b/app/src/main/java/com/example/airquality/MainActivity.java
@@ -1,23 +1,15 @@
package com.example.airquality;
-import android.content.Intent;
import android.os.Bundle;
-import android.view.MenuInflater;
-import android.widget.ListView;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.volley.Request;
import com.android.volley.RequestQueue;
-import com.android.volley.Response;
import com.android.volley.VolleyError;
-import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.example.airquality.api.ForecastAPIRequest;
import com.example.airquality.types.City;
@@ -25,30 +17,15 @@ import com.example.airquality.types.Weather3h;
import com.example.airquality.utils.PreferencesManager;
import com.example.airquality.utils.ToolbarCompatActivity;
import com.example.airquality.utils.Weather3hAdapter;
-import com.example.airquality.utils.Weather3hParser;
-
-import org.json.JSONObject;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
public class MainActivity extends ToolbarCompatActivity {
List prognoza;
private RecyclerView recyclerView;
- private static final Map cityCoordinates = new HashMap<>();
- static {
- cityCoordinates.put("Subotica", new double[]{46.1, 19.6667});
- cityCoordinates.put("Novi Sad", new double[]{45.2517, 19.8369});
- cityCoordinates.put("Beograd", new double[]{44.804, 20.4651});
- cityCoordinates.put("San Francisko", new double[]{37.7749, -122.4194});
- cityCoordinates.put("Sidnej", new double[]{-33.8679, 151.2073});
- }
-
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -61,13 +38,26 @@ public class MainActivity extends ToolbarCompatActivity {
initToolbar();
}
+ @Override
protected void onResume() {
super.onResume();
loadForecast();
}
+ private void saveOffline(Weather3h[] weathers) {
+ // Save to db
+ }
+ private Weather3h[] loadOffline() {
+ // Load from db
+ return new Weather3h[] { };
+ }
+
@Override
protected void onRefreshOptionToolbar() {
+ if(!checkInternet()) {
+ Toast.makeText(MainActivity.this, "You can't load data from internet on offline mode", Toast.LENGTH_SHORT).show();
+ return;
+ }
loadForecast(true);
}
@@ -79,10 +69,18 @@ public class MainActivity extends ToolbarCompatActivity {
int days = PreferencesManager.getDays(this);
String units = PreferencesManager.getUnits(this);
- setToolbarTitle(city.name);
if (city == null) {
- Toast.makeText(this, "Unknown city: " + city.name, Toast.LENGTH_SHORT).show();
+ Toast.makeText(this, "Unknown city", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ setToolbarTitle(city.toString());
+
+ // If no internet
+ if(!checkInternet()) {
+ displayRecycler(loadOffline(), city, days);
+ Toast.makeText(MainActivity.this, "You are on offline mode", Toast.LENGTH_SHORT).show();
return;
}
@@ -91,14 +89,12 @@ public class MainActivity extends ToolbarCompatActivity {
ForecastAPIRequest forecastAPI = new ForecastAPIRequest(this, city, units) {
@Override
public void onSuccess(Weather3h[] weatherList) {
- Weather3h[] arr = Arrays.copyOfRange(weatherList, 0, days);
- prognoza = Arrays.asList(arr);
-
- Weather3hAdapter adapter = new Weather3hAdapter(MainActivity.this, prognoza, city);
- recyclerView.setAdapter(adapter);
+ displayRecycler(weatherList, city, days);
if(isUpdated)
Toast.makeText(MainActivity.this, "List Updated!", Toast.LENGTH_SHORT).show();
+
+ saveOffline(weatherList);
}
@Override
@@ -109,4 +105,16 @@ public class MainActivity extends ToolbarCompatActivity {
queue.add(forecastAPI.getRequest());
}
+ private void displayRecycler(Weather3h[] weathers, City city, int days) {
+ if(weathers.length > 0) {
+ Weather3h[] weatherDaysRange = Arrays.copyOfRange(weathers, 0, days * 8);
+ prognoza = Arrays.asList(weatherDaysRange);
+ }
+ else {
+ prognoza.clear();
+ }
+
+ Weather3hAdapter adapter = new Weather3hAdapter(this, prognoza, city);
+ recyclerView.setAdapter(adapter);
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/airquality/SearchCityActivity.java b/app/src/main/java/com/example/airquality/SearchCityActivity.java
new file mode 100644
index 0000000..6a65788
--- /dev/null
+++ b/app/src/main/java/com/example/airquality/SearchCityActivity.java
@@ -0,0 +1,82 @@
+package com.example.airquality;
+
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.activity.EdgeToEdge;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.graphics.Insets;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+import com.android.volley.RequestQueue;
+import com.android.volley.VolleyError;
+import com.android.volley.toolbox.Volley;
+import com.example.airquality.api.CityAPIRequest;
+import com.example.airquality.databinding.ActivitySearchCityBinding;
+import com.example.airquality.types.City;
+import com.example.airquality.utils.BaseCompatActivity;
+import com.example.airquality.utils.CityAdapter;
+import com.example.airquality.utils.PreferencesManager;
+import com.example.airquality.utils.Weather3hAdapter;
+
+import java.util.Arrays;
+
+public class SearchCityActivity extends BaseCompatActivity {
+
+ private ActivitySearchCityBinding binding;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ EdgeToEdge.enable(this);
+
+ binding = ActivitySearchCityBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ binding.citySearchResult.setLayoutManager(new LinearLayoutManager(this));
+ }
+
+ public void onSearchBtn(View view) {
+ loadCities();
+ }
+
+ private void addToFavorite(City city) {
+ // Add to db
+ }
+
+ private void loadCities() {
+ String searchQuery = binding.searchEditText.getText().toString();
+
+ // If no internet
+ if(!checkInternet()) {
+ Toast.makeText(this, "You are on offline mode", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ RequestQueue queue = Volley.newRequestQueue(this);
+
+ CityAPIRequest cityAPIRequest = new CityAPIRequest(this, searchQuery) {
+ @Override
+ public void onSuccess(City[] objectList) {
+ CityAdapter adapter = new CityAdapter(SearchCityActivity.this, Arrays.asList(objectList), "Add") {
+ @Override
+ public void onSelectCity(City city) {
+ addToFavorite(city);
+ finish();
+ }
+ };
+
+ binding.citySearchResult.setAdapter(adapter);
+ }
+
+ @Override
+ public void onError(VolleyError error) {
+ Toast.makeText(SearchCityActivity.this, "Failed to load weather data", Toast.LENGTH_SHORT).show();
+ }
+ };
+
+ queue.add(cityAPIRequest.getRequest());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/airquality/SettingsActivity.java b/app/src/main/java/com/example/airquality/SettingsActivity.java
index 64dbfd3..9e4e30c 100644
--- a/app/src/main/java/com/example/airquality/SettingsActivity.java
+++ b/app/src/main/java/com/example/airquality/SettingsActivity.java
@@ -7,47 +7,35 @@ import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
-import android.widget.CheckBox;
import android.widget.RadioGroup;
import android.widget.Spinner;
+import android.widget.TextView;
-import androidx.activity.EdgeToEdge;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.graphics.Insets;
-import androidx.core.view.ViewCompat;
-import androidx.core.view.WindowInsetsCompat;
-
+import com.example.airquality.types.City;
import com.example.airquality.utils.BaseCompatActivity;
+import com.example.airquality.utils.PreferencesManager;
public class SettingsActivity extends BaseCompatActivity {
Spinner spinnerCity;
RadioGroup radioGroupDays, radioGroupUnits;
Button buttonSave;
-
- String[] cities = {"Subotica", "Novi Sad", "Beograd", "San Francisko", "Sidnej"};
+ TextView cityNameText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
- spinnerCity = findViewById(R.id.spinnerCity);
radioGroupDays = findViewById(R.id.radioGroupDays);
radioGroupUnits = findViewById(R.id.radioGroupUnits);
buttonSave = findViewById(R.id.buttonSave);
-
- // Podesi spinner
- ArrayAdapter adapter = new ArrayAdapter<>(this,
- android.R.layout.simple_spinner_item, cities);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spinnerCity.setAdapter(adapter);
+ cityNameText = findViewById(R.id.cityName);
buttonSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- String selectedCity = spinnerCity.getSelectedItem().toString();
- int days = 7; // podrazumevano
+ int days = 1; // podrazumevano
if (radioGroupDays.getCheckedRadioButtonId() == R.id.radio3days) {
days = 3;
} else if (radioGroupDays.getCheckedRadioButtonId() == R.id.radio5days) {
@@ -59,15 +47,22 @@ public class SettingsActivity extends BaseCompatActivity {
units = "imperial";
}
- SharedPreferences prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString("city", selectedCity);
- editor.putInt("days", days);
- editor.putString("units", units);
- editor.apply();
+ PreferencesManager.savePreferences(SettingsActivity.this, days, units);
finish();
}
});
}
+
+ public void onFavoriteBtn(View view) {
+ Intent intent = new Intent(this, FavoritesActivity.class);
+ startActivity(intent);
+ }
+
+ protected void onResume() {
+ super.onResume();
+
+ City currentCity = PreferencesManager.getCity(this);
+ cityNameText.setText(currentCity.toString());
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/airquality/api/CityAPIRequest.java b/app/src/main/java/com/example/airquality/api/CityAPIRequest.java
new file mode 100644
index 0000000..c9858d8
--- /dev/null
+++ b/app/src/main/java/com/example/airquality/api/CityAPIRequest.java
@@ -0,0 +1,59 @@
+package com.example.airquality.api;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+
+import com.android.volley.Request;
+import com.android.volley.Response;
+import com.android.volley.VolleyError;
+import com.android.volley.toolbox.JsonArrayRequest;
+import com.android.volley.toolbox.JsonObjectRequest;
+import com.example.airquality.types.City;
+import com.example.airquality.utils.CityParser;
+import com.example.airquality.utils.Weather3hParser;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+public class CityAPIRequest extends JsonAPIRequest {
+
+ @SuppressLint("DefaultLocale")
+ public CityAPIRequest(Context context, String query) {
+ super(context);
+ this.url = String.format(
+ "https://api.openweathermap.org/geo/1.0/direct?q=%s&limit=10&appid=%s",
+ query, getKey()
+ );
+ }
+ @Override
+ public JsonArrayRequest getRequest() {
+ return new JsonArrayRequest(
+ Request.Method.GET,
+ url,
+ null,
+ new Response.Listener() {
+ @Override
+ public void onResponse(JSONArray response) {
+ onSuccess(CityParser.parse(response));
+ }
+ },
+ new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ error.printStackTrace();
+ onError(error);
+ }
+ }
+ );
+ }
+
+ @Override
+ public void onSuccess(City[] objectList) {
+
+ }
+
+ @Override
+ public void onError(VolleyError error) {
+
+ }
+}
diff --git a/app/src/main/java/com/example/airquality/api/ForecastAPIRequest.java b/app/src/main/java/com/example/airquality/api/ForecastAPIRequest.java
index ab7dfbd..392f4d6 100644
--- a/app/src/main/java/com/example/airquality/api/ForecastAPIRequest.java
+++ b/app/src/main/java/com/example/airquality/api/ForecastAPIRequest.java
@@ -16,7 +16,7 @@ import org.json.JSONObject;
import java.util.Arrays;
-public class ForecastAPIRequest extends JsonAPIRequest {
+public class ForecastAPIRequest extends JsonAPIRequest {
@SuppressLint("DefaultLocale")
public ForecastAPIRequest(Context context, City city, String units) {
@@ -49,6 +49,6 @@ public class ForecastAPIRequest extends JsonAPIRequest {
);
}
- public void onSuccess(Weather3h[] weatherList) { }
+ public void onSuccess(Weather3h[] objectList) { }
public void onError(VolleyError error) { }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/airquality/api/JsonAPIRequest.java b/app/src/main/java/com/example/airquality/api/JsonAPIRequest.java
index 1a1e0aa..b196f25 100644
--- a/app/src/main/java/com/example/airquality/api/JsonAPIRequest.java
+++ b/app/src/main/java/com/example/airquality/api/JsonAPIRequest.java
@@ -9,12 +9,13 @@ import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.example.airquality.MainActivity;
import com.example.airquality.R;
+import com.example.airquality.types.Weather3h;
import com.example.airquality.utils.Weather3hAdapter;
import com.example.airquality.utils.Weather3hParser;
import org.json.JSONObject;
-public abstract class JsonAPIRequest {
+public abstract class JsonAPIRequest {
private Context appContext;
protected String url;
@@ -28,5 +29,8 @@ public abstract class JsonAPIRequest {
{
return this.appContext.getString(R.string.weather_api_key);
}
- public abstract JsonObjectRequest getRequest();
+ public abstract JR getRequest();
+
+ public abstract void onSuccess(T[] objectList);
+ public abstract void onError(VolleyError error);
}
diff --git a/app/src/main/java/com/example/airquality/types/City.java b/app/src/main/java/com/example/airquality/types/City.java
index 322ed8c..f5aeaae 100644
--- a/app/src/main/java/com/example/airquality/types/City.java
+++ b/app/src/main/java/com/example/airquality/types/City.java
@@ -1,15 +1,30 @@
package com.example.airquality.types;
+import androidx.annotation.NonNull;
+
import java.io.Serializable;
public class City implements Serializable {
public String name;
+ public String country;
public double latitude;
public double longitude;
+ public String lastEnteredAt;
- public City(String name, double latitude, double longitude) {
+ public City(String name, String country, double latitude, double longitude, String lastEnteredAt) {
this.name = name;
+ this.country = country;
this.latitude = latitude;
this.longitude = longitude;
+ this.lastEnteredAt = lastEnteredAt;
+ }
+ public City(String name, String country, double latitude, double longitude) {
+ this(name, country, latitude, longitude, "");
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return this.name + " (" + this.country + ")";
}
}
diff --git a/app/src/main/java/com/example/airquality/types/FormattedTemp.java b/app/src/main/java/com/example/airquality/types/FormattedTemperature.java
similarity index 72%
rename from app/src/main/java/com/example/airquality/types/FormattedTemp.java
rename to app/src/main/java/com/example/airquality/types/FormattedTemperature.java
index 613e589..af59c90 100644
--- a/app/src/main/java/com/example/airquality/types/FormattedTemp.java
+++ b/app/src/main/java/com/example/airquality/types/FormattedTemperature.java
@@ -2,18 +2,14 @@ package com.example.airquality.types;
import android.content.Context;
-import androidx.annotation.NonNull;
-
import com.example.airquality.utils.PreferencesManager;
-import java.util.Objects;
-
-public class FormattedTemp {
+public class FormattedTemperature {
public String tempText;
public String tempMinText;
public String tempMaxText;
- public FormattedTemp(Context context, double temp, double tempMin, double tempMax)
+ public FormattedTemperature(Context context, double temp, double tempMin, double tempMax)
{
String units = PreferencesManager.getUnits(context);
diff --git a/app/src/main/java/com/example/airquality/types/Weather3h.java b/app/src/main/java/com/example/airquality/types/Weather3h.java
index a4cba6b..c87d501 100644
--- a/app/src/main/java/com/example/airquality/types/Weather3h.java
+++ b/app/src/main/java/com/example/airquality/types/Weather3h.java
@@ -49,8 +49,8 @@ public class Weather3h implements Serializable {
return tempMax;
}
- public FormattedTemp formattedTemp(Context context) {
- return new FormattedTemp(context, temp, tempMin, tempMax);
+ public FormattedTemperature formattedTemp(Context context) {
+ return new FormattedTemperature(context, temp, tempMin, tempMax);
}
public int getDt() {
diff --git a/app/src/main/java/com/example/airquality/utils/BaseCompatActivity.java b/app/src/main/java/com/example/airquality/utils/BaseCompatActivity.java
index 5c76eb0..9d8da41 100644
--- a/app/src/main/java/com/example/airquality/utils/BaseCompatActivity.java
+++ b/app/src/main/java/com/example/airquality/utils/BaseCompatActivity.java
@@ -3,6 +3,7 @@ package com.example.airquality.utils;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
+import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
@@ -13,4 +14,9 @@ public class BaseCompatActivity extends AppCompatActivity {
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}
+
+ public void onBackButton(View view)
+ {
+ finish();
+ }
}
diff --git a/app/src/main/java/com/example/airquality/utils/CityAdapter.java b/app/src/main/java/com/example/airquality/utils/CityAdapter.java
new file mode 100644
index 0000000..2e65c85
--- /dev/null
+++ b/app/src/main/java/com/example/airquality/utils/CityAdapter.java
@@ -0,0 +1,74 @@
+package com.example.airquality.utils;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.example.airquality.R;
+import com.example.airquality.types.City;
+
+import java.util.List;
+
+public class CityAdapter extends RecyclerView.Adapter {
+
+ private Context context;
+ private List cityList;
+ private String applyBtnText;
+
+ public CityAdapter(Context context, List cityList) {
+ this(context, cityList, "Select");
+ }
+ public CityAdapter(Context context, List cityList, String applyBtnText) {
+ this.context = context;
+ this.cityList = cityList;
+ this.applyBtnText = applyBtnText;
+ }
+ public static class CityViewHolder extends RecyclerView.ViewHolder {
+ TextView cityName, cityCoords, lastEnteredTime;
+ Button selectBtn;
+
+ public CityViewHolder(View itemView) {
+ super(itemView);
+ cityName = itemView.findViewById(R.id.cityName);
+ cityCoords = itemView.findViewById(R.id.cityCoords);
+ selectBtn = itemView.findViewById(R.id.selectBtn);
+ lastEnteredTime = itemView.findViewById(R.id.lastEnteredTime);
+ }
+ }
+
+ @Override
+ public CityViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(context).inflate(R.layout.item_city, parent, false);
+ return new CityViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(CityViewHolder holder, int position) {
+ City item = cityList.get(position);
+ holder.cityName.setText(item.toString());
+ holder.cityCoords.setText(
+ "Long: " + String.format("%.3f", item.longitude) + ", Lat: " + String.format("%.3f", item.latitude));
+ holder.lastEnteredTime.setText(item.lastEnteredAt);
+
+ holder.selectBtn.setText(this.applyBtnText);
+
+ holder.selectBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onSelectCity(item);
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return cityList.size();
+ }
+
+ public void onSelectCity(City city) { }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/airquality/utils/CityParser.java b/app/src/main/java/com/example/airquality/utils/CityParser.java
new file mode 100644
index 0000000..cd0c6ee
--- /dev/null
+++ b/app/src/main/java/com/example/airquality/utils/CityParser.java
@@ -0,0 +1,34 @@
+package com.example.airquality.utils;
+
+import com.example.airquality.types.City;
+import com.example.airquality.types.Weather3h;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CityParser {
+ public static City[] parse(JSONArray jsonArray) {
+ List cities = new ArrayList<>();
+
+ try {
+ for(int i = 0; i < jsonArray.length(); i++) {
+ JSONObject jsonObject = jsonArray.getJSONObject(i);
+
+ String cityName = jsonObject.getString("name");
+ double lon = jsonObject.getDouble("lon");
+ double lat = jsonObject.getDouble("lat");
+ String countryName = jsonObject.getString("country");
+
+ City city = new City(cityName, countryName, lat, lon);
+ cities.add(city);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return cities.toArray(new City[0]);
+ }
+}
diff --git a/app/src/main/java/com/example/airquality/utils/PreferencesManager.java b/app/src/main/java/com/example/airquality/utils/PreferencesManager.java
index 3a11d3f..d94c489 100644
--- a/app/src/main/java/com/example/airquality/utils/PreferencesManager.java
+++ b/app/src/main/java/com/example/airquality/utils/PreferencesManager.java
@@ -11,7 +11,7 @@ public class PreferencesManager {
private static final String KEY_DAYS = "days";
private static final String KEY_UNITS = "units";
- public static void savePreferences(Context context, String city, int days, String units) {
+ public static void savePreferences(Context context, int days, String units) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(KEY_DAYS, days);
@@ -20,13 +20,28 @@ public class PreferencesManager {
}
public static City getCity(Context context) {
- // DAVID: Realizovati iz sqlite
- return new City("Subotica", 46.1, 19.6667);
+ SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+ String cityName = prefs.getString("city_name", "Subotica");
+ String country = prefs.getString("city_country", "RS");
+ double longitude = prefs.getFloat("city_longitude", 46.1f);
+ double latitude = prefs.getFloat("city_latitude", 19.6667f);
+
+ return new City(cityName, country, longitude, latitude);
+ }
+ public static void setCity(Context context, City city) {
+ SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+
+ editor.putString("city_name", city.name);
+ editor.putString("city_country", city.country);
+ editor.putFloat("city_longitude", (float)city.longitude);
+ editor.putFloat("city_latitude", (float)city.latitude);
+ editor.apply();
}
public static int getDays(Context context) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
- return prefs.getInt(KEY_DAYS, 7); // default: 7 dana
+ return prefs.getInt(KEY_DAYS, 1); // default: 1 dana
}
public static String getUnits(Context context) {
diff --git a/app/src/main/java/com/example/airquality/utils/Weather3hAdapter.java b/app/src/main/java/com/example/airquality/utils/Weather3hAdapter.java
index 1f81963..a2fb869 100644
--- a/app/src/main/java/com/example/airquality/utils/Weather3hAdapter.java
+++ b/app/src/main/java/com/example/airquality/utils/Weather3hAdapter.java
@@ -5,17 +5,14 @@ import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.BaseAdapter;
import android.widget.TextView;
-import android.widget.Toast;
import androidx.recyclerview.widget.RecyclerView;
import com.example.airquality.DetailsActivity;
-import com.example.airquality.MainActivity;
import com.example.airquality.R;
import com.example.airquality.types.City;
-import com.example.airquality.types.FormattedTemp;
+import com.example.airquality.types.FormattedTemperature;
import com.example.airquality.types.Weather3h;
import java.util.List;
@@ -31,8 +28,6 @@ public class Weather3hAdapter extends RecyclerView.Adapter
+
+
+
+
diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml
index 283b320..c8a44cf 100644
--- a/app/src/main/res/layout/activity_details.xml
+++ b/app/src/main/res/layout/activity_details.xml
@@ -17,6 +17,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/include_toolbar"
app:layout_constraintBottom_toBottomOf="parent"
+ android:background="@color/white"
android:padding="20dp"
>
@@ -57,12 +58,9 @@
>
+ android:text="City name"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_search_city.xml b/app/src/main/res/layout/activity_search_city.xml
new file mode 100644
index 0000000..f0214a8
--- /dev/null
+++ b/app/src/main/res/layout/activity_search_city.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index 98cf030..5359529 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -2,6 +2,7 @@
@@ -10,9 +11,24 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
+
+
+
+
+
+
-
- android:popupBackground="@color/green_popup"/>
+
+
+
+
-
+
+
-
-
+
-
+