ติดตั้งแอปแบบไม่โต้ตอบโดยได้รับอนุญาต INSTALL_PACKAGES


86

ฉันกำลังพยายามติดตั้ง apk ลงในระบบโดยเงียบ แอปของฉันอยู่ใน / system / app และได้รับอนุญาต "android.permission.INSTALL_PACKAGES" เรียบร้อยแล้ว

อย่างไรก็ตามฉันไม่พบวิธีใช้สิทธิ์นี้จากที่ใด ฉันพยายามคัดลอกไฟล์ไปยัง / data / app และไม่ประสบความสำเร็จ ฉันลองใช้รหัสนี้ด้วย

    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(
            Uri.parse("file:///sdcard/app.apk"),
            "application/vnd.android.package-archive");
    startActivity(intent);

แต่รหัสนี้จะเปิดกล่องโต้ตอบการติดตั้งมาตรฐาน ฉันจะติดตั้งแอปโดยไม่ต้องรูทโดยไม่ได้รับอนุญาตได้android.permission.INSTALL_PACKAGESอย่างไร

ป.ล. ฉันกำลังเขียนแอพที่จะติดตั้ง apks จำนวนมากจากโฟลเดอร์ลงในระบบเมื่อเริ่มต้นครั้งแรก (แทนที่ Setup Wizard) ฉันต้องการมันเพื่อทำให้เฟิร์มแวร์เบาลง

หากคุณคิดว่าฉันกำลังเขียนไวรัส: มีการติดตั้งโปรแกรมทั้งหมดลงใน / data / app สิทธิ์ Install_packages สามารถให้สิทธิ์กับโปรแกรมระดับระบบที่อยู่ใน / system / app หรือเซ็นชื่อด้วยคีย์ระบบเท่านั้น ไวรัสจึงไม่สามารถไปที่นั่นได้

ดังที่กล่าวไว้ว่าhttp://www.mail-archive.com/android-porting@googlegroups.com/msg06281.htmlแอปสามารถติดตั้งแบบเงียบได้หากมีการอนุญาตติดตั้ง ยิ่งไปกว่านั้นคุณไม่จำเป็นต้องมีสิทธิ์ Install_packages ในการติดตั้งแพ็กเกจ รวมถึงhttp://www.androidzoom.com/android_applications/tools/silent-installer_wgqi.html


9
@Fosco สมมติว่าเขาทำอุปกรณ์ดังกล่าวเป็นผู้ผลิตอุปกรณ์ดั้งเดิม?
dascandy

41
@Fosco ใครสนใจ? เป็นคำถามที่ถูกต้องเหมือนที่ dascandy อธิบาย โดยทั่วไปแล้วจะไม่เกิดผลเมื่อมีคนตอบคำถามเช่นนี้โดยระบุว่า "คุณไม่ควรทำอย่างนั้น" เราได้รับความเข้าใจอะไรจากคำตอบแบบนั้น?
ZachM

3
การพูดถึงสิ่งที่ไม่ก่อให้เกิดผล .. คุณเพิ่งไปปาร์ตี้ Zach นี้มาช้ากว่า 2 ปีและคำถามดูแตกต่างไปจากเดิมมาก
Fosco

2
@ ฟอสโกฮ่า ๆ . นอกจากนี้ฉันสามารถยืนยันได้ว่าสิ่งนี้ยังใช้งานได้ในระบบปฏิบัติการ Android ใหม่ล่าสุด
POMATu

1
@LarsH ฉันเพิ่งติดตั้งแอพ F-Droid: พวกเขาไม่ได้ติดตั้งสิ่งต่างๆอย่างเงียบ ๆ พวกเขาเพียงแค่แจ้งตัวจัดการแพ็คเกจของ Android
Joaquin Iurchuk

คำตอบ:


60

เดิมพันครั้งแรกของคุณคือการมองเข้าไปในพื้นเมืองของ Android PackageInstaller ฉันขอแนะนำให้แก้ไขแอปนั้นตามที่คุณต้องการหรือเพียงแค่แยกฟังก์ชันที่จำเป็นออก


