Statistics
| Branch: | Revision:

root / src / com / rackspace / cloud / android / ContainerObjectDetails.java @ 732d9c2c

History | View | Annotate | Download (18.2 kB)

1
package com.rackspace.cloud.android;
2

    
3
import java.io.BufferedOutputStream;
4
import java.io.File;
5
import java.io.FileNotFoundException;
6
import java.io.FileOutputStream;
7
import java.io.IOException;
8
import java.util.Iterator;
9
import java.util.Map.Entry;
10

    
11
import org.apache.http.HttpEntity;
12
import org.apache.http.HttpResponse;
13
import org.apache.http.util.EntityUtils;
14

    
15
import android.app.Activity;
16
import android.app.AlertDialog;
17
import android.app.Dialog;
18
import android.content.DialogInterface;
19
import android.content.Intent;
20
import android.net.Uri;
21
import android.os.AsyncTask;
22
import android.os.Bundle;
23
import android.os.Environment;
24
import android.util.Log;
25
import android.view.LayoutInflater;
26
import android.view.Menu;
27
import android.view.MenuInflater;
28
import android.view.MenuItem;
29
import android.view.View;
30
import android.view.View.OnClickListener;
31
import android.widget.Button;
32
import android.widget.CheckBox;
33
import android.widget.CompoundButton;
34
import android.widget.CompoundButton.OnCheckedChangeListener;
35
import android.widget.LinearLayout;
36
import android.widget.TabHost;
37
import android.widget.TextView;
38
import android.widget.Toast;
39

    
40
import com.rackspace.cloud.files.api.client.ContainerObjectManager;
41
import com.rackspace.cloud.files.api.client.ContainerObjects;
42
import com.rackspace.cloud.files.api.client.Permission;
43
import com.rackspace.cloud.servers.api.client.CloudServersException;
44
import com.rackspace.cloud.servers.api.client.http.HttpBundle;
45

    
46
/** 
47
 * 
48
 * @author Phillip Toohill
49
 *
50
 */
