Pages

Showing posts with label android app. Show all posts
Showing posts with label android app. Show all posts

Wednesday, October 23, 2013

Folder Locker for Android

In this tutorial, you will learn to create a Folder Locker app. The Folder Locker is used to lock a folder so that all files and sub folders in the folder can not be viewed or read by other people. To lock a folder, you need to provide password in the password text box and push the Lock button. When the folder is locked, the locked icon will display instead of the normal folder icon. The locked folder can be unlocked if you provide the correct password used to lock the folder. You will push the Unlock button to unlock the locked folder.



Now open your Eclipse and create a new project. The project name will be FolderLock. For this Folder Locker app, its interface is simple as the File Lokcer interface. We need one EditText to allow the user to input the password, two Buttons for locking and unlocking the folder and one ListView to display the list of files and directories for the user to choose. These components are defined int he activity_main.xml file that is the resource file of the MainActivity class. Its content is shown below.

activity_main.xml file

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:background="@drawable/back_style"
     >

  <EditText
        android:id="@+id/txt_input"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword"    
        android:hint="@string/txt_hint"
        />
        <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="horizontal"
             >
<Button
          android:id="@+id/bt_lock"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/label_lock"
          android:onClick="lockFolder"
          />
   <Button
          android:id="@+id/bt_unlock"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/label_unlock"
          android:onClick="unlockFolder"
          />
  </LinearLayout>
  <TextView
         android:id="@+id/txt_view"
   android:layout_width="fill_parent"
         android:layout_height="wrap_content"
      />
        <ListView
            android:id="@+id/files_list"
            android:layout_width="fill_parent"
            android:layout_height="300dp"
            android:paddingBottom="5dp"
            android:paddingTop="5dp"
     
            />    

</LinearLayout>


The file that applies background style to the interface is called back_style.xml. It is saved in the drawable directory of the project.

back_style.xml file

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
       <item>
        <shape>
            <gradient
                android:startColor="#000000"
                android:endColor="#000000"
                android:angle="270" />
            <stroke
                android:width="1dp"
                android:color="#171717" />
            <corners
                android:radius="4dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>
</selector>


In the drawable directory you also need to have three small image files. One is file icon image. One is directory icon. And the last one is the icon image to represent the locked folder. You can download these images from here.

The string values that are used in the activity_main.xml file are defined in the strings.xml file. This is the content of the strings.xml file.
strings.xml file

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">FolderLock</string>
    <string name="action_settings">Settings</string>
   <string name="label_lock">Lock</string>
   <string name="txt_hint">Enter password</string>
   <string name="label_unlock">Unlock</string>
   <string name="icon_image">Icon</string>

</resources>


Again, we need to customize the ListView to display both images and text. This can be accomplished by defining the components for each item of the ListView in its layout file. Then you need to customize the ArrayAdapter class to supply both images and text to the ListView. You will have a class that extends the ArrayAdapter class. The object of the class will be the data source of the ListView. Here are the content of the listlayout.xml file and ListAdapterModel. java file. The ListAdaperModel stored in the ListAdapterModel.java file extends the ArrayAdapter class.

listlayout.xml file

<?xml version="1.0" encoding="utf-8"?>
<!--  Single List Item Design -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="5dip" >

<ImageView
    android:id="@+id/icon"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:padding="5sp"
    android:contentDescription="icon_image"
 />

<TextView
    android:id="@+id/label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10sp"
        android:textSize="20sp"
        android:textColor="#0000ff"
        android:textStyle="bold" >
</TextView>
</LinearLayout>


ListAdapterModel.java file

package com.example.folderlock;

import java.io.File;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;


