Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialJason Tjahja
8,668 PointsRuntime Error
08-22 17:37:37.473 2697-2697/com.example.theodorusjasontjahja.stormy E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.theodorusjasontjahja.stormy, PID: 2697
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.theodorusjasontjahja.stormy/com.example.theodorusjasontjahja.stormy.MainActivity}: java.lang.IllegalStateException: Required view 'timeLabel' with ID 2131492946 for field 'mTimeLabel' was not found. If this view is optional add '@Nullable' (fields) or '@Optional' (methods) annotation.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: Required view 'timeLabel' with ID 2131492946 for field 'mTimeLabel' was not found. If this view is optional add '@Nullable' (fields) or '@Optional' (methods) annotation.
at butterknife.internal.Finder.findRequiredView(Finder.java:62)
at butterknife.internal.Finder.findRequiredViewAsType(Finder.java:74)
at com.example.theodorusjasontjahja.stormy.MainActivity_ViewBinding.<init>(MainActivity_ViewBinding.java:18)
at com.example.theodorusjasontjahja.stormy.MainActivity_ViewBinder.bind(MainActivity_ViewBinder.java:13)
at com.example.theodorusjasontjahja.stormy.MainActivity_ViewBinder.bind(MainActivity_ViewBinder.java:10)
at butterknife.ButterKnife.bind(ButterKnife.java:125)
at com.example.theodorusjasontjahja.stormy.MainActivity.onCreate(MainActivity.java:43)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
private CurrentWeather mCurrentWeather;
@BindView(R.id.timeLabel) TextView mTimeLabel;
@BindView(R.id.temperatureLabel) TextView mTemperatureLabel;
@BindView(R.id.humidityValue) TextView mHumidityValue;
@BindView(R.id.precipValue) TextView mPrecipValue;
@BindView(R.id.summaryLabel) TextView mSummaryLabel;
@BindView(R.id.iconImageView) ImageView mIconImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
ButterKnife.bind(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String apiKey = *** STEVE HID THIS *** ;
double latitude = 37.8267;
double longtitude= -122.423;
String foreCastURL = "https://api.forecast.io/forecast/" + apiKey +
"/" + latitude + "," + longtitude;
if(isNetworkAvailabe()){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(foreCastURL)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try {
String jsonData = response.body().string();
Log.v(TAG,jsonData );
if (response.isSuccessful()) {
mCurrentWeather = getCurrentDetails(jsonData);
runOnUiThread(new Runnable() {
@Override
public void run() {
updateDisplay();
}
});
} else {
alertUserAboutError();
}
} catch (IOException e) {
Log.e(TAG, "Exception caught: ", e);
} catch (JSONException e){
Log.e(TAG, "Exception caught: ", e);
}
}
});
}else{
Toast.makeText(this, R.string.network_unavailable_message, Toast.LENGTH_LONG).show();
}
Log.d(TAG,"Main UI code is running!");
}
private void updateDisplay() {
// Temperature
String temperatureFormat = getResources().getString(R.string.integerOutput);
int currentTemperature = mCurrentWeather.getTemperature();
String temperatureLabel = String.format(temperatureFormat,currentTemperature);
mTemperatureLabel.setText(temperatureLabel);
// Time
String timeFormat = getString(R.string.timeString);
String currentTime = mCurrentWeather.getFormattedTime();
String timeLabel = String.format(timeFormat,currentTime);
mTimeLabel.setText(timeLabel);
// Humidity
String humidityFormat = getString(R.string.percentageOutput);
int currentHumidity = mCurrentWeather.getHumidity();
String humidityLabel = String.format(humidityFormat,currentHumidity);
mHumidityValue.setText(humidityLabel);
//Precipitation Chance
String precipitationFormat = getString(R.string.percentageOutput);
int currentPrecipitationChance = mCurrentWeather.getPrecipitationChance();
String precipitationLabel = String.format(precipitationFormat, currentPrecipitationChance);
mPrecipValue.setText(precipitationLabel);
// Summary Text
mSummaryLabel.setText(mCurrentWeather.getSummary());
// Icon Update
Drawable drawable = ResourcesCompat.getDrawable(getResources(), mCurrentWeather.getIconId(), null);
mIconImageView.setImageDrawable(drawable);
}
private CurrentWeather 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.setHumidity(currently.getDouble("humidity"));
currentWeather.setTime(currently.getLong("time"));
currentWeather.setIcon(currently.getString("icon"));
currentWeather.setPrecipChance(currently.getDouble("precipProbability"));
currentWeather.setSummary(currently.getString("summary"));
currentWeather.setTemperature(currently.getDouble("temperature"));
currentWeather.setTimeZone(timezone);
Log.d(TAG, currentWeather.getFormattedTime());
return currentWeather;
}
private boolean isNetworkAvailabe() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkinfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if(networkinfo != null && networkinfo.isConnected()){
isAvailable = true;
}
return isAvailable;
}
private void alertUserAboutError() {
AlertDialogFragment dialog = new AlertDialogFragment();
dialog.show(getFragmentManager(),"error_dialog");
}
}
public class CurrentWeather {
private String mIcon;
private long mTime;
private double mTemperature;
private double mHumidity;
private double mPrecipChance;
private String mSummary;
private String mTimeZone;
public String getTimeZone() {
return mTimeZone;
}
public void setTimeZone(String timeZone) {
mTimeZone = timeZone;
}
public String getIcon() {
return mIcon;
}
public void setIcon(String icon) {
mIcon = icon;
}
public int getIconId(){
//clear-day, clear-night, rain, snow, sleet, wind, fog, cloudy, partly-cloudy-day, or partly-cloudy-night
int iconId = R.drawable.clear_day;
if (mIcon.equals("clear-day")) {
iconId = R.drawable.clear_day;
}
else if (mIcon.equals("clear-night")) {
iconId = R.drawable.clear_night;
}
else if (mIcon.equals("rain")) {
iconId = R.drawable.rain;
}
else if (mIcon.equals("snow")) {
iconId = R.drawable.snow;
}
else if (mIcon.equals("sleet")) {
iconId = R.drawable.sleet;
}
else if (mIcon.equals("wind")) {
iconId = R.drawable.wind;
}
else if (mIcon.equals("fog")) {
iconId = R.drawable.fog;
}
else if (mIcon.equals("cloudy")) {
iconId = R.drawable.cloudy;
}
else if (mIcon.equals("partly-cloudy-day")) {
iconId = R.drawable.partly_cloudy;
}
else if (mIcon.equals("partly-cloudy-night")) {
iconId = R.drawable.cloudy_night;
}
return iconId;
}
public long getTime() {
return mTime;
}
public String getFormattedTime(){
SimpleDateFormat formatter = new SimpleDateFormat("h:mm a");
formatter.setTimeZone(TimeZone.getTimeZone(getTimeZone()));
Date dateTime = new Date(getTime() * 1000);
String timeString = formatter.format(dateTime);
return timeString;
}
public void setTime(long time) {
mTime = time;
}
public int getTemperature() {
return (int)Math.round(mTemperature);
}
public void setTemperature(double temperature) {
mTemperature = temperature;
}
public int getHumidity() {
return (int)mHumidity;
}
public void setHumidity(double humidity) {
mHumidity = humidity;
}
public int getPrecipitationChance() {
double precipPrecentage = mPrecipChance * 100;
return (int) Math.round(precipPrecentage);
}
public void setPrecipChance(double precipChance) {
mPrecipChance = precipChance;
}
public String getSummary() {
return mSummary;
}
public void setSummary(String summary) {
mSummary = summary;
}
}
6 Answers
Steve Hunter
57,712 PointsThe above aside, one thing to try is the position of ButterKnife.bind(this);
. Try moving it after the call to the superclass and if that doesn't help, move it another line further down, to after the setContentView
method.
Worth a try ...
Steve.
Steve Hunter
57,712 PointsHi Jason,
The app didn't find a view called timeLabel
which you have bound mTimeLabel
to.
Show us the XML file for your CurrentWeather. The error is Required view 'timeLabel' with ID 2131492946 for field 'mTimeLabel' was not found
- which is what makes me think this might be a naming error in your XML file.
Steve.
Steve Hunter
57,712 PointsI updated/reformatted your code blocks and hid your API key too!
Steve Hunter
57,712 PointsI can't see anything immediately in your XML that might cause a problem.
I have noticed a significant difference between my code and yours, though. This may be due to my code being old and out of date, though.
For my ButterKnife commands, my code has @InjectView
where yours has @BindView
and inside onCreate
, mine has ButterKnife.inject(this);
rather than .bind(this);
. As I say, this is probably either due to my code being old, or maybe that get changed later in the project, I don't know.
Steve.
Steve Hunter
57,712 PointsI just had a look at the video and both my points seem valid - here's a grab of Ben's code:
I might be worth switching the command to reflect what Ben has and seeing if that works from there.
Steve.
Jason Tjahja
8,668 Pointshere's my xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.theodorusjasontjahja.stormy.MainActivity"
android:background="#fc970b">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="--"
android:id="@+id/temperatureLabel"
android:textColor="@android:color/white"
android:textSize="150sp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/degreeImageView"
android:layout_alignTop="@+id/temperatureLabel"
android:layout_toRightOf="@+id/temperatureLabel"
android:layout_toEndOf="@+id/temperatureLabel"
android:src="@drawable/degree"
android:paddingTop="50dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="..."
android:id="@+id/timeLabel"
android:textColor="#80ffffff"
android:textSize="18sp"
android:layout_above="@+id/temperatureLabel"
android:layout_centerHorizontal="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Alcatraz Island, CA"
android:id="@+id/locationLabel"
android:layout_above="@+id/temperatureLabel"
android:layout_centerHorizontal="true"
android:layout_marginBottom="60dp"
android:textColor="@android:color/white"
android:textSize="24sp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/iconImageView"
android:src="@drawable/cloudy_night"
android:layout_alignBottom="@+id/locationLabel"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/temperatureLabel"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:weightSum="100"
android:id="@+id/linearLayout">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="50"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="HUMIDITY"
android:id="@+id/humidityLabel"
android:textColor="#80ffffff"
android:gravity="center_horizontal"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="--"
android:id="@+id/humidityValue"
android:textColor="@android:color/white"
android:textSize="24sp"
android:gravity="center_horizontal"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="50">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="RAIN/SNOW?"
android:id="@+id/precipLabel"
android:textColor="#80ffffff"
android:gravity="center_horizontal"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="--"
android:id="@+id/precipValue"
android:textColor="@android:color/white"
android:textSize="24sp"
android:gravity="center_horizontal"/>
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Getting current weather..."
android:id="@+id/summaryLabel"
android:layout_below="@+id/linearLayout"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:textColor="@android:color/white"
android:textSize="18sp"
android:gravity="center_horizontal"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/refreshImageView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:src="@drawable/refresh"/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progressBar"
android:layout_alignBottom="@+id/refreshImageView"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
Jason Tjahja
8,668 PointsFor everyone who had an error in this course, try to compare your codes with mine (this is for Butterknife 8.2.1)
build.gradle for module-level
apply plugin:'com.android.application'
apply plugin: 'android-apt'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "com.examp.theodorusjasontjahja.stormy"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.jakewharton:butterknife:8.2.1'
apt 'com.jakewharton:butterknife-compiler:8.2.1'
}
build.gradle project-level
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.theodorusjasontjahja.stormy.MainActivity"
android:background="#fc970b">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="--"
android:id="@+id/temperatureLabel"
android:textColor="@android:color/white"
android:textSize="150sp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/degreeImageView"
android:layout_alignTop="@+id/temperatureLabel"
android:layout_toRightOf="@+id/temperatureLabel"
android:layout_toEndOf="@+id/temperatureLabel"
android:src="@drawable/degree"
android:paddingTop="50dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="..."
android:id="@+id/timeLabel"
android:textColor="#80ffffff"
android:textSize="18sp"
android:layout_above="@+id/temperatureLabel"
android:layout_centerHorizontal="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Alcatraz Island, CA"
android:id="@+id/locationLabel"
android:layout_above="@+id/temperatureLabel"
android:layout_centerHorizontal="true"
android:layout_marginBottom="60dp"
android:textColor="@android:color/white"
android:textSize="24sp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/iconImageView"
android:src="@drawable/cloudy_night"
android:layout_alignBottom="@+id/locationLabel"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/temperatureLabel"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:weightSum="100"
android:id="@+id/linearLayout">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="50"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="HUMIDITY"
android:id="@+id/humidityLabel"
android:textColor="#80ffffff"
android:gravity="center_horizontal"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="--"
android:id="@+id/humidityValue"
android:textColor="@android:color/white"
android:textSize="24sp"
android:gravity="center_horizontal"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="50">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="RAIN/SNOW?"
android:id="@+id/precipLabel"
android:textColor="#80ffffff"
android:gravity="center_horizontal"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="--"
android:id="@+id/precipValue"
android:textColor="@android:color/white"
android:textSize="24sp"
android:gravity="center_horizontal"/>
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Getting current weather..."
android:id="@+id/summaryLabel"
android:layout_below="@+id/linearLayout"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:textColor="@android:color/white"
android:textSize="18sp"
android:gravity="center_horizontal"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/refreshImageView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:src="@drawable/refresh"/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progressBar"
android:layout_alignBottom="@+id/refreshImageView"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
Main
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
private CurrentWeather mCurrentWeather;
@BindView(R.id.timeLabel) TextView mTimeLabel;
@BindView(R.id.temperatureLabel) TextView mTemperatureLabel;
@BindView(R.id.humidityValue) TextView mHumidityValue;
@BindView(R.id.precipValue) TextView mPrecipValue;
@BindView(R.id.summaryLabel) TextView mSummaryLabel;
@BindView(R.id.iconImageView) ImageView mIconImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
String apiKey = ****** ;
double latitude = 37.8267;
double longtitude= -122.423;
String foreCastURL = "https://api.forecast.io/forecast/" + apiKey +
"/" + latitude + "," + longtitude;
if(isNetworkAvailabe()){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(foreCastURL)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try {
String jsonData = response.body().string();
Log.v(TAG,jsonData );
if (response.isSuccessful()) {
mCurrentWeather = getCurrentDetails(jsonData);
runOnUiThread(new Runnable() {
@Override
public void run() {
updateDisplay();
}
});
} else {
alertUserAboutError();
}
} catch (IOException e) {
Log.e(TAG, "Exception caught: ", e);
} catch (JSONException e){
Log.e(TAG, "Exception caught: ", e);
}
}
});
}else{
Toast.makeText(this, R.string.network_unavailable_message, Toast.LENGTH_LONG).show();
}
Log.d(TAG,"Main UI code is running!");
}
private void updateDisplay() {
// Temperature
String temperatureFormat = getResources().getString(R.string.integerOutput);
int currentTemperature = mCurrentWeather.getTemperature();
String temperatureLabel = String.format(temperatureFormat,currentTemperature);
mTemperatureLabel.setText(temperatureLabel);
// Time
String timeFormat = getString(R.string.timeString);
String currentTime = mCurrentWeather.getFormattedTime();
String timeLabel = String.format(timeFormat,currentTime);
mTimeLabel.setText(timeLabel);
// Humidity
String humidityFormat = getString(R.string.percentageOutput);
int currentHumidity = mCurrentWeather.getHumidity();
String humidityLabel = String.format(humidityFormat,currentHumidity);
mHumidityValue.setText(humidityLabel);
//Precipitation Chance
String precipitationFormat = getString(R.string.percentageOutput);
int currentPrecipitationChance = mCurrentWeather.getPrecipitationChance();
String precipitationLabel = String.format(precipitationFormat, currentPrecipitationChance);
mPrecipValue.setText(precipitationLabel);
// Summary Text
mSummaryLabel.setText(mCurrentWeather.getSummary());
// Icon Update
Drawable drawable = ResourcesCompat.getDrawable(getResources(), mCurrentWeather.getIconId(), null);
mIconImageView.setImageDrawable(drawable);
}
private CurrentWeather 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.setHumidity(currently.getDouble("humidity"));
currentWeather.setTime(currently.getLong("time"));
currentWeather.setIcon(currently.getString("icon"));
currentWeather.setPrecipChance(currently.getDouble("precipProbability"));
currentWeather.setSummary(currently.getString("summary"));
currentWeather.setTemperature(currently.getDouble("temperature"));
currentWeather.setTimeZone(timezone);
Log.d(TAG, currentWeather.getFormattedTime());
return currentWeather;
}
private boolean isNetworkAvailabe() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkinfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if(networkinfo != null && networkinfo.isConnected()){
isAvailable = true;
}
return isAvailable;
}
private void alertUserAboutError() {
AlertDialogFragment dialog = new AlertDialogFragment();
dialog.show(getFragmentManager(),"error_dialog");
}
}
mCurrentWeather
public class CurrentWeather {
private String mIcon;
private long mTime;
private double mTemperature;
private double mHumidity;
private double mPrecipChance;
private String mSummary;
private String mTimeZone;
public String getTimeZone() {
return mTimeZone;
}
public void setTimeZone(String timeZone) {
mTimeZone = timeZone;
}
public String getIcon() {
return mIcon;
}
public void setIcon(String icon) {
mIcon = icon;
}
public int getIconId(){
//clear-day, clear-night, rain, snow, sleet, wind, fog, cloudy, partly-cloudy-day, or partly-cloudy-night
int iconId = R.drawable.clear_day;
if (mIcon.equals("clear-day")) {
iconId = R.drawable.clear_day;
}
else if (mIcon.equals("clear-night")) {
iconId = R.drawable.clear_night;
}
else if (mIcon.equals("rain")) {
iconId = R.drawable.rain;
}
else if (mIcon.equals("snow")) {
iconId = R.drawable.snow;
}
else if (mIcon.equals("sleet")) {
iconId = R.drawable.sleet;
}
else if (mIcon.equals("wind")) {
iconId = R.drawable.wind;
}
else if (mIcon.equals("fog")) {
iconId = R.drawable.fog;
}
else if (mIcon.equals("cloudy")) {
iconId = R.drawable.cloudy;
}
else if (mIcon.equals("partly-cloudy-day")) {
iconId = R.drawable.partly_cloudy;
}
else if (mIcon.equals("partly-cloudy-night")) {
iconId = R.drawable.cloudy_night;
}
return iconId;
}
public long getTime() {
return mTime;
}
public String getFormattedTime(){
SimpleDateFormat formatter = new SimpleDateFormat("h:mm a");
formatter.setTimeZone(TimeZone.getTimeZone(getTimeZone()));
Date dateTime = new Date(getTime() * 1000);
String timeString = formatter.format(dateTime);
return timeString;
}
public void setTime(long time) {
mTime = time;
}
public int getTemperature() {
return (int)Math.round(mTemperature);
}
public void setTemperature(double temperature) {
mTemperature = temperature;
}
public int getHumidity() {
return (int)mHumidity;
}
public void setHumidity(double humidity) {
mHumidity = humidity;
}
public int getPrecipitationChance() {
double precipPrecentage = mPrecipChance * 100;
return (int) Math.round(precipPrecentage);
}
public void setPrecipChance(double precipChance) {
mPrecipChance = precipChance;
}
public String getSummary() {
return mSummary;
}
public void setSummary(String summary) {
mSummary = summary;
}
<resources>
<string name="app_name">Stormy</string>
<string name="error_title">Oops! Sorry!</string>
<string name="error_message">There was an error. Please try again.</string>
<string name="error_ok_button_text">OK</string>
<string name="network_unavailable_message">Network is unavailable !</string>
<string name="tempPreview">--</string>
<string name="degree_symbol">Degree Symbol</string>
<string name="timePreview">…</string>
<string name="defaultLocation">Alcatraz Island, CA</string>
<string name="defaultLocationForScreenReaders">Current Weather Location</string>
<string name="humidityColumnHeader">HUMIDITY</string>
<string name="humidityPreview">--</string>
<string name="precipColumnHeader">RAIN/SNOW?</string>
<string name="precipPreview">--</string>
<string name="summaryPreview">Getting Current Weather…</string>
<string name="timeString">At %1$s it will be</string>
<string name="percentageOutput">%d%%</string>
<string name="integerOutput">%d</string>
</resources>
Jason Tjahja
8,668 PointsJason Tjahja
8,668 PointsHello Steve,
Really thanks for your answer, the app launched perfectly, thanks for your time to notice it. Spending hours just for mention a mistake is very annoying. Really big thanks, actually I already completed this challenge few days ago, I didn't use Butterknife, instead changed it to just using findViewById. But now I start using ButterKnife again and it runs.
Jason.