โดยเฉพาะอย่างยิ่งถ้าคุณดูPackageInstallerActivityและวิธีการonClickListener:

 public void onClick(View v) {
    if(v == mOk) {
        // Start subactivity to actually install the application
        Intent newIntent = new Intent();
        ...
        newIntent.setClass(this, InstallAppProgress.class);
        ...
        startActivity(newIntent);
        finish();
    } else if(v == mCancel) {
        // Cancel and finish
        finish();
    }
}

จากนั้นคุณจะสังเกตเห็นว่าตัวติดตั้งจริงอยู่ในคลาสInstallAppProgress ตรวจสอบระดับที่คุณจะพบว่าinitViewเป็นฟังก์ชั่นติดตั้งหลักและสิ่งสุดท้ายที่มันไม่สามารถเรียกร้องให้PackageManager's installPackageฟังก์ชั่น:

public void initView() {
...
pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
}

ขั้นตอนต่อไปคือการตรวจสอบPackageManagerซึ่งเป็นคลาสนามธรรม คุณจะพบinstallPackage(...)ฟังก์ชันที่นั่น ข่าวร้ายคือมีเครื่องหมาย @ ซ่อน ซึ่งหมายความว่าไม่สามารถใช้งานได้โดยตรง (คุณจะไม่สามารถรวบรวมด้วยการเรียกใช้วิธีนี้ได้)

 /**
  * @hide
  * ....
  */
  public abstract void installPackage(Uri packageURI,
             IPackageInstallObserver observer, 
             int flags,String installerPackageName); 

แต่คุณจะสามารถเข้าถึงวิธีการนี้ผ่านการสะท้อนกลับ

หากคุณมีความสนใจในวิธีการPackageManagerของinstallPackageฟังก์ชั่นจะดำเนินการจะดูที่PackageManagerService

สรุป

คุณจะต้องได้รับวัตถุผู้จัดการแพคเกจผ่าน'sContext getPackageManager()จากนั้นคุณจะเรียกinstallPackageใช้ฟังก์ชันผ่านการสะท้อน


2
ช่วยด้วย! เทคนิคนี้ส่งผลให้เกิดจาก: java.lang.SecurityException: ทั้งผู้ใช้ 10101 และกระบวนการปัจจุบันไม่มี android.permission.INSTALL_PACKAGES แม้ว่าแอปของฉันจะได้รับอนุญาต
ก็ตาม

14
แอปของคุณขอการอนุญาตนั้น แต่ Android ไม่ให้สิทธิ์นั้นกับแอปของบุคคลที่สาม ดูLogCatบันทึกที่เกี่ยวข้องกับสิทธิ์
inazaruk

@inazaruk ฉันอ่านว่าแอปที่ติดตั้งใน / system / app จะได้รับอนุญาตให้ใช้ install_pakages โดยอัตโนมัติ แต่ตามที่อธิบายไว้ในโพสต์นี้ดูเหมือนว่าจะไม่ทำงาน ขอคำแนะนำหน่อยได้ไหม
Zorb

3
ฉันจะเรียก installPackage ผ่านการสะท้อนกลับได้อย่างไร ที่จริงฉันไม่สามารถทำ Method method = aPackageManagerClass.getMethod ("installPackage", new Class [] {Uri.class, IPackageInstallObserver.class, Integer.TYPE, String.class}); เนื่องจาก IPackageInstallObserver ยังซ่อนอยู่มีใครช่วยฉันได้ไหมโพสต์รหัสที่ถูกต้องเพื่อทำการสะท้อนที่นี่
Shilaghae

8
ลิงก์ทั้งหมดในคำตอบนั้นตายแล้ว
Mayur Gangurde

13

ฉันตรวจสอบแล้วว่า ADB ติดตั้งแอพอย่างไร
- มันคัดลอก APK ไปยัง / data / local / tmp
- มันทำงาน 'shell: pm install /data/local/tmp/app.apk'

ฉันได้พยายามทำซ้ำพฤติกรรมนี้โดยทำ: (บนพีซีโดยใช้สาย usb)
adb push app.apk /sdcard/app.apk
adb shell
$ pm install /sdcard/app.apk
สิ่งนี้ได้ผล ติดตั้งแอปแล้ว

