Statistics
| Branch: | Revision:

root / src / com / rackspacecloud / android / ListAccountsActivity.java @ 3d654446

History | View | Annotate | Download (15.4 kB)

1
package com.rackspacecloud.android;
2

    
3
import java.io.FileInputStream;
4
import java.io.FileNotFoundException;
5
import java.io.FileOutputStream;
6
import java.io.IOException;
7
import java.io.ObjectInputStream;
8
import java.io.ObjectOutputStream;
9
import java.io.StreamCorruptedException;
10
import java.util.ArrayList;
11
import java.util.TreeMap;
12

    
13
import com.rackspace.cloud.servers.api.client.Account;
14
import com.rackspace.cloud.servers.api.client.Flavor;
15
import com.rackspace.cloud.servers.api.client.FlavorManager;
16
import com.rackspace.cloud.servers.api.client.Image;
17
import com.rackspace.cloud.servers.api.client.ImageManager;
18
import com.rackspace.cloud.servers.api.client.http.Authentication;
19

    
20
import android.app.AlertDialog;
21
import android.app.Dialog;
22
import android.app.ProgressDialog;
23
import android.content.Context;
24
import android.content.DialogInterface;
25
import android.content.DialogInterface.OnCancelListener;
26
import android.content.Intent;
27
import android.os.AsyncTask;
28
import android.os.Bundle;
29
import android.util.Log;
30
import android.view.ContextMenu;
31
import android.view.ContextMenu.ContextMenuInfo;
32
import android.view.LayoutInflater;
33
import android.view.Menu;
34
import android.view.MenuInflater;
35
import android.view.MenuItem;
36
import android.view.View;
37
import android.view.View.OnClickListener;
38
import android.view.ViewGroup;
39
import android.widget.AdapterView.AdapterContextMenuInfo;
40
import android.widget.ArrayAdapter;
41
import android.widget.Button;
42
import android.widget.EditText;
43
import android.widget.ImageView;
44
import android.widget.ListView;
45
import android.widget.TextView;
46
import android.widget.Toast;
47

    
48
public class ListAccountsActivity extends GaListActivity{
49

    
50
        private final int PASSWORD_PROMPT = 123;
51
        private final String FILENAME = "accounts.data";
52
        private static final String PAGE_ROOT = "/Root";
53

    
54
        private boolean authenticating;
55
        private ArrayList<Account> accounts;
56
        private Intent tabViewIntent;
57
        private ProgressDialog dialog;
58
        private Context context;
59
        //need to store if the user has successfully logged in
60
        private boolean loggedIn;
61
        private AuthenticateTask authTask;
62
        private LoadImagesTask imageTask;
63
        private LoadFlavorsTask flavorTask;
64

    
65
        public void onCreate(Bundle savedInstanceState) {
66
                super.onCreate(savedInstanceState);
67
                trackPageView(PAGE_ROOT);
68
                onRestoreInstanceState(savedInstanceState);
69
                registerForContextMenu(getListView());
70
                context = getApplicationContext();
71
                tabViewIntent = new Intent(this, TabViewActivity.class);
72
                verifyPassword();
73
        }
74

    
75
        @Override
76
        protected void onSaveInstanceState(Bundle outState) {
77
                super.onSaveInstanceState(outState);
78
                outState.putBoolean("authenticating", authenticating);
79
                outState.putBoolean("loggedIn", loggedIn);
80

    
81
                //need to set authenticating back to true because it is set to false
82
                //in hideDialog()
83
                if(authenticating){
84
                        hideDialog();
85
                        authenticating = true;
86
                }
87
                writeAccounts();
88
        }
89

    
90
        @Override
91
        protected void onRestoreInstanceState(Bundle state) {                
92
                if (state != null && state.containsKey("loggedIn")){
93
                        loggedIn = state.getBoolean("loggedIn");
94
                }
95
                else{
96
                        loggedIn = false;
97
                }
98
                if (state != null && state.containsKey("authenticating") && state.getBoolean("authenticating")) {
99
                        Log.d("info", "captin on restore show");
100
                        showDialog();
101
                } else {
102
                        hideDialog();
103
                }
104
                if (state != null && state.containsKey("accounts")) {
105
                        accounts = readAccounts();
106
                        if (accounts.size() == 0) {
107
                                displayNoAccountsCell();
108
                        } else {
109
                                getListView().setDividerHeight(1); // restore divider lines 
110
                                setListAdapter(new AccountAdapter());
111
                        }
112
                } else {
113
                        loadAccounts();        
114
                }         
115
        }
116

    
117
        @Override
118
        protected void onStart(){
119
                super.onStart();
120
                if(authenticating){
121
                        showDialog();
122
                }
123
        }
124

    
125
        @Override
126
        protected void onStop(){
127
                super.onStop();
128
                if(authenticating){
129
                        Log.d("info", "captin onstop called");
130
                        hideDialog();
131
                        authenticating = true;
132
                }
133
        }
134

    
135
        /*
136
         * if the application is password protected,
137
         * the user must provide the password before
138
         * gaining access
139
         */
140
        private void verifyPassword(){
141
                PasswordManager pwManager = new PasswordManager(getSharedPreferences(
142
                                Preferences.SHARED_PREFERENCES_NAME, MODE_PRIVATE));
143
                if(pwManager.hasPassword() && !loggedIn){
144
                        createCustomDialog(PASSWORD_PROMPT);
145
                }
146
        }
147

    
148
        private boolean rightPassword(String password){
149
                PasswordManager pwManager = new PasswordManager(getSharedPreferences(
150
                                Preferences.SHARED_PREFERENCES_NAME, MODE_PRIVATE));
151
                return pwManager.verifyEnteredPassword(password);
152
        }
153

    
154

    
155
        /*
156
         * forces the user to enter a correct password
157
         * before they gain access to application data
158
         */
159
        private void createCustomDialog(int id) {
160
                final Dialog dialog = new Dialog(ListAccountsActivity.this);
161
                switch (id) {
162
                case PASSWORD_PROMPT:
163
                        dialog.setContentView(R.layout.passworddialog);
164
                        dialog.setTitle("Enter your password:");
165
                        dialog.setCancelable(false);
166
                        Button button = (Button) dialog.findViewById(R.id.submit_password);
167
                        button.setOnClickListener(new OnClickListener() {
168
                                public void onClick(View v){
169
                                        EditText passwordText = ((EditText)dialog.findViewById(R.id.submit_password_text));
170
                                        if(!rightPassword(passwordText.getText().toString())){
171
                                                passwordText.setText("");
172
                                                showToast("Password was incorrect.");
173
                                                loggedIn = false;
174
                                        }
175
                                        else{
176
                                                dialog.dismiss();
177
                                                loggedIn = true;
178
                                        }
179
                                }
180

    
181
                        });
182
                        dialog.show();
183
                }
184
        }
185

    
186
        private void loadAccounts() {
187
                //check and see if there are any in memory
188
                if(accounts == null){
189
                        accounts = readAccounts();
190
                }
191
                //if nothing was written before accounts will still be null
192
                if(accounts == null){
193
                        accounts = new ArrayList<Account>();
194
                }
195

    
196
                setAccountList();
197
        }
198

    
199
        private void setAccountList() {
200

    
201
                if (accounts.size() == 0) {
202
                        displayNoAccountsCell();
203
                } else {
204
                        getListView().setDividerHeight(1); // restore divider lines 
205
                        this.setListAdapter(new AccountAdapter());
206
                }
207
        }
208

    
209
        private void writeAccounts(){
210
                FileOutputStream fos;
211
                ObjectOutputStream out = null;
212
                try{
213
                        fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
214
                        out = new ObjectOutputStream(fos);
215
                        out.writeObject(accounts);
216
                        out.flush();
217
                        out.close();
218
                } catch (FileNotFoundException e) {
219
                        showAlert("Error", "Could not save accounts.");
220
                        e.printStackTrace();
221
                } catch (IOException e) {
222
                        showAlert("Error", "Could not save accounts.");
223
                        e.printStackTrace();
224
                }
225
        }
226

    
227
        private ArrayList<Account> readAccounts(){
228
                FileInputStream fis;
229
                ObjectInputStream in;
230
                try {
231
                        fis = openFileInput(FILENAME);
232
                        in = new ObjectInputStream(fis);
233
                        @SuppressWarnings("unchecked")
234
                        ArrayList<Account> file = (ArrayList<Account>)in.readObject();
235
                        in.close();
236
                        return file;
237
                } catch (FileNotFoundException e) {
238
                        //showAlert("Error", "Could not load accounts.");
239
                        e.printStackTrace();
240
                        return null;
241
                } catch (StreamCorruptedException e) {
242
                        showAlert("Error", "Could not load accounts.");
243
                        e.printStackTrace();
244
                } catch (IOException e) {
245
                        showAlert("Error", "Could not load accounts.");
246
                        e.printStackTrace();
247
                } catch (ClassNotFoundException e) {
248
                        showAlert("Error", "Could not load accounts.");
249
                        e.printStackTrace();
250
                }
251
                return null;
252

    
253
        }
254

    
255
        private void displayNoAccountsCell() {
256
                String a[] = new String[1];
257
                a[0] = "No Accounts";
258
                setListAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.noaccountscell, R.id.no_accounts_label, a));
