Statistics
| Branch: | Revision:

root / src / com / rackspacecloud / android / ListAccountsActivity.java @ a7d1fdc2

History | View | Annotate | Download (14.6 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.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 ListActivity{
48

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

    
61

    
62
        public void onCreate(Bundle savedInstanceState) {
63
        super.onCreate(savedInstanceState);
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
                    showDialog();
96
            } else {
97
                    hideDialog();
98
            }
99
                if (state != null && state.containsKey("accounts")) {
100
                    accounts = readAccounts();
101
                    if (accounts.size() == 0) {
102
                            displayNoAccountsCell();
103
                    } else {
104
                            getListView().setDividerHeight(1); // restore divider lines 
105
                            setListAdapter(new AccountAdapter());
106
                    }
107
            } else {
108
            loadAccounts();        
109
            }         
110
    }
111
        
112
        @Override
113
        protected void onStart(){
114
                super.onStart();
115
                if(authenticating){
116
                        showDialog();
117
                }
118
        }
119
        
120
        @Override
121
        protected void onStop(){
122
                super.onStop();
123
                if(authenticating){
124
                        hideDialog();
125
                        authenticating = true;
126
                }
127
        }
128

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

    
190
                setAccountList();
191
        }
192

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

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

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

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

    
287
            case R.id.contact_rackspace:
288
                    startActivity(new Intent(this, ContactActivity.class));
289
                    return true;
290
                    
291
            case R.id.add_password:
292
                    startActivity(new Intent(this, CreatePasswordActivity.class));
293
                    return true;
294
            }        
295
            return false;
296
    } 
297

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

    
306
        //removes the selected account from account list if remove is clicked
307
        public boolean onContextItemSelected(MenuItem item) {
308
                AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
309
                accounts.remove(info.position);
310
                writeAccounts();
311
                loadAccounts();
312
                return true;
313
        }
314

    
315
        class AccountAdapter extends ArrayAdapter<Account> {
316

    
317
                AccountAdapter() {
318
                        super(ListAccountsActivity.this, R.layout.listaccountcell, accounts);
319
                }
320
                
321
                public View getView(int position, View convertView, ViewGroup parent) {
322
                        
323
                        LayoutInflater inflater = getLayoutInflater();
324
                        View row = inflater.inflate(R.layout.listaccountcell, parent, false);
325

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

    
366
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
367
                super.onActivityResult(requestCode, resultCode, data);
368
                
369
                if (resultCode == RESULT_OK && requestCode == 78) {          
370
                        Account acc = new Account();
371
                        Bundle b = data.getBundleExtra("accountInfo");
372
                        acc.setApiKey(b.getString("apiKey"));
373
                        acc.setUsername(b.getString("username"));
374
                        acc.setAuthServer(b.getString("server"));
375
                        accounts.add(acc);
376
                        writeAccounts();
377
                        loadAccounts();
378
                }
379
        }        
380
/*
381
        private void setActivityIndicatorsVisibility(int visibility) {
382
                //FINISH THIS TO LET USER KNOW PROGRAM IS STILL WORKING
383
                
384
        //ProgressBar pb = new ProgressBar();
385
            //TextView tv = (TextView) findViewById(R.id.login_authenticating_label);
386
        //pb.setVisibility(visibility);
387
        //tv.setVisibility(visibility);
388
    }
389
        
390
        private void setActivityIndicatorsVisibility(int visibility, View v) {
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
        
400
        private void showDialog() {
401
                authenticating = true;
402
                dialog = ProgressDialog.show(ListAccountsActivity.this, "", "Authenticating...", true);
403
    }
404
    
405
    private void hideDialog() {
406
            if(dialog != null){
407
                    dialog.dismiss();
408
            }
409
            authenticating = false;
410
    }
411

    
412
        private class AuthenticateTask extends AsyncTask<Void, Void, Boolean> {
413
            
414
                @Override
415
                protected void onPreExecute(){
416
                        showDialog();
417
                }
418
                
419
                @Override
420
                protected Boolean doInBackground(Void... arg0) {
421
                        return new Boolean(Authentication.authenticate(context));
422
                        //return true;
423
                }
424
            
425
                @Override
426
                protected void onPostExecute(Boolean result) {
427
                        if (result.booleanValue()) {
428
                                //startActivity(tabViewIntent);
429
                        new LoadImagesTask().execute((Void[]) null);
430
                        } else {
431
                                hideDialog();
432
                                showAlert("Login Failure", "Authentication failed.  Please check your User Name and API Key.");
433
                        }
434
                }
435
    }
436

    
437
    private class LoadFlavorsTask extends AsyncTask<Void, Void, ArrayList<Flavor>> {
438
            
439
                @Override
440
                protected ArrayList<Flavor> doInBackground(Void... arg0) {
441
                        return (new FlavorManager()).createList(true, context);
442
                }
443
            
444
                @Override
445
                protected void onPostExecute(ArrayList<Flavor> result) {
446
                        if (result != null && result.size() > 0) {
447
                                TreeMap<String, Flavor> flavorMap = new TreeMap<String, Flavor>();
448
                                for (int i = 0; i < result.size(); i++) {
449
                                        Flavor flavor = result.get(i);
450
                                        flavorMap.put(flavor.getId(), flavor);
451
                                }
452
                                Flavor.setFlavors(flavorMap);
453
                                hideDialog();
454
                                startActivity(tabViewIntent);
455
                        } else {
456
                                hideDialog();
457
                                showAlert("Login Failure", "There was a problem loading server flavors.  Please try again.");
458
                        }
459
                }
460
    }
461

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