Instaluj aplikacje po cichu, z przyznanym pozwoleniem INSTALL PACKAGES

Próbuję po cichu zainstalować apk w systemie. Moja aplikacja znajduje się w /system / app i pomyślnie przyznano uprawnienia " android.pozwolenie.INSTALL_PACKAGES "

Jednak nigdzie nie mogę znaleźć, jak wykorzystać to pozwolenie. Próbowałem skopiować pliki do /data / app i nie powiodło mi się. Również próbowałem użyć tego kodu

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

Ale ten kod otwiera standardowe okno instalacji. Jak zainstalować aplikację bez roota z granted android.permission.INSTALL_PACKAGES?

[[2]] PS piszę aplikację, która będzie zainstaluj wiele plików APK z folderu do systemu przy pierwszym uruchomieniu (zastąp Kreatora instalacji). Potrzebuję go, żeby było lżejsze.

Jeśli uważasz, że piszę wirusa: Wszystkie programy są zainstalowane w /data/app. Uprawnienia Install_packages mogą być przyznane tylko programom na poziomie systemu znajdującym się w /system/app lub podpisanym kluczem systemowym. Więc wirus nie może się tam dostać.

Jak powiedział http://www.mail-archive.com/[email protected]/msg06281.html aplikacje mogą być ciche zainstalowane, jeśli mają uprawnienia install_packages. Co więcej, nie potrzebujesz uprawnień Install_packages, aby instalować pakiety nie po cichu. Plus http://www.androidzoom.com/android_applications/tools/silent-installer_wgqi.html

Author: Milad Faridnia, 2011-04-27

14 answers

Twoim pierwszym zakładem jest sprawdzenie natywnego pakietu Androida PackageInstaller . Polecam modyfikowanie tej aplikacji tak, jak chcesz, lub po prostu wyodrębnić wymaganą funkcjonalność.


W szczególności, jeśli przyjrzysz się Pakietinstalleractivity i jej metodzie 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();
    }
}

Wtedy zauważysz, że rzeczywisty instalator znajduje się w klasie InstallAppProgress. Sprawdzając tę klasę przekonasz się, że initView jest podstawową funkcją Instalatora, a ostateczna to, co robi, to wywołanie PackageManager ' s installPackage function:

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

Kolejnym krokiem jest sprawdzenie Packagemanagera, czyli klasy abstrakcyjnej. Znajdziesz tam installPackage(...) funkcję. Zła wiadomość jest taka, że jest oznaczona @hide. Oznacza to, że nie jest bezpośrednio dostępna (nie będzie można kompilować z wywołaniem tej metody).

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

Ale będziesz mógł uzyskać dostęp do tych metod poprzez refleksję.

Jeśli interesuje Cię jak zaimplementowana jest funkcja PackageManager, spójrz na PackageManagerService .

Podsumowanie

Musisz pobrać obiekt package manager Poprzez Context ' s getPackageManager(). Następnie wywołasz installPackage funkcję poprzez odbicie.

 58
Author: inazaruk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-27 14:34:35

Sprawdziłem jak ADB instaluje aplikacje.
- Kopiuje apk do /data / local / tmp
- uruchamia powłokę: pm install/data/local/tmp / app.apk"

Próbowałem odtworzyć to zachowanie robiąc: (na pc, za pomocą kabla usb)
adb push app.apk /sdcard/app.apk
adb shell
$ pm install /sdcard/app.apk
To działa. Aplikacja jest zainstalowana.

Zrobiłem aplikację (o nazwie AppInstall), która powinna zainstalować drugą aplikację.
(zainstalowany normalnie, urządzenie nie rooted)
Tak.:
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
Ale to daje błąd:
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
Wygląda na to, że błąd jest wyrzucany przez pm, a nie przez AppInstall.
Ponieważ SecurityException nie jest przechwytywany przez AppInstall i aplikacja nie ulega awarii.

Próbowałem tego samego na zakorzenionym urządzeniu (ta sama aplikacja i AppInstall) i działało jak urok.
(Również normalnie zainstalowany, Nie w / system lub cokolwiek)
AppInstall nawet nie zapytał root-uprawnienia.
Ale to dlatego, że powłoka jest zawsze # zamiast $ na tym urządzeniu.

Btw, ty potrzebujesz roota, aby zainstalować aplikację w systemie, prawda?
Próbowałem ADB remount na urządzeniu non-rooted i dostałem:
remount failed: Operation not permitted.
Dlatego nie mogłem wypróbować / system rzeczy na urządzeniu non-rooted.

Wniosek: powinieneś użyć zakorzenionego urządzenia
Mam nadzieję, że to pomoże:)

 11
Author: FrankkieNL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-20 13:51:40

Powinieneś zdefiniować

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

W manifeście, to jeśli jesteś w partycji systemowej (/system / app) lub masz aplikację podpisaną przez producenta, Będziesz mieć uprawnienia INSTALL_PACKAGES.

Moja sugestia to stworzenie małego projektu dla Androida z poziomem kompatybilności 1.5 używanego do wywoływania installPackages poprzez reflection i eksportowania jar z metodami do instalowania pakietów i wywoływania rzeczywistych metod. Następnie, importując jar do swojego projektu, będziesz bądź gotowy do instalacji pakietów.

 8
Author: iLRedEiMAtTi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-03 21:57:24

Od niedawna realizuję instalację bez zgody Użytkownika - była to aplikacja kiosk dla poziomu API 21+ , gdzie miałem pełną kontrolę nad środowiskiem.