259
                getListView().setTextFilterEnabled(true);
260
                getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
261
                getListView().setItemsCanFocus(false);
262
        }
263

    
264
        protected void onListItemClick(ListView l, View v, int position, long id) {
265
                if (accounts != null && accounts.size() > 0) {
266
                        //setActivityIndicatorsVisibility(View.VISIBLE, v);
267
                        Account.setAccount(accounts.get(position));
268
                        login();
269
                }                
270
        }
271

    
272
        public void login() {
273
                //showActivityIndicators();
274
                //setLoginPreferences();
275
                authTask = new AuthenticateTask();
276
                authTask.execute((Void[]) null);
277
        }
278

    
279
        //setup menu for when menu button is pressed
280
        public boolean onCreateOptionsMenu(Menu menu) {
281
                super.onCreateOptionsMenu(menu);
282
                MenuInflater inflater = getMenuInflater();
283
                inflater.inflate(R.menu.accounts_list_menu, menu);
284
                return true;
285
        } 
286

    
287
        @Override 
288
        //in options menu, when add account is selected go to add account activity
289
        public boolean onOptionsItemSelected(MenuItem item) {
290
                switch (item.getItemId()) {
291
                case R.id.add_account:
292
                        startActivityForResult(new Intent(this, AddAccountActivity.class), 78); // arbitrary number; never used again
293
                        return true;
294

    
295
                case R.id.contact_rackspace:
296
                        startActivity(new Intent(this, ContactActivity.class));
297
                        return true;
298

    
299
                case R.id.add_password:
300
                        startActivity(new Intent(this, CreatePasswordActivity.class));
301
                        return true;
302
                }        
303
                return false;
304
        } 
