Android Open Source - Android-Backup Core






From Project

Back to project page Android-Backup.

License

The source code is released under:

GNU General Public License

If you think the Android project Android-Backup listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.Akkad.AndroidBackup;
//  www  .ja  v a2 s  .c  om
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeoutException;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.util.Log;
import android.widget.Toast;

import com.stericson.RootTools.Command;
import com.stericson.RootTools.CommandCapture;
import com.stericson.RootTools.RootTools;
import com.stericson.RootTools.RootToolsException;

/**
 * Class that provides the core functionality of Android Backup used to backup and restore applications
 * 
 * @author Raafat Akkad
 */
public class Core extends Activity {
  private final static String DATA_DIRECTORY = "/data/data/";
  private static String output;

  private static final String TAG = "Android Backup Core";

  /**
   * Generates a files md5 sum
   * 
   * @param filePath
   *            the filepath for the file that you want to generate an md5 sum for
   * @return the md5 sum of the file
   */
  private static String generateMD5Sum(String filePath) {
    output = "";
    try {
      RootTools.closeAllShells();
    } catch (IOException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    }

    CommandCapture command = new CommandCapture(0, "md5sum " + filePath) {

      public void output(int id, String line) {
        if (!line.equals("")) {
          output = line;
        }
      }
    };
    try {
      RootTools.getShell(true).add(command).waitForFinish();
    } catch (InterruptedException e) {
      return "";
    } catch (IOException e) {
      return "";
    } catch (TimeoutException e) {
      return "";
    }

    // Check for errors
    if (output.toLowerCase().contains("could not read file") || output.toLowerCase().contains("it's a directory") || output.toLowerCase().contains("is a directory") || !output.split("  ")[1].equals(filePath) || output.equals("")) {
      Log.e(TAG, "Could not generate md5 as the file couldn't be read or it's a directory");
      return "";
    } else {
      return output.split("  ")[0]; // Returns the md5 sum
    }
  }

  /**
   * 
   * @param packageName
   *            package name of the app to be killed
   * @return if the app was killed
   */
  public static boolean killApp(String packageName) {
    CommandCapture command = new CommandCapture(0, "kill `busybox pidof " + packageName + "`");
    try {
      RootTools.getShell(true).add(command).waitForFinish();
    } catch (Exception e) {
      return false;
    }
    return true;

  }

  /**
   * Restores Application Data
   * 
   * @param packageName
   *            the package name of the data backup
   * @param md5
   *            the checksum of the data backup
   * @param dataBackupPath
   *            the location of the data backup that is to be restored
   * @return if the restore was successful
   */
  public static boolean restoreApplicationData(String packageName, String md5, String dataBackupPath) {
    if (!md5.equals("") && md5.equals(generateMD5Sum(dataBackupPath))) { // Checks that the data backup matches its md5
      if (wipeAppData(packageName)) { // kill app and wipe data
        CommandCapture command = new CommandCapture(0, "su", "cd " + DATA_DIRECTORY, "tar -xzvf " + dataBackupPath);
        try {
          RootTools.getShell(true).add(command).waitForFinish();
        } catch (InterruptedException e) {
          Log.e(TAG, "Could not restore " + packageName + "'s Data");
          return false;
        } catch (IOException e) {
          Log.e(TAG, "Could not restore " + packageName + "'s Data");
          return false;
        } catch (TimeoutException e) {
          Log.e(TAG, "Could not restore " + packageName + "'s Data");
          return false;
        }
      }
    } else {
      Log.e(TAG, "Backup md5 does not match");
      return false; // md5 is incorrect so the data of the app will not be restored
    }
    return true; // App data has been restored
  }

  /**
   * Wipes the Apps data located in /data/data/com.packageName
   * 
   * @param packageName
   *            The packageName of the app that will have its data wiped
   */
  public static boolean wipeAppData(String packageName) {
    if (killApp(packageName)) {
      CommandCapture command = new CommandCapture(0, "pm disable " + packageName, "rm -r " + DATA_DIRECTORY + packageName + "/*", "pm enable " + packageName);
      try {
        RootTools.getShell(true).add(command).waitForFinish();
      } catch (Exception e) {
        return false;
      }
    } else {
      return false;
    }
    return true;
  }

