APK ইনস্টল না করে Android .apk ফাইল সংস্করণ নাম বা সংস্করণকোড পান


183

ডাউনলোড করার পরে এবং ইনস্টল না করেই আমি কীভাবে প্রোগ্রামেমেটিকভাবে আমার এপকের সংস্করণ কোড বা সংস্করণ নাম পেতে পারি can

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xxx.xx.xxx"
    android:versionCode="1"
    android:versionName="1.1" >

উদাহরণস্বরূপ আমি ডিভাইসে ইনস্টল করার পরে, আমার আইআইএস পরিষেবাতে কোনও নতুন সংস্করণ আপলোড করা হয়েছে কিনা তা যাচাই করতে চাই, এটি যদি নতুন সংস্করণ না হয় তবে আমি এটি ইনস্টল করতে চাই না।


এই পরীক্ষা stackoverflow.com/a/4761689/1109425
nandeesh

বিটিডাব্লু, আমি আশা করি কেউই ফাইলটি ডাউনলোড করার জন্য একটি ভাল সমাধান বলে মনে করেন না, এবং তারপরে এটির প্রয়োজন কিনা তা যাচাই করুন - প্রথম বাক্যটি যা বোঝায় এটি। সম্ভবত আপনি তার পরিবর্তে আপনার সার্ভারে চলমান কোডটি চাইবেন এবং উপলভ্য সংস্করণ নম্বরটি দিয়ে সাড়া দিন।
টুলমেকারস্টেভ

./aapt d badging release.apk | grep -Po "(?<=\sversion(Code|Name)=')([0-9.]+)"
ক্রিস রূফ

2.6Mডিস্কের জায়গার জন্য অ্যাপেটের জন্য ব্যয় হবে , আপনি এপিপি ফাইলটি পার্স করতে পার্সারও লিখতে পারেন AXMLResourceযার সাথে প্রায় ব্যয় হবে 52k। পড়ুন জাভা পার্স XML অঘোষিত নামস্থান সঙ্গে
ক্রিস Roofe

উত্তর:


416

কমান্ড লাইন থেকে নিম্নলিখিতটি আমার জন্য কাজ করেছে:

aapt dump badging myapp.apk

দ্রষ্টব্য: aapt.exe build-toolsএসডিকে একটি উপ-ফোল্ডারে পাওয়া যায় । উদাহরণ স্বরূপ:

<sdk_path>/build-tools/23.0.2/aapt.exe

26
কাজ করে জরিমানা, এই সঠিক উত্তর হিসেবে চিহ্নিত করা উচিত, তথ্যের জন্য, aaptহয় বিল্ড-সরঞ্জামগুলি চালু / এক্সএক্স SDK হবে।
কোয়ান্টিন ক্লেইন

8
আমি এটি "<sdk_path> / বিল্ড
টোলেটস /

1
একটি ম্যাকতে জ্যামারিন ব্যবহার করে, এটি ছিল~/Library/Developer/Xamarin/android-sdk-macosx/build-tools/{version}
cscott530

platformBuildVersionNameআমি যখন এই আদেশটি ব্যবহার করি তখন এটি কী মুদ্রিত হয় এবং এটি খালি কেন?
সেবাদাস্তন সাবন্যুক

আপনি যে aapt dump badging %1 pauseকোনও
এপিপি

85
final PackageManager pm = getPackageManager();
String apkName = "example.apk";
String fullPath = Environment.getExternalStorageDirectory() + "/" + apkName;        
PackageInfo info = pm.getPackageArchiveInfo(fullPath, 0);
Toast.makeText(this, "VersionCode : " + info.versionCode + ", VersionName : " + info.versionName , Toast.LENGTH_LONG).show();

5
আমি অ্যাপ্লিকেশন ইনস্টল না করে কীভাবে apkসামগ্রী পড়তে পারি ? @ পেট্রিকচো
তালহা 06

2
এটি আসলে কাজ করে। এবং আপনার এটি ইনস্টল করার দরকার নেই। আপনার ডিভাইসের স্টোরেজে কোথাও একটি APK রয়েছে এবং প্যাকেজ ম্যানেজারকে এটির জন্য সরবরাহ সরবরাহ করুন। এটি প্রকৃতপক্ষে প্যাকেজের তথ্য ফিরিয়ে দেবে।
ড্যানিয়েল জোলনাই

