7. OUTILS DE DÉVELOPPEMENT
7.3. A PPCELERATOR T ITANIUM
Les langages de programmation pour l’iPhone et pour Androïd sont différents. Il en va de même pour les environnements de développement. Ainsi, il nous a paru intéressant de faire des recherches sur un moyen de programmer pour les deux plateformes simultanément. C’est ainsi que nous avons expérimenté la plateforme Appcelerator Titanium.
Appcelerator Titanium est une plateforme libre, développée par Appcelerator Inc., pour développer des applications mobiles et de bureau en utilisant des technologies web. Les applications peuvent être développées nativement pour l’iOS de l’iPhone, ou bien encore pour le système Android. Cette plateforme comporte plusieurs versions, une pour Linux, une pour Windows et enfin une pour Mac.
Appcelerator Titanium comporte de multiples avantages pour le développement d’applications mobiles. Les technologies supportées pour coder les applications mobiles peuvent être HTML, CSS et JavaScript. La plateforme joue un rôle de compilateur pouvant aboutir à de l’Objective-‐C pour les applications iPhone, et Java pour Android. De plus Appcelerator Titanium possède de multiples bibliothèques spécifiques au langage cible. Par exemple certaines nous donnent des informations sur le système, à savoir les processus en marchent, la mémoire utilisée, etc. L’avantage étant que l’on peut obtenir une même application sur iPhone et Android en générant un code avec peu de différences. Enfin la plateforme intègre des émulateurs de systèmes iOS et Android pour pouvoir tester les applications sans avoir obligatoirement la machine concernée à disposition.
Une application test a été développée sous Titanium. Elle permet la lecture d’informations système (Capture 9). Son code est disponible en annexe.
CAPTURE 9 : APPLICATION DE LECTURE DES INFORMATIONS SYSTEMES DEVELOPPEE SOUS TITANIUM
Cependant, malgré les multiples avantages de Titanium, un problème survient : celui du SDK iPhone. En effet ce dernier, payant, n'est disponible que sous MacOS. Nous pouvons donc nous poser la question quant à l'utilité de la plateforme Titanium pour notre projet et si nous l'utiliserons par la suite. De plus, Titanium permet de créer des applications native pour iPhone et Android, mais cependant ne permet pas de créer d'application Windows Mobile. Malgré le fait que ceci ne corresponde pas à notre projet, cela pourrait être intéressant. Mais envisager cette possibilité rend l'utilisation de Titanium un peu plus restrictive.
8. Plannification
Nom de la tâche Durée Début Fin
Apprentissage : Continuation de la pré-‐étude 20 jours Jeu 21/10/10 Mer 17/11/10 Apprentissage : WEKA : prise en main &
algorithmes 10 jours Jeu 18/11/10 Mer 01/12/10
Apprentissage : Application au projet 43 jours Jeu 02/12/10 Lun 31/01/11
Tests iPhone 10 jours Jeu 04/11/10 Mer 17/11/10 Installation Snow Leopard, Xcode… 10 jours Jeu 21/10/10 Mer 03/11/10 iPhone : spécification & Faisabilité 7 jours Jeu 18/11/10 Ven 26/11/10
Réflexion & tests autours de la généricité (Titanium, machine virtuelle, fichier de règles générique…)
15 jours Jeu 21/10/10 Mer 10/11/10
Android : spécification & faisabilité 7 jours Jeu 11/11/10 Ven 19/11/10
Serveur : spécification (cas d'utilisation, fichier entrée, fichier sortie apprentissage, fichier sortie actions génériques)
10 jours Jeu 11/11/10 Mer 24/11/10
Conception 46 jours Lun 29/11/10 Lun 31/01/11
Développement 65 jours Mar 01/02/11 Lun 02/05/11
Tests 10 jours Mar 03/05/11 Lun 16/05/11
9. Conclusion
Nous avons pu prendre connaissance, de façon approfondie, du travail réalisé par les étudiants de l’année passée, d’en comprendre les tenants et les aboutissants, orientant ainsi nos recherches sur les deux systèmes iOS et Android. Nous avons ainsi pu découvrir et analyser les principes et le fonctionnement de ces deux systèmes, mais aussi tester des moyens pour développer de façon plus ou moins unifiée sur les deux plateformes (Appcelerator TItanium).
L’aspect apprentissage constituait un point important de la pré-‐étude.
Malgré les progrès et découvertes réalisés, des interrogations subsistent encore sur la faisabilité du projet sur l’iPhone avec sa conception différente du multitâche. De la même façon, au fur et à mesure de nos découvertes, de nouvelles voies de recherche s’ouvrent à nous. Les études de faisabilité impliquent intrinsèquement une répartition du temps plus axée sur la recherche et l’expérimentation. Il est ainsi évident que d’autres découvertes, et recherches font partie intégrante de nos prochains objectifs, au même titre que la spécification logicielle.
10. Bibliographie
1. iPuP. Programmez pour iPhone, iPod Touch, iPad avec iOS4. s.l. : Pearson, 2010.
2. Appcelerator, Inc. Appcelerator. [En ligne] [Citation : 21 10 2010.]
http://www.appcelerator.com/.
3. Xsysinfo -‐ Display bar graphs of system load. Linux Software Directory. [En ligne]
[Citation : 27 Septembre 2010.] http://linux.maruhn.com/sec/xsysinfo.html.
4. WITTEN, Ian H. et FRANK, Eibe. Data Mining. s.l. : Morgan Kaufmann, 2005.
5. McEntire, Norman. How to use iPhone with Unix System and Library Calls : A Tutorial for Software Developers. How to use iPhone with Unix System and Library Calls. [En ligne] 18 Janvier 2009. [Citation : 27 09 2010.] http://www.servin.com/iphone/iPhone-‐Unix-‐
System-‐Calls.html.
6. Guy, Romain. Painless threading. Android Developers. [En ligne] 2009.
http://android-‐developers.blogspot.com/2009/05/painless-‐threading.html.
7. Collins, Charlie. Android Application and AsyncTask basics. [En ligne] 2010.
http://www.screaming-‐penguin.com/node/7746.
8. Apple Inc. iOS Reference Library. [En ligne] 2010.
http://developer.apple.com/library/ios/navigation/.
9. Google. Android SDK. [En ligne] 2010.
http://developer.android.com/sdk/index.html.
11. Annexes
11.1. Annexe : Exemple de récupération d’informations sous Android
Cette application affiche une liste d’informations récupérées à propos du système (Modèle du téléphone, version du SDK, mémoire disponible, services en cours, …).
MainActivity.java
publicclass MainActivity extends ListActivity { ArrayList<String> values;
for(int i=0; i<networkinfo.length; i++){
values.add(networkinfo[i].getTypeName()+" :
"+networkinfo[i].getState());
}
ActivityManager activityManager
=(ActivityManager)this.getSystemService( ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mInfo =new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo( mInfo );
values.add("Memoire disponible = "+mInfo.availMem+" octets");
List<ActivityManager.RunningServiceInfo> servicelist = activityManager.getRunningServices(100);
for(ActivityManager.RunningServiceInfo serviceinfo : servicelist){
values.add("Service : "+serviceinfo.process);
} } /**
* Création de l'adapter */
protected ListAdapter createAdapter(ArrayList<String> list) {
ListAdapter adapter =new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
return adapter;
} }
11.2. Annexe : Application de lecture des logs sous Android
Exemple d’application lançant un service chargé de signaler lorsqu’un processus lève une exception de type RuntimeException.
MainActivity.java : * @author Vincent Le Biannic
*
*/ publicclass MainActivity extends Activity { Intent serviceIntent =null;
/**
* Lancement de l'Activity
*/
final Button startbutton =(Button) findViewById(R.id.startbutton);
final Button stopbutton =(Button) findViewById(R.id.stopbutton);
serviceIntent =new Intent();
startbutton.setOnClickListener(new View.OnClickListener(){
publicvoid onClick(View v){
stopbutton.setOnClickListener(new View.OnClickListener(){
publicvoid onClick(View v){
stopService(serviceIntent);
} });
} * @author Vincent Le Biannic
* */
publicclass WatcherService extends Service { private WatcherTask watcher =null;
* Lancement du Service */
// Affichage d'une notification durant toute l'execution du service
CharSequence text ="Service en cours d'execution";
Notification notification =new Notification(R.drawable.icon, text,
Toast.makeText(this,"Lancement du monitoring", Toast.LENGTH_LONG).show();
if(watcher ==null){
watcher =new WatcherTask();
if(watcher.getStatus()!= AsyncTask.Status.RUNNING){
Toast.makeText(this,"Arret du monitoring", Toast.LENGTH_LONG).show();
* Affiche une notification avec le numero de l'erreur ainsi que le * nom et pid du processus ayant provoqué l'erreur.
! * * @param processName Chaine content le nom et le pid du processus
*/ publicvoid showNotif(int nb, String processName){
CharSequence text ="RuntimeError n°"+nb+" : "+processName;
Notification notification =new Notification(R.drawable.icon, text,
System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this,0, new Intent(this, MainActivity.class),0);
notification.setLatestEventInfo(this,"Log Watcher", text, contentIntent);
// Envoi de la notification
mNM.notify(R.layout.main, notification);
}
/**
* Tâche qui sera exécutée dans un autre thread
* @author Vincent Le Biannic *
*/
privateclass WatcherTask extends AsyncTask<Void, Void, Void>{
Process process =null;
process = Runtime.getRuntime().exec("logcat -c");
process.waitFor();
// Lance logcat en filtrant les erreurs
process = Runtime.getRuntime().exec("logcat");//
*:E");
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(process.getInputStream()));
// cours pour trouver celui
// qui correspond au PID ayant
List<RunningAppProcessInfo> pInfo = activityManager.getRunningAppProcesses();
for(RunningAppProcessInfo current : pInfo){
if(current.pid == pid)
processName =
current.processName;
}
// Affichage de la notification showNotif(i, processName+"
Log.e("LOGTEST","Erreur de lecture des logs !");
}catch(SecurityException e){
watcher =null;
process =null;
}
@Override
protectedvoid onCancelled(){
if(process !=null){
// Fin du processus process.destroy();
process =null;
}
watcher =null;
} } }
11.3. Annexe : Application de lecture des
var tabGroup = Titanium.UI.createTabGroup();
// System Informations
var osName = Titanium.Platform.osname;
var osType = Titanium.Platform.ostype;
var avMem = Titanium.Platform.availableMemory;
var batLvl = Titanium.Platform.batteryLevel;
var macAdr = Titanium.Platform.macaddress;
var model = Titanium.Platform.model;
var nbUc = Titanium.Platform.processorCount;
var label1 = Titanium.UI.createLabel({
color:'#000',
font:{fontSize:14,fontFamily:'Helvetica Neue'}, textAlign:'left',
11.4. Annexe : Premier Programme sur iPhone
//
// HelloWorldViewController.h // HelloWorld
@interface HelloWorldViewController : UIViewController { UILabel *monLabel;
UILabel *myLabelAvailableMem;
UILabel *myLabelTotalMem;
@property (nonatomic, retain) UILabel *monLabel;
@property (nonatomic, retain) UILabel *myLabelName;
@property (nonatomic, retain) UILabel *myLabelVersion;
@property (nonatomic, retain) UILabel *myLabelModel;
@property (nonatomic, retain) UILabel *myLabelAMem;
@property (nonatomic, retain) UILabel *myLabelTMem;
@property (nonatomic, retain) UILabel *myLabelTotalMem;
@property (nonatomic, retain) UILabel *myLabelAvailableMem;
@property(nonatomic,retain) NSString *aMem;
@property(nonatomic,retain) NSString *tMem;
@property (nonatomic, readonly, retain) NSString *systemName;
@property (nonatomic, readonly, retain) NSString *systemVersion;
@property (nonatomic, readonly, retain) NSString *phoneModel;
//
// HelloWorldViewController.m // HelloWorld
-‐ (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) !=
KERN_SUCCESS) NSLog(@"Failed to fetch vm statistics");
//natural_t mem_used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pagesize;
natural_t mem_free = vm_stat.free_count * pagesize;
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) !=
KERN_SUCCESS) NSLog(@"Failed to fetch vm statistics");
natural_t mem_used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pagesize;
natural_t mem_free = vm_stat.free_count * pagesize; CGRect mainFrame = [[UIScreen mainScreen] applicationFrame];
UIView *contentView = [[UIView alloc] initWithFrame:mainFrame];
contentView.backgroundColor = [UIColor groupTableViewBackgroundColor];
self.view = contentView;
[contentView release];
//Positionnement et initialisation des Labels sur l'écran
monLabel = [[UILabel alloc] initWithFrame:CGRectMake(10,10,mainFrame.size.width -‐ 20, 40)];
monLabel.backgroundColor = [UIColor clearColor];
monLabel.textColor = [UIColor blackColor];
[monLabel setTextAlignment:UITextAlignmentCenter];
monLabel.text = @"OS :";
myLabelName = [[UILabel alloc]
initWithFrame:CGRectMake(10,30,mainFrame.size.width -‐20,40)];
myLabelName.backgroundColor = [UIColor clearColor];
myLabelName.textColor = [UIColor blackColor];
[myLabelName setTextAlignment:UITextAlignmentCenter];
myLabelVersion = [[UILabel alloc]
initWithFrame:CGRectMake(10,50,mainFrame.size.width -‐20,40)];
myLabelVersion.backgroundColor = [UIColor clearColor];
myLabelVersion.textColor = [UIColor blackColor];
[myLabelVersion setTextAlignment:UITextAlignmentCenter];
myLabelModel = [[UILabel alloc]
initWithFrame:CGRectMake(10,70,mainFrame.size.width -‐20,40)];
myLabelModel.backgroundColor = [UIColor clearColor];
myLabelModel.textColor = [UIColor blackColor];
[myLabelModel setTextAlignment:UITextAlignmentCenter];
myLabelTotalMem = [[UILabel alloc]
initWithFrame:CGRectMake(10,90,mainFrame.size.width -‐20,40)];
myLabelTotalMem.backgroundColor = [UIColor clearColor];
myLabelTotalMem.textColor = [UIColor blackColor];
[myLabelTotalMem setTextAlignment:UITextAlignmentCenter];
myLabelTotalMem.text = @"Memoire totale :";
myLabelTMem = [[UILabel alloc]
initWithFrame:CGRectMake(10,110,mainFrame.size.width -‐20,40)];
myLabelTMem.backgroundColor = [UIColor clearColor];
myLabelTMem.textColor = [UIColor blackColor];
[myLabelTMem setTextAlignment:UITextAlignmentCenter];
myLabelAvailableMem = [[UILabel alloc]
initWithFrame:CGRectMake(10,130,mainFrame.size.width -‐20,40)];
myLabelAvailableMem.backgroundColor = [UIColor clearColor];
myLabelAvailableMem.textColor = [UIColor blackColor];
[myLabelAvailableMem setTextAlignment:UITextAlignmentCenter];
myLabelAvailableMem.text = @"Memoire libre :";
myLabelAMem = [[UILabel alloc]
initWithFrame:CGRectMake(10,150,mainFrame.size.width -‐20,40)];
myLabelAMem.backgroundColor = [UIColor clearColor];
myLabelAMem.textColor = [UIColor blackColor];
[myLabelAMem setTextAlignment:UITextAlignmentCenter];
myLabelVersion.text = systemVersion;
//**** Memoire total et memoire libre *****
natural_t availableMemory = freeMemory();
natural_t totMemory = totalMemory();
aMem = [NSString stringWithFormat:@"%d", availableMemory];
// uniqueIdentifier = [myDevice uniqueIdentifier];
myLabelAMem.text = aMem;
tMem = [NSString stringWithFormat:@"%d", totMemory];
myLabelTMem.text = tMem;
[self.view addSubview:monLabel];
[self.view addSubview:myLabelName];
[self.view addSubview:myLabelVersion];
[self.view addSubview:myLabelModel];
[self.view addSubview:myLabelAvailableMem];
[self.view addSubview:myLabelAMem];
[self.view addSubview:myLabelTotalMem];
[self.view addSubview:myLabelTMem];
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
-‐ (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.