public class ListAdapterModel extends ArrayAdapter<String>{
int groupid;
String[] names;
Context context;
String path;
public ListAdapterModel(Context context, int vg, int id, String[] names, String parentPath){
super(context,vg, id, names);
this.context=context;
groupid=vg;
this.names=names;
this.path=parentPath;
}
public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View itemView = inflater.inflate(groupid, parent, false);
        ImageView imageView = (ImageView) itemView.findViewById(R.id.icon);
        TextView textView = (TextView) itemView.findViewById(R.id.label);
        String item=names[position];
        textView.setText(item);
        File lockedfile=new File(context.getFilesDir(),item);
        if(lockedfile.exists()){
        //set the locked icon to the folder that was already locked.
        imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.folder_lock));
        }
        else{//set the directory and file icon to the unlocked files and folders
        File f=new File(path+"/"+item);
        if(f.isDirectory())
        imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.diricon));
        else
        imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.fileicon));
        }
        return itemView;
}

}



To help in locking and unlocking a folder, we also need a Locker class. The Locker.java file defines a class called Locker. This class contains methods that will be used in locking and unlocking folder processes. You will click this Locker.java to download the complete Locker.java file.

Locking and unlocking the folder is similar to locking and unlocking a file. First you need to package the folder in a single zip file. Please read the post Zipper to learn how to zip and extract files and folders. Then the zip file is encrypted so that it can not be extracted or viewed or extract by other apps. The technique to encrypt and decrypt the zip file here is the same as the technique used in the File Locker app. So you can read the explanation on how to encrypt a file on page File Locker.
Now we take a look at the MainActivity class that is in the MainActivity file. Here is the complete MainActivity.java file of the Folder Locker app.

package com.example.folderlock;
import java.io.File;

