Java tutorial
/* * Copyright 2012 Feedlr * * 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.chalmers.feedlr.service; import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; import com.chalmers.feedlr.activity.FeedActivity; import com.chalmers.feedlr.client.FacebookHelper; import com.chalmers.feedlr.client.TwitterHelper; import com.chalmers.feedlr.database.DatabaseHelper; import com.chalmers.feedlr.model.FacebookItem; import com.chalmers.feedlr.model.Feed; import com.chalmers.feedlr.model.TwitterItem; import com.chalmers.feedlr.model.User; import com.chalmers.feedlr.parser.FacebookJSONParser; import com.chalmers.feedlr.parser.TwitterJSONParser; import com.facebook.android.FacebookError; import android.app.Service; import android.content.Intent; import android.database.Cursor; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; /** * The DataService class handles requests, response parsing and database storage * of client data. On call from an Activity the service makes the necessary * requests to client APIs, parses the received JSON response and stores all * relevant data to the application database. When a complete request has been * made and all data has successfully been saved to the database a broadcast is * made to inform listeners that new data is avalable for display. * * @author Olle Werme */ public class DataService extends Service { private final IBinder binder = new FeedServiceBinder(); private LocalBroadcastManager lbm; private TwitterHelper twitter; private FacebookHelper facebook; private DatabaseHelper db; public class FeedServiceBinder extends Binder { DataService getService() { return DataService.this; } } @Override public int onStartCommand(Intent intent, int flags, int startId) { lbm = LocalBroadcastManager.getInstance(DataService.this); twitter = new TwitterHelper(this); facebook = new FacebookHelper(); db = new DatabaseHelper(this); return START_STICKY; } @Override public IBinder onBind(Intent arg0) { return binder; } /** * Simple method for running tasks asynchronous. * * @param runnable * the runnable to be run */ private void runAsync(final Runnable runnable) { new Thread() { @Override public void run() { runnable.run(); } }.start(); } /** * Populates the application database ITEM table with the most recent tweets * from the registered users twitter timeline. This method is currently not * in use. */ public void updateTwitterTimeline() { runAsync(new Runnable() { @Override public void run() { long time = System.currentTimeMillis(); List<TwitterItem> twitterTimeline = twitter.getTimeline(); if (twitterTimeline != null) { // Save to database db.addListOfItems(twitterTimeline); } // Broadcast update to activity Intent intent = new Intent(); intent.setAction(FeedActivity.FEED_UPDATED); lbm.sendBroadcast(intent); Log.i(TwitterJSONParser.class.getName(), "Time in millis for complete Twitter timeline request: " + (System.currentTimeMillis() - time)); } }); } /** * Updates application database USER table with the registered users * "following users" from his or her Twitter account, also known as * "friends". */ public void updateTwitterUsers() { runAsync(new Runnable() { @Override public void run() { long time = System.currentTimeMillis(); Intent intent = new Intent(); List<User> users = twitter.getFollowing(); if (users != null) { // Save to database db.addUsers(users); intent.setAction(FeedActivity.TWITTER_USERS_UPDATED); } else { intent.setAction(FeedActivity.TWITTER_USERS_PROBLEM_UPDATING); } // Broadcast update to activity lbm.sendBroadcast(intent); Log.i(TwitterJSONParser.class.getName(), "Time in millis for complete Twitter following request: " + (System.currentTimeMillis() - time)); } }); } /** * Populates application database ITEM table with the most recent tweets * from the user with the given userID within a specific feed. * * This method is currently not in use. * * @param userID * the id for the user * @param feed * the feed that sent the request */ private void updateTweetsByUser(final String userID, final Feed feed) { runAsync(new Runnable() { @Override public void run() { long time = System.currentTimeMillis(); Intent intent = new Intent(); List<TwitterItem> userTweets = twitter.getUserTweets(userID); if (userTweets != null) { db.addListOfItems(userTweets); intent.setAction(FeedActivity.FEED_UPDATED); } else { intent.setAction(FeedActivity.FEED_PROBLEM_UPDATING); } // Broadcast update to activity Bundle b = new Bundle(); b.putString("feedTitle", feed.getTitle()); intent.putExtras(b); lbm.sendBroadcast(intent); Log.i(TwitterJSONParser.class.getName(), "Time in millis for complete Twitter user tweets request: " + (System.currentTimeMillis() - time)); } }); } /** * Populates application database ITEM table with the most recent tweets * from all the users in the specified feed through {@link * #updateTweetsByUser(final String userID, final Feed feed) * updateTweetsByUser}. * * @param feed * the feed to be updated */ public void updateFeedTwitterItems(final Feed feed) { runAsync(new Runnable() { @Override public void run() { final List<User> twitterUsersInFeed = new ArrayList<User>(); Cursor c = db.getUsers(feed, "twitter"); c.moveToFirst(); while (!c.isAfterLast()) { User u = new User(c.getString(c.getColumnIndex(DatabaseHelper.USER_COLUMN_USERID)), c.getString(c.getColumnIndex(DatabaseHelper.USER_COLUMN_USERNAME))); twitterUsersInFeed.add(u); c.moveToNext(); } for (User u : twitterUsersInFeed) { updateTweetsByUser(u.getId(), feed); } } }); } /** * Updates application database USER table with all the friends the * registered user has on its facebook account. */ public void updateFacebookUsers() { final long time = System.currentTimeMillis(); facebook.getFriends(new com.facebook.android.AsyncFacebookRunner.RequestListener() { @Override public void onComplete(String response, Object state) { if (response != null) { List<User> users = new FacebookJSONParser().parseUsers(response); for (User u : users) { u.setSource("facebook"); u.setProfileImageURL(facebook.getProfileImageURL(u.getId())); } db.addUsers(users); // Broadcast update to activity Intent intent = new Intent(); intent.setAction(FeedActivity.FACEBOOK_USERS_UPDATED); lbm.sendBroadcast(intent); Log.i(FacebookJSONParser.class.getName(), "Time in millis for complete Facebook friends request: " + (System.currentTimeMillis() - time)); } } @Override public void onFacebookError(FacebookError e, final Object state) { Log.e("Parse", "Facebook Error:" + e.getMessage()); } @Override public void onFileNotFoundException(FileNotFoundException e, final Object state) { Log.e("Parse", "Resource not found:" + e.getMessage()); } @Override public void onIOException(IOException e, final Object state) { Log.e("Parse", "Network Error:" + e.getMessage()); } @Override public void onMalformedURLException(MalformedURLException e, final Object state) { Log.e("Parse", "Invalid URL:" + e.getMessage()); } }); } /** * Populates the application database ITEM table with the most recent feed * from the registered users facebook timeline. * * This method is currently not in use. */ public void updateFacebookTimeline() { final long time = System.currentTimeMillis(); facebook.getTimeline(new com.facebook.android.AsyncFacebookRunner.RequestListener() { @Override public void onComplete(String response, Object state) { if (response != null) { List<FacebookItem> facebookTimeline = new FacebookJSONParser().parseFeed(response); // save to database // Broadcast update to activity Intent intent = new Intent(); intent.setAction(FeedActivity.FACEBOOK_USERS_UPDATED); lbm.sendBroadcast(intent); Log.i(FacebookJSONParser.class.getName(), "Time in millis for complete Facebook friends request: " + (System.currentTimeMillis() - time)); } } @Override public void onFacebookError(FacebookError e, final Object state) { Log.e("Parse", "Facebook Error:" + e.getMessage()); } @Override public void onFileNotFoundException(FileNotFoundException e, final Object state) { Log.e("Parse", "Resource not found:" + e.getMessage()); } @Override public void onIOException(IOException e, final Object state) { Log.e("Parse", "Network Error:" + e.getMessage()); } @Override public void onMalformedURLException(MalformedURLException e, final Object state) { Log.e("Parse", "Invalid URL:" + e.getMessage()); } }); // Broadcast update to activity Intent intent = new Intent(); intent.setAction(FeedActivity.FACEBOOK_TIMELINE_UPDATED); lbm.sendBroadcast(intent); Log.i(FacebookJSONParser.class.getName(), "Time in millis for complete Facebook timeline request: " + (System.currentTimeMillis() - time)); } /* * Populates application database ITEM table with the most recent facebook * feed updates from the users in the feed. */ public void updateFeedFacebookItems(final Feed feed) { final long time = System.currentTimeMillis(); final List<User> facebookUsersInFeed = new ArrayList<User>(); final List<FacebookItem> facebookItemsForUsers = new ArrayList<FacebookItem>(); Cursor c = db.getUsers(feed, "facebook"); c.moveToFirst(); while (!c.isAfterLast()) { facebookUsersInFeed.add(new User(c.getString(c.getColumnIndex(DatabaseHelper.USER_COLUMN_USERID)), c.getString(c.getColumnIndex(DatabaseHelper.USER_COLUMN_USERNAME)))); c.moveToNext(); } facebook.getFeedsForUsers(facebookUsersInFeed, new com.facebook.android.AsyncFacebookRunner.RequestListener() { private int responses = 0; @Override public void onComplete(String response, Object state) { try { if (response != null) { facebookItemsForUsers.addAll(new FacebookJSONParser().parseFeed(response)); } } catch (Exception e) { Log.e(getClass().getName(), e.getMessage()); } responses++; if (responses == facebookUsersInFeed.size()) { onAllComplete(); } } private void onAllComplete() { db.addListOfItems(facebookItemsForUsers); // Broadcast update to activity Intent intent = new Intent(); intent.setAction(FeedActivity.FEED_UPDATED); Bundle b = new Bundle(); b.putString("feedTitle", feed.getTitle()); intent.putExtras(b); lbm.sendBroadcast(intent); Log.i(TwitterJSONParser.class.getName(), "Time in millis for complete update of feed \"" + feed.getTitle() + "\" facebook items request: " + (System.currentTimeMillis() - time)); } @Override public void onFacebookError(FacebookError e, final Object state) { Log.e("Parse", "Facebook Error:" + e.getMessage()); } @Override public void onFileNotFoundException(FileNotFoundException e, final Object state) { Log.e("Parse", "Resource not found:" + e.getMessage()); } @Override public void onIOException(IOException e, final Object state) { Log.e("Parse", "Network Error:" + e.getMessage()); } @Override public void onMalformedURLException(MalformedURLException e, final Object state) { Log.e("Parse", "Invalid URL:" + e.getMessage()); } }); } }