ฉันสร้างแอปพลิเคชัน (ชื่อ AppInstall) ซึ่งควรติดตั้งแอปอื่น
(ติดตั้งตามปกติไม่ใช่อุปกรณ์ที่รูท)
มันทำ:
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
แต่สิ่งนี้ทำให้เกิดข้อผิดพลาด:
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
ดูเหมือนว่าข้อผิดพลาดจะถูกส่งโดย pm ไม่ใช่ AppInstall
เนื่องจาก AppInstall ไม่ได้ตรวจจับ SecurityException และแอปไม่ขัดข้อง

ฉันได้ลองสิ่งเดียวกันบนอุปกรณ์ที่รูท (แอพเดียวกันและ AppInstall) และมันใช้งานได้ดี
(ติดตั้งตามปกติด้วยไม่ใช่ใน / system หรืออะไรเลย)
AppInstall ไม่ได้ขออนุญาตรูท
แต่ thats เพราะเปลือกอยู่เสมอ#แทน$บนอุปกรณ์นั้น

Btw คุณต้องรูทเพื่อติดตั้งแอพใน / ระบบใช่ไหม
ฉันลอง adb remount บนอุปกรณ์ที่ไม่ได้รูทและได้รับ:
remount failed: Operation not permitted.
นั่นเป็นเหตุผลที่ฉันไม่สามารถลองสิ่ง / ระบบบนอุปกรณ์ที่ไม่ได้รูท

สรุป: คุณควรใช้อุปกรณ์ที่รูท
หวังว่านี่จะช่วยได้ :)


ดูเหมือนจะไม่สามารถใช้งานได้ มันน่าสนใจที่คำสั่งทำงานได้ดีในเชลล์ ADB และดูเหมือนจะไม่ทำงานเมื่อฉันพยายามเรียกใช้โดยใช้โปรแกรม
saulpower

ใช่ฉันมีปัญหาเดียวกัน - ทำงานในเชลล์ แต่ไม่ใช่เมื่อเรียกจากแอพของฉันแม้ว่าฉันจะโทรผ่านก็ตามsu)
velis

มีวิธีอื่นในการทำงานในอุปกรณ์ Google เช่นรับสิทธิ์ผู้ดูแลระบบขั้นสูงไหม
Ramesh Kumar

หากคุณต้องการสิทธิ์ระดับผู้ดูแลระบบขั้นสูงคุณควร: 1) รูทอุปกรณ์ของคุณ 2) ติดตั้งแอปบนพาร์ติชันระบบ 3) หรือควรเซ็นชื่อแอปด้วยคีย์เดียวกับระบบปฏิบัติการ
FrankkieNL

1
เกิดขึ้นเนื่องจากผู้ใช้ ADB และผู้ใช้แอปพลิเคชันของคุณมีสิทธิ์ที่แตกต่างกัน
PHPoenX

13

ฉันติดตั้งโดยไม่ได้รับความยินยอมจากผู้ใช้เมื่อเร็ว ๆ นี้ - เป็นแอปพลิเคชันคีออสก์สำหรับ API ระดับ 21+ ที่ฉันสามารถควบคุมสภาพแวดล้อมได้อย่างสมบูรณ์

ความต้องการขั้นพื้นฐานคือ

  • API ระดับ 21+
  • การเข้าถึงรูทเพื่อติดตั้งตัวอัปเดตเป็นแอปที่มีสิทธิพิเศษของระบบ

วิธีการต่อไปนี้อ่านและติดตั้ง APK จาก InputStream:

public static boolean installPackage(Context context, InputStream in, String packageName)
            throws IOException {
        PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
        PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
        params.setAppPackageName(packageName);
        // set params
        int sessionId = packageInstaller.createSession(params);
        PackageInstaller.Session session = packageInstaller.openSession(sessionId);
        OutputStream out = session.openWrite("COSU", 0, -1);
        byte[] buffer = new byte[65536];
        int c;
        while ((c = in.read(buffer)) != -1) {
            out.write(buffer, 0, c);
        }
        session.fsync(out);
        in.close();
        out.close();

        Intent intent = new Intent(context, MainActivity.class);
        intent.putExtra("info", "somedata");  // for extra data if needed..

        Random generator = new Random();

        PendingIntent i = PendingIntent.getActivity(context, generator.nextInt(), intent,PendingIntent.FLAG_UPDATE_CURRENT);
            session.commit(i.getIntentSender());


        return true;
    }

รหัสต่อไปนี้เรียกการติดตั้ง

 try {
     InputStream is = getResources().openRawResource(R.raw.someapk_source);
                    installPackage(MainActivity.this, is, "com.example.apk");
     } catch (IOException e) {
                    Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
     }

สำหรับการทำงานทั้งหมดคุณต้องINSTALL_PACKAGESได้รับอนุญาตอย่างยิ่งไม่เช่นนั้นรหัสด้านบนจะล้มเหลวโดยไม่โต้ตอบ

<uses-permission
        android:name="android.permission.INSTALL_PACKAGES" />

เพื่อรับการอนุญาตนี้คุณต้องติดตั้ง APK ของคุณเป็นแอปพลิเคชันระบบซึ่งต้องใช้รูท (อย่างไรก็ตามหลังจากที่คุณติดตั้งแอปพลิเคชันตัวอัปเดตดูเหมือนว่าจะทำงานได้โดยไม่ต้องรูท)

ในการติดตั้งเป็นแอปพลิเคชันระบบฉันได้สร้าง APK ที่ลงชื่อแล้วและผลักดันด้วย

adb push updater.apk /sdcard/updater.apk

จากนั้นย้ายไปที่system/priv-app- ซึ่งต้องติดตั้ง FS ใหม่ (นี่คือสาเหตุที่ต้องใช้รูท)

adb shell
su
mount -o rw,remount /system
mv /sdcard/updater.apk /system/priv-app
chmod 644 /system/priv-app/updater.apk

ด้วยเหตุผลบางประการมันใช้ไม่ได้กับเวอร์ชันดีบักอย่างง่าย แต่logcatจะแสดงข้อมูลที่เป็นประโยชน์หากแอปพลิเคชันของคุณpriv-appไม่ถูกหยิบขึ้นมาด้วยเหตุผลบางประการ


"ด้วยเหตุผลบางอย่างมันใช้ไม่ได้กับเวอร์ชันดีบักแบบง่าย" คุณหมายถึงมันใช้งานได้ในรีลีสหรือเวอร์ชันดีบัก "แบบธรรมดา" อื่น ๆ
JM Lord

1
@JMLord มันใช้งานได้กับเวอร์ชันรีลีสที่ลงนามและใช้งานไม่ได้ทั้งกับเวอร์ชันดีบักที่ลงชื่อและไม่ได้ลงชื่อ- ฉันคิดว่ามันแปลกที่มันใช้ไม่ได้กับเวอร์ชันดีบักที่ลงชื่อฉัน แต่ฉันไม่มีเวลาตรวจสอบ อย่างไรก็ตามบันทึก Logcat ของระบบเป็นสิ่งสำคัญมากในการตรวจสอบว่ามีการติดตั้ง APK หรือไม่
Boris Treukhov

อันที่จริงแล้วด้วยเหตุผลบางประการการติดตั้งเมื่อปล่อยเป็นกุญแจสำคัญในการได้รับสิทธิ์ INSTALL_PACKAGES แอปสามารถทำงานในการแก้ไขข้อบกพร่องที่ลงชื่อจากแอป priv แต่คำขอสิทธิ์ถูกปฏิเสธ ขอบคุณมาก!
JM Lord

@BorisTreukhov เฮ้ฉันขอตรวจสอบกับคุณได้ไหมว่าพารามิเตอร์ packageName มีไว้เพื่ออะไร ฉันเปลี่ยน InputStream เป็น FileInputStream แต่ฉันได้รับข้อความแสดงข้อผิดพลาดนี้: ไม่สามารถแยกวิเคราะห์ /data/app/vmdl676191029.tmp/COSU

วิธีการติดตั้งแอพ system priv หลังจากคำสั่งเหล่านี้?
user2323471

8

คุณควรกำหนด

<uses-permission
    android:name="android.permission.INSTALL_PACKAGES" />

ในรายการของคุณหากคุณอยู่ในพาร์ติชันระบบ (/ system / app) หรือคุณมีแอปพลิเคชันของคุณที่ลงชื่อโดยผู้ผลิตคุณจะได้รับสิทธิ์ INSTALL_PACKAGES

ข้อเสนอแนะของฉันคือการสร้างโครงการ Android เล็ก ๆ ที่มีระดับความเข้ากันได้ 1.5 ที่ใช้ในการเรียก installPackages ผ่านการสะท้อนกลับและเพื่อส่งออก jar พร้อมวิธีการติดตั้งแพ็คเกจและเพื่อเรียกใช้วิธีการจริง จากนั้นเมื่อนำเข้า jar ในโครงการของคุณคุณจะพร้อมติดตั้งแพ็คเกจ


5

ฉันลองใช้ Android 4.2.2 ที่รูทแล้วและวิธีนี้ใช้ได้กับฉัน:

private void installApk(String filename) {
    File file = new File(filename); 
    if(file.exists()){
        try {   
            final String command = "pm install -r " + file.getAbsolutePath();
            Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command });
            proc.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
     }
}

2
คำถามเกี่ยวกับการติดตั้งแอปโดยไม่ต้องรูท แต่ระบบได้รับอนุญาต "INSTALL_PACKAGES" ฉันเห็น "su" ในคำตอบของคุณดังนั้นจึงต้องใช้รูท
POMATu

ขอบคุณมากสำหรับคำตอบนี้! ฉันมีรหัสเดียวกัน แต่ฉันใช้ "adb install -r" แทน "pm install -r" และมันจะใช้ไม่ได้สำหรับฉัน คุณช่วยฉันได้มากเวลาที่นี่!
Jeff.H

@ Vladmir ฉันต้องการความช่วยเหลือจากคุณ คุณให้เวลาฉันหน่อยได้ไหม ฉันจะขอบคุณมากสำหรับ u
twana eng

4

ฉันไม่รู้ว่าจะทำอย่างไรเพราะไม่มีใครตอบได้ในเวลานั้นและฉันไม่พบเอกสารเกี่ยวกับการอนุญาตนี้ ก็เลยหาทางออกของตัวเอง มันแย่กว่าของคุณ แต่นี่ก็เป็นวิธีแก้ปัญหาอยู่ดี

ฉันติดตั้ง busybox ซึ่งตั้งค่าสิทธิ์ 777 ให้กับ / data / app (ฉันไม่สนใจเรื่องความปลอดภัย) จากนั้นดำเนินการ "การติดตั้ง busybox" จากแอป วิธีนี้ใช้งานได้ แต่มีการรั่วไหลของระบบรักษาความปลอดภัยขนาดใหญ่ หากคุณตั้งค่าสิทธิ์ 777 ไม่จำเป็นต้องรูท


3
คุณใช้รหัสแบบนี้หรือไม่? Process install; install = Runtime.getRuntime().exec("/system/bin/busybox install " + myAPK.getAbsolutePath()); int iSuccess = install.waitFor();
ใครสักคน

4

คุณสามารถใช้ API ที่ซ่อนอยู่android.content.pm.IPackageInstallObserverโดยการสะท้อน:

public class PackageManagement {
    public static final int INSTALL_REPLACE_EXISTING = 0x00000002;
    public static final int INSTALL_SUCCEEDED = 1;

    private static Method installPackageMethod;
    private static Method deletePackageMethod;

