2 votos

¿Existe una herramienta no-app para el backup por lotes de archivos APK?

Como las otras veces, una respuesta a mi pregunta no deberá contemplar una app de la Play Store, o de cualquier otra fuente. Lo que yo busco, es una herramienta capaz de copia de seguridad de usuario de las aplicaciones, aplicaciones del sistema o de ambas categorías, cuando se inicia desde dentro de un trabajo de sistema operativo Android.

Copia de seguridad de las apps externos de los datos no es relevante. La única cosa que cuenta, es la capacidad de proceso por lotes de copia de seguridad de la base.apk archivo, se encuentra en cada uno de /data/app/appName/ directorio, en fin para mí ser capaz de volver a instalarlo, ya sea para volver a una versión anterior, o instalar desde cero.

Por último, yo preferiría que la herramienta para ser libremente personalizable (por ejemplo, no compilado). Tal vez algo parecido a un script de shell?

5voto

Aquí está mi renovado script, que ahora se llama la NEMRIS, que responde a la pregunta. Como de costumbre, es libremente editable por cualquier persona, y sh-compatible como bien, lo que significa que se puede ejecutar desde el shell de Android.

En realidad, la secuencia de comandos depende de la aapt utilidad, puede discernir si la utilidad está instalado, es capaz de determinar si el backupDir y appsToBackup variables están vacíos o no y, si lo son, se establece los valores predeterminados en lugar de abortar.

Aún así, la fecha binario no puede determinar su verdadera zona horaria, por lo que todo el mundo debería editar manualmente su TZ variable.

Una vez que ha sido corrió por primera vez, la herramienta es capaz de discernir si un APK ya ha sido respaldado o no, haciendo uso de una matriz llena de sumas de comprobación MD5. Espero que puede resultar muy útil.


#!/system/bin/sh

#This variable is used to calculate the total elapsed time
#DO NOT alter it, or the script won't be able to calculate it
SECONDS=0

#This variable is used to output the time when the script is launched
#Edit the plus/minus and the value after "UTC", to force date into displaying your correct time zone
timeAtStart="$(TZ=UTC-2 date +%H:%M:%S)"

#This variable stores the path where to backup your apps' APK files
#Edit it freely, but do not forget the quotes
backupDir=""

#This variable tells the script which apps to backup
#Supported values are:
# - "User": tells the script to backup only third-party apps
# - "System": tells the script to backup only system apps
# - "All": tells the script to backup both 3rd party and system apps
appsToBackup=""

#This function outputs the time when the operations start. Purely cosmetic: can be disabled safely
#///Beginning of function "timeInfo"///
function timeInfo {
 echo "[ INFO ] Operations started at "$timeAtStart"."
}
#///End of function "timeInfo"///

#This function checks if the "aapt" utility is installed
#///Beginning of function "dependencyChecker"///
function dependencyChecker {
 echo "[ INFO ] Checking if aapt is installed..."
 whence -v aapt &> /dev/null
 isAaptAbsent="$(echo $?)"

 if [ "$isAaptAbsent" == "0" ]; then
  echo "[ INFO ] aapt has been found."
  unset isAaptAbsent
 else
  echo "[ FATAL ] aapt cannot be found. Aborting."
  exit
 fi
}
#///End of function "dependencyChecker"///

#This function verifies whether the values into "backupDir" and "appsToBackup" have anything inside or not
#In the case that the variables are empty, default values will be used, instead
#///Beginning of the function "variablesChecker"///
function variablesChecker {
 echo "[ INFO ] Checking if a backup path has already been specified..."
 if [ "$backupDir" == "$(cat /dev/null)" ]; then
  echo "[ WARNING ] A backup path has not been specified."
  echo "[ WARNING ] Setting the path to default (/sdcard/AppsBackup)."
  backupDir="/sdcard/AppsBackup"
 else
  echo "[ INFO ] Backup path has already been specified."
 fi
 echo ""

 echo "[ INFO ] Checking if the typology of apps to backup has already been chosen..."
 if [ "$appsToBackup" == "$(cat /dev/null)" ]; then
  echo "[ WARNING ] A typology of apps to backup has not been specified."
  echo "[ WARNING ] Setting the default typology (User)."
  appsToBackup="User"
 else
  echo "[ INFO ] A typology of apps has already been specified."
 fi
}
#///End of the function "variablesChecker"///

#This function emulates the case insensitivity for "appsToBackup", usually provided by brace expansion, but lacked by sh
#In the case that an unsupported value is found, a default value will be used instead
#///Beginning of the function "caseInsensitiveWorkaround"///
function caseInsensitiveWorkaround {
 systemArray="$(echo -n {s,S}{y,Y}{s,S}{t,T}{e,E}{m,M})"
 userArray="$(echo -n {u,U}{s,S}{e,E}{r,R})"
 allArray="$(echo -n {a,A}{l,L}{l,L})"

 case ${appsToBackup:0:1} in
  s|S)
   for i in $systemArray; do
    case "$appsToBackup" in
     $i)
      appsToBackup="System"
      ;;
    esac
   done
   ;;
  u|U)
   for i in $userArray; do
    case "$appsToBackup" in
     $i)
      appsToBackup="User"
      ;;
    esac
   done
   ;;
  a|A)
   for i in $allArray; do
    case "$appsToBackup" in
     $i)
      appsToBackup="All"
      ;;
    esac
   done
   ;;
  *)
   echo "[ WARNING ] \""$appsToBackup"\": invalid typology."
   echo "[ WARNING ] Setting the default typology (User)."
   appsToBackup="User"
   ;;
 esac

 case "$appsToBackup" in
  System|User|All)
   ;;
  *)
   echo "[ WARNING ] \""$appsToBackup"\": invalid typology."
   echo "[ WARNING ] Setting the default typology (User)."
   appsToBackup="User"
   ;;
 esac
}
#///End of the function "caseInsensitiveWorkaround"///

#This function checks if the backup directory already exists
#///Beginning of the function "backupDirCheck"///
function backupDirCheck {
 echo "[ INFO ] Checking if the backup directory already exists..."
 if [ -d "$backupDir" ]; then
  echo -n "[ INFO ] Backup directory already exists, "

  cd "$backupDir"
  #echo "[ INFO ] Checking if the directory is empty..."
  if [ "$(ls | grep "\.apk$" | head -n 1)" == "$(cat /dev/null)" ]; then
   echo "and does not have any APK file inside."
  else
   echo "and has at least an APK file inside."
   isDirectoryEmpty="0"
  fi
 else
  echo "[ INFO ] Backup directory does not exist. Creating it now."
  mkdir -p "$backupDir"
  cd "$backupDir"
 fi
}
#///End of the function "backupDirCheck"///

#This function generates a MD5 array, filled with the checksum of each APK file
#///Beginning of the function "checksumsGenerator"///
function checksumsGenerator {
 echo "[ INFO ] Generating file checksums..."
 apkList="$(printf "%s\n" * | grep "\.apk$")"
 for i in $apkList; do
  tempMd5=($(md5sum $i))
  md5Array="$tempMd5 $md5Array"
 done
 echo "[ INFO ] MD5 array generated."
}
#///End of the function "checksumsGenerator"///

#This function creates a list of the apps to backup, based on the content in "appsToBackup"
#///Beginning of the function "appListGenerator"///
function appListGenerator {
 case "$appsToBackup" in
  System)
   echo "[ INFO ] Retrieving system apps list..."
   appList="$(pm list packages -s)"
   ;;
  User)
   echo "[ INFO ] Retrieving third-party apps list..."
   appList="$(pm list packages -3)"
   ;;
  All)
   echo "[ INFO ] Retrieving apps list..."
   appList="$(pm list packages)"
   ;;
 esac
 echo "[ INFO ] Applications list retrieved."
}
#///End of the function "appListGenerator"///

