source: dispositivos_moviles/TibisayMovil/src/ve/gob/cenditel/tibisaymovil/FilesToPDFSignActivity.java @ 931bb65

Last change on this file since 931bb65 was 931bb65, checked in by Jose Ruiz <joseruiz@…>, 11 years ago

firma electronica pdf

  • Property mode set to 100644
File size: 21.6 KB
Line 
1package ve.gob.cenditel.tibisaymovil;
2
3import java.io.File;
4import java.text.SimpleDateFormat;
5import java.util.ArrayList;
6import java.util.Collections;
7import java.util.Date;
8import java.util.List;
9
10
11import ve.gob.cenditel.tibisaymovil.R;
12import android.app.Activity;
13import android.app.AlertDialog;
14import android.content.DialogInterface;
15import android.content.Intent;
16import android.content.DialogInterface.OnCancelListener;
17import android.content.DialogInterface.OnDismissListener;
18import android.graphics.drawable.Drawable;
19import android.net.Uri;
20import android.os.Build;
21import android.os.Bundle;
22import android.view.LayoutInflater;
23import android.view.View;
24import android.view.ViewGroup;
25import android.view.View.OnClickListener;
26import android.view.Window;
27import android.webkit.MimeTypeMap;
28import android.widget.AdapterView;
29import android.widget.BaseAdapter;
30import android.widget.CheckBox;
31import android.widget.ImageView;
32import android.widget.LinearLayout;
33import android.widget.ListView;
34import android.widget.TextView;
35import android.widget.AdapterView.OnItemClickListener;
36import android.widget.Toast;
37
38public class FilesToPDFSignActivity extends KeyChainClientActivity implements OnItemClickListener, OnClickListener {
39
40        private File cwd;
41    private List<File> selected;
42    private FileBrowserView viewHolder;
43    private FileListAdapter listAdapter;
44        private int requestCode;
45        private int resultCode;
46        private Intent data;
47        private String privateKeyAlias;
48    private String filterMImeType = "application/pdf";
49
50        @Override
51        protected void onCreate(Bundle savedInstanceState) {
52                //Estilando la barra de titulo
53                final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
54
55                super.onCreate(savedInstanceState);
56               
57                this.viewHolder = new FileBrowserView();       
58
59        if (savedInstanceState != null) {
60               
61                this.selected = TypeUtils.convertToFileList(savedInstanceState.getStringArrayList("selected"));
62            if (this.selected.size() > 0) {             
63                FilesToPDFSignActivity.this.updateButton
64                (FilesToPDFSignActivity.this.viewHolder.accept,true);
65            }
66           
67            this.cwd = new File(savedInstanceState.getString("cwd"));
68            this.viewHolder.fileList.setAdapter(this.listAdapter = new FileListAdapter(this.cwd.getAbsolutePath(), filterMImeType));
69           
70        } else {
71            this.selected = new ArrayList<File>();
72            this.viewHolder.fileList.setAdapter(this.listAdapter = new FileListAdapter());
73        }
74       
75       
76        boolean enabled = false;
77        if (!this.selected.isEmpty())
78                enabled = this.viewHolder.accept.isEnabled();
79       
80                FilesToPDFSignActivity.this.updateButton(FilesToPDFSignActivity.this.viewHolder.accept,enabled);
81       
82        FilesToPDFSignActivity.this.updateButton
83        (FilesToPDFSignActivity.this.viewHolder.accept,enabled);
84       
85        //Estilando Barra de titulo
86                if(customTitleSupported)
87                        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_bar);
88                //Obtiene o crea un instancia de en keyChain y le asigna la actividad que lo genera
89               
90        KeyChainStrategy.getInstance().setClientActivity(this);
91        }
92
93       
94    /**
95     * Provides the data to be shown in the file browser ListView.
96     *
97     * @author José M. Prieto (jmprieto@emergya.com)
98     */
99    private class FileListAdapter extends BaseAdapter {
100
101        private final ArrayList<File> directories;
102        private final ArrayList<File> files;
103
104        private FileListAdapter() {
105            this("/",filterMImeType);
106        }
107
108        private FileListAdapter(String location) {
109            this(location, "");
110        }
111       
112        private FileListAdapter(String location, String filterMimeType) {
113               
114            directories = new ArrayList<File>();
115            files = new ArrayList<File>();
116           
117            //Obtiene etiqueta que se colocará antes del path que visualizará el usuario
118                String toPathText = FilesToPDFSignActivity.this.getString(R.string.pathstring)+":   ";
119                //Coloca el texto de la etiqueta en la vista
120                FilesToPDFSignActivity.this.viewHolder.pathString.setText(toPathText);
121                //Coloca el texto con el path actual
122                FilesToPDFSignActivity.this.viewHolder.path.setText(location);
123                //Crea un objeto file cwd con la ubicacion dada en location
124            FilesToPDFSignActivity.this.cwd = new File(location);
125            //Obtiene el directorio padre del objeto file cwd
126            File parent = FilesToPDFSignActivity.this.cwd.getParentFile();
127            //Si tiene un padre, lo agrega en la posición cero de la lista de directorios 
128           
129            if (parent != null) {
130                directories.add(0, parent);
131            }
132           
133            //Crea un arreglo con las lista de archivos contenidos en el directorio cwd
134            File[] ls = FilesToPDFSignActivity.this.cwd.listFiles();
135            if (ls != null) {
136                for (File f : ls) { //recorre todos los archivos contenidos en el directorio
137                       
138                    if (FsUtils.isHiddenOrNotReadable(f)) { // Si son ocultos no hace nada
139                        continue;
140                    }
141                  // Si son directorios los agrega a la lista de directorios a partir de la posición 1
142                  // En la posición 0 se encuentra el directorio padre 
143                    if (f.isDirectory()) {
144                        directories.add(f);
145                    } else // De lo contrario lo agrega a la lista de archivos
146                        {
147                        //Valida tipo de archivo a mostrar
148                        Uri selectedUri = Uri.fromFile(f);
149                        String fileExtension = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString());
150                        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
151                         
152//                        Toast.makeText(FileToSignHandwrittenSignatureActivity.this,
153//                          "FileExtension: " + fileExtension + "\n" +
154//                          "MimeType: " + mimeType,
155//                          Toast.LENGTH_LONG).show();
156                       
157                        //Filtra por mimeType
158                        if(filterMimeType.isEmpty() || filterMimeType == mimeType)
159                            files.add(f);
160                               
161                    }
162                }
163            }
164
165            Collections.sort(directories); // Ordena los directorios alfabeticamente
166            Collections.sort(files); // Ordena los archivos alfabeticamente
167        }
168       
169        /**
170         * Retorna cantidad total de elementos que se listarán en el directorio.
171         */
172        @Override 
173        public int getCount() {
174               
175            return directories.size() + files.size();
176           
177        }
178
179        /**
180         * Dada una posición en el listado del directorio, retorna un archivo o directorio
181         * según corresponda.
182         */
183        @Override
184        public File getItem(int position) {
185
186            if (position < directories.size()) {
187                return directories.get(position);
188            } else {
189                return files.get(position - directories.size());
190            }
191        }
192
193        /**
194         * Retorna un código hash para el archivo, permite comparar si dos archivos son los mismos
195         */
196        @Override
197        public long getItemId(int position) {
198
199            return getItem(position).hashCode();
200        }
201       
202        /**
203         * Crea la visualización de cada item del fileBrowser
204         */
205        @Override
206        public View getView(int position, View convertView, ViewGroup parent) {
207
208                //Crea la vista de cada fila del filebrowser a partir del layout
209            if (convertView == null) {
210                LayoutInflater inflater = LayoutInflater.from(FilesToPDFSignActivity.this);
211                convertView = inflater.inflate(R.layout.files_to_pdf_sign_item, parent, false); 
212            }
213           
214            // Se enlaza a cada componente del layout
215            ImageView image = (ImageView) convertView.findViewById(R.id.type_image);
216            TextView fileName = (TextView) convertView.findViewById(R.id.filename_text);
217            TextView modified = (TextView) convertView.findViewById(R.id.filename_modified);
218           
219            // Se obtiene el archivo ubicado en position
220                File file = getItem(position);
221               
222                //RadioButton
223            CheckBox check = (CheckBox) convertView.findViewById(R.id.file_check);
224            check.setFocusable(false);
225           
226            // Se asignan los iconos según el tipo de archivo y se oculta el radio en los directorios
227            if (file.isDirectory()) {
228                image.setImageResource(R.drawable.ic_carpeta);
229                check.setVisibility(View.INVISIBLE);
230                check.setChecked(false);
231            } else {
232                image.setImageResource(R.drawable.ic_archivo);
233                check.setVisibility(View.VISIBLE);
234                if (!FilesToPDFSignActivity.this.selected.contains(file)){
235                        check.setChecked(false);
236                } else{
237                        check.setChecked(true);
238                }
239         
240            }
241
242            // Si es el directorio que hace referencia al padre le coloca como nombre ".."
243            if (file.isDirectory() && position == 0 && ! "/".equals(FilesToPDFSignActivity.this.cwd.getAbsolutePath())) {
244                fileName.setText("..");
245            } else {
246                fileName.setText(file.getName());
247            }
248 
249           
250            //Datos de modificación del archivo
251            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
252            Date date = new Date(file.lastModified());
253           
254            String dateString = FilesToPDFSignActivity.this.getString(R.string.modified)+": ";
255            if (file.lastModified()>0)
256                modified.setText(dateString+sdf.format(date));
257            else
258                modified.setText(dateString+"-");
259           
260            return convertView;
261        }
262       
263        /**
264         * Controla la selección de cada item del fileBrowser
265         */
266        public void select(ListView parent, int position) {
267
268            File item = getItem(position);
269            //Si es un directorio el seleccionado se hace un llamado del fileBrowser del directorio
270            if (item.isDirectory()) {
271                parent.setAdapter(FilesToPDFSignActivity.this.listAdapter = new FileListAdapter(item.getAbsolutePath()));
272            } else { // Si es un archivo
273               
274                        //Se agrega el archivo a la lista de seleccionados si no se encuentra en la misma               
275                if (!FilesToPDFSignActivity.this.selected.contains(item)){
276                       
277                        FilesToPDFSignActivity.this.selected.add(item);                         
278                        FilesToPDFSignActivity.this.updateButton(FilesToPDFSignActivity.this.viewHolder.accept,true);           
279                                               
280                }
281                else{ // De lo contrario se elimina de la lista de seleccionados
282                       
283                        FilesToPDFSignActivity.this.selected.remove(item);
284                       
285                        if (FilesToPDFSignActivity.this.selected.isEmpty()){
286                               
287                                FilesToPDFSignActivity.this.updateButton(FilesToPDFSignActivity.this.viewHolder.accept,false);
288
289                               
290                        }else {
291                                FilesToPDFSignActivity.this.updateButton(FilesToPDFSignActivity.this.viewHolder.accept,true);
292
293                        }
294                                       
295                }
296                notifyDataSetChanged();
297           }
298        }       
299    }   
300
301
302   
303   
304    @Override
305    protected void onSaveInstanceState(Bundle outState) {
306        super.onSaveInstanceState(outState);
307
308        outState.putParcelable("intent", this.getIntent());
309        outState.putString("cwd", this.cwd.getAbsolutePath());
310        outState.putStringArrayList("selected", TypeUtils.convertToStringArrayList(this.selected));
311       
312        outState.putParcelable("intent", this.data);
313        outState.putInt("requestCode", this.requestCode);
314        outState.putInt("resultCode", this.resultCode);
315       
316        }
317   
318    private void updateButton(View v, boolean bool) {
319        try{
320
321                v.setEnabled(bool);
322                if (v instanceof TextView){
323                        Drawable icon = ((TextView)v).getCompoundDrawables()[1];
324                        if (icon!=null)
325                        if (bool)
326                                icon.setAlpha(255);
327                        else
328                                icon.setAlpha(127);     
329                }
330                if (v instanceof ImageView){
331                        ImageView result = (ImageView) v;
332                        if (bool)
333                                result.setAlpha(255);
334                        else
335                                result.setAlpha(127);   
336                }
337       
338        }catch(NullPointerException e){}
339                       
340        }
341   
342    private void updateButton(LinearLayout layout, boolean bool) {
343        try{
344        layout.setEnabled(bool);
345        for (int i=0; i<layout.getChildCount();i++){
346                this.updateButton(layout.getChildAt(i), bool);
347        }
348        }catch(NullPointerException e){}
349                       
350        }
351
352       
353       
354        /**
355     * Holds references to view objects.
356     *
357     * @author José M. Prieto (jmprieto@emergya.com)
358     */
359    private class FileBrowserView {
360
361        public ListView fileList;
362        public TextView path;
363        public LinearLayout accept;
364                public LinearLayout clear;
365        public TextView pathString;
366
367        public FileBrowserView() {
368
369            setContentView(R.layout.activity_file_to_sign_handwritten_signature);
370            this.path = (TextView) findViewById(R.id.path);
371            this.pathString = (TextView) findViewById(R.id.pathstring);
372
373            this.fileList = (ListView) findViewById(R.id.file_list);
374            this.fileList.setOnItemClickListener(FilesToPDFSignActivity.this);
375            this.fileList.setItemsCanFocus(true);
376         
377           
378            this.clear = (LinearLayout) findViewById(R.id.button_clear_zone);
379            this.clear.setOnClickListener(FilesToPDFSignActivity.this);
380           
381            this.accept = (LinearLayout) findViewById(R.id.button_accept_zone);
382            this.accept.setOnClickListener(FilesToPDFSignActivity.this);
383
384        }
385    }
386   
387        @Override
388    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
389       
390       
391        if (parent.getId() == R.id.file_list) { // user selects a file
392            this.listAdapter.select((ListView) parent, position);
393           
394        } else { // user de-selects a file
395            //this.listAdapter.addIfSameDirectory(selectedAdapter.doUnselect((ListView) parent, position));
396               
397        }
398        //this.viewHolder.numSelected.setText(Integer.toString(this.selected.size()));
399    }
400
401    @Override
402    public void onClick(View v) {
403
404        switch (v.getId()) {
405
406       
407        case R.id.button_clear_zone:
408
409                this.selected.clear();
410                this.listAdapter.notifyDataSetChanged();
411
412                //this.viewHolder.numSelected.setText(""+this.selected.size());
413            this.updateButton(this.viewHolder.accept, false);
414                break;         
415       
416
417       
418            case R.id.button_accept_zone: 
419
420                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH || this.getFileStreamPath(DirectKeyChain.keyStoreFilename).exists()){
421                       
422           
423                Intent intent = new Intent(this, FilesToPDFSignConfirmationActivity.class);
424                intent.putStringArrayListExtra(IntentExtraField.FILES, TypeUtils.convertToStringArrayList(this.selected));
425                startActivityForResult(intent, ActivityResult.FILES_CONFIRMATED);
426         
427               
428                        }else{
429                                this.createNoKeyStoreDialog();
430                        }
431           
432                break;         
433       
434        }
435    }
436   
437   
438        private void createNoKeyStoreDialog() {
439                AlertDialog.Builder builder = new AlertDialog.Builder(this);
440
441                builder.setCancelable(false);
442                builder.setMessage(R.string.error_keystore_file);
443                builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
444                public void onClick(DialogInterface dialog, int id) {
445                    dialog.dismiss();
446                }
447            });
448                AlertDialog dialog = builder.create(); 
449                dialog.show();
450               
451        }
452   
453        @Override
454    protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
455        Toast.makeText(this, "result", Toast.LENGTH_LONG).show();
456
457        this.requestCode = requestCode;
458        this.resultCode = resultCode;
459        this.data=data;
460        Toast.makeText(this, "request_code="+this.requestCode+" result="+this.resultCode, Toast.LENGTH_LONG).show();
461       
462       
463
464        if (resultCode == RESULT_CANCELED && requestCode!=ActivityResult.FILES_CONFIRMATED
465                &&      requestCode!=ActivityResult.IMPORT_CERTIFICATE) {
466                //Removed to fix task error #73085
467            /*setResult(RESULT_CANCELED);
468            finish();
469            return;
470            */
471               
472               
473                if (this.selected.size()>0){
474                 Intent intent = new Intent(this, FilesToPKCS7SignConfirmationActivity.class);
475             intent.putStringArrayListExtra(IntentExtraField.FILES, TypeUtils.convertToStringArrayList(this.selected));
476             startActivityForResult(intent, ActivityResult.FILES_CONFIRMATED);
477                }
478               
479               
480        }
481
482       
483        switch (requestCode) {
484        case ActivityResult.CHECK_CERTIFICATE_VALIDITY:
485
486            if (resultCode == RESULT_OK) {
487                Toast.makeText(FilesToPDFSignActivity.this, "aqui", Toast.LENGTH_LONG).show();
488
489                boolean embedSignature = data.getBooleanExtra(IntentExtraField.EMBED_SIGNATURE_IN_PDF, false);
490                Intent intent = new Intent(this, SignActivity.class);
491                intent.putExtra(IntentExtraField.EMBED_SIGNATURE_IN_PDF, embedSignature);
492                intent.putExtra(IntentExtraField.ALIAS, this.privateKeyAlias);
493                intent.putParcelableArrayListExtra(IntentExtraField.FILES, TypeUtils.convertToUriArrayList(this.selected));
494                startActivity(intent);
495               
496                //Finish only in this branch to fix error #73085
497                finish();
498            }
499            break;
500       
501        case ActivityResult.FILES_CONFIRMATED:
502                if (resultCode == RESULT_OK){
503                                               
504                        this.selected.clear();
505                        List<String> paths = data.getStringArrayListExtra(IntentExtraField.FILES);
506                        for (String s: paths)
507                                this.selected.add(new File(s));
508                       
509                        this.listAdapter.notifyDataSetChanged();
510                        KeyChainStrategy.getInstance().choosePrivateKeyAlias();
511
512                }
513                break;
514        }
515               
516               
517//        if (requestCode == ActivityResult.IMPORT_CERTIFICATE && resultCode == Activity.RESULT_OK) {
518//            //this.launchPasswordDialog(data);
519//        }
520    }
521       
522
523
524    private void launchPasswordDialog(final Intent data) {
525                //TODO: Setting boolean to false instead of true. Disables "New KeyStore" option.
526
527        final PasswordDialog dialog = new PasswordDialog(this, R.string.certificate_password, false);
528        dialog.setAcceptListener(new OnClickListener() {
529
530            @Override
531            public void onClick(View v) {
532
533                try {
534                        DirectKeyChain direct = DirectKeyChain.getInstance();
535                    int imported = direct.importCertificate(data.getData(), dialog.getPassword());
536                    String text = FilesToPDFSignActivity.this.getResources().getQuantityString(R.plurals.number_imported_certificates, imported, imported);
537                    Toast.makeText(FilesToPDFSignActivity.this, text, Toast.LENGTH_LONG).show();
538                    direct.saveKeystore();
539                    direct.refreshAdapter();
540                   
541                } catch (IncorrectPasswordException e) {
542                    Toast toast = Toast.makeText(FilesToPDFSignActivity.this, R.string.incorrect_password, Toast.LENGTH_LONG);
543                    toast.show();
544                } catch (Exception e) {
545                    Toast toast = Toast.makeText(FilesToPDFSignActivity.this, R.string.error_reading_p12, Toast.LENGTH_LONG);
546                    toast.show();
547                }
548               
549             
550               
551                dialog.dismiss();
552                FilesToPDFSignActivity.this.requestCode=Integer.MIN_VALUE;
553                FilesToPDFSignActivity.this.resultCode=Integer.MIN_VALUE;
554                FilesToPDFSignActivity.this.data=null;
555            }
556        });
557       
558       
559       
560        //TODO:
561       
562       dialog.setOnDismissListener(new OnDismissListener(){
563
564                @Override
565                public void onDismiss(DialogInterface arg0) {
566                        FilesToPDFSignActivity.this.data=null;
567                        FilesToPDFSignActivity.this.requestCode=Integer.MIN_VALUE;
568                        FilesToPDFSignActivity.this.resultCode=Integer.MIN_VALUE;                       
569                }});
570       
571       
572       
573       
574        dialog.setOnCancelListener(new OnCancelListener(){
575
576                        @Override
577                        public void onCancel(DialogInterface dialog) {
578                                FilesToPDFSignActivity.this.data=null;
579                                FilesToPDFSignActivity.this.requestCode=Integer.MIN_VALUE;
580                                FilesToPDFSignActivity.this.resultCode=Integer.MIN_VALUE;                               
581                        }});
582       
583        dialog.show();
584       
585        }
586
587
588    @Override
589    public void setAlias(String alias) {
590
591        if (alias == null) {
592                Toast.makeText(CustomKeyChain.activity, "alias null", Toast.LENGTH_LONG).show();
593
594            finish();
595            return;
596        }
597       // Toast.makeText(this, "setAlias="+alias, Toast.LENGTH_LONG).show();
598       
599        this.privateKeyAlias = alias;
600        Intent intent = new Intent(this, CertValidatorActivity.class);
601        intent.putExtra(IntentExtraField.ALIAS, alias);
602        intent.putExtra(IntentExtraField.EMBED_SIGNATURE_IN_PDF, true);
603        intent.putParcelableArrayListExtra(IntentExtraField.FILES, TypeUtils.convertToUriArrayList(this.selected));
604        startActivityForResult(intent, ActivityResult.CHECK_CERTIFICATE_VALIDITY);
605    }
606       
607
608}
Note: See TracBrowser for help on using the repository browser.