Java tutorial
/* * Copyright 2014 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package pl.edu.agh.schedule.myschedule; import android.app.Fragment; import android.app.FragmentManager; import android.app.ListFragment; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.support.design.widget.TabLayout; import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPager; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import com.estimote.sdk.Beacon; import com.estimote.sdk.BeaconManager; import com.estimote.sdk.Region; import com.estimote.sdk.SystemRequirementsChecker; import org.joda.time.DateTime; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import pl.edu.agh.schedule.BuildConfig; import pl.edu.agh.schedule.R; import pl.edu.agh.schedule.model.ScheduleHelper; import pl.edu.agh.schedule.settings.SettingsActivity; import pl.edu.agh.schedule.ui.BaseActivity; import pl.edu.agh.schedule.util.BeaconUtils; import pl.edu.agh.schedule.util.TimeUtils; import static pl.edu.agh.schedule.util.LogUtils.makeLogTag; public class MyScheduleActivity extends BaseActivity implements MyScheduleFragment.Listener, SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = makeLogTag(MyScheduleActivity.class); private static final int DAYS_RANGE = 15; private static final int TODAY = 7; private static final String TITLE = "pl.edu.agh.schedule.myschedule.TITLE"; private static final String LOCATION = "pl.edu.agh.schedule.myschedule.LOCATION"; private static final String DAY_INDEX = "pl.edu.agh.schedule.myschedule.DAY_INDEX"; // The adapters that serves as the source of data for the UI, indicating the available // items. We have one adapter per day of the conference. When we push new data into these // adapters, the corresponding UIs update automatically. private MyScheduleAdapter[] mScheduleAdapters = new MyScheduleAdapter[DAYS_RANGE]; // The ScheduleHelper is responsible for feeding data in a format suitable to the Adapter. private ScheduleHelper mDataHelper; // View pager and adapter ViewPager mViewPager = null; OurViewPagerAdapter mViewPagerAdapter = null; TabLayout mTabLayout = null; boolean mDestroyed = false; private Set<MyScheduleFragment> mMyScheduleFragments = new HashSet<>(); private int baseTabViewId = 12345; private BeaconManager beaconManager; private Region region; private String location; private static Boolean cachedSettingsState = null; @Override protected int getSelfNavDrawerItem() { return NAVDRAWER_ITEM_MY_SCHEDULE; } @Override protected void onCreate(Bundle savedInstanceState) { Log.d(TAG, "onCreate"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_schedule); if (mDataHelper == null) { mDataHelper = new ScheduleHelper(this); } mViewPager = (ViewPager) findViewById(R.id.view_pager); for (int i = 0; i < DAYS_RANGE; i++) { mScheduleAdapters[i] = new MyScheduleAdapter(this, getLUtils()); } mViewPagerAdapter = new OurViewPagerAdapter(getFragmentManager()); mViewPager.setAdapter(mViewPagerAdapter); mTabLayout = (TabLayout) findViewById(R.id.sliding_tabs); if (mTabLayout != null) { mTabLayout.setTabsFromPagerAdapter(mViewPagerAdapter); } mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { mViewPager.setCurrentItem(tab.getPosition(), true); TextView view = (TextView) findViewById(baseTabViewId + tab.getPosition()); if (view != null) { view.setContentDescription( getString(R.string.talkback_selected, getString(R.string.a11y_button, tab.getText()))); } } @Override public void onTabUnselected(TabLayout.Tab tab) { TextView view = (TextView) findViewById(baseTabViewId + tab.getPosition()); if (view != null) { view.setContentDescription(getString(R.string.a11y_button, tab.getText())); } } @Override public void onTabReselected(TabLayout.Tab tab) { // Do nothing } }); mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { // When swiping between pages, select the corresponding tab. securelySelectTab(position); } }); mViewPager.setPageMargin(getResources().getDimensionPixelSize(R.dimen.my_schedule_page_margin)); mViewPager.setPageMarginDrawable(R.drawable.page_margin); setTabLayoutContentDescriptions(); overridePendingTransition(0, 0); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); sp.registerOnSharedPreferenceChangeListener(this); if (cachedSettingsState == null) { cachedSettingsState = getIsScanEnabled(sp); } // FIXME adjust settings beaconManager = new BeaconManager(this); beaconManager.setForegroundScanPeriod(1000, 5000); beaconManager.setRangingListener(new BeaconManager.RangingListener() { @Override public void onBeaconsDiscovered(Region region, List<Beacon> list) { if (!list.isEmpty()) { Beacon nearestBeacon = list.get(0); String id = String.format("%s:%d:%d", nearestBeacon.getProximityUUID().toString(), nearestBeacon.getMajor(), nearestBeacon.getMinor()); if (!id.equals(BeaconUtils.nearestBeacon())) { setTitle(mDataHelper.getLocationForBeacon(id)); BeaconUtils.nearestBeacon(id); updateData(); } } } }); region = new Region("ranged region", null, null, null); SystemRequirementsChecker.checkWithDefaultDialogs(this); if (mViewPager != null) { selectDay(TODAY); } if (savedInstanceState == null) { new Handler().postDelayed(new Runnable() { @Override public void run() { securelySelectTab(TODAY); } }, 100); } if (getIsScanEnabled(sp)) { beaconManager.connect(new BeaconManager.ServiceReadyCallback() { @Override public void onServiceReady() { beaconManager.startRanging(region); } }); } } private boolean getIsScanEnabled(SharedPreferences sharedPreferences) { return sharedPreferences.getBoolean(SettingsActivity.PREF_BEACON_SCAN_ENABLED, true); } private void securelySelectTab(int position) { TabLayout.Tab tab = mTabLayout.getTabAt(position); if (tab != null) { tab.select(); } } private void setTabLayoutContentDescriptions() { LayoutInflater inflater = getLayoutInflater(); int gap = 0; for (int i = 0, count = mTabLayout.getTabCount(); i < count; i++) { TabLayout.Tab tab = mTabLayout.getTabAt(i); if (tab != null) { TextView view = (TextView) inflater.inflate(R.layout.tab_my_schedule, mTabLayout, false); view.setId(baseTabViewId + i); view.setText(tab.getText()); if (i == 0) { view.setContentDescription( getString(R.string.talkback_selected, getString(R.string.a11y_button, tab.getText()))); } else { view.setContentDescription(getString(R.string.a11y_button, tab.getText())); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { view.announceForAccessibility( getString(R.string.my_schedule_tab_desc_a11y, getDayName(i - gap))); } tab.setCustomView(view); } else { Log.e(TAG, "Tab is null."); } } } @Override public void onSaveInstanceState(Bundle outState) { outState.putString(TITLE, getTitle().toString()); outState.putInt(DAY_INDEX, mViewPager.getCurrentItem()); outState.putString(LOCATION, location); super.onSaveInstanceState(outState); } @Override public void onRestoreInstanceState(Bundle savedInstanceState) { setTitle(savedInstanceState.getString(TITLE)); location = savedInstanceState.getString(LOCATION); final int day = savedInstanceState.getInt(DAY_INDEX); new Handler().postDelayed(new Runnable() { @Override public void run() { securelySelectTab(day); } }, 100); selectDay(day); updateData(); super.onRestoreInstanceState(savedInstanceState); } private void selectDay(int day) { mViewPager.setCurrentItem(day); } @Override public boolean canSwipeRefreshChildScrollUp() { for (MyScheduleFragment fragment : mMyScheduleFragments) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { if (!fragment.getUserVisibleHint()) { continue; } } return ViewCompat.canScrollVertically(fragment.getListView(), -1); } return false; } protected void updateData() { Log.d(TAG, "Filling adapters with data."); for (int i = 0; i < DAYS_RANGE; i++) { mDataHelper.getScheduleDataAsync(mScheduleAdapters[i], getDayAtPosition(i), location); } } private Date getDayAtPosition(int position) { DateTime dateTime = new DateTime(new Date()); int shift = position - TODAY; dateTime = dateTime.plusDays(shift); return dateTime.toDate(); } @Override protected void onDestroy() { super.onDestroy(); mDestroyed = true; SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); sp.unregisterOnSharedPreferenceChangeListener(this); } @Override public void onFragmentViewCreated(ListFragment fragment) { int dayIndex = fragment.getArguments().getInt(DAY_INDEX, 0); fragment.setListAdapter(mScheduleAdapters[dayIndex]); fragment.getListView().setRecyclerListener(mScheduleAdapters[dayIndex]); } @Override public void onFragmentAttached(MyScheduleFragment fragment) { mMyScheduleFragments.add(fragment); } @Override public void onFragmentDetached(MyScheduleFragment fragment) { mMyScheduleFragments.remove(fragment); } private class OurViewPagerAdapter extends FragmentPagerAdapter { public OurViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { Log.d(TAG, "Creating fragment #" + position); MyScheduleFragment frag = new MyScheduleFragment(); Bundle args = new Bundle(); args.putInt(DAY_INDEX, position); frag.setArguments(args); return frag; } @Override public int getCount() { return DAYS_RANGE; } @Override public CharSequence getPageTitle(int position) { return getDayName(position); } } private String getDayName(int position) { return TimeUtils.formatShortDate(this, getDayAtPosition(position)); } @Override public boolean onPrepareOptionsMenu(Menu menu) { menu.clear(); for (String location : mDataHelper.getLocations()) { menu.add(location); } return super.onPrepareOptionsMenu(menu); } @Override protected void onResume() { onlineOfflineMode(); super.onResume(); } private void onlineOfflineMode() { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); boolean scanEnabled = getIsScanEnabled(sharedPreferences); if (scanEnabled != cachedSettingsState) { if (scanEnabled) { beaconManager.connect(new BeaconManager.ServiceReadyCallback() { @Override public void onServiceReady() { beaconManager.startRanging(region); } }); location = null; Log.d(TAG, "Start ranging beacons."); } else { beaconManager.disconnect(); BeaconUtils.nearestBeacon(""); if (location == null) { setTitle("Offline mode"); } Log.d(TAG, "Stop ranging beacons."); } cachedSettingsState = scanEnabled; } } @Override public boolean onOptionsItemSelected(MenuItem item) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = sp.edit(); editor.putBoolean(SettingsActivity.PREF_BEACON_SCAN_ENABLED, false); editor.apply(); onlineOfflineMode(); String newLocation = item.getTitle().toString(); location = newLocation; updateData(); setTitle(newLocation); return super.onOptionsItemSelected(item); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(BuildConfig.BEACONS) || key.equals(BuildConfig.SCHEDULE)) { mDataHelper.refreshCalendar(); Log.d(TAG, "Refreshing calendar."); updateData(); } } }