305

    
306
        //the context menu for a long press on an account
307
        public void onCreateContextMenu(ContextMenu menu, View v,
308
                        ContextMenuInfo menuInfo) {
309
                super.onCreateContextMenu(menu, v, menuInfo);
310
                MenuInflater inflater = getMenuInflater();
311
                inflater.inflate(R.menu.account_context_menu, menu);
312
        }
313

    
314
        //removes the selected account from account list if remove is clicked
315
        public boolean onContextItemSelected(MenuItem item) {
316
                AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
317
                accounts.remove(info.position);
318
                writeAccounts();
319
                loadAccounts();
320
                return true;
321
        }
322

    
323
        class AccountAdapter extends ArrayAdapter<Account> {
324

    
325
                AccountAdapter() {
326
                        super(ListAccountsActivity.this, R.layout.listaccountcell, accounts);
327
                }
328

    
329
                public View getView(int position, View convertView, ViewGroup parent) {
330

    
331
                        LayoutInflater inflater = getLayoutInflater();
332
                        View row = inflater.inflate(R.layout.listaccountcell, parent, false);
333

    
334
                        TextView label = (TextView) row.findViewById(R.id.label);
335
                        label.setText(accounts.get(position).getUsername());
336

    
337
                        TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
338
                        sublabel.setText(getAccountServer(accounts.get(position)));
339

    
340
                        ImageView icon = (ImageView) row.findViewById(R.id.account_type_icon);
341
                        icon.setImageResource(setAccountIcon(accounts.get(position)));
342

    
343
                        return row;
344
                }
345
        }
