package org.mtransit.android.ui.fragment; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.concurrent.TimeUnit; import org.mtransit.android.R; import org.mtransit.android.commons.ArrayUtils; import org.mtransit.android.commons.BundleUtils; import org.mtransit.android.commons.CollectionUtils; import org.mtransit.android.commons.Constants; import org.mtransit.android.commons.LocationUtils; import org.mtransit.android.commons.MTLog; import org.mtransit.android.commons.SensorUtils; import org.mtransit.android.commons.TaskUtils; import org.mtransit.android.commons.TimeUtils; import org.mtransit.android.commons.data.News; import org.mtransit.android.commons.data.POIStatus; import org.mtransit.android.commons.data.RouteTripStop; import org.mtransit.android.commons.data.Schedule; import org.mtransit.android.commons.data.ServiceUpdate; import org.mtransit.android.commons.provider.NewsProviderContract; import org.mtransit.android.commons.provider.POIProviderContract; import org.mtransit.android.commons.task.MTAsyncTask; import org.mtransit.android.data.AgencyProperties; import org.mtransit.android.data.DataSourceManager; import org.mtransit.android.data.DataSourceProvider; import org.mtransit.android.data.NewsProviderProperties; import org.mtransit.android.data.POIArrayAdapter; import org.mtransit.android.data.POIManager; import org.mtransit.android.data.ScheduleProviderProperties; import org.mtransit.android.provider.FavoriteManager; import org.mtransit.android.task.NearbyPOIListLoader; import org.mtransit.android.ui.MTActivityWithLocation; import org.mtransit.android.ui.MainActivity; import org.mtransit.android.ui.view.MTOnClickListener; import org.mtransit.android.ui.view.MapViewController; import org.mtransit.android.ui.view.POINewsViewController; import org.mtransit.android.ui.view.POIServiceUpdateViewController; import org.mtransit.android.ui.view.POIStatusDetailViewController; import org.mtransit.android.ui.view.POIViewController; import org.mtransit.android.util.LinkUtils; import org.mtransit.android.util.LoaderUtils; import org.mtransit.android.util.MapUtils; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.res.Configuration; import android.graphics.Color; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.location.Location; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.widget.AbsListView; import android.widget.ScrollView; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; public class POIFragment extends ABFragment implements LoaderManager.LoaderCallbacks<ArrayList<POIManager>>, POIViewController.POIDataProvider, MTActivityWithLocation.UserLocationListener, SensorEventListener, SensorUtils.CompassListener, SensorUtils.SensorTaskCompleted, FavoriteManager.FavoriteUpdateListener, TimeUtils.TimeChangedReceiver.TimeChangedListener, MapViewController.MapMarkerProvider, MapViewController.MapListener { private static final String TAG = POIFragment.class.getSimpleName(); @Override public String getLogTag() { if (!TextUtils.isEmpty(this.uuid)) { return TAG + "-" + this.uuid; } return TAG; } private static final String TRACKING_SCREEN_NAME = "POI"; @Override public String getScreenName() { if (!TextUtils.isEmpty(this.uuid)) { return TRACKING_SCREEN_NAME + "/" + this.uuid; } return TRACKING_SCREEN_NAME; } private static final String EXTRA_AUTHORITY = "extra_agency_authority"; private static final String EXTRA_POI_UUID = "extra_poi_uuid"; public static POIFragment newInstance(String uuid, String authority, AgencyProperties optAgency, POIManager optPoim) { POIFragment f = new POIFragment(); Bundle args = new Bundle(); args.putString(EXTRA_AUTHORITY, authority); f.authority = authority; f.agency = optAgency; args.putString(EXTRA_POI_UUID, uuid); f.uuid = uuid; f.poim = optPoim; f.setPOIProperties(); f.setArguments(args); return f; } private String authority; private AgencyProperties agency; private MapViewController mapViewController = new MapViewController(TAG, this, this, false, true, false, false, false, false, 32, true, false, true, true, false); private boolean hasAgency() { if (this.agency == null) { initAgencyAsync(); return false; } return true; } private void initAgencyAsync() { if (this.loadAgencyTask != null && this.loadAgencyTask.getStatus() == MTAsyncTask.Status.RUNNING) { return; } if (TextUtils.isEmpty(this.authority)) { return; } this.loadAgencyTask = new LoadAgencyTask(); TaskUtils.execute(this.loadAgencyTask); } private LoadAgencyTask loadAgencyTask = null; private class LoadAgencyTask extends MTAsyncTask<Void, Void, Boolean> { @Override public String getLogTag() { return POIFragment.this.getLogTag() + ">" + LoadAgencyTask.class.getSimpleName(); } @Override protected Boolean doInBackgroundMT(Void... params) { return initAgencySync(); } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (result) { applyNewAgency(); } } } private AgencyProperties getAgencyOrNull() { if (!hasAgency()) { return null; } return this.agency; } private boolean initAgencySync() { if (this.agency != null) { return false; } if (!TextUtils.isEmpty(this.authority)) { this.agency = DataSourceProvider.get(getActivity()).getAgency(getActivity(), this.authority); } return this.agency != null; } private void applyNewAgency() { if (this.agency == null) { return; } POIManager poim = getPoimOrNull(); if (poim != null) { POIStatusDetailViewController.updateView(getActivity(), getPOIStatusView(getView()), poim, this); } getAbController().setABTitle(this, getABTitle(getActivity()), false); getAbController().setABReady(this, isABReady(), true); } private void resetAgency() { this.agency = null; } private String uuid; private POIManager poim; private boolean hasPoim() { if (this.poim == null) { initPoimAsync(); return false; } return true; } private void initPoimAsync() { if (this.loadPoimTask != null && this.loadPoimTask.getStatus() == MTAsyncTask.Status.RUNNING) { return; } if (TextUtils.isEmpty(this.uuid) || TextUtils.isEmpty(this.authority)) { return; } this.loadPoimTask = new LoadPoimTask(); TaskUtils.execute(this.loadPoimTask); } private LoadPoimTask loadPoimTask = null; private class LoadPoimTask extends MTAsyncTask<Void, Void, Boolean> { @Override public String getLogTag() { return POIFragment.this.getLogTag() + ">" + LoadPoimTask.class.getSimpleName(); } @Override protected Boolean doInBackgroundMT(Void... params) { return initPoimSync(); } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (result) { applyNewPoim(); } } } private POIManager getPoimOrNull() { if (!hasPoim()) { return null; } return this.poim; } private boolean initPoimSync() { if (this.poim != null) { return false; } if (!TextUtils.isEmpty(this.uuid) && !TextUtils.isEmpty(this.authority)) { this.poim = DataSourceManager.findPOI(getActivity(), this.authority, POIProviderContract.Filter.getNewUUIDFilter(this.uuid)); } return this.poim != null; } private void setPOIProperties() { if (this.poim != null) { this.poim.setInFocus(true); this.poim.setScheduleMaxDataRequests(Schedule.ScheduleStatusFilter.DATA_REQUEST_MONTHS); this.poim.resetLastFindTimestamps(); } } private void applyNewPoim() { if (this.poim == null) { return; } setPOIProperties(); if (this.adapter != null) { this.adapter.clear(); } resetFavorite(); View view = getView(); FragmentActivity activity = getActivity(); this.mapViewController.notifyMarkerChanged(this); this.mapViewController.showMap(view); POIViewController.updateView(activity, getPOIView(view), this.poim, this); POIStatusDetailViewController.updateView(activity, getPOIStatusView(view), this.poim, this); POIServiceUpdateViewController.updateView(activity, getPOIServiceUpdateView(view), this.poim, this); POINewsViewController.updateView(activity, getPOINewsView(view), getNewsOrNull()); setupRTSFullScheduleBtn(view); setupMoreNewsButton(view); setupMoreNearbyButton(view); if (activity != null) { activity.supportInvalidateOptionsMenu(); // add/remove star from action bar } setupNearbyList(); } private ArrayList<News> news; private ArrayList<News> getNewsOrNull() { if (!hasNews()) { return null; } return this.news; } private boolean hasNews() { if (this.news == null) { initNewsAsync(); return false; } return true; } private void initNewsAsync() { if (this.loadNewsTask != null && this.loadNewsTask.getStatus() == MTAsyncTask.Status.RUNNING) { return; } if (!hasPoim()) { return; } this.loadNewsTask = new LoadNewsTask(); TaskUtils.execute(this.loadNewsTask); } private LoadNewsTask loadNewsTask = null; private class LoadNewsTask extends MTAsyncTask<Void, Void, Boolean> { @Override public String getLogTag() { return POIFragment.this.getLogTag() + ">" + LoadNewsTask.class.getSimpleName(); } @Override protected Boolean doInBackgroundMT(Void... params) { return initNewsSync(); } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (result) { applyNewNews(); } } } private boolean initNewsSync() { if (this.news != null) { return false; } POIManager poim = getPoimOrNull(); if (poim == null) { return false; } Context context = getActivity(); if (context == null) { return false; } this.news = new ArrayList<News>(); HashSet<NewsProviderProperties> poiNewsProviders = DataSourceProvider.get(context).getTargetAuthorityNewsProviders(poim.poi.getAuthority()); if (CollectionUtils.getSize(poiNewsProviders) == 0) { return true; // no news, need to apply } long nowInMs = TimeUtils.currentTimeMillis(); long minCreatedAtInMs = nowInMs - TimeUnit.DAYS.toMillis(7); ArrayList<News> allNews = new ArrayList<News>(); for (NewsProviderProperties poiNewsProvider : poiNewsProviders) { ArrayList<News> providerNews = DataSourceManager.findNews(context, poiNewsProvider.getAuthority(), NewsProviderContract.Filter.getNewTargetFilter(poim.poi).setMinCreatedAtInMs(minCreatedAtInMs)); if (providerNews != null) { allNews.addAll(providerNews); } } if (CollectionUtils.getSize(allNews) == 0) { return true; // no news, need to apply } CollectionUtils.sort(allNews, News.NEWS_SEVERITY_COMPARATOR); for (News news : allNews) { if (nowInMs - news.getCreatedAtInMs() <= news.getNoteworthyInMs()) { this.news.add(0, news); break; } } return true; // need to apply } private void applyNewNews() { if (this.news == null) { return; } POINewsViewController.updateView(getActivity(), getPOINewsView(getView()), this.news); } @Override public POIManager getClosestPOI() { return this.poim; } @Override public POIManager getPOI(String uuid) { return this.poim != null && this.poim.poi.getUUID().equals(uuid) ? this.poim : null; } @Override public Collection<POIManager> getPOIs() { if (this.poim == null) { return null; } return Collections.singletonList(this.poim); } @Override public Collection<MapViewController.POIMarker> getPOMarkers() { return null; } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); this.mapViewController.onConfigurationChanged(newConfig); } @Override public void onCameraChange(LatLngBounds latLngBounds) { } @Override public void onMapClick(LatLng position) { POIManager poim = getPoimOrNull(); FragmentActivity activity = getActivity(); if (poim != null && activity != null) { ((MainActivity) activity).addFragmentToStack(MapFragment.newInstance(LocationUtils.getNewLocation(poim.getLat(), poim.getLng()), poim.poi.getUUID(), poim.poi.getDataSourceTypeId())); } } private void resetPoim() { this.poim = null; } @Override public void onAttach(Activity activity) { super.onAttach(activity); initAdapters(activity); this.mapViewController.onAttach(activity); } @Override public void onDetach() { super.onDetach(); this.mapViewController.onDetach(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); restoreInstanceState(savedInstanceState, getArguments()); this.mapViewController.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.fragment_poi, container, false); this.mapViewController.onCreateView(view, savedInstanceState); return view; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); setupView(view); this.mapViewController.onViewCreated(view, savedInstanceState); } @Override public void onSaveInstanceState(Bundle outState) { if (!TextUtils.isEmpty(this.uuid)) { outState.putString(EXTRA_POI_UUID, this.uuid); } if (!TextUtils.isEmpty(this.authority)) { outState.putString(EXTRA_AUTHORITY, this.authority); } this.mapViewController.onSaveInstanceState(outState); super.onSaveInstanceState(outState); } private void restoreInstanceState(Bundle... bundles) { String newAuthority = BundleUtils.getString(EXTRA_AUTHORITY, bundles); if (!TextUtils.isEmpty(newAuthority) && !newAuthority.equals(this.authority)) { this.authority = newAuthority; resetAgency(); } String newUuid = BundleUtils.getString(EXTRA_POI_UUID, bundles); if (!TextUtils.isEmpty(newUuid) && !newUuid.equals(this.uuid)) { this.uuid = newUuid; resetPoim(); } } private POIArrayAdapter adapter; private void setupNearbyList() { if (this.adapter != null && this.adapter.isInitialized()) { showNearbyList(); return; } hideNearbyList(true); if (hasPoim()) { LoaderUtils.restartLoader(this, NEARBY_POIS_LOADER, null, this); } } private static final int NEARBY_POIS_LOADER = 0; private LocationUtils.AroundDiff ad = LocationUtils.getNewDefaultAroundDiff(); @Override public Loader<ArrayList<POIManager>> onCreateLoader(int id, Bundle args) { switch (id) { case NEARBY_POIS_LOADER: POIManager poim = getPoimOrNull(); if (TextUtils.isEmpty(this.authority) || poim == null) { return null; } Context context = getActivity(); if (context == null) { return null; } return new NearbyPOIListLoader(context, poim.poi.getLat(), poim.poi.getLng(), this.ad.aroundDiff, LocationUtils.MIN_POI_NEARBY_POIS_LIST_COVERAGE_IN_METERS, LocationUtils.MAX_POI_NEARBY_POIS_LIST, false, true, this.authority); default: MTLog.w(this, "Loader id '%s' unknown!", id); return null; } } @Override public void onLoaderReset(Loader<ArrayList<POIManager>> loader) { if (this.adapter != null) { this.adapter.clear(); } } @Override public void onLoadFinished(Loader<ArrayList<POIManager>> loader, ArrayList<POIManager> data) { POIManager poim = getPoimOrNull(); if (CollectionUtils.getSize(data) < LocationUtils.MIN_NEARBY_LIST && poim != null && !LocationUtils.searchComplete(poim.poi.getLat(), poim.poi.getLng(), this.ad.aroundDiff)) { LocationUtils.incAroundDiff(this.ad); LoaderUtils.restartLoader(this, NEARBY_POIS_LOADER, null, this); return; } if (poim != null && data != null) { int i = 0; Iterator<POIManager> it = data.iterator(); while (it.hasNext()) { if (it.next().poi.getUUID().equals(poim.poi.getUUID())) { it.remove(); continue; } if (i >= LocationUtils.MAX_POI_NEARBY_POIS_LIST) { it.remove(); } i++; } } this.adapter.setPois(data); this.adapter.updateDistanceNowAsync(this.userLocation); this.adapter.initManual(); if (this.adapter.getPoisCount() > 0) { showNearbyList(); } else { hideNearbyList(false); } } private void hideNearbyList(boolean invisibleInsteadOfGone) { View view = getView(); if (view == null) { return; } view.findViewById(R.id.poi_nearby_pois_title).setVisibility(invisibleInsteadOfGone ? View.INVISIBLE : View.GONE); view.findViewById(R.id.poi_nearby_pois_list).setVisibility(invisibleInsteadOfGone ? View.INVISIBLE : View.GONE); } private void showNearbyList() { View view = getView(); if (view == null) { return; } view.findViewById(R.id.poi_nearby_pois_title).setVisibility(View.VISIBLE); view.findViewById(R.id.poi_nearby_pois_list).setVisibility(View.VISIBLE); } private void initAdapters(Activity activity) { this.adapter = new POIArrayAdapter(activity); this.adapter.setTag(getLogTag()); } private void setupView(View view) { if (view == null) { return; } this.adapter.setManualScrollView((ScrollView) view.findViewById(R.id.scrollview)); this.adapter.setManualLayout((ViewGroup) view.findViewById(R.id.poi_nearby_pois_list)); } private void setupRTSFullScheduleBtn(View view) { if (view == null) { return; } View rtsScheduleBtn = view.findViewById(R.id.fullScheduleBtn); if (rtsScheduleBtn != null) { Collection<ScheduleProviderProperties> scheduleProviders = DataSourceProvider.get(getActivity()) .getTargetAuthorityScheduleProviders(this.authority); if (CollectionUtils.getSize(scheduleProviders) == 0) { rtsScheduleBtn.setVisibility(View.GONE); } else { rtsScheduleBtn.setOnClickListener(new MTOnClickListener() { @Override public void onClickMT(View view) { POIManager poim = getPoimOrNull(); if (poim == null || !(poim.poi instanceof RouteTripStop)) { MTLog.w(POIFragment.this, "onClick() > skip (no poi or not RTS)"); return; } FragmentActivity activity = getActivity(); if (activity == null) { MTLog.w(POIFragment.this, "onClick() > skip (no activity)"); return; } ((MainActivity) activity).addFragmentToStack(ScheduleFragment.newInstance(POIFragment.this.uuid, POIFragment.this.authority, (RouteTripStop) poim.poi, poim.getColor(activity))); } }); rtsScheduleBtn.setVisibility(View.VISIBLE); } } } private void setupMoreNewsButton(View view) { if (view == null) { return; } View newsView = view.findViewById(R.id.poi_news); View moreBtn = newsView == null ? null : newsView.findViewById(R.id.moreBtn); if (moreBtn != null) { moreBtn.setOnClickListener(new MTOnClickListener() { @Override public void onClickMT(View view) { POIManager poim = getPoimOrNull(); if (poim == null) { return; } FragmentActivity activity = getActivity(); if (activity == null) { MTLog.w(POIFragment.this, "onClick() > skip (no activity)"); return; } Integer colorInt = poim.getColor(activity); String subtitle = POIManager.getOneLineDescription(activity, poim.poi); ((MainActivity) activity).addFragmentToStack(NewsFragment.newInstance(colorInt, subtitle, ArrayUtils.asArrayList(poim.poi.getAuthority()), null, NewsProviderContract.Filter.getNewTargetFilter(poim.poi).getTargets())); } }); moreBtn.setVisibility(View.VISIBLE); } } private void setupMoreNearbyButton(View view) { if (view == null) { return; } View moreBtn = view.findViewById(R.id.poi_nearby_pois_title).findViewById(R.id.moreBtn); if (moreBtn != null) { moreBtn.setOnClickListener(new MTOnClickListener() { @Override public void onClickMT(View view) { Activity activity = getActivity(); if (activity == null) { return; } POIManager poim = getPoimOrNull(); if (poim == null) { return; } Integer optTypeId = null; AgencyProperties agency = getAgencyOrNull(); if (agency != null) { optTypeId = agency.getType().getId(); } ((MainActivity) activity).addFragmentToStack(NearbyFragment.newFixedOnInstance(optTypeId, poim.getLat(), poim.getLng(), POIManager.getOneLineDescription(activity, poim.poi), poim.getColor(activity))); } }); moreBtn.setVisibility(View.VISIBLE); } } private View getPOIStatusView(View view) { POIManager poim = getPoimOrNull(); if (view == null || poim == null) { return null; } if (view.findViewById(R.id.poi_status_detail) == null) { // IF NOT present/inflated DO Integer layoutResId = POIStatusDetailViewController.getLayoutResId(poim); if (layoutResId != null) { ((ViewStub) view.findViewById(R.id.poi_status_detail_stub)).setLayoutResource(layoutResId); ((ViewStub) view.findViewById(R.id.poi_status_detail_stub)).inflate(); // inflate setupRTSFullScheduleBtn(view); } } return view.findViewById(R.id.poi_status_detail); } private View getPOIServiceUpdateView(View view) { if (view == null) { return null; } if (view.findViewById(R.id.poi_service_update) == null) { // IF NOT present/inflated DO Integer layoutResId = POIServiceUpdateViewController.getLayoutResId(); if (layoutResId != null) { ((ViewStub) view.findViewById(R.id.poi_service_update_stub)).setLayoutResource(layoutResId); ((ViewStub) view.findViewById(R.id.poi_service_update_stub)).inflate(); // inflate } } return view.findViewById(R.id.poi_service_update); } private View getPOINewsView(View view) { if (view == null) { return null; } if (view.findViewById(R.id.poi_news) == null) { // IF NOT present/inflated DO Integer layoutResId = POINewsViewController.getLayoutResId(); if (layoutResId != null) { ((ViewStub) view.findViewById(R.id.poi_news_stub)).setLayoutResource(layoutResId); ((ViewStub) view.findViewById(R.id.poi_news_stub)).inflate(); // inflate view.findViewById(R.id.the_poi_news).setOnClickListener(new MTOnClickListener() { @Override public void onClickMT(View view) { ArrayList<News> news = getNewsOrNull(); if (news == null || news.size() == 0) { return; } News lastNews = news.get(0); if (lastNews == null) { return; } Activity activity = getActivity(); if (activity == null) { return; } ((MainActivity) activity).addFragmentToStack(NewsDetailsFragment.newInstance(lastNews.getUUID(), lastNews.getAuthority(), lastNews)); } }); } } return view.findViewById(R.id.poi_news); } private View getPOIView(View view) { POIManager poim = getPoimOrNull(); if (view == null || poim == null) { return null; } if (view.findViewById(R.id.this_poi) == null) { // IF NOT present/inflated DO int layoutResId = POIViewController.getLayoutResId(poim); ((ViewStub) view.findViewById(R.id.this_poi_stub)).setLayoutResource(layoutResId); ((ViewStub) view.findViewById(R.id.this_poi_stub)).inflate(); // inflate } return view.findViewById(R.id.this_poi); } @Override public void onStatusLoaded(POIStatus status) { View view = getView(); POIViewController.updatePOIStatus(getActivity(), getPOIView(view), status, this); POIStatusDetailViewController.updatePOIStatus(getActivity(), getPOIStatusView(view), status, this, getPoimOrNull()); } @Override public void onServiceUpdatesLoaded(String targetUUID, ArrayList<ServiceUpdate> serviceUpdates) { View view = getView(); POIViewController.updateServiceUpdatesView(getPOIView(view), serviceUpdates, this); POIServiceUpdateViewController.updateServiceUpdate(getActivity(), getPOIServiceUpdateView(view), serviceUpdates, this); } @Override public boolean onURLClick(String url) { return LinkUtils.open(getActivity(), url, getString(R.string.web_browser), true); } private Location userLocation; @Override public Location getLocation() { return this.userLocation; } @Override public void onUserLocationChanged(Location newLocation) { if (newLocation == null) { return; } if (this.userLocation == null || LocationUtils.isMoreRelevant(getLogTag(), this.userLocation, newLocation)) { this.userLocation = newLocation; this.locationDeclination = SensorUtils.getLocationDeclination(newLocation); if (!this.compassUpdatesEnabled) { SensorUtils.registerCompassListener(getActivity(), this); this.compassUpdatesEnabled = true; } POIManager poim = getPoimOrNull(); if (poim != null) { LocationUtils.updateDistanceWithString(getActivity(), poim, newLocation); POIViewController.updatePOIDistanceAndCompass(getPOIView(getView()), poim, this); } this.mapViewController.onUserLocationChanged(this.userLocation); if (this.adapter != null) { this.adapter.setLocation(newLocation); } } } private boolean compassUpdatesEnabled = false; @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } private float[] accelerometerValues = new float[3]; private float[] magneticFieldValues = new float[3]; @Override public void onSensorChanged(SensorEvent se) { SensorUtils.checkForCompass(getActivity(), se, this.accelerometerValues, this.magneticFieldValues, this); } private long lastCompassChanged = -1l; @Override public void updateCompass(float orientation, boolean force) { long now = TimeUtils.currentTimeMillis(); int roundedOrientation = SensorUtils.convertToPosivite360Degree((int) orientation); SensorUtils.updateCompass(force, this.userLocation, roundedOrientation, now, AbsListView.OnScrollListener.SCROLL_STATE_IDLE, this.lastCompassChanged, this.lastCompassInDegree, Constants.ADAPTER_NOTIFY_THRESHOLD_IN_MS, this); } @Override public void onSensorTaskCompleted(boolean result, int roundedOrientation, long now) { if (result) { this.lastCompassInDegree = roundedOrientation; this.lastCompassChanged = now; if (this.compassUpdatesEnabled && this.userLocation != null && this.lastCompassInDegree >= 0) { POIManager poim = getPoimOrNull(); if (poim != null) { POIViewController.updatePOIDistanceAndCompass(getPOIView(getView()), poim, this); } } } } private boolean modulesUpdated = false; @Override public void onModulesUpdated() { this.modulesUpdated = true; if (!isResumed()) { return; } MainActivity activity = (MainActivity) getActivity(); if (activity == null) { return; } POIManager newPoim = DataSourceManager.findPOI(activity, this.authority, POIProviderContract.Filter.getNewUUIDFilter(this.uuid)); if (newPoim == null) { if (activity.isMTResumed()) { activity.popFragmentFromStack(this); // close this fragment this.modulesUpdated = false; // processed } } else { this.modulesUpdated = false; // nothing to do } } @Override public void onResume() { super.onResume(); View view = getView(); if (this.modulesUpdated) { if (view != null) { view.post(new Runnable() { @Override public void run() { if (POIFragment.this.modulesUpdated) { onModulesUpdated(); } } }); } } resetFavorite(); // force refresh getFavoriteFolderId(); enableTimeChangedReceiver(); this.mapViewController.onResume(); if (this.adapter != null) { this.adapter.onResume(getActivity(), this.userLocation); } POIManager poim = getPoimOrNull(); if (poim != null) { this.mapViewController.notifyMarkerChanged(this); this.mapViewController.showMap(view); POIViewController.updateView(getActivity(), getPOIView(view), poim, this); POIStatusDetailViewController.updateView(getActivity(), getPOIStatusView(view), poim, this); POIServiceUpdateViewController.updateView(getActivity(), getPOIServiceUpdateView(view), poim, this); POINewsViewController.updateView(getActivity(), getPOINewsView(view), getNewsOrNull()); setupRTSFullScheduleBtn(view); setupMoreNewsButton(view); setupMoreNearbyButton(view); setupNearbyList(); } onUserLocationChanged(((MTActivityWithLocation) getActivity()).getUserLocation()); } @Override public void onPause() { super.onPause(); if (this.compassUpdatesEnabled) { SensorUtils.unregisterSensorListener(getActivity(), this); this.compassUpdatesEnabled = false; } disableTimeChangedReceiver(); this.mapViewController.onPause(); if (this.adapter != null) { this.adapter.onPause(); } } private long nowToTheMinute = -1L; @Override public long getNowToTheMinute() { if (this.nowToTheMinute < 0L) { resetNowToTheMinute(); enableTimeChangedReceiver(); } return this.nowToTheMinute; } @Override public void onTimeChanged() { resetNowToTheMinute(); } private void resetNowToTheMinute() { this.nowToTheMinute = TimeUtils.currentTimeToTheMinuteMillis(); View view = getView(); POIManager poim = getPoimOrNull(); if (poim != null) { View poiView = getPOIView(view); POIViewController.updatePOIStatus(getActivity(), poiView, poim, this); POIViewController.updatePOIServiceUpdate(getActivity(), poiView, poim, this); POIStatusDetailViewController.updateView(getActivity(), getPOIStatusView(view), poim, this); POIServiceUpdateViewController.updateView(getActivity(), getPOIServiceUpdateView(view), poim, this); } ArrayList<News> news = getNewsOrNull(); if (news != null) { POINewsViewController.updateView(getActivity(), getPOINewsView(view), news); } } private boolean timeChangedReceiverEnabled = false; private void enableTimeChangedReceiver() { if (!this.timeChangedReceiverEnabled) { getActivity().registerReceiver(timeChangedReceiver, TimeUtils.TIME_CHANGED_INTENT_FILTER); this.timeChangedReceiverEnabled = true; } } private void disableTimeChangedReceiver() { if (this.timeChangedReceiverEnabled) { getActivity().unregisterReceiver(this.timeChangedReceiver); this.timeChangedReceiverEnabled = false; this.nowToTheMinute = -1L; } } private final BroadcastReceiver timeChangedReceiver = new TimeUtils.TimeChangedReceiver(this); @Override public boolean hasLocation() { return this.userLocation != null; } private int lastCompassInDegree = -1; @Override public int getLastCompassInDegree() { return lastCompassInDegree; } @Override public boolean hasLastCompassInDegree() { return lastCompassInDegree >= 0; } private float locationDeclination; @Override public float getLocationDeclination() { return this.locationDeclination; } @Override public boolean isClosestPOI(String uuid) { return false; } private Integer favoriteFolderId = null; public Integer getFavoriteFolderId() { if (this.favoriteFolderId == null) { POIManager poim = getPoimOrNull(); if (poim != null) { this.favoriteFolderId = FavoriteManager.findFavoriteFolderId(getActivity(), poim.poi.getUUID()); } } return this.favoriteFolderId; } public boolean isFavorite() { if (this.favoriteFolderId == null) { POIManager poim = getPoimOrNull(); if (poim != null) { this.favoriteFolderId = FavoriteManager.findFavoriteFolderId(getActivity(), poim.poi.getUUID()); } } return getFavoriteFolderId() == null ? false : getFavoriteFolderId() >= 0; } private void resetFavorite() { this.favoriteFolderId = null; } @Override public boolean isFavorite(String uuid) { POIManager poim = getPoimOrNull(); if (poim != null && poim.poi != null && poim.poi.getUUID().equals(uuid)) { return isFavorite(); } return FavoriteManager.isFavorite(getActivity(), uuid); } @Override public boolean isShowingFavorite() { return false; // shown in the action bar } @Override public boolean isShowingStatus() { return true; } @Override public boolean isShowingExtra() { return true; } @Override public boolean isShowingServiceUpdates() { return true; } private MenuItem addRemoveFavoriteMenuItem; @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.menu_poi, menu); this.addRemoveFavoriteMenuItem = menu.findItem(R.id.menu_add_remove_favorite); updateFavMenuItem(); } private void updateFavMenuItem() { if (this.addRemoveFavoriteMenuItem == null) { return; } POIManager poim = getPoimOrNull(); if (poim != null && poim.isFavoritable()) { boolean isFav = isFavorite(); this.addRemoveFavoriteMenuItem.setIcon(isFav ? R.drawable.ic_action_toggle_star_material_dark : R.drawable.ic_action_toggle_star_outline_material_dark); this.addRemoveFavoriteMenuItem.setTitle(isFav ? // FavoriteManager.get(getContext()).isUsingFavoriteFolders() ? // R.string.menu_action_edit_favorite : R.string.menu_action_remove_favorite : R.string.menu_action_add_favorite); this.addRemoveFavoriteMenuItem.setVisible(true); } else { this.addRemoveFavoriteMenuItem.setVisible(false); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_add_remove_favorite: POIManager poim = getPoimOrNull(); if (poim != null && poim.isFavoritable()) { return FavoriteManager.get(getContext()).addRemoveFavorite(getActivity(), poim.poi.getUUID(), this); } break; case R.id.menu_show_directions: POIManager poim2 = getPoimOrNull(); if (poim2 != null) { MapUtils.showDirection(getActivity(), poim2.poi.getLat(), poim2.poi.getLng(), null, null, poim2.poi.getName()); return true; // handled } break; } return super.onOptionsItemSelected(item); } @Override public void onFavoriteUpdated() { resetFavorite(); updateFavMenuItem(); POIManager poim = getPoimOrNull(); if (poim != null) { POIViewController.updateView(getActivity(), getPOIView(getView()), poim, this); } } @Override public boolean isABReady() { return hasAgency(); } @Override public CharSequence getABTitle(Context context) { AgencyProperties agency = getAgencyOrNull(); if (agency != null) { return agency.getShortName(); } return context.getString(R.string.ellipsis); } @Override public Integer getABBgColor(Context context) { return Color.TRANSPARENT; } @Override public void onLowMemory() { super.onLowMemory(); this.mapViewController.onLowMemory(); } @Override public void onDestroyView() { super.onDestroyView(); this.mapViewController.onDestroyView(); } @Override public void onDestroy() { super.onDestroy(); this.mapViewController.onDestroy(); if (this.adapter != null) { this.adapter.onDestroy(); this.adapter = null; } TaskUtils.cancelQuietly(this.loadAgencyTask, true); TaskUtils.cancelQuietly(this.loadPoimTask, true); TaskUtils.cancelQuietly(this.loadNewsTask, true); } }