import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {

   private String path="";
   private String selectedFile="";
   private Context context;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.context=this;
     
 
    }

    protected void onStart(){
    super.onStart();
    ListView lv=(ListView) findViewById(R.id.files_list);
if(lv!=null){
lv.setSelector(R.drawable.selection_style);
lv.setOnItemClickListener(new ClickListener());
}
path="/mnt";
listDirContents();
    }
   
    public void onBackPressed(){
    goBack();
    }
   
    public void goBack(){
    if(path.length()>1){ //up one level of directory structure
    File f=new File(path);
    path=f.getParent();
    listDirContents();
    }
    else{
    refreshThumbnails();
    System.exit(0); //exit app
   
    }
    }
   
   
    private void refreshThumbnails(){
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
}
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

   
    private class ClickListener implements OnItemClickListener{
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
      //selected item      
            ViewGroup vg=(ViewGroup)view;
      String selectedItem = ((TextView) vg.findViewById(R.id.label)).getText().toString();
            path=path+"/"+selectedItem;
            //et.setText(path);          
            listDirContents();
      }
     
     
      }
   
   
   
    private void listDirContents(){
    ListView l=(ListView) findViewById(R.id.files_list);
    if(path!=null){
    try{
    File f=new File(path);
    if(f!=null){
    if(f.isDirectory()){
    String[] contents=f.list();
    if(contents.length>0){
    //create the data source for the list
    ListAdapterModel lm=new ListAdapterModel(this,R.layout.listlayout,R.id.label,contents,path);
    //supply the data source to the list so that they are ready to display
    l.setAdapter(lm);
    selectedFile=path;
    }
    else
    {
    //keep track the parent directory of empty directory
    path=f.getParent();
    }
    }
    else{
    //capture the selected file path
    selectedFile=path;
    //keep track the parent directory of the selected file
    path=f.getParent();
   
    }
    }
    }catch(Exception e){}
    }    
   
   
    }
   
    public void lockFolder(View view){
    EditText txtpwd=(EditText)findViewById(R.id.txt_input);
String pwd=txtpwd.getText().toString();
File f=new File(selectedFile);
if(pwd.length()>0){

if(f.isDirectory()){
BackTaskLock btlock=new BackTaskLock();
btlock.execute(pwd,null,null);

}
else{
MessageAlert.showAlert("It is not a folder.",context);
}
}
else{
MessageAlert.showAlert("Please enter password",context);
}
    }
   
    public void startLock(String pwd){
    Locker locker=new Locker(context,selectedFile,pwd);
locker.lock();
    }

    public void unlockFolder(View view){
    EditText txtpwd=(EditText)findViewById(R.id.txt_input);
String pwd=txtpwd.getText().toString();
File f=new File(selectedFile);
if(pwd.length()>0){

if(f.isFile()){

if(isMatched(pwd)){
BackTaskUnlock btunlock=new BackTaskUnlock();
btunlock.execute(pwd,null,null);
}
else{
MessageAlert.showAlert("Invalid password or folder not locked",context);
}

}

else{
MessageAlert.showAlert("Please select a locked folder to unlock",context);
}
}
else{
MessageAlert.showAlert("Please enter password",context);
}

    }
   
    public boolean isMatched(String pwd){
    boolean mat=false;
    Locker locker=new Locker(context, selectedFile, pwd);
byte[] pas=locker.getPwd();
int pwdRead=locker.bytearrayToInt(pas);
int pwdInput=locker.bytearrayToInt(pwd.getBytes());
if(pwdRead==pwdInput) mat=true;
return mat;
    }
   
    private class BackTaskLock extends AsyncTask<String,Void,Void>{  
    ProgressDialog pd;
    protected void onPreExecute(){
super.onPreExecute();
//show process dialog
pd = new ProgressDialog(context);
pd.setTitle("Locking the folder");
pd.setMessage("Please wait.");
pd.setCancelable(true);
pd.setIndeterminate(true);
pd.show();


}
protected Void doInBackground(String...params){    
try{

startLock(params[0]);

}catch(Exception e){
pd.dismiss();   //close the dialog if error occurs
}
return null;

}
protected void onPostExecute(Void result){
pd.dismiss();
goBack();
}


}
   
   
    public void startUnlock(String pwd){
    Locker locker=new Locker(context,selectedFile,pwd);
locker.unlock();
    }
 
   
    private class BackTaskUnlock extends AsyncTask<String,Void,Void>{  
    ProgressDialog pd;
    protected void onPreExecute(){
super.onPreExecute();
//show process dialog
pd = new ProgressDialog(context);
pd.setTitle("Unlocking the folder");
pd.setMessage("Please wait.");
pd.setCancelable(true);
pd.setIndeterminate(true);
pd.show();


}
protected Void doInBackground(String...params){  
try{

startUnlock(params[0]);

}catch(Exception e){
pd.dismiss();   //close the dialog if error occurs

}
return null;

}
protected void onPostExecute(Void result){
pd.dismiss();
listDirContents();//refresh the list
}


}
 
   
}


The content of the MainActivity.java file in the Folder Locker app is nearly the sample as the content of the MainActivity.java file in the File Locker app, except that the lockFile and unlockFile methods are changed to lockFolder to unlockFolder.

Again, in the onStart method of MainActivity class, the ListView component is registered to the item click event so that the ListView is responsive and update its contents when its item is selected. The listDirContents method is invoked to display files and directories in the /mnt directory. The selection style of the list is defined by the selection_style.xml file that is stored in the drawable directory.

selection_style.xml file

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
 
    <item>
        <shape>
            <gradient
                android:startColor="#dfdfdf"
                android:endColor="#dfdfdf"            
                android:angle="180" />  
        </shape>        
    </item>
</selector>


The lockFolder and unlockFoler methods are called when the user pushes the Lock and Unlock buttons. The locking and unlocking folder processes are wrapped in the AsncTask classes so that they can be performed in background without locking the user interface.

Before running the Folder Locker app, you need to take a look at the MessageAlert class. Simply, this class has the showAlert method to display the alert message to the user when he/she does not enter the password before locking or unlocking the folder, when the incorrect password is entered to unlocked the folder, and when the user tries to select a file instead of a folder to lock. The Folder Locker does allow the user to lock folder only.

MessageAlert.java file

package com.example.folderlock;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;

public class MessageAlert {
//This method will be invoked to display alert dialog
    public static void showAlert(String message,Context context){
   
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage(message);
        builder.setCancelable(true);
        builder.setPositiveButton("OK", new OnClickListener(){
        public void onClick(DialogInterface dialog, int which) {
          dialog.dismiss();
          }

        });
        AlertDialog dialog = builder.create();        
        dialog.show();
   
    }
}


Merge or Combine PDF, Txt, Images

Friday, October 18, 2013

Zipper

In this tutorial, you learn to create a Zipper for Android. The Zipper can be used to zip files and folders. The result of the compression is a zip file. The user also can use this app for extracting zip or jar files.

To zip a file or folder, firstly the user has to open the Zipper app. Then he/she will select the file or folder from the file chooser. By pushing the Compress button, the file or folder will be compressed in to a single zip file stored in the Zip folder of your external card.

compass app flashLight app

zip files and folders for android

To extract a zip file or jar file, the user can select the file from anywhere in Android and press the Extract button. Alternatively, the user can open Zipper app first and then select the zip file or jar file from the file chooser list. The extracted file or folder is stored in the Extract folder.

storage of the zipper in real device



Now open your Eclipse and create a new project called Zipper. In this app, we need one EditText to display the selected file or folder path and allow the user to enter the file or folder path. Two Buttons are needed. One is for extracting action and another is for compressing action. A ListView component will be used as a file chooser that displays files and folders for selection. These components are defined in the activity_main xml file that is the interface' elements resource of the MainActivity.class.

activity_main.xml file

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:orientation="vertical"

     >

  <EditText
        android:id="@+id/txt_input"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="text"
        android:hint="@string/txt_hint"
        />
        <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="horizontal"
             >
<Button
          android:id="@+id/bt_extract"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/bt_extract"
          android:onClick="extract"
          />
  <Button
          android:id="@+id/bt_compress"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/bt_compress"
          android:onClick="compress"
          />
   </LinearLayout>
  <TextView
          android:id="@+id/txt_view"
    android:layout_width="fill_parent"
          android:layout_height="wrap_content"
      />
        <ListView
            android:id="@+id/files_list"
            android:layout_width="fill_parent"
            android:layout_height="300dp"
            android:paddingBottom="5dp"
            android:paddingTop="5dp"
     
            />    

</LinearLayout>



In the activity_xml files, some string variables are used. These string variables are defined in the strings.xml file. This is the content of the strings.xml file.

strings.xml file

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Zipper</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="bt_extract">Extract</string>
    <string name="txt_hint">Type file path</string>
    <string name="bt_compress">Compress</string>
   <string name="icon_image">Icon</string>
</resources>


Again, the ListView displays both files and directories. Each item of the list contains two parts--icon and text. The icon can be file icon or folder icon. The text is the file name or folder name. The ListView must be customized so that its item can be displayed both icon and text. This can be done in two-steps process. The first step will define two components in the layout file of the list. One component is the ImageView and another is the TextView. The ImageView is for displaying the icon and the TextView displays the file name or directory name. Here is the content of the listlayout.xml file that is the layout file of the ListView.

listlayout.xml file

<?xml version="1.0" encoding="utf-8"?>
<!--  Single List Item Design -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="5dip" >

<ImageView
    android:id="@+id/icon"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:padding="5sp"
    android:contentDescription="@string/icon_image"
 />

<TextView
    android:id="@+id/label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10sp"
        android:textSize="20sp"
        android:textColor="#0000ff"
        android:textStyle="bold" >
</TextView>
</LinearLayout>


The last step will customize the ArrayAdapter class to supply icon image and text to the ListView. The ArrayAdapter object will be used as a data source of the ListView. Below is the ListAdapter class that extends the ArrayAdapter class and customize its getView method.

ListAdapterModel.java

package com.example.zipper;

import java.io.File;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;


public class ListAdapterModel extends ArrayAdapter<String>{
int groupid;
String[] names;
Context context;
String path;
public ListAdapterModel(Context context, int vg, int id, String[] names, String parentPath){
super(context,vg, id, names);
this.context=context;
groupid=vg;
this.names=names;
this.path=parentPath;
}
public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View itemView = inflater.inflate(groupid, parent, false);
        ImageView imageView = (ImageView) itemView.findViewById(R.id.icon);
        TextView textView = (TextView) itemView.findViewById(R.id.label);
        String item=names[position];
        textView.setText(item);
        File f=new File(path+"/"+item);
        if(f.isDirectory())
        imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.diricon));
        else
        imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.fileicon));
        return itemView;
}

}


Now we take a look at the MainActivity.java that defines the MainActivity class. The MainActivity class represents the main interface of the Zipper app. This is where the user interacts with the Zipper by entering file or folder path, pushing the Extract or Compress button, and select a file or folder from the file chooser.

MainActivity.java file

package com.example.zipper;

import java.io.File;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {

   private String pathintent="";
   private String path="";
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //get the intent object broadcast by Android
        Intent intent=getIntent();
        String action=intent.getAction();      
        String type =intent.getType();
        //get zip file path from intent
        if(Intent.ACTION_VIEW.equals(action) || Intent.ACTION_PICK.equals(action) && type!=""){        
        pathintent=intent.getData().getPath();
         }

    }

    protected void onStart(){
    super.onStart();
    regComponents();
    }
 
    protected void onResume(){
    super.onResume();
    //register the broadcast receiver to receive intents
    registerReceiver(receiverextract, new IntentFilter("com.example.zipper.extract"));
    registerReceiver(receivercompress, new IntentFilter("com.example.zipper.compress"));

    }
 
    protected void onPause(){
    super.onPause();
    //unregister the broadcast receivers
    unregisterReceiver(receiverextract);
    unregisterReceiver(receivercompress);

    }
    public void onBackPressed(){
    if(path.length()>1){ //up one level of directory structure
    File f=new File(path);
    path=f.getParent();
    EditText et=(EditText) findViewById(R.id.txt_input);
    et.setText(path); //update text box of path
    //listDirContents();
    }
    else{
   
    System.exit(0); //exit app
   
    }
    }

    private BroadcastReceiver receiverextract=new BroadcastReceiver(){
    public void onReceive(Context context,Intent intent){
   
        Bundle b=intent.getExtras();
        if(b!=null){
        TextView tv=(TextView)findViewById(R.id.txt_view);
        tv.setText(b.getString("BACKMESS"));
        }
    }
    };
 
    private BroadcastReceiver receivercompress=new BroadcastReceiver(){
    public void onReceive(Context context,Intent intent){
   
        Bundle b=intent.getExtras();
        if(b!=null){
        TextView tv=(TextView)findViewById(R.id.txt_view);
        tv.setText(b.getString("BACKMESS"));
        }
    }
    };

 
 
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
 
    public void regComponents(){
EditText et=(EditText) findViewById(R.id.txt_input);
if(et!=null){
et.addTextChangedListener(new ChangeListener());
if(pathintent.length()>0)
et.setText(pathintent);
else{
path=Environment.getExternalStorageDirectory().getPath();
et.setText(path);
}
ListView lv=(ListView) findViewById(R.id.files_list);
lv.setSelector(R.drawable.selection_style);
lv.setOnItemClickListener(new ClickListener());
}
}
 
class ChangeListener implements TextWatcher{
   
    public void beforeTextChanged(CharSequence s, int start, int before, int count){
   
   
    }
   
    public void onTextChanged(CharSequence s, int start, int before, int count){
    EditText et=(EditText) findViewById(R.id.txt_input);
    path=et.getText().toString(); //capture file path    
    listDirContents();//update list
    }
   
    public void afterTextChanged(Editable ed){
   
   
    }
    }
 
    class ClickListener implements OnItemClickListener{
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
      // selected item      
            ViewGroup vg=(ViewGroup)view;
      String selectedItem = ((TextView) vg.findViewById(R.id.label)).getText().toString();
            EditText et=(EditText) findViewById(R.id.txt_input);
            path=path+"/"+selectedItem;
            et.setText(path); //update file path          
           
      }
      public void onNothingSelected(AdapterView<?> parent){
     
      }
     
     
      }  
 
 
    public void listDirContents(){
    ListView l=(ListView) findViewById(R.id.files_list);
    if(path!=null){
    try{
    File f=new File(path);
    if(f!=null){
    if(f.isDirectory()){
    String[] contents=f.list();
    if(contents.length>0){
    ListAdapterModel lm=new ListAdapterModel(this,R.layout.listlayout,R.id.label,contents,path);
    l.setAdapter(lm);
    }
    else
    {  //keep tract the parent folder of empty directory
    path=f.getParent();
    }
    }
    else{
    //keep tract the parent folder of the selected file
    path=f.getParent();
    }
    }
    }catch(Exception e){}
    }    
 
   
    }
//This method will be invoked to detect the zip and jar file types
public boolean isZipFile(String file){

boolean isZip=false;
String extension = MimeTypeMap.getFileExtensionFromUrl(file);
File f=new File(file);
if(f.isFile()){
String mimeType=MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if(mimeType!=null){
if(mimeType.endsWith("zip")) //detect zip file
isZip=true;
}
else{
if (file.endsWith(".jar")) //detect jar file
isZip=true;
}
}
        return isZip;
}


    public void extract(View view){
    TextView tv=(TextView)findViewById(R.id.txt_view);
    EditText et=(EditText)findViewById(R.id.txt_input);
    String txtpath=et.getText().toString();
    if(txtpath.length()>0){
    if(isZipFile(txtpath)){
    tv.setText("Please wait...");
    //create intent object and set it to the extracting service object
    Intent newIntent=new Intent(this,ExtractingService.class);
    newIntent.putExtra(ExtractingService.FILEPATH,txtpath);
    newIntent.putExtra(ExtractingService.DESPATH,Environment.getExternalStorageDirectory()+"/Extract");
    startService(newIntent);
    }
    else{
    showAlert("This is not a zip file.");
    }
    }
    else{
    showAlert("Please enter or select file path.");
    }

    }
 
 

    public void compress(View view){
    TextView tv=(TextView)findViewById(R.id.txt_view);
    EditText et=(EditText)findViewById(R.id.txt_input);
    String txtpath=et.getText().toString();
    if(txtpath.length()>0){
    tv.setText("Please wait...");
    //create intent object and set it to the zipping service object
    Intent newIntent=new Intent(this,ZippingService.class);
    newIntent.putExtra(ZippingService.FILEPATH,txtpath);
    newIntent.putExtra(ZippingService.DESPATH,Environment.getExternalStorageDirectory()+"/Zip");
   
    startService(newIntent);
    }
    else{
    showAlert("Please enter or select file path.");
    }

    }
    public void showAlert(String message){
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(message);
        builder.setCancelable(true);
        builder.setPositiveButton("OK", new OnClickListener(){
        public void onClick(DialogInterface dialog, int which) {
          dialog.dismiss();
          }

        });
        AlertDialog dialog = builder.create();      
        dialog.show();
   }
 
}


In the onCreate method of the MainActivity class, the getIntent method is invoked to receive the intent object broadcast by Android. The intent object contains the zip or jar file path that the user selected from anywhere on Android. This file path will be displayed in the text box. The intent-filters are used to allow the Zipper app to receive the data sent by Android system. The intent-filters are defined in the AndroidManifest.xml file. This is the content of the AndroidManifest file for the Zipper app.

AndroidManifest.xml file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.zipper"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
    <application
        android:allowBackup="true"
        android:icon="@drawable/zipper"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity android:configChanges="orientation"          
            android:name="com.example.zipper.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
            <data android:scheme="file"/>
            <data android:mimeType="*/*"/>
            <data android:pathPattern=".*\\.zip"/>
            <data android:host="*"/>
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
            <data android:scheme="file"/>
            <data android:mimeType="*/*"/>
            <data android:pathPattern=".*\\.jar"/>
            <data android:host="*"/>
        </intent-filter>
       
       
        </activity>
        <service
android:name="ExtractingService"
android:icon="@drawable/ic_launcher"
android:label="MYSERVICE">
</service>

        <service
android:name="ZippingService"
android:icon="@drawable/ic_launcher"
android:label="MYSERVICE1">
</service>      
     
    </application>

</manifest>


You might want to read WebDownloader page to learn more about intent filers.

In the onStart method, the regComponents method is called to register the EditText to the change event listener and the ListView to the item click event listener.

In the onResume method, two broadcast receivers are registered with the current context to receive the intent objects that will be sent from Intent Services. One receiver, receiverextract will receive intent object sent by the extracting intent service and another one, receivercompress receives intent sent by the compressing or zipping service. A broadcast receiver is defined by using the BroadcastReceiver class. You need to override its onReceive method to get the intent object sent by an intent service.

The extract method will be invoked when the user pushes the Extract button to extract the selected zip or jar file. This method calls the isZipFile method to detect the zip or jar file to make sure that other types of files are not extracted. As the text box is not blank and the desired file is selected, the intent object is created to wrap the selected file path and the destination folder (folder to store the extracted file). This intent object is sent to the extracting service by calling the startService method. The extracting service that will receive the intent object is called ExtractingService defined in the ExtractingService class that extends the IntentService class. Here is the content of the ExtractingService class.

ExtractingService.java file

package com.example.zipper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;

