/* * * * Copyright (C) 2014 Open Whisper Systems * * 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 org.anhonesteffort.flock; import android.accounts.Account; import android.accounts.AccountManager; import android.app.Activity; import android.content.ContentProviderClient; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.RemoteException; import android.provider.ContactsContract; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.CompoundButton; import android.widget.ListView; import android.widget.Toast; import org.anhonesteffort.flock.sync.addressbook.AddressbookSyncScheduler; import org.anhonesteffort.flock.sync.addressbook.LocalContactCollection; import java.util.LinkedList; import java.util.List; /** * Programmer: rhodey */ public class ImportContactsFragment extends AccountAndKeyRequiredFragment implements CompoundButton.OnCheckedChangeListener { private static final String TAG = "org.anhonesteffort.flock.ImportContactsFragment"; private AsyncTask asyncTask; private ListView accountDetailsListView; private SetupActivity setupActivity; private List<ImportContactsFragment.AccountContactDetails> selectedAccounts; private boolean list_is_initializing = false; @Override public void onAttach(Activity activity) { super.onAttach(activity); if (activity instanceof SetupActivity) this.setupActivity = (SetupActivity) activity; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View fragmentView = inflater.inflate(R.layout.fragment_simple_list, container, false); if (!accountAndKeyAvailable()) return fragmentView; initButtons(); return fragmentView; } @Override public void onResume() { super.onResume(); if (!accountAndKeyAvailable()) return ; initializeList(); } @Override public void onPause() { super.onPause(); if (asyncTask != null && !asyncTask.isCancelled()) asyncTask.cancel(true); } private void initButtons() { Button actionButton; if (setupActivity != null) { actionButton = (Button) getActivity().findViewById(R.id.button_next); actionButton.setText(R.string.skip); } else { actionButton = (Button) getActivity().findViewById(R.id.button_action); actionButton.setText(R.string.cancel); } actionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent copyService = new Intent(getActivity(), ContactCopyService.class); if (selectedAccounts.size() == 0) { handleBackgroundImportStarted(); return; } for (ImportContactsFragment.AccountContactDetails copyAccount : selectedAccounts) { copyService.setAction(ContactCopyService.ACTION_QUEUE_ACCOUNT_FOR_COPY); copyService.putExtra(ContactCopyService.KEY_FROM_ACCOUNT, copyAccount.account); copyService.putExtra(ContactCopyService.KEY_TO_ACCOUNT, account.getOsAccount()); copyService.putExtra(ContactCopyService.KEY_CONTACT_COUNT, copyAccount.contact_count); getActivity().startService(copyService); } copyService.setAction(ContactCopyService.ACTION_START_COPY); getActivity().startService(copyService); handleBackgroundImportStarted(); } }); } private void initializeList() { Log.d(TAG, "initializeList()"); if (list_is_initializing) return; selectedAccounts = new LinkedList<AccountContactDetails>(); list_is_initializing = true; asyncTask = new RetrieveAccountContactDetailsTask().execute(); } @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { Button actionButton; if (setupActivity != null) actionButton = (Button) getActivity().findViewById(R.id.button_next); else actionButton = (Button) getActivity().findViewById(R.id.button_action); if (selectedAccounts.size() > 0 && setupActivity != null) actionButton.setText(R.string.next); else if (selectedAccounts.size() > 0 && setupActivity == null) actionButton.setText(R.string.button_import); else if (setupActivity != null) actionButton.setText(R.string.skip); else actionButton.setText(R.string.cancel); } private void handleBackgroundImportStarted() { Log.d(TAG, "handleBackgroundImportStarted()"); Integer contactCount = 0; for (ImportContactsFragment.AccountContactDetails copyAccount : selectedAccounts) contactCount += copyAccount.contact_count; if (selectedAccounts.size() > 0) { String toastMessage = getString(R.string.started_background_import_of_contacts, contactCount); Toast.makeText(getActivity(), toastMessage, Toast.LENGTH_SHORT).show(); } if (setupActivity != null) setupActivity.updateFragmentUsingState(SetupActivity.STATE_IMPORT_CALENDARS); else getActivity().finish(); } private void handleAccountDetailsRetrieved(List<AccountContactDetails> accountDetails) { Log.d(TAG, "handleAccountDetailsRetrieved()"); AccountContactDetails[] accountDetailsArray = new AccountContactDetails[accountDetails.size()]; for (int i = 0; i < accountDetails.size(); i++) accountDetailsArray[i] = accountDetails.get(i); AccountContactDetailsListAdapter listAdapter = new AccountContactDetailsListAdapter(getActivity().getBaseContext(), accountDetailsArray, selectedAccounts, this); accountDetailsListView = (ListView)getView().findViewById(R.id.list); accountDetailsListView.setAdapter(listAdapter); list_is_initializing = false; } private class RetrieveAccountContactDetailsTask extends AsyncTask<Void, Void, Bundle> { List<AccountContactDetails> accountDetails = new LinkedList<AccountContactDetails>(); @Override protected void onPreExecute() { Log.d(TAG, "RetrieveAccountContactDetailsTask()"); getActivity().setProgressBarIndeterminateVisibility(true); getActivity().setProgressBarVisibility(true); } protected void populateAccountContactCounts(List<AccountContactDetails> accounts) throws RemoteException { Uri rawContactsUri = null; Cursor cursor = null; ContentProviderClient client = getActivity().getContentResolver() .acquireContentProviderClient(AddressbookSyncScheduler.CONTENT_AUTHORITY); for (AccountContactDetails accountDetails : accounts) { if (!accountDetails.account.type.equals(getString(R.string.local_storage))) { rawContactsUri = LocalContactCollection .getSyncAdapterUri(ContactsContract.RawContacts.CONTENT_URI, accountDetails.account); cursor = client.query(rawContactsUri, null, null, null, null); accountDetails.contact_count = cursor.getCount(); Log.d(TAG, "account with type " + accountDetails.account.type + " has " + accountDetails.contact_count + " contacts"); } else { rawContactsUri = ContactsContract.RawContacts.CONTENT_URI; cursor = client.query(rawContactsUri, null, ContactsContract.RawContacts.ACCOUNT_TYPE + " IS NULL", null, null); accountDetails.contact_count = cursor.getCount(); Log.d(TAG, "local storage has " + accountDetails.contact_count + " contacts"); } cursor.close(); } } protected List<AccountContactDetails> getOtherAccounts() { List<AccountContactDetails> accounts = new LinkedList<AccountContactDetails>(); for (Account osAccount : AccountManager.get(getActivity()).getAccounts()) { if (!osAccount.name.equals(account.getOsAccount().name) && !osAccount.type.equals(account.getOsAccount().type)) { accounts.add(new AccountContactDetails(osAccount, 0)); } } accounts.add( new AccountContactDetails( new Account(getString(R.string.local_storage), getString(R.string.local_storage)),0 ) ); return accounts; } @Override protected Bundle doInBackground(Void... params) { Bundle result = new Bundle(); try { accountDetails = getOtherAccounts(); populateAccountContactCounts(accountDetails); result.putInt(ErrorToaster.KEY_STATUS_CODE, ErrorToaster.CODE_SUCCESS); } catch (RemoteException e) { ErrorToaster.handleBundleError(e, result); } return result; } @Override protected void onPostExecute(Bundle result) { Log.d(TAG, "STATUS: " + result.getInt(ErrorToaster.KEY_STATUS_CODE)); getActivity().setProgressBarIndeterminateVisibility(false); getActivity().setProgressBarVisibility(false); if (result.getInt(ErrorToaster.KEY_STATUS_CODE) == ErrorToaster.CODE_SUCCESS) handleAccountDetailsRetrieved(accountDetails); else ErrorToaster.handleDisplayToastBundledError(getActivity(), result); } } protected class AccountContactDetails { public Account account; public int contact_count; public AccountContactDetails(Account account, int contact_count) { this.account = account; this.contact_count = contact_count; } } }