51

    
52
public class ContainerObjectDetails extends CloudActivity {
53

    
54
        private static final int deleteObject = 0;
55
        private final String DOWNLOAD_DIRECTORY = "/RackspaceCloud";
56
        
57
        private ContainerObjects objects;
58
        private String containerNames;
59
        private String cdnURL;
60
        private String cdnEnabled;
61
        public String LOG = "ViewObject";
62
        private int bConver = 1048576;
63
        private int kbConver = 1024;
64
        private double megaBytes;
65
        private double kiloBytes;
66
        public Button previewButton;
67
        public Button downloadButton;
68
        private Boolean isDownloaded;
69
        private AndroidCloudApplication app;
70
        private DeleteObjectListenerTask deleteObjTask;
71
        private DownloadObjectListenerTask downloadObjTask;
72
                
73
        /** Called when the activity is first created. */
74
        @Override
75
        public void onCreate(Bundle savedInstanceState) {
76
                super.onCreate(savedInstanceState);
77
                trackPageView(GoogleAnalytics.PAGE_STORAGE_OBJECT);
78

    
79
                objects = (ContainerObjects) this.getIntent().getExtras().get("container");
80
                containerNames =  (String) this.getIntent().getExtras().get("containerNames");
81
                cdnURL = (String) this.getIntent().getExtras().get("cdnUrl");
82
                cdnEnabled = (String) this.getIntent().getExtras().get("isCdnEnabled");
83

    
84
                setContentView(R.layout.viewobject); 
85
                TabHost tabs = (TabHost)findViewById(R.id.tabhost2);
86

    
87
        tabs.setup();
88

    
89
        TabHost.TabSpec spec = tabs.newTabSpec("tag1");
90

    
91
        spec.setContent(R.id.details);
92
        spec.setIndicator("Details");
93
        tabs.addTab(spec);
94

    
95
        spec = tabs.newTabSpec("tag2");
96
        spec.setContent(R.id.metadata);
97
        spec.setIndicator("Metadata");
98
        tabs.addTab(spec);
99
        
100
        spec = tabs.newTabSpec("tag3");
101
        spec.setContent(R.id.sharing);
102
        spec.setIndicator("Sharing");
103
        tabs.addTab(spec);
104
        
105
        spec = tabs.newTabSpec("tag4");
106
        spec.setContent(R.id.versions);
107
        spec.setIndicator("Versions");
108
        tabs.addTab(spec);
109
        
110
                restoreState(savedInstanceState);
111
        }
112

    
113
        @Override
114
        protected void onSaveInstanceState(Bundle outState) {
115
                super.onSaveInstanceState(outState);
116
                outState.putSerializable("container", objects);
117
                outState.putBoolean("isDownloaded", isDownloaded);
118
        }
119

    
120
        protected void restoreState(Bundle state) {
121
                super.restoreState(state);
122
                /*
123
                 * need reference to the app so you can access curDirFiles
124
                 * as well as processing status
125
                 */
126
                app = (AndroidCloudApplication)this.getApplication();
127

    
128
                if (state != null && state.containsKey("container")) {
129
                        objects = (ContainerObjects) state.getSerializable("container");
130
                }
131
                loadObjectData();
132

    
133
                if ( cdnEnabled.equals("true"))  {
134
                        this.previewButton = (Button) findViewById(R.id.preview_button);
135
                        previewButton.setOnClickListener(new MyOnClickListener());
136
                } else {
137
                        this.previewButton = (Button) findViewById(R.id.preview_button);
138
                        previewButton.setVisibility(View.GONE);
139
                }
140

    
141
                if (state != null && state.containsKey("isDownloaded")){
142
                        isDownloaded = state.getBoolean("isDownloaded");
143
                }
144
                else{
145
                        isDownloaded = fileIsDownloaded();
146
                }
147
                this.downloadButton = (Button) findViewById(R.id.download_button);
148
                if ( isDownloaded )  {
149
                        downloadButton.setText("Open File");
150
                } else {
151
                        downloadButton.setText("Download File");
152
                }           
153
                downloadButton.setOnClickListener(new MyOnClickListener());
154
                
155
                if(app.isDeletingObject()){
156
                        deleteObjTask = new DeleteObjectListenerTask();
157
                        deleteObjTask.execute();
158
                }
159
                
160
                if(app.isDownloadingObject()){
161
                        downloadObjTask = new DownloadObjectListenerTask();
162
                        downloadObjTask.execute();
163
                }
164
                
165
        }
166
        
167
        
168
        
169
        @Override
170
        protected void onStop(){
171
                super.onStop();
172

    
173
                /*
174
                 * Need to stop running listener task
175
                 * if we exit
176
                 */
177
                if(deleteObjTask != null){
178
                        deleteObjTask.cancel(true);
179
                }
180
                
181
                if(downloadObjTask != null){
182
                        downloadObjTask.cancel(true);
183
                }
184
        }
185

    
186

    
187
        private void loadObjectData() {
188
                //Object Name
189
                TextView name = (TextView) findViewById(R.id.view_container_name);
190
                name.setText(objects.getCName().toString());
191

    
192
                //File size
193
                if (objects.getBytes() >= bConver) {
194
                        megaBytes = Math.abs(objects.getBytes()/bConver + 0.2);
195
                        TextView sublabel = (TextView) findViewById(R.id.view_file_bytes);
196
                        sublabel.setText(megaBytes + " MB");
197
                } else if (objects.getBytes() >= kbConver){
198
                        kiloBytes = Math.abs(objects.getBytes()/kbConver + 0.2);
199
                        TextView sublabel = (TextView) findViewById(R.id.view_file_bytes);
200
                        sublabel.setText(kiloBytes + " KB");
201
                } else {
202
                        TextView sublabel = (TextView) findViewById(R.id.view_file_bytes);
203
                        sublabel.setText(objects.getBytes() + " B");
204
                }        
205

    
206
                //Content Type
207
                TextView cType = (TextView) findViewById(R.id.view_content_type);
208
                cType.setText(objects.getContentType().toString());
209

    
210
                //Last Modification date
211
                String strDate = objects.getLastMod();
212
                strDate = strDate.substring(0, strDate.indexOf('T'));
213

    
214
                TextView lastmod = (TextView) findViewById(R.id.view_file_modification);
215
                lastmod.setText(strDate);              
216
                rebuildMetadataList();
217
                rebuildPermissionList();
218
        }
219
        
220
        private void rebuildMetadataList(){
221
                LayoutInflater layoutInflater = LayoutInflater.from(ContainerObjectDetails.this);
222
                final LinearLayout metadata = (LinearLayout) findViewById(R.id.metadataList);
223
                if(metadata.getChildCount()>0)
224
                        metadata.removeViews(0,metadata.getChildCount());
225
                metadata.removeAllViews();
226
                
227
                if(objects.getMetadata()!=null){
228
                        int i=0;
229
                        Iterator<Entry<String,String>> it = objects.getMetadata().entrySet().iterator();
230
                        while (it.hasNext()) {
231
                                final Entry<String,String> perm = it.next();
232
                                final View v = layoutInflater.inflate(R.layout.metadatarow, null);
233
                                populateMetadataList(perm, v, metadata, i);
234
                                i++;
235
                        }
236
                }
237
        }
238
        
239
        private void populateMetadataList(final Entry<String,String>  metadata, final View v, final LinearLayout properties, int i){
240
                properties.addView(v, i);
241
                Log.d(LOG,i+" "+metadata.getKey()+" "+metadata.getValue());
242
                ((TextView) v.findViewById(R.id.mkey)).setText(metadata.getKey());
243
                ((TextView) v.findViewById(R.id.mvalue)).setText(metadata.getValue());
244
        }
245

    
246
        
247
        private void rebuildPermissionList(){
248
                LayoutInflater layoutInflater = LayoutInflater.from(ContainerObjectDetails.this);
249
                final LinearLayout properties = (LinearLayout) findViewById(R.id.permissionsList);
250
                if(properties.getChildCount()>0)
251
                        properties.removeViews(0,properties.getChildCount());
252
                properties.removeAllViews();
253
                Iterator<Permission> it=null;
254
                if(objects.getPermissions()!=null){
255
                        it= objects.getPermissions().iterator();
256
                        int i = 0;
257
                        while (it.hasNext()) {
258
                                final Permission perm = it.next();
259
                                final View v = layoutInflater.inflate(R.layout.propertiesrow, null);
260
                                populatePermissionList(perm, v, properties, i);
261
                                i++;
262
                        }
263
                }
264
        }
265
        
266
        private void populatePermissionList(final Permission perm, final View v, final LinearLayout properties, int i){
267
                
268
                
269
                properties.addView(v, i);
270
                
271
                
272
                
273
                ((TextView) v.findViewById(R.id.ownerName)).setText(perm.getUser());
274
                ((CheckBox) v.findViewById(R.id.read)).setChecked(perm.isRead());
275
                ((CheckBox) v.findViewById(R.id.write)).setChecked(perm.isWrite());
276
                
277
                ((CheckBox) v.findViewById(R.id.read)).setOnCheckedChangeListener(new OnCheckedChangeListener() {
278

    
279
                        @Override
280
                        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
281
                                perm.setRead(isChecked);
282

    
283
                        }
284
                });
285
                ((CheckBox) v.findViewById(R.id.write)).setOnCheckedChangeListener(new OnCheckedChangeListener() {
286

    
287
                        @Override
288
                        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
289
                                perm.setWrite(isChecked);
290

    
291
                        }
292
                });
