Statistics
| Branch: | Revision:

root / src / com / rackspacecloud / android / ListAccountsActivity.java @ 008fa428

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.Intent;
26
import android.os.AsyncTask;
27
import android.os.Bundle;
28
import android.util.Log;
29
import android.view.ContextMenu;
30
import android.view.ContextMenu.ContextMenuInfo;
31
import android.view.LayoutInflater;
32
import android.view.Menu;
33
import android.view.MenuInflater;
34
import android.view.MenuItem;
35
import android.view.View;
36
import android.view.View.OnClickListener;
37
import android.view.ViewGroup;
38
import android.widget.AdapterView.AdapterContextMenuInfo;
39
import android.widget.ArrayAdapter;
40
import android.widget.Button;
41
import android.widget.EditText;
42
import android.widget.ImageView;
43
import android.widget.ListView;
44
import android.widget.TextView;
45
import android.widget.Toast;
46

    
47
public class ListAccountsActivity extends GaListActivity{
48

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

    
53
        private boolean authenticating;
54
        private ArrayList<Account> accounts;
55
        private Intent tabViewIntent;
56
        private ProgressDialog dialog;
57
        private Context context;
58
        //need to store if the user has successfully logged in
59
        private boolean loggedIn;
60

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

    
71
        @Override
72
        protected void onSaveInstanceState(Bundle outState) {
73
                super.onSaveInstanceState(outState);
74
                outState.putBoolean("authenticating", authenticating);
75
                outState.putBoolean("loggedIn", loggedIn);
76

    
77
                //need to set authenticating back to true because it is set to false
78
                //in hideDialog()
79
                if(authenticating){
80
                        hideDialog();
81
                        authenticating = true;
82
                }
83
                writeAccounts();
84
        }
85

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

    
113
        @Override
114
        protected void onStart(){
115
                super.onStart();
116
                if(authenticating){
117
                        showDialog();
118
                }
119
        }
120

    
121
        @Override
122
        protected void onStop(){
123
                super.onStop();
124
                if(authenticating){
125
                        Log.d("info", "captin onstop called");
126
                        hideDialog();
127
                        authenticating = true;
128
                }
129
        }
130

    
131

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

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

    
151

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

    
178
                        });
179
                        dialog.show();
180
                }
181
        }
182

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

    
193
                setAccountList();
194
        }
195

    
196
        private void setAccountList() {
197

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

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

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

    
250
        }
251

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

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

    
269
        public void login() {
270
                //showActivityIndicators();
271
                //setLoginPreferences();
272
                new AuthenticateTask().execute((Void[]) null);
273
        }
274

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

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

    
291
                case R.id.contact_rackspace:
292
                        startActivity(new Intent(this, ContactActivity.class));
293
                        return true;
294

    
295
                case R.id.add_password:
296
                        startActivity(new Intent(this, CreatePasswordActivity.class));
297
                        return true;
298
                }        
299
                return false;
300
        } 
301

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

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

    
324
        class AccountAdapter extends ArrayAdapter<Account> {
325

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

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

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

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

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

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

    
344
                        return row;
345
                }
346
        }
347

    
348
        public String getAccountServer(Account account){
349
                String authServer = account.getAuthServer();
350
                String result;
351
                if(authServer.equals(Preferences.COUNTRY_UK_AUTH_SERVER)){
352
                        result = "Rackspace Cloud (UK)";
353
                }
354
                else if(authServer.equals(Preferences.COUNTRY_US_AUTH_SERVER)){
355
                        result = "Rackspace Cloud (US)";
356
                }
357
                else if(authServer.equals(Preferences.PITHOS_SERVER)){
358
                        result = "Pithos+";
359
                }
360
                else if(authServer.equals(Preferences.PITHOS_DEV_SERVER)){
361
                        result = "Pithos+ Dev";
362
                }
363
                else{
364
                        result = "Custom:" +authServer;
365
                        //setCustomIcon();
366
                }
367
                return result;
368
        }
369

    
370
        //display rackspace logo for cloud accounts and openstack logo for others
371
        private int setAccountIcon(Account account){
372
                if(account.getAuthServer().equals(Preferences.COUNTRY_UK_AUTH_SERVER) 
373
                                || account.getAuthServer().equals(Preferences.COUNTRY_US_AUTH_SERVER)){
374
                        return R.drawable.rackspacecloud_icon;
375
                }
376
                if(account.getAuthServer().equals(Preferences.PITHOS_DEV_SERVER) 
377
                                || account.getAuthServer().equals(Preferences.PITHOS_SERVER)){
378
                        return R.drawable.pithos_icon;
379
                }
380
                else{
381
                        return R.drawable.openstack_icon;
382
                }
383
        }
384

    
385
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
386
                super.onActivityResult(requestCode, resultCode, data);
387

    
388
                if(requestCode == 187){
389
                        hideDialog(); 
390
                }
391

    
392
                if (resultCode == RESULT_OK && requestCode == 78) {          
393
                        Account acc = new Account();
394
                        Bundle b = data.getBundleExtra("accountInfo");
395
                        acc.setApiKey(b.getString("apiKey"));
396
                        acc.setUsername(b.getString("username"));
397
                        acc.setAuthServer(b.getString("server"));
398
                        accounts.add(acc);
399
                        writeAccounts();
400
                        loadAccounts();
401
                }
