Statistics
| Branch: | Revision:

root / src / com / rackspacecloud / android / ListAccountsActivity.java @ 25881fb3

History | View | Annotate | Download (14.9 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.ListActivity;
23
import android.app.ProgressDialog;
24
import android.content.Context;
25
import android.content.DialogInterface;
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 ListActivity{
49

    
50
        private final int PASSWORD_PROMPT = 123;
51
        private final String FILENAME = "accounts.data";
52
        
53
        private boolean authenticating;
54
        private ArrayList<Account> accounts;
55
        private Intent tabViewIntent;
56
        private ProgressDialog dialog;
57
        private Context context;
58
        
59
        //need to store if the user has successfully logged in
60
        private boolean loggedIn;
61

    
62

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

    
72
        @Override
73
        protected void onSaveInstanceState(Bundle outState) {
74
                super.onSaveInstanceState(outState);
75
                outState.putBoolean("authenticating", authenticating);
76
                outState.putBoolean("loggedIn", loggedIn);
77
                
78
                //need to set authenticating back to true because it is set to false
79
                //in hideDialog()
80
                if(authenticating){
81
                        hideDialog();
82
                        authenticating = true;
83
                }
84
                writeAccounts();
85
        }
86
        
87
        @Override
88
        protected void onRestoreInstanceState(Bundle state) {
89
                if (state != null && state.containsKey("loggedIn")){
90
                        loggedIn = state.getBoolean("loggedIn");
91
                }
92
                else{
93
                        loggedIn = false;
94
                }
95
                if (state != null && state.containsKey("authenticating") && state.getBoolean("authenticating")) {
96
                        Log.d("info", "captin on restore show");
97
                    showDialog();
98
            } else {
99
                    hideDialog();
100
            }
101
                if (state != null && state.containsKey("accounts")) {
102
                    accounts = readAccounts();
103
                    if (accounts.size() == 0) {
104
                            displayNoAccountsCell();
105
                    } else {
106
                            getListView().setDividerHeight(1); // restore divider lines 
107
                            setListAdapter(new AccountAdapter());
108
                    }
109
            } else {
110
            loadAccounts();        
111
            }         
112
    }
113

    
114
        @Override
115
        protected void onStart(){
116
                super.onStart();
117
                if(authenticating){
118
                        showDialog();
119
                }
120
        }
121
        
122
        @Override
123
        protected void onStop(){
124
                super.onStop();
125
                if(authenticating){
126
                        Log.d("info", "captin onstop called");
127
                        hideDialog();
128
                        authenticating = true;
129
                }
130
        }
131
        
132

    
133
        /*
134
         * if the application is password protected,
135
         * the user must provide the password before
136
         * gaining access
137
         */
138
        private void verifyPassword(){
139
                PasswordManager pwManager = new PasswordManager(getSharedPreferences(
140
                                Preferences.SHARED_PREFERENCES_NAME, MODE_PRIVATE));
141
                if(pwManager.hasPassword() && !loggedIn){
142
                        createCustomDialog(PASSWORD_PROMPT);
143
                }
144
        }
145
        
146
        private boolean rightPassword(String password){
147
                PasswordManager pwManager = new PasswordManager(getSharedPreferences(
148
                                Preferences.SHARED_PREFERENCES_NAME, MODE_PRIVATE));
149
                return pwManager.verifyEnteredPassword(password);
150
        }
151
        
152
        
153
        /*
154
         * forces the user to enter a correct password
155
         * before they gain access to application data
156
         */
157
        private void createCustomDialog(int id) {
158
                final Dialog dialog = new Dialog(ListAccountsActivity.this);
159
                switch (id) {
160
                case PASSWORD_PROMPT:
161
                        dialog.setContentView(R.layout.passworddialog);
162
                        dialog.setTitle("Enter your password:");
163
                        dialog.setCancelable(false);
164
                        Button button = (Button) dialog.findViewById(R.id.submit_password);
165
                        button.setOnClickListener(new OnClickListener() {
166
                                public void onClick(View v){
167
                                        EditText passwordText = ((EditText)dialog.findViewById(R.id.submit_password_text));
168
                                        if(!rightPassword(passwordText.getText().toString())){
169
                                                passwordText.setText("");
170
                                                showToast("Password was incorrect.");
171
                                                loggedIn = false;
172
                                        }
173
                                        else{
174
                                                dialog.dismiss();
175
                                                loggedIn = true;
176
                                        }
177
                                }
178
                                
179
                        });
180
                        dialog.show();
181
                }
182
        }
183
        
184
        private void loadAccounts() {
185
                //check and see if there are any in memory
186
                if(accounts == null){
187
                        accounts = readAccounts();
188
                }
189
                //if nothing was written before accounts will still be null
190
                if(accounts == null){
191
                        accounts = new ArrayList<Account>();
192
                }
193

    
194
                setAccountList();
195
        }
196

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

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

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

    
253
        private void displayNoAccountsCell() {
254
            String a[] = new String[1];
255
            a[0] = "No Accounts";
256
        setListAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.noaccountscell, R.id.no_accounts_label, a));
257
        getListView().setTextFilterEnabled(true);
258
        getListView().setDividerHeight(0); // hide the dividers so it won't look like a list row
259
        getListView().setItemsCanFocus(false);
260
    }