293
                ((Button) v.findViewById(R.id.remove)).setOnClickListener(new OnClickListener() {
294

    
295
                        @Override
296
                        public void onClick(View v1) {
297
                                properties.removeView(v);
298
                                objects.getPermissions().remove(perm);
299

    
300
                        }
301
                });
302
        }
303
        
304
        
305
        private class MyOnClickListener implements View.OnClickListener {
306
                @Override
307
                public void onClick(View v) {
308
                        if(v.equals(findViewById(R.id.preview_button))){
309
                                Intent viewIntent = new Intent("android.intent.action.VIEW", Uri.parse(cdnURL + "/" + objects.getCName()));
310
                                startActivity(viewIntent);  
311
                        }
312
                        /*
313
                         * need to perform different functions based on if
314
                         * the file is in the devices filesystem
315
                         */
316
                        if(v.equals(findViewById(R.id.download_button))){
317
                                if(!isDownloaded){
318
                                        if(storageIsReady()){
319
                                                new ContainerObjectDownloadTask().execute();
320
                                        }
321
                                        else{
322
                                                showAlert("Error", "Storage not found.");
323
                                        }
324
                                }
325
                                else{
326
                                        openFile();
327
                                }
328
                        }
329
                }
330
        }
331

    
332
        //Create the Menu options
