ตรวจสอบว่ามีการติดตั้งแอปพลิเคชัน - Android


105

ฉันกำลังพยายามติดตั้งแอปจาก Google Play ฉันเข้าใจว่าเมื่อเปิด URL ของ Google Play Store จะเป็นการเปิด Google Play และเมื่อฉันกดปุ่มย้อนกลับกิจกรรมจะดำเนินต่อไป

Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(appURL));
marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivity(marketIntent);

เมื่อฉันกลับไปที่กิจกรรมฉันลองโทรonResume()ไปที่สิ่งนี้เพื่อตรวจสอบว่าติดตั้งแอพแล้วหรือยัง แต่ฉันได้รับข้อผิดพลาด:

@Override
protected void onResume() {
    super.onResume();
    boolean installed = false;
    while (!installed) {
        installed  =   appInstalledOrNot(APPPACKAGE);
        if (installed) {
             Toast.makeText(this, "App installed", Toast.LENGTH_SHORT).show();
        }
    }
}

private boolean appInstalledOrNot(String uri) {
  PackageManager pm = getPackageManager();
  boolean app_installed = false;
  try {
      pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
      app_installed = true;
  }
  catch (PackageManager.NameNotFoundException e) {
      app_installed = false;
  }
  return app_installed ;
}

ข้อผิดพลาดมีดังนี้:

E / AndroidRuntime (796): java.lang.RuntimeException: ไม่สามารถเริ่มกิจกรรม ComponentInfo {com.example.appinstaller / com.example.appinstaller.MainActivity}: android.content.ActivityNotFoundException: ไม่พบกิจกรรมที่จัดการกับ Intent {act = android .intent.action.VIEW dat = market: // details? id = com.package.name flg = 0x40080000}

onPause()ผมคิดว่ากิจกรรมคือ มีวิธีที่ดีกว่าในการนำไปใช้หรือไม่? ฉันกำลังพยายามตรวจสอบว่าแอปติดตั้งเสร็จหรือไม่



@SiddharthanAsokan ถ้าฉันเข้าใจถูกต้องสิ่งที่คุณพยายามจะบรรลุคือเริ่มแอพของคุณ -> ไปที่ play store-> คลิกติดตั้ง -> กลับมาที่กิจกรรมของคุณเอง -> เริ่มแอพที่ติดตั้งใหม่ .. ถูกต้องหรือไม่?
Varun

ไม่กลับไปที่แอพที่ฉันเปิดตอนแรก ฉันต้องการรับข้อมูลบางอย่างเกี่ยวกับแอพที่ติดตั้งโดยใช้ PackageManager การดึงข้อมูลนี้เริ่มต้นหลังจากที่ฉันติดตั้งแอปจากจุดเริ่มต้นที่ใช้เปิด url ของเว็บ
Siddharthan Asokan

คำตอบ:


306

ลองสิ่งนี้:

private boolean isPackageInstalled(String packageName, PackageManager packageManager) {
    try {
        packageManager.getPackageInfo(packageName, 0);
        return true;
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }
}

ก็พยายามที่จะดึงข้อมูลเกี่ยวกับแพคเกจที่มีชื่อคุณผ่าน. ความล้มเหลวที่ถ้าถูกโยนมันหมายความว่าไม่มีแพคเกจที่มีชื่อที่มีการติดตั้งเพื่อให้เรากลับมาNameNotFoundExceptionfalse

โปรดทราบว่าเราผ่านในPackageManagerแทนContextเพื่อให้วิธีการที่เล็กน้อยสามารถใช้งานได้อย่างคล่องตัวและไม่ละเมิดกฎหมายของ Demeter คุณสามารถใช้วิธีนี้โดยไม่ต้องเข้าถึงContextอินสแตนซ์ตราบเท่าที่คุณมีPackageManagerอินสแตนซ์

ใช้แบบนี้:

public void someMethod() {
    // ...

    PackageManager pm = context.getPackageManager();
    boolean isInstalled = isPackageInstalled("com.somepackage.name", pm);

    // ...
}

1
เงื่อนไขคือ: ฉันต้องตรวจสอบกระบวนการติดตั้งนี้หากเสร็จสิ้น ฉันคลิกที่ติดตั้งและในเวลานั้นฉันพยายามตรวจสอบการติดตั้งแบบวนซ้ำ รหัสนั้นใช้ได้ แต่วิธีการตรวจสอบว่าการติดตั้งเสร็จสมบูรณ์หรือไม่คือสิ่งที่ฉันกำลังมองหา
สิทธารถอโศก

3
@SiddharthanAsokan คุณสามารถใช้เครื่องรับสัญญาณสำหรับการดำเนินการ package_added
Varun

@Varun ฉันเพิ่งแก้ไขรหัส ไม่มีชื่อแพ็กเกจแอปอีกต่อไปที่ฉันใช้ เพียงแค่ URL เว็บของแอพใน Google Play Store
Siddharthan Asokan

@Robin Kanters โปรดตรวจสอบการเปลี่ยนแปลงที่ฉันทำ
Siddharthan Asokan

สิ่งที่คุณทำในคำถามของคุณเหมือนกับคำตอบของฉัน
Robin Kanters

35

คำตอบของ Robin Kanters ถูกต้อง แต่จะตรวจสอบแอปที่ติดตั้งโดยไม่คำนึงถึงสถานะที่เปิดใช้งานหรือปิดใช้งาน

เราทุกคนทราบดีว่าแอปสามารถติดตั้งได้ แต่ผู้ใช้ปิดใช้งานจึงใช้ไม่ได้

สิ่งนี้จะตรวจหาแอพที่ติดตั้งและเปิดใช้งาน:

public static boolean isPackageInstalled(String packageName, PackageManager packageManager) {
    try {
        return packageManager.getApplicationInfo(packageName, 0).enabled;
    }
    catch (PackageManager.NameNotFoundException e) {
        return false;
    }
}

คุณสามารถใส่วิธีนี้ในคลาสที่ชอบUtilsและเรียกมันได้ทุกที่โดยใช้:

boolean isInstalled = Utils.isPackageInstalled("com.package.name", context.getPackageManager())

7

วิธีแก้ปัญหาที่เร็วกว่า:

private boolean isPackageInstalled(String packagename, PackageManager packageManager) {
    try {
        packageManager.getPackageGids(packagename);
        return true;
    } catch (NameNotFoundException e) {
        return false;
    }
}

getPackageGidsมีราคาไม่แพงgetPackageInfoดังนั้นจึงทำงานได้เร็วขึ้น

Run 10000 on API 15
Exists pkg:
getPackageInfo: nanoTime = 930000000
getPackageGids: nanoTime = 350000000
Not exists pkg:
getPackageInfo: nanoTime = 420000000
getPackageGids: nanoTime = 380000000

Run 10000 on API 17
Exists pkg:
getPackageInfo: nanoTime = 2942745517
getPackageGids: nanoTime = 2443716170
Not exists pkg:
getPackageInfo: nanoTime = 2467565849
getPackageGids: nanoTime = 2479833890

Run 10000 on API 22
Exists pkg:
getPackageInfo: nanoTime = 4596551615
getPackageGids: nanoTime = 1864970154
Not exists pkg:
getPackageInfo: nanoTime = 3830033616
getPackageGids: nanoTime = 3789230769

Run 10000 on API 25
Exists pkg:
getPackageInfo: nanoTime = 3436647394
getPackageGids: nanoTime = 2876970397
Not exists pkg:
getPackageInfo: nanoTime = 3252946114
getPackageGids: nanoTime = 3117544269

หมายเหตุ: สิ่งนี้จะไม่ทำงานในพื้นที่เสมือนจริงบางส่วน พวกเขาสามารถละเมิด Android API และส่งคืนอาร์เรย์ได้เสมอแม้ว่าจะไม่มีแอปพลิเคชันที่มีชื่อแพ็กเกจนั้นก็ตาม
ในกรณีนี้ให้ใช้getPackageInfo.


5

ลองสิ่งนี้:

public static boolean isAvailable(Context ctx, Intent intent) {
    final PackageManager mgr = ctx.getPackageManager();
    List<ResolveInfo> list =
        mgr.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    return list.size() > 0;
}

2

ตั้งแต่ Android 11 (API ระดับ 30) แอปที่ผู้ใช้ติดตั้งส่วนใหญ่จะมองไม่เห็นโดยค่าเริ่มต้น ในไฟล์ Manifest ของคุณคุณต้องประกาศว่าจะรับข้อมูลเกี่ยวกับแอปใดดังต่อไปนี้:

<manifest>
    <queries>
        <!-- Explicit apps you know in advance about: -->
        <package android:name="com.example.this.app"/>
        <package android:name="com.example.this.other.app"/>
    </queries>
    
    ...
</manifest>

จากนั้นคำตอบของ @RobinKanters ใช้งานได้:

private boolean isPackageInstalled(String packageName, PackageManager packageManager) {
    try {
        packageManager.getPackageInfo(packageName, 0);
        return true;
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }
}

// ...
// This will return true on Android 11 if the app is installed,
// since we declared it above in the manifest.
isPackageInstalled("com.example.this.app", pm); 
// This will return false on Android 11 even if the app is installed:
isPackageInstalled("another.random.app", pm); 

เรียนรู้เพิ่มเติมที่นี่:


0

หากคุณต้องการทดลองใช้โดยไม่ต้องบล็อก try catch สามารถใช้วิธีต่อไปนี้สร้างความตั้งใจและตั้งค่าแพ็คเกจของแอพที่คุณต้องการตรวจสอบ

val intent = Intent(Intent.ACTION_VIEW)
intent.data = uri
intent.setPackage("com.example.packageofapp")

และโทรตามวิธีการต่อไปนี้เพื่อตรวจสอบว่าติดตั้งแอปแล้วหรือไม่

fun isInstalled(intent:Intent) :Boolean{
    val list = context.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
    return list.isNotEmpty()
}

0

ผู้ที่กำลังมองหาโซลูชัน Kotlin สามารถใช้วิธีนี้

ที่นี่ฉันได้แชร์รหัสเต็มและจัดการสถานะเปิดใช้งานด้วย ตรวจสอบว่ามีการติดตั้งแอปพลิเคชันใน Android Kotlin หรือไม่

fun isAppInstalled(packageName: String, context: Context): Boolean {
        return try {
            val packageManager = context.packageManager
            packageManager.getPackageInfo(packageName, 0)
            true
        } catch (e: PackageManager.NameNotFoundException) {
            false
        }
    }

0

คุณสามารถใช้สิ่งนี้ใน Kotlin extentions.kt

fun Context.isPackageInstalled(packageName: String): Boolean {
    return try {
        packageManager.getPackageInfo(packageName, 0)
        true
    } catch (e: PackageManager.NameNotFoundException) {
        false
    }
}

การใช้งาน

context.isPackageInstalled("com.somepackage.name")

-1
    private boolean isAppExist() {

    PackageManager pm = getPackageManager();
    try {
        PackageInfo info = pm.getPackageInfo("com.facebook.katana", PackageManager.GET_META_DATA);
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }
    return true;
}




if (isFacebookExist()) {showToast(" Facebook is  install.");}
     else {showToast(" Facebook is not install.");}

นี่เหมือนกับคำตอบที่ยอมรับ
user13044086

-1
isFakeGPSInstalled = Utils.isPackageInstalled(Utils.PACKAGE_ID_FAKE_GPS, this.getPackageManager());

// วิธีตรวจสอบแพ็คเกจที่ติดตั้งจริง / เท็จ

  public static boolean isPackageInstalled(String packageName, PackageManager packageManager) {
    boolean found = true;
    try {
      packageManager.getPackageInfo(packageName, 0);
    } catch (PackageManager.NameNotFoundException e) {
      found = false;
    }

    return found;
  }

นี่เหมือนกับคำตอบที่ยอมรับ
user13044086

-9
@Override 
protected void onResume() {
    super.onResume();
    boolean installed = false;

    while (!installed) {
        installed = appInstalledOrNot (APPPACKAGE);
        if (installed) {
            Toast.makeText(this, "App installed", Toast.LENGTH_SHORT).show ();
        }
    }
} 

private boolean appInstalledOrNot (String uri) {
    PackageManager pm = getPackageManager();
    boolean app_installed = false;
    try {
        pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
        app_installed = true;
    } catch (PackageManager.NameNotFoundException e) {
        app_installed = false;
    }
    return app_installed;
}

8
นี่คือการวนซ้ำที่ไม่มีที่สิ้นสุด
Robin Kanters
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.