it-swarm.com.de

Wie installiere/aktualisiere/entferne ich APK mithilfe der "PackageInstaller" -Klasse in Android L?

Bitte überprüfen Sie die Klasse und geben Sie mir einen Vorschlag, wie Sie sie verwenden können https://developer.Android.com/reference/Android/content/pm/PackageInstaller.htmlhttps://developer.Android.com/reference/Android/content/pm/PackageInstaller.Session.html

Bitte geben Sie mir ein Beispiel für die Installation/Aktualisierung/Deinstallation der App. Kann es sein, dass die neue Anwendung im Geräteprofilbesitzer installiert wird?

22
Sud

Es ist ohne Systemberechtigungen ab Android M möglich möglich.

if ((mPm.checkUidPermission(Android.Manifest.permission.INSTALL_PACKAGES, installerUid)
        == PackageManager.PERMISSION_GRANTED)
        || (installerUid == Process.ROOT_UID)
        || mIsInstallerDeviceOwner) {
    mPermissionsAccepted = true;
} else {
    mPermissionsAccepted = false;
}

Automatische Installation und Deinstallation von Apps durch den Geräteeigentümer:

Ein Gerätebesitzer kann Anwendungen jetzt unabhängig von Google Play for Work mithilfe der PackageInstaller-APIs unbeaufsichtigt installieren und deinstallieren.

Mehr in diesem Link.


Dies ist ab Android 6.0 möglich.

  • Machen Sie Ihre App zum Besitzer des Geräts.

Sobald Ihre App die Berechtigung für den Gerätebesitzer erhält, können wir ohne Benutzereingriff unbeaufsichtigt installieren, deinstallieren und aktualisieren.

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

    session.commit(createIntentSender(context, sessionId));
    return true;
}



private static IntentSender createIntentSender(Context context, int sessionId) {
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                context,
                sessionId,
                new Intent(ACTION_INSTALL_COMPLETE),
                0);
        return pendingIntent.getIntentSender();
    }

Deinstallation:

String appPackage = "com.your.app.package";
Intent intent = new Intent(getActivity(), getActivity().getClass());
PendingIntent sender = PendingIntent.getActivity(getActivity(), 0, intent, 0);
PackageInstaller mPackageInstaller = getActivity().getPackageManager().getPackageInstaller();
mPackageInstaller.uninstall(appPackage, sender.getIntentSender());

Git Repo hier .

20
amalBit

Mit PackageInstaller.Session.commit () können Sie keine Drittanbieteranwendung im neu erstellten Benutzer ohne bestimmte "Rechte" installieren.
.__ Sie benötigen entweder: 

  • die Berechtigung INSTALL_PACKAGES . Diese Erlaubnis ist jedoch nicht für Anwendungen von Drittanbietern verfügbar. Selbst mit Ihrer Profilbesitzer-App haben Sie diese spezielle Berechtigung nicht.
  • Führen Sie den Prozess als ROOT_UID aus. Was bedeutet, dass Sie das Gerät rooten müssen. 

Von dem Android-Quellcode

if ((mPm.checkUidPermission(Android.Manifest.permission.INSTALL_PACKAGES, installerUid) == PackageManager.PERMISSION_GRANTED) 
   || (installerUid == Process.ROOT_UID)) {
    mPermissionsAccepted = true;
} else {
    mPermissionsAccepted = false;
}

Wenn Sie weder über Rootzugriff noch über die Berechtigung INSTALL_PACKAGES verfügen, wird der Benutzer in einer Meldung gefragt, ob er die Berechtigungen bestätigt. Diese Bestätigung wird dann während des Festschreibens process der PackageInstaller's-Sitzung verwendet. Offensichtlich ist dies in diesem Fall nicht transparent, da der Benutzer die Installation Ihrer Apps manuell bestätigen muss.

6
Florent Dupont

Die bereitgestellte Installationsmethode @amalBit hat bei mir nicht funktioniert. Es ist merkwürdig, da dies so ist, wie es in Google Sample implementiert ist.