333
        @Override 
334
        public boolean onCreateOptionsMenu(Menu menu) {
335
                super.onCreateOptionsMenu(menu);
336
                MenuInflater inflater = getMenuInflater();
337
                inflater.inflate(R.menu.container_object_list_menu, menu);
338
                return true;
339
        } 
340

    
341
        @Override 
342
        public boolean onOptionsItemSelected(MenuItem item) {
343
                switch (item.getItemId()) {
344
                case R.id.delete_object:
345
                        showDialog(deleteObject); 
346
                        return true;
347
                case R.id.refresh:
348
                        loadObjectData();
349
                        return true;
350
                }
351
                return false;
352
        } 
353

    
354
        @Override
355
        protected Dialog onCreateDialog(int id ) {
356
                switch (id) {
357
                case deleteObject:
358
                        return new AlertDialog.Builder(ContainerObjectDetails.this)
359
                        .setIcon(R.drawable.alert_dialog_icon)
360
                        .setTitle("Delete File")
361
                        .setMessage("Are you sure you want to delete this file?")
362
                        .setPositiveButton("Delete File", new DialogInterface.OnClickListener() {
363
                                public void onClick(DialogInterface dialog, int whichButton) {
364
                                        // User clicked OK so do some stuff
365
                                        trackEvent(GoogleAnalytics.CATEGORY_FILE, GoogleAnalytics.EVENT_DELETE, "", -1);
366
                                        new ContainerObjectDeleteTask().execute((Void[]) null);
367
                                }
368
                        })
369
                        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
370
                                public void onClick(DialogInterface dialog, int whichButton) {
371
                                        // User clicked Cancel so do some stuff
372
                                }
373
                        })
374
                        .create();
375
                }
376
                return null;
377
        }
378
        /**
379
         * @return the file
380
         */
381
        public ContainerObjects getViewFile() {
382
                return objects;
383
        }
384

    
385
        /**
386
         * @param File the file to set
387
         */
388
        public void setViewFile(ContainerObjects object) {
389
                this.objects = object;
390
        }
391

    
392
        /*
393
         * returns false if external storage is not avaliable
394
         * (if its mounted, missing, read-only, etc)
395
         * from: http://developer.android.com/guide/topics/data/data-storage.html#filesExternal
396
         */
397
        private boolean storageIsReady(){
398
                boolean mExternalStorageAvailable = false;
399
                boolean mExternalStorageWriteable = false;
400
                String state = Environment.getExternalStorageState();
401

    
402
                if (Environment.MEDIA_MOUNTED.equals(state)) {
403
                        // We can read and write the media
404
                        mExternalStorageAvailable = mExternalStorageWriteable = true;
405
                } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
406
                        // We can only read the media
407
                        mExternalStorageAvailable = true;
408
                        mExternalStorageWriteable = false;
409
                } else {
410
                        // Something else is wrong. It may be one of many other states, but all we need
411
                        //  to know is we can neither read nor write
412
                        mExternalStorageAvailable = mExternalStorageWriteable = false;
413
                }
