Monday 15 February 2016

HB Blog 104: How To Zip And Unzip Files In Androd Programatically???

ZIP is an archive file format that supports lossless data compression. A .ZIP file may contain one or more files or directories that may have been compressed. .ZIP files generally use the file extensions ".zip" or ".ZIP" and the MIME media type application/zip.

In Android, we can use Java's zip utility classes to compress files from sd-card. The process is as simple as normal file writing program. Just, consider normal file writing program where you copy textual data from one file to another file having extension as .txt, similarly, we can write files into another file format with extension .zip. Here, internal compression algorithum is taken care by Java's utility classes.

Refer the below link for complete sample code:-

Download Sample Code

Have a look on few code snippets,

//ZipManager.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package com.example.harshalbenake.zipcompressfiles;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import android.util.Log;

public class ZipManager {
    private static final int BUFFER = 80000;

    public void zip(String[] _files, String zipFileName) {
        try {
            BufferedInputStream origin = null;
            FileOutputStream dest = new FileOutputStream(zipFileName);
            ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
                    dest));
            byte data[] = new byte[BUFFER];

            for (int i = 0; i < _files.length; i++) {
                Log.v("Compress", "Adding: " + _files[i]);
                FileInputStream fi = new FileInputStream(_files[i]);
                origin = new BufferedInputStream(fi, BUFFER);

                ZipEntry entry = new ZipEntry(_files[i].substring(_files[i].lastIndexOf("/") + 1));
                out.putNextEntry(entry);
                int count;

                while ((count = origin.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }
                origin.close();
            }

            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void unzip(String _zipFile, String _targetLocation) {
        //create target location folder if not exist
        File f = new File(_targetLocation);
        if (!f.isDirectory()) {
            f.mkdirs();
        }

        try {
            FileInputStream fin = new FileInputStream(_zipFile);
            ZipInputStream zin = new ZipInputStream(fin);
            ZipEntry ze = null;
            while ((ze = zin.getNextEntry()) != null) {

                //create dir if required while unzipping
                if (ze.isDirectory()) {
                    File f1 = new File(ze.getName());
                    if (!f1.isDirectory()) {
                        f1.mkdirs();
                    }
                } else {
                    FileOutputStream fout = new FileOutputStream(_targetLocation + ze.getName());
                    for (int c = zin.read(); c != -1; c = zin.read()) {
                        fout.write(c);
                    }

                    zin.closeEntry();
                    fout.close();
                }

            }
            zin.close();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

//MainActivity.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.example.harshalbenake.zipcompressfiles;

import android.app.Activity;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class MainActivity extends Activity {

    String inputPathExternal = Environment.getExternalStorageDirectory().getPath()+ "/ZipDemo/";
    String inputPathInternal = Environment.getExternalStorageDirectory()+ "/hb/";
    String inputFile = "Apply.zip";
    String outputPath = Environment.getExternalStorageDirectory().getPath()+ "/UnZipDemo/";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // declare an array for storing the files
        // i.e the path of your source files
        String[] s = new String[2];

    // Type the path of the files in here
        s[0] = inputPathInternal + "/hb1.txt";
        s[1] = inputPathInternal + "/hb2.txt"; // /sdcard/ZipDemo/textfile.txt

    // first parameter is d files second parameter is zip file name
        ZipManager zipManager = new ZipManager();

    // calling the zip function
        zipManager.zip(s, inputPathInternal + inputFile);
    }

}

For unzipping files from a .zip file refer in Android you can follow my blog How To Download And Unzip File From Server In Android?

Monday 1 February 2016

HB Blog 103: Using InputFilter To Restrict Android Mobile User's From Typing Wrong Input's.

             In Android development, we need very specific inputs from the users. Now a days, developer are trying to work n custom keyboard applications where user can type with more accuracy and correctly. Developer's come across a scenario where he has to restrict the charters to 0-9, a-z, A-Z and space-bar only specifically.
For example, user needs to enter his mobile number as an input in EditText. So, the developer should not allow Alphabets and special characters as an input. You can always declare the input method by adding the android:inputType attribute to the <EditText> element. But, imagine a case where we have to specify a range of digits such as in case of months. We have 12 months so we can have a EditText where input are supposed to be in a range from 1 to 12.

Usually, we apply if condition as below,

1
2
if(strMonth>=1 && strMonth<=12){
}

That's perfect, nothing wrong with this. But, 'Precaution is better than cure'. In above example, we can check this conditions after user makes mistake. Now, we can have more optimized solution to it. We can restrict user's from typing wrong input's itself using InputFilter. InputFilters can be attached to Editable's to constrain the change's that can be made to them.

We can do something like below code snippets,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 EditText et=(EditText)findViewById(R.id.btn);
        et.setFilters(new InputFilter[]{ new InputFilter() {
            @Override
            public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int den) {
                try {
                    int input = Integer.parseInt(dest.toString() + source.toString());
                    if (isInRange(1, 12, input))
                        return null;
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
                return "";
            }
        }});

Where isInRange() method is as below,

1
2
3
  private boolean isInRange(int min, int max, int input) {
        return max > min ? input >= min && input <= max : input >= max && input <= min;
    }

And, dont forget to add input type as android:inputType="number" in above case.

The filter method is called when the buffer is going to replace the range dstart dend of dest with the new text from the range start end of source. It returns the CharSequence that you would like to have placed there instead, including an empty string if appropriate, or null to accept the original replacement. Be careful to not to reject 0-length replacements, as this is what happens when you delete text.