Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

branch 2.03 #292

Open
wants to merge 78 commits into
base: 2.03_add_refresh_xml
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f7f49a8
2.04 Inflate menu
sdspikes May 30, 2014
f18784f
2.05 Execute FetchWeatherTask
sdspikes May 28, 2014
d1579a4
2.06 Add Internet permission
sdspikes May 30, 2014
30afc9f
2.07 Build URL with params
sdspikes May 29, 2014
c281fef
2.08 Add in JSON parsing code
sdspikes May 29, 2014
c8542c3
2.09 Update the adapter so that the data is displayed
sdspikes May 29, 2014
2141b9c
3.00 remove verbose logging statements
sdspikes Jun 5, 2014
bd57648
3.01 Add toast on item click
sdspikes May 30, 2014
e8e638d
3.02 Create new DetailActivity
Dec 17, 2014
4a61c5a
3.03 Launch DetailActivity by initiating an explicit intent
Dec 18, 2014
0d060ff
3.04 Get the forecast from the intent and use it to populate the deta…
Dec 18, 2014
296319f
3.05 Add SettingsActivity and associated entry in the manifest
sdspikes May 31, 2014
fd12441
3.06 Launch the settings activity when the settings menu item is sele…
sdspikes May 31, 2014
d5eebe9
3.07 Add location setting xml
sdspikes May 31, 2014
5204747
3.08 Inflate view in SettingsActivity
sdspikes May 31, 2014
a01a072
3.09 Get location from shared prefs
sdspikes May 31, 2014
29db009
3.10 Refactor fetching weather data so we don't have to stare at the …
Dec 16, 2014
cdd3f2c
3.11 Add fully functional units setting
sdspikes Jun 5, 2014
745a01e
3.12 Add map intent from new menu item
Dec 17, 2014
f63ba9f
3.13 Add ShareActionProvider to detail fragment menu
Dec 18, 2014
35bbc96
4.01 Lifecycle Events quiz adding log statements
Dec 18, 2014
413fbdf
Revert "4.1 Lifecycle Events quiz -- add log statements to MainActivi…
Feb 10, 2015
eacae0c
4.02 Complete starting code for Lesson 4. Includes lots of important …
DAGalpin Jan 10, 2015
bc10a05
4.03 Define constants in Contract
Feb 9, 2015
a660986
4.04 Create Sunshine's location database
Feb 9, 2015
bf7b04b
4.05 Test read and write from the location table
Feb 25, 2015
dd092ef
4.06 Test read and write from the weather table
Feb 25, 2015
44facd1
4.07 Add the content provider to the weather contract
Feb 10, 2015
37e439c
4.08 Adding weather with location to the uribuilder
Feb 10, 2015
c31d580
4.09 Write the urimatcher
Feb 10, 2015
ed27994
4.10 Register the ContentProvider
Feb 10, 2015
d041e49
4.11 getType : coding the ContentProvider
Feb 10, 2015
4eb23f5
4.12 Query : coding the ContentProvider
Feb 10, 2015
b1f2141
4.13 Insert : coding the ContentProvider
Feb 10, 2015
a96d6de
4.14 Updating and Deleting : coding the ContentProvider
Feb 10, 2015
f3ef5ac
4.15 Refactoring to use our new FetchWeatherTask
Feb 10, 2015
6bdaacc
4.16 Inserts with the ContentProvider
Mar 4, 2015
3d7d597
4.17 Bulkinserts with the ContentProvider
Feb 10, 2015
c76f10b
4.18 Adding a CursorAdapter
Feb 10, 2015
73c9c58
4.19 Leveraging loaders
Feb 10, 2015
f9f2413
4.20 Leveraging Projection
Mar 4, 2015
07b3fb5
4.21 Adding the details view
Feb 10, 2015
e16a1f1
4.22 Make details view functional
Feb 10, 2015
90c8f63
4.23 Make settings change view
Feb 10, 2015
754c74f
5.01 Building List Item (quiz)
Feb 3, 2015
a658087
5.02 Building today list item
Feb 3, 2015
5065e18
5.03 CursorAdapter- use ForecastAdapter
Feb 6, 2015
de2bde3
5.04 Two Item View Types
Feb 4, 2015
8fdc98e
5.05 Using View Holder Pattern
Feb 4, 2015
b99aa09
5.06 Formatting Strings
Feb 4, 2015
87b9e6d
5.07 Refactor DetailFragment into a new file
Feb 4, 2015
e8cfce1
5.07 Coding task for Details screen (quiz)
Feb 4, 2015
5da9899
5.08 Images
Feb 4, 2015
1ea4116
5.09 Build Two Pane Tablet UI
Feb 13, 2015
c6432e8
5.10 Coding Task on Selected Item on Tablet
Feb 11, 2015
c3e328f
5.11 Coding Task for Activated List Item
Feb 4, 2015
57b2926
5.11 Coding Task for Activated List Item (quiz)
Feb 4, 2015
1e95ccd
5.12 Coding Task to Restore scroll position on rotation (quiz)
Feb 5, 2015
04188f7
5.13 Coding Task for Alternative Detail Layout
Feb 5, 2015
b920522
5.14 Coding Task for Today Item on Tablet
Feb 5, 2015
a66c4cc
5.15 Coding Task on Action Bar
Feb 6, 2015
15b7446
5.16 Settings Activity Action Bar
Feb 7, 2015
6e89499
5.17 Implementing Redlines - list_item_forecast
Feb 7, 2015
09203c3
5.18 Implement the rest of the redlines
Feb 6, 2015
dd9674e
5.19 Coding Task on Accessibility
Feb 6, 2015
dd2aee0
6.01 Using Services
Mar 4, 2015
886658c
6.02 Using Alarms
Feb 6, 2015
0b532cd
6.03 Implementing a Sync Adapter
Feb 6, 2015
f58d695
6.04 Finish the SyncAdapter
Feb 6, 2015
e5721de
6.05 Scheduled Synchronization
Feb 6, 2015
f30d62b
6.06 Notifications Question
Feb 6, 2015
822c68c
6.07 Notifications Answer
Feb 6, 2015
69a39ee
6.08 Turning Weather Notifications On Off
Feb 6, 2015
f4f385f
6.09 Delete Old Weather Data
Feb 6, 2015
6f18226
6.10 Update Map Intent
Feb 6, 2015
4bfbe6f
Add API Key Parameter to OpenWeatherMap API Call
cdlei Oct 16, 2015
1674b67
Update README.md with API key guidance.
cdlei Oct 19, 2015
5d0dd65
Update README.md
SudKul Jun 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 20 additions & 1 deletion README.md
@@ -1,3 +1,10 @@
# Archival Note
We are archiving this repository because we do not want learners to push personal development to the current repository. If you have any issues or suggestions to make, feel free to:
- Utilize the https://knowledge.udacity.com/ forum to seek help on content-specific issues.
- Submit a support ticket along with the link to your forked repository if (learners are) blocked for other reasons. Here are the links for the [retail consumers](https://udacity.zendesk.com/hc/en-us/requests/new) and [enterprise learners](https://udacityenterprise.zendesk.com/hc/en-us/requests/new?ticket_form_id=360000279131).



Sunshine
========

Expand All @@ -7,10 +14,22 @@ Take the course to find out how to build this app a step at a time, and eventual

This is the second version of the Sunshine code. The repository has been updated on:

* **October 18th, 2015** - Updated to support use of the openweathermap.org API key.
* **February 13th, 2015** - Major update
* February 25, 2015 - Minor bug fixes
* March 4th, 2015 - Minor bug fixes

### Open Weather Map API Key is required.

In order for the Sunshine app to function properly as of October 18th, 2015 an API key for openweathermap.org must be included with the build.

We recommend that each student obtain a key via the following [instructions](http://openweathermap.org/appid#use), and include the unique key for the build by adding the following line to [USER_HOME]/.gradle/gradle.properties

`MyOpenWeatherMapApiKey="<UNIQUE_API_KEY">`

For help migrating an existing repo (fork or clone prior to 10/18/15), please check out this [guide.](https://docs.google.com/document/d/1e8LXahedBlCW1_dp_FyvQ3ugUAwUBJDuJCoKf3tgNVs/pub?embedded=true)

========
For the original version, please go [here](https://github.com/udacity/Sunshine).

A changelog for the course can be found [here](https://docs.google.com/a/knowlabs.com/document/d/193xJb_OpcNCqgquMhxPrMh05IEYFXQqt0S6-6YK8gBw/pub).
A changelog for the course can be found [here](https://docs.google.com/a/knowlabs.com/document/d/193xJb_OpcNCqgquMhxPrMh05IEYFXQqt0S6-6YK8gBw/pub).
3 changes: 3 additions & 0 deletions app/build.gradle
Expand Up @@ -17,6 +17,9 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildTypes.each {
it.buildConfigField 'String', 'OPEN_WEATHER_MAP_API_KEY', MyOpenWeatherMapApiKey
}
}

dependencies {
Expand Down

This file was deleted.

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.sunshine.app;

import android.test.suitebuilder.TestSuiteBuilder;

import junit.framework.Test;
import junit.framework.TestSuite;

public class FullTestSuite extends TestSuite {
public static Test suite() {
return new TestSuiteBuilder(FullTestSuite.class)
.includeAllPackagesUnderHere().build();
}

public FullTestSuite() {
super();
}
}
@@ -0,0 +1,237 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.sunshine.app.data;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.test.AndroidTestCase;

import java.util.HashSet;

public class TestDb extends AndroidTestCase {

public static final String LOG_TAG = TestDb.class.getSimpleName();

// Since we want each test to start with a clean slate
void deleteTheDatabase() {
mContext.deleteDatabase(WeatherDbHelper.DATABASE_NAME);
}

/*
This function gets called before each test is executed to delete the database. This makes
sure that we always have a clean test.
*/
public void setUp() {
deleteTheDatabase();
}

/*
Students: Uncomment this test once you've written the code to create the Location
table. Note that you will have to have chosen the same column names that I did in
my solution for this test to compile, so if you haven't yet done that, this is
a good time to change your column names to match mine.

Note that this only tests that the Location table has the correct columns, since we
give you the code for the weather table. This test does not look at the
*/
public void testCreateDb() throws Throwable {
// build a HashSet of all of the table names we wish to look for
// Note that there will be another table in the DB that stores the
// Android metadata (db version information)
final HashSet<String> tableNameHashSet = new HashSet<String>();
tableNameHashSet.add(WeatherContract.LocationEntry.TABLE_NAME);
tableNameHashSet.add(WeatherContract.WeatherEntry.TABLE_NAME);

mContext.deleteDatabase(WeatherDbHelper.DATABASE_NAME);
SQLiteDatabase db = new WeatherDbHelper(
this.mContext).getWritableDatabase();
assertEquals(true, db.isOpen());

// have we created the tables we want?
Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);

assertTrue("Error: This means that the database has not been created correctly",
c.moveToFirst());

// verify that the tables have been created
do {
tableNameHashSet.remove(c.getString(0));
} while( c.moveToNext() );

// if this fails, it means that your database doesn't contain both the location entry
// and weather entry tables
assertTrue("Error: Your database was created without both the location entry and weather entry tables",
tableNameHashSet.isEmpty());

// now, do our tables contain the correct columns?
c = db.rawQuery("PRAGMA table_info(" + WeatherContract.LocationEntry.TABLE_NAME + ")",
null);

assertTrue("Error: This means that we were unable to query the database for table information.",
c.moveToFirst());

// Build a HashSet of all of the column names we want to look for
final HashSet<String> locationColumnHashSet = new HashSet<String>();
locationColumnHashSet.add(WeatherContract.LocationEntry._ID);
locationColumnHashSet.add(WeatherContract.LocationEntry.COLUMN_CITY_NAME);
locationColumnHashSet.add(WeatherContract.LocationEntry.COLUMN_COORD_LAT);
locationColumnHashSet.add(WeatherContract.LocationEntry.COLUMN_COORD_LONG);
locationColumnHashSet.add(WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING);

int columnNameIndex = c.getColumnIndex("name");
do {
String columnName = c.getString(columnNameIndex);
locationColumnHashSet.remove(columnName);
} while(c.moveToNext());

// if this fails, it means that your database doesn't contain all of the required location
// entry columns
assertTrue("Error: The database doesn't contain all of the required location entry columns",
locationColumnHashSet.isEmpty());
db.close();
}

/*
Students: Here is where you will build code to test that we can insert and query the
location database. We've done a lot of work for you. You'll want to look in TestUtilities
where you can uncomment out the "createNorthPoleLocationValues" function. You can
also make use of the ValidateCurrentRecord function from within TestUtilities.
*/
public void testLocationTable() {
insertLocation();
}

/*
Students: Here is where you will build code to test that we can insert and query the
database. We've done a lot of work for you. You'll want to look in TestUtilities
where you can use the "createWeatherValues" function. You can
also make use of the validateCurrentRecord function from within TestUtilities.
*/
public void testWeatherTable() {
// First insert the location, and then use the locationRowId to insert
// the weather. Make sure to cover as many failure cases as you can.

// Instead of rewriting all of the code we've already written in testLocationTable
// we can move this code to insertLocation and then call insertLocation from both
// tests. Why move it? We need the code to return the ID of the inserted location
// and our testLocationTable can only return void because it's a test.

long locationRowId = insertLocation();

// Make sure we have a valid row ID.
assertFalse("Error: Location Not Inserted Correctly", locationRowId == -1L);

// First step: Get reference to writable database
// If there's an error in those massive SQL table creation Strings,
// errors will be thrown here when you try to get a writable database.
WeatherDbHelper dbHelper = new WeatherDbHelper(mContext);
SQLiteDatabase db = dbHelper.getWritableDatabase();

// Second Step (Weather): Create weather values
ContentValues weatherValues = TestUtilities.createWeatherValues(locationRowId);

// Third Step (Weather): Insert ContentValues into database and get a row ID back
long weatherRowId = db.insert(WeatherContract.WeatherEntry.TABLE_NAME, null, weatherValues);
assertTrue(weatherRowId != -1);

// Fourth Step: Query the database and receive a Cursor back
// A cursor is your primary interface to the query results.
Cursor weatherCursor = db.query(
WeatherContract.WeatherEntry.TABLE_NAME, // Table to Query
null, // leaving "columns" null just returns all the columns.
null, // cols for "where" clause
null, // values for "where" clause
null, // columns to group by
null, // columns to filter by row groups
null // sort order
);

// Move the cursor to the first valid database row and check to see if we have any rows
assertTrue( "Error: No Records returned from location query", weatherCursor.moveToFirst() );

// Fifth Step: Validate the location Query
TestUtilities.validateCurrentRecord("testInsertReadDb weatherEntry failed to validate",
weatherCursor, weatherValues);

// Move the cursor to demonstrate that there is only one record in the database
assertFalse( "Error: More than one record returned from weather query",
weatherCursor.moveToNext() );

// Sixth Step: Close cursor and database
weatherCursor.close();
dbHelper.close();
}


/*
Students: This is a helper method for the testWeatherTable quiz. You can move your
code from testLocationTable to here so that you can call this code from both
testWeatherTable and testLocationTable.
*/
public long insertLocation() {
// First step: Get reference to writable database
// If there's an error in those massive SQL table creation Strings,
// errors will be thrown here when you try to get a writable database.
WeatherDbHelper dbHelper = new WeatherDbHelper(mContext);
SQLiteDatabase db = dbHelper.getWritableDatabase();

// Second Step: Create ContentValues of what you want to insert
// (you can use the createNorthPoleLocationValues if you wish)
ContentValues testValues = TestUtilities.createNorthPoleLocationValues();

// Third Step: Insert ContentValues into database and get a row ID back
long locationRowId;
locationRowId = db.insert(WeatherContract.LocationEntry.TABLE_NAME, null, testValues);

// Verify we got a row back.
assertTrue(locationRowId != -1);

// Data's inserted. IN THEORY. Now pull some out to stare at it and verify it made
// the round trip.

// Fourth Step: Query the database and receive a Cursor back
// A cursor is your primary interface to the query results.
Cursor cursor = db.query(
WeatherContract.LocationEntry.TABLE_NAME, // Table to Query
null, // all columns
null, // Columns for the "where" clause
null, // Values for the "where" clause
null, // columns to group by
null, // columns to filter by row groups
null // sort order
);

// Move the cursor to a valid database row and check to see if we got any records back
// from the query
assertTrue( "Error: No Records returned from location query", cursor.moveToFirst() );

// Fifth Step: Validate data in resulting Cursor with the original ContentValues
// (you can use the validateCurrentRecord function in TestUtilities to validate the
// query if you like)
TestUtilities.validateCurrentRecord("Error: Location Query Validation Failed",
cursor, testValues);

// Move the cursor to demonstrate that there is only one record in the database
assertFalse( "Error: More than one record returned from location query",
cursor.moveToNext() );

// Sixth Step: Close Cursor and Database
cursor.close();
db.close();
return locationRowId;
}
}