Java tutorial
/** * 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; } } }