402
        }        
403
        /*
404
        private void setActivityIndicatorsVisibility(int visibility) {
405
                //FINISH THIS TO LET USER KNOW PROGRAM IS STILL WORKING
406

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

413
        private void setActivityIndicatorsVisibility(int visibility, View v) {
414
                //FINISH THIS TO LET USER KNOW PROGRAM IS STILL WORKING
415

416
        //ProgressBar pb = new ProgressBar();
417
            //TextView tv = (TextView) findViewById(R.id.login_authenticating_label);
418
        //pb.setVisibility(visibility);
419
        //tv.setVisibility(visibility);
420
    }
421
         */
422

    
423
        private void showDialog() {
424
                authenticating = true;
425
                if(dialog == null || !dialog.isShowing()){
426
                        dialog = ProgressDialog.show(ListAccountsActivity.this, "", "Authenticating...", true);
427
                }
428
    }
429
    
430
    private void hideDialog() {
431
            if(dialog != null){
432
                    dialog.dismiss();
433
            }
434
            authenticating = false;
435
    }
436

    
437
        private class AuthenticateTask extends AsyncTask<Void, Void, Boolean> {
438

    
439
                @Override
440
                protected void onPreExecute(){
441
                        showDialog();
442
                }
443

    
444
                @Override
445
                protected Boolean doInBackground(Void... arg0) {
446
                        return new Boolean(Authentication.authenticate(context));
447
                        //return true;
448
                }
449

    
450
                @Override
451
                protected void onPostExecute(Boolean result) {
452
                        if (result.booleanValue()) {
453
                                //startActivity(tabViewIntent);
454
                                new LoadImagesTask().execute((Void[]) null);
455
                        } else {
456
                                hideDialog();
457
                                showAlert("Login Failure", "Authentication failed.  Please check your User Name and API Key.");
458
                        }
459
                }
460
        }
461

    
462
        private class LoadFlavorsTask extends AsyncTask<Void, Void, ArrayList<Flavor>> {
463

    
464
                @Override
465
                protected ArrayList<Flavor> doInBackground(Void... arg0) {
466
                        return (new FlavorManager()).createList(true, context);
467
                }
468

    
469
                @Override
470
                protected void onPostExecute(ArrayList<Flavor> result) {
471
                        if (result != null && result.size() > 0) {
472
                                TreeMap<String, Flavor> flavorMap = new TreeMap<String, Flavor>();
473
                                for (int i = 0; i < result.size(); i++) {
474
                                        Flavor flavor = result.get(i);
475
                                        flavorMap.put(flavor.getId(), flavor);
476
                                }
477
                                Flavor.setFlavors(flavorMap);
478
                                hideDialog();
479
                                startActivityForResult(tabViewIntent, 187);
480
                        } else {
481
                                /*
482
                                hideDialog();
483
                                showAlert("Login Failure", "There was a problem loading server flavors.  Please try again.");
484
                                */
485
                                TreeMap<String, Flavor> flavorMap = new TreeMap<String, Flavor>();
486
                                
487
                                Flavor.setFlavors(flavorMap);
488
                                hideDialog();
489
                                startActivityForResult(tabViewIntent, 187);
490
                        }
491
                }
492
        }
493

    
494
        private class LoadImagesTask extends AsyncTask<Void, Void, ArrayList<Image>> {
495

    
496
                @Override
497
                protected ArrayList<Image> doInBackground(Void... arg0) {
498
                        return (new ImageManager()).createList(true, context);
499
                }
500

    
501
                @Override
502
                protected void onPostExecute(ArrayList<Image> result) {
503
                        Log.i("IMG SIZE", result+" "+result.size());
504
                        if (result != null && result.size() > 0) {
505
                                TreeMap<String, Image> imageMap = new TreeMap<String, Image>();
506
                                for (int i = 0; i < result.size(); i++) {
507
                                        Image image = result.get(i);
508
                                        imageMap.put(image.getId(), image);
509
                                }
510
                                Image.setImages(imageMap);
511
                                new LoadFlavorsTask().execute((Void[]) null);
512
                                //startActivity(tabViewIntent);
513
                        } else {
514
                                TreeMap<String, Image> imageMap = new TreeMap<String, Image>();
515
                                                                
516
                                Image.setImages(imageMap);
517
                                new LoadFlavorsTask().execute((Void[]) null);
518
                                //hideDialog();
519
                                //showAlert("Login Failure", "There was a problem loading server images.  Please try again.");
520
                        }
521
                }
522
        }
523

    
524
        private void showAlert(String title, String message) {
525
                AlertDialog alert = new AlertDialog.Builder(this).create();
526
                alert.setTitle(title);
527
                alert.setMessage(message);
528
                alert.setButton("OK", new DialogInterface.OnClickListener() {
529
                        public void onClick(DialogInterface dialog, int which) {
530
                                return;
531
                        } }); 
532
                alert.show();
533
        }
534

    
535
        private void showToast(String message) {
536
                Context context = getApplicationContext();
537
                int duration = Toast.LENGTH_SHORT;
538
                Toast toast = Toast.makeText(context, message, duration);
539
                toast.show();
540
        }
541

    
542

    
543

    
544

    
545
}