diff --git a/HW5/AndroidManifest.xml b/HW5/AndroidManifest.xml index de2d868..12c2964 100644 --- a/HW5/AndroidManifest.xml +++ b/HW5/AndroidManifest.xml @@ -32,6 +32,10 @@ android:name="edu.uncc.itcs4180.hw5.DetailedTweetActivity" android:label="@string/title_activity_detailed_tweet" > + + diff --git a/HW5/libs/android-support-v4.jar b/HW5/libs/android-support-v4.jar deleted file mode 100644 index 9056828..0000000 Binary files a/HW5/libs/android-support-v4.jar and /dev/null differ diff --git a/HW5/project.properties b/HW5/project.properties index 4ab1256..fae65bb 100644 --- a/HW5/project.properties +++ b/HW5/project.properties @@ -12,3 +12,4 @@ # Project target. target=android-19 +android.library.reference.1=../../../workspace/appcompat_v7_5 diff --git a/HW5/res/layout/activity_saved_news.xml b/HW5/res/layout/activity_saved_news.xml new file mode 100644 index 0000000..a722e1d --- /dev/null +++ b/HW5/res/layout/activity_saved_news.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/HW5/res/layout/saved_tweets_list.xml b/HW5/res/layout/saved_tweets_list.xml new file mode 100644 index 0000000..47f1295 --- /dev/null +++ b/HW5/res/layout/saved_tweets_list.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HW5/res/menu/saved_news.xml b/HW5/res/menu/saved_news.xml new file mode 100644 index 0000000..1b04039 --- /dev/null +++ b/HW5/res/menu/saved_news.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/HW5/res/values-w820dp/dimens.xml b/HW5/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..f9f069f --- /dev/null +++ b/HW5/res/values-w820dp/dimens.xml @@ -0,0 +1,10 @@ + + + + 64dp + + diff --git a/HW5/res/values/strings.xml b/HW5/res/values/strings.xml index 9d3c2dc..c724dfd 100644 --- a/HW5/res/values/strings.xml +++ b/HW5/res/values/strings.xml @@ -6,5 +6,6 @@ Hello world! TweetsListActivity DetailedTweetActivity + SavedNewsActivity diff --git a/HW5/src/edu/uncc/itcs4180/hw5/MainActivity.java b/HW5/src/edu/uncc/itcs4180/hw5/MainActivity.java index a523aa8..97024b9 100644 --- a/HW5/src/edu/uncc/itcs4180/hw5/MainActivity.java +++ b/HW5/src/edu/uncc/itcs4180/hw5/MainActivity.java @@ -3,8 +3,11 @@ package edu.uncc.itcs4180.hw5; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import edu.uncc.itcs4180.hw5.database.DataManager; +import edu.uncc.itcs4180.hw5.database.SavedTweet; import edu.uncc.itcs4180.hw5.twitter.TweetList; import edu.uncc.itcs4180.hw5.twitter.TwitterClient; import android.os.Bundle; @@ -26,6 +29,8 @@ public class MainActivity extends Activity { private static final Map newsSites; private static final String[] newsSitesTitles; + private static DataManager dm; + static { Map mMap = new LinkedHashMap(); // Put news sites here @@ -42,6 +47,8 @@ public class MainActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + dm = new DataManager(this); + dm.saveTweet(new SavedTweet(0, "apple", "Stuff about an apple", "00:00:12", "")); // Set up all the news feeds ListView feeds = (ListView)findViewById(R.id.listNewsFeeds); @@ -70,12 +77,26 @@ public class MainActivity extends Activity { } public void onViewSaved(View v) { - + SavedTweet t = dm.getTweet(1); + if(t!=null) + { + Intent i = new Intent(MainActivity.this, SavedNewsActivity.class); + startActivity(i); + } + else + { + Toast.makeText(this, "No saved tweets to view", Toast.LENGTH_SHORT).show(); + } } public void onClearSaved(View v) { - // TODO: Implement the database clearing functionality here. + dm.deleteAll(); Toast.makeText(this, "All Saved News are Cleared!", Toast.LENGTH_SHORT).show(); } + protected void onDestroy() + { + dm.close(); + super.onDestroy(); + } } diff --git a/HW5/src/edu/uncc/itcs4180/hw5/SavedNewsActivity.java b/HW5/src/edu/uncc/itcs4180/hw5/SavedNewsActivity.java new file mode 100644 index 0000000..d28396e --- /dev/null +++ b/HW5/src/edu/uncc/itcs4180/hw5/SavedNewsActivity.java @@ -0,0 +1,58 @@ +package edu.uncc.itcs4180.hw5; + +import java.util.List; + +import edu.uncc.itcs4180.hw5.database.DataManager; +import edu.uncc.itcs4180.hw5.database.SavedTweet; +import edu.uncc.itcs4180.hw5.twitter.Tweet; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.ListAdapter; +import android.widget.ListView; + +public class SavedNewsActivity extends Activity { + + private List tweets; + private DataManager dm; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_saved_news); + + dm = new DataManager(this); + tweets = dm.getAllTweets(); + ListView lv = (ListView)findViewById(R.id.listTweetList); + ListAdapter la = new SavedNewsAdapter(this, tweets.toArray(new SavedTweet[tweets.size()])); + lv.setAdapter(la); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.saved_news, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + if (id == R.id.action_settings) { + return true; + } + return super.onOptionsItemSelected(item); + } + + protected void onDestroy() + { + dm.close(); + super.onDestroy(); + } +} diff --git a/HW5/src/edu/uncc/itcs4180/hw5/SavedNewsAdapter.java b/HW5/src/edu/uncc/itcs4180/hw5/SavedNewsAdapter.java new file mode 100644 index 0000000..46ef2dd --- /dev/null +++ b/HW5/src/edu/uncc/itcs4180/hw5/SavedNewsAdapter.java @@ -0,0 +1,65 @@ +package edu.uncc.itcs4180.hw5; + +import edu.uncc.itcs4180.hw5.database.SavedTweet; +import android.app.Activity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; + +public class SavedNewsAdapter extends ArrayAdapter +{ + private final int TWEET_TAG_KEY = 1337; + Activity activity; + SavedTweet[] tweets; + + public SavedNewsAdapter(Activity activity, SavedTweet[] tweets) { + super(activity, R.layout.saved_tweets_list, tweets); + this.tweets = tweets; + this.activity = activity; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View rowView = convertView; + TweetView tv = null; + SavedTweet tweet = tweets[position]; + + if (rowView == null) { + // Inflate a new row + rowView = activity.getLayoutInflater().inflate(R.layout.tweet_list, null); + + tv = new TweetView(); + tv.imgProfileImage = (ImageView) rowView.findViewById(R.id.imgProfileImage); + tv.txtTweetText = (TextView) rowView.findViewById(R.id.txtTweetText); + tv.txtTweetInfo = (TextView) rowView.findViewById(R.id.txtTweetInfo); + tv.imgIsRetweet = (ImageView) rowView.findViewById(R.id.imgIsRetweet); + + rowView.setTag(tv); + rowView.setTag(R.id.TWEET_TAG_KEY, tweet); + } else { + tv = (TweetView) rowView.getTag(); + } + + // Add information to the current row + // Start up our BitmapDownloader - it will update the ImageView for us + new BitmapDownloader(tv.imgProfileImage).execute(tweet.getProfileImageUrl()); + tv.txtTweetText.setText(tweet.getText()); + tv.txtTweetInfo.setText(tweet.getTime()); + // Set the retweet image + //if (tweet.isRetweet()) { + tv.imgIsRetweet.setImageDrawable(activity.getResources().getDrawable(R.drawable.retweeted)); + //} + + return rowView; + } + + protected static class TweetView { + ImageView imgProfileImage; + TextView txtTweetText; + TextView txtTweetInfo; + ImageView imgIsRetweet; + } +} diff --git a/HW5/src/edu/uncc/itcs4180/hw5/TweetListAdapter.java b/HW5/src/edu/uncc/itcs4180/hw5/TweetListAdapter.java index a3dbfaf..8adab55 100644 --- a/HW5/src/edu/uncc/itcs4180/hw5/TweetListAdapter.java +++ b/HW5/src/edu/uncc/itcs4180/hw5/TweetListAdapter.java @@ -7,6 +7,8 @@ import java.net.URL; import org.apache.http.HttpConnection; +import edu.uncc.itcs4180.hw5.database.DataManager; +import edu.uncc.itcs4180.hw5.database.SavedTweet; import edu.uncc.itcs4180.hw5.twitter.Tweet; import android.app.Activity; import android.content.Context; @@ -24,11 +26,13 @@ public class TweetListAdapter extends ArrayAdapter { private final int TWEET_TAG_KEY = 1337; Activity activity; Tweet[] tweets; + private static DataManager dm; public TweetListAdapter(Activity activity, Tweet[] tweets) { super(activity, R.layout.tweet_list, tweets); this.tweets = tweets; this.activity = activity; + dm = new DataManager(activity.getBaseContext()); } @Override @@ -64,10 +68,11 @@ public class TweetListAdapter extends ArrayAdapter { tv.imgIsRetweet.setImageDrawable(activity.getResources().getDrawable(R.drawable.retweeted)); } // Save tweets when we are clicked + tv.ibtnSaveTweet.setTag(tweet); tv.ibtnSaveTweet.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - saveTweet((Tweet)v.getTag(TWEET_TAG_KEY)); + saveTweet((Tweet)v.getTag()); } }); @@ -83,7 +88,12 @@ public class TweetListAdapter extends ArrayAdapter { } private void saveTweet(Tweet t) { - // TODO: Save tweets here. + SavedTweet save = new SavedTweet(); + save.setUsername(t.getUser().getName()); + save.setText(t.getText()); + save.setTime(t.getDateCreated()); + save.setProfileImageUrl(t.getUser().getProfileImageUrl()); + dm.saveTweet(save); Toast.makeText(activity, "Saved in DB!", Toast.LENGTH_SHORT).show(); } diff --git a/HW5/src/edu/uncc/itcs4180/hw5/database/DataManager.java b/HW5/src/edu/uncc/itcs4180/hw5/database/DataManager.java new file mode 100644 index 0000000..c17df53 --- /dev/null +++ b/HW5/src/edu/uncc/itcs4180/hw5/database/DataManager.java @@ -0,0 +1,57 @@ +package edu.uncc.itcs4180.hw5.database; + +import java.util.List; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; + +public class DataManager +{ + Context mContext; + DatabaseHelper dbOpenHelper; + SQLiteDatabase db; + SavedTweetDAO tweetDao; + + public DataManager(Context mContext) + { + this.mContext = mContext; + dbOpenHelper = new DatabaseHelper(mContext); + db = dbOpenHelper.getWritableDatabase(); + tweetDao = new SavedTweetDAO(db); + } + + public void close() + { + db.close(); + } + + public long saveTweet(SavedTweet tweet) + { + return tweetDao.save(tweet); + } + + public boolean updateTweet(SavedTweet tweet) + { + return tweetDao.update(tweet); + } + + public boolean deleteTweet(SavedTweet tweet) + { + return tweetDao.delete(tweet); + } + + public SavedTweet getTweet(long id) + { + return tweetDao.get(id); + } + + public List getAllTweets() + { + return tweetDao.getAll(); + } + + public boolean deleteAll() + { + return tweetDao.deleteAll(); + } +} diff --git a/HW5/src/edu/uncc/itcs4180/hw5/database/DatabaseHelper.java b/HW5/src/edu/uncc/itcs4180/hw5/database/DatabaseHelper.java new file mode 100644 index 0000000..5c9771b --- /dev/null +++ b/HW5/src/edu/uncc/itcs4180/hw5/database/DatabaseHelper.java @@ -0,0 +1,37 @@ +package edu.uncc.itcs4180.hw5.database; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +public class DatabaseHelper extends SQLiteOpenHelper +{ + final static String DATABASE_NAME = "savedtweets.db"; + final static int DATABASE_VERSION = 1; + final static String TAG = "STdb1"; + + DatabaseHelper(Context mContext) + { + super(mContext, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onOpen(SQLiteDatabase db) + { + super.onOpen(db); + } + + @Override + public void onCreate(SQLiteDatabase db) + { + SavedTweetTable.onCreate(db); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) + { + Log.w(TAG, "Upgrading db from version "+ oldVersion+ " to "+ newVersion); + SavedTweetTable.onUpgrade(db, oldVersion, newVersion); + } +} diff --git a/HW5/src/edu/uncc/itcs4180/hw5/database/SavedTweet.java b/HW5/src/edu/uncc/itcs4180/hw5/database/SavedTweet.java new file mode 100644 index 0000000..80bf940 --- /dev/null +++ b/HW5/src/edu/uncc/itcs4180/hw5/database/SavedTweet.java @@ -0,0 +1,75 @@ +package edu.uncc.itcs4180.hw5.database; + +public class SavedTweet +{ + private long id; + private String username; + private String text; + private String time; + private String profileImageUrl; + + public SavedTweet() + { + this.id= 0; + this.username = ""; + this.text = ""; + this.time = ""; + this.profileImageUrl = ""; + } + + public SavedTweet(long id, String username, String text, String time, String profileImageUrl) + { + this.id= id; + this.username = username; + this.text = text; + this.time = time; + this.profileImageUrl = profileImageUrl; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } + + public String getProfileImageUrl() { + return profileImageUrl; + } + + public void setProfileImageUrl(String profileImageUrl) { + this.profileImageUrl = profileImageUrl; + } + + @Override + public String toString() { + return "SavedTweet [id=" + id + ", username=" + username + ", text=" + + text + ", time=" + time + ", profileImageUrl=" + + profileImageUrl + "]"; + } +} diff --git a/HW5/src/edu/uncc/itcs4180/hw5/database/SavedTweetDAO.java b/HW5/src/edu/uncc/itcs4180/hw5/database/SavedTweetDAO.java new file mode 100644 index 0000000..ae6fa91 --- /dev/null +++ b/HW5/src/edu/uncc/itcs4180/hw5/database/SavedTweetDAO.java @@ -0,0 +1,123 @@ +package edu.uncc.itcs4180.hw5.database; + +import java.util.ArrayList; +import java.util.List; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; + +public class SavedTweetDAO +{ + private SQLiteDatabase db; + + public SavedTweetDAO(SQLiteDatabase db) + { + this.db = db; + } + + public long save(SavedTweet tweet) + { + ContentValues values = new ContentValues(); + values.put(SavedTweetTable.USER_NAME, tweet.getUsername()); + values.put(SavedTweetTable.TEXT, tweet.getText()); + values.put(SavedTweetTable.TIME, tweet.getTime()); + values.put(SavedTweetTable.PROFILE_IMAGE_URL, tweet.getProfileImageUrl()); + return db.insert(SavedTweetTable.TABLE_NAME, null, values); + } + + public boolean update(SavedTweet tweet) + { + ContentValues values = new ContentValues(); + values.put(SavedTweetTable.USER_NAME, tweet.getUsername()); + values.put(SavedTweetTable.TEXT, tweet.getText()); + values.put(SavedTweetTable.TIME, tweet.getTime()); + values.put(SavedTweetTable.PROFILE_IMAGE_URL, tweet.getProfileImageUrl()); + return db.update(SavedTweetTable.TABLE_NAME, values, SavedTweetTable.ID+"="+tweet.getId(), null)<0; + } + + public boolean delete(SavedTweet tweet) + { + return db.delete(SavedTweetTable.TABLE_NAME, SavedTweetTable.ID+"="+tweet.getId(), null)>0; + } + + public SavedTweet get(long id) + { + SavedTweet tweet = null; + Cursor c = db.query(true, SavedTweetTable.TABLE_NAME, + new String[]{SavedTweetTable.ID, SavedTweetTable.USER_NAME, SavedTweetTable.TEXT, SavedTweetTable.TIME, SavedTweetTable.PROFILE_IMAGE_URL}, + SavedTweetTable.ID+"="+id, null, null, null, null, null); + if(c!=null) + { + c.moveToFirst(); + tweet = this.buildFromCursor(c); + } + if(!c.isClosed()) + { + c.close(); + } + return tweet; + } + + public List getAll() + { + List list = new ArrayList(); + Cursor c = db.query(SavedTweetTable.TABLE_NAME, + new String[]{SavedTweetTable.ID, SavedTweetTable.USER_NAME, SavedTweetTable.TEXT, SavedTweetTable.TIME, SavedTweetTable.PROFILE_IMAGE_URL}, + null, null, null, null, null); + if(c!=null) + { + c.moveToFirst(); + do + { + SavedTweet tweet = this.buildFromCursor(c); + if(tweet != null) + { + list.add(tweet); + } + }while(c.moveToNext()); + } + if(!c.isClosed()) + { + c.close(); + } + return list; + } + + private SavedTweet buildFromCursor(Cursor c) + { + SavedTweet tweet = null; + if(c!=null) + { + try + { + tweet = new SavedTweet(); + tweet.setId(c.getLong(0)); + tweet.setUsername(c.getString(1)); + tweet.setText(c.getString(2)); + tweet.setTime(c.getString(3)); + tweet.setProfileImageUrl(c.getString(4)); + } + catch(Exception e) + { + return null; + } + } + return tweet; + } + + public boolean deleteAll() + { + try + { + db.execSQL("delete from "+ SavedTweetTable.TABLE_NAME); + db.execSQL("delete from sqlite_sequence where name='"+ SavedTweetTable.TABLE_NAME+"'"); + return true; + } + catch(SQLException e) + { + return false; + } + } +} diff --git a/HW5/src/edu/uncc/itcs4180/hw5/database/SavedTweetTable.java b/HW5/src/edu/uncc/itcs4180/hw5/database/SavedTweetTable.java new file mode 100644 index 0000000..e521b26 --- /dev/null +++ b/HW5/src/edu/uncc/itcs4180/hw5/database/SavedTweetTable.java @@ -0,0 +1,39 @@ +package edu.uncc.itcs4180.hw5.database; + +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; + +public class SavedTweetTable +{ + final static String TABLE_NAME = "savedtweets"; + final static String ID = "_id"; + final static String USER_NAME = "username"; + final static String TEXT = "text"; + final static String TIME = "time"; + final static String PROFILE_IMAGE_URL = "profileimageurl"; + + public static void onCreate(SQLiteDatabase db) + { + String createTableSql = "CREATE TABLE "+ SavedTweetTable.TABLE_NAME + "("+ + SavedTweetTable.ID+ " integer primary key autoincrement, "+ + SavedTweetTable.USER_NAME+ " text not null, "+ + SavedTweetTable.TEXT+ " text not null, "+ + SavedTweetTable.TIME+ " text not null, "+ + SavedTweetTable.PROFILE_IMAGE_URL+ " text not null);"; + + try + { + db.execSQL(createTableSql); + } + catch(SQLException e) + { + e.printStackTrace(); + } + } + + public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) + { + db.execSQL("DROP TABLE IF EXISTS "+ SavedTweetTable.TABLE_NAME); + SavedTweetTable.onCreate(db); + } +}