Java tutorial
/* * FlightIntel for Pilots * * Copyright 2011-2016 Nadeem Hasan <nhasan@nadmm.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.nadmm.airports; import android.app.SearchManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.design.widget.NavigationView; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.content.ContextCompat; import android.support.v4.view.GravityCompat; import android.support.v4.view.MenuItemCompat; import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.SearchView; import android.support.v7.widget.Toolbar; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.view.animation.DecelerateInterpolator; import android.widget.AbsListView; import android.widget.CheckBox; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.nadmm.airports.aeronav.ChartsDownloadActivity; import com.nadmm.airports.afd.AfdMainActivity; import com.nadmm.airports.clocks.ClocksActivity; import com.nadmm.airports.data.DatabaseManager; import com.nadmm.airports.data.DatabaseManager.Airports; import com.nadmm.airports.data.DatabaseManager.Nav1; import com.nadmm.airports.data.DatabaseManager.States; import com.nadmm.airports.data.DownloadActivity; import com.nadmm.airports.donate.DonateActivity; import com.nadmm.airports.donate.DonateDatabase; import com.nadmm.airports.e6b.E6bActivity; import com.nadmm.airports.library.LibraryActivity; import com.nadmm.airports.scratchpad.ScratchPadActivity; import com.nadmm.airports.tfr.TfrListActivity; import com.nadmm.airports.utils.CursorAsyncTask; import com.nadmm.airports.utils.DataUtils; import com.nadmm.airports.utils.ExternalStorageActivity; import com.nadmm.airports.utils.FormatUtils; import com.nadmm.airports.utils.SystemUtils; import com.nadmm.airports.utils.TimeUtils; import com.nadmm.airports.utils.UiUtils; import com.nadmm.airports.views.MultiSwipeRefreshLayout; import com.nadmm.airports.views.ObservableScrollView; import com.nadmm.airports.wx.WxMainActivity; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; public class ActivityBase extends AppCompatActivity implements MultiSwipeRefreshLayout.CanChildScrollUpCallback { private DatabaseManager mDbManager; private LayoutInflater mInflater; private CursorAsyncTask mTask; private IntentFilter mFilter; private BroadcastReceiver mExternalStorageReceiver; private Toolbar mActionBarToolbar; private SwipeRefreshLayout mSwipeRefreshLayout; // variables that control the Action Bar auto hide behavior (aka "quick recall") private boolean mActionBarAutoHideEnabled = false; private int mActionBarAutoHideSensivity = 0; private int mActionBarAutoHideMinY = 0; private int mActionBarAutoHideSignal = 0; private boolean mActionBarShown = true; private Handler mHandler; private int mProgressBarTopWhenActionBarShown; private DrawerLayout mDrawerLayout; private ActionBarDrawerToggle mDrawerToggle; private NavigationView mNavigationView; // When set, these components will be shown/hidden in sync with the action bar // to implement the "quick recall" effect (the Action Bar and the header views disappear // when you scroll down a list, and reappear quickly when you scroll up). private ArrayList<View> mHideableHeaderViews = new ArrayList<>(); private static final int HEADER_HIDE_ANIM_DURATION = 300; private static final int NAVDRAWER_LAUNCH_DELAY = 300; protected static final int NAVDRAWER_ITEM_INVALID = -1; private FragmentManager.OnBackStackChangedListener mBackStackChangedListener = new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { updateDrawerToggle(); } }; public static final String FRAGMENT_TAG_EXTRA = "FRAGMENT_TAG_EXTRA"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDbManager = DatabaseManager.instance(this); mInflater = getLayoutInflater(); overridePendingTransition(R.anim.fade_in, R.anim.fade_out); mHandler = new Handler(); mFilter = new IntentFilter(); mFilter.addAction(Intent.ACTION_MEDIA_MOUNTED); mFilter.addAction(Intent.ACTION_MEDIA_SHARED); mFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); mFilter.addAction(Intent.ACTION_MEDIA_REMOVED); mFilter.addDataScheme("file"); mExternalStorageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { externalStorageStatusChanged(); } }; if (Application.sDonationDone == null) { DonateDatabase db = new DonateDatabase(this); Cursor c = db.queryAllDonations(); Application.sDonationDone = c.moveToFirst(); db.close(); } // Enable Google Analytics ((Application) getApplication()).getAnalyticsTracker(); } @Override protected void onPause() { if (mTask != null) { mTask.cancel(true); } overridePendingTransition(R.anim.fade_in, R.anim.fade_out); unregisterReceiver(mExternalStorageReceiver); getSupportFragmentManager().removeOnBackStackChangedListener(mBackStackChangedListener); super.onPause(); } @Override protected void onResume() { super.onResume(); registerReceiver(mExternalStorageReceiver, mFilter); // Whenever the fragment back stack changes, we may need to update the // action bar toggle: only top level screens show the hamburger-like icon, inner // screens - either Activities or fragments - show the "Up" icon instead. getSupportFragmentManager().addOnBackStackChangedListener(mBackStackChangedListener); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); setupNavDrawer(); trySetupSwipeRefresh(); updateSwipeRefreshProgressBarTop(); enableDisableSwipeRefresh(false); enableActionBarAutoHide(); // Sync the toggle state after onRestoreInstanceState has occurred. if (mDrawerToggle != null) { mDrawerToggle.syncState(); } } @Override public void setContentView(int layoutResID) { super.setContentView(layoutResID); getActionBarToolbar(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (mDrawerToggle != null) { mDrawerToggle.onConfigurationChanged(newConfig); } } @Override public void onBackPressed() { // If the drawer is open, back will close it if (mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START)) { mDrawerLayout.closeDrawers(); return; } // Otherwise, it may return to the previous fragment stack FragmentManager fragmentManager = getSupportFragmentManager(); if (fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStack(); } else { // Lastly, it will rely on the system behavior for back super.onBackPressed(); } } private void setupNavDrawer() { int selfItem = getSelfNavDrawerItem(); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); if (mDrawerLayout == null) { return; } mDrawerLayout.setStatusBarBackgroundColor(ContextCompat.getColor(this, R.color.color_primary_dark)); mNavigationView = (NavigationView) mDrawerLayout.findViewById(R.id.navdrawer); if (selfItem == NAVDRAWER_ITEM_INVALID) { // do not show a nav drawer if (mNavigationView != null) { ((ViewGroup) mNavigationView.getParent()).removeView(mNavigationView); } mDrawerLayout = null; return; } mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, getActionBarToolbar(), R.string.drawer_open, R.string.drawer_close) { public void onDrawerClosed(View view) { supportInvalidateOptionsMenu(); onNavDrawerStateChanged(false, false); } /** Called when a drawer has settled in a completely open state. */ public void onDrawerOpened(View drawerView) { onNavDrawerStateChanged(true, false); supportInvalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() } }; mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); mDrawerLayout.addDrawerListener(mDrawerToggle); updateDrawerToggle(); // Initialize navigation drawer mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(MenuItem item) { item.setChecked(true); final int id = item.getItemId(); if (id != getSelfNavDrawerItem()) { // Launch the target Activity after a short delay to allow the drawer close // animation to finish without stutter mHandler.postDelayed(new Runnable() { @Override public void run() { goToNavDrawerItem(id); } }, NAVDRAWER_LAUNCH_DELAY); } mDrawerLayout.closeDrawer(GravityCompat.START); return false; } }); MenuItem item = mNavigationView.getMenu().findItem(selfItem); item.setChecked(true); } protected void updateDrawerToggle() { if (mDrawerToggle == null) { return; } boolean isRoot = getSupportFragmentManager().getBackStackEntryCount() == 0; mDrawerToggle.setDrawerIndicatorEnabled(isRoot); mDrawerLayout .setDrawerLockMode(isRoot ? DrawerLayout.LOCK_MODE_UNLOCKED : DrawerLayout.LOCK_MODE_LOCKED_CLOSED); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayShowHomeEnabled(!isRoot); actionBar.setDisplayHomeAsUpEnabled(!isRoot); actionBar.setHomeButtonEnabled(!isRoot); } if (isRoot) { mDrawerToggle.syncState(); } } private void goToNavDrawerItem(int id) { Intent intent; switch (id) { case R.id.navdrawer_afd: intent = new Intent(this, AfdMainActivity.class); startActivity(intent); finish(); break; case R.id.navdrawer_wx: intent = new Intent(this, WxMainActivity.class); startActivity(intent); finish(); break; case R.id.navdrawer_tfr: intent = new Intent(this, TfrListActivity.class); startActivity(intent); finish(); break; case R.id.navdrawer_library: intent = new Intent(this, LibraryActivity.class); startActivity(intent); finish(); break; case R.id.navdrawer_scratchpad: intent = new Intent(this, ScratchPadActivity.class); startActivity(intent); finish(); break; case R.id.navdrawer_clocks: intent = new Intent(this, ClocksActivity.class); startActivity(intent); finish(); break; case R.id.navdrawer_e6b: intent = new Intent(this, E6bActivity.class); startActivity(intent); finish(); break; case R.id.navdrawer_charts: intent = new Intent(this, ChartsDownloadActivity.class); startActivity(intent); finish(); break; case R.id.navdrawer_donate: Intent donate = new Intent(this, DonateActivity.class); startActivity(donate); break; case R.id.navdrawer_settings: intent = new Intent(this, PreferencesActivity.class); startActivity(intent); break; } } public void setDrawerIndicatorEnabled(boolean enable) { if (mDrawerToggle != null) { mDrawerToggle.setDrawerIndicatorEnabled(enable); } } protected Toolbar getActionBarToolbar() { if (mActionBarToolbar == null) { mActionBarToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar); if (mActionBarToolbar != null) { setSupportActionBar(mActionBarToolbar); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setHomeButtonEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true); } } } return mActionBarToolbar; } protected int getSelfNavDrawerItem() { return NAVDRAWER_ITEM_INVALID; } private void trySetupSwipeRefresh() { mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout); if (mSwipeRefreshLayout != null) { mSwipeRefreshLayout.setColorSchemeResources(R.color.refresh_progress_1, R.color.refresh_progress_2, R.color.refresh_progress_3); mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { requestDataRefresh(); } }); if (mSwipeRefreshLayout instanceof MultiSwipeRefreshLayout) { MultiSwipeRefreshLayout mswrl = (MultiSwipeRefreshLayout) mSwipeRefreshLayout; mswrl.setCanChildScrollUpCallback(this); } } } @Override public boolean canSwipeRefreshChildScrollUp() { return false; } protected void setProgressBarTopWhenActionBarShown(int progressBarTopWhenActionBarShown) { mProgressBarTopWhenActionBarShown = progressBarTopWhenActionBarShown; updateSwipeRefreshProgressBarTop(); } private void updateSwipeRefreshProgressBarTop() { if (mSwipeRefreshLayout == null) { return; } int progressBarStartMargin = getResources() .getDimensionPixelSize(R.dimen.swipe_refresh_progress_bar_start_margin); int progressBarEndMargin = getResources() .getDimensionPixelSize(R.dimen.swipe_refresh_progress_bar_end_margin); int top = mActionBarShown ? mProgressBarTopWhenActionBarShown : 0; mSwipeRefreshLayout.setProgressViewOffset(false, top + progressBarStartMargin, top + progressBarEndMargin); } public void setRefreshing(boolean refreshing) { if (mSwipeRefreshLayout != null) { mSwipeRefreshLayout.setRefreshing(refreshing); } } public boolean isRefreshing() { return mSwipeRefreshLayout.isRefreshing(); } public void enableDisableSwipeRefresh(boolean enable) { if (mSwipeRefreshLayout != null) { mSwipeRefreshLayout.setEnabled(enable); } } protected void requestDataRefresh() { } public void onFragmentStarted(FragmentBase fragment) { // Action bar may be hidden when this fragment was attached so make sure it is visible autoShowOrHideActionBar(true); fragment.registerActionBarAutoHideView(); updateContentTopClearance(fragment); } private void updateContentTopClearance(FragmentBase fragment) { int topClearance = UiUtils.calculateActionBarSize(this); if (findViewById(R.id.sliding_tabs) != null) { int tabbarClearance = getResources().getDimensionPixelSize(R.dimen.tabbar_height); topClearance += tabbarClearance; } fragment.setContentTopClearance(topClearance); setProgressBarTopWhenActionBarShown(topClearance); } public void registerActionBarAutoHideListView(final ListView listView) { listView.setOnScrollListener(new AbsListView.OnScrollListener() { final int ITEMS_THRESHOLD = 2; int lastFvi = 0; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { onMainContentScrolled(firstVisibleItem <= ITEMS_THRESHOLD ? 0 : Integer.MAX_VALUE, lastFvi - firstVisibleItem > 0 ? Integer.MIN_VALUE : lastFvi == firstVisibleItem ? 0 : Integer.MAX_VALUE); lastFvi = firstVisibleItem; } }); } public void registerActionBarAutoHideScrollView(final ObservableScrollView scrollView) { scrollView.setCallbacks(new ObservableScrollView.Callbacks() { final int ITEM_SIZE = dpToPx(56); final int ITEMS_THRESHOLD = 2; int lastFvi = 0; @Override public void onScrollChanged(int l, int t, int oldl, int oldt) { int firstVisibleItem = t / ITEM_SIZE; onMainContentScrolled(firstVisibleItem <= ITEMS_THRESHOLD ? 0 : Integer.MAX_VALUE, lastFvi - firstVisibleItem > 0 ? Integer.MIN_VALUE : lastFvi == firstVisibleItem ? 0 : Integer.MAX_VALUE); lastFvi = firstVisibleItem; } }); } protected void registerHideableHeaderView(View hideableHeaderView, int offset) { if (!mHideableHeaderViews.contains(hideableHeaderView)) { hideableHeaderView.setTag(R.id.AUTOHIDE_OFFSET, offset); mHideableHeaderViews.add(hideableHeaderView); } } protected void autoShowOrHideActionBar(boolean show) { if (show == mActionBarShown) { return; } mActionBarShown = show; onActionBarAutoShowOrHide(show); } /** * Initializes the Action Bar auto-hide (aka Quick Recall) effect. */ private void initActionBarAutoHide() { mActionBarAutoHideEnabled = true; mActionBarAutoHideMinY = getResources().getDimensionPixelSize(R.dimen.action_bar_auto_hide_min_y); mActionBarAutoHideSensivity = getResources().getDimensionPixelSize(R.dimen.action_bar_auto_hide_sensivity); } protected void enableActionBarAutoHide() { enableActionBarAutoHide(0); } protected void enableActionBarAutoHide(int extraOffset) { View header = findViewById(R.id.headerbar); if (header != null) { registerHideableHeaderView(header, UiUtils.calculateActionBarSize(this) + extraOffset); initActionBarAutoHide(); } } /** * Indicates that the main content has scrolled (for the purposes of showing/hiding * the action bar for the "action bar auto hide" effect). currentY and deltaY may be exact * (if the underlying view supports it) or may be approximate indications: * deltaY may be INT_MAX to mean "scrolled forward indeterminately" and INT_MIN to mean * "scrolled backward indeterminately". currentY may be 0 to mean "somewhere close to the * start of the list" and INT_MAX to mean "we don't know, but not at the start of the list" */ private void onMainContentScrolled(int currentY, int deltaY) { if (deltaY > mActionBarAutoHideSensivity) { deltaY = mActionBarAutoHideSensivity; } else if (deltaY < -mActionBarAutoHideSensivity) { deltaY = -mActionBarAutoHideSensivity; } if (Math.signum(deltaY) * Math.signum(mActionBarAutoHideSignal) < 0) { // deltaY is a motion opposite to the accumulated signal, so reset signal mActionBarAutoHideSignal = deltaY; } else { // add to accumulated signal mActionBarAutoHideSignal += deltaY; } boolean shouldShow = currentY < mActionBarAutoHideMinY || (mActionBarAutoHideSignal <= -mActionBarAutoHideSensivity); autoShowOrHideActionBar(shouldShow); } protected void resetActionBarAutoHide() { mActionBarAutoHideSignal = 0; } protected void onActionBarAutoShowOrHide(boolean shown) { for (View view : mHideableHeaderViews) { if (shown) { view.animate().translationY(0).setDuration(HEADER_HIDE_ANIM_DURATION) .setInterpolator(new DecelerateInterpolator()); } else { int offset = (int) view.getTag(R.id.AUTOHIDE_OFFSET); view.animate().translationY(-offset).setDuration(HEADER_HIDE_ANIM_DURATION) .setInterpolator(new DecelerateInterpolator()); } } } // Subclasses can override this for custom behavior protected void onNavDrawerStateChanged(boolean isOpen, boolean isAnimating) { if (mActionBarAutoHideEnabled && isOpen) { autoShowOrHideActionBar(true); } } protected CursorAsyncTask setBackgroundTask(CursorAsyncTask task) { mTask = task; return mTask; } protected void externalStorageStatusChanged() { if (!SystemUtils.isExternalStorageAvailable()) { Intent intent = new Intent(this, ExternalStorageActivity.class); startActivity(intent); } } public DatabaseManager getDbManager() { return mDbManager; } protected View createContentView(int id) { View view = inflate(id); return createContentView(view); } public View createContentView(View view) { FrameLayout root = new FrameLayout(this); int white = ContextCompat.getColor(this, android.R.color.white); root.setBackgroundColor(white); root.setDrawingCacheBackgroundColor(white); root.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); LinearLayout pframe = new LinearLayout(this); pframe.setId(R.id.INTERNAL_PROGRESS_CONTAINER_ID); pframe.setGravity(Gravity.CENTER); ProgressBar progress = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge); pframe.addView(progress, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); root.addView(pframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); FrameLayout lframe = new FrameLayout(this); lframe.setId(R.id.INTERNAL_FRAGMENT_CONTAINER_ID); lframe.setVisibility(View.GONE); lframe.addView(view, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); root.addView(lframe, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); return root; } public void setContentShown(boolean shown) { View root = findViewById(android.R.id.content); setContentShown(root, shown, true); } public void setContentShown(View view, boolean shown) { setContentShown(view, shown, true); } public void setContentShownNoAnimation(boolean shown) { View root = findViewById(android.R.id.content); setContentShown(root, shown, false); } public void setContentShownNoAnimation(View view, boolean shown) { setContentShown(view, shown, false); } protected void setContentShown(View view, boolean shown, boolean animation) { View progress = view.findViewById(R.id.INTERNAL_PROGRESS_CONTAINER_ID); View content = view.findViewById(R.id.INTERNAL_FRAGMENT_CONTAINER_ID); if (progress == null || content == null) { return; } if (shown) { if (animation) { progress.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_out)); content.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in)); } progress.setVisibility(View.GONE); content.setVisibility(View.VISIBLE); } else { if (animation) { progress.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in)); content.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_out)); } progress.setVisibility(View.VISIBLE); content.setVisibility(View.GONE); } } protected void setContentMsg(String msg) { TextView tv = new TextView(this); tv.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL); tv.setPadding(dpToPx(12), dpToPx(8), dpToPx(12), dpToPx(8)); tv.setText(msg); setContentView(createContentView(tv)); } protected Fragment replaceFragment(Class<?> clss, Bundle args, boolean addToStack) { return replaceFragment(clss, args, R.id.fragment_container, addToStack); } protected Fragment replaceFragment(Class<?> clss, Bundle args) { return replaceFragment(clss, args, R.id.fragment_container); } protected Fragment replaceFragment(Class<?> clss, Bundle args, int id) { return replaceFragment(clss, args, id, true); } protected Fragment replaceFragment(Class<?> clss, Bundle args, int id, boolean addToStack) { String tag = clss.getSimpleName(); if (args != null && args.containsKey(FRAGMENT_TAG_EXTRA)) { String extra = args.getString(FRAGMENT_TAG_EXTRA); if (extra != null) { tag = tag.concat(extra); } } FragmentManager fm = getSupportFragmentManager(); Fragment f = fm.findFragmentByTag(tag); if (f == null) { f = Fragment.instantiate(this, clss.getName(), args); } FragmentTransaction ft = fm.beginTransaction(); ft.replace(id, f, tag); if (addToStack) { ft.addToBackStack(tag); } ft.commit(); return f; } protected Fragment addFragment(Class<?> clss, Bundle args) { return addFragment(clss, args, R.id.fragment_container); } protected Fragment addFragment(Class<?> clss, Bundle args, int id) { String tag = clss.getSimpleName(); FragmentManager fm = getSupportFragmentManager(); Fragment f = fm.findFragmentByTag(tag); if (f == null) { f = Fragment.instantiate(this, clss.getName(), args); FragmentTransaction ft = fm.beginTransaction(); ft.add(id, f, tag); ft.commit(); } return f; } protected Fragment getFragment(Class<?> clss) { String tag = clss.getSimpleName(); FragmentManager fm = getSupportFragmentManager(); return fm.findFragmentByTag(tag); } protected View inflate(int resId) { return mInflater.inflate(resId, null, false); } protected View inflate(int resId, ViewGroup root) { return mInflater.inflate(resId, root, false); } public Cursor getAirportDetails(String siteNumber) { SQLiteDatabase db = getDatabase(DatabaseManager.DB_FADDS); SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); builder.setTables(Airports.TABLE_NAME + " a LEFT OUTER JOIN " + States.TABLE_NAME + " s" + " ON a." + Airports.ASSOC_STATE + "=s." + States.STATE_CODE); Cursor c = builder.query(db, new String[] { "*" }, Airports.SITE_NUMBER + "=?", new String[] { siteNumber }, null, null, null, null); if (!c.moveToFirst()) { return null; } return c; } public SQLiteDatabase getDatabase(String type) { SQLiteDatabase db = mDbManager.getDatabase(type); if (db == null) { Intent intent = new Intent(this, DownloadActivity.class); intent.putExtra("MSG", "Database is corrupted. Please delete and re-install"); startActivity(intent); finish(); } return db; } public void showAirportTitle(Cursor c) { View root = findViewById(R.id.airport_title_layout); TextView tv = (TextView) root.findViewById(R.id.facility_name); String code = c.getString(c.getColumnIndex(Airports.ICAO_CODE)); if (code == null || code.length() == 0) { code = c.getString(c.getColumnIndex(Airports.FAA_CODE)); } String tower = c.getString(c.getColumnIndex(Airports.TOWER_ON_SITE)); int color = tower.equals("Y") ? Color.rgb(48, 96, 144) : Color.rgb(128, 72, 92); tv.setTextColor(color); String name = c.getString(c.getColumnIndex(Airports.FACILITY_NAME)); String siteNumber = c.getString(c.getColumnIndex(Airports.SITE_NUMBER)); String type = DataUtils.decodeLandingFaclityType(siteNumber); tv.setText(String.format(Locale.US, "%s %s", name, type)); tv = (TextView) root.findViewById(R.id.facility_id); tv.setTextColor(color); tv.setText(code); tv = (TextView) root.findViewById(R.id.facility_info); String city = c.getString(c.getColumnIndex(Airports.ASSOC_CITY)); String state = c.getString(c.getColumnIndex(States.STATE_NAME)); if (state == null) { state = c.getString(c.getColumnIndex(Airports.ASSOC_COUNTY)); } tv.setText(String.format(Locale.US, "%s, %s", city, state)); tv = (TextView) root.findViewById(R.id.facility_info2); int distance = c.getInt(c.getColumnIndex(Airports.DISTANCE_FROM_CITY_NM)); String dir = c.getString(c.getColumnIndex(Airports.DIRECTION_FROM_CITY)); String status = c.getString(c.getColumnIndex(Airports.STATUS_CODE)); tv.setText(String.format(Locale.US, "%s, %d miles %s of city center", DataUtils.decodeStatus(status), distance, dir)); tv = (TextView) root.findViewById(R.id.facility_info3); float elev_msl = c.getFloat(c.getColumnIndex(Airports.ELEVATION_MSL)); int tpa_agl = c.getInt(c.getColumnIndex(Airports.PATTERN_ALTITUDE_AGL)); String est = ""; if (tpa_agl == 0) { tpa_agl = 1000; est = " (est.)"; } tv.setText(String.format(Locale.US, "%s MSL elev. - %s MSL TPA %s", FormatUtils.formatFeet(elev_msl), FormatUtils.formatFeet(elev_msl + tpa_agl), est)); String s = c.getString(c.getColumnIndex(Airports.EFFECTIVE_DATE)); GregorianCalendar endDate = new GregorianCalendar(Integer.valueOf(s.substring(6)), Integer.valueOf(s.substring(3, 5)), Integer.valueOf(s.substring(0, 2))); // Calculate end date of the 56-day cycle endDate.add(GregorianCalendar.DAY_OF_MONTH, 56); Calendar now = Calendar.getInstance(); if (now.after(endDate)) { // Show the expired warning tv = (TextView) root.findViewById(R.id.expired_label); tv.setVisibility(View.VISIBLE); } CheckBox cb = (CheckBox) root.findViewById(R.id.airport_star); cb.setChecked(mDbManager.isFavoriteAirport(siteNumber)); cb.setTag(siteNumber); cb.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { CheckBox cb = (CheckBox) v; String siteNumber = (String) cb.getTag(); if (cb.isChecked()) { mDbManager.addToFavoriteAirports(siteNumber); Toast.makeText(ActivityBase.this, "Added to favorites list", Toast.LENGTH_LONG).show(); } else { mDbManager.removeFromFavoriteAirports(siteNumber); Toast.makeText(ActivityBase.this, "Removed from favorites list", Toast.LENGTH_LONG).show(); } } }); ImageView iv = (ImageView) root.findViewById(R.id.airport_map); String lat = c.getString(c.getColumnIndex(Airports.REF_LATTITUDE_DEGREES)); String lon = c.getString(c.getColumnIndex(Airports.REF_LONGITUDE_DEGREES)); if (lat.length() > 0 && lon.length() > 0) { iv.setTag("geo:" + lat + "," + lon + "?z=16"); iv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String tag = (String) v.getTag(); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(tag)); startActivity(intent); } }); } else { iv.setVisibility(View.GONE); } } protected void showNavaidTitle(Cursor c) { View root = findViewById(R.id.navaid_title_layout); String id = c.getString(c.getColumnIndex(Nav1.NAVAID_ID)); String name = c.getString(c.getColumnIndex(Nav1.NAVAID_NAME)); String type = c.getString(c.getColumnIndex(Nav1.NAVAID_TYPE)); TextView tv = (TextView) root.findViewById(R.id.navaid_name); tv.setText(String.format(Locale.US, "%s - %s %s", id, name, type)); String city = c.getString(c.getColumnIndex(Nav1.ASSOC_CITY)); String state = c.getString(c.getColumnIndex(States.STATE_NAME)); tv = (TextView) root.findViewById(R.id.navaid_info); tv.setText(String.format(Locale.US, "%s, %s", city, state)); String use = c.getString(c.getColumnIndex(Nav1.PUBLIC_USE)); Float elev_msl = c.getFloat(c.getColumnIndex(Nav1.ELEVATION_MSL)); tv = (TextView) root.findViewById(R.id.navaid_info2); tv.setText(String.format(Locale.US, "%s, %s elevation", use.equals("Y") ? "Public use" : "Private use", FormatUtils.formatFeetMsl(elev_msl))); tv = (TextView) root.findViewById(R.id.navaid_morse1); tv.setText(DataUtils.getMorseCode(id.substring(0, 1))); if (id.length() > 1) { tv = (TextView) root.findViewById(R.id.navaid_morse2); tv.setText(DataUtils.getMorseCode(id.substring(1, 2))); } if (id.length() > 2) { tv = (TextView) root.findViewById(R.id.navaid_morse3); tv.setText(DataUtils.getMorseCode(id.substring(2, 3))); } } public boolean postRunnable(Runnable r, long delayMillis) { return mHandler.postDelayed(r, delayMillis); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.mainmenu, menu); MenuItem settingsItem = menu.findItem(R.id.menu_settings); settingsItem.setVisible(getSelfNavDrawerItem() == NAVDRAWER_ITEM_INVALID); MenuItem searchItem = menu.findItem(R.id.menu_search); SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); searchView.setIconifiedByDefault(false); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (mDrawerToggle != null && mDrawerToggle.onOptionsItemSelected(item)) { return true; } switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; case R.id.menu_search: return true; case R.id.menu_download: Intent download = new Intent(this, DownloadActivity.class); startActivity(download); return true; case R.id.menu_settings: Intent intent = new Intent(this, PreferencesActivity.class); startActivity(intent); return true; case R.id.menu_about: Intent about = new Intent(this, AboutActivity.class); startActivity(about); return true; default: return super.onOptionsItemSelected(item); } } public void setActionBarTitle(Cursor c) { ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { String siteNumber = c.getString(c.getColumnIndex(Airports.SITE_NUMBER)); String type = DataUtils.decodeLandingFaclityType(siteNumber); String name = c.getString(c.getColumnIndex(Airports.FACILITY_NAME)); String code = c.getString(c.getColumnIndex(Airports.ICAO_CODE)); if (code == null || code.length() == 0) { code = c.getString(c.getColumnIndex(Airports.FAA_CODE)); } actionBar.setTitle(String.format(Locale.US, "%s - %s %s", code, name, type)); } } protected int dpToPx(float dp) { return UiUtils.convertDpToPx(this, dp); } protected void setActionBarTitle(Cursor c, String subtitle) { String code = c.getString(c.getColumnIndex(Airports.ICAO_CODE)); if (code == null || code.length() == 0) { code = c.getString(c.getColumnIndex(Airports.FAA_CODE)); } String title = code; Boolean isScreenWide = getResources().getBoolean(R.bool.IsScreenWide); if (isScreenWide) { String siteNumber = c.getString(c.getColumnIndex(Airports.SITE_NUMBER)); String type = DataUtils.decodeLandingFaclityType(siteNumber); String name = c.getString(c.getColumnIndex(Airports.FACILITY_NAME)); title = String.format(Locale.US, "%s - %s %s", code, name, type); } setActionBarTitle(title, subtitle); } protected void setActionBarTitle(String title) { setActionBarTitle(title, getTitle().toString()); } protected void setActionBarTitle(String title, String subtitle) { ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setTitle(title); actionBar.setSubtitle(subtitle); } } protected void setActionBarSubtitle(String subtitle) { ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setSubtitle(subtitle); } } protected void showFaddsEffectiveDate(Cursor c) { TextView tv = (TextView) findViewById(R.id.effective_date); if (tv != null) { String s = c.getString(c.getColumnIndex(Airports.EFFECTIVE_DATE)); Date date = TimeUtils.parseFaaDate(s); if (date != null) { Calendar start = Calendar.getInstance(); start.setTime(date); start.add(Calendar.MINUTE, 9 * 60 + 1); Calendar end = (Calendar) start.clone(); end.add(Calendar.DATE, 56); s = TimeUtils.formatDateRange(this, start, end); tv.setText(s); } } } }