Installere apps stille, med innvilget INSTALL_PACKAGES tillatelse

stemmer
80

Jeg prøver å stille installere apk inn i systemet. Appen min ligger i / system / app og hell gitt tillatelse android.permission.INSTALL_PACKAGES

Men jeg kan ikke finne noe sted hvordan du bruker denne tillatelsen. Jeg prøvde å kopiere filer til / data / app og hadde ingen suksess. Også jeg prøvd å bruke denne koden

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

Men denne koden åpner standard installasjonsdialogen. Hvordan kan jeg installere app stille uten rot med innvilget android.permission.INSTALL_PACKAGES?

PS Jeg skriver en app som vil installere mange APK fra mappen inn i systemet på den første start (bytt Setup Wizard). Jeg trenger det for å gjøre firmware lettere.

Hvis du tror at jeg skriver et virus: Alle programmene er installert i / data / app. Tillatelse Install_packages kan bare gis til systemnivå programmer som ligger i / system / app eller signert med systemnøkkel. Så virus kan ikke komme dit.

Som sagt http://www.mail-archive.com/android-porting@googlegroups.com/msg06281.html apps kan stille installert hvis de har install_packages tillatelse. Videre trenger du ikke Install_packages tillatelse til å installere pakker ikke stille. pluss http://www.androidzoom.com/android_applications/tools/silent-installer_wgqi.html

Publisert på 27/04/2011 klokken 10:21
kilden bruker
På andre språk...                            


16 svar

stemmer
58

Din første alternativet er å se nærmere på Android innfødte PackageInstaller . Jeg vil anbefale å modifisere at app slik du liker, eller bare trekke ut ønsket funksjonalitet.


Spesielt hvis du ser inn PackageInstallerActivity og dens metode 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();
    }
}

Deretter vil du legge merke til at selve installasjons ligger i InstallAppProgress klasse. Inspeksjon den klassen du vil finne at initViewer kjernen installasjonsfunksjonen, og den siste ting den gjør er å ringe til PackageManagersin installPackagefunksjon:

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

Neste trinn er å inspisere Package , som er abstrakt klasse. Du vil finne installPackage(...)funksjon der. Den dårlige nyheten er at det er merket med @hide. Dette betyr at det ikke er direkte tilgjengelig (du vil ikke være i stand til å kompilere med kall til denne metoden).

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

Men du vil kunne få tilgang til dette metoder via refleksjon.

Hvis du er interessert i hvordan PackageManager's installPackagefunksjonen er implementert, ta en titt på PackageManagerService .

Sammendrag

Du må få pakkehåndterer objekt via Context's getPackageManager(). Deretter vil du kalle installPackagefunksjon via refleksjon.

Svarte 27/04/2011 kl. 11:57
kilden bruker

stemmer
4

Jeg hadde ingen anelse om hvordan du gjør dette, fordi ingen svarte den gang, og jeg fant ingen dokumentasjon om denne tillatelsen. Så jeg fant min egen løsning. Det er worser at din, men dette er en løsning uansett.

Jeg installerte busybox, som setter 777 tillatelse til / data / app (jeg ikke bryr seg om sikkerhet). Så bare utført "busybox install" fra app. Dette fungerer, men har en stor sikkerhetsrisiko lekkasje. Hvis du angir tillatelser 777, som kreves ingen rot.

Svarte 19/07/2011 kl. 09:25
kilden bruker

stemmer
8

Du bør definere

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

i manifestet, så hvis enten du er i systempartisjonen (/ system / app) eller du har din søknad undertegnet av produsenten, er du nødt til INSTALL_PACKAGES tillatelse.

Mitt forslag er å lage en liten android prosjekt med 1,5 kompatibilitet nivå pleide å kalle installPackages via refleksjon og til å eksportere en krukke med metoder for å installere pakker, og å kalle den virkelige metoder. Deretter ved å importere glasset i prosjektet vil du være klar til å installere pakker.

Svarte 13/02/2012 kl. 08:21
kilden bruker

stemmer
11

Jeg har sjekket hvordan ADB installerer apps.
- Det kopier APK til / data / local / tmp
- den kjører 'shell: pm installere /data/local/tmp/app.apk'

Jeg har prøvd å gjenskape dette problemet ved å gjøre: (på pc, ved hjelp av usb-kabel)
adb push app.apk /sdcard/app.apk
adb shell
$ pm install /sdcard/app.apk
Dette fungerer. Programmet er installert.

Jeg gjorde et program (kalt AppInstall) som skal installere annen app.
(installert normalt, ikke-forankret enhet)
Det gjør:
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
Men dette gir feil:
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
Det virker som feilen er kastet av pm, ikke av AppInstall.
Fordi SecurityException ikke catched av AppInstall og app ikke krasjer.

Jeg har prøvd det samme på en rotfestet enhet (samme app og AppInstall), og det virket som en sjarm.
(Også installeres normalt, ikke i / system eller noe)
AppInstall ikke engang spørre root-tillatelse.
Men dvs fordi skallet er alltid #i stedet for $på den enheten.

Btw, trenger du root for å installere en app i / system, riktig?
Jeg prøvde ADB remount på ikke-rotfestet enhet og fikk:
remount failed: Operation not permitted.
Det er derfor jeg ikke kunne prøve / system ting på ikke-rotfestet enhet.

Konklusjon: Du bør bruke en rotfestet enhet
Håper dette hjelper :)

Svarte 20/05/2012 kl. 11:51
kilden bruker