414
                return mExternalStorageAvailable && mExternalStorageWriteable;
415
        }
416

    
417
        private boolean fileIsDownloaded(){
418
                if(storageIsReady()){
419
                        String fileName = Environment.getExternalStorageDirectory().getPath() + "/RackspaceCloud/" + objects.getCName();
420
                        File f = new File(fileName);
421
                        return f.isFile();
422
                }
423
                return false;
424
        }
425

    
426
        private void openFile(){
427
                File object = new File(Environment.getExternalStorageDirectory().getPath() + "/RackspaceCloud/" + objects.getCName());
428
                Intent myIntent = new Intent(android.content.Intent.ACTION_VIEW);
429
                File file = new File(object.getAbsolutePath()); 
430
                String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());
431
                String mimetype = android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
432
                myIntent.setDataAndType(Uri.fromFile(file),mimetype);
433
                //myIntent.setData(Uri.fromFile(file));
434
                try{
435
                        startActivity(myIntent);
436
                }
437
                catch(Exception e){
438
                        Toast.makeText(this, "Could not open file.", Toast.LENGTH_SHORT).show();
439
                }
440
        }
441

    
442
        private boolean writeFile(byte[] data){
443
                String directoryName = Environment.getExternalStorageDirectory().getPath() + DOWNLOAD_DIRECTORY;
444
                File f = new File(directoryName);
445

    
446
                if(!f.isDirectory()){
447
                        if(!f.mkdir()){
448
                                return false;
449
                        }
450
                }
451

    
452
                String filename = directoryName + "/" + objects.getCName();
453
                File object = new File(filename);
454
                BufferedOutputStream bos = null;
455

    
456
                try{
457
                        FileOutputStream fos = new FileOutputStream(object);
458
                        bos = new BufferedOutputStream(fos);
459
                        bos.write(data);
460
                }
461
                catch(FileNotFoundException e){
462
                        e.printStackTrace();
463
                }
464
                catch(IOException e){
465
                        e.printStackTrace();
466
                }
467
                finally{
468
                        if(bos != null){
469
                                try {
470
                                        bos.flush();
471
                                        bos.close();
472
                                } catch (IOException e) {
473
                                        // TODO Auto-generated catch block
474
                                        e.printStackTrace();
475
                                }
476
                        }
477
                }
478
                return true;
479
        }
480

    
481
        //Task's
482

    
483
        private class ContainerObjectDeleteTask extends AsyncTask<Void, Void, HttpBundle> {
484

    
485
                private CloudServersException exception;
486

    
487
                protected void onPreExecute(){
488
                        showDialog();
489
                        app.setDeleteingObject(true);
490
                        deleteObjTask = new DeleteObjectListenerTask();
491
                        deleteObjTask.execute();
492
                }
493

    
494
                @Override
495
                protected HttpBundle doInBackground(Void... arg0) {
496
                        HttpBundle bundle = null;        
497
                        try {
498
                                bundle = (new ContainerObjectManager(getContext())).deleteObject(containerNames, objects.getCName() );
499
                        } catch (CloudServersException e) {
500
                                exception = e;
501
                        }
502
                        
503
                        return bundle;
504
                }
505

    
506
                @Override
507
                protected void onPostExecute(HttpBundle bundle) {
508
                        app.setDeleteingObject(false);
509
                        hideDialog();
510
                        HttpResponse response = bundle.getResponse();
511
                        if (response != null) {
512
                                int statusCode = response.getStatusLine().getStatusCode();
513
                                if (statusCode == 204) {
514
                                        //handled by listener
515
                                } else {
516
                                        CloudServersException cse = parseCloudServersException(response);
517
                                        if ("".equals(cse.getMessage())) {
518
                                                showError("There was a problem deleting your File.", bundle);
519
                                        } else {
520
                                                showError("There was a problem deleting your file: " + cse.getMessage(), bundle);
521
                                        }
522
                                }
523
                        } else if (exception != null) {
524
                                showError("There was a problem deleting your file: " + exception.getMessage(), bundle);                                
525
                        }                        
526
                }
527
        }