  /**
   * @param apkLocation
   *            the location of the App
   * @return if the App is a System App
   */
  public short applicationsType(String apkLocation) {
    if (apkLocation.toLowerCase().contains("/data/app")) {
      return 0; // Normal App
    } else if (apkLocation.toLowerCase().contains("/system/app")) {
      return 1; // System App
    } else {
      return 2; // Normal App on SD Card
    }
  }

  /**
   * Backups the application apk, data and creates an information text file which stores information about the file
   * 
   * @param packageName
   * @param apkLocation
   * @return
   */
  public boolean backupApplication(ApplicationInfo selectedApp, PackageManager pm) {
    Calendar calendar = Calendar.getInstance();

    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd-HHmmss");
    String formattedDate = formatter.format(calendar.getTime()); // Date is saved so it is the same for the backed up apk, data and app information

    String backedUpApkMD5 = backupApplicationApk(selectedApp.packageName, selectedApp.sourceDir, formattedDate);
    String backedUpDataMD5 = backupApplicationData(selectedApp.packageName, formattedDate);

    if (!backedUpApkMD5.equals("") && !backedUpDataMD5.equals("")) {
      Backup backup = new Backup(calendar, "" + selectedApp.loadLabel(pm), selectedApp.packageName, selectedApp.targetSdkVersion, backedUpApkMD5, backedUpDataMD5, applicationsType(selectedApp.sourceDir));
      backup.saveBackupInformation();
      return true;
    } else {
      Toast.makeText(getParent(), "Backup Failed", Toast.LENGTH_SHORT).show();

      /* Delete the backups that were made */
      String apkBackupLocation = BackupStore.getBackupFolderLocation() + selectedApp.packageName + "-" + formattedDate + ".apk";
      String appDateBackupLocation = BackupStore.getBackupFolderLocation() + selectedApp.packageName + "-" + formattedDate + ".tar.gz";

      CommandCapture command = new CommandCapture(0, "rm " + apkBackupLocation, "rm " + appDateBackupLocation);

      try {
        RootTools.getShell(true).add(command).waitForFinish();
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (TimeoutException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      return false;
    }
  }

  public String backupApplicationApk(String packageName, String apkLocation, String formattedDate) {
    File apk = new File(apkLocation);
    if (apk.length() <= InformationFragment.getExternalStorageFreeSpace()) { // Checks that there is enough free space on the sd card
      String apkBackupLocation = BackupStore.getBackupFolderLocation() + packageName + "-" + formattedDate + ".apk";
      RootTools.copyFile(apkLocation, apkBackupLocation, false, false);

      String installedAPKMD5 = generateMD5Sum(apkLocation);
      String backupAPKMD5 = generateMD5Sum(apkBackupLocation);

      if (!backupAPKMD5.equals("") && backupAPKMD5.equals(installedAPKMD5)) {
        return backupAPKMD5;
      } else {
        Log.e(TAG, "MD5 do not match");
        return "";
      }
    } else {
      return "";
    }

  }

  /**
   * Backs up the package names data into a tar.gz and returns its msd5 sum
   * 
   * @param packageName
   *            the packageName data to be backed up
   * @param formattedDate
   *            the date the data was backed up
   * @return the md5 sum of the backed up data
   */
  public String backupApplicationData(String packageName, String formattedDate) {
    // CommandCapture command = new CommandCapture(0, "su", "tar -zcvf " + BackupStore.getBackupFolderLocation() + packageName + "-" + formattedDate + ".tar.gz" + " " + DATA_DIRECTORY + packageName);
    CommandCapture command = new CommandCapture(0, "cd " + DATA_DIRECTORY, "tar -czvf " + BackupStore.getBackupFolderLocation() + packageName + "-" + formattedDate + ".tar.gz " + packageName); // TODO is packagename needed?
    // TODO check using pwd that it's in the correct directory
    try {
      RootTools.getShell(true).add(command).waitForFinish();
    } catch (InterruptedException e) {
      return "";
    } catch (IOException e) {
      return "";
    } catch (TimeoutException e) {
      return "";
    }
    return generateMD5Sum(BackupStore.getBackupFolderLocation() + packageName + "-" + formattedDate + ".tar.gz");
  }

  /**
   * Checks if the process is running
   * 
   * @param processName
   *            The process that you want to check is running
   * @return If the process is running
   */
  public boolean isNamedProcessRunning(String processName) {
    if (processName == null) { // The processName is empty
      Log.e(TAG, "The process name doesn't exist");
      return false;
    }
    ActivityManager manager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    List<RunningAppProcessInfo> processes = manager.getRunningAppProcesses(); // Gets the list of running processes

    for (RunningAppProcessInfo process : processes) { // Loops through processes
      if (processName.equals(process.processName)) { // Checks if the process is part of the running process list
        Log.e(TAG, "The process is running");
        return true; // process is running
      }
    }
    Log.e(TAG, "The process is not running");
    return false; // process is not running
  }

  /**
   * Mounts the System partition as Read-Only
   */
  private boolean mountSystemasRO() throws IOException, RootToolsException, TimeoutException {
    return RootTools.remount("/system", "ro");
  }

  /**
   * Mounts the System partition as Read/Write
   */
  private boolean mountSystemasRW() {
    return RootTools.remount("/system", "rw");
  }

  /**
   * Reboots the device
   */
  public void rebootDevice() {
    CommandCapture command = new CommandCapture(0, "reboot");
    try {
      RootTools.getShell(true).add(command).waitForFinish();
    } catch (Exception e) {
      return;
    }
  }

  /**
   * Uninstalls an application using root permissions to prevent an uninstall prompt and to remove system applications
   * 
   * TODO clean Dalvik Cache for uninstalled application
   * 
   * @param packageName
   * @param apkLocation
   */
  public boolean UninstallAppRoot(String packageName, String apkLocation) {
    if (killApp(packageName)) {

      wipeAppData(packageName);

      if (applicationsType(apkLocation) == 1) // A System App
      {
        if (!mountSystemasRW()) { // Mounts System/ as read/write
          Log.d(TAG, "Couldn't mount /System as RW");
          return false;
        }
      }

      CommandCapture command = new CommandCapture(0, "pm disable " + packageName, "rm " + apkLocation, "pm uninstall " + packageName);

      try {
        RootTools.getShell(true).add(command).waitForFinish();
      } catch (InterruptedException e) {
        return false;
      } catch (IOException e) {
        return false;
      } catch (TimeoutException e) {
        return false;
      }

      if (applicationsType(apkLocation) == 1) // A System App
      {
        try {
          mountSystemasRO(); // remounts /System as read only
        } catch (Exception e) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * Wipes the Dalvik Cache and reboots the device
   * 
   * @return if the Dalvik Cache was wiped
   */
  public void wipeDalvikCache() {
    if (RootTools.remount("/cache", "rw")) { // checks if /cache is mounted as writable
      CommandCapture command = new CommandCapture(0, "rm -r /data/dalvik-cache/*", "rm -r /cache/dalvik-cache/*", "rm -r /cache/dc/*", "reboot");
      try {
        RootTools.getShell(true).add(command).waitForFinish();
      } catch (Exception e) {
        return;
      }
    }
  }
}




Java Source Code List

com.Akkad.AndroidBackup.AndroidBackupActivity.java
com.Akkad.AndroidBackup.AppInfoAdapter.java
com.Akkad.AndroidBackup.ApplicationsFragment.java
com.Akkad.AndroidBackup.BackupListAdapter.java
com.Akkad.AndroidBackup.BackupStore.java
com.Akkad.AndroidBackup.Backup.java
com.Akkad.AndroidBackup.Core.java
com.Akkad.AndroidBackup.InformationFragment.java
com.Akkad.AndroidBackup.ScheduleFragment.java
com.Akkad.AndroidBackup.TabsPagerAdapter.java
com.Akkad.AndroidBackup.TasksFragment.java