346

    
347
        public String getAccountServer(Account account){
348
                String authServer = account.getAuthServer();
349
                String result;
350
                if(authServer.equals(Preferences.COUNTRY_UK_AUTH_SERVER)){
351
                        result = "Rackspace Cloud (UK)";
352
                }
353
                else if(authServer.equals(Preferences.COUNTRY_US_AUTH_SERVER)){
354
                        result = "Rackspace Cloud (US)";
355
                }
356
                else{
357
                        result = "Custom";
358
                        //setCustomIcon();
359
                }
360
                return result;
361
        }
362

    
363
        //display rackspace logo for cloud accounts and openstack logo for others
364
        private int setAccountIcon(Account account){
365
                if(account.getAuthServer().equals(Preferences.COUNTRY_UK_AUTH_SERVER) 
366
                                || account.getAuthServer().equals(Preferences.COUNTRY_US_AUTH_SERVER)){
367
                        return R.drawable.rackspacecloud_icon;
368
                }
369
                else{
370
                        return R.drawable.openstack_icon;
371
                }
372
        }
373

    
374
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
375
                super.onActivityResult(requestCode, resultCode, data);
376

    
377
                if(requestCode == 187){
378
                        hideDialog(); 
379
                }
380

    
381
                if (resultCode == RESULT_OK && requestCode == 78) {          
382
                        Account acc = new Account();
383
                        Bundle b = data.getBundleExtra("accountInfo");
384
                        acc.setApiKey(b.getString("apiKey"));
385
                        acc.setUsername(b.getString("username"));
386
                        acc.setAuthServer(b.getString("server"));
387
                        accounts.add(acc);
388
                        writeAccounts();
389
                        loadAccounts();
390
                }
391
        }        
392
        /*
393
        private void setActivityIndicatorsVisibility(int visibility) {
394
                //FINISH THIS TO LET USER KNOW PROGRAM IS STILL WORKING
395

396
        //ProgressBar pb = new ProgressBar();
397
            //TextView tv = (TextView) findViewById(R.id.login_authenticating_label);
398
        //pb.setVisibility(visibility);
399
        //tv.setVisibility(visibility);
400
    }
401

402
        private void setActivityIndicatorsVisibility(int visibility, View v) {
403
                //FINISH THIS TO LET USER KNOW PROGRAM IS STILL WORKING
404

405
        //ProgressBar pb = new ProgressBar();
406
            //TextView tv = (TextView) findViewById(R.id.login_authenticating_label);
407
        //pb.setVisibility(visibility);
408
        //tv.setVisibility(visibility);
409
    }
410
         */
411

    
412
        private void showDialog() {
413
                authenticating = true;
414
                if(dialog == null || !dialog.isShowing()){
415
                        dialog = ProgressDialog.show(ListAccountsActivity.this, "", "Authenticating...", true);
416
                        dialog.setCancelable(true);
417
                        dialog.setOnCancelListener(new OnCancelListener() {
418
                                
419
                                @Override
420
                                public void onCancel(DialogInterface dialog) {
421
                                        if(authTask != null){ 
422
                                                authTask.cancel(true);
423
                                        }
424
                                        if(imageTask != null){
425
                                                imageTask.cancel(true);
426
                                        }
427
                                        if(flavorTask != null){
428
                                                flavorTask.cancel(true);
429
                                        }
430
                                        hideDialog();
431
                                }
432
                        });
433
                }
434
    }
435
    
436
    private void hideDialog() {
437
            if(dialog != null){
438
                    dialog.dismiss();
439
            }
440
            authenticating = false;
441
    }
