com.newtifry.android.ChooseAccount.java Source code

Java tutorial

Introduction

Here is the source code for com.newtifry.android.ChooseAccount.java

Source

/**
 * Newtifry for Android.
 * 
 * Copyright 2011 Daniel Foote
 *
 * 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.
 * 
 * The contents of this are heavily based on this blog post:
 * http://blog.notdot.net/2010/05/Authenticating-against-App-Engine-from-an-Android-app
 * Thanks dude for your awesome writeup!
 */

package com.newtifry.android;

import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONException;

//import com.actionbarsherlock.app.SherlockExpandableListActivity;
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.gcm.GCMRegistrar;
import com.newtifry.android.database.NewtifryAccount;
import com.newtifry.android.remote.BackendRequest;
import com.newtifry.android.remote.BackendResponse;
import com.newtifry.android.R;
import static com.newtifry.android.CommonUtilities.TAG;

import android.accounts.AccountManager;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class ChooseAccount extends SherlockListActivity
        implements CompoundButton.OnCheckedChangeListener, View.OnClickListener {
    private static final int REFRESH_IDS = 1;
    private final ChooseAccount thisActivity = this;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        AccountManager accountManager = AccountManager.get(getApplicationContext());

        // Sync our database. Only on create.
        NewtifryAccount.FACTORY.syncAccountList(this, accountManager);

        // Set the layout, and allow text filtering.
        setContentView(R.layout.screen_accounts);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        getListView().setTextFilterEnabled(true);
    }

    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setContentView(R.layout.screen_accounts);
    }

    public void onResume() {
        super.onResume();

        // When coming back, refresh our list of accounts.
        refreshView();

        // Show the help.
        //      SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
        if (Preferences.getChooseAccountFirstTime(this)) {
            // Show first time help.
            new AlertDialog.Builder(this).setTitle(getString(R.string.accounts_and_sources))
                    .setMessage(getString(R.string.accounts_help)).setPositiveButton(getString(R.string.ok), null)
                    .show();

            // And don't show again.
            Preferences.saveChooseAccountFirstTime(false, this);
            /*
                     Editor editor = settings.edit();
                     editor.putBoolean("chooseAccountFirstTime", false);
                     editor.commit();
            */
        }
    }

    public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
        boolean result = super.onCreateOptionsMenu(menu);
        menu.add(0, REFRESH_IDS, 0, R.string.refresh_ids).setIcon(android.R.drawable.ic_menu_rotate)
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
        return result;
    }

    public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            return true;
        case REFRESH_IDS:
            // Dispatch this to the updater service.
            Intent intentData = new Intent(getBaseContext(), UpdaterService.class);
            intentData.putExtra("type", "registration");
            intentData.putExtra("registration", GCMRegistrar.getRegistrationId(this));
            startService(intentData);

            Toast.makeText(thisActivity, getString(R.string.background_refreshing), Toast.LENGTH_SHORT).show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    // Refresh the list of accounts viewed by this activity.
    public void refreshView() {
        // Refresh our list of accounts.
        ArrayList<NewtifryAccount> accounts = NewtifryAccount.FACTORY.listAll(this);

        this.setListAdapter(new AccountArrayAdapter(this, this, R.layout.account_list_row, accounts));
    }

    // Handler for when you click an account name.
    // @param account
    public void clickAccountName(NewtifryAccount account) {
        // If enabled, launch the sources list for this account.
        if (account.getEnabled()) {
            Intent intent = new Intent(getBaseContext(), SourceList.class);
            intent.putExtra("account", account.getAccountName());
            startActivity(intent);
        }
    }

    // Handler for when you check or uncheck an account, which fires off a request to the server.
    // @param account
    // @param state

    public void checkedAccount(NewtifryAccount account, boolean state) {
        // Refresh the account object. In case it's changed.
        NewtifryAccount refreshedAccount = NewtifryAccount.FACTORY.get(this, account.getId());

        // Add some metadata to the request so we know how to deal with it
        // afterwards.
        HashMap<String, Object> metadata = new HashMap<String, Object>();
        metadata.put("account", refreshedAccount);

        String statusMessage;

        if (state) {
            // Enable the account.
            metadata.put("operation", "register");
            metadata.put("registration", GCMRegistrar.getRegistrationId(this));

            statusMessage = getString(R.string.registering_with_server);
        } else {
            // Disable the account.
            metadata.put("operation", "deregister");
            statusMessage = getString(R.string.deregistering_with_server);
        }

        // And send off the request.
        refreshedAccount.registerWithBackend(this, GCMRegistrar.getRegistrationId(this), state, statusMessage,
                handler, metadata);
    }

    // Private handler class that is the callback for when the external requests are complete.
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // Fetch out the response.
            BackendResponse response = (BackendResponse) msg.obj;

            // Was it successful?
            if (response.isError()) {
                // No, not successful.
                Toast.makeText(thisActivity, response.getError() + getString(R.string.try_again), Toast.LENGTH_LONG)
                        .show();
                BackendRequest request = response.getRequest();
                String operation = (String) request.getMeta("operation");
                if (operation.equals("register")) {
                    // TODO : uncheck account
                }

            } else {
                try {
                    // Fetch out metadata.
                    BackendRequest request = response.getRequest();
                    NewtifryAccount account = (NewtifryAccount) request.getMeta("account");
                    String operation = (String) request.getMeta("operation");

                    // Determine our operation.
                    if (operation.equals("register")) {
                        // We were registering the account.
                        // The server would have given us a registration ID.
                        account.setServerRegistrationId(
                                Long.parseLong(response.getJSON().getJSONObject("device").getString("id")));

                        // Enable the account.
                        account.setEnabled(true);

                        // We need a refresh.
                        account.setRequiresSync(true);

                        // Store the registration ID.
                        account.setLastC2DMId((String) request.getMeta("registration"));

                        // Persist it.
                        account.save(thisActivity);

                        refreshView();

                        Toast.makeText(thisActivity, String.format(
                                getString(R.string.registering_with_server_complete, account.getAccountName())),
                                Toast.LENGTH_SHORT).show();
                    } else if (operation.equals("deregister")) {
                        // We've deregistered the account.
                        account.setServerRegistrationId(null);
                        account.setEnabled(false);
                        account.setLastC2DMId(null);

                        // Persist it to the database.
                        account.save(thisActivity);

                        refreshView();

                        Toast.makeText(thisActivity, String.format(
                                getString(R.string.deregistering_with_server_complete, account.getAccountName())),
                                Toast.LENGTH_SHORT).show();
                    }
                } catch (JSONException e) {
                    // The response doesn't look like we expected.
                    Log.d(TAG, "Invalid response from server: " + e.getMessage());
                    Toast.makeText(thisActivity, getString(R.string.server_invalid_response), Toast.LENGTH_LONG)
                            .show();
                    refreshView();
                }
            }
        }
    };

    public void onCheckedChanged(CompoundButton checkbox, boolean checked) {
        Long id = (Long) checkbox.getTag();
        NewtifryAccount account = NewtifryAccount.FACTORY.get(this, id);

        this.checkedAccount(account, checked);
    }

    public void onClick(View textview) {
        Long id = (Long) textview.getTag();
        NewtifryAccount account = NewtifryAccount.FACTORY.get(this, id);

        this.clickAccountName(account);
    }

    // An array adapter to put accounts into the list view.
    private class AccountArrayAdapter extends ArrayAdapter<NewtifryAccount> {
        final private ChooseAccount parentActivity;
        private ArrayList<NewtifryAccount> accounts;

        public AccountArrayAdapter(ChooseAccount parentActivity, Context context, int textViewResourceId,
                ArrayList<NewtifryAccount> objects) {
            super(context, textViewResourceId, objects);
            this.parentActivity = parentActivity;
            this.accounts = objects;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            // Inflate a view if required.
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.account_list_row, null);
            }

            convertView.setClickable(true);
            convertView.setLongClickable(true);

            // Find the account.
            final NewtifryAccount account = this.accounts.get(position);

            // And set the values on our row.
            if (account != null) {
                TextView title = (TextView) convertView.findViewById(R.id.account_row_account_name);
                CheckBox enabled = (CheckBox) convertView.findViewById(R.id.account_row_account_enabled);
                ImageView nextView = (ImageView) convertView.findViewById(R.id.account_row_account_next);
                if (title != null) {
                    title.setText(account.getAccountName());
                    title.setTag(account.getId());
                    title.setClickable(true);
                    title.setOnClickListener(parentActivity);
                }
                if (enabled != null) {
                    enabled.setChecked(account.getEnabled());
                    enabled.setTag(account.getId());
                    enabled.setOnCheckedChangeListener(parentActivity);
                }
                if (nextView != null) {
                    if (account.getEnabled()) {
                        nextView.setImageResource(R.drawable.arrow_next);
                        nextView.setClickable(true);
                        nextView.setTag(account.getId());
                        nextView.setOnClickListener(parentActivity);
                        nextView.setVisibility(View.VISIBLE);
                    } else {
                        nextView.setVisibility(View.GONE);
                    }
                }
            }

            return convertView;
        }
    }
}