Diese Antwort hat mir geholfen, eine Lösung zu finden. Ich musste einige Teile des Codes ändern. Hier ist meine Implementierung:

public static void installPackage(Context context, InputStream inputStream)
        throws IOException {
    PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
    int sessionId = packageInstaller.createSession(new PackageInstaller
            .SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));
    PackageInstaller.Session session = packageInstaller.openSession(sessionId);

    long sizeBytes = 0;

    OutputStream out = null;
    out = session.openWrite("my_app_session", 0, sizeBytes);

    int total = 0;
    byte[] buffer = new byte[65536];
    int c;
    while ((c = inputStream.read(buffer)) != -1) {
        total += c;
        out.write(buffer, 0, c);
    }
    session.fsync(out);
    inputStream.close();
    out.close();

    // fake intent
    IntentSender statusReceiver = null;
    Intent intent = new Intent(context, SomeActivity.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
            1337111117, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    session.commit(pendingIntent.getIntentSender());
    session.close();
}

Diese Methode kann wie folgt aufgerufen werden:

        InputStream inputStream = getActivity().getAssets().open("my_awesome_app.apk");
        InstallationHelper.installPackage(getActivity(), inputStream);
3
devz

Sie löschen einfach Ihre Einschränkungen

public static DevicePolicyManager getDpm(Context context) {
    return (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
}

public static ComponentName getAdmin(Context context) {
    return new ComponentName(context, MyDevicePolicyReceiver.class);
}

public static void addMyRestrictions(Context context) {
    getDpm(context).addUserRestriction(getAdmin(context), UserManager.DISALLOW_INSTALL_APPS);
    getDpm(context).addUserRestriction(getAdmin(context), UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
}

public static void clearMyRestrictions(Context context) {
    getDpm(context).clearUserRestriction(getAdmin(context), UserManager.DISALLOW_INSTALL_APPS);
    getDpm(context).clearUserRestriction(getAdmin(context), UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
}

public static void installPackage(Context context, InputStream inputStream)
        throws IOException {
    PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
    int sessionId = packageInstaller.createSession(new PackageInstaller
            .SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));

    //openSession checks for user restrictions
    clearMyRestrictions(context);
    PackageInstaller.Session session = packageInstaller.openSession(sessionId);

    long sizeBytes = 0;

    OutputStream out = null;
    out = session.openWrite("my_app_session", 0, sizeBytes);

    int total = 0;
    byte[] buffer = new byte[65536];
    int c;
    while ((c = inputStream.read(buffer)) != -1) {
        total += c;
        out.write(buffer, 0, c);
    }
    session.fsync(out);
    inputStream.close();
    out.close();

    // fake intent
    IntentSender statusReceiver = null;
    Intent intent = new Intent(context, SomeActivity.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
            1337111117, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    session.commit(pendingIntent.getIntentSender());
    session.close();
}
1
Himmat Chavan

Dies funktioniert auch für mich, obwohl mein Gerätebesitzer die Installation von Apps und unbekannten Quellen durch den Benutzer einschränkt. Selbst wenn ich dieses Beispiel als Geräteadministrator ausführen möchte, habe ich den Java.lang.SecurityException: User restriction prevents installing.

openSession sucht nach Berechtigungen. Mit dieser einfachen Änderung können die Benutzereinschränkungen nur während eines kurzen Methodenaufrufs zurückgesetzt werden.

public static DevicePolicyManager getDpm(Context context) {
    return (DevicePolicyManager)context.getSystemService(Context.DEVICE_POLICY_SERVICE);
}

public static ComponentName getAdmin(Context context) {
    return new ComponentName(context, MyDevicePolicyReceiver.class);
}

public static void addMyRestrictions(Context context) {
   getDpm(context).addUserRestriction(getAdmin(context), UserManager.DISALLOW_INSTALL_APPS);
   getDpm(context).addUserRestriction(getAdmin(context), UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
}

public static void clearMyRestrictions(Context context) {    
   getDpm(context).clearUserRestriction(getAdmin(context), UserManager.DISALLOW_INSTALL_APPS);
   getDpm(context).clearUserRestriction(getAdmin(context), UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
}

public static void installPackage(Context context, InputStream inputStream)
    throws IOException {
    PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
    int sessionId = packageInstaller.createSession(new PackageInstaller
        .SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));

    //openSession checks for user restrictions
    clearMyRestrictions(context);
    PackageInstaller.Session session = packageInstaller.openSession(sessionId);
    addMyRestrictions(context);

    long sizeBytes = 0;

    OutputStream out = null;
    out = session.openWrite("my_app_session", 0, sizeBytes);

    int total = 0;
    byte[] buffer = new byte[65536];
    int c;
    while ((c = inputStream.read(buffer)) != -1) {
        total += c;
        out.write(buffer, 0, c);
    }
    session.fsync(out);
    inputStream.close();
    out.close();

    // fake intent
    IntentSender statusReceiver = null;
    Intent intent = new Intent(context, SomeActivity.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
        1337111117, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    session.commit(pendingIntent.getIntentSender());
    session.close();
}

Bitte achten Sie auf die Ausnahmebehandlung.

1
Mr. Fish

In Android Api-21 ist ein Codeausschnitt, über den wir apk im Hintergrund installieren können.

private void runInstallWrite() throws IOException, RemoteException {
        long sizeBytes = -1;

        String opt;
        while ((opt = nextOption()) != null) {
            if (opt.equals("-S")) {
                sizeBytes = Long.parseLong(nextOptionData());
            } else {
                throw new IllegalArgumentException("Unknown option: " + opt);
            }
        }

        final int sessionId = Integer.parseInt(nextArg());
        final String splitName = nextArg();

        String path = nextArg();
        if ("-".equals(path)) {
            path = null;
        } else if (path != null) {
            final File file = new File(path);
            if (file.isFile()) {
                sizeBytes = file.length();
            }
        }

        final SessionInfo info = mInstaller.getSessionInfo(sessionId);

        PackageInstaller.Session session = null;
        InputStream in = null;
        OutputStream out = null;
        try {
            session = new PackageInstaller.Session(mInstaller.openSession(sessionId));

            if (path != null) {
                in = new FileInputStream(path);
            } else {
                in = new SizedInputStream(System.in, sizeBytes);
            }
            out = session.openWrite(splitName, 0, sizeBytes);

            int total = 0;
            byte[] buffer = new byte[65536];
            int c;
            while ((c = in.read(buffer)) != -1) {
                total += c;
                out.write(buffer, 0, c);

                if (info.sizeBytes > 0) {
                    final float fraction = ((float) c / (float) info.sizeBytes);
                    session.addProgress(fraction);
                }
            }
            session.fsync(out);

            System.out.println("Success: streamed " + total + " bytes");
        } finally {
            IoUtils.closeQuietly(out);
            IoUtils.closeQuietly(in);
            IoUtils.closeQuietly(session);
        }
    }

Der obige Code wurde vom Framework hier übernommen.

Kann ich diesen Code mit device_owner oder normalem Benutzer in LoLiipop verwenden?

Antwort - Nein Da es in Android-Frameworks apis gibt, das @hide-Tag ist, wurde zwar PackageManager.Session in API 21 eingeführt, aber es ist nicht möglich, PAckageManager.Session () neu zu verwenden, da es in API 21 @hide ist.

Wenn Sie diesen Code weiterhin über framework.jar verwenden möchten, müssen Sie Lolippop-Quellcode erstellen und jar aus out /..../ framework.jar extrahieren und über apis aufrufen. 

0
KOTIOS

INSTALLIEREN: 

Intent promptInstall = new Intent(Intent.ACTION_VIEW);
        promptInstall.setDataAndType(Uri.fromFile(new File(Environment
                .getExternalStorageDirectory() + "/download/" + APK_NAME)),
                "application/vnd.Android.package-archive");
        promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(promptInstall);

DEINSTALLIEREN:

Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package",
getPackageManager().getPackageArchiveInfo(apkUri.getPath(), 0).packageName,null));
startActivity(intent);
0
Vibhor Chopra