    static {
        try {
            installPackageMethod = PackageManager.class.getMethod("installPackage", Uri.class, IPackageInstallObserver.class, Integer.TYPE, String.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public static void installPackage(PackageManager pm, Uri mPackageUri, IPackageInstallObserver observer, int installFlags, String installerPackageName) {
        try {
            installPackageMethod.invoke(pm, mPackageUri, observer, installFlags, installerPackageName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

นำเข้าandroid.content.pm.IPackageInstallObserverสู่โครงการของคุณ แอปของคุณต้องเป็นระบบ คุณต้องเปิดใช้งานการอนุญาตandroid.permission.INSTALL_PACKAGESในไฟล์รายการของคุณ


คุณได้ทดสอบโค้ดนี้บน Lollipop และ Marshamallow แล้วหรือยัง? ดูเหมือนเป็นแนวทางที่ยอดเยี่ยมสำหรับฉันและฉันต้องการใช้
Farhad Faghihi

ฉันได้ทดสอบจาก ICS เป็น Lollipop แล้ว
Hermann Poilpre

บรรทัดที่ต้องดูคือ "แอปของคุณต้องเป็นระบบ" ฉันค่อนข้างแน่ใจว่าสิ่งนี้ใช้ได้กับ lollipop หรืออะไรก็ตาม - เนื่องจากแอปของคุณเป็น "ระบบ" นั่นคือแอปของคุณมีสิทธิ์ของระบบ ในกรณีนี้คุณสามารถใช้โปรแกรมติดตั้งบรรทัดคำสั่งได้
Lassi Kinnunen

1
ฉันจะเรียกเมธอด installPackage ได้อย่างไร ความหมายฉันจะรับ IPackageInstallObserver ได้อย่างไร
phoebus

ค่าของ installFlags คืออะไร?
Shivam Kumar

3

คุณสามารถใช้คำสั่ง adb install เพื่อติดตั้ง / อัปเดต APK แบบเงียบ ๆ โค้ดตัวอย่างอยู่ด้านล่าง

public static void InstallAPK(String filename){
    File file = new File(filename); 
    if(file.exists()){
        try {   
            String command;
            filename = StringUtil.insertEscape(filename);
            command = "adb install -r " + filename;
            Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command });
            proc.waitFor();
        } catch (Exception e) {
        e.printStackTrace();
        }
     }
  }

StringUtils หมายถึงอะไร? กำลังเผชิญกับข้อผิดพลาดที่ไม่สามารถแก้ไขได้?
AndroidOptimist

ขอโทษฉันควรจะอธิบาย นี่คือคลาสที่กำหนดเองของฉันสำหรับสตริงและวิธีนี้ทำให้เส้นทางนั้นถูกต้อง คุณสามารถเพิกเฉยได้
ZeeShaN AbbAs

3
คลาส StringUtil คืออะไร คุณสามารถโพสต์วิธี StringUtil.insertEscape () ได้หรือไม่? เพราะถ้าฉันแสดงความคิดเห็นในบรรทัดนั้นฉันได้รับข้อยกเว้น Error running exec () คำสั่ง: [su, -c, adb install -r /storage/sdcard0/Android/data/com.install.file ขอบคุณล่วงหน้า
sandeepmaaram

java.io.IOException: เกิดข้อผิดพลาดในการเรียกใช้ exec () คำสั่ง: [su, -c, adb install -r /storage/emulated/0/download/SwipeAnimation.apk] Working Directory: null Environment: null - คุณสามารถอธิบายข้อผิดพลาด .. ? และหากมีการอนุญาตใด ๆ ในรายการ
Sandeep P

1
@ZeeShaNAbbAs หลังจากรูทแก้ปัญหาแล้ว .. ขอบคุณ
Sandeep P

1

วิชาบังคับก่อน:

APK ของคุณต้องได้รับการลงนามโดยระบบตามที่ระบุไว้อย่างถูกต้องก่อนหน้านี้ วิธีหนึ่งในการบรรลุเป้าหมายคือการสร้างอิมเมจ AOSP ด้วยตัวเองและเพิ่มซอร์สโค้ดลงในบิลด์

รหัส:

เมื่อติดตั้งเป็นแอประบบแล้วคุณสามารถใช้วิธีการจัดการแพ็คเกจเพื่อติดตั้งและถอนการติดตั้ง APK ดังต่อไปนี้:

ติดตั้ง:

public boolean install(final String apkPath, final Context context) {
    Log.d(TAG, "Installing apk at " + apkPath);
    try {
        final Uri apkUri = Uri.fromFile(new File(apkPath));
        final String installerPackageName = "MyInstaller";
        context.getPackageManager().installPackage(apkUri, installObserver, PackageManager.INSTALL_REPLACE_EXISTING, installerPackageName);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

ถอนการติดตั้ง:

public boolean uninstall(final String packageName, final Context context) {
    Log.d(TAG, "Uninstalling package " + packageName);
    try {
        context.getPackageManager().deletePackage(packageName, deleteObserver, PackageManager.DELETE_ALL_USERS);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

หากต้องการให้โทรกลับเมื่อติดตั้ง / ถอนการติดตั้ง APK ของคุณคุณสามารถใช้สิ่งนี้:

/**
 * Callback after a package was installed be it success or failure.
 */
private class InstallObserver implements IPackageInstallObserver {

    @Override
    public void packageInstalled(String packageName, int returnCode) throws RemoteException {

        if (packageName != null) {
            Log.d(TAG, "Successfully installed package " + packageName);
            callback.onAppInstalled(true, packageName);
        } else {
            Log.e(TAG, "Failed to install package.");
            callback.onAppInstalled(false, null);
        }
    }

    @Override
    public IBinder asBinder() {
        return null;
    }
}

/**
 * Callback after a package was deleted be it success or failure.
 */
private class DeleteObserver implements IPackageDeleteObserver {

    @Override
    public void packageDeleted(String packageName, int returnCode) throws RemoteException {
        if (packageName != null) {
            Log.d(TAG, "Successfully uninstalled package " + packageName);
            callback.onAppUninstalled(true, packageName);
        } else {
            Log.e(TAG, "Failed to uninstall package.");
            callback.onAppUninstalled(false, null);
        }
    }

    @Override
    public IBinder asBinder() {
        return null;
    }
}

/**
 * Callback to give the flow back to the calling class.
 */
public interface InstallerCallback {
    void onAppInstalled(final boolean success, final String packageName);
    void onAppUninstalled(final boolean success, final String packageName);
}

===> ทดสอบบน Android 8.1 และทำงานได้ดี


ฉันต้องการความช่วยเหลือจากคุณ. คุณให้เวลาฉันหน่อยได้ไหม ฉันจะขอบคุณมากสำหรับ u
twana eng

ฉันต้องการความช่วยเหลือจากคุณ ฉันอยากรู้ว่าเราจะสร้าง AOSP ของตัวเองได้อย่างไร
twana eng

0

ฉันสร้างแอปทดสอบสำหรับการติดตั้งแบบไม่โต้ตอบโดยใช้เมธอด PackageManager.installPackage

ฉันได้รับเมธอด installPackage ผ่านการสะท้อนและสร้างอินเทอร์เฟซ android.content.pm.IPackageInstallObserver ในโฟลเดอร์ src ของฉัน (เพราะมันซ่อนอยู่ในแพ็คเกจ android.content.pm)

เมื่อฉันเรียกใช้ installPackage ฉันได้รับ SecurityException พร้อมตัวบ่งชี้สตริงว่าแอปของฉันไม่มี android.permission.INSTALL_PACKAGES แต่กำหนดไว้ใน AndroidManifest.xml

ฉันคิดว่ามันเป็นไปไม่ได้ที่จะใช้วิธีนี้

ปล. ฉันทดสอบใน Android SDK 2.3 และ 4.0 อาจจะใช้ได้กับเวอร์ชันก่อนหน้านี้


มันทำงานใน 4.1 และ 4.0 รวมถึงใน Android เวอร์ชันใด ๆ ที่สูงกว่า 2.1 (รวมถึง 2.1) ตอนนี้ฉันใช้ 4.0 SDK คุณต้องเพิ่มลงในโฟลเดอร์ / system / app มิฉะนั้นแอปของคุณจะไม่มีสิทธิ์ระดับระบบที่จำเป็น (ไม่ใช่รูท) นอกจากนี้ฉันยังสามารถลบแอพแบบเงียบ ๆ ด้วยวิธีนี้ให้ตรวจสอบคำถามอื่น ๆ ที่เกี่ยวข้องกับการลบ
POMATu

ใช่มันใช้งานได้ แต่ต้องใช้สิทธิ์ของรูทเท่านั้น และไม่สามารถติดตั้งแอปลงในระบบ / แอปบนอุปกรณ์ที่ไม่ได้รูท
АндрейМосквичёв

ไม่ใช้รูท แต่มีสิทธิ์ระดับระบบ คุณสามารถเพิ่มลงใน / system / app ได้หากคุณเป็นผู้ผลิตเฟิร์มแวร์ ในกรณีของฉัน - ฉัน (ฉันขอให้ผู้ผลิตอุปกรณ์เพิ่ม apks ของฉันไปยังเฟิร์มแวร์) คุณจะไม่สามารถติดตั้งแอปแบบเงียบ ๆ ได้ด้วยวิธีอื่นมิฉะนั้นจะเป็นช่องโหว่ด้านความปลอดภัยที่ดี
POMATu

เกี่ยวกับช่องโหว่ด้านความปลอดภัย - ฉันเห็นด้วยอย่างยิ่งกับคุณ และจะแปลกใจสำหรับฉันถ้าวิธีนี้ใช้ได้กับแอพใด ๆ ฉันจะติดตั้งแอปลงใน / system / app โดยไม่ต้องรูทได้อย่างไร? ฉันไม่ใช่ผู้ผลิต
АндрейМосквичёв

1
หากไม่มีรูทหรือ reflashing คุณไม่สามารถทำได้
POMATu


0

แอปพลิเคชันของบุคคลที่สามไม่สามารถติดตั้งแอป Android ได้ อย่างไรก็ตามแอปพลิเคชันของบุคคลที่สามสามารถขอให้ระบบปฏิบัติการ Android ติดตั้งแอปพลิเคชันได้

ดังนั้นคุณควรกำหนดสิ่งนี้:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file:///sdcard/app.apk", "application/vnd.android.package-archive");
startActivity(intent);

คุณยังสามารถลองติดตั้งเป็นแอประบบเพื่อให้สิทธิ์และละเว้นการกำหนดนี้ (ต้องรูท)

คุณสามารถเรียกใช้คำสั่งต่อไปนี้บนแอปของบุคคลที่สามเพื่อติดตั้งแอปบนอุปกรณ์ที่รูท

รหัสคือ:

private void installApk(String filename) {
File file = new File(filename); 
if(file.exists()){
    try {   
        final String command = "pm install -r " + file.getAbsolutePath();
        Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command });
        proc.waitFor();
    } catch (Exception e) {
        e.printStackTrace();
    }
 }
}

ฉันหวังว่าคำตอบนี้จะเป็นประโยชน์สำหรับคุณ


0

เป็นไปได้ที่จะทำการติดตั้งแบบเงียบบน Android 6 ขึ้นไป ใช้ฟังก์ชั่นที่ให้มาในคำตอบโดย Boris Treukhov ละเว้นสิ่งอื่นใดในโพสต์ไม่จำเป็นต้องรูท

ติดตั้งแอปของคุณในฐานะผู้ดูแลอุปกรณ์คุณสามารถมีโหมดคีออสก์เต็มรูปแบบพร้อมการติดตั้งการอัปเดตแบบไม่โต้ตอบ


0

ฉันตรวจสอบคำตอบทั้งหมดแล้วข้อสรุปดูเหมือนว่าคุณต้องมีการเข้าถึงรูทอุปกรณ์ก่อนเพื่อให้ใช้งานได้

แต่แล้วฉันพบว่าบทความเหล่านี้มีประโยชน์มาก เนื่องจากฉันกำลังสร้างอุปกรณ์ "ของ บริษัท "

วิธีอัปเดตแอป Android แบบเงียบ ๆ โดยไม่ต้องโต้ตอบกับผู้ใช้

เจ้าของอุปกรณ์ Android - แอปน้อยที่สุด

นี่คือเอกสารของ Google เกี่ยวกับ "อุปกรณ์ที่มีการจัดการ"

อุปกรณ์ที่มีการจัดการเต็มรูปแบบ



-6

! / bin / ทุบตี

f=/home/cox/myapp.apk   #or $1 if input from terminal.

#backup env var
backup=$LD_LIBRARY_PATH
LD_LIBRARY_PATH=/vendor/lib:/system/lib
myTemp=/sdcard/temp.apk
adb push $f $myTemp
adb shell pm install -r $myTemp
#restore env var
LD_LIBRARY_PATH=$backup

สิ่งนี้ใช้ได้กับฉัน ฉันเรียกใช้สิ่งนี้บน ubuntu 12.04 บนเทอร์มินัลเชลล์

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