diff --git a/app/build.gradle b/app/build.gradle index e23eed873..e3d4c9d1d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -54,7 +54,6 @@ dependencies { compile 'com.squareup.picasso:picasso:2.4.0' compile 'com.android.support:recyclerview-v7:22.2.0' compile 'org.threeten:threetenbp:1.2' - compile 'com.koushikdutta.ion:ion:2.+' compile 'com.github.johnkil.android-robototextview:robototextview:2.4.0' compile 'com.jpardogo.materialtabstrip:library:1.0.9' compile 'com.cocosw:bottomsheet:1.+@aar' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b44663250..76473cd2d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -84,26 +84,6 @@ - - - - paths; protected static HashMap queries; + protected static String userName; + protected static String password; + private static MitEndpoint mitEndpoint = MitEndpoint.create(); private static RequestInterceptor requestInterceptor = new RequestInterceptor() { @@ -83,21 +94,39 @@ public void intercept(RequestFacade request) { } queries.clear(); } + + if (!TextUtils.isEmpty(userName) && !TextUtils.isEmpty(password)) { + String credentials = userName + ":" + password; + String base64EncodedCredentials = new String(Base64.encode(credentials.getBytes(), Base64.NO_WRAP)); + request.addHeader("Authorization", "Basic " + base64EncodedCredentials); + } } }; - protected static RestAdapter MIT_REST_ADAPTER = new RestAdapter.Builder() - .setEndpoint(mitEndpoint) - .setConverter(new GsonConverter(gson)) - .setLog(new RestAdapter.Log() { - @Override - public void log(String message) { - Timber.d(message); - } - }) - .setRequestInterceptor(requestInterceptor) - .setLogLevel(RestAdapter.LogLevel.FULL) - .build(); + protected static RestAdapter MIT_REST_ADAPTER; + + static { + CookieManager cookieManager = new CookieManager(); + cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); + + OkHttpClient client = new OkHttpClient(); + client.setCookieHandler(cookieManager); + + OkClient restServiceClient = new OkClient(client); + MIT_REST_ADAPTER = new RestAdapter.Builder() + .setEndpoint(mitEndpoint) + .setClient(restServiceClient) + .setConverter(new GsonConverter(gson)) + .setLog(new RestAdapter.Log() { + @Override + public void log(String message) { + Timber.d(message); + } + }) + .setRequestInterceptor(requestInterceptor) + .setLogLevel(RestAdapter.LogLevel.FULL) + .build(); + } public static void changeEndpoint(String url) { if (mitEndpoint.getUrl() != null) { diff --git a/app/src/main/java/edu/mit/mitmobile2/dining/activities/DiningActivity.java b/app/src/main/java/edu/mit/mitmobile2/dining/activities/DiningActivity.java deleted file mode 100644 index cf5b1ee70..000000000 --- a/app/src/main/java/edu/mit/mitmobile2/dining/activities/DiningActivity.java +++ /dev/null @@ -1,21 +0,0 @@ -package edu.mit.mitmobile2.dining.activities; - -import edu.mit.mitmobile2.MITMainActivity; -import edu.mit.mitmobile2.R; - -import android.os.Bundle; -import android.util.Log; - -public class DiningActivity extends MITMainActivity { - - protected String mTitle = "Dining"; - - - @Override - protected void onCreate(Bundle savedInstanceState) { - Log.d("ZZZ","DINING ACTIVITY"); - this.setContentLayoutId(R.layout.content_dining); - super.onCreate(savedInstanceState); - } - -} diff --git a/app/src/main/java/edu/mit/mitmobile2/libraries/LibrariesActivity.java b/app/src/main/java/edu/mit/mitmobile2/libraries/LibrariesActivity.java deleted file mode 100644 index 64a733075..000000000 --- a/app/src/main/java/edu/mit/mitmobile2/libraries/LibrariesActivity.java +++ /dev/null @@ -1,15 +0,0 @@ -package edu.mit.mitmobile2.libraries; - -import edu.mit.mitmobile2.MITMainActivity; -import edu.mit.mitmobile2.R; - -import android.os.Bundle; - -public class LibrariesActivity extends MITMainActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - this.setContentLayoutId(R.layout.content_libraries); - super.onCreate(savedInstanceState); - } -} diff --git a/app/src/main/java/edu/mit/mitmobile2/libraries/LibrariesFragment.java b/app/src/main/java/edu/mit/mitmobile2/libraries/LibrariesFragment.java index dd2f2f503..034cc6d8a 100644 --- a/app/src/main/java/edu/mit/mitmobile2/libraries/LibrariesFragment.java +++ b/app/src/main/java/edu/mit/mitmobile2/libraries/LibrariesFragment.java @@ -23,7 +23,7 @@ import edu.mit.mitmobile2.MitMobileApplication; import edu.mit.mitmobile2.OttoBusEvent; import edu.mit.mitmobile2.R; -import edu.mit.mitmobile2.libraries.activities.AccountActivity; +import edu.mit.mitmobile2.libraries.activities.LibraryLoginActivity; import edu.mit.mitmobile2.libraries.adapter.LibraryLinksAdapter; import edu.mit.mitmobile2.libraries.model.MITLibrariesLink; import edu.mit.mitmobile2.shared.SharedIntentManager; @@ -91,7 +91,7 @@ public void onItemClick(AdapterView parent, View view, int position, long id) headerView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent intent = new Intent(getActivity(), AccountActivity.class); + Intent intent = new Intent(getActivity(), LibraryLoginActivity.class); startActivity(intent); } }); @@ -134,10 +134,11 @@ public void failure(RetrofitError error) { private void refreshLinks(List mitLibrariesLink) { links.clear(); if (mitLibrariesLink != null) { - // append predefined links here - String[] predefinedLinks = getResources().getStringArray(R.array.predefined_link_titles); - for (String title : predefinedLinks) { - links.add(new MITLibrariesLink(title)); + // add predefined links here + String[] predefinedTitles = getResources().getStringArray(R.array.predefined_link_titles); + String[] predefinedLinks = getResources().getStringArray(R.array.predefined_links); + for (int i = 0; i < predefinedLinks.length; i++) { + links.add(new MITLibrariesLink(predefinedTitles[i], predefinedLinks[i])); } links.addAll(mitLibrariesLink); } diff --git a/app/src/main/java/edu/mit/mitmobile2/libraries/LibraryManager.java b/app/src/main/java/edu/mit/mitmobile2/libraries/LibraryManager.java index 8a615d306..dc67ecdfe 100644 --- a/app/src/main/java/edu/mit/mitmobile2/libraries/LibraryManager.java +++ b/app/src/main/java/edu/mit/mitmobile2/libraries/LibraryManager.java @@ -19,13 +19,16 @@ import edu.mit.mitmobile2.libraries.model.MITLibrariesWorldcatItem; import edu.mit.mitmobile2.shared.logging.LoggingManager; import retrofit.Callback; +import retrofit.client.Response; +import retrofit.http.Body; import retrofit.http.GET; +import retrofit.http.Headers; +import retrofit.http.POST; +import retrofit.mime.TypedString; -/** - * Created by grmartin on 5/7/15. - */ public class LibraryManager extends RetrofitManager { private static final MitLibraryService MIT_LIBRARY_SERVICE = MIT_REST_ADAPTER.create(MitLibraryService.class); + private static final MitSecureService MIT_SECURE_SERVICE = MIT_REST_ADAPTER.create(MitSecureService.class); private static final int LIBRARY_ITEMS_SEARCH_LIMIT = 20; @@ -33,9 +36,17 @@ public class LibraryManager extends RetrofitManager { public static void makeHttpCall(String apiType, String path, HashMap pathParams, HashMap queryParams, Object callback) throws NoSuchFieldException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException { - Method m = findMethodViaDirectReflection(MitLibraryService.class, path, pathParams, queryParams, Callback.class); - LoggingManager.Timber.d("Method = " + m); - m.invoke(MIT_LIBRARY_SERVICE, callback); + if (apiType.equals(Constants.SECURE) && path.equals(Constants.Secure.SECURE_USER_PATH)) { + Method m = findMethodViaDirectReflection(MitSecureService.class, path, pathParams, queryParams, Callback.class); + LoggingManager.Timber.d("Method = " + m); + + m.invoke(MIT_SECURE_SERVICE, callback); + } else { + Method m = findMethodViaDirectReflection(MitLibraryService.class, path, pathParams, queryParams, Callback.class); + LoggingManager.Timber.d("Method = " + m); + + m.invoke(MIT_LIBRARY_SERVICE, callback); + } } @SuppressWarnings("unused") @@ -113,6 +124,36 @@ public static LibraryManagerCall getIdentity(Activity activity, Callback callback) { + LibraryManagerCallWrapper returnValue = new LibraryManagerCallWrapper<>(new MITAPIClient(activity), callback); + + returnValue.getClient().get(Constants.SECURE, Constants.Secure.SECURE_USER_PATH, null, null, returnValue); + + return returnValue; + } + + public static LibraryManagerCall loginUser(Activity activity, Callback callback) { + LibraryManagerCallWrapper returnValue = new LibraryManagerCallWrapper<>(new MITAPIClient(activity), callback); + + returnValue.getClient().get(Constants.LOGIN, "/", null, null, returnValue); + + return returnValue; + } + + public static void postLoginToIdp(TypedString body, Callback callback) { + MIT_SECURE_SERVICE._postloginuser(body, callback); + } + + public static void postAuthToShibboleth(TypedString body, Callback callback) { + MIT_SECURE_SERVICE._postloginuser2(body, callback); + } + + + public static void setUsernameAndPassword(String username, String password) { + RetrofitManager.userName = username; + RetrofitManager.password = password; + } + /* POST requests */ public interface MitLibraryService { @@ -138,6 +179,27 @@ public interface MitLibraryService { void _getuser(Callback callback); } + public interface MitSecureService { + @Headers({ + "Accept: application/vnd.paos+xml,*/*", + "PAOS: ver=\"urn:liberty:paos:2003-08\"; \"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp\";" + }) + @GET(Constants.Secure.SECURE_USER_PATH) + void _getsecure(Callback callback); + + @Headers({ + "Content-Type: application/vnd.paos+xml" + }) + @POST("/idp/profile/SAML2/SOAP/ECP") + void _postloginuser(@Body TypedString obj, Callback callback); + + @Headers({ + "Content-Type: application/vnd.paos+xml" + }) + @POST("/SAML2/ECP") + void _postloginuser2(@Body TypedString obj, Callback callback); + } + public static class LibraryManagerCallWrapper extends MITAPIClient.ApiCallWrapper implements LibraryManagerCall, Callback { public LibraryManagerCallWrapper(MITAPIClient client, Callback callback) { super(client, callback); diff --git a/app/src/main/java/edu/mit/mitmobile2/libraries/activities/LibraryLoginActivity.java b/app/src/main/java/edu/mit/mitmobile2/libraries/activities/LibraryLoginActivity.java index 9d5e5034e..c2a7e03b6 100644 --- a/app/src/main/java/edu/mit/mitmobile2/libraries/activities/LibraryLoginActivity.java +++ b/app/src/main/java/edu/mit/mitmobile2/libraries/activities/LibraryLoginActivity.java @@ -5,9 +5,21 @@ import android.widget.EditText; import android.widget.Switch; +import java.util.List; + +import butterknife.ButterKnife; import butterknife.InjectView; import butterknife.OnClick; import edu.mit.mitmobile2.R; +import edu.mit.mitmobile2.libraries.LibraryManager; +import edu.mit.mitmobile2.shared.logging.LoggingManager; +import retrofit.Callback; +import retrofit.RetrofitError; +import retrofit.client.Header; +import retrofit.client.Response; +import retrofit.mime.TypedByteArray; +import retrofit.mime.TypedInput; +import retrofit.mime.TypedString; public class LibraryLoginActivity extends AppCompatActivity { @@ -24,6 +36,8 @@ public class LibraryLoginActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_library_login); + + ButterKnife.inject(this); } @OnClick(R.id.login_button) @@ -31,11 +45,100 @@ void login() { String user = String.valueOf(username.getText()); String pwd = String.valueOf(password.getText()); - // TODO: Connect with touchstone somehow + LibraryManager.setUsernameAndPassword(null, null); if (saveLoginSwitch.isChecked()) { // TODO: Save login info in AccountUtils? } + + LibraryManager.getLoginAuth(this, new Callback() { + @Override + public void success(Response response, Response response2) { + LoggingManager.Timber.d("Success!"); + + List
headers = response.getHeaders(); + for (Header header : headers) { + if (header.getName() != null && header.getName().equals("Content-Type")) { + if (header.getValue().equals("application/vnd.paos+xml")) { + String xml = getStringFromBody(response.getBody()); + + int i = xml.indexOf(""); + + String relayState = xml.substring(i, k); + relayState = relayState.replaceAll(" S:", " soap11:"); + + TypedString typedString = alterXmlString(xml, "", "", ""); + postUserLoginInfo(relayState, typedString); + return; + } + } + } + } + + @Override + public void failure(RetrofitError error) { + LoggingManager.Timber.e(error.getMessage()); + } + }); + } + + + private void postUserLoginInfo(final String relayState, final TypedString body) { + LibraryManager.changeEndpoint("https://idp.touchstonenetwork.net/"); + LibraryManager.setUsernameAndPassword("mitlibrarytest@gmail.com", "readingrainbow22"); + + LibraryManager.postLoginToIdp(body, new Callback() { + @Override + public void success(Response response, Response response2) { + LoggingManager.Timber.d("Success!"); + + String xml = getStringFromBody(response.getBody()); + + TypedString typedString = alterXmlString(xml, "", relayState); + postLoginAuth(typedString); + } + + @Override + public void failure(RetrofitError error) { + LoggingManager.Timber.e(error.getMessage()); + } + }); + + } + + private void postLoginAuth(TypedString response) { + LibraryManager.changeEndpoint("https://mobile-dev.mit.edu/Shibboleth.sso/"); + + LibraryManager.setUsernameAndPassword(null, null); + + LibraryManager.postAuthToShibboleth(response, new Callback() { + @Override + public void success(Response response, Response response2) { + LoggingManager.Timber.d("Success!"); + } + + @Override + public void failure(RetrofitError error) { + LoggingManager.Timber.e(error.getMessage()); + } + }); + } + + private TypedString alterXmlString(String xml, String start, String end, String substitution) { + int i = xml.indexOf(start); + int k = xml.indexOf(end); + + String before = xml.substring(0, i); + String after = xml.substring(k, xml.length()); + + String postString = before + substitution + after; + return new TypedString(postString); + } + + private String getStringFromBody(TypedInput body) { + TypedByteArray byteArray = (TypedByteArray) body; + return new String(byteArray.getBytes()); } } diff --git a/app/src/main/java/edu/mit/mitmobile2/libraries/model/MITLibrariesLink.java b/app/src/main/java/edu/mit/mitmobile2/libraries/model/MITLibrariesLink.java index 3994c8f50..edffde2b6 100644 --- a/app/src/main/java/edu/mit/mitmobile2/libraries/model/MITLibrariesLink.java +++ b/app/src/main/java/edu/mit/mitmobile2/libraries/model/MITLibrariesLink.java @@ -5,9 +5,6 @@ import com.google.gson.annotations.SerializedName; -/** - * Created by serg on 5/19/15. - */ public class MITLibrariesLink implements Parcelable { @SerializedName("title") @@ -20,8 +17,9 @@ public MITLibrariesLink() { // empty constructor } - public MITLibrariesLink(String title) { + public MITLibrariesLink(String title, String url) { this.title = title; + this.url = url; } public String getTitle() { diff --git a/app/src/main/java/edu/mit/mitmobile2/links/LinksActivity.java b/app/src/main/java/edu/mit/mitmobile2/links/LinksActivity.java deleted file mode 100644 index 2eb0a11f7..000000000 --- a/app/src/main/java/edu/mit/mitmobile2/links/LinksActivity.java +++ /dev/null @@ -1,17 +0,0 @@ -package edu.mit.mitmobile2.links; - -import edu.mit.mitmobile2.MITMainActivity; -import edu.mit.mitmobile2.R; - -import android.os.Bundle; - -public class LinksActivity extends MITMainActivity { - - - @Override - protected void onCreate(Bundle savedInstanceState) { - this.setContentLayoutId(R.layout.content_links); - super.onCreate(savedInstanceState); - } - -} diff --git a/app/src/main/java/edu/mit/mitmobile2/mobius/ResourceViewFragment.java b/app/src/main/java/edu/mit/mitmobile2/mobius/ResourceViewFragment.java index 7d8ed7582..e4c953c68 100644 --- a/app/src/main/java/edu/mit/mitmobile2/mobius/ResourceViewFragment.java +++ b/app/src/main/java/edu/mit/mitmobile2/mobius/ResourceViewFragment.java @@ -26,21 +26,12 @@ import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; -import com.koushikdutta.async.future.FutureCallback; -import com.koushikdutta.ion.Ion; -import com.koushikdutta.ion.Response; +import com.squareup.picasso.Picasso; import org.json.JSONException; import org.json.JSONObject; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import edu.mit.mitmobile2.MITAPIClient; @@ -53,8 +44,6 @@ /** * A fragment representing a single step in a wizard. The fragment shows a dummy title indicating * the page number, along with some dummy text. - * - * */ public class ResourceViewFragment extends Fragment { @@ -67,7 +56,7 @@ public static final ResourceViewFragment newInstance(ResourceItem resourceItem) } @Override - public View onCreateView(final LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { + public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TabHost tabHost; final ResourceItem resourceItem = getArguments().getParcelable("resource"); Timber.d("room = " + resourceItem.getName()); @@ -93,7 +82,7 @@ public View onCreateView(final LayoutInflater inflater, ViewGroup container,Bund imgUrl += resourceItem.getImages()[0] + "?size=large"; Timber.d("image url = " + imgUrl); ImageView resourceImage = (ImageView) v.findViewById(R.id.resource_image); - Ion.with(resourceImage).load(imgUrl); + Picasso.with(getActivity()).load(imgUrl).into(resourceImage); } // Resource Name @@ -101,14 +90,13 @@ public View onCreateView(final LayoutInflater inflater, ViewGroup container,Bund resourceName.setText(resourceItem.getName()); // Resource Status - TextView resource_online = (TextView)v.findViewById(R.id.resource_online); - TextView resource_offline = (TextView)v.findViewById(R.id.resource_offline); + TextView resource_online = (TextView) v.findViewById(R.id.resource_online); + TextView resource_offline = (TextView) v.findViewById(R.id.resource_offline); if (resourceItem.getStatus().equalsIgnoreCase(ResourceItem.ONLINE)) { resource_online.setVisibility(View.VISIBLE); resource_offline.setVisibility(View.GONE); - } - else { + } else { resource_online.setVisibility(View.GONE); resource_offline.setVisibility(View.VISIBLE); } @@ -118,7 +106,7 @@ public View createTabContent(String arg0) { LinearLayout tab1 = (LinearLayout) inflater.inflate(R.layout.resource_shop_tab, null); // Resource Hours - TableLayout resourceHours = (TableLayout)tab1.findViewById(R.id.resource_hours); + TableLayout resourceHours = (TableLayout) tab1.findViewById(R.id.resource_hours); // loop through the roomset hours and combine repeating hours where possible HashMap hoursMap = new HashMap(); @@ -131,9 +119,8 @@ public View createTabContent(String arg0) { if (hoursMap.containsKey(rh.getDay())) { h = hoursMap.get(rh.getDay()) + '\n' + rh.getStart_time() + " - " + rh.getEnd_time(); - hoursMap.put(rh.getDay(),h); - } - else { + hoursMap.put(rh.getDay(), h); + } else { hoursMap.put(rh.getDay(), rh.getStart_time() + " - " + rh.getEnd_time()); } } @@ -165,23 +152,23 @@ public View createTabContent(String arg0) { resourceRoom.setText(resourceItem.getRoom()); //View Map - ImageView resourceViewMap = (ImageView)tab1.findViewById(R.id.resource_view_map); + ImageView resourceViewMap = (ImageView) tab1.findViewById(R.id.resource_view_map); resourceViewMap.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { JSONObject params = new JSONObject("{'where':[]}"); - JSONObject criteria = new JSONObject(); - criteria.put("field", "_id"); - criteria.put("value",resourceItem.get_id()); - params.getJSONArray("where").put(criteria); - Intent i = new Intent(getActivity(),ResourceListActivity.class); - i.putExtra("params",params.toString()); - startActivity(i); + JSONObject criteria = new JSONObject(); + criteria.put("field", "_id"); + criteria.put("value", resourceItem.get_id()); + params.getJSONArray("where").put(criteria); + Intent i = new Intent(getActivity(), ResourceListActivity.class); + i.putExtra("params", params.toString()); + startActivity(i); } catch (JSONException e) { Timber.d(e.getMessage()); } - } + } }); return tab1; } diff --git a/app/src/main/java/edu/mit/mitmobile2/qrreader/QrreaderActivity.java b/app/src/main/java/edu/mit/mitmobile2/qrreader/QrreaderActivity.java deleted file mode 100644 index 6a49b7390..000000000 --- a/app/src/main/java/edu/mit/mitmobile2/qrreader/QrreaderActivity.java +++ /dev/null @@ -1,17 +0,0 @@ -package edu.mit.mitmobile2.qrreader; - -import edu.mit.mitmobile2.MITMainActivity; -import edu.mit.mitmobile2.R; - -import android.os.Bundle; - -public class QrreaderActivity extends MITMainActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - this.setContentLayoutId(R.layout.content_qrreader); - super.onCreate(savedInstanceState); - //setContentView(R.layout.activity_qrreader); - } - -} diff --git a/app/src/main/java/edu/mit/mitmobile2/shuttles/activities/ShuttlesActivity.java b/app/src/main/java/edu/mit/mitmobile2/shuttles/activities/ShuttlesActivity.java deleted file mode 100644 index 4ef402b2c..000000000 --- a/app/src/main/java/edu/mit/mitmobile2/shuttles/activities/ShuttlesActivity.java +++ /dev/null @@ -1,390 +0,0 @@ -package edu.mit.mitmobile2.shuttles.activities; - -import android.app.AlertDialog; -import android.content.ActivityNotFoundException; -import android.content.ContentResolver; -import android.content.DialogInterface; -import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.LoaderManager; -import android.support.v4.content.Loader; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.RelativeLayout; -import android.widget.Toast; - -import java.util.ArrayList; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - -import butterknife.ButterKnife; -import butterknife.InjectView; -import edu.mit.mitmobile2.Constants; -import edu.mit.mitmobile2.DBAdapter; -import edu.mit.mitmobile2.MITMainActivity; -import edu.mit.mitmobile2.MitMobileApplication; -import edu.mit.mitmobile2.PreferenceUtils; -import edu.mit.mitmobile2.R; -import edu.mit.mitmobile2.Schema; -import edu.mit.mitmobile2.shared.MITContentProvider; -import edu.mit.mitmobile2.shuttles.callbacks.ShuttleAdapterCallback; -import edu.mit.mitmobile2.shuttles.utils.ShuttlesDatabaseHelper; -import edu.mit.mitmobile2.shuttles.adapter.MITShuttleAdapter; -import edu.mit.mitmobile2.shuttles.model.MitMiniShuttleRoute; -import edu.mit.mitmobile2.shared.logging.LoggingManager.Timber; - -public class ShuttlesActivity extends MITMainActivity implements ShuttleAdapterCallback, LoaderManager.LoaderCallbacks { - - int contentLayoutId = R.layout.content_shuttles; - - private static final int PREDICTIONS_PERIOD = 20000; - private static final int PREDICTIONS_TIMER_OFFSET = 10000; - private static final int PREDICTIONS_TIMEOUT = 60000; - private static final int ROUTES_TIMEOUT = 80000; - - private int loopCount = 0; - private boolean immediatelyReloadPredictions = false; - private boolean blockServerCalls = false; - - private MITShuttleAdapter mitShuttleAdapter; - private ArrayList mitShuttleRoutes = new ArrayList<>(); - - @InjectView(R.id.shuttle_refresh_layout) - SwipeRefreshLayout shuttleRefreshLayout; - @InjectView(R.id.shuttle_listview) - ListView shuttleListView; - - private static Timer timer; - - @Override - protected void onCreate(Bundle savedInstanceState) { - this.setContentLayoutId(R.layout.content_shuttles); - super.onCreate(savedInstanceState); - - ButterKnife.inject(this); - - if (savedInstanceState != null) { - mitShuttleRoutes = savedInstanceState.getParcelableArrayList("routes"); - mitShuttleAdapter = new MITShuttleAdapter(this, mitShuttleRoutes, null); - } else { - mitShuttleAdapter = new MITShuttleAdapter(this, new ArrayList(), null); - } - shuttleListView.setAdapter(mitShuttleAdapter); - initialShuttleView(); - - shuttleRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { - @Override - public void onRefresh() { - shuttleRefreshLayout.setRefreshing(true); - updateAllRoutes(); - immediatelyReloadPredictions = true; - loopCount = 0; - } - }); - - getSupportLoaderManager().initLoader(0, null, this); - } - - private void loadCursor() { - Cursor cursor = getContentResolver().query(MITContentProvider.ALL_ROUTES_URI, Schema.Route.ALL_COLUMNS, null, null, null); - - List routes = new ArrayList<>(); - ShuttlesDatabaseHelper.generateMiniRouteObjects(routes, cursor); - cursor.close(); - - if (routes.size() > 0) { - routes = sortRoutesByStatus(routes); - } - - mitShuttleAdapter.updateListItems(routes); - } - - private void checkStatusOfDatabase() { - long routesTimestamp = PreferenceUtils.getDefaultSharedPreferencesMultiProcess(this).getLong(Constants.ROUTES_TIMESTAMP, 0); - long diff = System.currentTimeMillis() - routesTimestamp; - if (diff < ROUTES_TIMEOUT) { - long predictionsTimestamp = PreferenceUtils.getDefaultSharedPreferencesMultiProcess(this).getLong(Constants.PREDICTIONS_TIMESTAMP, 0); - if ((System.currentTimeMillis() - predictionsTimestamp) < PREDICTIONS_TIMEOUT) { - // load route info WITH preference data - loadCursor(); - Timber.d("Predictions OK"); - } else { - ShuttlesDatabaseHelper.clearAllPredictions(this); - loadCursor(); - updatePredictions(); - Timber.d("Routes OK, refreshing predictions"); - } - } else { - DBAdapter.getInstance().flushStaleData(); - loadCursor(); - updateAllRoutes(); - immediatelyReloadPredictions = true; - Timber.d("Refreshing routes"); - } - } - - private void startTimerTask() { - timer.schedule(new TimerTask() { - @Override - public void run() { - if (mitShuttleAdapter.getCount() == 0) { - return; - } - - if (timer == null) { - return; - } - - if (blockServerCalls) { - return; - } - - Timber.d("Timer fired"); - - if (loopCount == 5) { - updateAllRoutes(); - immediatelyReloadPredictions = true; - } else { - updatePredictions(); - } - - loopCount++; - loopCount = loopCount % 6; - } - }, PREDICTIONS_TIMER_OFFSET, PREDICTIONS_PERIOD); - } - - private void updatePredictions() { - Bundle bundle = new Bundle(); - bundle.putString(Constants.Shuttles.MODULE_KEY, Constants.SHUTTLES); - bundle.putString(Constants.Shuttles.PATH_KEY, Constants.Shuttles.PREDICTIONS_PATH); - bundle.putString(Constants.Shuttles.URI_KEY, MITContentProvider.PREDICTIONS_URI.toString()); - - String mitTuples = mitShuttleAdapter.getRouteStopTuples("mit"); - String crTuples = mitShuttleAdapter.getRouteStopTuples("charles-river"); - - bundle.putString(Constants.Shuttles.MIT_TUPLES_KEY, mitTuples); - bundle.putString(Constants.Shuttles.CR_TUPLES_KEY, crTuples); - - // FORCE THE SYNC - bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); - bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); - - Timber.d("Requesting Predictions"); - - ContentResolver.requestSync(MitMobileApplication.mAccount, MitMobileApplication.AUTHORITY, bundle); - blockServerCalls = true; - } - - private void updateAllRoutes() { - Bundle bundle = new Bundle(); - bundle.putString(Constants.Shuttles.MODULE_KEY, Constants.SHUTTLES); - bundle.putString(Constants.Shuttles.PATH_KEY, Constants.Shuttles.ALL_ROUTES_PATH); - bundle.putString(Constants.Shuttles.URI_KEY, MITContentProvider.ALL_ROUTES_URI.toString()); - - // FORCE THE SYNC - bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); - bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); - - // Request All Routes info - ContentResolver.requestSync(MitMobileApplication.mAccount, MitMobileApplication.AUTHORITY, bundle); - blockServerCalls = true; - } - - private void initialShuttleView() { - View footer = ((LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE)) - .inflate(R.layout.shuttle_list_footer, null, false); - initialListViewFooter(footer); - shuttleListView.addFooterView(footer); - } - - public List sortRoutesByStatus(List routes) { - List shuttleRouteStatusInService = new ArrayList<>(); - List shuttleRouteStatusNotInservice = new ArrayList<>(); - List shuttleRouteStatusUnknown = new ArrayList<>(); - - for (MitMiniShuttleRoute route : routes) { - if (route.isPredictable()) { - shuttleRouteStatusInService.add(route); - } else if (route.isScheduled()) { - shuttleRouteStatusUnknown.add(route); - } else { - shuttleRouteStatusNotInservice.add(route); - } - } - - routes.clear(); - - for (MitMiniShuttleRoute shuttleRoute : shuttleRouteStatusInService) { - routes.add(shuttleRoute); - } - for (MitMiniShuttleRoute shuttleRoute : shuttleRouteStatusUnknown) { - routes.add(shuttleRoute); - } - for (MitMiniShuttleRoute shuttleRoute : shuttleRouteStatusNotInservice) { - routes.add(shuttleRoute); - } - - for (MitMiniShuttleRoute shuttleRoute : routes) { - mitShuttleRoutes.add(shuttleRoute); - } - - return routes; - } - - public void initialListViewFooter(View footer) { - final RelativeLayout parkOffice = (RelativeLayout) footer.findViewById(R.id.park_office); - final RelativeLayout saferide = (RelativeLayout) footer.findViewById(R.id.saferide); - final LinearLayout realTimeBusArrivals = (LinearLayout) footer.findViewById(R.id.real_time_bus_arrivals); - final LinearLayout realTimeTrainArribals = (LinearLayout) footer.findViewById(R.id.real_time_train_arrivals); - final LinearLayout googleTransit = (LinearLayout) footer.findViewById(R.id.google_transit); - - parkOffice.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - phoneCallDialog(getResources().getString(R.string.parking_office_number)); - } - }); - saferide.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - phoneCallDialog(getResources().getString(R.string.saferide_number)); - } - }); - realTimeBusArrivals.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - openMBTAUrl(getResources().getString(R.string.real_time_bus_url)); - } - }); - realTimeTrainArribals.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - openMBTAUrl(getResources().getString(R.string.real_time_train_url)); - } - }); - googleTransit.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - openMBTAUrl(getResources().getString(R.string.real_time_google_transit_url)); - } - }); - } - - public void phoneCallDialog(final String phoneNumber) { - String[] splittedPhoneNumber = phoneNumber.split("\\."); - new AlertDialog.Builder(this) - .setMessage("Call 1 (" + splittedPhoneNumber[0] + ")" + splittedPhoneNumber[1] + "-" + splittedPhoneNumber[2] + "?") - .setPositiveButton(getResources().getString(R.string.ok_button), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - setPhoneCall(phoneNumber); - } - }) - .setNegativeButton(getResources().getString(R.string.cancel_button), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } - }) - .show(); - } - - public void setPhoneCall(String phoneNumber) { - String uri = "tel:" + phoneNumber.trim(); - Intent intent = new Intent(Intent.ACTION_CALL); - intent.setData(Uri.parse(uri)); - startActivity(intent); - } - - public void openMBTAUrl(String url) { - try { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - } catch (ActivityNotFoundException e) { - Toast.makeText(this, "No application can handle this request. " + - "Please install a map app.", Toast.LENGTH_SHORT).show(); - e.printStackTrace(); - } - } - - @Override - public void shuttleRouteClick(final String routeId) { - Intent intent = new Intent(this, ShuttleRouteActivity.class); - intent.putExtra(Constants.ROUTE_ID_KEY, routeId); - startActivity(intent); - } - - @Override - public void shuttleStopClick(String routeId, String stopId) { - Intent intent = new Intent(this, ShuttleStopActivity.class); - intent.putExtra(Constants.ROUTE_ID_KEY, routeId); - intent.putExtra(Constants.STOP_ID_KEY, stopId); - startActivity(intent); - } - - @Override - public Loader onCreateLoader(int id, Bundle args) { - return null; - } - - @Override - public void onLoadFinished(Loader loader, Cursor data) { - if (data.getCount() == 0) { - return; - } - - Timber.d("Notified!"); - blockServerCalls = false; - - if (!immediatelyReloadPredictions) { - List routes = new ArrayList<>(); - ShuttlesDatabaseHelper.generateMiniRouteObjects(routes, data); - routes = sortRoutesByStatus(routes); - mitShuttleAdapter.updateListItems(routes); - - runOnUiThread(new Runnable() { - @Override - public void run() { - if (shuttleRefreshLayout.isRefreshing()) { - shuttleRefreshLayout.setRefreshing(false); - } - } - }); - } else { - immediatelyReloadPredictions = false; - updatePredictions(); - } - } - - @Override - public void onLoaderReset(Loader loader) { - } - - @Override - protected void onResume() { - super.onResume(); - checkStatusOfDatabase(); - timer = new Timer(); - startTimerTask(); - } - - @Override - protected void onPause() { - timer.cancel(); - timer.purge(); - timer = null; - super.onPause(); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putParcelableArrayList("routes", mitShuttleRoutes); - } -} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7c2aa5b3a..84f99f9b5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -229,9 +229,21 @@ MON - SUN + Search Locations & Hours + Find a Study Space Ask Us Tell Us + News & Events + + + + http://libraries.mit.edu/search/ + http://libraries.mit.edu/hours/ + http://libraries.mit.edu/study/ + http://libraries.mit.edu/ask/ + http://libraries.mit.edu/tellus + http://libraries.mit.edu/news/ Touchstone diff --git a/build.gradle b/build.gradle index 0454307c7..81db73b43 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { maven { url "http://maven.restlet.com" } } dependencies { - classpath 'com.android.tools.build:gradle:1.2.3' + classpath 'com.android.tools.build:gradle:1.3.0' } }