45

আপনি ব্যবহার করে থাকেন সংস্করণ 2.2 এবং উপরোক্ত এর অ্যান্ড্রয়েড স্টুডিও অ্যান্ড্রয়েড স্টুডিও ব্যবহারে তারপর Build Analyze APKতারপর AndroidManifest.xml ফাইলে নির্বাচন করুন।


7
ওপি কীভাবে এটি পাবে জিজ্ঞাসা করেছিলprogrammatically
forresthopkinsa

3
কারণ তিনি জানতেন না যে এ জাতীয় একটি সরঞ্জাম অ্যান্ড্রয়েড স্টুডিওতে নির্মিত। তিনি এপকে ইনস্টল না করে জিজ্ঞাসাও করেছিলেন ।
ভাইওয়াহস্ট ইস্ট

3
অবশ্যই তিনি জানতেন না, কারণ এই প্রশ্নটি জিজ্ঞাসা করার সময় অ্যান্ড্রয়েড স্টুডিওর অস্তিত্ব ছিল না। অতিরিক্তভাবে, এটি করা সত্ত্বেও, এটি তার সমস্যার সমাধান করে না - তিনি তার ডিভাইসটি প্রোগ্রামটিতে তার আইআইএস সার্ভারের আপডেটগুলি পরীক্ষা করতে চান , যেমনটি তিনি প্রশ্নের বিবরণ দিয়েছিলেন। প্যাট্রিক চো-র উত্তরটি ইনস্টল না করে প্রোগ্রামিকভাবে এটি কীভাবে করবেন তা ব্যাখ্যা করে।
forresthopkinsa

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

এটি ফলাফল হিসাবে কেবল সংস্করণ নম্বরটি দিয়ে প্রশ্নের উত্তর দেয়। যাহোক......

পূর্বে উল্লিখিত লক্ষ্যটি হ'ল সার্ভারে থাকা এপিপি এটি ডাউনলোড বা ইনস্টল করার চেষ্টা করার আগে ইনস্টল হওয়াটির চেয়ে নতুন কিনা to এটি করার সহজতম উপায়টি হ'ল সার্ভারে হোস্ট করা এপিকে ফাইলের নামের সংস্করণ নম্বর অন্তর্ভুক্ত করাmyapp_1.01.apk

তুলনা করার জন্য আপনাকে ইতিমধ্যে ইনস্টল হওয়া অ্যাপগুলির নাম এবং সংস্করণ নম্বরটি ইনস্টল করতে হবে installed আপনার যদি রমটিতে ইতিমধ্যে অন্তর্ভুক্ত না করা হয় তবে আপনার কাছে একটি রুট ডিভাইস বা অ্যাপট বাইনারি এবং ব্যস্তবক্স ইনস্টল করার একটি মাধ্যম প্রয়োজন হবে।

এই স্ক্রিপ্টটি আপনার সার্ভার থেকে অ্যাপ্লিকেশনগুলির তালিকা পাবে এবং যে কোনও ইনস্টল করা অ্যাপ্লিকেশনগুলির সাথে তুলনা করবে। ফলাফলটি আপগ্রেড / ইনস্টলেশনের জন্য পতাকাঙ্কিত একটি তালিকা।

#/system/bin/sh
SERVER_LIST=$(wget -qO- "http://demo.server.com/apk/" | grep 'href' | grep '\.apk' | sed 's/.*href="https://stackoverflow.com//' | \
              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

যেহেতু কেউ জিজ্ঞাসা করেছিল যে এপেট ব্যবহার না করে এটি কীভাবে করবেন। এটি apktool এবং কিছুটা স্ক্রিপ্টিং সহ apk তথ্য আহরণ করাও সম্ভব। অ্যান্ড্রয়েডে এই উপায়টি ধীর এবং সহজ নয় তবে আপনি অ্যাপ্টোল সেটআপ চালানোর সময় উইন্ডোজ / ম্যাক বা লিনাক্সে কাজ করবে।

#!/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

আপনার সার্ভারে একটি ড্রপ ফোল্ডার বিবেচনা করুন। এটিতে অ্যাপস আপলোড করুন এবং একটি ক্রোন টাস্ক নাম পরিবর্তন করে এটিকে আপনার আপডেট ফোল্ডারে নিয়ে যায়।

#!/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<commands>
            ;;
        "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

8

এই মুহুর্তে, নিম্নলিখিত হিসাবে এটি করা যেতে পারে

$ANDROID_HOME/build-tools/28.0.3/aapt dump badging /<path to>/<app name>.apk

সাধারণভাবে, এটি হবে:

$ANDROID_HOME/build-tools/<version_of_build_tools>/aapt dump badging /<path to>/<app name>.apk

5

আমি এখন তার বাইনারি এক্সএমএল ডেটা থেকে কোনও এপিএল ফাইলের সংস্করণ সফলভাবে পেতে পারি।

এই বিষয়টি যেখানে আমি আমার উত্তরের চাবি পেয়েছি (আমি রিবো কোডটির আমার সংস্করণটিও যুক্ত করেছি): কীভাবে একটি .apk প্যাকেজের ভিতরে AndroidManLive.xML ফাইলটি পার্স করতে হবে?

অতিরিক্তভাবে, আমি লিখেছি XML পার্সিং কোডটি, বিশেষভাবে সংস্করণটি আনার জন্য:

এক্সএমএল পার্সিং

/**
 * Verifies at Conductor APK path if package version if newer 
 * 
 * @return True if package found is newer, false otherwise
 */
public static boolean checkIsNewVersion(String conductorApkPath) {

    boolean newVersionExists = false;

    // Decompress found APK's Manifest XML
    // Source: /programming/2097813/how-to-parse-the-androidmanifest-xml-file-inside-an-apk-package/4761689#4761689
    try {

        if ((new File(conductorApkPath).exists())) {

            JarFile jf = new JarFile(conductorApkPath);
            InputStream is = jf.getInputStream(jf.getEntry("AndroidManifest.xml"));
            byte[] xml = new byte[is.available()];
            int br = is.read(xml);

            //Tree tr = TrunkFactory.newTree();
            String xmlResult = SystemPackageTools.decompressXML(xml);
            //prt("XML\n"+tr.list());

            if (!xmlResult.isEmpty()) {

                InputStream in = new ByteArrayInputStream(xmlResult.getBytes());

                // Source: http://developer.android.com/training/basics/network-ops/xml.html
                XmlPullParser parser = Xml.newPullParser();
                parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);

                parser.setInput(in, null);
                parser.nextTag();

                String name = parser.getName();
                if (name.equalsIgnoreCase("Manifest")) {

                    String pakVersion = parser.getAttributeValue(null, "versionName");
                            //NOTE: This is specific to my project. Replace with whatever is relevant on your side to fetch your project's version
                    String curVersion = SharedData.getPlayerVersion();

                    int isNewer = SystemPackageTools.compareVersions(pakVersion, curVersion); 

                    newVersionExists = (isNewer == 1); 
                }

            }
        }

    } catch (Exception ex) {
        android.util.Log.e(TAG, "getIntents, ex: "+ex);
        ex.printStackTrace();
    }

    return newVersionExists;
}

সংস্করণ তুলনা (আগের স্নিপেটে SystemPackageTools.compareVersions হিসাবে দেখা হয়) দ্রষ্টব্য: এই কোডটি নিম্নলিখিত বিষয় থেকে অনুপ্রাণিত: জাভাতে সংস্করণের স্ট্রিংগুলির তুলনা করার কার্যকর উপায়

/**
 * Compare 2 version strings and tell if the first is higher, equal or lower
 * Source: /programming/6701948/efficient-way-to-compare-version-strings-in-java
 * 
 * @param ver1 Reference version
 * @param ver2 Comparison version
 * 
 * @return 1 if ver1 is higher, 0 if equal, -1 if ver1 is lower
 */
public static final int compareVersions(String ver1, String ver2) {

    String[] vals1 = ver1.split("\\.");
    String[] vals2 = ver2.split("\\.");
    int i=0;
    while(i<vals1.length&&i<vals2.length&&vals1[i].equals(vals2[i])) {
      i++;
    }

    if (i<vals1.length&&i<vals2.length) {
        int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i]));
        return diff<0?-1:diff==0?0:1;
    }

    return vals1.length<vals2.length?-1:vals1.length==vals2.length?0:1;
}

আশা করি এটা কাজে লাগবে.


আপনি কি নতুন গ্র্যাডেল বা অ্যান্ড্রয়েড স্টুডিওতে আপগ্রেড করেছেন? এটি কি এখনও কাজ করে? রবিও কোডটি আর আমার জন্য এক্সএমএলকে সংক্ষেপিত করতে কাজ করে না।
জিআর দূত

4

আপগ্রেড দৃশ্যের জন্য বিশেষত বিকল্প বিকল্পটি এমন একটি ওয়েব পরিষেবা থাকতে পারে যা বর্তমান সংস্করণ নম্বর সরবরাহ করে এবং এটির সংস্করণটি পরীক্ষা করার জন্য পুরো এপিপি ডাউনলোড করার পরিবর্তে তা পরীক্ষা করে দেখুন। এটি কিছু ব্যান্ডউইদথ সাশ্রয় করবে, কিছুটা আরও পারফরম্যান্ট হবে (পুরো ডাউনলোডের বেশিরভাগ সময় যদি প্রয়োজন হয় না তবে কোনও এপিপি থেকে ডাউনলোড করা অনেক দ্রুত) এবং বাস্তবায়নের জন্য আরও সহজ।

সাধারণ ফর্মটিতে আপনার সার্ভারে একটি সাধারণ পাঠ্য ফাইল থাকতে পারে ... http://some-place.com/current-app-version.txt

সেই টেক্সট ফাইলের ভিতরে কিছু একটা থাকে

3.1.4

এবং তারপরে সেই ফাইলটি ডাউনলোড করুন এবং বর্তমানে ইনস্টল করা সংস্করণটি পরীক্ষা করুন।

এর আরও উন্নত সমাধান তৈরি করা হবে একটি সঠিক ওয়েব পরিষেবা বাস্তবায়ন করা এবং লঞ্চের সময় এপিআই কল করা যা কিছু জসনকে ফিরিয়ে আনতে পারে, অর্থাত http://api.some-place.com/versionCheck:

{
    "current_version": "3.1.4"
}

আপনি সঠিক পথে আছেন - কেবল ফাইলটির সংস্করণ পেতে ফাইলটি ডাউনলোড করা উচিত নয়। আমি কেবল উল্লেখ করতে চাই যে আমি পাঠ্য ফাইলটি ম্যানুয়ালি তৈরি করার পরামর্শ দেব না - এটি আসল এপিপি ফাইলের সাথে মেলে না এমনটি খুব সহজ। পরিবর্তে, এপিপির ভিতরে থাকা সংস্করণটি কী তা দেখতে ফাইল বা ডাটাবেসে সংরক্ষণ করে আপনি যেভাবে আলোচনা করেছেন তার মাধ্যমে পুনরুদ্ধার করতে একটি স্ক্রিপ্ট লিখুন (এটি অন্য উত্তরগুলির মধ্যে একটির ব্যবহার করে) write
টুলমেকারস্টেভ

হ্যাঁ এই দৃশ্যের ক্ষেত্রে এটি এমন নয় যে এটি সর্বদা APK এর সাথে মিলিয়ে নেওয়া দরকার, কেবল সর্বশেষতম সংস্করণ নম্বরটি কোথাও সর্বজনীনভাবে অ্যাক্সেসযোগ্য।
গ্রেগো

1
    EditText ET1 = (EditText) findViewById(R.id.editText1);

    PackageInfo pinfo;
    try {
        pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
        String versionName = pinfo.versionName;
        ET1.setText(versionName);
        //ET2.setText(versionNumber);
    } catch (NameNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

10
এটি প্রশ্নের উত্তর নয়। এটি এমন কোড যা চলমান অ্যাপের অভ্যন্তরে কিছু সংস্করণ তথ্য পেয়েছে এবং এটি প্রদর্শন করে। অ্যাপটি ইনস্টল না করে কীভাবে একটি APK ফাইল থেকে এই তথ্যটি পাবেন তা প্রশ্ন ।
টুলমেকারস্টেভ

এটি কেবল ইতিমধ্যে ইনস্টল করা অ্যাপ্লিকেশনের জন্য যা .apk ফাইলের জন্য নয়।
রুশফার 6'19
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.