261
        
262
        protected void onListItemClick(ListView l, View v, int position, long id) {
263
                if (accounts != null && accounts.size() > 0) {
264
                        //setActivityIndicatorsVisibility(View.VISIBLE, v);
265
                        Account.setAccount(accounts.get(position));
266
                        login();
267
                }                
268
    }
269
        
270
        public void login() {
271
        //showActivityIndicators();
272
        //setLoginPreferences();
273
        new AuthenticateTask().execute((Void[]) null);
274
    }
275
        
276
        //setup menu for when menu button is pressed
277
        public boolean onCreateOptionsMenu(Menu menu) {
278
                super.onCreateOptionsMenu(menu);
279
                MenuInflater inflater = getMenuInflater();
280
                inflater.inflate(R.menu.accounts_list_menu, menu);
281
                return true;
282
        } 
283
    
284
    @Override 
285
    //in options menu, when add account is selected go to add account activity
286
    public boolean onOptionsItemSelected(MenuItem item) {
287
            switch (item.getItemId()) {
288
            case R.id.add_account:
289
                    startActivityForResult(new Intent(this, AddAccountActivity.class), 78); // arbitrary number; never used again
290
                    return true;
291

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

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

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

    
320
        class AccountAdapter extends ArrayAdapter<Account> {
321

    
322
                AccountAdapter() {
323
                        super(ListAccountsActivity.this, R.layout.listaccountcell, accounts);
324
                }
325
                
326
                public View getView(int position, View convertView, ViewGroup parent) {
327
                        
328
                        LayoutInflater inflater = getLayoutInflater();
329
                        View row = inflater.inflate(R.layout.listaccountcell, parent, false);
330

    
331
                        TextView label = (TextView) row.findViewById(R.id.label);
332
                        label.setText(accounts.get(position).getUsername());
333
                        
334
                        TextView sublabel = (TextView) row.findViewById(R.id.sublabel);
335
                        sublabel.setText(getAccountServer(accounts.get(position)));
336
                        
337
                        ImageView icon = (ImageView) row.findViewById(R.id.account_type_icon);
338
                        icon.setImageResource(setAccountIcon(accounts.get(position)));
339
                        
340
                        return row;
341
                }
342
        }
343
        
344
        public String getAccountServer(Account account){
345
                String authServer = account.getAuthServer();
346
                String result;
347
                if(authServer.equals(Preferences.COUNTRY_UK_AUTH_SERVER)){
348
                        result = "Rackspace Cloud (UK)";
349
                }
350
                else if(authServer.equals(Preferences.COUNTRY_US_AUTH_SERVER)){
351
                        result = "Rackspace Cloud (US)";
352
                }
353
                else{
354
                        result = "Custom";
355
                        //setCustomIcon();
356
                }
357
                return result;
358
        }
359
        
360
        //display rackspace logo for cloud accounts and openstack logo for others
361
        private int setAccountIcon(Account account){
362
                if(account.getAuthServer().equals(Preferences.COUNTRY_UK_AUTH_SERVER) 
363
                                || account.getAuthServer().equals(Preferences.COUNTRY_US_AUTH_SERVER)){
364
                        return R.drawable.rackspacecloud_icon;
365
                }
366
                else{
367
                        return R.drawable.openstack_icon;
368
                }
369
        }
370

    
371
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
372
                super.onActivityResult(requestCode, resultCode, data);
373
                
374
                if(requestCode == 187){
375
                        hideDialog(); 
376
                }
377
                
378
                if (resultCode == RESULT_OK && requestCode == 78) {          
379
                        Account acc = new Account();
380
                        Bundle b = data.getBundleExtra("accountInfo");
381
                        acc.setApiKey(b.getString("apiKey"));
382
                        acc.setUsername(b.getString("username"));
383
                        acc.setAuthServer(b.getString("server"));
384
                        accounts.add(acc);
385
                        writeAccounts();
386
                        loadAccounts();
387
                }
388
        }        
389
/*
390
        private void setActivityIndicatorsVisibility(int visibility) {
391
                //FINISH THIS TO LET USER KNOW PROGRAM IS STILL WORKING
392
                
393
        //ProgressBar pb = new ProgressBar();
394
            //TextView tv = (TextView) findViewById(R.id.login_authenticating_label);
395
        //pb.setVisibility(visibility);
396
        //tv.setVisibility(visibility);
397
    }
398
        
399
        private void setActivityIndicatorsVisibility(int visibility, View v) {
400
                //FINISH THIS TO LET USER KNOW PROGRAM IS STILL WORKING
401
                
402
        //ProgressBar pb = new ProgressBar();
403
            //TextView tv = (TextView) findViewById(R.id.login_authenticating_label);
404
        //pb.setVisibility(visibility);
405
        //tv.setVisibility(visibility);
406
    }
407
*/
408
        
409
        private void showDialog() {
410
                authenticating = true;
411
                if(dialog == null || !dialog.isShowing()){
412
                        dialog = ProgressDialog.show(ListAccountsActivity.this, "", "Authenticating...", true);
413
                }
414
    }
415
    
416
    private void hideDialog() {
417
            if(dialog != null){
418
                    dialog.dismiss();
419
            }
420
            authenticating = false;
421
    }
422
       
423
        private class AuthenticateTask extends AsyncTask<Void, Void, Boolean> {
424
            
425
                @Override
426
                protected void onPreExecute(){
427
                        showDialog();
428
                }
429
                
430
                @Override
431
                protected Boolean doInBackground(Void... arg0) {
432
                        return new Boolean(Authentication.authenticate(context));
433
                        //return true;
434
                }
435
            
436
                @Override
437
                protected void onPostExecute(Boolean result) {
438
                        if (result.booleanValue()) {
439
                                //startActivity(tabViewIntent);
440
                        new LoadImagesTask().execute((Void[]) null);
441
                        } else {
442
                                hideDialog();
443
                                showAlert("Login Failure", "Authentication failed.  Please check your User Name and API Key.");
444
                        }
445
                }
446
    }
447

    
448
    private class LoadFlavorsTask extends AsyncTask<Void, Void, ArrayList<Flavor>> {
449
            
450
                @Override
451
                protected ArrayList<Flavor> doInBackground(Void... arg0) {
452
                        return (new FlavorManager()).createList(true, context);
453
                }
454
            
455
                @Override
456
                protected void onPostExecute(ArrayList<Flavor> result) {
457
                        if (result != null && result.size() > 0) {
458
                                TreeMap<String, Flavor> flavorMap = new TreeMap<String, Flavor>();
459
                                for (int i = 0; i < result.size(); i++) {
460
                                        Flavor flavor = result.get(i);
461
                                        flavorMap.put(flavor.getId(), flavor);
462
                                }
463
                                Flavor.setFlavors(flavorMap);
464
                                hideDialog();
465
                                startActivityForResult(tabViewIntent, 187);
466
                        } else {
467
                                hideDialog();
468
                                showAlert("Login Failure", "There was a problem loading server flavors.  Please try again.");
469
                        }
470
                }
471
    }
472

    
473
    private class LoadImagesTask extends AsyncTask<Void, Void, ArrayList<Image>> {
474
            
475
                @Override
476
                protected ArrayList<Image> doInBackground(Void... arg0) {
477
                        return (new ImageManager()).createList(true, context);
478
                }
479
            
480
                @Override
481
                protected void onPostExecute(ArrayList<Image> result) {
482
                        if (result != null && result.size() > 0) {
483
                                TreeMap<String, Image> imageMap = new TreeMap<String, Image>();
484
                                for (int i = 0; i < result.size(); i++) {
485
                                        Image image = result.get(i);
486
                                        imageMap.put(image.getId(), image);
487
                                }
488
                                Image.setImages(imageMap);
489
                                new LoadFlavorsTask().execute((Void[]) null);
490
                                //startActivity(tabViewIntent);
491
                        } else {
492
                                hideDialog();
493
                                showAlert("Login Failure", "There was a problem loading server images.  Please try again.");
494
                        }
495
                }
496
    }
497
    
498
    private void showAlert(String title, String message) {
499
                AlertDialog alert = new AlertDialog.Builder(this).create();
500
                alert.setTitle(title);
501
                alert.setMessage(message);
502
                alert.setButton("OK", new DialogInterface.OnClickListener() {
503
              public void onClick(DialogInterface dialog, int which) {
504
                return;
505
            } }); 
506
                alert.show();
507
    }
508
    
509
    private void showToast(String message) {
510
                Context context = getApplicationContext();
511
                int duration = Toast.LENGTH_SHORT;
512
                Toast toast = Toast.makeText(context, message, duration);
513
                toast.show();
514
    }
515
    
516
    
517
        
518
                
519
}