IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

Installateur d'applications (qui marche pÔ)


Sujet :

Android

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Points : 625
    Points
    625
    Par défaut Installateur d'applications (qui marche pÔ)
    Salut,
    venant du monde Windows, je suis assez nouveau en Android et j'ai de gros problèmes de synchronisation dans mon projet Android actuel.
    Solution recherchée : synchroniser les Intent d'installation et de désinstallation de package afin qu'ils se déroulent l'un après l'autre.

    Le but du projet est d'installer automatiquement les dernières versions des programmes Android disponibles dans l'entreprise.
    Pour cela, le programme récupère via service web une liste de programmes, le chemin de leur APK (nouvelle version coté serveur) ainsi que leur numéro de version (coté serveur) et un booleen précisant s'il doit s'exécuter automatiquement après l'installation, le tout sous la forme d'un DataSet.
    Une fois le DataSet récupéré, pour chaque programme listé je compare le numéro de version locale du programme déjà installé (s'il est déjà installé) au numéro de version coté serveur à (potentiellement) installer.
    Ensuite, pour chaque programme à installer (car version locale inférieure à la version serveur) je télécharge les APK un par un sur la tablette.

    Jusque là tout va bien, c'est maintenant que ca se corse :

    Pour chaque programme je dois :
    - Regarder s'il existe en local
    - si non je dois lancer l'installation
    - si oui je dois le désinstaller
    - s'il a bien été désinstallé, je dois installer la nouvelle version
    - s'il n'a pas été désinstallé (annulation...) je dois le désinstaller...
    - s'il a bien été installé je dois le lancer s'il est marqué en "auto"

    J'ai fait des fonctions (qui fonctionnent !!) pour chacune de ces étapes;
    Le problème c'est que j'ai vraiment du mal à comprendre le fonctionnement d'Android au niveau des threads UI et des synchronisations des fonctions.
    Du coup, si j'ai 3 programmes à installer, les 3 désinstallations se lancent en même temps, les installations aussi et le programme veut m'exécuter en auto un package qui est en cours de désinstall ou d'install...

    Voici les fonctions d'installation, de désinstallation, d'execution et de présence des packages :
    (j'utilise Xamarin pour pouvoir bosser en c#, mais ca devrait être lisible pour les adeptes de java)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
     
            public static async Task<bool> Installation_Package(string package, Activity activity)
            {
                Intent intent = new Intent(Android.Content.Intent.ActionInstallPackage);
                intent.SetDataAndType(Android.Net.Uri.FromFile(new Java.IO.File(package)), "application/vnd.android.package-archive");
                intent.SetFlags(ActivityFlags.NewTask);
                intent.PutExtra(Intent.ExtraReturnResult, true);
     
                activity.StartActivityForResult(intent, 2); //2 pour installation           
     
                return true;
            }
     
            public static async Task<bool> DesInstallation_Package(string package, Activity activity)
            {
                Intent intent = new Intent(Android.Content.Intent.ActionUninstallPackage, Android.Net.Uri.FromParts("package", activity.ApplicationContext.PackageManager.GetPackageArchiveInfo(Android.Net.Uri.FromFile(new Java.IO.File(package)).Path, 0).PackageName, null));
                intent.PutExtra("android.intent.extra.UNINSTALL_ALL_USERS", true);
                intent.PutExtra(Intent.ExtraReturnResult, true);
     
                activity.StartActivityForResult(intent, 1); //1 pour desinstallation           
     
                return true;
            }
     
            public static async Task<bool> EstLancee_Package(string package, Activity activity)
            {
                ActivityManager activityManager = (ActivityManager)activity.ApplicationContext.GetSystemService(Context.ActivityService);
                IList<ActivityManager.RunningAppProcessInfo> procInfos = activityManager.RunningAppProcesses;
                if (procInfos != null)
                {
                    foreach (ActivityManager.RunningAppProcessInfo processInfo in procInfos)
                    {
                        if (processInfo.ProcessName.Equals(package))
                        {
                            return true;
                        }
                    }
                }
     
                return false;
            }
     
            public static async Task<bool> EstInstalle_Package(string package, Activity activity)
            {
                try
                {
                    PackageInfo info = activity.ApplicationContext.PackageManager.GetPackageInfo(package, 0);
                    return info != null;
                }
                catch
                {
                    return false;
                }
            }
     
            public static async Task<bool> Execute_Package(string package, Activity activity)
            {
                Intent launchIntent = activity.ApplicationContext.PackageManager.GetLaunchIntentForPackage(package);
                if (launchIntent != null)
                {
                    activity.StartActivity(launchIntent);
                }
     
                return true;
            }
    Indépendamment elles fonctionnent toutes.

    Pour les appeler depuis mon activity principale j'utilise ces deux fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
            private async Task<bool> MiseAJour_Programmes()
            {
                bool termine = false;
     
                foreach (DataRow dr_Programme in _dt_Programmes.Rows)
                {
                    if ((bool)dr_Programme["MAJ"])
                    {
                        termine = await MiseAJour_Programme(dr_Programme);
                    }
                }
     
                return true;
            }
     
            private async Task<bool> MiseAJour_Programme(DataRow dr_Programme)
            {
                string nom_Package = dr_Programme["Nom_Package"].ToString();
                string nom_Programme = dr_Programme["Nom"].ToString();
                string chemin_Ecriture_Package = Chemin_Ecriture_Package(nom_Package);
                bool termine;
     
                if (await Outils_Android_Packages.Packages.EstInstalle_Package(nom_Package, this))
                {
                    termine = await Outils_Android_Packages.Packages.DesInstallation_Package(chemin_Ecriture_Package, this);
                }
                else
                {
                    termine = await Outils_Android_Packages.Packages.Installation_Package(chemin_Ecriture_Package, this);
                }
     
                return true;
            }
    Après de multiples recherches j'ai vu qu'il fallait utiliser StartActivityForResult et récupérer le résultat des Intent dans la fonction suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
            protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
            {
                switch (requestCode)
                {
                        case 1://après la désinstallation
                                  REINSTALLER LE PACKAGE QUE JE VIENS DE DESINSTALLER
                            break;
                        case 2://après l'installation
                                  POTENTIELLEMENT EXECUTER LE PROGRAMME NOUVELLEMENT INSTALLE
                            break;
                }
            }
    quand j'installe ou désinstalle un package, l'activity lance bien le "OnActivityResult" et le requestCode correspond bien à ce que j'ai lancé. Par contre le data est toujours "null".
    De plus, après la désinstallation il faut le réinstaller, or, comme plusieurs désinstalles se lancent en même temps je ne sais pas laquelle a fini et du coup laquelle réinstaller (j'espérais récupérer cette info via l'Intent 'data' mais il est null...).

    Du coup j'ai deux problèmes :
    - la fonction 'MiseAJour_Programmes()' me lance toutes les install/desinstall à la suite sans attendre alors que j'aimerais pouvoir les exécuter les unes après les autres.
    - la fonction 'OnActivityResult(...)' ne me donne pas d'info sur 'qui vient de finir son taf' et du coup m'empêche de réinstaller/executer le package.

    Si vous voyer trainer plein de 'await', 'async', 'Task' etc... inutiles, c'est bien parce que j'ai TOUT tenté ^^ et qu'aucun tutoriel ne m'a permis de comprendre la subtilité (soit trop vagues, soit qu'un concept prérequis important m'échappe)

    Voila, donc si quelqu'un à une (ou deux) solutions j'en serais très content.
    S'il y a une méthode alternative aussi
    Et si vous connaissez un tutoriel (en français de préférence) suffisamment explicite sur les await/async/task/asynctask et tout ça ce serait farpait.

    Eternellement Merci,
    TheMacleod.
    "Essayer est le premier pas vers l'Echec !" (Homer Simpson)

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Points : 625
    Points
    625
    Par défaut
    re,
    pour remédier au fait que les X install se lancent en même temps, j'ai tenté de mettre une boucle while avec un flag pour en sortir une fois l'installation/désinstallation terminée.
    Cependant le programme ne traite plus rien d'autre et le OnActivityResult n'est jamais atteint (c'est lui qui est censé mettre le flag à false).
    En Windows j'aurais simplement mis un Application.DoEvents() mais il n'y a apparemment aucun équivalent en Android
    "Essayer est le premier pas vers l'Echec !" (Homer Simpson)

  3. #3
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 691
    Points : 20 222
    Points
    20 222
    Par défaut
    Pourquoi désinstaller une application pour la mettre à jour ? Normalement ce n'est pas nécessaire , tout le process de mise à jour peut être gérer par le système sans rien désinstaller.

    je connais pas C# ni xamarin mais en android comme leur nom l'indique les Async Task sont asynchrones , donc absolument rien ne garantie leur ordre d’exécution et encore moins l'ordre des retours.

    De plus imbriqué des async task n'as pas réellement d'intérêt. Une globale suffit généralement à sortir du thread UI et d'executer tout ce dont ont à besoin.
    Tu fais une queue des actions à exécuter et une seule et unique async task dépile et exécute au fur et à mesure.
    Si tu as besoin de tout paralléliser il faut passer par un pool de thread qui s'occuperont chacun d'une partie du travail à faire.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Points : 625
    Points
    625
    Par défaut
    Merci pour ta réponse,

    Quand je tentais d'installer une nouvelle version de l'appli, le système me disait qu'une appli du même nom était déjà installée, d'où la nécessité de la désinstaller avant.

    Pour les "async Task", j'avais tenté car j'ai vu qu'on pouvait les "await" mais quelque chose doit m'échapper car il ne les awaitait pas du tout :/
    je viens donc de les virer de mes fonctions et le résultat est le même : les X install se lancent en même temps.

    Le problème vient de la boucle "pour chaque programme lance l'install", elle se fait sans attendre la fin de l'install.
    Et si je tente d'exploiter le "OnActivityResult" qui est atteint à la fin de l'install du prog1 pour lancer le prog2, je n'ai aucun moyen de savoir, via les arguments retournés par la fonction "OnActivityResult", ce que je dois installer ensuite.

    Mais en écrivant ces lignes il me vient une idée
    je vous tien au courant
    "Essayer est le premier pas vers l'Echec !" (Homer Simpson)

  5. #5
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 691
    Points : 20 222
    Points
    20 222
    Par défaut
    Quand je tentais d'installer une nouvelle version de l'appli, le système me disait qu'une appli du même nom était déjà installée
    Pour que cela fonctionne , il faut que :

    - Le code de version (dans le manifest) soit supérieur à la version installé
    - Que la clé servant à la compilation soit la même (installer une release sur une debug ne fonctionne pas par exemple)
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Points : 625
    Points
    625
    Par défaut
    Merci pour l'info, c'est vrai que je pousse mes tests toujours avec les mêmes apk (je ne vais pas les recompiler à chaque fois)
    je vais donc me garder deux apk de deux versions différentes pour tester.

    Entre temps j'ai modifié mon fonctionnement et supprimé ma boucle d'installation : je ne lance plus que la première installation.
    A la fin de l'installation, captée dans OnActivityResult, je lance l'installation/desinstallation suivante (je vais sans doute virer la désinstall du coup, après tests), ce qui permet de les installer les uns après les autres dans l'ordre;
    il m'a suffit de mettre un compteur en global ainsi que mon tableau de programmes à installer.
    A la fin d'une install (onactivityresult) j'augmente mon compteur et lance la maj suivante du tableau (dataset).

    Par contre un bug faisait que le OnActivityResult se lançait deux fois lors d'une installation (à la désinstallation pas de problème), au début (apparition de la fenetre) et à la fin de l'install.
    Ce lien m'a donné la solution : https://stackoverflow.com/questions/...on-intent?rq=1
    en résumé : "Also, IIRC, FLAG_ACTIVITY_NEW_TASK and startActivityForResult() are incompatible."

    j'ai donc viré la ligne "intent.SetFlags(ActivityFlags.NewTask);" dans ma fonction d'installation et ca donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
            public static bool Installation_Package(string package, Activity activity)
            {
                Intent intent = new Intent(Android.Content.Intent.ActionInstallPackage);
                intent.SetDataAndType(Android.Net.Uri.FromFile(new Java.IO.File(package)), "application/vnd.android.package-archive");
                intent.PutExtra(Intent.ExtraReturnResult, true);
     
                activity.StartActivityForResult(intent, 2);//2 pour préciser au OnActivityResult que c'est une installation, 1 pour la désinstall
     
                return true;
            }
    Je vais maintenant pousser les test avec des APK de version supérieure pour valider ta solution.
    Je ferai un retour
    "Essayer est le premier pas vers l'Echec !" (Homer Simpson)

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Points : 625
    Points
    625
    Par défaut
    J'ai eu pas mal de déboires avec la gestion des versions signées mais maintenant c'est rentré ^^

    Donc j'ai pu pousser mes tests avec succès

    Merci encore pour ton aide
    je passe la discussion en résolu.
    "Essayer est le premier pas vers l'Echec !" (Homer Simpson)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 10
    Dernier message: 14/03/2010, 14h26
  2. application crée avec delphi qui marche sur mobile
    Par adnanedelphi dans le forum Langage
    Réponses: 8
    Dernier message: 19/11/2008, 17h52
  3. Application qui marche ,mais jar qui bug
    Par jojodu31 dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 25/06/2008, 10h03
  4. application qui marche sur pc et sur le mobile
    Par phoenix8006 dans le forum Interfaces Graphiques en Java
    Réponses: 1
    Dernier message: 02/03/2007, 21h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo