Get Android .apk file VersionName or VersionCode WITHOUT installing apk

前端 未结 9 2559
鱼传尺愫
鱼传尺愫 2020-11-28 17:32

How can I get programmatically get the version code or version name of my apk from the AndroidManifest.xml file after downloading it and without installing it.



        
9条回答
  •  野趣味
    野趣味 (楼主)
    2020-11-28 18:26

    aapt dump badging test.apk | grep "VersionName" | sed -e "s/.*versionName='//" -e "s/' .*//"
    

    This answers the question by returning only the version number as a result. However......

    The goal as previously stated should be to find out if the apk on the server is newer than the one installed BEFORE attempting to download or install it. The easiest way to do this is include the version number in the filename of the apk hosted on the server eg myapp_1.01.apk

    You will need to establish the name and version number of the apps already installed (if it is installed) in order to make the comparison. You will need a rooted device or a means of installing the aapt binary and busybox if they are not already included in the rom.

    This script will get the list of apps from your server and compare with any installed apps. The result is a list flagged for upgrade/installation.

    #/system/bin/sh
    SERVER_LIST=$(wget -qO- "http://demo.server.com/apk/" | grep 'href' | grep '\.apk' | sed 's/.*href="//' | \
                  sed 's/".*//' | grep -v '\/' | sed -E "s/%/\\\\x/g" | sed -e "s/x20/ /g" -e "s/\\\\//g")
    LOCAL_LIST=$(for APP in $(pm list packages -f | sed -e 's/package://' -e 's/=.*//' | sort -u); do \
                  INFO=$(echo -n $(aapt dump badging $APP | grep -e 'package: name=' -e 'application: label=')) 2>/dev/null; \
                  PACKAGE=$(echo $INFO | sed "s/.*package: name='//" | sed "s/'.*$//"); \
                  LABEL=$(echo $INFO | sed "s/.*application: label='//" | sed "s/'.*$//"); if [ -z "$LABEL" ]; then LABEL="$PACKAGE"; fi; \
                  VERSION=$(echo $INFO | sed -e "s/.*versionName='//" -e "s/' .*//"); \
                  NAME=$LABEL"_"$VERSION".apk"; echo "$NAME"; \
                  done;)
    OFS=$IFS; IFS=$'\t\n'
    for REMOTE in $SERVER_LIST; do
        INSTALLED=0
        REMOTE_NAME=$(echo $REMOTE | sed 's/_.*//'); REMOTE_VER=$(echo $REMOTE | sed 's/^[^_]*_//g' | sed 's/[^0-9]*//g')
        for LOCAL in $LOCAL_LIST; do
            LOCAL_NAME=$(echo $LOCAL | sed 's/_.*//'); LOCAL_VER=$(echo $LOCAL | sed 's/^[^_]*_//g' | sed 's/[^0-9]*//g')
            if [ "$REMOTE_NAME" == "$LOCAL_NAME" ]; then INSTALLED=1; fi
            if [ "$REMOTE_NAME" == "$LOCAL_NAME" ] && [ ! "$REMOTE_VER" == "$LOCAL_VER" ]; then echo remote=$REMOTE ver=$REMOTE_VER local=$LOCAL ver=$LOCAL_VER; fi
        done
        if [ "$INSTALLED" == "0" ]; then echo "$REMOTE"; fi
    done
    IFS=$OFS
    

    As somebody asked how to do it without using aapt. It is also possible to extract apk info with apktool and a bit of scripting. This way is slower and not simple in android but will work on windows/mac or linux as long as you have working apktool setup.

    #!/bin/sh
    APK=/path/to/your.apk
    TMPDIR=/tmp/apktool
    rm -f -R $TMPDIR
    apktool d -q -f -s --force-manifest -o $TMPDIR $APK
    APK=$(basename $APK)
    VERSION=$(cat $TMPDIR/apktool.yml | grep "versionName" | sed -e "s/versionName: //")
    LABEL=$(cat $TMPDIR/res/values/strings.xml | grep 'string name="title"' | sed -e 's/.*">//' -e 's/<.*//')
    rm -f -R $TMPDIR
    echo ${LABEL}_$(echo $V).apk
    

    Also consider a drop folder on your server. Upload apks to it and a cron task renames and moves them to your update folder.

    #!/bin/sh
    # Drop Folder script for renaming APKs
    # Read apk file from SRC folder and move it to TGT folder while changing filename to APKLABEL_APKVERSION.apk
    # If an existing version of the APK exists in the target folder then script will remove it
    # Define METHOD as "aapt" or "apktool" depending upon what is available on server 
    
    # Variables
    METHOD="aapt"
    SRC="/home/user/public_html/dropfolders/apk"
    TGT="/home/user/public_html/apk"
    if [ -d "$SRC" ];then mkdir -p $SRC
    if [ -d "$TGT" ]then mkdir -p $TGT
    
    # Functions
    get_apk_filename () {
        if [ "$1" = "" ]; then return 1; fi
        local A="$1"
        case $METHOD in
            "apktool")
                local D=/tmp/apktool
                rm -f -R $D
                apktool d -q -f -s --force-manifest -o $D $A
                local A=$(basename $A)
                local V=$(cat $D/apktool.yml | grep "versionName" | sed -e "s/versionName: //")
                local T=$(cat $D/res/values/strings.xml | grep 'string name="title"' | sed -e 's/.*">//' -e 's/<.*//')
                rm -f -R $D
                ;;
            "aapt")
                local A=$(aapt dump badging $A | grep -e "application-label:" -e "VersionName")
                local V=$(echo $A | sed -e "s/.*versionName='//" -e "s/' .*//")
                local T=$(echo $A | sed -e "s/.*application-label:'//" -e "s/'.*//")
                ;;
            esac
        echo ${T}_$(echo $V).apk
    }
    
    # Begin script
    for APK in $(ls "$SRC"/*.apk); do
        APKNAME=$(get_apk_filename "$APK")
        rm -f $TGT/$(echo APKNAME | sed "s/_.*//")_*.apk
        mv "$APK" "$TGT"/$APKNAME
    done
    

提交回复
热议问题