diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 478a742..a436038 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,4 +28,5 @@ dependencies { compile 'com.squareup.okhttp3:okhttp:3.10.0' compile 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' + implementation 'com.android.support:recyclerview-v7:26.1.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a6cbd3e..148c8db 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,7 +3,7 @@ package="com.example.rhenigan.stormy"> - + - @@ -20,6 +21,8 @@ + + \ No newline at end of file diff --git a/app/src/main/java/com/example/rhenigan/stormy/HourlyForecastActivity.java b/app/src/main/java/com/example/rhenigan/stormy/HourlyForecastActivity.java new file mode 100644 index 0000000..4d178dc --- /dev/null +++ b/app/src/main/java/com/example/rhenigan/stormy/HourlyForecastActivity.java @@ -0,0 +1,44 @@ +package com.example.rhenigan.stormy; + +import android.content.Intent; +import android.os.Parcelable; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.example.rhenigan.stormy.UI.MainActivity; +import com.example.rhenigan.stormy.adapters.HourAdapter; +import com.example.rhenigan.stormy.weather.Hour; + +import java.util.Arrays; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class HourlyForecastActivity extends AppCompatActivity { + + private Hour[] mHours; + + @BindView(R.id.recyclerView) RecyclerView mRecyclerView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_hourly_forecast); + + ButterKnife.bind(this); + + Intent intent = getIntent(); + Parcelable[] parcelables = intent.getParcelableArrayExtra(MainActivity.HOURLY_FORECAST); + mHours = Arrays.copyOf(parcelables, parcelables.length, Hour[].class); + + HourAdapter adapter = new HourAdapter(mHours); + mRecyclerView.setAdapter(adapter); + + RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); + mRecyclerView.setLayoutManager(layoutManager); + + mRecyclerView.setHasFixedSize(true); + } +} diff --git a/app/src/main/java/com/example/rhenigan/stormy/AlertDialogFragment.java b/app/src/main/java/com/example/rhenigan/stormy/UI/AlertDialogFragment.java similarity index 90% rename from app/src/main/java/com/example/rhenigan/stormy/AlertDialogFragment.java rename to app/src/main/java/com/example/rhenigan/stormy/UI/AlertDialogFragment.java index 3c3ccae..ceddde6 100644 --- a/app/src/main/java/com/example/rhenigan/stormy/AlertDialogFragment.java +++ b/app/src/main/java/com/example/rhenigan/stormy/UI/AlertDialogFragment.java @@ -1,4 +1,4 @@ -package com.example.rhenigan.stormy; +package com.example.rhenigan.stormy.UI; import android.app.AlertDialog; import android.app.Dialog; @@ -6,6 +6,8 @@ import android.content.Context; import android.os.Bundle; +import com.example.rhenigan.stormy.R; + /** * Created by henig on 4/4/2018. * ------------------------------ diff --git a/app/src/main/java/com/example/rhenigan/stormy/MainActivity.java b/app/src/main/java/com/example/rhenigan/stormy/UI/MainActivity.java similarity index 57% rename from app/src/main/java/com/example/rhenigan/stormy/MainActivity.java rename to app/src/main/java/com/example/rhenigan/stormy/UI/MainActivity.java index 115ba35..3f9be13 100644 --- a/app/src/main/java/com/example/rhenigan/stormy/MainActivity.java +++ b/app/src/main/java/com/example/rhenigan/stormy/UI/MainActivity.java @@ -1,6 +1,7 @@ -package com.example.rhenigan.stormy; +package com.example.rhenigan.stormy.UI; import android.content.Context; +import android.content.Intent; import android.graphics.drawable.Drawable; import android.net.ConnectivityManager; import android.net.NetworkInfo; @@ -13,6 +14,14 @@ import android.widget.TextView; import android.widget.Toast; +import com.example.rhenigan.stormy.HourlyForecastActivity; +import com.example.rhenigan.stormy.R; +import com.example.rhenigan.stormy.weather.Current; +import com.example.rhenigan.stormy.weather.Day; +import com.example.rhenigan.stormy.weather.Forecast; +import com.example.rhenigan.stormy.weather.Hour; + +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -20,6 +29,7 @@ import butterknife.BindView; import butterknife.ButterKnife; +import butterknife.OnClick; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; @@ -29,8 +39,9 @@ public class MainActivity extends AppCompatActivity { public static final String TAG = "MAIN ACTIVITY"; + public static final String HOURLY_FORECAST = "HOURLY_FORECAST"; - private CurrentWeather mCurrentWeather; + private Forecast mForecast; @BindView(R.id.timeLabel) TextView mTimeLabel; @BindView(R.id.temperatureLabel) TextView mTemperatureLabel; @@ -42,6 +53,7 @@ public class MainActivity extends AppCompatActivity { @BindView(R.id.progressBar) ProgressBar mProgressBar; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -101,7 +113,7 @@ public void run() { try { String jsonData = response.body().string(); if (response.isSuccessful()) { - mCurrentWeather = getCurrentDetails(jsonData); + mForecast = parseForecastDetails(jsonData); runOnUiThread(new Runnable() { @Override public void run() { @@ -136,34 +148,93 @@ private void toggleRefresh() { } private void updateDisplay() { - mTemperatureLabel.setText(mCurrentWeather.getTemp() + ""); - mTimeLabel.setText("At " + mCurrentWeather.getFormattedTime() + " it will be"); - mHumidityValue.setText(mCurrentWeather.getHum() + ""); - mPrecipValue.setText(mCurrentWeather.getPrecip() + "%"); - mSummaryLabel.setText(mCurrentWeather.getSummary() + ""); - Drawable drawable = getResources().getDrawable(mCurrentWeather.getIconId()); + mTemperatureLabel.setText(mForecast.getCurrent().getTemp() + ""); + mTimeLabel.setText("At " + mForecast.getCurrent().getFormattedTime() + " it will be"); + mHumidityValue.setText(mForecast.getCurrent().getHum() + ""); + mPrecipValue.setText(mForecast.getCurrent().getPrecip() + "%"); + mSummaryLabel.setText(mForecast.getCurrent().getSummary() + ""); + Drawable drawable = getResources().getDrawable(mForecast.getCurrent().getIconId()); mIconImageView.setImageDrawable(drawable); } - private CurrentWeather getCurrentDetails(String jsonData) throws JSONException { + private Forecast parseForecastDetails(String jsonData) throws JSONException{ + Forecast forecast = new Forecast(); + + forecast.setCurrent(getCurrentDetails(jsonData)); + forecast.setHourlyForecast(getHourlyForecast(jsonData)); + forecast.setDailyForecast(getDailyForecast(jsonData)); + + return forecast; + } + + private Day[] getDailyForecast(String jsonData) throws JSONException{ + JSONObject forecast = new JSONObject(jsonData); + String timezone = forecast.getString("timezone"); + + JSONObject daily = forecast.getJSONObject("daily"); + JSONArray data = daily.getJSONArray("data"); + + Day[] days = new Day[data.length()]; + + for(int i = 0; i < data.length(); i++) { + JSONObject jsonDay = data.getJSONObject(i); + + Day day = new Day(); + + day.setSummary(jsonDay.getString("summary")); + day.setIcon(jsonDay.getString("icon")); + day.setTempMax(jsonDay.getDouble("temperatureMax")); + day.setTime(jsonDay.getLong("time")); + day.setTimeZone(timezone); + + days[i] = day; + } + return days; + } + + private Hour[] getHourlyForecast(String jsonData) throws JSONException{ + JSONObject forecast = new JSONObject(jsonData); + String timezone = forecast.getString("timezone"); + JSONObject hourly = forecast.getJSONObject("hourly"); + JSONArray data = hourly.getJSONArray("data"); + + Hour[] hours = new Hour[data.length()]; + + for(int i = 0; i < data.length(); i++) { + JSONObject jsonHour = data.getJSONObject(i); + + Hour hour = new Hour(); + + hour.setSummary(jsonHour.getString("summary")); + hour.setTemp(jsonHour.getDouble("temperature")); + hour.setIcon(jsonHour.getString("icon")); + hour.setTime(jsonHour.getLong("time")); + hour.setTimeZone(timezone); + + hours[i] = hour; + } + return hours; + } + + private Current getCurrentDetails(String jsonData) throws JSONException { JSONObject forecast = new JSONObject(jsonData); String timezone = forecast.getString("timezone"); Log.i(TAG, "From Json: " + timezone); JSONObject currently = forecast.getJSONObject("currently"); - CurrentWeather currentWeather = new CurrentWeather(); - currentWeather.setHum(currently.getDouble("humidity")); - currentWeather.setTime(currently.getLong("time")); - currentWeather.setIcon(currently.getString("icon")); - currentWeather.setPrecip(currently.getDouble("precipProbability")); - currentWeather.setSummary(currently.getString("summary")); - currentWeather.setTemp(currently.getDouble("temperature")); - currentWeather.setTimeZone(timezone); + Current current = new Current(); + current.setHum(currently.getDouble("humidity")); + current.setTime(currently.getLong("time")); + current.setIcon(currently.getString("icon")); + current.setPrecip(currently.getDouble("precipProbability")); + current.setSummary(currently.getString("summary")); + current.setTemp(currently.getDouble("temperature")); + current.setTimeZone(timezone); - Log.d(TAG, currentWeather.getFormattedTime()); + Log.d(TAG, current.getFormattedTime()); - return currentWeather; + return current; } private boolean isNetworkAvailable() { @@ -180,4 +251,11 @@ private void alertUserAboutError() { AlertDialogFragment dialog = new AlertDialogFragment(); dialog.show(getFragmentManager(), "error_dialog"); } + + @OnClick (R.id.HourlyButton) + public void startHourlyActivity(View view) { + Intent intent = new Intent(this, HourlyForecastActivity.class); + intent.putExtra(HOURLY_FORECAST, mForecast.getHourlyForecast()); + startActivity(intent); + } } diff --git a/app/src/main/java/com/example/rhenigan/stormy/adapters/HourAdapter.java b/app/src/main/java/com/example/rhenigan/stormy/adapters/HourAdapter.java new file mode 100644 index 0000000..a61ea58 --- /dev/null +++ b/app/src/main/java/com/example/rhenigan/stormy/adapters/HourAdapter.java @@ -0,0 +1,65 @@ +package com.example.rhenigan.stormy.adapters; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.example.rhenigan.stormy.R; +import com.example.rhenigan.stormy.weather.Hour; + +/** + * Created by henig on 4/16/2018. + * ------------------------------ + */ +public class HourAdapter extends RecyclerView.Adapter { + + private Hour[] mHours; + + public HourAdapter(Hour[] hours) { + mHours = hours; + } + + public class HourViewHolder extends RecyclerView.ViewHolder { + + public TextView mTimeLabel; + public TextView mSummaryLabel; + public TextView mTempLabel; + public ImageView mIconImageView; + + public HourViewHolder(View itemView) { + super(itemView); + + mTimeLabel = itemView.findViewById(R.id.timeLabel); + mSummaryLabel = itemView.findViewById(R.id.summaryLabel); + mTempLabel = itemView.findViewById(R.id.tempLabel); + mIconImageView = itemView.findViewById(R.id.iconImageView); + } + + public void bindHour(Hour hour) { + mTimeLabel.setText(hour.getHour()); + mSummaryLabel.setText(hour.getSummary()); + mTempLabel.setText(hour.getTemp() + ""); + mIconImageView.setImageResource(hour.getIconId()); + } + } + + @Override + public HourViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.hourly_list_item, parent, false); + HourViewHolder viewHolder = new HourViewHolder(view); + return viewHolder; + } + + @Override + public void onBindViewHolder(HourViewHolder holder, int position) { + holder.bindHour(mHours[position]); + } + + @Override + public int getItemCount() { + return mHours.length; + } +} diff --git a/app/src/main/java/com/example/rhenigan/stormy/CurrentWeather.java b/app/src/main/java/com/example/rhenigan/stormy/weather/Current.java similarity index 96% rename from app/src/main/java/com/example/rhenigan/stormy/CurrentWeather.java rename to app/src/main/java/com/example/rhenigan/stormy/weather/Current.java index d88dab8..eefb473 100644 --- a/app/src/main/java/com/example/rhenigan/stormy/CurrentWeather.java +++ b/app/src/main/java/com/example/rhenigan/stormy/weather/Current.java @@ -1,4 +1,6 @@ -package com.example.rhenigan.stormy; +package com.example.rhenigan.stormy.weather; + +import com.example.rhenigan.stormy.R; import java.text.SimpleDateFormat; import java.util.Date; @@ -9,7 +11,7 @@ * ------------------------------ */ -public class CurrentWeather { +public class Current { private String mIcon; private Long mTime; private double mTemp; diff --git a/app/src/main/java/com/example/rhenigan/stormy/weather/Day.java b/app/src/main/java/com/example/rhenigan/stormy/weather/Day.java new file mode 100644 index 0000000..320bf68 --- /dev/null +++ b/app/src/main/java/com/example/rhenigan/stormy/weather/Day.java @@ -0,0 +1,55 @@ +package com.example.rhenigan.stormy.weather; + +/** + * Created by henig on 4/9/2018. + * ------------------------------ + */ + +public class Day { + + private Long mTime; + private String mSummary; + private double mTempMax; + private String mIcon; + private String mTimeZone; + + public Long getTime() { + return mTime; + } + + public void setTime(Long time) { + mTime = time; + } + + public String getSummary() { + return mSummary; + } + + public void setSummary(String summary) { + mSummary = summary; + } + + public double getTempMax() { + return mTempMax; + } + + public void setTempMax(double tempMax) { + mTempMax = tempMax; + } + + public String getIcon() { + return mIcon; + } + + public void setIcon(String icon) { + mIcon = icon; + } + + public String getTimeZone() { + return mTimeZone; + } + + public void setTimeZone(String timeZone) { + mTimeZone = timeZone; + } +} diff --git a/app/src/main/java/com/example/rhenigan/stormy/weather/Forecast.java b/app/src/main/java/com/example/rhenigan/stormy/weather/Forecast.java new file mode 100644 index 0000000..dea1538 --- /dev/null +++ b/app/src/main/java/com/example/rhenigan/stormy/weather/Forecast.java @@ -0,0 +1,79 @@ +package com.example.rhenigan.stormy.weather; + +import com.example.rhenigan.stormy.R; + +/** + * Created by henig on 4/9/2018. + * ------------------------------ + */ + +public class Forecast { + + private Current mCurrent; + private Hour[] mHourlyForecast; + private Day[] mDaylyForecast; + + public Current getCurrent() { + return mCurrent; + } + + public void setCurrent(Current current) { + mCurrent = current; + } + + public Hour[] getHourlyForecast() { + return mHourlyForecast; + } + + public void setHourlyForecast(Hour[] hourlyForecast) { + mHourlyForecast = hourlyForecast; + } + + public Day[] getDaylyForecast() { + return mDaylyForecast; + } + + public void setDailyForecast(Day[] daylyForecast) { + mDaylyForecast = daylyForecast; + } + + public static int getIconId(String iconString) { + + // clear-day, clear-night, rain, snow, sleet, wind, fog, cloudy, partly-cloudy-day, or partly-cloudy-night. + int iconId = R.drawable.clear_day; + + + if (iconString.equals("clear-day")) { + iconId = R.drawable.clear_day; + } + else if (iconString.equals("clear-night")) { + iconId = R.drawable.clear_night; + } + else if (iconString.equals("rain")) { + iconId = R.drawable.rain; + } + else if (iconString.equals("snow")) { + iconId = R.drawable.snow; + } + else if (iconString.equals("sleet")) { + iconId = R.drawable.sleet; + } + else if (iconString.equals("wind")) { + iconId = R.drawable.wind; + } + else if (iconString.equals("fog")) { + iconId = R.drawable.fog; + } + else if (iconString.equals("cloudy")) { + iconId = R.drawable.cloudy; + } + else if (iconString.equals("partly-cloudy-day")) { + iconId = R.drawable.partly_cloudy; + } + else if (iconString.equals("partly-cloudy-night")) { + iconId = R.drawable.cloudy_night; + } + + return iconId; + } +} diff --git a/app/src/main/java/com/example/rhenigan/stormy/weather/Hour.java b/app/src/main/java/com/example/rhenigan/stormy/weather/Hour.java new file mode 100644 index 0000000..66225b4 --- /dev/null +++ b/app/src/main/java/com/example/rhenigan/stormy/weather/Hour.java @@ -0,0 +1,109 @@ +package com.example.rhenigan.stormy.weather; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created by henig on 4/9/2018. + * ------------------------------ + */ + +public class Hour implements Parcelable { + + private long mTime; + private String mSummary; + private double mTemp; + private String mIcon; + private String mTimezone; + + public Hour() {} + + public long getTime() { + return mTime; + } + + public void setTime(long time) { + mTime = time; + } + + public String getSummary() { + return mSummary; + } + + public void setSummary(String summary) { + mSummary = summary; + } + + public void setTemp(double temp) { + mTemp = temp; + } + + public String getIcon() { + return mIcon; + } + + public void setIcon(String icon) { + mIcon = icon; + } + + public String getTimezone() { + return mTimezone; + } + + public void setTimeZone(String timezone) { + mTimezone = timezone; + } + + public int getIconId() { + return Forecast.getIconId(mIcon); + } + + public int getTemp() { + return (int) Math.round(mTemp); + } + + public String getHour() { + SimpleDateFormat formatter = new SimpleDateFormat("h a"); + Date date = new Date(mTime *1000); + return formatter.format(date); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeLong(mTime); + parcel.writeDouble(mTemp); + parcel.writeString(mSummary); + parcel.writeString(mIcon); + parcel.writeString(mTimezone); + } + + private Hour(Parcel in) { + mTime = in.readLong(); + mTemp = in.readDouble(); + mSummary = in.readString(); + mIcon = in.readString(); + mTimezone = in.readString(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public Hour createFromParcel(Parcel parcel) { + return new Hour(parcel); + } + + @Override + public Hour[] newArray(int i) { + return new Hour[i]; + } + }; + + +} diff --git a/app/src/main/res/drawable/bg_gradient.xml b/app/src/main/res/drawable/bg_gradient.xml new file mode 100644 index 0000000..61a79a4 --- /dev/null +++ b/app/src/main/res/drawable/bg_gradient.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_hourly_forecast.xml b/app/src/main/res/layout/activity_hourly_forecast.xml new file mode 100644 index 0000000..926f931 --- /dev/null +++ b/app/src/main/res/layout/activity_hourly_forecast.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 1df9905..47b0c95 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,9 +6,8 @@ android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" - android:paddingBottom="@dimen/activity_vertical_margin" - tools:context=".MainActivity" - android:background="#fffc970b"> + tools:context=".UI.MainActivity" + android:background="@drawable/bg_gradient"> + + +