public class ExtractingService extends IntentService {
public static final String FILEPATH="FILEPATH";
public static final String DESPATH="DESPATH";
private String feedback="";
public ExtractingService() {
super("SERVICE");
// TODO Auto-generated constructor stub
}

public void onHandleIntent(Intent intent){
//receive information sent from the MainAcivity
Bundle b=intent.getExtras();
String filepath="";
String despath="";
if(b!=null){
filepath=b.getString(FILEPATH);
despath=b.getString(DESPATH);
extractFiles(filepath,despath);

}


}

public void extractFiles(String srcfile, String despath){
ZipFile zf=null;
    try {
zf=new ZipFile(srcfile); //create  a zip file object
if(zf.size()>0){ //read through the zip file
Enumeration<ZipEntry> entries=(Enumeration<ZipEntry>) zf.entries();
while(entries.hasMoreElements()){
ZipEntry entry=entries.nextElement();
if(!entry.isDirectory() && !entry.getName().endsWith("/")){
//start extracting the files
extract(zf.getInputStream(entry),entry.getName(),despath);

}

}

}

feedback="Complete";

} catch (IOException e) {

e.printStackTrace();

}finally{
if(zf!=null)
try {
zf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//send feedback message to the broadcast receiver
if(feedback.length()<=0)
feedback="Can't not extract the file";
Intent backIntent=new Intent("com.example.zipper.extract");
backIntent.putExtra("BACKMESS", feedback);
sendBroadcast(backIntent);
}
    }
 
public void extract(InputStream is, String fname, String storeDir){

FileOutputStream fos;
File fi=new File(storeDir+File.separator+fname); //output file
File fparent=new File(fi.getParent());
fparent.mkdirs();//create parent directories for output files

try {

fos=new FileOutputStream(fi);
int content=0;
while((content=is.read())!=-1){
fos.write(content);
}
is.close();
fos.close();
} catch (Exception e) {

e.printStackTrace();
}

}

}


Immediately as the ExteractingService receives the intent object sent from the MainActivity, the extracting process begins to extract the content of the file path to store in the destination folder by invoking the extractFiles method . In this method, the ZipFile class of Java is used to read the content of the zip file. Each file or folder is presented by a ZipEntry object. You can get all ZipEntries by using the entries method of the ZipFile. The ZipEntry has the getInputStream method that returns an InputStream object in which you can get its content out. When the extracting process finishes, an intent object is created to wrap the feedback message that will be sent back to the MainActivity.

The compress method will be invoked to compress the file or folder when the user pushes the Compress button. The selected file or folder path and the destination path (folder path to store the zip file) to the ZippingService intent service. Once these information received the compression process begins by calling the doCompression method. To write content of a file or folder to a zip output file you can use the ZipOutputStream. The user might select a file or folder to compress. If the selected path is a file, the comrpessFile method will be called to read the file content and output it to the zip output file. If the selected path is a folder, the compressDir method will be called to compress the folder. The folder might contain many files and sub folders. To compress all files and sub folders in the folder, the recursive process is needed to traverse the folder hierarchy.

ZippingService.java file

package com.example.zipper;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class ZippingService extends IntentService {
public static final String FILEPATH="FILEPATH";
public static final String DESPATH="DESPATH";

public ZippingService() {
super("SERVICE");
// TODO Auto-generated constructor stub
}

public void onHandleIntent(Intent intent){
//receive information sent from the MainAcivity
Bundle b=intent.getExtras();
String filepath="";
String despath="";
if(b!=null){
filepath=b.getString(FILEPATH);
despath=b.getString(DESPATH);
doCompression(filepath,despath);

}

}

public void doCompression(String src,String despath){
File f=new File(src);
File foutdir=new File(despath);
if(!foutdir.exists()) foutdir.mkdir();
ZipOutputStream zos=null;
try{
//create ZipOutputStream object to write to output zip file
zos=new ZipOutputStream(new FileOutputStream(foutdir.getPath()+"/"+getName(src)+".zip"));
if(f.exists()){
String path=getPath(f.getPath());
if(f.isFile()){
compressFile(f.getPath(),path,zos);
}
else{ //source is a directory
File[] files=f.listFiles();
for(File sf:files){
compressDir(sf.getPath(),path,zos);
}
}


}
else{
Log.e("Error","Source not found!");
}
zos.close();
                //send the feed back message to the MainActivity
String feedback="Complete";
Intent backIntent=new Intent("com.example.zipper.compress");
backIntent.putExtra("BACKMESS", feedback);
sendBroadcast(backIntent);

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

}
public String getPath(String srcpath){

String path="";
if(srcpath.endsWith(File.separator)){
path=srcpath.substring(0,srcpath.length()-1);
path=path.substring(path.lastIndexOf(File.separator)+1);
}
else
path=srcpath.substring(srcpath.lastIndexOf(File.separator)+1);
return path;
}

public String getName(String srcpath){
String fname;
fname=srcpath.substring(srcpath.lastIndexOf("/")+1);
if(fname.contains("."))
fname=fname.substring(0, fname.lastIndexOf("."));
return fname;
}
public void compressDir(String srcpath, String path, ZipOutputStream zos){
File fsrcdir=new File(srcpath);
String rpath=getPath(srcpath);
if(fsrcdir.isDirectory()){
try {

rpath=path+File.separator+rpath;
zos.putNextEntry(new ZipEntry(rpath+File.separator));
zos.closeEntry();
File[] files=fsrcdir.listFiles();
for(File f:files){
if(f.isDirectory()){
compressDir(f.getPath(),rpath,zos);
}
else{
compressFile(f.getPath(),rpath,zos);
}
}

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
compressFile(srcpath,path,zos);
}
}

public void compressFile(String srcfile, String path,ZipOutputStream zos){
//write a new entry to the zip file
String rpath=getPath(srcfile);
try {
FileInputStream fis=new FileInputStream(srcfile);
int content=0;
zos.putNextEntry(new ZipEntry(path+File.separator+rpath));
while((content=fis.read())!=-1){
zos.write(content);
}
zos.closeEntry();
fis.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}

Now you are ready to run and test the Zipper for Android app. If you want to download the apk file from here, click the link below. If you have any questions, please write them at the comment section.