528

    
529
        private class ContainerObjectDownloadTask extends AsyncTask<Void, Void, HttpBundle> {
530

    
531
                private CloudServersException exception;
532

    
533
                @Override
534
                protected void onPreExecute(){
535
                        showDialog();
536
                        app.setDownloadingObject(true);
537
                        downloadObjTask = new DownloadObjectListenerTask();
538
                        downloadObjTask.execute();
539
                }
540

    
541
                @Override
542
                protected HttpBundle doInBackground(Void... arg0) {
543
                        HttpBundle bundle = null;        
544
                        try {
545
                                bundle = (new ContainerObjectManager(getContext())).getObject(containerNames, objects.getCName());
546
                        } catch (CloudServersException e) {
547
                                exception = e;
548
                        }
549
                        return bundle;
550
                }
551

    
552
                @Override
553
                protected void onPostExecute(HttpBundle bundle) {
554
                        app.setDownloadingObject(false);
555
                        hideDialog();
556
                        HttpResponse response = bundle.getResponse();
557
                        if (response != null) {
558
                                int statusCode = response.getStatusLine().getStatusCode();
559
                                if (statusCode == 200) {
560
                                        setResult(Activity.RESULT_OK);
561
                                        HttpEntity entity = response.getEntity();
562
                                        app.setDownloadedEntity(entity);
563
                                } else {
564
                                        CloudServersException cse = parseCloudServersException(response);
565
                                        if ("".equals(cse.getMessage())) {
566
                                                showError("There was a problem downloading your File.", bundle);
567
                                        } else {
568
                                                showError("There was a problem downloading your file: " + cse.getMessage(), bundle);
569
                                        }
570
                                }
571
                        } else if (exception != null) {
572
                                showError("There was a problem downloading your file: " + exception.getMessage(), bundle);                                
573
                        }                        
574
                }
575
        }
576
        
577
        private class DeleteObjectListenerTask extends
578
        AsyncTask<Void, Void, Void> {
579
                
580
                @Override
581
                protected Void doInBackground(Void... arg1) {
582

    
583
                        while(app.isDeletingObject()){
584
                                // wait for process to finish
585
                                // or have it be canceled
586
                                if(deleteObjTask.isCancelled()){
587
                                        return null;
588
                                }
589
                        }
590
                        return null;
591
                }
592

    
593
                /*
594
                 * when no longer processing, time to load
595
                 * the new files
596
                 */
597
                @Override
598
                protected void onPostExecute(Void arg1) {
599
                        hideDialog();
600
                        setResult(99);
601
                        finish();
602
                }
603
        }
604
        
605
        private class DownloadObjectListenerTask extends
606
        AsyncTask<Void, Void, Void> {
607
                
608
                @Override
609
                protected Void doInBackground(Void... arg1) {
610

    
611
                        while(app.isDownloadingObject()){
612
                                // wait for process to finish
613
                                // or have it be canceled
614
                                if(downloadObjTask.isCancelled()){
615
                                        return null;
616
                                }
617
                        }
618
                        return null;
619
                }
620

    
621
                /*
622
                 * when no longer processing, time to load
623
                 * the new files
624
                 */
625
                @Override
626
                protected void onPostExecute(Void arg1) {
627
                        hideDialog();
628
                        try {
629
                                if(writeFile(EntityUtils.toByteArray(app.getDownloadedEntity()))){
630
                                        downloadButton.setText("Open File");
631
                                        isDownloaded = true;
632
                                }
633
                                else{
634
                                        showAlert("Error", "There was a problem downloading your file.");
635
                                }
636

    
637
                        } catch (IOException e) {
638
                                showAlert("Error", "There was a problem downloading your file.");
639
                                e.printStackTrace();
640
                        } catch (Exception e) {
641
                                showAlert("Error", "There was a problem downloading your file.");
642
                                e.printStackTrace();
643
                        }
644
                }
645
        }
646

    
647
}