Hourly data grouped by day, setting location updates data
This commit is contained in:
@@ -4,15 +4,15 @@ import android.app.AlertDialog;
|
|||||||
import android.app.TabActivity;
|
import android.app.TabActivity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.location.Address;
|
import android.location.Address;
|
||||||
import android.location.Location;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.widget.ExpandableListView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import eur.one00kb.minipogodynka.adapters.DetailsAdapter;
|
import eur.one00kb.minipogodynka.adapters.DetailsAdapter;
|
||||||
@@ -21,7 +21,6 @@ import eur.one00kb.minipogodynka.weather.WeatherAPIFetcher;
|
|||||||
import eur.one00kb.minipogodynka.weather.WeatherAPIParser;
|
import eur.one00kb.minipogodynka.weather.WeatherAPIParser;
|
||||||
import eur.one00kb.minipogodynka.weather.WeatherData;
|
import eur.one00kb.minipogodynka.weather.WeatherData;
|
||||||
|
|
||||||
// TODO: Searching functionality
|
|
||||||
// TODO: Location history
|
// TODO: Location history
|
||||||
// TODO: Replace Date with Calendar, apparently it's better
|
// TODO: Replace Date with Calendar, apparently it's better
|
||||||
// TODO: Action icons
|
// TODO: Action icons
|
||||||
@@ -34,40 +33,53 @@ public class MainActivity extends TabActivity {
|
|||||||
|
|
||||||
private PreferenceHolder mPreferenceHolder;
|
private PreferenceHolder mPreferenceHolder;
|
||||||
private Address mCurrentAddress;
|
private Address mCurrentAddress;
|
||||||
private Map<Date, WeatherData> mWeatherData;
|
private Map<Date, List<WeatherData>> mWeatherData;
|
||||||
|
|
||||||
private LocationSearchView mLocationSearchView;
|
private HourlyAdapter mHourlyAdapter;
|
||||||
private ListView mHourlyView;
|
private DetailsAdapter mDetailsAdapter;
|
||||||
|
private ExpandableListView mHourlyView;
|
||||||
|
|
||||||
private AlertDialog mLocationDialog;
|
private AlertDialog mLocationSearchDialog;
|
||||||
private AlertDialog.Builder mDetailsDialogBuilder;
|
private AlertDialog mDetailsDialog;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
mPreferenceHolder = new PreferenceHolder(this);
|
mPreferenceHolder = new PreferenceHolder(this);
|
||||||
|
mHourlyAdapter = new HourlyAdapter(this);
|
||||||
|
mDetailsAdapter = new DetailsAdapter(this);
|
||||||
|
|
||||||
mLocationSearchView = (LocationSearchView)
|
mLocationSearchDialog = new AlertDialog.Builder(this)
|
||||||
getLayoutInflater().inflate(R.layout.dialog_location, null);
|
|
||||||
|
|
||||||
mLocationDialog = new AlertDialog.Builder(this)
|
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setTitle(R.string.dialog_search_title)
|
.setTitle(R.string.dialog_search_title)
|
||||||
.setView(mLocationSearchView).create();
|
.setView(getLayoutInflater().inflate(R.layout.dialog_search, null))
|
||||||
|
.create();
|
||||||
|
|
||||||
mDetailsDialogBuilder = new AlertDialog.Builder(this)
|
mDetailsDialog = new AlertDialog.Builder(this)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(android.R.string.ok, null);
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
|
.setAdapter(mDetailsAdapter, null)
|
||||||
|
.create();
|
||||||
|
|
||||||
mHourlyView = new ListView(this);
|
mHourlyView = new ExpandableListView(this);
|
||||||
mHourlyView.setOnItemClickListener((parent, view, position, id) -> {
|
mHourlyView.setAdapter(mHourlyAdapter);
|
||||||
WeatherData data = (WeatherData) mHourlyView.getItemAtPosition(position);
|
|
||||||
mDetailsDialogBuilder
|
mHourlyView.setOnChildClickListener((parent, view, groupPosition, childPosition, id) -> {
|
||||||
.setTitle(String.format("%tR, %<tA", data.date))
|
WeatherData data = (WeatherData) mHourlyAdapter.getChild(groupPosition, childPosition);
|
||||||
.setAdapter(new DetailsAdapter(this, data.getMemberInfo()), null)
|
|
||||||
.show();
|
mDetailsAdapter.clear();
|
||||||
|
|
||||||
|
for (WeatherData.MemberInfo info : data.getMemberInfo()) {
|
||||||
|
mDetailsAdapter.add(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDetailsAdapter.notifyDataSetChanged();
|
||||||
|
mDetailsDialog.setTitle(String.format("%tR, %<tA", data.date));
|
||||||
|
mDetailsDialog.show();
|
||||||
|
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
getTabHost().addTab(getTabHost().newTabSpec("hourly")
|
getTabHost().addTab(getTabHost().newTabSpec("hourly")
|
||||||
@@ -88,9 +100,9 @@ public class MainActivity extends TabActivity {
|
|||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
|
|
||||||
if (id == R.id.action_update) {
|
if (id == R.id.action_update) {
|
||||||
updateApiData();
|
fetchApiData(this::updateInfo);
|
||||||
} else if (id == R.id.action_location) {
|
} else if (id == R.id.action_location) {
|
||||||
mLocationDialog.show();
|
mLocationSearchDialog.show();
|
||||||
} else if (id == R.id.action_settings) {
|
} else if (id == R.id.action_settings) {
|
||||||
startActivity(new Intent(this, SettingsActivity.class));
|
startActivity(new Intent(this, SettingsActivity.class));
|
||||||
}
|
}
|
||||||
@@ -101,25 +113,16 @@ public class MainActivity extends TabActivity {
|
|||||||
public void setAddress(Address address) {
|
public void setAddress(Address address) {
|
||||||
mCurrentAddress = address;
|
mCurrentAddress = address;
|
||||||
setTitle(mCurrentAddress.getAddressLine(0));
|
setTitle(mCurrentAddress.getAddressLine(0));
|
||||||
}
|
mLocationSearchDialog.dismiss();
|
||||||
|
fetchApiData(this::updateInfo);
|
||||||
public void dismissLocationDialog() {
|
|
||||||
mLocationDialog.dismiss();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateInfo() {
|
private void updateInfo() {
|
||||||
Date forApiDate = Utilities.getDateOnly();
|
mHourlyAdapter.setKeysAndData(new ArrayList<>(mWeatherData.keySet()), mWeatherData);
|
||||||
ArrayList<WeatherData> forAdapter = new ArrayList<>();
|
mHourlyAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
for (int i = forApiDate.getHours(); i < 24; ++i) {
|
|
||||||
forApiDate.setHours(i);
|
|
||||||
forAdapter.add(mWeatherData.get(forApiDate));
|
|
||||||
}
|
|
||||||
|
|
||||||
mHourlyView.setAdapter(new HourlyAdapter(this, forAdapter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateApiData() {
|
private void fetchApiData(Runnable afterCallback) {
|
||||||
if (mCurrentAddress == null) {
|
if (mCurrentAddress == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -130,7 +133,7 @@ public class MainActivity extends TabActivity {
|
|||||||
String apiData = WeatherAPIFetcher.fetch(mCurrentAddress.getLatitude(),
|
String apiData = WeatherAPIFetcher.fetch(mCurrentAddress.getLatitude(),
|
||||||
mCurrentAddress.getLongitude(), mPreferenceHolder.getProvider());
|
mCurrentAddress.getLongitude(), mPreferenceHolder.getProvider());
|
||||||
mWeatherData = WeatherAPIParser.parse(apiData, mPreferenceHolder.getProvider());
|
mWeatherData = WeatherAPIParser.parse(apiData, mPreferenceHolder.getProvider());
|
||||||
runOnUiThread(this::updateInfo);
|
runOnUiThread(afterCallback);
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import android.widget.Toast;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class Utilities {
|
public class Utilities {
|
||||||
public static Date getDateOnly() {
|
public static Date getDayOnly() {
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
date.setHours(0);
|
date.setHours(0);
|
||||||
date.setMinutes(0);
|
date.setMinutes(0);
|
||||||
@@ -15,6 +15,15 @@ public class Utilities {
|
|||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Date toDayOnly(Date date) {
|
||||||
|
Date clone = (Date) date.clone();
|
||||||
|
date.setHours(0);
|
||||||
|
date.setMinutes(0);
|
||||||
|
date.setSeconds(0);
|
||||||
|
date.setTime(date.getTime() - (date.getTime() % 1000));
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
public static void quickToast(Context context, String message) {
|
public static void quickToast(Context context, String message) {
|
||||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Filter;
|
|
||||||
import android.widget.Filterable;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import eur.one00kb.minipogodynka.R;
|
|||||||
import eur.one00kb.minipogodynka.weather.WeatherData;
|
import eur.one00kb.minipogodynka.weather.WeatherData;
|
||||||
|
|
||||||
public class DetailsAdapter extends ArrayAdapter<WeatherData.MemberInfo> {
|
public class DetailsAdapter extends ArrayAdapter<WeatherData.MemberInfo> {
|
||||||
public DetailsAdapter(Context context, WeatherData.MemberInfo[] objects) {
|
public DetailsAdapter(Context context) {
|
||||||
super(context, 0, objects);
|
super(context, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,41 +1,108 @@
|
|||||||
package eur.one00kb.minipogodynka.adapters;
|
package eur.one00kb.minipogodynka.adapters;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.text.Layout;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.BaseExpandableListAdapter;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import eur.one00kb.minipogodynka.R;
|
import eur.one00kb.minipogodynka.R;
|
||||||
import eur.one00kb.minipogodynka.weather.WeatherData;
|
import eur.one00kb.minipogodynka.weather.WeatherData;
|
||||||
|
|
||||||
public class HourlyAdapter extends ArrayAdapter<WeatherData> {
|
public class HourlyAdapter extends BaseExpandableListAdapter {
|
||||||
public HourlyAdapter(Context context, List<WeatherData> objects) {
|
private Context mContext;
|
||||||
super(context, 0, objects);
|
private final List<Date> mKeys;
|
||||||
|
private final Map<Date, List<WeatherData>> mData;
|
||||||
|
|
||||||
|
public HourlyAdapter(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
mKeys = new ArrayList<>();
|
||||||
|
mData = new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeysAndData(List<Date> keys, Map<Date, List<WeatherData>> data) {
|
||||||
|
mKeys.clear();
|
||||||
|
mData.clear();
|
||||||
|
mKeys.addAll(keys);
|
||||||
|
mData.putAll(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public int getGroupCount() {
|
||||||
|
return mKeys.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildrenCount(int groupPosition) {
|
||||||
|
return mData.get(mKeys.get(groupPosition)).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getGroup(int groupPosition) {
|
||||||
|
return mKeys.get(groupPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getChild(int groupPosition, int childPosition) {
|
||||||
|
return mData.get(mKeys.get(groupPosition)).get(childPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getGroupId(int groupPosition) {
|
||||||
|
return groupPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getChildId(int groupPosition, int childPosition) {
|
||||||
|
return childPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStableIds() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_hour, parent,
|
convertView = LayoutInflater.from(mContext)
|
||||||
false);
|
.inflate(R.layout.item_group, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherData data = getItem(position);
|
((TextView) convertView).setText(String.format("%tA, %<td",
|
||||||
TextView time = convertView.findViewById(R.id.hour_time);
|
(Date) getGroup(groupPosition)));
|
||||||
TextView temperature = convertView.findViewById(R.id.hour_temp);
|
|
||||||
TextView precipitation = convertView.findViewById(R.id.hour_precp);
|
|
||||||
|
|
||||||
if (data != null) {
|
|
||||||
time.setText(String.format("%tR", data.date));
|
|
||||||
// No one cares about the decimals.
|
|
||||||
temperature.setText(String.format("%d °C", Math.round(data.temperature)));
|
|
||||||
precipitation.setText(String.format("%d %%", Math.round(data.precipitation)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_hour, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
WeatherData child = (WeatherData) getChild(groupPosition, childPosition);
|
||||||
|
|
||||||
|
((TextView) convertView.findViewById(R.id.hour_time))
|
||||||
|
.setText(String.format("%tR", child.date));
|
||||||
|
((TextView) convertView.findViewById(R.id.hour_temp))
|
||||||
|
.setText(String.format("%.0f °C", child.temperature));
|
||||||
|
((TextView) convertView.findViewById(R.id.hour_precp))
|
||||||
|
.setText(String.format("%.0f %%", child.precipitation));
|
||||||
|
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChildSelectable(int groupPosition, int childPosition) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-7
@@ -1,16 +1,12 @@
|
|||||||
package eur.one00kb.minipogodynka;
|
package eur.one00kb.minipogodynka.views;
|
||||||
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.location.Address;
|
import android.location.Address;
|
||||||
import android.location.Geocoder;
|
import android.location.Geocoder;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -24,10 +20,14 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import eur.one00kb.minipogodynka.MainActivity;
|
||||||
|
import eur.one00kb.minipogodynka.R;
|
||||||
import eur.one00kb.minipogodynka.adapters.AddressAdapter;
|
import eur.one00kb.minipogodynka.adapters.AddressAdapter;
|
||||||
|
|
||||||
// TODO: This doesn't need to have a parent. However, for some reason it screams with a bunch of
|
// TODO: This doesn't need to have a parent. However, for some reason it screams with a bunch of
|
||||||
// exceptions when you extend AutoCompleteTextView.
|
// exceptions when you extend AutoCompleteTextView.
|
||||||
|
// TODO: Make this tabbed, and add coordinates. The dialog neutral button will then be used for
|
||||||
|
// geolocating.
|
||||||
|
|
||||||
public class LocationSearchView extends LinearLayout
|
public class LocationSearchView extends LinearLayout
|
||||||
implements TextWatcher, AdapterView.OnItemClickListener {
|
implements TextWatcher, AdapterView.OnItemClickListener {
|
||||||
@@ -94,8 +94,6 @@ public class LocationSearchView extends LinearLayout
|
|||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
((MainActivity) getContext()).setAddress(mAddressAdapter.getItem(position));
|
((MainActivity) getContext()).setAddress(mAddressAdapter.getItem(position));
|
||||||
((MainActivity) getContext()).dismissLocationDialog();
|
|
||||||
|
|
||||||
AutoCompleteTextView mSearchField = findViewById(R.id.dl_search);
|
AutoCompleteTextView mSearchField = findViewById(R.id.dl_search);
|
||||||
mSearchField.setText("");
|
mSearchField.setText("");
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package eur.one00kb.minipogodynka.weather;
|
package eur.one00kb.minipogodynka.weather;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@@ -7,21 +9,26 @@ import org.json.JSONObject;
|
|||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import eur.one00kb.minipogodynka.Utilities;
|
||||||
|
|
||||||
public class WeatherAPIParser {
|
public class WeatherAPIParser {
|
||||||
|
private static final String TAG = "WeatherAPIParser";
|
||||||
private static final DateFormat OM_DATEFORMAT =
|
private static final DateFormat OM_DATEFORMAT =
|
||||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm", Locale.US);
|
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm", Locale.US);
|
||||||
private static final DateFormat MET_DATEFORMAT =
|
private static final DateFormat MET_DATEFORMAT =
|
||||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||||
|
|
||||||
public static Map<Date, WeatherData> parse(String json, String provider) {
|
public static Map<Date, List<WeatherData>> parse(String json, String provider) {
|
||||||
switch (provider) {
|
switch (provider) {
|
||||||
case "met":
|
case "met":
|
||||||
return parseMetNo(json);
|
|
||||||
case "mf":
|
case "mf":
|
||||||
return null;
|
return null;
|
||||||
case "om":
|
case "om":
|
||||||
@@ -30,8 +37,8 @@ public class WeatherAPIParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<Date, WeatherData> parseOpenMeteo(String json) {
|
public static Map<Date, List<WeatherData>> parseOpenMeteo(String json) {
|
||||||
HashMap<Date, WeatherData> hours = new HashMap<>();
|
Map<Date, List<WeatherData>> weatherDays = new LinkedHashMap<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JSONObject root = new JSONObject(json);
|
JSONObject root = new JSONObject(json);
|
||||||
@@ -47,62 +54,76 @@ public class WeatherAPIParser {
|
|||||||
JSONArray windDirections = hourly.getJSONArray("wind_direction_10m");
|
JSONArray windDirections = hourly.getJSONArray("wind_direction_10m");
|
||||||
JSONArray uvIndexes = hourly.getJSONArray("uv_index");
|
JSONArray uvIndexes = hourly.getJSONArray("uv_index");
|
||||||
|
|
||||||
for (int i = 0; i < times.length(); ++i) {
|
Date currentDay = Utilities.toDayOnly(OM_DATEFORMAT.parse(times.getString(0)));
|
||||||
WeatherData data = new WeatherData();
|
List<WeatherData> dayData = new ArrayList<>();
|
||||||
data.date = OM_DATEFORMAT.parse(times.getString(i));
|
|
||||||
data.temperature = temperatures.getDouble(i);
|
|
||||||
data.humidity = humidities.getDouble(i);
|
|
||||||
data.precipitation = precipitations.getDouble(i);
|
|
||||||
data.pressure = pressures.getDouble(i);
|
|
||||||
data.cloudCover = cloudCovers.getDouble(i);
|
|
||||||
data.windSpeed = windSpeeds.getDouble(i);
|
|
||||||
data.windDirection = windDirections.getDouble(i);
|
|
||||||
data.uvIndex = uvIndexes.getDouble(i);
|
|
||||||
|
|
||||||
hours.put(OM_DATEFORMAT.parse(times.getString(i)), data);
|
for (int i = 0; i < times.length(); ++i) {
|
||||||
|
Date day = Utilities.toDayOnly(OM_DATEFORMAT.parse(times.getString(i)));
|
||||||
|
|
||||||
|
if (day.getDay() != currentDay.getDay()) {
|
||||||
|
weatherDays.put(currentDay, dayData);
|
||||||
|
dayData = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
WeatherData hourData = new WeatherData();
|
||||||
|
hourData.date = OM_DATEFORMAT.parse(times.getString(i));
|
||||||
|
hourData.temperature = temperatures.getDouble(i);
|
||||||
|
hourData.humidity = humidities.getDouble(i);
|
||||||
|
hourData.precipitation = precipitations.getDouble(i);
|
||||||
|
hourData.pressure = pressures.getDouble(i);
|
||||||
|
hourData.cloudCover = cloudCovers.getDouble(i);
|
||||||
|
hourData.windSpeed = windSpeeds.getDouble(i);
|
||||||
|
hourData.windDirection = windDirections.getDouble(i);
|
||||||
|
hourData.uvIndex = uvIndexes.getDouble(i);
|
||||||
|
|
||||||
|
dayData.add(hourData);
|
||||||
|
currentDay = day;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
weatherDays.put(currentDay, dayData);
|
||||||
} catch (JSONException | ParseException e) {
|
} catch (JSONException | ParseException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error when parsing weather data", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hours;
|
Log.d(TAG, weatherDays.toString());
|
||||||
|
return weatherDays;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<Date, WeatherData> parseMetNo(String json) {
|
public static void parseMetNo(String json) {
|
||||||
HashMap<Date, WeatherData> hours = new HashMap<>();
|
// HashMap<Date, WeatherData> hours = new HashMap<>();
|
||||||
|
//
|
||||||
try {
|
// try {
|
||||||
JSONObject root = new JSONObject(json);
|
// JSONObject root = new JSONObject(json);
|
||||||
JSONArray timeseries = root.getJSONObject("properties")
|
// JSONArray timeseries = root.getJSONObject("properties")
|
||||||
.getJSONArray("timeseries");
|
// .getJSONArray("timeseries");
|
||||||
|
//
|
||||||
for (int i = 0; i < timeseries.length(); ++i) {
|
// for (int i = 0; i < timeseries.length(); ++i) {
|
||||||
JSONObject obj = timeseries.getJSONObject(i);
|
// JSONObject obj = timeseries.getJSONObject(i);
|
||||||
JSONObject instant = obj.getJSONObject("data")
|
// JSONObject instant = obj.getJSONObject("data")
|
||||||
.getJSONObject("instant").getJSONObject("details");
|
// .getJSONObject("instant").getJSONObject("details");
|
||||||
JSONObject next1hr = obj.getJSONObject("data")
|
// JSONObject next1hr = obj.getJSONObject("data")
|
||||||
.getJSONObject("next_1_hours").getJSONObject("details");
|
// .getJSONObject("next_1_hours").getJSONObject("details");
|
||||||
WeatherData data = new WeatherData();
|
// WeatherData data = new WeatherData();
|
||||||
|
//
|
||||||
data.date = MET_DATEFORMAT.parse(obj.getString("time"));
|
// data.date = MET_DATEFORMAT.parse(obj.getString("time"));
|
||||||
data.temperature = instant.getDouble("air_temperature");
|
// data.temperature = instant.getDouble("air_temperature");
|
||||||
data.humidity = instant.getDouble("relative_humidity");
|
// data.humidity = instant.getDouble("relative_humidity");
|
||||||
// I think this should be correct. If the time is 13, then it's the data for the
|
// // I think this should be correct. If the time is 13, then it's the data for the
|
||||||
// next 60 minutes, isn't it?
|
// // next 60 minutes, isn't it?
|
||||||
data.precipitation = next1hr.getDouble("precipitation_amount");
|
// data.precipitation = next1hr.getDouble("precipitation_amount");
|
||||||
data.pressure = instant.getDouble("air_pressure_at_sea_level");
|
// data.pressure = instant.getDouble("air_pressure_at_sea_level");
|
||||||
data.cloudCover = instant.getDouble("cloud_area_fraction");
|
// data.cloudCover = instant.getDouble("cloud_area_fraction");
|
||||||
data.windSpeed = instant.getDouble("wind_speed");
|
// data.windSpeed = instant.getDouble("wind_speed");
|
||||||
data.windDirection = instant.getDouble("wind_from_direction");
|
// data.windDirection = instant.getDouble("wind_from_direction");
|
||||||
data.uvIndex = instant.getDouble("ultraviolet_index_clear_sky");
|
// data.uvIndex = instant.getDouble("ultraviolet_index_clear_sky");
|
||||||
|
//
|
||||||
hours.put(MET_DATEFORMAT.parse(obj.getString("time")), data);
|
// hours.put(MET_DATEFORMAT.parse(obj.getString("time")), data);
|
||||||
}
|
// }
|
||||||
} catch (JSONException | ParseException e) {
|
// } catch (JSONException | ParseException e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return hours;
|
// return hours;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void parseMeteoFrance() {
|
public static void parseMeteoFrance() {
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ public class WeatherData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class MemberInfo {
|
public static class MemberInfo {
|
||||||
public String label;
|
public final String label;
|
||||||
public Double value;
|
public final Double value;
|
||||||
public String unit;
|
public final String unit;
|
||||||
|
|
||||||
public MemberInfo(String labela, Double valuea, String unita) {
|
public MemberInfo(String labela, Double valuea, String unita) {
|
||||||
label = labela;
|
label = labela;
|
||||||
|
|||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<eur.one00kb.minipogodynka.LocationSearchView xmlns:android="http://schemas.android.com/apk/res/android"
|
<eur.one00kb.minipogodynka.views.LocationSearchView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
<AutoCompleteTextView
|
<AutoCompleteTextView
|
||||||
android:id="@+id/dl_search"
|
android:id="@+id/dl_search"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:completionThreshold="2"
|
android:completionThreshold="2"
|
||||||
android:hint="@string/dialog_search_field"
|
android:dropDownHeight="170dp"
|
||||||
android:dropDownHeight="170dp" />
|
android:hint="@string/dialog_search_field" />
|
||||||
|
|
||||||
</eur.one00kb.minipogodynka.LocationSearchView>
|
</eur.one00kb.minipogodynka.views.LocationSearchView>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||||
|
android:textSize="24sp">
|
||||||
|
|
||||||
|
</TextView>
|
||||||
@@ -2,18 +2,16 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">MiniPogodynka</string>
|
<string name="app_name">MiniPogodynka</string>
|
||||||
<string name="settings_name">Settings</string>
|
<string name="settings_name">Settings</string>
|
||||||
<string name="location_name">Location</string>
|
|
||||||
|
|
||||||
<string name="placeholder">Placeholder</string>
|
<string name="placeholder">Placeholder</string>
|
||||||
|
|
||||||
<string name="dialog_search_title">Set location</string>
|
<string name="dialog_search_title">Search for location</string>
|
||||||
<string name="dialog_search_field">Search for location</string>
|
<string name="dialog_search_field">City, street, area…</string>
|
||||||
<string name="dialog_search_error">Geocoder unavailable</string>
|
<string name="dialog_search_error">Geocoder unavailable</string>
|
||||||
|
|
||||||
<string name="menu_item_update">Update</string>
|
<string name="menu_item_update">Update</string>
|
||||||
<string name="menu_item_location">Location</string>
|
<string name="menu_item_location">Location</string>
|
||||||
<string name="menu_item_settings">Settings</string>
|
<string name="menu_item_settings">Settings</string>
|
||||||
<string name="menu_item_search">Search</string>
|
|
||||||
|
|
||||||
<string name="preferences_key_provider">weather_provider</string>
|
<string name="preferences_key_provider">weather_provider</string>
|
||||||
<string name="preferences_title_provider">Weather provider</string>
|
<string name="preferences_title_provider">Weather provider</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user