Java tutorial
package com.hangulo.powercontact; /* * Copyright (C) 2015 The Android Open Source Project * * 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. * * // udacity // https://github.com/udacity/google-play-services/tree/master/LocationLessons_Final/LocationLesson1 */ import android.Manifest; import android.accounts.AccountManager; import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; import android.location.Geocoder; import android.location.Location; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.percent.PercentFrameLayout; import android.support.percent.PercentLayoutHelper; import android.support.v4.app.ActivityCompat; import android.support.v4.app.DialogFragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.ContextCompat; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.GravityCompat; import android.support.v4.view.MenuItemCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.SwitchCompat; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.CompoundButton; import android.widget.FrameLayout; import android.widget.ProgressBar; import android.support.design.widget.NavigationView; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.Arrays; import java.util.Locale; import java.util.Vector; import com.google.android.gms.common.AccountPicker; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.model.LatLng; import com.hangulo.powercontact.data.PowerContactContract; import com.hangulo.powercontact.model.PowerContactAddress; import com.hangulo.powercontact.service.FetchPowerAddressIntentService; import com.hangulo.powercontact.util.Utils; import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; import com.hangulo.powercontact.model.PowerContactSettings; /* * ================================================ * Android Devlelopment Nanodegree * Project 8: Capstone, Stage 2 - Build * PowerContact by Kwanghyun Jung (ihangulo@gmail.com) * ================================================ * * date : Apr. 4th 2016 * * MainActivity.java * ------------- * * */ public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>, NavigationView.OnNavigationItemSelectedListener, ContactsListFragment.ContactsListCallback, MapViewFragment.MapViewCallback, ConnectionCallbacks, OnConnectionFailedListener { private final String LOG_TAG = MainActivity.class.getSimpleName(); // for broadcast private BroadcastReceiver messageReceiver; private static boolean onFetching = false; // is it now fetching address? // search public String mSearchKeyword = ""; // Stores the current search query term public String mPreviousSearchKeyword = ""; // Stores the current search query term // https://developers.google.com/android/guides/api-client // Request code to use when launching the resolution activity private static final int REQUEST_RESOLVE_ERROR = 1001; // Unique tag for the error dialog fragment private static final String DIALOG_ERROR = "dialog_error"; // Bool to track whether the app is already resolving an error private boolean mResolvingError = false; private static final String STATE_RESOLVING_ERROR = "resolving_error"; //main menu ui private NavigationView mDrawer; private ActionBarDrawerToggle mDrawerToggle; private DrawerLayout mDrawerLayout; private FrameLayout mTopFrameLayout; private android.support.design.widget.AppBarLayout mTopLayout; private FloatingActionButton mMakeDemoButton; SwitchCompat mDemoSwitch; //? TextView mTextDemoMode; private boolean mIsExpandedFragment; // ? ? ? . ?? ? . protected final static String LOCATION_KEY = "LOCATION_KEY"; protected final static String LAST_UPDATED_TIME_STRING_KEY = "LAST_UPDATED_TIME_STRING_KEY"; protected final static String POWER_CONTACT_SETTINGS_KEY = "POWER_CONTACT_SETTINGS"; protected final static String DEMO_CREATED_KEY = "DEMO_CREATED"; private static final String IS_EXPANDED_FRAGMENT = "IS_EXPANDED"; // panel? ?? protected final static String TAG_FRAGMENT_PANE1 = "fragment_pane1"; protected final static String TAG_FRAGMENT_PANE2 = "fragment_pane2"; public static final String QUERY_KEY = "QUERY"; // private static final String STATE_PREVIOUSLY_SELECTED_KEY = // "com.hangulo.powercontact.SELECTED_ITEM"; // //private static final String DISTANCE_UNITS_KEY = "DISTANCE_UNITS_KEY"; // distance units save key protected Geocoder mGeocoder; // local geocoding ArrayList<PowerContactAddress> mPowerContactArrayList = new ArrayList<>(); // save positions boolean mTwoPane; // determine two_pane mode ProgressBar mProgressCircle; // loading circle // default values --> settings public static PowerContactSettings mPowerContactSettings = new PowerContactSettings(); // settings value boolean demoCreated; // demo data ? boolean isLoaderInitAlready; // ? ? init ? (onConnection?..) boolean isLoaderRestartNeed; // ? ?? ? ? (onConnection?..) protected GoogleApiClient mGoogleApiClient; // Provides the entry point to Google Play services. protected String mLastUpdateTime; // Time when the location was updated represented as a String. protected Location mCurrentLocation; // Represents a geographical location. MapViewFragment mMapFragment; ContactsListFragment mListFragment; String mAccountName = null; // account name boolean FROM_WIDGET; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // supprot two pane mode mTwoPane = getResources().getBoolean(R.bool.two_pane); // two_pane mode check // Analytics tracking start ((AnalyticsApplication) getApplication()).startTracking(); // use toolbar Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar); setSupportActionBar(toolbar); // ? // setting left drawer setleftMenuDrawer(toolbar); mTopFrameLayout = (FrameLayout) findViewById(R.id.top_frame_layout); // ? mTopLayout = (android.support.design.widget.AppBarLayout) findViewById(R.id.layout_toolbar); // ?? ? mProgressCircle = (ProgressBar) findViewById(R.id.loading_circle); // loading circle // ?? ? ?? . (? ? .) mGeocoder = new Geocoder(this, Locale.KOREA); // public Geocoder (Context context, Locale locale) // why korea??? -=--> ? ?. ? ??. mTextDemoMode = (TextView) findViewById(R.id.text_demo_mode); mMakeDemoButton = (FloatingActionButton) findViewById(R.id.fab_make_demo); mMakeDemoButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { makeDemoData(200); getSupportLoaderManager().restartLoader(Constants.POWERCONTACT_LOADER, null, MainActivity.this); // reset Loader } }); readDefaultSettings(mPowerContactSettings); // ? ?. (? ?? .) if (savedInstanceState != null) { // ? ? ? .... // If we're restoring state after this fragment was recreated then // retrieve previous search term and previously selected search // result. mSearchKeyword = savedInstanceState.getString(QUERY_KEY); mPreviousSearchKeyword = mSearchKeyword; // ? mPowerContactSettings = savedInstanceState.getParcelable(POWER_CONTACT_SETTINGS_KEY); demoCreated = savedInstanceState.getBoolean(DEMO_CREATED_KEY); // https://developers.google.com/android/guides/api-client mResolvingError = savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false); mIsExpandedFragment = savedInstanceState.getBoolean("IS_EXPANDED", false); // ? ? ? // Update the value of mCurrentLocation from the Bundle and update the UI to show the // correct latitude and longitude. if (savedInstanceState.keySet().contains(LOCATION_KEY)) { // Since LOCATION_KEY was found in the Bundle, we can be sure that mCurrentLocation // is not null. mCurrentLocation = savedInstanceState.getParcelable(LOCATION_KEY); } // Update the value of mLastUpdateTime from the Bundle and update the UI. if (savedInstanceState.keySet().contains(LAST_UPDATED_TIME_STRING_KEY)) { mLastUpdateTime = savedInstanceState.getString(LAST_UPDATED_TIME_STRING_KEY); } } Intent intent = getIntent(); if (intent != null) { FROM_WIDGET = intent.getBooleanExtra(Constants.FROM_WIDGET_KEY, false); if (FROM_WIDGET) { Log.v(LOG_TAG, "From Widget distance"); setDistance(0.0f); // distance all mPowerContactSettings.setDemoMode(false); } } // ? ?? toggleDemoMode(mPowerContactSettings.isDemoMode()); // demo mode false! buildGoogleApiClient(); // // https://github.com/umano/AndroidSlidingUpPanel/blob/master/demo/src/com/sothree/slidinguppanel/demo/DemoActivity.java mMapFragment = (MapViewFragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT_PANE1); mListFragment = (ContactsListFragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT_PANE2); if (mMapFragment == null) mMapFragment = new MapViewFragment(); if (mListFragment == null) mListFragment = new ContactsListFragment(); getSupportFragmentManager().beginTransaction() .replace(R.id.contact_map_view_container, mMapFragment, TAG_FRAGMENT_PANE1).commit(); getSupportFragmentManager().beginTransaction() .replace(R.id.contact_list_view_container, mListFragment, TAG_FRAGMENT_PANE2).commit(); } // set left Menu drawer void setleftMenuDrawer(Toolbar toolbar) { mDrawer = (NavigationView) findViewById(R.id.main_drawer); mDrawer.setNavigationItemSelectedListener(this); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close); mDrawerLayout.setDrawerListener(mDrawerToggle); mDrawerToggle.syncState(); } // read prefrerence void readDefaultSettings(PowerContactSettings settings) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); // SharedPreferences prefMarkerType = getSharedPreferences(getString(R.string.pref_key_default_marker_type), Context.MODE_PRIVATE); settings.setMarkerType( Integer.parseInt(prefs.getString(getString(R.string.pref_key_default_marker_type), "0"))); // SharedPreferences prefDefaultDistance = getSharedPreferences(getString(R.string.pref_key_default_range_distance), Context.MODE_PRIVATE); // auto? ? ?? settings.setDistance(Double.parseDouble(prefs.getString(getString(R.string.pref_key_default_range_distance), String.valueOf(Constants.DEFAULT_DISTANCE_METER)))); // SharedPreferences prefDemoMode = getSharedPreferences(getString(R.string.pref_key_demo_mode_setting), Context.MODE_PRIVATE); settings.setDemoMode(prefs.getBoolean(getString(R.string.pref_key_demo_mode_setting), false)); // distance units 0:auto 1:meter 2:mile settings.setDistanceUnits( Integer.parseInt(prefs.getString(getString(R.string.pref_key_default_distance_units), String.valueOf(Constants.DISTANCE_UNITS_AUTO)))); } @Override protected void onResume() { // ? . --> . --> ... // ? ? . ( ? ) 2016.3.25 if (FROM_WIDGET) { Log.v(LOG_TAG, "onResume now setting spinner"); mListFragment.setSpinnerDistanceChanged( getResources().getStringArray(R.array.pref_range_distance_values_meter).length - 1); // ? . FROM_WIDGET = false; // reset for next } toggleDemoMode(mPowerContactSettings.isDemoMode()); // ? , , ? . if (mCurrentLocation == null) { isLoaderInitAlready = false; // wait until connected } else { Log.v(LOG_TAG, "Main/onResume-restartLoader()"); getSupportLoaderManager().restartLoader(Constants.POWERCONTACT_LOADER, null, this); // ?. } super.onResume(); } // on/off loading circle void showLoadingCircle(boolean onoff) { if (onoff) { mProgressCircle.bringToFront(); mProgressCircle.setVisibility(View.VISIBLE); // show loading circle } else mProgressCircle.setVisibility(View.GONE); // show off } @Override public void onBackPressed() { if (mDrawerLayout.isDrawerOpen(mDrawer)) // ? mDrawerLayout.closeDrawer(GravityCompat.START); else if (mIsExpandedFragment) launchSearchFragment(false); // ..? else super.onBackPressed(); } // @Override public void onSaveInstanceState(Bundle outState) { outState.putParcelable(POWER_CONTACT_SETTINGS_KEY, mPowerContactSettings); outState.putString(QUERY_KEY, mSearchKeyword); outState.putParcelable(LOCATION_KEY, mCurrentLocation); outState.putString(LAST_UPDATED_TIME_STRING_KEY, mLastUpdateTime); outState.putBoolean(STATE_RESOLVING_ERROR, mResolvingError); // https://developers.google.com/android/guides/api-client outState.putBoolean(IS_EXPANDED_FRAGMENT, mIsExpandedFragment); // ? ?? ? ? . ? ? ?? super.onSaveInstanceState(outState); } // demo data delete private void deleteDemoData() { // delete previous data first Uri uri = PowerContactContract.PowerContactEntry.CONTENT_URI; String sWhere = PowerContactContract.PowerContactEntry.COLUMN_CONTACT_DATA_TYPE + " = ?"; String[] sSelection = { String.valueOf(PowerContactContract.PowerContactEntry.CONTACT_DATA_TYPE_DEMO) }; int del_count = getContentResolver().delete(uri, sWhere, sSelection); // delete it Log.v(LOG_TAG, "makeDemoData()/deleted demo : " + del_count); } // demo mode? ? ? void toggleDemoMode(boolean newMode) { // ? // ? // ? // ? . if (mPowerContactSettings == null) return; // ok... change it mPowerContactSettings.setDemoMode(newMode); // demo mode /* if (mDemoSwitch!=null) mDemoSwitch.setChecked(newMode); */ if (newMode) { // demo mode mMakeDemoButton.show(); // refresh? ?... ? . mTextDemoMode.setVisibility(View.VISIBLE); // ?? ? ? ? . } else { mMakeDemoButton.hide(); // ? mTextDemoMode.setVisibility(View.INVISIBLE); } } // make dummy addresses for testing private int makeDemoData(int max) { showLoadingCircle(true); // ? ~~~!!!!! deleteDemoData(); // ?? . String[] dummyNames; dummyNames = getResources().getStringArray(R.array.dummy_names); int maxNames = dummyNames.length - 1; Vector<ContentValues> cVVector = new Vector<>(max + 10); // ArrayList<PowerContactAddress> retAddress = new ArrayList<>(); LatLng currentLatLng = getCurrentLatLng(); double lat, lng; for (int i = 1; i <= (max + 2); i++) { // South Korea // double latitude = Utils.getRandomNumber((double) 36.4922565f, (double) 38.4922565f); // double longitude = Utils.getRandomNumber((double) 125.92319053333333f, (double) 127.92319053333333f); ContentValues addrValues = new ContentValues(); // addr String name = dummyNames[Utils.getRandomNumber(0, maxNames)] + " :" + i; if (i <= max) { lat = Utils.getRandomNumber((currentLatLng.latitude - 1), currentLatLng.latitude + 1); lng = Utils.getRandomNumber(currentLatLng.longitude - 1, currentLatLng.longitude + 1); } else {// to make same location data lat = currentLatLng.latitude; lng = currentLatLng.longitude; name = "duplicated" + i; } long contactId = 100000 + i; long dataId = 1000000 + i; String lookupKey = ""; String address = "Address Phone " + i; int type = 1; String addrLabel = ""; // double dist = Utils.getDistanceX(currentLatLng.latitude, currentLatLng.longitude, lat, lng); // addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_CONTACT_ID, contactId); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_DATA_ID, dataId); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_LOOKUP_KEY, lookupKey); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_NAME, name); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_ADDR, address); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_TYPE, type); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_LABEL, addrLabel); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_LAT, lat); // ? addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_LNG, lng); //? // constants for calculation distance query * http://king24.tistory.com/4 addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_SIN_LAT, Math.sin(Math.toRadians(lat))); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_SIN_LNG, Math.sin(Math.toRadians(lng))); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_COS_LAT, Math.cos(Math.toRadians(lat))); addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_COS_LNG, Math.cos(Math.toRadians(lng))); // this is demo addrValues.put(PowerContactContract.PowerContactEntry.COLUMN_CONTACT_DATA_TYPE, PowerContactContract.PowerContactEntry.CONTACT_DATA_TYPE_DEMO); cVVector.add(addrValues); // save this row --> ??. } // wrote to database // bulk update int return_count = 0; if (cVVector.size() > 0) { ContentValues[] cvArray = new ContentValues[cVVector.size()]; cVVector.toArray(cvArray); return_count = getContentResolver().bulkInsert(PowerContactContract.PowerContactEntry.CONTENT_URI, cvArray); } showDemoInfo(return_count); Log.v(LOG_TAG, "makeDemoData()/dummydata input : " + return_count); showLoadingCircle(false); return return_count; } // .. void showDemoInfo(int count) { //final int max_num = max; Snackbar snackbar = Snackbar.make(mTopFrameLayout, count + " " + getString(R.string.msg_demo_data_created), Snackbar.LENGTH_LONG).setAction(getString(R.string.msg_delete), new View.OnClickListener() { // remake @Override public void onClick(View view) { deleteDemoData(); } }); snackbar.show(); } // left drawer // @Override public boolean onNavigationItemSelected(MenuItem menuItem) { //Navigation? ?? ?? ? // update the main content by replacing fragments // ? ?? ? ?? . //Intent intent; int mSelectedId; menuItem.setChecked(true); mSelectedId = menuItem.getItemId(); switch (mSelectedId) { case R.id.drawer_menu_header: mDrawerLayout.closeDrawer(GravityCompat.START); //Drawer ? return true; case R.id.main_drawer_item_01: { // ? mDrawerLayout.closeDrawer(GravityCompat.START); //Drawer ? selectAccount(true); // start sync return true; } case R.id.main_drawer_item_02: // ?? // Toast.makeText(this, "Menu item selected -> " + position, Toast.LENGTH_SHORT).show(); { mDrawerLayout.closeDrawer(GravityCompat.START); //Drawer ? Intent intentNext = new Intent(this, ErrorContactsListActivity.class); startActivity(intentNext); return true; } case R.id.main_drawer_item_04: { // Settings mDrawerLayout.closeDrawer(GravityCompat.START); Intent SettingActivity = new Intent(this, SettingsActivity.class); startActivityForResult(SettingActivity, Constants.SETTINGS_REQUEST); // when settings changed then apply it immediately return true; } case R.id.main_drawer_item_05: // about mDrawerLayout.closeDrawer(GravityCompat.START); //Drawer ? OpensourceFragment.displayLicensesFragment(getSupportFragmentManager()); return true; } return false; } // Loader callback @Override public Loader<Cursor> onCreateLoader(int i, Bundle bundle) { LatLng currentLatLng = getCurrentLatLng(); String[] projection = { PowerContactContract.PowerContactEntry.COLUMN_CONTACT_ID, PowerContactContract.PowerContactEntry.COLUMN_DATA_ID, PowerContactContract.PowerContactEntry.COLUMN_LOOKUP_KEY, PowerContactContract.PowerContactEntry.COLUMN_NAME, PowerContactContract.PowerContactEntry.COLUMN_ADDR, PowerContactContract.PowerContactEntry.COLUMN_TYPE, PowerContactContract.PowerContactEntry.COLUMN_LABEL, PowerContactContract.PowerContactEntry.COLUMN_PHOTO, PowerContactContract.PowerContactEntry.COLUMN_LAT, PowerContactContract.PowerContactEntry.COLUMN_LNG, PowerContactContract.PowerContactEntry.COLUMN_SIN_LAT, PowerContactContract.PowerContactEntry.COLUMN_SIN_LNG, PowerContactContract.PowerContactEntry.COLUMN_COS_LAT, PowerContactContract.PowerContactEntry.COLUMN_COS_LNG, }; Log.v(LOG_TAG, "LOADER:MainActivity/onCreateLoader : distance " + mPowerContactSettings.getDistance()); int mode; mode = (mPowerContactSettings.isDemoMode()) ? PowerContactContract.PowerContactEntry.POWERCONTACT_MODE_DEMO : PowerContactContract.PowerContactEntry.POWERCONTACT_MODE_NORMAL; Log.v(LOG_TAG, "LOADER:MainActivity/onCreateLoader: DEMOMODE" + mode); return new CursorLoader(this, PowerContactContract.PowerContactEntry.buildLocationByDistance(currentLatLng.latitude, currentLatLng.longitude, mPowerContactSettings.getDistance(), mode), projection, // projection // only works null, // cols for "where" clause // ignored ? null, // values for "where" clause // ignored ? PowerContactContract.PowerContactEntry.COLUMN_AS_DISTANCE + " DESC"); // sort order --> distance); } // Query index static final int INDEX_COL_CONTACT_ID = 0; static final int INDEX_COL_DATA_ID = 1; static final int INDEX_COL_LOOKUP_KEY = 2; static final int INDEX_COL_NAME = 3; static final int INDEX_COL_ADDR = 4; static final int INDEX_COL_TYPE = 5; static final int INDEX_COL_LABEL = 6; static final int INDEX_COL_PHOTO = 7; static final int INDEX_COL_LAT = 8; static final int INDEX_COL_LNG = 9; static final int INDEX_COL_DISTANCE = 14; @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { Log.v(LOG_TAG, "LOADER:MainActivity/onLoaderFinished : cursor num " + cursor.getCount()); mPowerContactArrayList.clear(); // first clear! if (cursor.moveToFirst()) { do { long contact_id = cursor.getLong(INDEX_COL_CONTACT_ID); long data_id = cursor.getLong(INDEX_COL_DATA_ID); String lookup_key = cursor.getString(INDEX_COL_LOOKUP_KEY); String name = cursor.getString(INDEX_COL_NAME); String addr = cursor.getString(INDEX_COL_ADDR); int type = cursor.getInt(INDEX_COL_TYPE); String label = cursor.getString(INDEX_COL_LABEL); double lat = cursor.getDouble(INDEX_COL_LAT); double lng = cursor.getDouble(INDEX_COL_LNG); double dist = cursor.getDouble(INDEX_COL_DISTANCE); // distance String photo = cursor.getString(INDEX_COL_PHOTO); // photo mPowerContactArrayList.add(new PowerContactAddress(contact_id, data_id, lookup_key, name, addr, type, label, photo, lat, lng, dist)); } while (cursor.moveToNext()); } Log.v(LOG_TAG, "LOADER:MainActivity/onLoaderFinished : powercontact size " + mPowerContactArrayList.size()); // ? ?? . // . if (mMapFragment != null) { Log.v(LOG_TAG, "LOADER:MainActivity/mMapFragment/setClusterManager :distance " + mPowerContactSettings.getDistance()); mPreviousSearchKeyword = mSearchKeyword; mMapFragment.setClusterManager(mPowerContactArrayList, mPowerContactSettings.getMarkerType()); // ?? . } if (mListFragment != null) { // mListFragment.setContactsList(mPowerContactArrayList, mPowerContactSettings.getDistance()); // ? . Log.v(LOG_TAG, "LOADER:MainActivity/mListFragment/restartLoader() : "); mListFragment.restartLoader(); } } @Override public void onLoaderReset(Loader<Cursor> loader) { // ? ?? . // .. // ... ?.. Log.v(LOG_TAG, "LOADER:MainActivity/onLoaderReset : "); mPowerContactArrayList.clear(); // clear all data // ? ? --> ? if (mMapFragment != null) { mPreviousSearchKeyword = mSearchKeyword; mMapFragment.setClusterManager(mPowerContactArrayList, mPowerContactSettings.getMarkerType()); // ?? . } if (mListFragment != null) { //getSupportLoaderManager().restartLoader(Constants.CONTACTLIST_LOADER, null, mListFragment); mListFragment.setLoaderReset(); // call loader routain //mListFragment.setContactsList(mPowerContactArrayList, mPowerContactSettings.getDistance()); // ? . } } // -==================== ListView callbacks =============================================== // mapview? ? ? (listfragment? ) // callback (ContactsListFragment call back) @Override public void makeMapClusterItemClick(PowerContactAddress item) { if (mMapFragment != null) mMapFragment.onClusterItemClickFromListView(item); } // // slide panel? ?? on/off (listfragment? ) // @Override // public void setSlidingUpPanelEnabled(boolean isTurnon) { // mSlidingUpPanelLayout.setEnabled(isTurnon); // } // ? --> ?? 2016.1.3 @Override public void restartMainLoader(double distance) { Log.v(LOG_TAG, "restartMainLoader "); mPowerContactSettings.setDistance(distance); // ? ?. --> if (mCurrentLocation == null) isLoaderRestartNeed = true; // set true (when it connected restart) else { Log.v(LOG_TAG, "Main/Callback _restartMainLoader "); getSupportLoaderManager().restartLoader(Constants.POWERCONTACT_LOADER, null, MainActivity.this); } } @Override public ArrayList<PowerContactAddress> getContactAddress() { return mPowerContactArrayList; } // ? @Override public PowerContactSettings getPowerContactSettings() { return mPowerContactSettings; } // ?. ?.... // http://stackoverflow.com/questions/26715942/change-the-size-of-a-fragment-with-a-button // --> ? // http://stackoverflow.com/questions/32292656/percentrelativelayout-how-to-set-the-height-programatically // --> ? . public void launchSearchFragment(boolean onoff) { if (mTwoPane) return; // twopane ? ? . ActionBar actionBar = getSupportActionBar(); if (onoff == mIsExpandedFragment) return; // ? ? ? ? ? . FrameLayout view = (FrameLayout) findViewById(R.id.contact_list_view_container); PercentFrameLayout.LayoutParams params = (PercentFrameLayout.LayoutParams) view.getLayoutParams(); // This will currently return null, if it was not constructed from XML. PercentLayoutHelper.PercentLayoutInfo info = params.getPercentLayoutInfo(); if (onoff) { // expand info.heightPercent = 1.0f; mIsExpandedFragment = true; // ? if (actionBar != null) actionBar.hide(); // ? ? ... // // change status bar color if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(ContextCompat.getColor(this, R.color.myColorPrimaryDark)); } if (mListFragment != null && mListFragment.mBtnHomeUp != null) mListFragment.mBtnHomeUp.setVisibility(View.VISIBLE); // ? ? ? . } else { // collapse info.heightPercent = 0.4f; mIsExpandedFragment = false; // ? . if (actionBar != null) actionBar.show(); // ? ? ... // // change status bar color if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(ContextCompat.getColor(this, R.color.myColorPrimaryDark)); } if (mListFragment != null && mListFragment.mBtnHomeUp != null) { mListFragment.mBtnHomeUp.setVisibility(View.GONE); // ? . // ?... ? ?... // mListFragment.mSearchView.setIconified(false); } } view.requestLayout(); // // LinearLayout layoutListView = (LinearLayout) findViewById(R.id.testtest); // lpListView = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT,0); // if(onoff) // lpListView.weight=20; // else // lpListView.weight=2; // layoutListView.setLayoutParams(lpListView); } // expanded ? . @Override public boolean isExpandedListViewFragment() { return mIsExpandedFragment; } // ... // listview call back // unit? . 1(meter) ? 2(mile)? . public int getRealDistanceUnits() { return mPowerContactSettings.getRealDistanceUnits(); } // . @Override public void setDistance(double distance) { mPowerContactSettings.setDistance(distance); Log.v(LOG_TAG, "SET DISTANCE : " + distance); } // callabck mapview ------------------------- @Override public void selectListMarkerItem(PowerContactAddress item) { if (mListFragment != null) mListFragment.makeSelectItem(item); } // ? . @Override public int getMarkerType() { return mPowerContactSettings.getMarkerType(); } @Override public void searchListMarkerItemByCoord(LatLng data) { if (mListFragment != null) mListFragment.searchItemByCoord(data); } /* http://developer.dramancompany.com/2015/11/%EB%A6%AC%EB%A9%A4%EB%B2%84%EC%9D%98-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-6-0-m%EB%B2%84%EC%A0%84-%EB%8C%80%EC%9D%91%EA%B8%B0/ ? */ public boolean getCurrentLocation() { return getCurrentLocation(true); } static boolean isRequestingLocationPermissions = false; // ?? ?? public boolean getCurrentLocation(boolean locationChange) { // for support mashmallow // http://googledevkr.blogspot.kr/2015/09/playservice81android60.html if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) { if (mGoogleApiClient != null) { mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if (mCurrentLocation != null) if (locationChange) onMyLocationChanged(); return true; } } else { // Marshmallow if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? // if (ActivityCompat.shouldShowRequestPermissionRationale(this, // Manifest.permission.ACCESS_FINE_LOCATION)) { // // Show an expanation to the user *asynchronously* -- don't block // // this thread waiting for the user's response! After the user // // sees the explanation, try again to request the permission. // // } else { // ?? . requestLocationPermissions(Constants.REQUEST_CODE_LOCATION); // Request missing location permission. // if (!isRequestingLocationPermissions ) { // ActivityCompat.requestPermissions(this, // new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, // REQUEST_CODE_LOCATION); // isRequestingLocationPermissions = true; // } } } else { // if have permission if (mGoogleApiClient != null) { mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if (mCurrentLocation != null) if (locationChange) onMyLocationChanged(); return true; } } } return false; } // ?... // ACCESS_FINE_LOCATION ? .. requestCode? ? . @Override public void requestLocationPermissions(int requestCode) { // only 1) not requesting now 2) above marshmallow if (!isRequestingLocationPermissions && Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, requestCode); isRequestingLocationPermissions = true; } } // ? . // http://googledevkr.blogspot.kr/2015/09/playservice81android60.html @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == Constants.REQUEST_CODE_LOCATION) { // ??. .. .. isRequestingLocationPermissions = false; // ? . if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // success! // http://stackoverflow.com/questions/33562951/android-6-0-location-permissions //noinspection ResourceType <-- important mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if (mCurrentLocation != null) onMyLocationChanged(); if (mMapFragment != null && mMapFragment.mMap != null) { //noinspection ResourceType <-- important mMapFragment.mMap.setMyLocationEnabled(true); // my location enable } } else { // Permission was denied or request was cancelled Toast.makeText(this, R.string.msg_need_permission_location, Toast.LENGTH_SHORT).show(); } } else if (requestCode == Constants.REQUEST_CODE_CONTACTS) { // contacts isRequestingContactPermissions = false; // if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (mAccountName == null) selectAccount(true); // . else { startSyncDataIntentService(mAccountName); } } else { // fail Toast.makeText(this, R.string.msg_need_permission_contacts, Toast.LENGTH_SHORT).show(); } } } // get current location call back @Override public LatLng getCurrentLatLng() { //Location location = getCurrentLocation(); if (mCurrentLocation != null) return new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude()); else { Log.e(LOG_TAG, "ERROR:at getCurrentLocation"); return new LatLng(0.0f, 0.0f); // default value } } //--------- // FetchAddressIntentService // https://github.com/udacity/google-play-services/blob/master/LocationLessons_Final/LocationLesson2_3/app/src/main/java/com/google/devplat/lmoroney/locationlesson2_3/MainActivity.java void selectAccount(boolean runService) { // :http://stackoverflow.com/questions/22174259/pick-an-email-using-accountpicker-newchooseaccountintent // AccountManager accountManager = AccountManager.get(getApplicationContext()); // Account[] accounts = accountManager.getAccountsByType(null); // for (Account account : accounts) { // Log.d(LOG_TAG, "account: " + account.name + " : " + account.type); // } Intent aintent = AccountPicker.newChooseAccountIntent(null, null, new String[] { "com.google" }, true, getString(R.string.msg_support_account), null, null, null); // ? '?'? // ? https://developers.google.com/android/reference/com/google/android/gms/common/AccountPicker#public-methods int key = (runService) ? Constants.REQUEST_ACCOUNT_SELECT_AND_RUN_SERVICE : Constants.REQUEST_ACCOUNT_SELECT; startActivityForResult(aintent, key); } protected void startSyncDataIntentService(String accountName) { // show loading circle (? ?) // TODO if (accountName == null) return; if (onFetching) return; // it cannot running twice same time. // register message receiver if (messageReceiver == null) { messageReceiver = new MessageReciever(); } LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, new IntentFilter(Constants.MESSAGE_EVENT)); //register receiver // ? ? ?? . READ_CONTACTS Intent intent = new Intent(this, FetchPowerAddressIntentService.class); // intent.putExtra(Constants.RECEIVER, mResultReceiver); // ? ? . intent.putExtra(Constants.SERVICE_ACCOUNT_NAME_EXTRA, accountName); //intent.putExtra(Constants.SERVICE_LOCATION_DATA_EXTRA, mLastLocation); startService(intent); onFetching = true; } static boolean isRequestingContactPermissions = false; // ?? ?? public boolean getPermissionAndsyncData(String accountName) { // for support mashmallow // http://googledevkr.blogspot.kr/2015/09/playservice81android60.html if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) { // ?? ? startSyncDataIntentService(accountName); return true; } else { // Marshmallow if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? // if (ActivityCompat.shouldShowRequestPermissionRationale(this, // Manifest.permission.ACCESS_FINE_LOCATION)) { // // Show an expanation to the user *asynchronously* -- don't block // // this thread waiting for the user's response! After the user // // sees the explanation, try again to request the permission. // // } else { // ?? . // requestLocationPermissions(Constants.REQUEST_CODE_CONTACTS); if (!isRequestingContactPermissions && Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_CONTACTS }, Constants.REQUEST_CODE_CONTACTS); isRequestingContactPermissions = true; } // Request missing location permission. // if (!isRequestingLocationPermissions ) { // ActivityCompat.requestPermissions(this, // new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, // REQUEST_CODE_LOCATION); // isRequestingLocationPermissions = true; // } } } else { // if have permission startSyncDataIntentService(accountName); return true; } } return false; } // ? @Override protected void onStart() { super.onStart(); mGoogleApiClient.connect(); } @Override protected void onStop() { mGoogleApiClient.disconnect(); super.onStop(); } // broadcast @Override protected void onDestroy() { if (messageReceiver != null) { LocalBroadcastManager.getInstance(this).unregisterReceiver(messageReceiver); messageReceiver = null; } super.onDestroy(); } // get location // package com.google.android.gms.location.sample.locationupdates; /** * Builds a GoogleApiClient. Uses the {@code #addApi} method to request the * LocationServices API. */ protected synchronized void buildGoogleApiClient() { Log.i(LOG_TAG, "Building GoogleApiClient"); if (mGoogleApiClient == null) { mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this) .addOnConnectionFailedListener(this).addApi(LocationServices.API).build(); } } @Override public void onConnectionSuspended(int cause) { // The connection to Google Play services was lost for some reason. We call connect() to // attempt to re-establish the connection. Log.i(LOG_TAG, "Connection suspended"); mGoogleApiClient.connect(); } // @Override // public void onConnectionFailed(ConnectionResult result) { // // Refer to the javadoc for ConnectionResult to see what error codes might be returned in // // onConnectionFailed. // Log.i(LOG_TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode()); // } // http://googledevkr.blogspot.kr/2015/09/playservice81android60.html // ? // https://developers.google.com/android/guides/api-client @Override public void onConnectionFailed(ConnectionResult result) { if (mResolvingError) { // Already attempting to resolve an error. Log.e(LOG_TAG, "Already attempting to resolve an error."); } else if (result.hasResolution()) { try { mResolvingError = true; result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR); } catch (IntentSender.SendIntentException e) { // There was an error with the resolution intent. Try again. mGoogleApiClient.connect(); } } else { // Show dialog using GooglePlayServicesUtil.getErrorDialog() showErrorDialog(result.getErrorCode()); //getErrorDialog(this, result.getErrorCode(), 0, null); mResolvingError = true; } } // The rest of this code is all about building the error dialog // https://developers.google.com/android/guides/api-client /* Creates a dialog for an error message */ private void showErrorDialog(int errorCode) { // Create a fragment for the error dialog ErrorDialogFragment dialogFragment = new ErrorDialogFragment(); // Pass the error that should be displayed Bundle args = new Bundle(); args.putInt(DIALOG_ERROR, errorCode); dialogFragment.setArguments(args); dialogFragment.show(getSupportFragmentManager(), "errordialog"); } // https://developers.google.com/android/guides/api-client /* Called from ErrorDialogFragment when the dialog is dismissed. */ public void onDialogDismissed() { mResolvingError = false; } /* A fragment to display an error dialog */ public static class ErrorDialogFragment extends DialogFragment { public ErrorDialogFragment() { } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // Get the error code and retrieve the appropriate dialog int errorCode = this.getArguments().getInt(DIALOG_ERROR); return GoogleApiAvailability.getInstance().getErrorDialog(this.getActivity(), errorCode, REQUEST_RESOLVE_ERROR); } @Override public void onDismiss(DialogInterface dialog) { ((MainActivity) getActivity()).onDialogDismissed(); } } /** * Runs when a GoogleApiClient object successfully connects. */ @Override public void onConnected(Bundle connectionHint) { Log.i(LOG_TAG, "Connected to GoogleApiClient"); if (mCurrentLocation == null) { getCurrentLocation(); Log.v(LOG_TAG, "Now getCurrentLocation / onConnected()"); } } // toolbar menu @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_main, menu); /* MenuItem demoMenu = menu.findItem(R.id.action_switch_demo); mDemoSwitch = (SwitchCompat) MenuItemCompat.getActionView(demoMenu); // http://developer.android.com/guide/topics/ui/controls/togglebutton.html mDemoSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { toggleDemoMode(isChecked); // Log.v(LOG_TAG, "Main/onCreateOptionsMenu/mDemoSwitch - restartLoader()"); getSupportLoaderManager().restartLoader(Constants.POWERCONTACT_LOADER, null, MainActivity.this); // reset Loader } }); if(mPowerContactSettings != null) if(mPowerContactSettings.isDemoMode()) mDemoSwitch.setChecked(true); else mDemoSwitch.setChecked(false); */ return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; default: super.onOptionsItemSelected(item); } return super.onOptionsItemSelected(item); } @Override protected void onRestart() { super.onRestart(); } // // activity Result ========================================= @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Check which request we're responding to if (requestCode == Constants.SETTINGS_REQUEST) { // Make sure the request was successful if (resultCode == RESULT_OK) { // ok there is some changed vaule, find & activate to current screen // PowerContactSettings mLastSavedSettings = new PowerContactSettings(); // --> ? .... PowerContactSettings changedSettings = new PowerContactSettings(); readDefaultSettings(changedSettings); // ?? ?. if (!changedSettings.equals(mPowerContactSettings)) { // ? ... // . // onResume? ?? ? ?. // ?. // 3. ( ?) // 4. ? boolean mustChangeSpinnerType = false; boolean mustChangeSpinnerPosition = false; if (changedSettings.getDistance() != mPowerContactSettings.getDistance()) { // .. ?? .. ? . mustChangeSpinnerPosition = true; // mustChangeAllLoader = true; mPowerContactSettings.setDistance(changedSettings.getDistance()); // change ~! } if (changedSettings.getMarkerType() != mPowerContactSettings.getMarkerType()) { // Toast.makeText(this, "Now change marker", Toast.LENGTH_SHORT).show(); mPowerContactSettings.setMarkerType(changedSettings.getMarkerType()); } if (changedSettings.getRealDistanceUnits() != mPowerContactSettings.getRealDistanceUnits()) { // ... // 1. . // 2. .( ) mustChangeSpinnerType = true; mustChangeSpinnerPosition = true; // mustChangeListView=true; mPowerContactSettings.setDistanceUnits(changedSettings.getRealDistanceUnits()); // ? ? ?...??? --> settings? ?. } // demo mode if (changedSettings.isDemoMode() != mPowerContactSettings.isDemoMode()) { // demo mode .. ? ? ?? --> ? mPowerContactSettings.setDemoMode(changedSettings.isDemoMode()); } if (mustChangeSpinnerType) { if (mListFragment != null) { mListFragment.setDistanceSpinnerAdapter(); } } if (mustChangeSpinnerPosition) { final int num_array_pref_range_distance_values; // ?? ? ? ? . if (mPowerContactSettings.getRealDistanceUnits() == Constants.DISTANCE_UNITS_METER) { num_array_pref_range_distance_values = R.array.pref_range_distance_values_meter; } else { // if (mPowerContactSettings.getRealDistanceUnits() == Constants.DISTANCE_UNITS_MILE) num_array_pref_range_distance_values = R.array.pref_range_distance_values_mile; } if (mListFragment != null) { // ? ? ?? ... mListFragment.mSpinnerDistance.setSelection(Arrays .asList(getResources().getStringArray(num_array_pref_range_distance_values)) .indexOf((String.valueOf(mPowerContactSettings.getDistance())))); // set default distance // 2. ? . // Toast.makeText(this, "Now change marker", Toast.LENGTH_SHORT).show(); } } // ? ? onResume()? ? ??. } } } else if (requestCode == REQUEST_RESOLVE_ERROR) { // https://developers.google.com/android/guides/api-client mResolvingError = false; if (resultCode == RESULT_OK) { // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } } else if (requestCode == Constants.REQUEST_ACCOUNT_SELECT || requestCode == Constants.REQUEST_ACCOUNT_SELECT_AND_RUN_SERVICE && resultCode == RESULT_OK) { mAccountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); // write to shared preference SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = prefs.edit(); editor.putString(Constants.SETTINGS_ACCOUNT_KEY, mAccountName); editor.apply(); if (requestCode == Constants.REQUEST_ACCOUNT_SELECT_AND_RUN_SERVICE) // ok start service getPermissionAndsyncData(mAccountName); } } // current location button clicked on MapView @Override public void onMyLocationButtonClick() { getCurrentLocation(false); // don't update map, because this calls from map.. it is changed automatilcally } public void onMyLocationChanged() { //Log.v(LOG_TAG, "onLocationChanged() called"); // onConnection? ? if (!isLoaderInitAlready) { getSupportLoaderManager().initLoader(Constants.POWERCONTACT_LOADER, null, this); //Log.v(LOG_TAG, "LoaderInit/onLocationChanged()"); isLoaderInitAlready = true; } else if (isLoaderRestartNeed) { getSupportLoaderManager().restartLoader(Constants.POWERCONTACT_LOADER, null, MainActivity.this); //Log.v(LOG_TAG, "Main/onLocationChanged()-restartLoader()"); isLoaderRestartNeed = false; } if (mMapFragment != null) { //Log.v(LOG_TAG, "moveMapLocation/onLocationChanged()"); mMapFragment.moveMapLocation(getCurrentLatLng()); } // shared prefrerence? ?.(? ) // save last position (for using wdiget) SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = prefs.edit(); editor.putString(Constants.SETTINGS_LAST_LOCATION_LAT_KEY, String.valueOf(mCurrentLocation.getLatitude())); editor.putString(Constants.SETTINGS_LAST_LOCATION_LNG_KEY, String.valueOf(mCurrentLocation.getLongitude())); editor.apply(); } // Broadcast receiver ==================================================================== // get message from private class MessageReciever extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int result = intent.getIntExtra(Constants.RESULT_KEY, Constants.FAILURE_RESULT); String msgKey = intent.getStringExtra(Constants.MESSAGE_KEY); if (msgKey != null) Toast.makeText(MainActivity.this, intent.getStringExtra(Constants.MESSAGE_KEY), Toast.LENGTH_LONG) .show(); switch (result) { // if message contains "service is ended" then delete it's result case Constants.SUCCESS_RESULT: case Constants.FAILURE_RESULT: // 1) remove loading circle // TODO showLoadingCircle(false); onFetching = false; // now turn off // 2) remove broadcast receiver LocalBroadcastManager.getInstance(MainActivity.this).unregisterReceiver(messageReceiver); messageReceiver = null; break; case Constants.START_LOADING: showLoadingCircle(true); // start loding circle break; } } } } // ------------ end of program ---------------------------------------------------------------------------------