Podstawowe wymagania to

  • API poziom 21 +
  • root access aby zainstalować updater jako systemową aplikację uprzywilejowaną.

Następująca metoda odczytuje i instaluje APK z 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;
    }

Poniższy kod wywołuje instalację

 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();
     }

Dla całego do pracy potrzebujesz INSTALL_PACKAGES pozwolenia, albo powyższy kod zawiedzie po cichu

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

Aby uzyskać to pozwolenie, musisz zainstalować APK jako aplikację systemową, która wymaga roota (jednak po zainstalowaniu aplikacji updater wydaje się działać bez roota)

Aby zainstalować jako aplikację systemową utworzyłem podpisany APK i wcisnąłem go za pomocą

adb push updater.apk /sdcard/updater.apk

A następnie przeniósł go do system/priv-app - co wymaga remountu FS (dlatego root jest wymagane)

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

Z jakiegoś powodu nie działa z prostą wersją debugowania, ale logcat pokazuje przydatne informacje, jeśli aplikacja w priv-app nie jest z jakiegoś powodu pobierana.

 7
Author: Boris Treukhov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-06 07:08:44

Próbowałem na rooted Android 4.2.2 i ta metoda działa dla mnie:

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();
        }
     }
}
 5
Author: Vladimir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-20 09:44:08

Nie miałem pojęcia, jak to zrobić, ponieważ nikt nie odpowiedział tym razem, i nie znalazłem dokumentacji na temat tego pozwolenia. Więc znalazłem własne rozwiązanie. To gorsze niż Twoje, ale i tak jest to rozwiązanie.

Zainstalowałem busybox, który ustawił uprawnienia 777 do /data / app(nie dbam o bezpieczeństwo). Następnie wykonaj "busybox install" z aplikacji. To działa, ale ma duży przeciek bezpieczeństwa. Jeśli ustawisz uprawnienia 777, nie jest Wymagany root.

 4
Author: POMATu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-19 11:25:26

Możesz użyć ukrytego API android.content.pm.IPackageInstallObserver poprzez odbicie:

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();
        }
    }
}

Importuj android.content.pm.IPackageInstallObserver do swojego projektu. Twoja aplikacja musi być systemowa. Musisz aktywować uprawnienia android.permission.INSTALL_PACKAGES w swoim pliku manifestu.

 4
Author: Hermann Poilpre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-08 02:42:58

Tutaj jest bardzo ładny post na ten temat. Bardzo mi to pomogło.

 3
Author: anbuf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-04 18:29:02

Możesz po prostu użyć polecenia install adb, aby zainstalować / zaktualizować APK w ciszy. Przykładowy kod znajduje się poniżej

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();
        }
     }
  }
 3
Author: ZeeShaN AbbAs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-29 10:37:14

Zrobiłem aplikację testową do cichych instalacji, używając PackageManager.metoda installPackage.

Otrzymałem metodę installPackage poprzez odbicie i zrobiłem interfejs android. content. pm. IPackageInstallObserver w moim folderze src (bo jest ukryty w android.content.pm pakiet).

Kiedy uruchamiam installPackage, mam SecurityException ze wskazaniem string, że moja aplikacja nie ma Androida.pozwolenie.INSTALL_PACKAGES, ale zdefiniowany w AndroidManifest.xml.

Więc myślę, że to nie możliwość zastosowania tej metody.

PS. Testowałem na Android SDK 2.3 i 4.0. Może zadziała z wcześniejszymi wersjami.

 0
Author: Андрей Москвичёв,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-13 18:48:58

Spróbuj tego LD_LIBRARY_PATH=/vendor/lib:/system/lib przed instalacją pm. Działa dobrze.

 0
Author: Ankita Gujar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-04 05:32:54

Aplikacja innej firmy nie może zainstalować aplikacji na Androida. Jednak aplikacja innej firmy może poprosić SYSTEM OPERACYJNY Android o zainstalowanie aplikacji.

Więc powinieneś zdefiniować to:

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

Możesz również spróbować zainstalować go jako aplikację systemową, aby przyznać uprawnienia i zignorować to zdefiniowanie. (Root Required)

Możesz uruchomić następujące polecenie w aplikacji 3rd party, aby zainstalować aplikację na urządzeniu zakorzenionym.

Kod to:

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();
    }
 }
}

Mam nadzieję, że ta odpowiedź jest pomocne dla Ciebie.

 0
Author: Benjamin Pasalic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 17:55:40

Warunek:

Twój APK musi być podpisany przez system, jak poprawnie wskazano wcześniej. Jednym ze sposobów, aby to osiągnąć, jest samodzielne zbudowanie obrazu AOSP i dodanie kodu źródłowego do kompilacji.

Kod:

Po zainstalowaniu jako aplikacja systemowa, możesz użyć metod menedżera pakietów, aby zainstalować i odinstalować APK w następujący sposób:

Zainstaluj:

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;
    }
}

Odinstaluj:

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;
    }
}

Aby uzyskać oddzwonienie po zainstalowaniu / odinstalowaniu APK możesz użyć tego:

/**
 * 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);
}

===> testowany na Androidzie 8.1 i działał dobrze.

 0
Author: phoebus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-26 17:06:51

!/ bin / bash

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
To mi pasuje. Uruchamiam to na ubuntu 12.04, na terminalu shell.
 -6
Author: cox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-06 05:53:12