/* * Copyright 2012 Google Inc. * * 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.google.android.apps.iosched.ui; import com.google.android.apps.iosched.R; import com.google.android.apps.iosched.provider.ScheduleContract; import com.google.android.apps.iosched.util.AccountUtils; import com.google.api.client.googleapis.extensions.android2.auth.GoogleAccountManager; import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockListFragment; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import android.accounts.Account; import android.accounts.AccountManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import java.util.Arrays; import java.util.List; import static com.google.android.apps.iosched.util.LogUtils.makeLogTag; /** * The first activity most users see. This wizard-like activity first presents an account * selection fragment ({@link ChooseAccountFragment}), and then an authentication progress fragment * ({@link AuthProgressFragment}). */ public class AccountActivity extends SherlockFragmentActivity implements AccountUtils.AuthenticateCallback { private static final String TAG = makeLogTag(AccountActivity.class); public static final String EXTRA_FINISH_INTENT = "com.google.android.iosched.extra.FINISH_INTENT"; private static final int REQUEST_AUTHENTICATE = 100; private final Handler mHandler = new Handler(); private Account mChosenAccount; private Intent mFinishIntent; private boolean mCancelAuth = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_account); if (getIntent().hasExtra(EXTRA_FINISH_INTENT)) { mFinishIntent = getIntent().getParcelableExtra(EXTRA_FINISH_INTENT); } if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, new ChooseAccountFragment(), "choose_account") .commit(); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_AUTHENTICATE) { if (resultCode == RESULT_OK) { tryAuthenticate(); } else { // go back to previous step mHandler.post(new Runnable() { @Override public void run() { getSupportFragmentManager().popBackStack(); } }); } } else { super.onActivityResult(requestCode, resultCode, data); } } private void tryAuthenticate() { AccountUtils.tryAuthenticate(AccountActivity.this, AccountActivity.this, REQUEST_AUTHENTICATE, mChosenAccount); } @Override public boolean shouldCancelAuthentication() { return mCancelAuth; } @Override public void onAuthTokenAvailable(String authToken) { ContentResolver.setIsSyncable(mChosenAccount, ScheduleContract.CONTENT_AUTHORITY, 1); if (mFinishIntent != null) { mFinishIntent.addCategory(Intent.CATEGORY_LAUNCHER); mFinishIntent.setAction(Intent.ACTION_MAIN); mFinishIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(mFinishIntent); } finish(); } /** * A fragment that presents the user with a list of accounts to choose from. Once an account is * selected, we move on to the login progress fragment ({@link AuthProgressFragment}). */ public static class ChooseAccountFragment extends SherlockListFragment { public ChooseAccountFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } @Override public void onResume() { super.onResume(); reloadAccountList(); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.add_account, menu); super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.menu_add_account) { Intent addAccountIntent = new Intent(Settings.ACTION_ADD_ACCOUNT); addAccountIntent.putExtra(Settings.EXTRA_AUTHORITIES, new String[]{ScheduleContract.CONTENT_AUTHORITY}); startActivity(addAccountIntent); return true; } return super.onOptionsItemSelected(item); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ViewGroup rootView = (ViewGroup) inflater.inflate( R.layout.fragment_login_choose_account, container, false); TextView descriptionView = (TextView) rootView.findViewById(R.id.choose_account_intro); descriptionView.setText(Html.fromHtml(getString(R.string.description_choose_account))); return rootView; } private AccountListAdapter mAccountListAdapter; private void reloadAccountList() { if (mAccountListAdapter != null) { mAccountListAdapter = null; } AccountManager am = AccountManager.get(getActivity()); Account[] accounts = am.getAccountsByType(GoogleAccountManager.ACCOUNT_TYPE); mAccountListAdapter = new AccountListAdapter(getActivity(), Arrays.asList(accounts)); setListAdapter(mAccountListAdapter); } private class AccountListAdapter extends ArrayAdapter<Account> { private static final int LAYOUT_RESOURCE = android.R.layout.simple_list_item_1; public AccountListAdapter(Context context, List<Account> accounts) { super(context, LAYOUT_RESOURCE, accounts); } private class ViewHolder { TextView text1; } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = getLayoutInflater(null).inflate(LAYOUT_RESOURCE, null); holder = new ViewHolder(); holder.text1 = (TextView) convertView.findViewById(android.R.id.text1); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } final Account account = getItem(position); if (account != null) { holder.text1.setText(account.name); } else { holder.text1.setText(""); } return convertView; } } @Override public void onListItemClick(ListView l, View v, int position, long id) { AccountActivity activity = (AccountActivity) getActivity(); ConnectivityManager cm = (ConnectivityManager) activity.getSystemService(CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); if (activeNetwork == null || !activeNetwork.isConnected()) { Toast.makeText(activity, R.string.no_connection_cant_login, Toast.LENGTH_SHORT).show(); return; } activity.mCancelAuth = false; activity.mChosenAccount = mAccountListAdapter.getItem(position); activity.getSupportFragmentManager().beginTransaction() .replace(R.id.fragment_container, new AuthProgressFragment(), "loading") .addToBackStack("choose_account") .commit(); activity.tryAuthenticate(); } } /** * This fragment shows a login progress spinner. Upon reaching a timeout of 7 seconds (in case * of a poor network connection), the user can try again. */ public static class AuthProgressFragment extends SherlockFragment { private static final int TRY_AGAIN_DELAY_MILLIS = 7 * 1000; // 7 seconds private final Handler mHandler = new Handler(); public AuthProgressFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_login_loading, container, false); final View takingAWhilePanel = rootView.findViewById(R.id.taking_a_while_panel); final View tryAgainButton = rootView.findViewById(R.id.retry_button); tryAgainButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { getFragmentManager().popBackStack(); } }); mHandler.postDelayed(new Runnable() { @Override public void run() { if (!isAdded()) { return; } takingAWhilePanel.setVisibility(View.VISIBLE); } }, TRY_AGAIN_DELAY_MILLIS); return rootView; } @Override public void onDetach() { super.onDetach(); ((AccountActivity) getActivity()).mCancelAuth = true; } } }