442

    
443
        private class AuthenticateTask extends AsyncTask<Void, Void, Boolean> {
444

    
445
                @Override
446
                protected void onPreExecute(){
447
                        showDialog();
448
                }
449

    
450
                @Override
451
                protected Boolean doInBackground(Void... arg0) {
452
                        if(isCancelled()){
453
                                return false;
454
                        }
455
                        return new Boolean(Authentication.authenticate(context));
456
                        //return true;
457
                }
458

    
459
                @Override
460
                protected void onPostExecute(Boolean result) {
461
                        if (result.booleanValue()) {
462
                                //startActivity(tabViewIntent);
463
                                imageTask = new LoadImagesTask();
464
                                imageTask.execute((Void[]) null);
465
                        } else {
466
                                hideDialog();
467
                                showAlert("Login Failure", "Authentication failed.  Please check your User Name and API Key.");
468
                        }
469
                }
470
        }
471

    
472
        private class LoadFlavorsTask extends AsyncTask<Void, Void, ArrayList<Flavor>> {
473

    
474
                @Override
475
                protected ArrayList<Flavor> doInBackground(Void... arg0) {
476
                        return (new FlavorManager()).createList(true, context);
477
                }
478

    
479
                @Override
480
                protected void onPostExecute(ArrayList<Flavor> result) {
481
                        if(isCancelled()){
482
                                return;
483
                        }
484
                        
485
                        if (result != null && result.size() > 0) {
486
                                TreeMap<String, Flavor> flavorMap = new TreeMap<String, Flavor>();
487
                                for (int i = 0; i < result.size(); i++) {
488
                                        Flavor flavor = result.get(i);
489
                                        flavorMap.put(flavor.getId(), flavor);
490
                                }
491
                                Flavor.setFlavors(flavorMap);
492
                                if(isCancelled()){
493
                                        return;
494
                                }
495
                                hideDialog();
496
                                startActivityForResult(tabViewIntent, 187);
497
                        } else {
498
                                hideDialog();
499
                                showAlert("Login Failure", "There was a problem loading server flavors.  Please try again.");
500
                        }
501
                }
502
        }
503

    
504
        private class LoadImagesTask extends AsyncTask<Void, Void, ArrayList<Image>> {
505

    
506
                @Override
507
                protected ArrayList<Image> doInBackground(Void... arg0) {
508
                        return (new ImageManager()).createList(true, context);
509
                }
510

    
511
                @Override
512
                protected void onPostExecute(ArrayList<Image> result) {
513
                        if(isCancelled()){
514
                                return;
515
                        }
516
                        
517
                        if (result != null && result.size() > 0) {
518
                                TreeMap<String, Image> imageMap = new TreeMap<String, Image>();
519
                                for (int i = 0; i < result.size(); i++) {
520
                                        Image image = result.get(i);
521
                                        imageMap.put(image.getId(), image);
522
                                }
523
                                Image.setImages(imageMap);
524
                                
525
                                if(isCancelled()){
526
                                        return;
527
                                }
528
                                
529
                                flavorTask = new LoadFlavorsTask();
530
                                flavorTask.execute((Void[]) null);
531
                        } else {
532
                                hideDialog();
533
                                showAlert("Login Failure", "There was a problem loading server images.  Please try again.");
534
                        }
535
                }
536
        }
537

    
538
        private void showAlert(String title, String message) {
539
                AlertDialog alert = new AlertDialog.Builder(this).create();
540
                alert.setTitle(title);
541
                alert.setMessage(message);
542
                alert.setButton("OK", new DialogInterface.OnClickListener() {
543
                        public void onClick(DialogInterface dialog, int which) {
544
                                return;
545
                        } }); 
546
                alert.show();
547
        }
548

    
549
        private void showToast(String message) {
550
                Context context = getApplicationContext();
551
                int duration = Toast.LENGTH_SHORT;
552
                Toast toast = Toast.makeText(context, message, duration);
553
                toast.show();
554
        }
555

    
556

    
557

    
558

    
559
}