/* * Copyright 2015. Appsi Mobile * * 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 com.appsimobile.appsii; import android.accounts.Account; import android.accounts.AccountManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.PeriodicSync; import android.content.SharedPreferences; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import com.appsimobile.appsii.module.home.WeatherFragment; import com.appsimobile.appsii.module.weather.WeatherContract; import com.appsimobile.appsii.module.weather.WeatherLoadingService; import com.appsimobile.appsii.preference.PreferenceHelper; import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; /** * Created by nick on 14/04/15. */ @Singleton public final class AccountHelper implements SharedPreferences.OnSharedPreferenceChangeListener { // The authority for the sync adapter's content provider public static final String AUTHORITY = WeatherContract.AUTHORITY; // An account type, in the form of a domain name // Do not use the BuildConfig.APPLICATION_ID because we use two variants and // only need one account public static final String ACCOUNT_TYPE = "com.appsimobile.appsii"; public static final long SECONDS_PER_MINUTE = 60L; public static final long SYNC_INTERVAL_IN_MINUTES = 60L; public static final long SYNC_INTERVAL = SYNC_INTERVAL_IN_MINUTES * SECONDS_PER_MINUTE; // The account name public static final String ACCOUNT = "Appsii"; private final PreferenceHelper mPreferenceHelper; private final AccountManager mAccountManager; private final Context mContext; SharedPreferences mPrefs; Account mAccount; String mDefaultWeatherUnit; @Inject public AccountHelper(Context context, SharedPreferences preferences, PreferenceHelper preferenceHelper, AccountManager accountManager) { mContext = context; mPrefs = preferences; mPreferenceHelper = preferenceHelper; mAccountManager = accountManager; BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { onWeatherUpdated(); } }; IntentFilter intentFilter = new IntentFilter(WeatherLoadingService.ACTION_WEATHER_UPDATED); mContext.registerReceiver(receiver, intentFilter); mDefaultWeatherUnit = preferenceHelper.getDefaultWeatherTemperatureUnit(); mPrefs.registerOnSharedPreferenceChangeListener(this); } @Nullable public static Account getExistingAccount(AccountManager accountManager) { Account[] accounts = accountManager.getAccountsByType(ACCOUNT_TYPE); if (accounts.length > 0) { return accounts[0]; } return null; } /** * Create a new dummy account for the sync adapter * * @param context The application context */ private static Account createSyncAccount(Context context, AccountManager accountManager) { // Create the account type and default account Account newAccount = new Account(ACCOUNT, ACCOUNT_TYPE); /* * Add the account and account type, no password or user data * If successful, return the Account object, otherwise report an error. */ if (!accountManager.addAccountExplicitly(newAccount, null, null)) { /* * The account exists or some other error occurred. Log this, report it, * or handle it internally. */ Log.i("Appsi", "local account already exists"); } return newAccount; } void onWeatherUpdated() { mPrefs.edit().putLong( WeatherLoadingService.PREFERENCE_LAST_UPDATED_MILLIS, System.currentTimeMillis()). apply(); } public void requestSync(String woeid) { Log.w("AccountHelper", "request sync " + ContentResolver.getIsSyncable(mAccount, AUTHORITY)); Bundle bundle = createManualSyncBundle(woeid); ContentResolver.requestSync(mAccount, AUTHORITY, bundle); } @NonNull private Bundle createManualSyncBundle(@Nullable String woeid) { Bundle bundle = createDefaultSyncBundle(); if (woeid != null) { bundle.putString(WeatherLoadingService.EXTRA_INCLUDE_WOEID, woeid); } bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); return bundle; } @NonNull private Bundle createDefaultSyncBundle() { String defaultUnit = mPreferenceHelper.getDefaultWeatherTemperatureUnit(); String unit = mPrefs.getString(WeatherFragment.PREFERENCE_WEATHER_UNIT, defaultUnit); Bundle bundle = new Bundle(); bundle.putString(WeatherLoadingService.EXTRA_UNIT, unit); return bundle; } public void configureAutoSyncAndSync() { createAccountIfNeeded(); updateSyncSettings(); if (ContentResolver.getIsSyncable(mAccount, AUTHORITY) < 1) { Log.d("AccountHelper", "making account syncable..."); ContentResolver.setIsSyncable(mAccount, AUTHORITY, 1); ContentResolver.setSyncAutomatically(mAccount, AUTHORITY, true); } requestSync(); // ContentResolver.requestSync(mAccount, AUTHORITY, Bundle.EMPTY); } public boolean createAccountIfNeeded() { // Get an instance of the Android account manager mAccount = getExistingAccount(mAccountManager); boolean created = mAccount == null; if (mAccount == null) { mAccount = createSyncAccount(mContext, mAccountManager); } // start of as not syncable ContentResolver.setIsSyncable(mAccount, AUTHORITY, -1); return created; } public void updateSyncSettings() { Bundle bundle = createDefaultSyncBundle(); List<PeriodicSync> syncs = ContentResolver.getPeriodicSyncs(mAccount, AUTHORITY); int N = syncs.size(); for (int i = 0; i < N; i++) { PeriodicSync sync = syncs.get(i); ContentResolver.removePeriodicSync(sync.account, sync.authority, sync.extras); } ContentResolver.addPeriodicSync( mAccount, AUTHORITY, bundle, SYNC_INTERVAL); } public void requestSync() { Log.w("AccountHelper", "request sync " + ContentResolver.getIsSyncable(mAccount, AUTHORITY)); Bundle extras = createManualSyncBundle(null /* no woeid */); ContentResolver.requestSync(mAccount, AUTHORITY, extras); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (getExistingAccount(mAccountManager) == null) { Log.d("AccountHelper", "Weather unit changed, but no account. Not updating settings…"); return; } if (ContentResolver.getIsSyncable(mAccount, AUTHORITY) > 0) { if ("weather_default_unit".equals(key)) { String value = sharedPreferences.getString(key, "c"); if (!TextUtils.equals(mDefaultWeatherUnit, value)) { mDefaultWeatherUnit = value; updateSyncSettings(); requestSync(); } } } else { Log.d("AccountHelper", "Weather unit changed, but account not syncable…"); } } }