Big documentation (no functionality) update

ugly-unit-test
Bradlee Speice 2014-05-10 20:20:16 -04:00
parent 8292dc91a1
commit 4e01ff666e
11 changed files with 146 additions and 50 deletions

View File

@ -7,32 +7,56 @@ import dagger.ObjectGraph;
public class MinimalBible extends Application { public class MinimalBible extends Application {
/**
* The graph used by Dagger to track dependencies
*/
private ObjectGraph graph; private ObjectGraph graph;
/**
* A singleton reference to the Application currently being run.
* Used mostly so we have a fixed point to get the App Context from
*/
private static MinimalBible instance; private static MinimalBible instance;
/**
* Create the application, and persist the application Context
*/
public MinimalBible() { public MinimalBible() {
instance = this; instance = this;
} }
/**
* Get the Application Context. Please note, all attempts to get the App Context should come
* through here, and please be sure that the Application won't satisfy what you need.
* @return The Application Context
*/
public static Context getAppContext() { public static Context getAppContext() {
return instance; return instance;
} }
public static MinimalBible getApplication(Context ctx) { /**
return (MinimalBible)ctx.getApplicationContext(); * Get the Application, rather than just the Application Context. You likely should be using
} * this, rather than {@link #getAppContext()}
* @return The MinimalBible {@link android.app.Application} object
*/
public static MinimalBible getApplication() { public static MinimalBible getApplication() {
return (MinimalBible)getAppContext(); return (MinimalBible)getAppContext();
} }
/**
* Create the {@link android.app.Application}. Responsible for building and
* holding on to the master ObjectGraph.
*/
@Override @Override
public void onCreate() { public void onCreate() {
graph = ObjectGraph.create(new MinimalBibleModules()); graph = ObjectGraph.create(new MinimalBibleModules());
graph.inject(this); graph.inject(this);
} }
/**
* Inject a Dagger object
* @param o The object to be injected
*/
public void inject(Object o) { public void inject(Object o) {
graph.inject(o); graph.inject(o);
} }

View File

@ -5,7 +5,7 @@ import org.bspeice.minimalbible.activities.ActivityModules;
import dagger.Module; import dagger.Module;
/** /**
* Modules for the global application * Master module for MinimalBible
*/ */
@Module( @Module(
injects = { injects = {

View File

@ -8,10 +8,12 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarActivity;
/**
* Wrapper for activities in MinimalBible to make sure we can support
* common functionality between them all.
*/
public class BaseActivity extends ActionBarActivity { public class BaseActivity extends ActionBarActivity {
// BaseActivity to take care of some stuff like setting the action bar color
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);

View File

@ -0,0 +1,26 @@
package org.bspeice.minimalbible.activities;
import android.app.Activity;
import android.os.Build;
import android.support.v4.app.Fragment;
import android.view.View;
import com.readystatesoftware.systembartint.SystemBarTintManager;
/**
* Base class that defines all behavior common to Fragments in MinimalBible
*/
public class BaseFragment extends Fragment {
/**
* Calculate the offset we need to display properly if the System bar is translucent
* @param context The {@link android.app.Activity} we are displaying in
* @param view The {@link android.view.View} we need to calculate the offset for.
*/
public static void setInsets(Activity context, View view) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
SystemBarTintManager tintManager = new SystemBarTintManager(context);
SystemBarTintManager.SystemBarConfig config = tintManager.getConfig();
view.setPadding(0, config.getPixelInsetTop(true), config.getPixelInsetRight(), config.getPixelInsetBottom());
}
}

View File

@ -26,7 +26,7 @@ public class ActivityDownloaderModule {
* Provide a Singleton DownloadManager for injection * Provide a Singleton DownloadManager for injection
* Note that we need to annotate Singleton here, only annotating on the * Note that we need to annotate Singleton here, only annotating on the
* DownloadManager itself is not enough. * DownloadManager itself is not enough.
* @return global DownloadManager instance * @return Global DownloadManager instance
*/ */
@Provides @Singleton @Provides @Singleton
DownloadManager provideDownloadManager() { DownloadManager provideDownloadManager() {

View File

@ -4,9 +4,7 @@ import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -14,11 +12,9 @@ import android.view.ViewGroup;
import android.widget.ListView; import android.widget.ListView;
import android.widget.Toast; import android.widget.Toast;
import com.readystatesoftware.systembartint.SystemBarTintManager;
import org.androidannotations.annotations.sharedpreferences.Pref;
import org.bspeice.minimalbible.MinimalBible; import org.bspeice.minimalbible.MinimalBible;
import org.bspeice.minimalbible.R; import org.bspeice.minimalbible.R;
import org.bspeice.minimalbible.activities.BaseFragment;
import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager; import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager;
import org.bspeice.minimalbible.activities.downloader.manager.EventBookList; import org.bspeice.minimalbible.activities.downloader.manager.EventBookList;
import org.crosswire.jsword.book.Book; import org.crosswire.jsword.book.Book;
@ -27,7 +23,6 @@ import org.crosswire.jsword.book.BookComparators;
import org.crosswire.jsword.book.BookFilter; import org.crosswire.jsword.book.BookFilter;
import org.crosswire.jsword.book.FilterUtil; import org.crosswire.jsword.book.FilterUtil;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -40,7 +35,7 @@ import butterknife.InjectView;
* A placeholder fragment containing a simple view. * A placeholder fragment containing a simple view.
*/ */
public class BookListFragment extends Fragment { public class BookListFragment extends BaseFragment {
/** /**
* The fragment argument representing the section number for this fragment. * The fragment argument representing the section number for this fragment.
*/ */
@ -72,7 +67,7 @@ public class BookListFragment extends Fragment {
@Override @Override
public void onCreate(Bundle state) { public void onCreate(Bundle state) {
super.onCreate(state); super.onCreate(state);
MinimalBible.getApplication().inject(this); MinimalBible.getApplication().inject(this); // Injection for Dagger goes here, not ctor
} }
@Override @Override
@ -92,6 +87,10 @@ public class BookListFragment extends Fragment {
.getString(ARG_BOOK_CATEGORY)); .getString(ARG_BOOK_CATEGORY));
} }
/**
* Trigger the functionality to display a list of modules. Prompts user if downloading
* from the internet is allowable.
*/
public void displayModules() { public void displayModules() {
boolean dialogDisplayed = downloadPrefs.showedDownloadDialog().get(); boolean dialogDisplayed = downloadPrefs.showedDownloadDialog().get();
@ -108,16 +107,22 @@ public class BookListFragment extends Fragment {
} }
} }
/**
* Do the work of refreshing modules (download manager handles using cached copy vs. actual
* refresh), and then displaying them when ready.
*/
private void refreshModules() { private void refreshModules() {
EventBookList bookList = downloadManager.getDownloadBus().getStickyEvent(EventBookList.class); // Check if the downloadManager has already refreshed everything
List<Book> bookList = downloadManager.getBookList();
if (bookList == null) { if (bookList == null) {
downloadManager.getDownloadBus().registerSticky(this); // downloadManager is in progress of refreshing
downloadManager.getDownloadBus().register(this);
refreshDialog = new ProgressDialog(getActivity()); refreshDialog = new ProgressDialog(getActivity());
refreshDialog.setMessage("Refreshing available modules..."); refreshDialog.setMessage("Refreshing available modules...");
refreshDialog.setCancelable(false); refreshDialog.setCancelable(false);
refreshDialog.show(); refreshDialog.show();
} else { } else {
displayBooks(bookList.getBookList()); displayBooks(bookList);
} }
} }
@ -132,17 +137,13 @@ public class BookListFragment extends Fragment {
displayBooks(event.getBookList()); displayBooks(event.getBookList());
} }
public static void setInsets(Activity context, View view) { /**
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return; * Do the hard work of creating the Adapter and displaying books.
SystemBarTintManager tintManager = new SystemBarTintManager(context); * @param bookList The (unfiltered) list of {link org.crosswire.jsword.Book}s to display
SystemBarTintManager.SystemBarConfig config = tintManager.getConfig(); */
view.setPadding(0, config.getPixelInsetTop(true), config.getPixelInsetRight(), config.getPixelInsetBottom());
}
public void displayBooks(List<Book> bookList) { public void displayBooks(List<Book> bookList) {
try { try {
// TODO: Should the filter be applied earlier in the process? // TODO: Should the filter be applied earlier in the process?
// TODO: Sort books by name?
List<Book> displayList; List<Book> displayList;
BookCategory c = BookCategory.fromString(getArguments().getString(ARG_BOOK_CATEGORY)); BookCategory c = BookCategory.fromString(getArguments().getString(ARG_BOOK_CATEGORY));
@ -156,7 +157,6 @@ public class BookListFragment extends Fragment {
// To be honest, there should be no reason you end up here. // To be honest, there should be no reason you end up here.
Log.e(TAG, e.getMessage()); Log.e(TAG, e.getMessage());
} }
} }
private class DownloadDialogListener implements private class DownloadDialogListener implements

View File

@ -44,6 +44,7 @@ public class DownloadActivity extends BaseActivity implements
@Override @Override
public void onNavigationDrawerItemSelected(int position) { public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments // update the main content by replacing fragments
//TODO: Switch to AutoFactory pattern, rather than newInstance()
FragmentManager fragmentManager = getSupportFragmentManager(); FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager fragmentManager
.beginTransaction() .beginTransaction()

View File

@ -1,6 +1,6 @@
/* /*
This is brutally ugly, but until https://github.com/square/dagger/issues/410 is resolved, This is brutally ugly, but until https://github.com/square/dagger/issues/410 is resolved,
this is the best I can do while making sure that I can refactor the API later. this is the best I can do while making sure that I can easily switch the API later
*/ */
// //
// DO NOT EDIT THIS FILE, IT HAS BEEN GENERATED USING AndroidAnnotations 3.0.1. // DO NOT EDIT THIS FILE, IT HAS BEEN GENERATED USING AndroidAnnotations 3.0.1.

View File

@ -9,7 +9,6 @@ import android.util.Log;
import org.bspeice.minimalbible.MinimalBible; import org.bspeice.minimalbible.MinimalBible;
import org.bspeice.minimalbible.activities.downloader.DownloadPrefs_; import org.bspeice.minimalbible.activities.downloader.DownloadPrefs_;
import org.crosswire.jsword.book.Book; import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookFilter;
import org.crosswire.jsword.book.install.InstallException; import org.crosswire.jsword.book.install.InstallException;
import org.crosswire.jsword.book.install.Installer; import org.crosswire.jsword.book.install.Installer;
@ -30,19 +29,12 @@ public class BookRefreshTask extends AsyncTask<Installer, Integer, List<Book>> {
DownloadPrefs_ downloadPrefs; DownloadPrefs_ downloadPrefs;
private EventBus downloadBus; private EventBus downloadBus;
private BookFilter filter;
public BookRefreshTask(EventBus downloadBus) { public BookRefreshTask(EventBus downloadBus) {
this.downloadBus = downloadBus; this.downloadBus = downloadBus;
MinimalBible.getApplication().inject(this); MinimalBible.getApplication().inject(this);
} }
public BookRefreshTask(EventBus downloadBus, BookFilter f) {
this.downloadBus = downloadBus;
this.filter = f;
MinimalBible.getApplication().inject(this);
}
@Override @Override
protected List<Book> doInBackground(Installer... params) { protected List<Book> doInBackground(Installer... params) {
List<Book> books = new LinkedList<Book>(); List<Book> books = new LinkedList<Book>();
@ -60,11 +52,7 @@ public class BookRefreshTask extends AsyncTask<Installer, Integer, List<Book>> {
} }
} }
if (filter != null) {
books.addAll(i.getBooks(filter));
} else {
books.addAll(i.getBooks()); books.addAll(i.getBooks());
}
publishProgress(++index, params.length); publishProgress(++index, params.length);
} }

View File

@ -3,10 +3,12 @@ package org.bspeice.minimalbible.activities.downloader.manager;
import android.util.Log; import android.util.Log;
import org.bspeice.minimalbible.MinimalBible; import org.bspeice.minimalbible.MinimalBible;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookCategory; import org.crosswire.jsword.book.BookCategory;
import org.crosswire.jsword.book.install.InstallManager; import org.crosswire.jsword.book.install.InstallManager;
import org.crosswire.jsword.book.install.Installer; import org.crosswire.jsword.book.install.Installer;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
@ -19,6 +21,11 @@ public class DownloadManager {
private final String TAG = "DownloadManager"; private final String TAG = "DownloadManager";
/**
* Cached copy of modules that are available so we don't refresh for everyone who requests it.
*/
private List<Book> availableModules = null;
@Inject @Inject
protected EventBus downloadBus; protected EventBus downloadBus;
@ -26,21 +33,37 @@ public class DownloadManager {
BookCategory.COMMENTARY, BookCategory.DICTIONARY, BookCategory.COMMENTARY, BookCategory.DICTIONARY,
BookCategory.MAPS }; BookCategory.MAPS };
/**
* Set up the DownloadManager, and notify jSword of where it should store files at
*/
public DownloadManager() { public DownloadManager() {
MinimalBible.getApplication().inject(this); MinimalBible.getApplication().inject(this);
setDownloadDir(); setDownloadDir();
downloadEvents(); refreshModules();
} }
/**
* Get the installers available to jSword - this is how we get access to the actual modules
* @return All available {@link org.crosswire.jsword.book.install.Installer}s
*/
public Map<String, Installer> getInstallers() { public Map<String, Installer> getInstallers() {
return new InstallManager().getInstallers(); return new InstallManager().getInstallers();
} }
/**
* Helper method to transform the installers map to an array
* @return Array with all available {@link org.crosswire.jsword.book.install.Installer} objects
*/
public Installer[] getInstallersArray() { public Installer[] getInstallersArray() {
Map<String, Installer> installers = getInstallers(); Map<String, Installer> installers = getInstallers();
return installers.values().toArray(new Installer[installers.size()]); return installers.values().toArray(new Installer[installers.size()]);
} }
/**
* Notify jSword that it needs to store files in the Android internal directory
* NOTE: Android will uninstall these files if you uninstall MinimalBible.
*/
@SuppressWarnings("null")
private void setDownloadDir() { private void setDownloadDir() {
// We need to set the download directory for jSword to stick with // We need to set the download directory for jSword to stick with
// Android. // Android.
@ -49,10 +72,38 @@ public class DownloadManager {
System.setProperty("jsword.home", home); System.setProperty("jsword.home", home);
} }
private void downloadEvents() { /**
* Do the work of kicking off the AsyncTask to refresh books, and make sure we know
* when it's done.
*/
private void refreshModules() {
downloadBus.register(this);
new BookRefreshTask(downloadBus).execute(getInstallersArray()); new BookRefreshTask(downloadBus).execute(getInstallersArray());
} }
/**
* When book refresh is done, cache the list so we can give that to someone else
* @param event A POJO wrapper around the Book list
*/
@SuppressWarnings("unused")
public void onEvent(EventBookList event) {
this.availableModules = event.getBookList();
}
/**
* Get the cached book list
* @return The cached book list, or null
*/
public List<Book> getBookList() {
return availableModules;
}
/**
* Get the current download bus if you want to know when refresh is done.
* Please note that you will not be notified if the book refresh has already
* been completed, make sure to check {@link #getBookList()} first.
* @return The EventBus the DownloadManager is using
*/
public EventBus getDownloadBus() { public EventBus getDownloadBus() {
return this.downloadBus; return this.downloadBus;
} }

View File

@ -4,6 +4,10 @@ import java.util.List;
import org.crosswire.jsword.book.Book; import org.crosswire.jsword.book.Book;
/**
* POJO class for {@link de.greenrobot.event.EventBus} to broadcast whenever
* we've finished updating the book list.
*/
public class EventBookList { public class EventBookList {
private List<Book> bookList; private List<Book> bookList;