stemmer
0

Jeg gjorde en test app for stille installasjoner, ved hjelp PackageManager.installPackage metode.

Jeg får Install metoden gjennom refleksjon, og gjort android.content.pm.IPackageInstallObserver grensesnittet i min src mappe (fordi det er skjult i android.content.pm pakken).

Når jeg kjører Install, jeg fikk SecurityException med streng indikasjon på at min app har ingen android.permission.INSTALL_PACKAGES, men det er definert i AndroidManifest.xml.

Så, jeg tror, ​​er det ikke mulig å bruke denne metoden.

PS. Jeg testet i på Android SDK 2.3 og 4.0. Kanskje det vil fungere med tidligere versjoner.

Svarte 13/02/2013 kl. 15:48
kilden bruker

stemmer
3

Her er et veldig fint innlegg om dette temaet. Det hjalp meg mye.

Svarte 04/07/2013 kl. 16:29
kilden bruker

stemmer
3

Du kan ganske enkelt bruke adb installere kommando for å installere / oppdatere APK lydløst. Eksempelkode er under

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();
        }
     }
  }
Svarte 29/08/2013 kl. 08:37
kilden bruker

stemmer
0

Prøv dette LD_LIBRARY_PATH=/vendor/lib:/system/libfør pm installere. Det fungerer godt.

Svarte 04/02/2014 kl. 02:10
kilden bruker

stemmer
5

Jeg prøvde på rotfestet Android 4.2.2 og denne metoden fungerer for meg:

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();
        }
     }
}
Svarte 20/02/2014 kl. 06:44
kilden bruker

stemmer
-5

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

Dette fungerer for meg. Jeg kjører dette på ubuntu 12.04, på shell terminal.

Svarte 06/06/2014 kl. 03:53
kilden bruker

stemmer
4

Du kan bruke skjulte API android.content.pm.IPackageInstallObserverved refleksjon:

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

Importere android.content.pm.IPackageInstallObserverinn i prosjektet. Din app må være system. Du må aktivere tillatelse android.permission.INSTALL_PACKAGESi manifestfilen.

Svarte 27/11/2014 kl. 11:21
kilden bruker

stemmer
7

Jeg har gjennomført installasjon uten brukerens samtykke nylig - det var en kiosk søknad om API-nivå 21+ der jeg hadde full kontroll over miljøet.

De grunnleggende kravene er

  • API-nivå 21+
  • root-tilgang for å installere oppdateringsprogrammet som et system privilegert app.

Følgende metode leser og installerer APK fra Input:

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

Følgende kode kaller installasjonen

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

for hele greia til å jobbe du desperat trenger INSTALL_PACKAGEStillatelse, eller koden ovenfor vil mislykkes stille

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

å få denne tillatelsen må du installere APK som System applikasjon som krever root (men etter at du har installert oppdateringsprogrammet det ser ut til å fungere uten root)

Å installere som systemisk jeg opprettet en signert APK og dyttet den med

adb push updater.apk /sdcard/updater.apk

og deretter flyttet til det system/priv-app- noe som krever ny montering FS (dette er grunnen til at roten er nødvendig)

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

en eller annen grunn gjorde det ikke med enkle debug-versjon, men logcat viser nyttig informasjon om programmet i priv-appikke er plukket opp av en eller annen grunn.

Svarte 05/11/2016 kl. 14:39
kilden bruker

stemmer
0

En tredje parts program kan ikke installere en Android App sliently. Imidlertid kan en tredje part applikasjonen be Android OS for å installere et program.

Så du bør definere dette:

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

Du kan også prøve å installere det som et system app for å gi tillatelse og ignorere denne definere. (Root Påkrevd)

Du kan kjøre følgende kommando på tredje parts app for å installere en app på rotfestet enhet.

Koden er:

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

Jeg håper at dette svaret er nyttig for deg.

Svarte 16/02/2018 kl. 15:55
kilden bruker

stemmer
0

Forutsetning:

APK må undertegnes av systemet som riktig påpekt tidligere. En måte å oppnå dette er å bygge AOSP bilde selv og legge kildekoden inn i bygget.

Kode:

Når programmet er installert som et system app, kan du bruke pakkebehandleren metoder for å installere og avinstallere en APK som følgende:

Installere:

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

Avinstaller:

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

Å ha en tilbakeringing når APK er installert / avinstallert du kan bruke denne:

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

===> Testet på Android 8.1 og fungerte bra.

Svarte 26/07/2018 kl. 16:06
kilden bruker

stemmer
0

Det er mulig å gjøre stille installasjon på Android 6 og nyere. Ved hjelp av funksjonen som følger med i svaret ved Boris Treukhov, ignorere alt annet i posten, er roten ikke nødvendig heller.

Installere app som enhetsadministrasjon, kan du ha full kioskmodus med stille installasjon av oppdateringer i bakgrunnen.

Svarte 27/01/2019 kl. 15:13
kilden bruker

stemmer
0

Jeg sjekket alle svarene, synes konklusjonen å være at du må ha root-tilgang til enheten første til å gjøre det arbeidet.

Men så fant jeg disse artiklene svært nyttig. Siden jeg gjør "selskapet eide" enheter.

Hvordan oppdatere Android App stille uten brukermedvirkning

Android-enhet Eier - Minimal App

Her er Googles dokumentasjonen om "styrt-enhet"

Fullt administrert enhet

Svarte 15/03/2019 kl. 07:40
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more