#This function creates an array, filled with each app's full path
#///Beginning of the function "apkPathRetriever"///
function apkPathRetriever {
 echo "[ INFO ] Collecting the path of each app's APK..."
 for i in $appList; do
  apkPath="${i#p*:}"
  apkPath="$(pm path $apkPath)"
  apkPath="${apkPath#p*:}"
  pathArray="$apkPath $pathArray"
 done
 echo "[ INFO ] Paths collected."
}
#///End of the function "apkPathRetriever"///

#This function extracts the label or the package name for the APK supplied to it
#It extracts the app label for any third-party app, the package name for any system app
#///Beginning of the function "appNameRetriever"///
function appNameRetriever {
 case "$1" in
  /system/*)
   appName="${aaptOutput#*name=\'}"
   appName="${appName//\'*/}"
   displayedName="$appName"
   ;;
  /data/*|/mnt/asec/*)
   appName="${aaptOutput#*application-label:\'}"
   appName="${appName//app*/}"
   appName="${appName%\'*}"
   displayedName=$appName
   appName="$(printf "%s" $appName)"
   ;;
 esac
}
#///End of the function "appNameRetriever"///

#This function retrieves the version number of the APK
#///Beginning of the function "appVersionRetriever"///
function appVersionRetriever {
 appVersion="${aaptOutput#*versionName=\'}"
 appVersion="${appVersion//platformBuildVersion*/}"
 appVersion="${appVersion%\'*}"
 appVersion="$(printf "%s" $appVersion)"
}
#///End of the function "appVersionRetriever"///

#This function compares the MD5 of the APK in question against any MD5 in the array
#If it founds a match, then the function exits and the APK isn't backed up
#///Beginning of the function "md5Compare"///
function md5Compare {
 alreadyBackedUp=0
 appMd5=($(md5sum "$1"))

 for c in $md5Array; do
  if [ "$alreadyBackedUp" == "0" ]; then
   if [ "$appMd5" == "$c" ]; then
    alreadyBackedUp=1;
   fi
  else
   break;
  fi
 done
}
#///End of the function "md5Compare"///

#This function decides whether to backup an app or not
#It calls both "appNameRetriever" and "appVersionRetriever" for renaming any copied "base.apk"
#It also decides whether to call "md5Compare" or not, in order to see if an app has already been backed up
#///Beginning of the function "apkBackup"///
function apkBackup {
 for i in $pathArray; do
  alreadyBackedUp=0
  aaptOutput="$(aapt d badging "$i")"

  appNameRetriever "$i"
  appVersionRetriever

  if [ "$isDirectoryEmpty" == "0" ]; then
   md5Compare "$i"

   if [ "$alreadyBackedUp" == "0" ]; then
    echo -n "[ INFO ] Backing up "$displayedName"... "
    cp "$i" "$backupDir"/$appName"_"$appVersion.apk
    echo "done."
   else
    echo "[ INFO ] "$displayedName" has already been backed up."
   fi
  else
   echo -n "[ INFO ] Backing up "$displayedName"... "
   cp "$i" "$backupDir"/$appName"_"$appVersion.apk
   echo "done."
  fi
 done
}
#///End of the function "apkBackup"///

#This is the core of the tool
echo "**************************"
echo " NEMRIS - App backup tool "
echo "  by Death Mask Salesman  "
echo "**************************"

timeInfo
echo ""

dependencyChecker
echo ""

variablesChecker
echo ""

caseInsensitiveWorkaround
echo ""

backupDirCheck
echo ""

if [ "$isDirectoryEmpty" == "0" ]; then
 checksumsGenerator
 echo ""
fi

appListGenerator
echo ""

apkPathRetriever
echo ""

apkBackup
echo ""

echo "[ INFO ] Operations took "$(((SECONDS/60)/60))" hours, "$(((SECONDS/60)%60))" minutes and "$((SECONDS%60))" seconds."
echo "[ INFO ] All done!"

PreguntAndroid.com

PreguntAndroid es una comunidad de usuarios de Android en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X