com.Candy.sizer.CandySizer.java Source code

Java tutorial

Introduction

Here is the source code for com.Candy.sizer.CandySizer.java

Source

/*=========================================================================
 *
 *  PROJECT:  SlimRoms
 *            Team Slimroms (http://www.slimroms.net)
 *
 *  COPYRIGHT Copyright (C) 2013 Slimroms http://www.slimroms.net
 *            All rights reserved
 *
 *  LICENSE   http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
 *
 *  AUTHORS:     fronti90
 *  DESCRIPTION: SlimSizer: manage your apps
 *
 *=========================================================================
 */
package com.Candy.sizer;

import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;

import com.candykat.ota.R;

public class CandySizer extends Fragment {
    private final int STARTUP_DIALOG = 1;
    private final int DELETE_DIALOG = 2;
    private final int DELETE_MULTIPLE_DIALOG = 3;
    private final int REBOOT_DIALOG = 4;
    protected ArrayAdapter<String> adapter;
    private ArrayList<String> mSysApp;
    private boolean startup = true;
    public final String systemPath = "/system/app/";
    protected Process superUser;
    protected DataOutputStream dos;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slim_sizer, container, false);
        return view;
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        showSuperuserRequest();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        final ImageView delButton = (ImageView) getView().findViewById(R.id.btn_delete);
        final ImageView profileButton = (ImageView) getView().findViewById(R.id.btn_profile);

        if (delButton == null) {
            return;
        }

        // create arraylist of apps not to be removed
        final ArrayList<String> safetyList = new ArrayList<String>();
        safetyList.add("BackupRestoreConfirmation.apk");
        safetyList.add("CertInstaller.apk");
        safetyList.add("Contacts.apk");
        safetyList.add("ContactsProvider.apk");
        safetyList.add("DefaultContainerService.apk");
        safetyList.add("DownloadProvider.apk");
        safetyList.add("DrmProvider.apk");
        safetyList.add("MediaProvider.apk");
        safetyList.add("Mms.apk");
        safetyList.add("PackageInstaller.apk");
        safetyList.add("Phone.apk");
        safetyList.add("Settings.apk");
        safetyList.add("SettingsProvider.apk");
        safetyList.add("CandyOTA.apk");
        safetyList.add("Superuser.apk");
        safetyList.add("SystemUI.apk");
        safetyList.add("TelephonyProvider.apk");

        // create arraylist from /system/app content
        File system = new File(systemPath);
        String[] sysappArray = system.list();
        mSysApp = new ArrayList<String>(Arrays.asList(sysappArray));

        // remove "apps not to be removed" from list and sort list
        mSysApp.removeAll(safetyList);
        Collections.sort(mSysApp);

        // populate listview via arrayadapter
        adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_multiple_choice,
                mSysApp);

        final ListView lv = (ListView) getView().findViewById(R.string.listsystem);
        lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        lv.setAdapter(adapter);

        // longclick an entry
        lv.setOnItemLongClickListener(new OnItemLongClickListener() {
            public boolean onItemLongClick(AdapterView<?> arg0, View arg1, final int arg2, long arg3) {
                // create deletion dialog
                String item = lv.getAdapter().getItem(arg2).toString();
                showDialog(DELETE_DIALOG, item, adapter, 0);
                return false;
            }
        });
        // click button delete
        delButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // check which items are selected
                String item = null;
                int itemCounter = 0;
                SparseBooleanArray checked = lv.getCheckedItemPositions();
                for (int i = lv.getCount() - 1; i > 0; i--) {
                    if (checked.get(i)) {
                        item = mSysApp.get(i);
                        itemCounter++;
                    }
                }
                if (item == null) {
                    toast(getResources().getString(R.string.sizer_message_noselect));
                    return;
                } else {
                    showDialog(DELETE_MULTIPLE_DIALOG, item, adapter, itemCounter);
                }
            }
        });
        // click button profile
        profileButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // call select dialog
                selectDialog(mSysApp, adapter);
            }
        });
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onResume() {
        super.onResume();
        showSuperuserRequest();
    }

    private void showSuperuserRequest() {
        if (this.getUserVisibleHint() && adapter != null && startup) {
            showDialog(STARTUP_DIALOG, null, adapter, 0);
            startup = false;
        }
    }

    private void showDialog(int id, final String item, final ArrayAdapter<String> adapter, int itemCounter) {
        // startup dialog
        final AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());

        if (id == STARTUP_DIALOG) {
            // create warning dialog
            alert.setMessage(R.string.sizer_message_startup).setTitle(R.string.caution).setCancelable(true)
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // action for ok
                            dialog.cancel();
                        }
                    });
            // delete dialog
        } else if (id == DELETE_DIALOG) {
            alert.setMessage(R.string.sizer_message_delete)
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // action for ok
                            // call delete
                            new CandySizer.SlimDeleter().execute(item);
                            // remove list entry
                            adapter.remove(item);
                            adapter.notifyDataSetChanged();
                        }
                    }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // action for cancel
                            dialog.cancel();
                        }
                    });
        } else if (id == DELETE_MULTIPLE_DIALOG) {
            String message;
            if (itemCounter == 1) {
                message = getResources().getString(R.string.sizer_message_delete_multi_one);
            } else {
                message = getResources().getString(R.string.sizer_message_delete_multi);
            }
            alert.setMessage(message).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    final ListView lv = (ListView) getView().findViewById(R.string.listsystem);
                    ArrayList<String> itemsList = new ArrayList<String>();
                    SparseBooleanArray checked = lv.getCheckedItemPositions();
                    for (int i = lv.getCount() - 1; i > 0; i--) {
                        if (checked.get(i)) {
                            String appName = mSysApp.get(i);
                            itemsList.add(appName);
                            // remove list entry
                            lv.setItemChecked(i, false);
                            adapter.remove(appName);
                        }
                    }
                    adapter.notifyDataSetChanged();
                    new CandySizer.SlimDeleter().execute(itemsList.toArray(new String[itemsList.size()]));
                }
            }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    // action for cancel
                    dialog.cancel();
                }
            });
        } else if (id == REBOOT_DIALOG) {
            // create warning dialog
            alert.setMessage(R.string.reboot).setTitle(R.string.caution).setCancelable(true)
                    .setPositiveButton(R.string.reboot_ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // action for ok
                            try {
                                dos.writeBytes("reboot");
                                dos.flush();
                                dos.close();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }).setNegativeButton(R.string.reboot_cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // action for cancel
                            dialog.cancel();
                        }
                    });
        }
        // show warning dialog
        alert.show();
    }

    // profile select dialog
    private void selectDialog(final ArrayList<String> sysAppProfile, final ArrayAdapter<String> adapter) {
        AlertDialog.Builder select = new AlertDialog.Builder(getActivity());
        select.setItems(R.array.slimsizer_profile_array, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                // The 'which' argument contains the index position
                // of the selected item
                short state = sdAvailable();
                File path = new File(Environment.getExternalStorageDirectory() + "/Slim");
                File savefile = new File(path + "/slimsizer.stf");
                if (which == 0) {
                    // load profile action
                    if (state >= 1) {
                        String profile;
                        try {
                            // read savefile and create arraylist
                            profile = new Scanner(savefile, "UTF-8").useDelimiter("\\A").next();
                            ArrayList<String> profileState = new ArrayList<String>(
                                    Arrays.asList(profile.split(", ")));
                            // create arraylist of unique entries in
                            // sysAppProfile (currently installed apps)
                            ArrayList<String> deleteList = new ArrayList<String>();
                            for (String item : sysAppProfile) {
                                if (!profileState.contains(item)) {
                                    deleteList.add(item);
                                }
                            }
                            // delete all entries in deleteList
                            ArrayList<String> itemsList = new ArrayList<String>();
                            for (int i = deleteList.size() - 1; i > 0; i--) {
                                String item = deleteList.get(i);
                                itemsList.add(item);
                                // remove list entry
                                adapter.remove(item);
                            }
                            adapter.notifyDataSetChanged();
                            new CandySizer.SlimDeleter().execute(itemsList.toArray(new String[itemsList.size()]));
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }
                    } else {
                        toast(getResources().getString(R.string.sizer_message_sdnoread));
                    }
                } else if (which == 1) {
                    // save profile action
                    if (state == 2) {
                        try {
                            // create directory if it doesnt exist
                            if (!path.exists()) {
                                path.mkdirs();
                            }
                            // create string from arraylists
                            String lists = sysAppProfile.toString();
                            lists = lists.replace("][", ",");
                            lists = lists.replace("[", "");
                            lists = lists.replace("]", "");
                            // delete savefile if it exists (overwrite)
                            if (savefile.exists()) {
                                savefile.delete();
                            }
                            // create savefile and output lists to it
                            FileWriter outstream = new FileWriter(savefile);
                            BufferedWriter save = new BufferedWriter(outstream);
                            save.write(lists);
                            save.close();
                            // check for success
                            if (savefile.exists()) {
                                toast(getResources().getString(R.string.sizer_message_filesuccess));
                            } else {
                                toast(getResources().getString(R.string.sizer_message_filefail));
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } else {
                        toast(getResources().getString(R.string.sizer_message_sdnowrite));
                    }
                }
            }
        });
        select.show();
    }

    public void toast(String text) {
        // easy toasts for all!
        Toast toast = Toast.makeText(getView().getContext(), text, Toast.LENGTH_SHORT);
        toast.show();
    }

    public short sdAvailable() {
        // check if sdcard is available
        // taken from developer.android.com
        short mExternalStorageAvailable = 0;
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // We can read and write the media
            mExternalStorageAvailable = 2;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            // We can only read the media
            mExternalStorageAvailable = 1;
        } else {
            // Something else is wrong. It may be one of many other states, but
            // all we need
            // to know is we can neither read nor write
            mExternalStorageAvailable = 0;
        }
        return mExternalStorageAvailable;
    }

    // mount /system as ro on close
    protected void onStop(Bundle savedInstanceState) throws IOException {
        try {
            dos.writeBytes("\n" + "mount -o remount,ro /system" + "\n");
            dos.writeBytes("\n" + "exit" + "\n");
            dos.flush();
            dos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class SlimDeleter extends AsyncTask<String, String, Void> {

        private ProgressDialog progress;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            if (dos == null) {
                try {
                    superUser = new ProcessBuilder("su", "-c", "/system/xbin/ash").start();
                    dos = new DataOutputStream(superUser.getOutputStream());
                    dos.writeBytes("\n" + "mount -o remount,rw /system" + "\n");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            progress = new ProgressDialog(getView().getContext());
            progress.setTitle(getString(R.string.delete_progress_title));
            progress.setMessage(getString(R.string.delete_progress));
            progress.show();
        }

        protected Void doInBackground(String... params) {
            for (String appName : params) {
                try {
                    dos.writeBytes("\n" + "rm -rf '" + systemPath + appName + "'\n");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void param) {
            super.onPreExecute();
            try {
                dos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            progress.dismiss();
            showDialog(REBOOT_DIALOG, null, adapter, 0);
        }
    }
}