web-dev-qa-db-fra.com

Comment installer/mettre à jour/supprimer APK en utilisant la classe "PackageInstaller" dans Android L?

Veuillez vérifier ci-dessous et donnez-moi des suggestions sur leur utilisation https://developer.Android.com/reference/Android/content/pm/PackageInstaller.htmlhttps://developer.Android.com/reference/Android/content/pm/PackageInstaller.Session.html

Alors, donnez-moi s'il vous plaît un exemple pour installer/mettre à jour/supprimer une application . Peut-il être possible que la nouvelle application s'installe dans le propriétaire du profil de périphérique?

22
Sud

Il est possible sans autorisations système à partir de Android M à partir de .

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

Installation et désinstallation silencieuses des applications par le propriétaire de l'appareil:

Un propriétaire de périphérique peut désormais installer et désinstaller des applications en mode silencieux à l'aide des API PackageInstaller, indépendamment de Google Play for Work.

Plus dans ce lien.


Ceci est possible à partir d'Android 6.0 et plus.

  • Faites de votre application le propriétaire de l'appareil.

Une fois que votre application obtient l'autorisation du propriétaire de l'appareil, nous pouvons installer, désinstaller et mettre à jour en mode silencieux sans aucune intervention de l'utilisateur.

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

Désinstaller:

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 ici .

20
amalBit

Vous ne pouvez pas installer en mode silencieux une application tierce chez l'utilisateur nouvellement créé avec PackageInstaller.Session.commit () sans "droits" spécifiques.
Vous avez besoin soit: 

  • le INSTALL_PACKAGES permission. Mais cette autorisation n'est pas disponible pour les applications tierces. Ainsi, même avec votre application propriétaire de profil, vous ne disposez pas de cette autorisation spécifique.
  • Exécutez le processus en tant que ROOT_UID. Ce qui signifie que vous devrez rooter le périphérique. 

De le code source Android

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

Si vous n'avez ni accès root, ni l'autorisation INSTALL_PACKAGES, un message sera demandé à l'utilisateur pour lui demander s'il confirme les autorisations. Cette confirmation est ensuite utilisée lors de la validation process de la session PackageInstaller's. Évidemment, dans ce cas, cela n’est pas transparent, car l’utilisateur devra confirmer manuellement l’installation de vos applications.

6
Florent Dupont

La méthode d'installation fournie par @amalBit n'a pas fonctionné pour moi. C'est étrange puisque c'est ainsi qu'il est implémenté dans le Google Sample .

Cette réponse m'a aidé à trouver une solution. J'ai dû changer certaines parties du code. Voici ma mise en œuvre:

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

Cette méthode peut s'appeler comme ceci:

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

Vous effacez simplement vos restrictions

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

Cela fonctionne également pour moi, bien que le propriétaire de mon appareil limite l'installation d'applications et de sources inconnues par l'utilisateur. Même si j'exécute cet exemple en tant qu'administrateur de périphérique, j'ai le Java.lang.SecurityException: User restriction prevents installing.

openSession recherche des autorisations. Avec cette modification simple, il est possible de réinitialiser les restrictions utilisateur uniquement pendant un appel de méthode court.

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

S'il vous plaît prendre en charge de la gestion des exceptions.

1
Mr. Fish

Sous Android, Api-21 est un extrait de code via lequel nous pouvons installer apk en mode silencieux.

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

Le code ci-dessus est extrait de Framework here

Puis-je utiliser ce code avec propriétaire_appareil ou utilisateur normal dans LoLiipop?

Réponse - Non. Comme il y a des apis qui ont été tag @hide dans les frameworks Android, PackageManager.Session est introduit dans l'API 21 mais nous ne pouvons pas utiliser le nouveau PAckageManager.Session () puisqu'il est masqué dans l'API 21.

Si vous voulez toujours utiliser ce code via framework.jar, vous devez créer le code source de Lolippop, extraire le fichier jar de /..../ framework.jar et appeler ci-dessus. 

0
KOTIOS

INSTALLER: 

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

DÉSINSTALLER:

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