ΣΧΟΛΗ ΤΕΧΝΟΛΟΓΙΚΏΝ ΕΦΑΡΜΟΓΏΝ ΤΜΉΜΑ ΒΙΟΜΗΧΑΝΙΚΉΣ ΠΛΗΡΟΦΟΡΙΚΉΣ ΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ Σχεδίαση και ανάπτυξη εφαρμογής Android για καταγραφή επιδόσεων τοξοβόλων Χαράλαμπος Ελπασίδης ΑΜ:1985 Επιβλέποντες: Ιωάννης Καζανίδης, Λευτέρης Μωυσιάδης Καβάλα, 2013
2
Περίληψη Σκοπός της παρούσας πτυχιακής εργασίας είναι η κατασκευή μιας mobile εφαρμογής που επιτρέπει σε αθλητές τοξοβολίας να καταγράφουν τις επιδόσεις τους σε ορισμένα αθλήματα τοξοβολίας, με την χρήση του Android SDK. Στο πρώτο κεφάλαιο γίνεται μια εισαγωγή στις mobile εφαρμογές και το λειτουργικό σύστημα Android. Στο δεύτερο κεφάλαιο παρουσιάζονται εφαρμογές παρόμοιες με αυτήν που υλοποιήθηκε για τις ανάγκες της τρέχουσας εργασίας και γίνεται μελέτη των δυνατοτήτων τους. Στο τρίτο κεφάλαιο αρχίζει η μελέτη της υλοποίησης της εφαρμογής με πρώτο θέμα την σχεδίαση και αρχιτεκτονική της. Το τέταρτο κεφάλαιο περιλαμβάνει την διαδικασία εγκατάστασης των εργαλείων για την υλοποίησή της και την περιγραφή των σημαντικότερων λειτουργιών της με κομμάτια κώδικα. Το πέμπτο και τελευταίο κεφάλαιο, αποτελεί ουσιαστικά το εγχειρίδιο χρήσης της εφαρμογής καθώς παρουσιάζει με εικόνες και επεξηγήσεις τις λειτουργίες της εφαρμογής.
Κατάλογος περιεχομένων 1. ΕΙΣΑΓΩΓΉ...6 1.1. Τί είναι ένα Mobile App;...6 1.2. Πώς ξεκίνησαν όλα...6 1.2.1. Wireless Application Protocol (WAP)...7 1.2.2. Φορητές Πλατφόρμες...8 1.3. Λίγα λόγια για το Android...9 1.3.1. Ιστορία...10 1.3.2. Γιατί Ανάπτυξη σε Android;...11 i) Λειτουργικότητα και ευελιξία...12 ii) Πλήρης παραμετροποίηση...12 iii) Διαδραστικότητα...12 iv) Απλούστερη aνάπτυξη εφαρμογών κινητών...12 1.4. Η αρχιτεκτονική του Αndroid...13 1.4.1. Linux Kernel...13 1.4.2. Libraries...13 1.4.3. Android Runtime...14 1.4.4. Application Framework...14 1.4.5. Applications...15 1.5. Aνατομία μιας Android εφαρμογής...15 1.5.1. Συστατικά εφαρμογής...15 i) Activities...15 ii) Services...15 iii) Content providers...16 iv) Broadcast receivers...16 1.5.2. Ενεργοποίηση Συστατικών...16 1.5.3. Το αρχείο Manifest...16 1.5.4. Resources...17 1.6. Κύκλος ζωής Activity...17 2. ΠΑΡΟΜΟΙΕΣ ΕΦΑΡΜΟΓΕΣ...19 2.1. Archery Score by Mage...19 2.2. ArcheryBuddy...19 2.3. Archery Goldrush...20 2.4. Archery ScoreBook...21 2.5. Archery Companion...22 2.6. Scoring Helper...22 2.7. Συμπεράσματα-Συγκρίσεις...23 2.8. Αποκόμιση Αναγκών...25 3. ΣΧΕΔΙΑΣΗ ΕΦΑΡΜΟΓΉΣ...26 3.1. Φιλοσοφία...26 3.2. Κανόνες...27 3.3. Απαιτήσεις...28 3.4. Λειτουργικότητα...29 3.5. Περιβάλλον εργασίας...31 3.6. Δεδομένα...37 4. YΛΟΠΟΙΗΣΗ...40 4.1. Εγκατάσταση λογισμικού...40 4.1.1. Εγκατάσταση Eclipse & Android SDK...40 4.1.2. Δημιουργία Εικονικής Συσκευής...46 4
4.1.3. Εγκατάσταση SQLite Database Browser...47 4.1.4. Εγκατάσταση GIMP...48 4.2. Περιγραφή Κώδικα...48 4.2.1. Δημιουργία της Βάσης Δεδομένων...49 4.2.2. Υπολογισμός και προβολή στατιστικών Ιστορικού...52 4.2.3. Διαχείριση Βελών...55 4.2.4. Διαχείριση Σημειώσεων...56 4.2.5. Μετακίνηση Ιστορικού στην κάρτα μνήμης...58 4.2.6. Διαχείριση Προπονήσεων...60 4.2.7. Καταχώρηση Βολών...61 5. ΠΑΡΟΥΣΙΑΣΗ EΦΑΡΜΟΓΉΣ...68 5.1. Αρχική οθόνη...68 5.2. Καταχώρηση Επιδόσεων...69 5.3. Διαχείριση Βελών...75 5.4. Διαχείριση Ιστορικού...79 5.5. Προβολή Στατιστικών...82 5
1. ΕΙΣΑΓΩΓΉ 1.1. Τί είναι ένα Mobile App; Μια φορητή εφαρμογή (ή αλλιώς mobile app) είναι μια εφαρμογή λογισμικού σχεδιασμένη να τρέχει σε smartphone, υπολογιστές tablet και άλλες φορητές συσκευές. Είναι διαθέσιμες στο κοινό μέσω πλατφορμών διανομής εφαρμογών, οι οποίες συνήθως λειτουργούν από τον ιδιοκτήτη του φορητού λειτουργικό συστήματος, όπως το Apple App Store, Google Play, BlackBerry App World. Τα Mobile apps, αρχικά είχαν στόχο την προσφορά στην γενική παραγωγικότητα του κοινού και την ανάκτηση πληροφοριών, συμπεριλαμβανομένων εφαρμογών για e-mail, ημερολόγιο, κατάλογο επαφών, χρηματιστηριακές αγορές και πληροφορίες για τον καιρό. Ωστόσο, η δημόσια ζήτηση και η διαθεσιμότητα των εργαλείων ανάπτυξης οδήγησε με γρήγορους ρυθμούς σε επέκταση και άλλων κατηγοριών, όπως παιχνίδια, αυτοματισμούς εργοστασίων, GPS και location-based υπηρεσίες, banking, εξέλιξη παραγγελιών, καθώς και στις αγορές εισιτηρίων. 1.2. Πώς ξεκίνησαν όλα Το Motorola DynaTAC 8000X ήταν το πρώτο εμπορικά διαθέσιμο κινητό τηλέφωνο. Πρωτοβγήκε στην αγορά το 1983, με διαστάσεις 33*4,5*9 εκατοστά, βάρος λίγο παραπάνω από το 1 κιλό και τιμή $3.995 συν τα μηνιαία πάγια και χρεώσεις ανά λεπτό, επέτρεπε κλήσεις συνολικής διάρκειας μισής ώρας. Αυτό, όπως και τα υπόλοιπα επερχόμενα πρώτα κινητά, δεν μπορούν να θεωρηθούν συσκευές πολλών δυνατοτήτων, παρόλο που οι περισσότερες συσκευές νέας γενιάς έχουν κληρονομήσει πολλά πλήκτρα από αυτά (SEND, END, CLEAR). Αντίθετα περιοριζόταν στην λήψη και πραγματοποίηση κλήσεων και στην διαχείριση επαφών μέσω μιας απλής εφαρμογής η οποία συνήθως ήταν δύσχρηστη. Εικόνα 1: Motorola DynaTAC 8000X: Το πρώτο κινητό διαθέσιμο στην αγορά 6
Τα κινητά τηλέφωνα πρώτης γενιάς σχεδιάζονταν και αναπτύσσονταν από τις ίδιες τις κατασκευάστριες εταιρίες των συσκευών. Ο ανταγωνισμός ήταν σκληρός και τα μυστικά του εμπορίου επισφαλώς σφραγισμένα. Οι κατασκευαστές δεν ήθελαν να εκθέσουν τα εσωτερικά των συσκευών τους και έτσι συνήθως η ανάπτυξη του λογισμικού τους γινόταν σε πολύ στενούς κύκλους. Οι προγραμματιστές της εποχής, αν δεν ανήκαν σε αυτούς τους κύκλους, δεν είχαν την ευκαιρία να γράψουν εφαρμογές για τις συσκευές αυτές, σε αντίθεση με σήμερα. Αυτή ήταν η περίοδος που είχαν κάνει την εμφάνισή τους για πρώτη φορά τα παιχνίδια σε κινητά τηλέφωνα. Η Nokia έγινε γνωστή βάζοντας το βιντεο-παιχνίδι Snake από την δεκαετία του '70, σε μερικές από τις πρώτες μονόχρωμες συσκευές της. Ακολούθησαν και άλλοι κατασκευαστές εγκαθιστώντας παιχνίδια, όπως τα Pong, Tetris και Τρίλιζα. Αυτά τα πρώτα τηλέφωνα μπορεί να είχαν ψεγάδια όμως κατάφεραν κάτι πολύ σημαντικό: να αλλάξουν τον τρόπο με τον οποίο ο κόσμος σκεφτόταν για την επικοινωνία. Όσο οι τιμές τους πέφταν, οι μπαταρίες βελτιωνόταν και οι περιοχές κάλυψης διευρύνονταν, τόσο και πιο πολλοί άνθρωποι άρχισαν να έχουν πάνω τους τέτοιες συσκευές χειρός. Σύντομα τα κινητά τηλέφωνα έπαψαν να είναι μια καινοτομία στον τρόπο επικοινωνίας. Οι ανάγκες των πελατών, με τον καιρό, έφερναν πιέσεις για περισσότερες καινοτομίες και παιχνίδια, όμως υπήρχε ένα βασικό πρόβλημα. Οι κατασκευαστές δεν είχαν τα κίνητρα και τους πόρους για να φτιάξουν κάθε εφαρμογή που ζητούσαν οι χρήστες. Έπρεπε να βρουν έναν τρόπο να τους παρέχουν μια πύλη που να προσφέρει υπηρεσίες ψυχαγωγίας και πληροφοριών χωρίς να επιτρέπουν την πρόσβαση στον προγραμματισμό των συσκευών. Για την επίλυση, λοιπόν, αυτού του προβλήματος, έγινε απόπειρα επιστράτευσης του Διαδικτύου. 1.2.1. Wireless Application Protocol (WAP) Όπως αποδείχτηκε, η απευθείας πρόσβαση στο Διαδίκτυο δεν μπόρεσε να ταιριάξει στις προδιαγραφές των τότε φορητών συσκευών. Οι ιστοσελίδες ήταν γεμάτες χρώματα, πληθώρα κειμένων, εικόνων και άλλων ειδών πολυμέσων. Η βάση αυτών των ιστοσελίδων ήταν το JavaScript και το Flash, καθώς και άλλες τεχνολογίες που σκοπό είχαν να βελτιστοποιήσουν την εμπειρία του χρήστη και συχνά ήταν σχεδιασμένες για να τρέχουν σε αναλύσεις 800*600 pixel και υψηλότερες. Όταν το πρώτο clamshell κινητό, το Motorola StarTAC, λανσαρίστηκε στην αγορά το 1996, είχε οθόνη LCD, μόλις, 10 ψηφίων. Παράλληλα η Nokia είχε κυκλοφορήσει ένα από τα πρώτα slider κινητά, το 8110, το οποίο μπορούσε να προβάλει κείμενο 13 χαρακτήρων ανά γραμμή. Τα κινητά αυτά, με τις εξαιρετικά μικρές οθόνες χαμηλών αναλύσεων και τον περιορισμένο αποθηκευτικό τους χώρο και υπολογιστικές δυνατότητες, δεν μπορούσαν να διαχειριστούν απαιτητικές διεργασίας με πολλά δεδομένα, με τον τρόπο που μέχρι στιγμής έκανε ένας συμβατικός browser. Εκτός αυτού, το κόστος για το απαιτούμενο bandwidth ήταν απαγορευτικό. Το Πρωτόκολλο Ασύρματων Εφαρμογών (WAP) έκανε την εμφάνισή του απευθυνόμενο στα προηγούμενα προβλήματα. Με απλά λόγια, το WAP ήταν μια ξεγυμνωμένη έκδοση του βασικού πρωτοκόλλου του Διαδικτύου, ΗΤΤP. Σε αντίθεση με τους συμβατικούς browser, οι WAP-browser είχαν σχεδιαστεί για να τρέχουν μέσα από την μνήμη και για τους περιορισμούς του bandwidth του τηλεφώνου. Ιστοσελίδες τρίτων προσέφεραν σελίδες WAP γραμμένες σε γλώσσα mark-up που ονομαζόταν Wireless Markup Language (WML) που προβαλλόταν στον WAP-browser ενός κινητού. Η πλοήγηση μέσα σε αυτές γινόταν με παρόμοιο τρόπο όπως γινόταν και σε αυτές του Διαδικτύου, απλά η φιλοσοφία τους ήταν πολύ πιο απλή. Η λύση που έφερε το WAP κατάφερε να πάρει να την πίεση για περισσότερες εφαρμογές,από πλευράς πελατών, από τις κατασκευάστριες εταιρίες και να την μετατοπίσει στους 7
προγραμματιστές, γεγονός που καθιστούσε αυτούς υπεύθυνους για την παροχή περισσότερων υπηρεσιών στους πελάτες. Έτσι για πρώτη φορά, οι προγραμματιστές είχαν την ευκαιρία να αναπτύξουν εφαρμογές για χρήστες κινητών τηλεφώνων. Οι περισσότερες από τις πρώτες WAP σελίδες ήταν επεκτάσεις ήδη γνωστών ιστοσελίδων, όπως CNN.com, ESPN.com, που απλά έψαχναν νέους τρόπους να πάρουν την πρωτιά από τους ανταγωνιστές τους. Ως αποτέλεσμα, οι χρήστες είχαν πρόσβαση σε Ειδήσεις, Χρηματιστήριο και αποτελέσματα αγώνων από το κινητό τους. Ωστόσο, η διαφήμιση WAP εφαρμογών ήταν δύσκολη, καθώς δεν υπήρχε κάποιος έτοιμος μηχανισμός. Μερικές από τις πιο πετυχημένες εφαρμογές ήταν εφαρμογές προσωποποίησης του κινητού, που για πρώτη φορά επέτρεπαν στους χρήστες να κατεβάζουν ringtone και wallpaper. Εικόνα 2: Μια WAP εφαρμογή για διαχείριση e-mail Από την άλλη πλευρά, ένας WAP browser συνήθως ήταν δύσχρηστος και αργός. Τα URL ήταν μεγάλα και δύσκολα να τυπωθούν με τα πληκτρολόγια των κινητών και οι σελίδες δύσκολες στην πλοήγηση και απευθυνόταν σε όλα τα είδη οθονών με ακριβώς τον ίδιο τρόπο με αποτέλεσμα η εμπειρία του χρήστη να είναι μέτρια και καθόλου ελκυστική. Αυτό σε συνδυασμό με τις εμπορικές ελλείψεις οδήγησαν το WAP σε αποτυχία στις περισσότερες περιοχές του κόσμου. Αποτυχία έγινε όμως και για τους προγραμματιστές, όταν οι πάροχοι δικτύων τηλεφωνίας, για διαφημιστικούς λόγους, άρχισαν να επιτρέπουν την πρόσβαση μόνο σε συγκεκριμένες σελίδες, με αποτέλεσμα οι περισσότερες εφαρμογές που ανέπτυσσαν να μην φτάνουν στο κοινό. 1.2.2. Φορητές Πλατφόρμες Ως επακόλουθο, οι απαιτήσεις του κοινού δεν κατευνάστηκαν. Η συγγραφή εφαρμογών με σύγχρονα γραφικά, όπως αυτά των videogames σε περιβάλλον WAP ήταν αδύνατη. Οι νέοι της εποχής έχοντας στην κατοχή τους συσκευές όπως music players, φορητές παιχνιδομηχανές, ψηφιακές φωτογραφικές μηχανές άρχισαν να αναζητούν λύσεις ενσωμάτωσης όλων των παραπάνω σε μία συσκευή που θα τους τα προσέφερε όλα. 8
Καθώς οι μνήμες γινόταν φθηνότερες, οι μπαταρίες καλύτερες και καθώς πολλά PDA και άλλες ενσωματωμένες συσκευές άρχισαν να τρέχουν συμπυκνωμένες εκδόσεις διάφορων γνωστών λειτουργικών συστημάτων, οι κατασκευάστριες εταιρείες κινητών συνειδητοποίησαν πως θα πρέπει αν αλλάξουν τακτική για να παραμείνουν στην αγορά. Με αυτό το σκεπτικό, εμφανίστηκαν στο προσκήνιο διάφορες φορητές πλατφόρμες, για τις οποίες οι προγραμματιστές γράφουν ακόμη και σήμερα εφαρμογές. Νέα smartphone άρχισαν να τρέχουν Palm (Garnet OS) και RIM BlackBerry OS. Η Sun Microsystems έβγαλε στο τραπέζι την δημοφιλή πλατφόρμα της Java και αναφάνηκε η J2ME (Java Micro Edition). Άλλες πλατφόρμες όπως το Symbian OS, αναπτύχθηκαν από κατασκευάστριες κινητών όπως Νοkia, Sony Ericsson, Motorola και Samsung, ενώ το Apple iphone OS προστέθηκε στην λίστα το 2008. Μία τέτοια πλατφόρμα είναι και το Android. Εικόνα 3: Κινητά τηλέφωνα από διάφορες πλατφόρμες φορητών συσκευών 1.3. Λίγα λόγια για το Android Το Android είναι λειτουργικό σύστημα για συσκευές κινητής τηλεφωνίας και άλλες συσκευές το οποίο τρέχει τον πυρήνα του λειτουργικού Linux. Αρχικά αναπτύχθηκε από την Google και αργότερα από την Open Handset Alliance. Επιτρέπει στους κατασκευαστές λογισμικού να συνθέτουν κώδικα με την χρήση της γλώσσας προγραμματισμού Java, ελέγχοντας την συσκευή μέσω βιβλιοθηκών λογισμικού ανεπτυγμένων από την Google. Η πρώτη παρουσίαση της πλατφόρμας Android έγινε στις 5 Νοεμβρίου 2007, παράλληλα με την ανακοίνωση της ίδρυσης του οργανισμού Open Handset Alliance, μιας κοινοπραξίας 48 τηλεπικοινωνιακών εταιριών, εταιριών λογισμικού καθώς και κατασκευής hardware, οι οποίες είναι αφιερωμένες στην ανάπτυξη και εξέλιξη ανοιχτών προτύπων στις συσκευές κινητής τηλεφωνίας. Η Google δημοσίευσε το μεγαλύτερο μέρος του κώδικα του Android υπό τους όρους της Apache License, μιας ελεύθερης άδειας λογισμικού. 9
Εικόνα 4: Το λογότυπο του Android 1.3.1. Ιστορία Το 2005 η Google αγόρασε την αρχική εταιρία Android Inc. Που βρισκόταν στο Palo Alto της California. Κάποια από τα άτομα που πήγαν εκεί για να δουλέψουν για την Google ήταν ο Rick Miner, ο συνιδρυτής της Wildfire Communications, ο Andy Rubin, συνιδρυτής της Danger, o Chris White, μηχανικός στο WebTv και ο Nick Sears ο πρώην αντιπρόεδρος της T-Mobile. Όλοι αυτοί ξεκίνησαν να αναπτύσσουν ένα Linux-based λειτουργικό σύστημα για κινητά τηλέφωνα και άλλες κινητές συσκευές. Ο στόχος τους ήταν ένα ευέλικτο λειτουργικό σύστημα καθώς και αναβαθμίσιμο. Στις 5 Νοεμβρίου του 2007, διάφορες εταιρίες συνεργάστηκαν για να δημιουργήσουν την Open Handset Alliance. Οι πιο γνωστές εταιρίες που συνεργάστηκαν είναι: HTC Corporation T- Mobile Vodafone Motorola, Inc. NVIDIA Corporation Sony Ericsson Intel Corporation Toshiba Texas Qualcomm Samsung Electronics Sprint Nextel LG Electronics, Inc. Instruments Incorporated Ξεκίνησαν με στόχο να αναπτύξουν open standards για mobile συσκευές και έτσι το πρώτο τους προϊόν ήταν η πλατφόρμα Android που ήταν χτισμένη πάνω στον πυρήνα του Linux. Σχεδιάστηκε ώστε να εξυπηρετεί τις εταιρίες κινητής τηλεφωνίας, τους κατασκευαστές συσκευών και τους προγραμματιστές εφαρμογών. Το Android SDK παρουσιάστηκε ανεπίσημα για πρώτη φορά τον Νοέμβριο του 2007. Τον Σεπτέμβριο του 2008 η T-Mobile ανακοίνωσε την διαθεσιμότητα του T-Mobile G1, του πρώτου Smartphone βασισμένο στο λειτουργικό Android. Λίγες μέρες αργότερα η Google ανακοίνωσε την 10
διαθεσιμότητα του Android SDK Release Candidate 1.0. Το Android ήταν διαθέσιμο σαν opensource λογισμικό από τον Οκτώβριο του 2008. Μέσω του Apache, ιδιωτικές εταιρίες μπορούσαν να προσθέσουν τις δικές τους εφαρμογές και επεκτάσεις και να τις πουλήσουν χωρίς να υποχρεούνται να τις υποβάλλουν στην open-source κοινότητα. Στα τέλη του 2008 η Google ανακοίνωσε μια συσκευή με το όνομα Android Dev Phone 1 που είχε την δυνατότητα να τρέχει Android εφαρμογές χωρίς να είναι άμεσα συνδεδεμένη με κάποιο δίκτυο κινητής τηλεφωνίας. Ο στόχος της συσκευής αυτής ήταν να επιτρέψει στους προγραμματιστές να πειραματιστούν με μια πραγματική συσκευή με Android χωρίς κάποιο συμβόλαιο με εταιρία κινητής τηλεφωνίας. Οι ημερομηνίες που κυκλοφόρησαν επίσημα διάφορες εκδόσεις του Android φαίνονται στον πίνακα 1: Έκδοση Ονομασία Ημερομηνία Έκδοσης Επίπεδο Διανομή στο κοινό API 4.2 Jelly Bean 13 Νοεμβρίου 2012 17 0.8% 4.1.x Jelly Bean 9 Ιουλίου 2012 16 5.9% 4.0.x Ice Cream Sandwich 19 Οκτωβρίου 2011 14-15 10.9% 3.x.x Honeycomb 22 Φεβρουαρίου 2011 12-13 2.1% 2.3.x Gingerbread 6 Δεκεμβρίου 2010 9-10 50.6% 2.2 Froyo 20 Μαϊόυ 2010 8 17.3% 2.0, 2.1 Eclair 26 Οκτωβρίου 2009 7 4.7% 1.6 Donut 15 Σεπτέμβριο 2009 4 0.5% 1.5 Cupcake 30 Μαρτίου 2009 3 0.2% Πίνακας 1 1.3.2. Γιατί Ανάπτυξη σε Android; To Android είναι μια ολοκληρωμένη, ανοιχτή και ελεύθερη πλατφόρμα για κινητά τηλέφωνα που περιλαμβάνει ένα λειτουργικό σύστημα (OS), το απαραίτητο ενδιάμεσο λογισμικό, βιλιοθήκες και βασικές εφαρμογές. Το Android SystemDevelopmentKit παρέχει στους προγραμματιστές όλα τα εργαλεία και APIs για να αρχίσουν να αναπτύσσουν λογισμικό για την πλατφόρμα Android χρησιμοποιώντας τη γλώσσα προγραμματισμού Java. 11
i) Λειτουργικότητα και ευελιξία Το Android είναι μια μοναδική πλατφόρμα που επιτρέπει την ανάπτυξη εφαρμογών λογισμικού το οποίο εκμεταλλεύεται πλήρως τις δυνατότητες μιας συμβατής συσκευής. Για παράδειγμα, οι προγραμματιστές εφαρμογών είναι ελεύθεροι να δημιουργήσουν εφαρμογές που χρησιμοποιούν οποιαδήποτε από τις βασικές λειτουργίες του τηλεφώνου όπως η αποστολή SMS, τηλεφωνικές κλήσεις, τη λήψη φωτογραφιών, το GPS κτλ. Έτσι διευκολύνονται στην ανάπτυξη πιο περίπλοκου και πιο πλούσια λειτουργικού λογισμικού. Αυτό το λειτουργικό σύστημα κινητών τηλεφώνων (ή άλλων μικρών φορητών συσκευών που συνδέονται στο διαδίκτυο) στηρίζεται στον ελεύθερο πυρήνα του Linux. Επιπλέον, η πλατφόρμα ανάπτυξης Android είναι μια πλατφόρμα multi tasking, πράγμα που σημαίνει ότι κάθε εφαρμογή μπορεί να τρέξει στο τηλέφωνο ταυτόχρονα κάποια άλλη χωρίς να επηρεαστεί η απόδοσή τους, και αυτό είναι καλύτερο από το να περιορίζεται σε μία εφαρμογή κάθε φορά. Το Android είναι μια πλατφόρμα ανοικτού κώδικα, πράγμα που σημαίνει ότι μπορεί εύκολα να επεκταθεί και να τροποποιηθεί για να συμβαδίζει και να υιοθετεί τις τελευταίες τεχνολογίες και εξελίξεις. Το γεγονός ότι και η πηγή της πλατφόρμας είναι ανοικτή διασφαλίζει ότι η ανάπτυξη το Android θα έχει συνεχή πρόοδο και θα εξελίσσεται αφού ένας μεγάλος αριθμός ικανών android προγραμματιστών εργάζεται για τη δημιουργία ελέυθερων για χρήση προηγμένων εργαλείων λογισμικού. ii) Πλήρης παραμετροποίηση Δεν υπάρχει διαφορά μεταξύ των λειτουργιών / εφαρμογών οι οποίες είναι ενσωματωμένες στο τηλεφώνου απο τις εφαρμογές που δημιουργούνται και προστίθενται από τρίτους προγραμματιστές Android. Οι τελευταίες μπορούν και έχουν την ίδια πρόσβαση σε όλες τις κύριες λειτουργίες της συσκευής κάτι που επιτρέπει στους τελικούς χρήστες να απολαμβάνουν ένα ευρύ φάσμα εφαρμογών Android που μπορούν να χρησιμοποιηθούν για τη σχεδόν απεριόριστους σκοπούς. Με συσκευές χτισμένες στην πλατφόρμα Android, οι χρήστες έχουν τη δυνατότητα να προσαρμόσουν πλήρως τη συσκευή τους ανάλογα με τις ανάγκες και τις απαιτήσεις τους. Τυχόν εφαρμογές ακόμα και οι βασικές λειτουργίες μπορεί να τροποποιηθούν ή να αντικατασταθούν πλήρως απο άλλες. Για παράδειγμα, ο χρήστης μπορεί να χρησιμοποιήσει την επιθυμητή του εφαρμογή για να εμφανίσει τις φωτογραφίες που είναι αποθηκευμένες στο τηλέφωνό του, ή για να έχει πρόσβαση στην αλληλογραφία του. iii) Διαδραστικότητα Οι προγραμματιστές Android μπορούν να δημιουργήσουν πολύπλοκες καινοτόμες εφαρμογές με σχεδόν απεριόριστη λειτουργικότητα. Για παράδειγμα, μια εφαρμογή μπορεί να μεταδώσει τα δεδομένα από το κινητό σας με το διαδίκτυο (κάτι που μπορεί να περιλαμβάνει το ημερολόγιο σας και τις προγραμματισμένες εκδηλώσεις, λίστα με τις επαφές, τις φωτογραφίες σας και ακόμη και την τρέχουσα θέση σας, αλλά και παραγγελίες, τιμολόγια κτλ) και να λάβει όλα όσα μπορεί να χρειαστεί online και να εμφανίζονται στην οθόνη της συσκευής. iv) Απλούστερη aνάπτυξη εφαρμογών κινητών Η πλατφόρμα παρέχει στο καθένα που ασχολείται με την ανάπτυξη εφαρμογών τη δυνατότητα χρησιμοποίησης μια μεγάλης ποικιλίας από βιβλιοθήκες και τα χρήσιμα εκείνα εργαλεία που μπορούν να χρησιμοποιηθούν για τη δημιουργία του πιο εξελιγμένου λογισμικού. Αυτή η ολοκληρωμένη δέσμη από έτοιμα εργαλεία αυξάνει σημαντικά την παραγωγικότητα των προγραμματιστών Android εφαρμογών και τους βοηθά να δημιουργήσουν εκπληκτικά πλούσιο λογισμικό γρηγορότερα και με λιγότερα λάθη. 12
1.4. Η αρχιτεκτονική του Αndroid Σε αυτήν την υποενότητα παρουσιάζεται η αρχιτεκτονική της πλατφόρμας Android, η οποία όπως φαίνεται στην Εικόνα 5 αποτελείται από τα layers: Linux Kernel, Libraries, Android Runtime, Application Framework και Applications. Εικόνα 5: Αρχιτεκτονική Αndroid 1.4.1. Linux Kernel Το Android έχει χτιστεί πάνω στον Linux Kernel και επομένως χρησιμοποιείται Linux Power Management για την επικοινωνία με το hardware της συσκευής. Συγκεκριμένα χρησιμοποιείται Linux για τους drivers της συσκευής, την διαχείριση μνήμης, την διαχείριση διεργασιών και τη δικτύωση. Ωστόσο ο προγραμματιστής εφαρμογών δεν θα χρειαστεί ποτέ να προγραμματίσει σε αυτό το επίπεδο. 1.4.2. Libraries Στο επόμενο επίπεδο βρίσκονται οι βιβλιοθήκες. Το Android περιλαμβάνει ένα σετ από βιβλιοθήκες, που χρησιμοποιούνται από διάφορα components του συστήματος και είναι γραμμένες σε C/C++. Αυτές οι δυνατότητες διαθέτονται στους developers μέσα από το Android Application Framework. Μερικές 13
από τις βασικές βιβλιοθήκες είναι οι παρακάτω: System C library: είναι μια BSD-παραγόμενη εφαρμογή της standard C system library (libc), συντονισμένη για embedded Linux-based συσκευές. Media Libraries: βασισμένες στο OpenCore ^y PacketVideo. Οι βιβλιοθήκες υποστηρίζουν playback και recording σε πολλά δημοφιλή audio και video formats, όπως MPEG4, H.264, MP3, AAC, AMR, JPG και PNG. Surface Manager: συνθετικός window manager παρόμοιος με αυτόν των Windows Vista ή του Compiz, αλλά πολύ πιο απλό. Οι εντολές σχεδιασμού πηγαίνουν εκτός οθόνης bitmap που μετέπειτα συνδυάζονται με άλλα bitmaps για να σχηματίσουν την οθόνη που βλέπει ο χρήστης. Αυτό επιτρέπει στο σύστημα να δημιουργήσει πολλά εφέ όπως διάφανα παράθυρα και εντυπωσιακά transitions. LibWebCore: ένας μοντέρνος browser που χρησιμοποιεί την WebKit βιβλιοθήκη για την γρήγορη προβολή HTML περιεχομένου. Η ίδια μηχανή χρησιμοποιείται και στο Google Chrome browser, στον Safari της Apple και στα Nokia S60. SGL: μηχανή για 2D γραφικά. 3D libraries: βασίζονται στα OpenGl ES 1.0 APIs. Οι βιβλιοθήκες χρησιμοποιούν 3D υλικό αν η συσκευή το διαθέτει αλλιώς έναν γρήγορο software rasterizer. SQLite: μια δυναμική και ελαφριά βάση δεδομένων, που χρησιμοποιείται από εφαρμογές για μόνιμη αποθήκευση δεδομένων, παρόμοια με αυτή που χρησιμοποιείται στον Firefox και στο IPhone. 1.4.3. Android Runtime Στο αμέσως επόμενο επίπεδο βρίσκεται το Android Runtime, το οποίο αποτελείται από μια εικονική μηχανή (Dalvik Virtual Machine) και τις βιβλιοθήκες πυρήνα. Dalvik είναι μια εικονική μηχανή (VM) που σχεδιάστηκες και γράφτηκε από τον Dan Bornstrein στη Google. Ο κώδικας της εφαρμογής μεταγλωττίζεται σε εντολές μηχανής που ονομάζονται bytecodes και στη συνέχεια εκτελούνται από την VM στο κινητό τηλέφωνο. Παρόλο που το format των bytecodes είναι λίγο διαφορετικό, η Dalvik είναι ουσιαστικά μια Java VM σχεδιασμένη για χαμηλές απαιτήσεις σε μνήμη. Επιτρέπει πολλαπλά instances της VM να τρέχουν ταυτόχρονα και εκμεταλλεύεται το Linux για τον τομέα της ασφάλειας και της διαχείρισης εφαρμογών. Η Dalvik VM διαφέρει από την παραδοσιακή Java σε δυο σημεία: Η πρώτη τρέχει.dex αρχεία, τα οποία έχουν προέλθει κατά την ώρα της μεταγλώττισης από τα.class και.jar αρχεία. Τα.dex αρχεία είναι πιο συμπαγή και αποδοτικά από τα.class το οποίο είναι στόχος για συσκευές περιορισμένης μνήμης μπαταρίας. Οι Java βιβλιοθήκες πυρήνα του Android είναι διαφορετικές από τις Java Standard Edition (Java SE) βιβλιοθήκες, αλλά και από τις Java Mobile Edition (Java ME) βιβλιοθήκες. 1.4.4. Application Framework Αυτό το επίπεδο παρέχει πλήρη προσβασιμότητα στους developers στα ίδια framework APIs που χρησιμοποιούνται από τις εφαρμογές πυρήνα. Έτσι συμπεριλαμβάνει τα υψηλού επιπέδου δομικά στοιχεία που μπορούν να χρησιμοποιηθούν για την δημιουργία εφαρμογών. Μέρη αυτού του toolkit παρέχονται από την Google και άλλα είναι επεκτάσεις των services των προγραμματιστών. 14
Κάτω από όλες τις εφαρμογές υπάρχει ένα σύνολο συστημάτων και υπηρεσιών συμπεριλαμβανομένου των παρακάτω: Μια πλούσια και επεκτάσιμη συλλογή από Views που μπορούν να χρησιμοποιηθούν για να δημιουργηθεί μια εφαρμογή, όπως λίστες, πίνακες, χώρος κειμένου, κουμπιά, ακόμα και ενσωματωμένος web browser. Content Providers που επιτρέπουν στις εφαρμογές να έχουν πρόσβαση σε δεδομένα άλλων εφαρμογών (όπως επαφές), ή να διαμοιράζονται τα δικά τους δεδομένα. Resource Manager, που παρέχει προσβασιμότητα σε οτιδήποτε δεν είναι κώδικας, όπως αλφαριθμητικά, γραφικά και αρχεία που αφορούν την εμφάνιση της εφαρμογής. Notification Manager, που επιτρέπει σε όλες τις εφαρμογές να εμφανίζουν ειδοποιήσεις στο status bar. Activity Manager, ο οποίος διαχειρίζεται τον κύκλο ζωής (life cycle) των εφαρμογών και παρέχει πληροφορίες για την πλοήγηση μεταξύ των εφαρμογών. 1.4.5. Applications Το τελευταίο στρώμα στην αρχιτεκτονική του Android είναι τα applications και είναι αυτά που αντιλαμβάνεται ο χρήστης. Πρόκειται για εφαρμογές όπως email client, πρόγραμμα για SMS, ημερολόγιο, χάρτες, browser και άλλα. Όλες οι εφαρμογές είναι προγραμματισμένες σε Java. Μια Java εφαρμογή για Android δεν είναι συμβατή με προγράμματα Java γραμμένα για Java SE και Java ME πλατφόρμες. 1.5. Aνατομία μιας Android εφαρμογής Υπάρχουν τέσσερα διαφορετικά είδη συστατικών μερών μια Android εφαρμογής. Κάθε είδος εξυπηρετεί συγκεκριμένο σκοπό και έχει συγκεκριμένο κύκλο ζωής που ορίζει πότε το συστατικό θα δημιουργηθεί και θα καταστραφεί. Τα τέσσερα αυτά building blocks είναι τα: Activities, Services, Content Providers, Broadcast receivers και αναλύονται στην συνέχεια. 1.5.1. Συστατικά εφαρμογής i) Activities Μια activity αντιπροσωπεύει μια οθόνη με ένα user interface. Για παράδειγμα, μια εφαρμογή για email μπορεί να έχει μια activity που δείχνει μια λίστα από νέα emails, μια άλλη activity για να δημιουργείς email και μια άλλη για να διαβάζεις emails. Παρόλο που οι activities συνεργάζονται για να δημιουργήσουν μια συνεκτική εμπειρία για τον χρήστη, κάθε μια είναι ανεξάρτητη από τις υπόλοιπες. Έτσι, μια διαφορετική εφαρμογή μπορεί να θέσει σε λειτουργία οποιαδήποτε από αυτές τις activities (αν η εφαρμογή για email το επιτρέπει). Για παράδειγμα, μια κάμερα μπορεί να θέσει σε λειτουργία την activity που μπορείς να συνθέσεις email, έτσι ώστε ο χρήστης να μπορέσει να την διαμοιραστεί. ii) Services Μια service είναι ένα συστατικό που τρέχει στο background για να διεκπεραιώσει μεγάλης χρονικής διάρκειας διαδικασίες, ή για να εκτελέσει εργασίες απομακρυσμένων διεργασιών. Μια service δεν παρέχει user interface. Για παράδειγμα, μια service μπορεί να παίζει μουσική στο background ενώ ο χρήστης έχει ανοιχτή μια άλλη εφαρμογή. Ένα άλλο συστατικό, όπως μια activity, μπορεί να θέσει σε λειτουργία μια service και να την αφήσει να τρέχει ή να την δεσμεύσει ώστε να επικοινωνεί μαζί της. 15
iii) Content providers Ένας content provider διαχειρίζεται ένα σύνολο από διαμοιραζόμενα δεδομένα της εφαρμογής. Έτσι τα δεδομένα μπορούν να αποθηκευτούν στο σύστημα αρχείων, στην SQLite βάση δεδομένων, στο web, ή σε οποιοδήποτε χώρο αποθήκευσης έχει πρόσβαση η εφαρμογή. Μέσω του content provider, άλλες εφαρμογές μπορούν να ζητήσουν ή να τροποποιήσουν τα δεδομένα αν αυτός το επιτρέπει. Για παράδειγμα το λειτουργικό σύστημα Android προσφέρει έναν content provider που διαχειρίζεται της πληροφορίες των επαφών του χρήστη. Έτσι οποιαδήποτε εφαρμογή με την κατάλληλη άδεια μπορεί να ζητήσει από ένα μέρος του content provider να διαβάσει ή να γράψει πληροφορία για μια συγκεκριμένη επαφή. Οι content providers είναι επίσης χρήσιμοι για την ανάγνωση και εγγραφή δεδομένων που είναι ιδιωτικά για την εφαρμογή μας και όχι διαμοιραζόμενα. Για παράδειγμα μια εφαρμογή Note Pad χρησιμοποιεί τον content provider για να αποθηκεύσει σημειώσεις. iv) Broadcast receivers Ένας broadcast receiver είναι ένα συστατικό που απαντά σε system-wide broadcast ανακοινώσεις. Πολλά broadcasts προέρχονται από το σύστημα, για παράδειγμα μια broadcast ανακοίνωση ότι η οθόνη έκλεισε, η μπαταρία είναι χαμηλή, ή ότι τραβήχτηκε μια φωτογραφία. Τα broadcasts μπορούν ακόμα να αρχικοποιηθούν από εφαρμογές, για παράδειγμα το να επιτρέπεται άλλες εφαρμογές να ξέρουν ότι κάποια δεδομένα έχουν φορτωθεί στην συσκευή και είναι διαθέσιμα για χρήση. Παρόλο που οι broadcast receivers δεν έχουν user interface, μπορούν να δημιουργήσουν μια ειδοποίηση στο status bar, για να ενημερώσουν το χρήστη όταν ένα broadcast συμβεί. 1.5.2. Ενεργοποίηση Συστατικών Τρία από τα τέσσερα building blocks - activities, services, και broadcast receivers - ενεργοποιούνται από ένα ασύγχρονο μήνυμα που ονομάζεται intent. Τα intents δεσμεύουν μεμονωμένα συστατικά μεταξύ τους κατά την διάρκεια της εκτέλεσης, είτε το συστατικό ανήκει στην εφαρμογή μας είτε σε άλλη. Για τις activities και τις services, ένα intent ορίζει την μια ενέργεια που πρέπει να εκτελεστεί ( για παράδειγμα να "δεις" ή να "στείλεις" κάτι) και μπορεί να διευκρινίζει το URI των δεδομένων πάνω στο οποίο θα γίνει η ενέργεια. Για παράδειγμα, ένα intent μπορεί να μεταβιβάσει μια αίτηση σε μια activity για να δείξει μια εικόνα ή να ανοίξει μια ιστοσελίδα. Σε μερικές περιπτώσεις υπάρχει η δυνατότητα να τεθεί σε λειτουργία μια activity για να λάβουμε ένα αποτέλεσμα το οποίο στη συγκεκριμένη περίπτωση μπορεί να επιστραφεί σε ένα intent από την activity. Για τους broadcast receivers, το intent ορίζει την ανακοίνωση που πρόκειται να γίνει broadcast. 1.5.3. Το αρχείο Manifest Πριν το Android θέσει σε λειτουργία ένα συστατικό μιας εφαρμογής, το σύστημα πρέπει να γνωρίζει ότι το συστατικό υπάρχει διαβάζοντας το αρχείο AndroidManifest.xml της εφαρμογής. Η εφαρμογή πρέπει να ορίζει όλα τα συστατικά της σε αυτό το αρχείο, το οποίο πρέπει να βρίσκεται στο root του project directory της εφαρμογής. Το αρχείο manifest προκειμένου να ορίσει τα συστατικά των εφαρμογών κάνει τα εξής: Προσδιορίζει κάθε άδεια του χρήστη που απαιτεί η εφαρμογή, όπως πρόσβαση στο Internet ή αναγνωσιμότητα των επαφών του χρήστη. Ορίζει το ελάχιστο API Level που απαιτείται από την εφαρμογή, και βασίζεται σε ποια APIs αυτή χρησιμοποιεί. Ορίζει τα χαρακτηριστικά του hardware και του software που χρησιμοποιούνται ή απαιτούνται από την εφαρμογή, όπως κάμερα, bluetooth services, ή multitouch οθόνη. 16
Δηλώνει τις API βιβλιοθήκες με τις οποίες η εφαρμογή χρειάζεται να συνδεθεί, για παράδειγμα η Google Maps βιβλιοθήλη. 1.5.4. Resources Μια Android εφαρμογή δεν είναι μόνο κώδικας αλλά και resources που είναι εικόνες, audio αρχεία και οτιδήποτε σχετικό με την εμφάνιση της εφαρμογής. Για παράδειγμα, ο προγραμματιστής πρέπει να ορίσει animations, menus, styles, χρώματα και την εμφάνιση της activity με XML αρχεία. Χρησιμοποιώντας application resources είναι εύκολο να αναβαθμιστούν πολλά χαρακτηριστικά μιας μια εφαρμογής χωρίς να τροποποιηθεί ο κώδικας. Όλα τα resources γίνονται compile μέσα στο application και αποθηκεύονται στον φάκελο res μέσα στο project. Υπάρχουν ξεχωριστοί φάκελοι για τις εικόνες, τα strings, τα xml και άλλα. Ο resource compiler συμπιέζει και πακετάρει τα resources και μετά δημιουργεί μια κλάση R που περιέχει τους identifiers που χρησιμοποιούνται στο πρόγραμμα για να ανακληθούν τα resources στο πρόγραμμα. Έτσι το Android αναγνωρίζει ότι όλες οι αναφορές σε resources είναι έγκυρες και σώζει χώρο καθώς δεν αποθηκεύει όλα τα resource keys. 1.6. Κύκλος ζωής Activity Οι activities στο σύστημα, διαχειρίζονται σαν μια στοίβα από activities. Όταν μια activity ξεκινήσει, τότε τοποθετείται στην κορυφή της στοίβας και γίνεται η τρέχουσα activity και η προηγούμενη activity παραμένει από κάτω στην στοίβα, η οποία έρχεται μόνο στο προσκήνιο αν η καινούρια activity τελειώσει. Μια activity μπορεί ουσιαστικά να βρεθεί σε τέσσερις καταστάσεις: Αν μια activity βρίσκεται στο προσκήνιο, δηλαδή εμφανίζεται στην οθόνη (είναι στην κορυφή της στοίβας), τότε είναι στην κατάσταση active ή running. Αν μια activity δεν είναι focused αλλά είναι ακόμα ορατή (δηλαδή μια νέα activity που δεν είναι full-sized είναι focused πάνω από την πρώτη activity), τότε βρίσκεται στην κατάσταση paused. Σε αυτήν την κατάσταση η activity είναι ζωντανή (διατηρεί όλη την κατάσταση), αλλά μπορεί να κλείσει από το σύστημα σε περίπτωση πολύ χαμηλής μνήμης. Αν μια activity είναι πλήρως κρυμμένη από άλλη activity, τότε βρίσκεται στην κατάσταση stopped. Διατηρεί όλη την κατάσταση και τις πληροφορίες, ωστόσο δεν είναι πλέον ορατή στον χρήστη, έτσι το παράθυρό της είναι κρυμμένο και συνήθως κλείνει από το σύστημα όταν υπάρχει ανάγκη για μνήμη. Αν μια είναι στην κατάσταση paused ή stopped, το σύστημα μπορεί να την βγάλει από την μνήμη, είτε ρωτώντας την να την σταματήσει, είτε απλώς κλείνοντας την διεργασία της. Όταν εμφανίζεται ξανά στο χρήστη, πρέπει να ξεκινήσει πάλι και να αποκαταστήσει την προηγούμενη της κατάσταση. Το διάγραμμα που ακολουθεί δείχνει τα σημαντικά μονοπάτια κατάστασης μιας Activity. Τα τετραγωνισμένα παραλληλόγραμμα δείχνουν τις callback μεθόδους που μπορούν να εφαρμοστούν για τις διάφορες διεργασίες όταν μια Activity κινείται μεταξύ διαφόρων καταστάσεων. Τα χρωματιστά στρογγυλεμένα παραλληλόγραμμα δείχνουν τις κύριες καταστάσεις στις οποίες μπορεί να βρεθεί μια Activity. 17
Σχεδίαση 1: Κύκλος ζωής Android Υπάρχουν τρία loops που μπορείτε να διαχειριστείτε μέσα σε μια activity: Το loop entire lifetime μιας activity διενεργείται μεταξύ της πρώτης κλήσης oncreate(bundle) μέχρι μιας τελικής κλήσης ondestroy(). Μια activity θα κάνει όλες τις αρχικοποιήσεις στην κλήση oncreate(), και θα απελευθερώσει όλα τα resources στην ondestroy(). Το loop visible lifetime μιας activity ουσιαστικά είναι μεταξύ μιας κλήσης onstart() και της αντίστοιχης κλήσης onstop(). Κατά την διάρκεια αυτού του loop ο χρήστης μπορεί αν δει την activity στην οθόνη, παρόλο που μπορεί να μην είναι στο προσκήνιο και να αλληλεπιδρά με τον χρήστη. Μεταξύ των δυο αυτών μεθόδων μπορούν να διατηρούνται τα resources που χρειάζονται για να δείχνουν την activity στο χρήστη. Αυτές οι δυο μέθοδοι μπορούν αν καλούνται πολλές φορές, καθώς μια activity εμφανίζεται ή είναι κρυμμένη στο χρήστη. Το foreground lifetime loop μιας activity διενεργείται μεταξύ μιας κλήσης onresume() και της αντίστοιχης κλήσης onpause(). Κατά τη διάρκεια αυτή η activity βρίσκεται μπροστά από όλες τις υπόλοιπες activities και αλληλεπιδρά με τον χρήστη. Μια activity μπορεί να συχνά να μεταβεί μεταξύ των δυο αυτών μεθόδων, για παράδειγμα όταν η συσκευή τίθεται σε sleep mode όταν φτάνει ένα αποτέλεσμα μιας activity μέσω ενός intent. Για αυτό το λόγο ο κώδικας σε αυτές τις μεθόδους πρέπει να είναι αρκετά ελαφρύς. 18
2. ΠΑΡΟΜΟΙΕΣ ΕΦΑΡΜΟΓΕΣ Στην ενότητα αυτή θα παρουσιαστούν και μελετηθούν μερικές από τις δημοφιλέστερες εφαρμογές τοξοβολίας που υπάρχουν στο Google Play, καθώς και οι υπηρεσίες που προσφέρουν. Όλες οι εφαρμογές που εξετάζονται δίνουν την δυνατότητα σε ένα τοξοβόλο να καταχωρήσει τις επιδόσεις του είτε σε μια φόρμα μορφής score-sheet είτε απευθείας σε εικονικό στόχο. 2.1. Archery Score by Mage Το Archery Score είναι μια εφαρμογή που επιτρέπει την εισαγωγή μέσω του touchscreen της συσκευής και προβολή ρίψεων σε εικονικό στόχο. Είναι βασισμένη στους κανόνες της Παγκόσμιας Ομοσπονδίας Τοξοβολίας και αποτελεί μια από τις σοβαρές εφαρμογές που υπάρχουν. Λαμβάνει υπόψη αγωνίσματα Αντίκυρτης και Σύνθετης τοξοβολίας επιτρέποντας παράλληλα την καταγραφή σημειώσεων. Μπορεί να χρησιμοποιηθεί από πολλούς αθλητές και μερικά από τα πλεονεκτήματά της είναι η δυνατότητα δημιουργίας προσωπικών αγωνισμάτων και στόχων με διαφορετικές βαθμολογίες από τους προκαθορισμένος των ήδη υπαρχόντων αγωνισμάτων, καθώς επίσης και η εξαγωγή των προπονήσεων σε αρχεία.csv. Εικόνα 6: Archery Score by Mage 2.2. ArcheryBuddy Το ArcheryBuddy είναι μια εφαρμογή με απλή φιλοσοφία. Μέσω ενός μινιμαλιστικού user interface προσφέρει στον χρήστη την δυνατότητα εισαγωγής και καταχώρησης βολών σε στόχο για ορισμένα αγωνίσματα σύνθετου και αντίκυρτου ή αλλιώς Ολυμπιακού τόξου και δίνει την δυνατότητα προβολής τους για μετέπειτα μελέτη. Παρέχει ένα mode προπόνησης, στο οποίο δεν υπάρχει περιορισμός στις ρίψεις βολών και στους γύρους. Έτσι ο χρήστης μπορεί να 19
χρησιμοποιήσει την εφαρμογή έξω από το πλαίσιο των επίσημων αγωνισμάτων τοξοβολίας. Επιπλέον, δίνεται η δυνατότητα για δημιουργία προσωπικών αγωνισμάτων με μοντέλα που θα καθορίσει ο ίδιος ο χρήστης της εφαρμογής. Τα αποτελέσματα των βολών μπορούν να φανούν και συγκεντρωτικά μαζί με επιπλέον στατιστικά για τις ρίψεις του χρήστη. Εικόνα 7: ArcheryBuddy 2.3. Archery Goldrush Πρόκειται για ένα πολύ απλό εργαλείο κατάδειξης βολών στο στόχο. Δεν προσφέρει την δυνατότητα αποθήκευσης βολών και μετέπειτα προβολής τους. Αντίθετα, η φιλοσοφία της στρέφεται στην δήλωση της θέσης των βελών πάνω στον στόχο, και μόνο, χωρίς να υπολογίσει την βαθμολογία τους, όπως δηλαδή μπορεί ο χρήστης να κάνει και σε ένα συμβατικό score-sheet, γεγονός που δεν περιορίζει τον αριθμό ρίψεων του χρήστη. Τέλος, αξίζει να σημειωθεί πως η εφαρμογή είναι ανοιχτού κώδικα και μοιράζεται ελεύθερα στο Google Code. 20
Εικόνα 8: Archery Goldrush 2.4. Archery ScoreBook Είναι μια εφαρμογή καταγραφής επιδόσεων σε αγωνίσματα τοξοβολίας εσωτερικών και εξωτερικών χώρων για Σύνθετο και Αντίκυρτο τόξο. Χρησιμοποιώντας την αφή δείχνουμε την θέση των βολών μας στον στόχο και η εφαρμογή υπολογίζει αυτόματα από την θέση κατάδειξης την βαθμολογία τους και αργότερα προβάλει στατιστικά προερχόμενα από αυτές. Επιτρέπει την αλλαγή του μεγέθους του στόχου, βελτιστοποιώντας τον όσο καλύτερα γίνεται στις διάφορες οθόνες των συσκευών που μπορεί να εγκατασταθεί και μπορεί να εξάγει τις περιόδους με τις βαθμολογίες τους σε ένα αρχείο excel για προβολή τους και εκτός της συσκευής. Περιέχει επίσης μετρητή βολών προς διευκόλυνση του αθλητή. Εικόνα 9: Archery ScoreBook 21
2.5. Archery Companion Το Archery Companion σε αντίθεση με τις περισσότερες εφαρμογές τοξοβολίας χρησιμοποιεί score-sheet για την καταχώρηση βαθμολογιών και όχι στόχο. Έτσι ο χρήστης επιλέγει κατευθείαν την βαθμολογία της βολής τους και η εφαρμογή δεν χρειάζεται να την υπολογίσει. Ο χρήστης μπορεί να καταγράψει τις επιδόσεις του σε όλα τα ομαδικά, ατομικά και προσωπικά του αγωνίσματα τοξοβολίας, ακόμη και για αυτά του παραδοσιακού αγγλικού Longbow, και μπορεί μάλιστα να διαβάσει τους κανόνες τους όπως επίσης να αλλάξει το σύστημα μονάδων μέτρησης σε αυτό που τον βολεύει. Αξίζει να σημειωθεί πως είναι η μόνη εφαρμογή που περιέχει ρυθμίσεις για αγωνίσματα ανηλίκων. Εικόνα 10: Archery Companion 2.6. Scoring Helper H εφαρμογή αυτή συνδυάζει την εισαγωγή βολών σε score-sheet με την εισαγωγή με κατάδειξη σε στόχο. Δίνει δηλαδή την επιλογή στον χρήστη να διαλέξει τον τρόπο που τον βολεύει περισσότερο. Ανεξαρτήτου επιλογής όμως, η εφαρμογή αποθηκεύει αγώνες των πιο γνωστών κατηγοριών και τους προβάλει κατά αίτηση του χρήστη. Ο τελευταίος μπορεί να φτιάξει τα δικά του αγωνίσματα και να κρατήσει μικρές σημειώσεις κατά την διάρκεια τους και όχι μόνο. Δίνει την δυνατότητα στον χρήστη να εξάγει τον στόχο με τις βολές του ως εικόνα jpeg και να την αποθηκεύσει στο κινητό του. Αξιοσημείωτη είναι η δυνατότητα αλλαγής των στοιχείων που προβάλλονται στην οθόνη, π.χ. η αλλαγή στην διάμετρο του αποτυπώματος των βελών. Τέλος όλες αυτές οι λειτουργίες υποστηρίζονται και για ομαδικά αγωνίσματα. 22
Εικόνα 11: Scoring Helper 2.7. Συμπεράσματα-Συγκρίσεις Όπως παρατηρείται, οι παραπάνω εφαρμογές μοιράζονται πολλούς μηχανισμούς στον τρόπο λειτουργίας τους, με την κάθε μια, όμως, να προσθέτει λίγα χαρακτηριστικά που οι άλλες δεν έχουν. Για παράδειγμα, η εφαρμογή Scoring Helper μπορεί να φιλτράρει και να αλλάξει τον τρόπο με τον όποιο προβάλλονται τα διάφορα στοιχεία της οθόνης και να τα προσαρμόσει στις ανάγκες μας. Οι ArcheryBuddy και Goldrush βλέπουμε πως μοιράζονται την ρύθμιση για, ουσιαστικά, άπειρες βολές σε έναν αγώνα, στην Αrchery ScoreBook συναντάμε έναν διαφορετικό τρόπο αλλαγής μεγέθους του στόχου, ενώ στις Scoring Helper και Archery Companion μπορούμε να εισάγουμε το σκορ σε Score-sheet, με την τελευταία να λειτουργεί και σαν εγχειρίδιο αγωνισμάτων τοξοβολίας. Οι ομοιότητες και οι διαφορές των εφαρμογών αυτών μπορούν να αναλυθούν στον Πίνακα 2, ο οποίος, μαζί με όλες τις εφαρμογές και τις ιδιότητες των εφαρμογών που αναφέρθηκαν προηγουμένως, περιλαμβάνει και παρουσιάζει την εφαρμογή και τις ιδιότητες της μfita, η οποία υλοποιήθηκε στα πλαίσια της εργασίας αυτής. 23
Ιδιότητες Καταχώρηση βολής με κατάδειξη στον στόχο Αυτόματος υπολογισμός βαθμολογίας Επιλογή είδους τόξου Υποστήριξη ομαδικών αγωνισμάτων Επιλογή αγωνίσματος Καταγραφή σημειώσεων Υποστήριξη καταγραφής επιδόσεων για πολλούς αθλητές Επιλογή Απόστασης από τον στόχο Αποθήκευση, επισκόπηση και επεξεργασία επιδόσεων Εξαγωγή επιδόσεων από την βάση δεδομένων Δημιουργία προσωπικών αγωνισμάτων Δημιουργία προσωπικών στόχων Προβολή στατιστικών περιόδου Υποστήριξη zoom στον στόχο Προβολή επιδόσεων ιστορικού Προβολή επιδόσεων μιας περιόδου από το ιστορικό στον στόχο Επιτρέπει καταγραφή επιδόσεων χωρίς όριο βολών Υποστήριξη καταχώρησης επιδόσεων για πολλούς αθλητές Προβολή παραμέτρων όλων των αγωνισμάτων Υποστήριξη αγωνισμάτων ανηλίκων Επιλογή συστήματος μονάδων μέτρησης Αποθήκευση περιόδου ως εικόνα Αλλαγή διαμέτρου αποτυπώματος βέλους στον στόχο Φιλτράρισμα στοιχείων προς προβολή στον στόχο Ταξινόμηση ιστορικού επιδόσεων και βελών βάσει κριτηρίων Καταχώρηση και διαχείριση βελών Δήλωση και μέτρηση σημαντικών επιδόσεων ανά βέλος Διαμοιρασμός επίδοσης σε κοινωνικά δίκτυα και άλλα Archery Score by Mage Archery Buddy Archery Goldrush Archery ScoreBook Scoring Helper Archery Companion μfita Πίνακας 2 Παρατηρούμε πως η μfita μοιράζεται πολλές από τις ιδιότητες της με αυτές που φέρουν οι υπόλοιπες εφαρμογές όμως προσφέρει κι αυτή με τη σειρά της, δικές τις χαρακτηριστικές λειτουργίες που δεν έχουν οι υπόλοιπες. Ειδικά, παρατηρούμε πως προσφέρει στον χρήστη δυνατότητα ταξινόμησης των αποθηκευμένων προπονήσεων, την καταχώρηση και διαχείριση βελών αλλά και την δυνατότητα δήλωσης και μέτρησης των επιδόσεων που μπορεί να θεωρηθούν σημαντικές για τον χρήστη, όλες, ιδιότητες, που δεν συναντώνται στις υπόλοιπες εφαρμογές 24
2.8. Αποκόμιση Αναγκών Οι ιδιότητες που παρουσιάζονται στον πίνακα είναι αποτέλεσμα των αναγκών που προέκυψαν μετά από συνέντευξη με τον τοξοβόλο Στέφανο Τσερκέζη. Κατά την διάρκεια της συζήτησης διαπιστώθηκε πως τοξοβόλοι που χρησιμοποιούν smartphone για την καταγραφή των επιδόσεών τους δεν έχουν συναντήσει κάποια εφαρμογή που να προσφέρει εισαγωγή και διαχείριση βελών παράλληλα με την καταχώρηση βολών. Ως αποτέλεσμα και κατά κύριο λόγο, η εφαρμογή μfita προσπαθεί να καλύψει την έλλειψη αυτή καθώς και τις βασικότερες ανάγκες των αθλητών σε ένα από το δημοφιλέστερα αγωνίσματα τοξοβολίας στην Ελλάδα. Οι ανάγκες που γεννήθηκαν κυμαίνονται σε αναμενόμενα επίπεδα, αν παρατηρήσει κανείς και αυτά που προσφέρουν οι υπόλοιπες εφαρμογές. Έτσι εκτός από την εισαγωγή και την διαχείριση βελών, κατά την διάρκεια της συνέντευξης, διαπιστώθηκε πως υπάρχει ανάγκη για δημιουργία σημειώσεων που περιγράφουν παρατηρήσεις που έχει να κάνει ο αθλητής σε σχέση με την επίδοση κάποιας βολής, την κατάσταση του τόξου ή κάποιου βέλους, την τεχνική του ίδιου του αθλητή, τις περιβαλλοντικές συνθήκες και πολλών άλλων που ίσως δεν είναι απαραίτητο να έχουν απ ευθείας σύνδεση με το άθλημα. Τονίστηκε πως είναι σημαντικό η δήλωση της βαθμολογίας μιας βολής είναι συνετό να γίνεται πάνω σε εικονικό στόχο, δείχνοντας έτσι και την θέση του βέλους, πληροφορία που θεωρείτε κρίσιμη προς αποθήκευση και μελέτη αργότερα. Άξιο αναφοράς είναι και το γεγονός πως αν μια επίδοση θεωρηθεί σημαντική, πολλοί αθλητές σημειώνουν το βέλος που την έφερε έχοντας έτσι μια γενική εικόνα του αριθμού των σημαντικών επιδόσεων που μπορεί να έφερε με το συγκεκριμένο βέλος. Τέλος, μια ακόμη σημαντική λειτουργία θεωρήθηκε και η εξαγωγή των επιδόσεων από το κινητό, χρήσιμη για την μελέτη τους και εκτός κινητού αλλά και για αποφυγή προβλημάτων απόδοσης λόγω του τυχών συσσωρευμένου αριθμού εγγραφών που θα πρέπει να υπάρχουν στο κινητό. Εκτενέστερη περιγραφή των κανόνων και των απαιτήσεων που αποκομίσθηκαν από την συνέντευξη γίνεται στο επόμενο κεφάλαιο, όπου εξηγείται επίσης, η αρχιτεκτονική και η γενική φιλοσοφία της εφαρμογής μfita. 25
3. ΣΧΕΔΙ ΑΣΗ ΕΦΑΡΜΟΓΉΣ ΧΕΔΙΑΣΗ Στα προηγούμενα κεφάλαια έγινε αναφορά στην Ιστορία των mobile εφαρμογών και εξετάστηκαν τα συστατικά μέρη του λειτουργικού Android. Στην συνέχεια παρουσιάστηκαν ορισμένες εφαρμογές που εξυπηρετούν τις ανάγκες καταγραφής επιδόσεων αθλητών τοξοβολίας και συγκρίθηκαν με τα χαρακτηριστικά της εφαρμογής που υλοποιήθηκε στα πλαίσια αυτής της εργασίας. Οι επόμενες ενότητες αφορούν τα βήματα που χρειάστηκε να παρθούν για να υλοποιηθεί αυτή η εφαρμογή. Έτσι, πριν φτάσουμε στο τελικό αποτέλεσμα και στην παρουσίασή του, θα μελετηθεί πρώτα η σχεδίαση της εφαρμογής. 3.1. Φιλοσοφία Όπως έχει αναφερθεί, ο σκοπός της εργασίας αυτής είναι η ανάπτυξη μιας εφαρμογής που θα επιτρέπει σε τοξοβόλους να καταγράφουν τις επιδόσεις τους σε ορισμένα αθλήματα. Αυτό σημαίνει πως η εφαρμογή θα πρέπει να λαμβάνει υπόψη τις κινήσεις και την συμπεριφορά ενός τοξοβόλου από την αρχή της προπόνησής του, δηλαδή την στιγμή που παίρνει το τόξο και διαλέγει τα βέλη, μέχρι και την στιγμή που θα μαζέψει για τελευταία φορά τα βέλη του από το στόχο. Για να γίνει πιο κατανοητή η διαδικασία που ακολουθείτε κατά την διάρκεια μιας προπόνησης από έναν αθλητή, παρατίθεται το εξής διάγραμμα. Επιλογή βελών Επιλογή στόχου και απόστασης Ρίψη βολών Αποτίμηση βαθμολογίας και περισυλλογή βελών Τέλος προπόνησης Όπως φαίνεται και στο διάγραμμα, ο αθλητής αρχικά, αφού φορέσει τον κατάλληλο εξοπλισμό του, διαλέγει το τόξο και τα βέλη που θα χρησιμοποιήσει και τα προσθέτει στην φαρέτρα του. Έπειτα, αναλόγως τον τύπο του αγωνίσματος και του στόχου που θα επιλέξει να αγωνιστεί, θα κληθεί να διαλέξει την διαφορά της απόστασης σε μέτρα που θα υπάρχει ανάμεσά του και στον στόχο. Σημειώνεται πως για τις ανάγκες τις εφαρμογής, υποστηρίζονται οι αποστάσεις του 26
αγωνίσματος FITA(WA) αντρών και γυναικών εξωτερικών χώρων, ολυμπιακού τόξου. Στο σημείο αυτό ο αθλητής θα κάνει ρίψη έξι βολών, σύμφωνα με τα πρότυπα του FITA, χρησιμοποιώντας έξι από τα βέλη που πρόσθεσε στην φαρέτρα προηγουμένως. Για να τα τοποθετήσει πάλι πίσω στην φαρέτρα θα πρέπει να μετακινηθεί κοντά στον στόχο, όπου και θα υπολογίσει την βαθμολογία του. Χρησιμοποιώντας το μfita, o αθλητής θα δηλώνει τα βέλη του και την απόστασή του από το στόχο μια φορά πριν αρχίσει τις ρίψεις βελών, ενώ όταν μετακινείται κοντά στον στόχο για την περισυλλογή τους, θα μπορεί να δηλώσει τις βαθμολογίες τους και να κρατήσει σημειώσεις. 3.2. Κανόνες Η εφαρμογή ακολουθεί τα πρότυπα του αγωνίσματος FITA (WA) για ολυμπιακό τόξο και εξωτερικούς χώρους. Ωστόσο η εφαρμογή καλείται να εξυπηρετήσει τις ανάγκες του αθλητή, περισσότερο, κατά την διάρκεια μιας προπόνησής του παρά σε μια επίσημη συμμετοχή του σε έναν αγώνα FITA, κάτι που συνήθως δεν είναι είναι απαραίτητο διότι παραχωρείται από τους διοργανωτές του αγώνα ένα μέσω για την καταγραφή των επιδόσεων του. Το παραπάνω επιτρέπει την επέκταση των ιδιοτήτων μιας εφαρμογής τέτοιας φύσης και τις προσαρμόζει καλύτερα στις ανάγκες του αθλητή και όχι στις ανάγκες που γεννά το ίδιο άθλημα για τον αθλητή. Εικόνα 12: Στόχος Fita Έτσι το προσαρμοσμένο, για την εφαρμογή, πρότυπο FITA (WA) εξωτερικών χώρων περιέχει μια κατηγορία για κάθε φύλο. Η κατηγορία των αντρών επιτρέπει βολές για μια από τις αποστάσεις των 30, 50, 70 και 90 μέτρων από το στόχο, ανά γύρο, ενώ αυτή των γυναικών περιέχει τις αποστάσεις 30, 50, 60 και 70 μέτρα από τον στόχο, ανά γύρο. Παρόλα αυτά, ο χρήστης μπορεί να επιλέξει απόσταση και από τις 2 κατηγορίες ανεξάρτητα από το φύλο του, εφόσον το επιθυμεί. Ο στόχος 27
που χρησιμοποιείται είναι στόχος 10 δακτυλίων με τον κάθε δακτύλιο να δίνει 10/9/8/7/6/5/4/3/2/1 βαθμούς αντίστοιχα, από τον μικρότερο στον μεγαλύτερο. Ενώ οι χρωματισμοί τους είναι λευκό/λευκό/μαύρο/μαύρο/μπλε/μπλε/κόκκινο/κόκκινο/κίτρινο/κίτρινο όπως φαίνεται και στην εικόνα ΤΑΔΕ.Οι βολές των αθλητών χωρίζονται σε end 6 βολών. Αυτό σημαίνει πως ένας αθλητής θα ρίξει έξι βέλη και στην συνέχεια θα πρέπει να τα αφαιρέσει από το στόχο πριν ρίξει τις επόμενες 6 βολές, δηλαδή το επόμενο end. Περιορισμός στον αριθμό των end δεν υπάρχει λόγω της προσαρμογής της εφαρμογής στις ανάγκες μιας προπόνησης. 3.3. Απαιτήσεις Οι απαιτήσεις του συστήματος εξήχθησαν κυρίως από την συνέντευξη που υπάρχει στο προηγούμενο κεφάλαιο. Άλλες πηγές είναι λειτουργίες που υποστηρίζονται από τις παρόμοιες εφαρμογές που αναφέρονται επίσης στο 2 κεφάλαιο, ενώ μερικές απαιτήσεις προέκυψαν κατά την διάρκεια της ανάπτυξης της εφαρμογής και δοκιμής της. Σύμφωνα με όσα έχουν αναφερθεί μέχρι στιγμής, το σύστημα θα πρέπει να είναι σε θέση να εκτελεί τα εξής: 1. Καταχώρηση και αποθήκευση βολών μέσω αφής σε εικονικό στόχο. Το σύστημα θα πρέπει να δέχεται τις συντεταγμένες μιας επιτυχημένης βολής πάνω σε έναν εικονικό στόχο, που θα καθορίζεται από το πρότυπο FITA που περιγράφηκε στους κανόνες τις εφαρμογές και θα εμφανίζεται στην οθόνη. Ο χρήστης θα δηλώνει την θέση της βολής δείχνοντας την θέση του βέλους πάνω στον στόχο. Έπειτα η εφαρμογή θα πρέπει να θυμάται την θέση του. 2. Υποστήριξη αγωνίσματος FITA. To σύστημα θα πρέπει να έχει την δυνατότητα να καταχωρήσει επιδόσεις σύμφωνα με το πρότυπο FITA, έτσι όπως περιγράφηκε στους κανόνες της εφαρμογής. 3. Επιλογή απόστασης. Ο χρήστης θα πρέπει να έχει την δυνατότητα να επιλέξει μια από τις αποστάσεις που περιγράφηκαν στους κανόνες της εφαρμογής. 4. Δημιουργία και αποθήκευση σημειώσεων. Ο χρήστης θα έχει την δυνατότητα να γράψει και να επεξεργαστεί σημειώσεις σε μορφή σημειωματάριου σε μια προπόνηση. Οι σημειώσεις θα πρέπει να παραμένουν αποθηκευμένες και να προβάλλονται κατά αίτηση του χρήστη. 5. Αυτόματη αναγνώριση βαθμολογίας βέλους και εμφάνισή της. Το σύστημα θα πρέπει να αναγνωρίζει αυτόματα την βαθμολογία μιας βολής από την θέση της στον εικονικό στόχο, που περιγράφηκε στην απαίτηση 1, και να την αντιστοιχεί και αποθηκεύει μαζί με την βολή από την οποία προήρθε. Θα πρέπει επίσης να προβάλλεται με τρόπο κατανοητό από τον χρήστη. 6. Αυτόματος υπολογισμός βαθμολογίας. Κατά την διάρκεια μιας προπόνησης θα πρέπει να υπολογίζεται η συνολική βαθμολογία από τις συνολικές επιδόσεις των βολών της. 7. Προβολή επιδόσεων προπόνησης. Ο χρήστης πρέπει να έχει την δυνατότητα να δει τις αποθηκευμένες επιδόσεις των βολών που έφερε σε μια προπόνηση, τόσο πάνω στον στόχο (απαίτηση 1) όσο και σε μια απλή λίστα. 8. Εξαγωγή επιδόσεων. Το σύστημα θα πρέπει να είναι σε θέση να εξάγει τις καταχωρημένες επιδόσεις και να τις μεταφέρει σε αρχείο στην κάρτα μνήμης, που μπορεί να μεταφερθεί και προσπελαστεί δια μέσου ηλεκτρονικού υπολογιστή ή άλλης συσκευής. 9. Προβολή ιστορικού επιδόσεων ανά προπόνηση. Το σύστημα θα πρέπει να εμφανίζει τις αποθηκευμένες επιδόσεις σε μορφή λίστας χωρισμένες ανά προπόνηση. Κάθε προπόνηση 28
θα πρέπει να συνοδεύεται από την συνολική βαθμολογία των επιδόσεών της, την ημερομηνία και ώρα της έναρξής της και τις σημειώσεις που γράφτηκαν κατά την διάρκειά της. 10. Προβολή στατιστικών. Το σύστημα θα πρέπει να έχει την δυνατότητα να υπολογίσει στατιστικά που βασίζονται στις επιδόσεις του χρήστη. 11. Εισαγωγή και αποθήκευση βελών. Ο χρήστης θα μπορεί να εισάγει βέλη. Τα βέλη θα πρέπει να αποθηκεύονται στο σύστημα και θα πρέπει να είναι επεξεργάσιμα. Ο χρήστης θα μπορεί να επιλέγει ποια βέλη θα χρησιμοποιεί. 12. Απόδοση ετικετών στα βέλη. Ο χρήστης θα μπορεί να δίνει σύντομες περιγραφές στα βέλη οι οποίες θα παραμένουν αποθηκευμένες και θα μπορούν να αλλάξουν κατά αίτηση του χρήστη. 13. Δήλωση σημαντικών επιδόσεων βελών. Ο χρήστης θα έχει την δυνατότητα να δηλώσει τον αριθμό σημαντικών επιδόσεων που έφερε ένα βέλος. Ο αριθμός αυτός θα είναι εμφανής και θα αποτελεί κριτήριο επιλογής βελών. 14. Αναίρεση βολής. Ο χρήστης θα έχει την επιλογή να ακυρώσει μια βολή εάν αυτή εισαχθεί με λανθασμένη επίδοση ή θέση πάνω στον στόχο (απαίτηση 1). 3.4. Λειτουργικότητα Σύμφωνα με τις απαιτήσεις που προέκυψαν, ο τελικός χρήστης θα έχει στην διάθεσή του μια δέσμη λειτουργιών που θα διευκολύνει την καταγραφή και διαχείριση των επιδόσεών του. Οι σημαντικότερες από αυτές τις λειτουργίες περιλαμβάνουν: Καταχώρηση Επιδόσεων σε Στόχο Προβολή Στατιστικών Προπονήσεων. Καταχώρηση και Διαχείριση Προπονήσεων. Καταχώρηση και Διαχείριση Βελών. Εξαγωγή Προπονήσεων στην κάρτα μνήμης. Δημιουργία, Προβολή και Επεξεργασία Σημειώσεων. Διαμοιρασμός επίδοσης προπόνησης σε κοινωνικά δίκτυα και άλλα. Το γενικό πλαίσιο των λειτουργιών της εφαρμογής μfita εκφράζεται καλύτερα στην Σχεδίαση 2, που αποτελεί το διάγραμμα περιπτώσεων της εφαρμογής. 29
Σχεδίαση 2: Use Case Diagramm 30
Αξίζει να σημειωθεί πως το διάγραμμα περιλαμβάνει μόνο ένα Αctor και καθόλου διαδικασίες διαχείρισης λογαριασμών. Αυτό συμβαίνει καθώς η εφαρμογή θα είναι προσωπική και θα δέχεται δεδομένα μόνο από τον αθλητή-ιδιοκτήτη του τηλεφώνου στο οποίο εγκαταστάθηκε η εφαρμογή. 3.5. Περιβάλλον εργασίας Για την βέλτιστη προσφορά του συνόλου των λειτουργιών της εφαρμογής στον χρήστη, το περιβάλλον εργασίας σχεδιάστηκε και στήθηκε με βάση τους ευρετικούς κανόνες του Jakob Nielsen. Σύμφωνα με τον Jakob Nielsen η ευρετική αξιολόγηση αποτελεί μια υποκειμενική μέθοδο εξέτασης του συστήματος από ειδικούς ευχρηστίας οι οποίοι δουλεύουν μόνοι τους για να μην επηρεάζονται και να διασφαλίζεται η ανεξαρτησία της γνώμης τους. Στηρίζονται σε μια λίστα από αναγνωρισμένους κανόνες ή αρχές ευχρηστίας: τα ευρετικά κριτήρια (heuristics criteria). Η συγκεκριμένη μέθοδος έχει αποδείξει ότι είναι μια πολύ αποδοτική και αποτελεσματική μέθοδος αξιολόγησης ευχρηστίας, αλλά υψηλού κόστους. Η αξιολόγηση με τη συγκεκριμένη μέθοδο εστιάζεται σε δύο βασικά σημεία: 1. Τη γενική σχεδίαση των οθονών του συστήματος. 2. Τη ροή διαλόγων, μηνυμάτων και ενεργειών που απαιτούνται για να γίνει μια συγκεκριμένη διεργασία. Ο Nielsen πρότεινε δέκα γενικούς κανόνες (heuristics) για την αξιολόγηση διαδραστικών συστημάτων, οι κανόνες αυτοί προέκυψαν από την ανάλυση 249 προβλημάτων ευχρηστίας: 1. Χρήση απλών και φυσικών διαλόγων. 2. Χρήση απλής και κατανοητής γλώσσας με την οποία είναι εξοικειωμένοι οι χρήστες και όχι δυσνόητη ορολογία. 3. Ελαχιστοποίηση του φορτίου μνήμης που απαιτείται από τον χρήστη. Κάθε ενέργεια που πρέπει να κάνει ο χρήστης πρέπει να είναι όσο πιο φανερή γίνεται, χωρίς να χρειάζεται να θυμάται ο χρήστης περίπλοκες εντολές. 4. Διατήρηση συνέπειας και συνέχειας στον τρόπο παρουσίασης των μενού επιλογής, και των άλλων συστατικών των διαλόγων. Συνεπώς η ίδια ενέργεια πρέπει να γίνεται πάντα με τον ίδιο τρόπο σε κάθε σημείο της διεπιφάνειας. 5. Παροχή ανάδρασης: Το σύστημα πρέπει ανα πάσα στιγμή να ενημερώνει τον χρήστη για την πρόοδο εργασιών στα πλαίσια ενός αποδεκτού χρόνου. 6. Ύπαρξη σαφών και εύκολων διεξόδων από κάποια διεργασία που ενδεχομένως έχει καλέσει εσφαλμένα ο χρήστης χωρίς να πρέπει να ακολουθήσει εκτενείς διαλόγους. Τυπικό παράδειγμα είναι οι εντολές undo και redo. 7. Παροχή συντομεύσεων που επιταχύνουν κάποιες διεργασίες για τους πεπειραμένους χρήστες και είναι όσο το δυνατόν "αόρατες" για τον αρχάριο χρήστη. Καλό είναι το σύστημα να παραμετροποιείται σε αυτό το σημείο με βάση τις ανάγκες του χρήστη για τις ενέργειες που θέλει να εκτελεί πιο συχνά. 8. Παροχή σαφών μηνυμάτων λαθών: θα πρέπει να παρέχονται σε απλή γλώσσα, να εστιάζουν στο πρόβλημα και να προτείνουν λύση εξόδου. 9. Να εμποδίζονται κατά το δυνατόν τα λάθη και η κακή χρήση του συστήματος. 31
10. Παροχή βοήθειας και τεκμηρίωσης. Με γνώμονα τους παραπάνω 10 κανόνες οι οθόνες διεπαφής του χρήστη με την εφαρμογή σχεδιάστηκαν όπως απεικονίζονται στην συνέχεια. Σχεδίαση 3: Οθόνες εφαρμογής 1 32
Σχεδίαση 4: Οθόνες εφαρμογής 2 33
Σχεδίαση 5: Οθόνες εφαρμογής 3 34
Σχεδίαση 6: Οθόνες εφαρμογής 5 35
Σχεδίαση 7: Οθόνες εφαρμογής 4 36
3.6. Δεδομένα Κατά τις απαιτήσεις της εφαρμογής, το σύστημα θα πρέπει να αποθηκεύει δεδομένα και να τα διατηρεί καθ' όλη την διάρκεια της λειτουργίας του και όχι μόνο. Για αυτό το σκοπό θα δημιουργηθεί μια βάση δεδομένων χρησιμοποιώντας της βιβλιοθήκες της SQLite που είναι ήδη ενσωματωμένες στο Android SDK. Πριν γίνει αναφορά στην σχεδίαση της βάσης, είναι συνετό να εξετάσουμε τα είδη των δεδομένων που θα χρειαστεί να αποθηκεύσουμε, τα οποία έχουν ήδη αναφερθεί στις απαιτήσεις του συστήματος. Τα δεδομένα που θα αποθηκεύει ο χρήστης περιλαμβάνουν: Όσων αφορά τις βολές Τις συντεταγμένες μιας βολής πάνω στον στόχο. Την βαθμολογία μιας βολής. Το end της βολής Την προπόνηση στην οποία ανήκει Για τις προπονήσεις: Την ημερομηνία και ώρα της έναρξής της Τον τύπο του αγωνίσματος Τον συνολικό αριθμό end Σημειώσεις που γράφτηκαν κατά την διάρκειά της Για τα βέλη Μια ετικέτα Το σύνολο των σημαντικών επιδόσεων που έφερε Το αν βρίσκεται μέσα στην φαρέτρα ή όχι Για τους τύπους των αγωνισμάτων θα προϋπάρχει ένας πίνακας που θα περιέχει την απόσταση από τον στόχο. Άρα συμπεραίνουμε πως θα πρέπει να υπάρχουν 4 πίνακες. Έχοντας μελετήσει τα δεδομένα που θα αποθηκεύονται κατασκευάζουμε το διάγραμμα Οντοτήτων-Συσχετίσεων, που περιγράφει συνοπτικά την δομή της βάσης. 37
Σχεδίαση 8: Μοντέλο Οντοτήτων-Συσχετίσεων Παρατηρούμε πως ο πίνακας Αγωνίσματα συσχετίζεται με τον Προπονήσεις και αυτός με τον πίνακα Βολές. Ο πίνακας Βέλη δεν έχει συσχετίσεις. Οι τύποι των πεδίων των πινάκων έχουν ως εξής: Aγωνίσματα ID Απόσταση από στόχο Integer auto increment PRIMARY_KEY Ιnteger Πίνακας 3: Αγωνίσματα Bέλη ID Όνομα Στην Φαρέτρα Σημαντικές Επιδόσεις Integer auto increment PRIMARY_KEY Text Text Integer Πίνακας 4: Βέλη Προπονήσεις ID Ημερομηνία Id Aγωνίσματος Σημειώσεις Σύνολο end Integer auto increment PRIMARY_KEY Date Integer FOREIGN_KEY Text Integer Πίνακας 5: Προπονήσεις 38
Βολές ID Βαθμολογία Νούμερο end ID Προπόνησης Αριθμός Βολής Θέση Χ Θέση Υ Integer auto increment PRIMARY_KEY Integer Integer Integer FOREIGN_KEY Integer Real Real Πίνακας 6: Βολές Σημειώνεται πως το πεδίο Στην Φαρέτρα του πίνακα Βέλη έχει τύπο Τext αντί για Boolean λόγω του ότι ο τελευταίος δεν υποστηρίζεται από την SQLite. Στο επόμενο κεφάλαιο, εξετάζεται η διαδικασία υλοποίησης της βάσης δεδομένων και της εφαρμογής μέσω κώδικα. 39
4. YΛΟΠΟΙ ΗΣΗ ΛΟΠΟΙΗΣΗ Το κεφάλαιο αυτό περιλαμβάνει τα στάδια υλοποίησης της εφαρμογής. Αυτό σημαίνει πως ξεκινάει την αναφορά του από την εγκατάσταση του απαραίτητου για την υλοποίηση λογισμικού και καταλήγει στην υλοποίηση της ίδιας της εφαρμογής μέσω κώδικα. 4.1. Εγκατάσταση λογισμικού Για την ανάπτυξη της εφαρμογής χρειάστηκε να γίνει εγκατάσταση του Android SDK μέσω της πλατφόρμας Eclipse. Για την δοκιμή της Βάσης Δεδομένων εγκαταστάθηκε το εργαλείο SQLite Database Browser, ενώ για την χειραγώγηση και δημιουργία των γραφικών που τοποθετήθηκαν στην εφαρμογή, χρησιμοποιήθηκε το GIMP. Ακολουθεί η διαδικασία εγκατάστασής τους. 4.1.1. Εγκατάσταση Eclipse & Android SDK Πριν εγκατασταθεί η Eclipse, θα πρέπει να κατεβάσουμε το Java Development Kit. Οπότε κατευθυνόμαστε στο site της Oracle (www.oracle.com) και από την καρτέλα Downloads επιλέγουμε την έκδοση που μας ταιριάζει. Στην περίπτωσή μας επιλέγουμε την έκδοση Windows x86. Εικόνα 13: Εγκατάσταση JDK Αφού ολοκληρωθεί η λήψη, κάνουμε εγκατάσταση χρησιμοποιώντας τον installation wizard. 40
Εικόνα 14: Εγκατάσταση Eclipse Αμέσως μετά επισκεπτόμαστε την ιστοσελίδα της Eclipse (www.eclipse.org) και επιλέγουμε από την καρτέλα Downloads την έκδοση Classic για Windows 32bit και την κατεβάζουμε. Όταν ολοκληρωθεί η λήψη και η εγκατάστασή της επιλέγουμε έναν φάκελο για το workspace όπου θα αποθηκεύονται τα project. Εικόνα 15: Επιλογή workspace 41
Στην συνέχεια θα χρειαστεί να κατεβάσουμε το Αndroid plug in. Μέσα στο περιβάλλον της Eclipse, πλοηγούμαστε στο μενού Help/Install New Software. Στο πλαίσιο Work with πατάμε add και πληκτρολογούμε την διεύθυνση του ADT plug in (https://dl-ssl.google.com/android/eclipse) και πατάμε ΟΚ (Εικόνα 16). Εικόνα 16: Εγκατάσταση Android SDK 42
Από τα αποτελέσματα που θα επιστραφούν κάνουμε check στο Developer Tools και πατάμε Next. Εικόνα 17: Εγκατάσταση Android SDK 43
Εάν όλα πάνε καλά, θα εμφανιστούν τα στοιχεία που πρόκειται εγκατασταθούν. Εμείς πατάμε απλά Next. Εικόνα 18: Εγκατάσταση Android SDK Πατώντας πάλι Next θα μεταφερθούμε στο επόμενο παράθυρο (Εικόνα 19) όπου θα κληθούμε να αποδεχτούμε τις άδειες χρήσης των στοιχείων που θα κατεβάσουμε. Τις αποδεχόμαστε όλες και πατάμε Finish. 44
Εικόνα 19: Εγκατάσταση Android SDK Όταν ολοκληρωθεί η λήψη του ADT plugin μεταφερόμαστε στο Android SDK Manager (μενού Window\Android SDK Manager). Από εδώ επιλέγουμε τα επίπεδα του Android API με τα οποία θα δουλέψουμε και πατάμε Ιnstall Packages (Εικόνα 20). Εικόνα 20: Επιλογή πακέτων API 45
4.1.2. Δημιουργία Εικονικής Συσκευής Με την βοήθεια μιας εικονικής συσκευής μπορεί να γίνει το debugging της εφαρμογής που αναπτύσσουμε χωρίς την ύπαρξη φυσικής συσκευής. Για την δημιουργία μιας εικονικής συσκευής πλοηγούμαστε στο Android Virtual Device Manager στο μενού Window της Εclipse. Στο παράθυρο που θα εμφανιστεί πατάμε New. Στην συνέχεια επιλέγουμε τα χαρακτηριστικά της εικονικής συσκευής. Εικόνα 21: Δημιουργία Εικονικής Συσκευής Αφού τελειώσουμε με την παραμετροποίηση της εικονικής συσκευής πατάμε ΟΚ. Η συσκευή θα εμφανιστεί στην λίστα. Την επιλέγουμε και πατάμε Start για να ανοίξει. 46
Μετά από λίγη ώρα, όταν τελειώσει η φόρτωση της, η συσκευή (Εικόνα 22) θα τρέχει το λειτουργικό Android που επιλέξαμε. Εικόνα 22: Εικονική Συσκευή Android 4.1.3. Εγκατάσταση SQLite Database Browser Το SQLite Database Browser μας επιτρέπει να επεξεργαστούμε και να κάνουμε απευθείας ερωτήματα σε μια βάση δεδομένων SQLite. Φιλοξενείται στις σελίδες του SourceForge οπότε για να το κατεβάσουμε αρκεί να επισκεφτούμε την ιστοσελίδα http://sourceforge.net/projects/sqlitebrowser/ και να πατήσουμε Download. Όταν ολοκληρωθεί η λήψη απλά κάνουμε extract τα περιεχόμενα του αρχείο.zip που μόλις κατεβάσαμε. Εικόνα 23: Εγκατάσταση SQLite Database Browser 47
4.1.4. Εγκατάσταση GIMP Το GIMP είναι ένα πρόγραμμα επεξεργασίας εικόνων και γραφικών, όπως το γνωστό Photoshop, με την διαφορά πως αυτό είναι ανοιχτού κώδικα. Για να το αποκτήσουμε επισκεπτόμαστε την σελίδα του στο Ίντερνετ (http://www.gimp.org) και το κατεβάζουμε από την καρτέλα Downloads. 4.2. Περιγραφή Κώδικα Στο κομμάτι αυτό περιλαμβάνεται και περιγράφεται η υλοποίηση των λειτουργιών της εφαρμογής μfita καθώς και το στήσιμο της Βάσης Δεδομένων με την οποία επικοινωνεί. Μερικές από τις βασικότερες λειτουργίες της εφαρμογής που θα περιγραφούν είναι: Προβολή Στατιστικών του Ιστορικού των προπονήσεων Εξαγωγή του ιστορικού στην κάρτα μνήμης Δημιουργία, προβολή, επεξεργασία και αποθήκευση σημειώσεων Καταχώρηση, προβολή και επεξεργασία βελών Προβολή, επεξεργασία και διαχείριση προπονήσεων Καταχώρηση επιδόσεων Επιπρόσθετα, θα παρουσιαστεί o τρόπος υλοποίησης αξιοσημείωτων διεπαφών της εφαρμογής. Το επίπεδο ΑPI των εντολών που χρησιμοποιήθηκε είναι το βασικό Android 1.5. 48
4.2.1. Δημιουργία της Βάσης Δεδομένων Όλες οι λειτουργίες της Βάσης Δεδομένων περιλαμβάνονται σε μια κλάση-βοηθό, συγκεκριμένα την SQLiteAdapter. H διάφορες διαδικασίες τις εφαρμογής καλούν τις μεθόδους αυτής της κλάσης όταν απαιτείται να υπάρξει ροή δεδομένων ανάμεσα στη Βάση και στην εφαρμογή. Όλες οι πληροφορίες και τα ονόματα που χρησιμοποιούνται στην βάση καταχωρούνται σε στατικά String. Όπως φαίνεται στο Απόσπασμα 1. Απόσπασμα 1 public class SQLiteAdapter extends Activity { //Πληροφορίες Βάσης public static final String MYDATABASE_NAME = "μfitadb"; public static final int MYDATABASE_VERSION = 1; //Ονομασίες Πίνακα βελών public static final String TABLE_ARROWS = "ARROWS"; public static final String KEY_ARROWS_ID = "_id"; public static final String KEY_ARROWS_NOTE = "note"; public static final String KEY_ARROWS_QUIVER = "quiver"; public static final String KEY_ARROWS_XCOUNTER = "xcounter"; public static final int KEY_ARROWS_XCOUNTER_DEFAULT = 0; public static final String KEY_ARROWS_QUIVER_DEFAULT = " "; //Ονομασίες Πίνακα αγωνισμάτων public static final String TABLE_ENDS = "ENDS"; public static final String KEY_ENDS_ID = "_id"; public static final String KEY_ENDS_SHOTS = "shots"; public static final String KEY_ENDS_DISTANCE = "distance"; public static final String KEY_ENDS_TARGET = "target"; //Ονομασίες Πίνακα προπονήσεων public static final String TABLE_SESSIONS = "SESSIONS"; public static final String KEY_SESSIONS_ID = "_id"; public static final String KEY_SESSIONS_DATE = "date"; public static final String KEY_SESSIONS_ENDID = "end_id"; public static final String KEY_SESSIONS_NOTES = "notes"; public static final String KEY_SESSIONS_ENDS = "ends"; public static final String SUM_SESSION_SCORE_AS = "summa"; //Ονομασίες Πίνακα βολών public static final String TABLE_SHOTS = "SHOTS"; public static final String KEY_SHOTS_ID = "_id"; public static final String KEY_SHOTS_POINTS = "points"; public static final String KEY_SHOTS_ENDNO = "end_no"; public static final String KEY_SHOTS_SESSIONID = "session_id"; public static final String KEY_SHOTS_SHOTNO = "shot_no"; public static final String KEY_SHOTS_POSX = "possition_x"; public static final String KEY_SHOTS_POSY = "possition_y"; Σε στατικά String, επίσης, καταχωρούνται και οι περιγραφές των εντολών δημιουργίας των πινάκων. Ακολουθεί το κυρίως μέρος της κλάσης (Απόσπασμα 2 και 3). 49
Απόσπασμα 2 //create table ARROWS (ID integer primary key, note text, quiver text, xcounter integer); private static final String SCRIPT_CREATE_TABLE_ARROWS = "create table " + TABLE_ARROWS + " (" + KEY_ARROWS_ID + " integer primary key autoincrement, " + KEY_ARROWS_NOTE + " text, " + KEY_ARROWS_QUIVER + " text DEFAULT '" + KEY_ARROWS_XCOUNTER_DEFAULT+"', " + KEY_ARROWS_XCOUNTER + " integer DEFAULT 0);"; //create table ENDS ( ID integer primary key, distance integer not null); private static final String SCRIPT_CREATE_TABLE_ENDS= "create table " + TABLE_ENDS + " (" + KEY_ENDS_ID + " integer primary key autoincrement, " + KEY_ENDS_DISTANCE + " integer not null " + ");" ; //create table SESSIONS (ID integer primary key, name text, datetime date not null, end_id int not null, notes text,noofends integer not null) private static final String SCRIPT_CREATE_TABLE_SESSIONS= "create table " + TABLE_SESSIONS + " (" + KEY_SESSIONS_ID + " integer primary key autoincrement, " + KEY_SESSIONS_DATE + " date, " + KEY_SESSIONS_ENDID + " integer, " + KEY_SESSIONS_NOTES + " text, " + KEY_SESSIONS_ENDS + " integer);"; //create table SHOTS (ID integer primary key, points integer not null, endno integer not null, sessionid integer not null, shotno integer not null, possitionx real not null, possitiony rean not null) private static final String SCRIPT_CREATE_TABLE_SHOTS = "create table " + TABLE_SHOTS + " (" + KEY_SHOTS_ID + " integer primary key autoincrement, " + KEY_SHOTS_POINTS + " integer not null, " + KEY_SHOTS_ENDNO + " integer not null, " + KEY_SHOTS_SESSIONID + " integer not null, " + KEY_SHOTS_SHOTNO + " integer not null, " + KEY_SHOTS_POSX + " float not null, " + KEY_SHOTS_POSY + " float not null);"; 50
Απόσπασμα 3 private SQLiteHelper sqlitehelper; private SQLiteDatabase sqlitedatabase; private Context context; //Δημιουργός Κλάσης public SQLiteAdapter(Context c){ context = c; //Άνοιγμα Βάσης για Διάβασμα public SQLiteAdapter opentoread() throws android.database.sqlexception { sqlitehelper = new SQLiteHelper(context, MYDATABASE_NAME, null, MYDATABASE_VERSION); sqlitedatabase = sqlitehelper.getreadabledatabase(); return this; //Άνοιγμα Βάσης για Γράψιμο public SQLiteAdapter opentowrite() throws android.database.sqlexception { sqlitehelper = new SQLiteHelper(context, MYDATABASE_NAME, null, MYDATABASE_VERSION); sqlitedatabase = sqlitehelper.getwritabledatabase(); return this; //Κλείσιμο Βάσης public void close(){ sqlitehelper.close(); //Μεταφορά Βάσης στην κάρτα μνήμης public void exportdb(){ try { File sd = Environment.getExternalStorageDirectory(); if (sd.canwrite()) { String currentdbpath = "data/data/android.archer.test/databases/μfitadb"; String backupdbpath = sd + "/filename.db"; File currentdb = new File(currentDBPath); File backupdb = new File(backupDBPath); if (currentdb.exists()) { FileChannel src = new FileInputStream(currentDB).getChannel(); FileChannel dst = new FileOutputStream(backupDB).getChannel(); dst.transferfrom(src, 0, src.size()); src.close(); dst.close(); catch (Exception e) { e.printstacktrace(); Σημειώνεται πως η μέθοδος exportdb() είναι υπεύθυνη για την αντιγραφή της Βάσης στην κάρτα 51
μνήμης και παράδειγμα μεθόδου που καλείται από τις υπόλοιπες Διαδικασίες τις εφαρμογής κατά την διάρκειά της εκτέλεσής της. Κατά την δημιουργία της Βάσης καλείται η υποκλάση SQLiteHelper που βρίσκεται μέσα στο ίδιο αρχείο.java με την SQLiteAdapter. Απόσπασμα 4 public class SQLiteHelper extends SQLiteOpenHelper { public SQLiteHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); //Δημιουργία Πινάκων @Override public void oncreate(sqlitedatabase db) { db.execsql(script_create_table_arrows); db.execsql(script_create_table_ends); db.execsql(script_create_table_sessions); db.execsql(script_create_table_shots); //Σβήσιμο παλιών Πινάκων σε περίπτωση τροποποίησης της Βάσης @Override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { db.execsql("drop TABLE IF EXISTS " + TABLE_ARROWS); db.execsql("drop TABLE IF EXISTS " + TABLE_ENDS); db.execsql("drop TABLE IF EXISTS " + TABLE_SESSIONS); db.execsql("drop TABLE IF EXISTS " + TABLE_SHOTS); oncreate(db); Στην μέθοδο oncreate δημιουργούνται οι πίνακες που περιγράψαμε στα String προηγουμένως, και στην onupgrade καθορίζεται η συμπεριφορά της κατά μια πιθανή αναβάθμιση. Χάρη στην αποθήκευση ονομάτων και εντολών σε String, μια πιθανή τροποποίηση στην Βάση γίνεται πολύ πιο εύκολα και γρήγορα. Σημειώνεται πως η έκδοση της SQLite στο επίπεδο API 8, που χρησιμοποιείται στην περίπτωσή μας, είναι η 3.5.9 και δεν υποστηρίζει ξένα κλειδιά. Έτσι η συμπεριφορά των σχέσεων μεταξύ των Πινάκων υλοποιείται προγραμματιστικά. 4.2.2. Υπολογισμός και προβολή στατιστικών Ιστορικού Η προβολή και ο υπολογισμός των στατιστικών των επιδόσεων του χρήστη παίρνει μέρος στην κλάση MainActivity.java. 52
public void onclick(view v) { Απόσπασμα 5 final Intent I; switch (v.getid()) { private void makestatsdialog(){ //Έλεγχος για το αν πατήθηκε το κουμπί Στατιστικά //Δημιουργία Διαλόγου case R.id.txtView_Stats: final Dialog StatsDialog = new Dialog(this); //Αν δεν υπάρχουν καταχωρήσεις εμφάνισε κατάλληλο μήνυμα StatsDialog.requestWindowFeature(Window.FEATURE_LEFT_ICON); if (dbadapter.countsessions(0)==0) Toast.makeText(this, "Δεν StatsDialog.setContentView(R.layout.dialog_stats); υπάρχουν καταχωρημένες προπονήσεις!", StatsDialog.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, Toast.LENGTH_SHORT).show(); R.drawable.dstats_line_chart); else makestatsdialog(); //Υπολογίζει και προβάλει τα //Δήλωση των widget //στατιστικά του Διαλόγου break; final TextView Message = (TextView)StatsDialog. findviewbyid(r.id.text_dialog_stats_message); final Button stats = (Button)StatsDialog.findViewById(R.id.butt_stats); //Γενικά στατιστικά stats.setonclicklistener(new OnClickListener() { public void onclick(view v) { final int distance = 0; final double sum = Double.parseDouble(new DecimalFormat("#,##"). format((((double)dbadapter.count10s(distance))/ (dbadapter.countshots(distance)))*100)); //Υπολογισμός και προβολή χρησιμοποιώντας ερωτήματα προς τη ΒΔ StatsDialog.setTitle("Στατιστικά: Γενικά"); Message.setText(String.valueOf(dbAdapter.countSHOTS(distance))+ " ρίψεις σε "+ String.valueOf(dbAdapter.countSESSIONS(distance))+ " προπονήσεις. "+ String.valueOf(dbAdapter.count10s(distance)) +" στο κέντρο. Ποσοστό ευστοχίας: "+ String.valueOf(sum)+ "%. Συχνότερος βαθμός: "+String.valueOf(dbAdapter.SumScore(distance)/ dbadapter.countshots(distance))+"\n"); ); //Προβολή Διαλόγου StatsDialog.show(); Αφού γίνει έλεγχος για το αν υπάρχουν καταχωρήσεις, η συνάρτηση makestatsdialog αναλαμβάνει τον υπολογισμό και την προβολή τους: Εδώ υπολογίζεται η γενική κατηγορία των Στατιστικών. Οι άλλες κατηγορίες υπολογίζονται με παρόμοιο τρόπο (Main.Activity.java). Τα ερωτήματα που χρησιμοποιήθηκαν βρίσκονται μέσα στην κλάση-βοηθό SQLiteAdapter και συγκεκριμένα στις συναρτήσεις countshots(int), countsessions(int), count10s(int), SumSessions(int). Μερικές από αυτές περιγράφονται στο Απόσπασμα 6. 53
Απόσπασμα 6 //Μέτρηση Ρίψεων συγκεκριμένης απόστασης public int countshots(int distance){ Cursor cursor; //Αν η απόσταση είναι 0 περιλαμβάνει ολόκληρο τον πίνακα if (distance==0) cursor= sqlitedatabase.rawquery ("select count(*) from " + TABLE_SHOTS, null); //Αλλιώς περιλαμβάνει μόνο την επιλεγμένη απόσταση else cursor = sqlitedatabase.rawquery ("SELECT count(*) FROM "+TABLE_SHOTS+", "+TABLE_SESSIONS+", "+TABLE_ENDS + " where " + TABLE_SHOTS+"."+ KEY_SHOTS_SESSIONID+"="+TABLE_SESSIONS+"."+ KEY_SESSIONS_ID +" and " + TABLE_SESSIONS+"."+ KEY_SESSIONS_ENDID+ "="+TABLE_ENDS+ "."+KEY_ENDS_ID + " and " +KEY_ENDS_DISTANCE + " = " + distance, null); cursor.movetofirst(); return cursor.getint(0); //Επιστρέφει το σύνολο των ρίψεων //Μέτρηση προπονήσεων συγκεκριμένης απόστασης public int countsessions(int distance){ Cursor cursor; //Αν η απόσταση είναι 0 περιλαμβάνει ολόκληρο τον πίνακα if (distance==0) cursor = sqlitedatabase.rawquery ("select count(*) from " + TABLE_SESSIONS, null); //Αλλιώς περιλαμβάνει μόνο την επιλεγμένη απόσταση else cursor = sqlitedatabase.rawquery ("SELECT count(*) FROM "+TABLE_SESSIONS+", "+TABLE_ENDS + " where " + TABLE_SESSIONS+"."+ KEY_SESSIONS_ENDID+"="+TABLE_ENDS+"."+ KEY_ENDS_ID + " and " +KEY_ENDS_DISTANCE + " = " + distance, null); cursor.movetofirst(); return cursor.getint(0); //Επιστρέφει το σύνολο των προπονήσεων //Μετρά τις βολές που φέραν 10 public int count10s(int distance){ Cursor cursor; //Αν η απόσταση είναι 0 περιλαμβάνει ολόκληρο τον πίνακα if (distance==0) cursor = sqlitedatabase.rawquery ("select count(*) from " + TABLE_SHOTS + " where " + KEY_SHOTS_POINTS + " = '10'", null); //Αλλιώς περιλαμβάνει μόνο την επιλεγμένη απόσταση else cursor = sqlitedatabase.rawquery ("SELECT count(*) FROM "+TABLE_SHOTS+", "+ TABLE_SESSIONS+", "+TABLE_ENDS + " where " + TABLE_SHOTS+"."+ KEY_SHOTS_SESSIONID+"="+TABLE_SESSIONS+"."+ KEY_SESSIONS_ID + " and " + TABLE_SESSIONS+"."+KEY_SESSIONS_ENDID +"="+ TABLE_ENDS+ "."+KEY_ENDS_ID + " and " +KEY_ENDS_DISTANCE + " = " + distance + " and " + KEY_SHOTS_POINTS + " = '10'", null); cursor.movetofirst(); return cursor.getint(0);//επιστροφή μετρητή 54
4.2.3. Διαχείριση Βελών Η διαχείριση των βελών γίνεται στην κλάση ArrowsActivity.java. Στο Απόσπασμα 7 γίνεται η προβολή τους στον χρήστη μέσω του listview ArrowsList. Απόσπασμα 7 //Δήλωση λίστας προβολής Βελών ArrowsList = (ListView)findViewById(R.id.arrowslist); //Αποστολή ερωτήματος στην βάση cursor = dbadapter.queue_arrows(sort_flag); //Επιστροφή Βελών από την ΒΔ και κατάταξή τους στην λίστα String[] from = new String[]{SQLiteAdapter.KEY_ARROWS_NOTE, SQLiteAdapter.KEY_ARROWS_XCOUNTER, SQLiteAdapter.KEY_ARROWS_QUIVER ; int[] to = new int[]{r.id.text1, R.id.text2, R.id.text3 ; cursoradapter=new SimpleCursorAdapter(this, R.layout.arrows_row, cursor, from, to); //Εμφάνιση Βελών στην λίστα ArrowsList.setAdapter(cursorAdapter); Για την καταχώρηση ενός νέου βέλους χρησιμοποιείται ένα πλαίσιο κειμένου που δέχεται το όνομά του από τον χρήστη και ένα κουμπί για την τελική εισαγωγή και αποθήκευσή του στην βάση δεδομένων. Απόσπασμα 8 //Δήλωση πλαισίου εισαγωγής ονόματος βέλους EditText inputarrowname = (EditText)findViewById(R.id.newArrowEt); //Δήλωση πλήκτρου καταχώρησης βέλους buttonaddarrow = (Button)findViewById(R.id.add); Button.OnClickListener buttonaddonclicklistener = new Button.OnClickListener(){ public void onclick(view arg0) { //Ανάκτηση κειμένου από πλαίσιο final String arrowname = inputarrowname.gettext().tostring(); //Έλεγχος για κενό Όνομα και ειδοποίηση χρήστη if (inputarrowname.gettext().tostring().trim().length() == 0) Toast.makeText(ArrowsActivity.this, "Δώστε ένα όνομα στο βέλος πριν κάνετε εισαγωγή!", Toast.LENGTH_SHORT).show(); //Καταχώρηση στην βάση και καθαρισμός πλαισίου else{ dbadapter.insertarrow(arrowname); inputarrowname.settext(""); updatelist(); ; Για την διαγραφή ή επεξεργασία ενός βέλους πρέπει να γίνει Long-click σε ένα στοιχείο της ArrowsList. Έτσι εμφανίζεται o custom διάλογος arrowsdialog που επιτρέπει την περαιτέρω επεξεργασία ενός βέλους μέσω των widget που εμφανίζει. 55
Απόσπασμα 9 private ListView.OnItemLongClickListener listcontenitemlongclicklistener = new OnItemLongClickListener(){ public boolean onitemlongclick(adapterview<?> parent, View view,int position, long id) { //Ανάκτηση ID Βέλους και στοιχείων του από την ΒΔ Cursor cursor = (Cursor) parent.getitematposition(position); final int item_id = cursor.getint (cursor.getcolumnindex(sqliteadapter.key_arrows_id)); final String item_notes = cursor.getstring (cursor.getcolumnindex(sqliteadapter.key_arrows_note)); final int item_xcounter = cursor.getint (cursor.getcolumnindex(sqliteadapter.key_arrows_xcounter)); //Δημιουργία Διαλόγου και ρύθμιση παραμέτρων του final Dialog arrowsdialog = new Dialog(ArrowsActivity.this); arrowsdialog.requestwindowfeature(window.feature_left_icon); arrowsdialog.setcontentview(r.layout.edit_arrow_dialog); arrowsdialog.settitle("eπεξεργασία"); arrowsdialog.setfeaturedrawableresource (Window.FEATURE_LEFT_ICON, R.drawable.dedit); //Κείμενο προβολής Ονόματος final TextView Title = (TextView)arrowsDialog.findViewById(R.id.dialog_editArrow_title); //Πλαίσιο επεξεργασίας ονόματος final EditText edit = (EditText)arrowsDialog.findViewById(R.id.dialog_editArrow_editText); //Κουμπί Διαγραφής final Button Delete = (Button) arrowsdialog.findviewbyid(r.id.dialog_editarrow_delete); //Κουμπί Αποθήκευσης final Button Update = (Button) arrowsdialog.findviewbyid(r.id.dialog_editarrow_update); //Κουμπί Επαναφοράς μετρητή επιδόσεων final Button Reset = (Button) arrowsdialog.findviewbyid(r.id.dialog_editarrow_reset); //Ανάθεση Ονόματος Βέλους σε τίτλο και πλαίσιο επεξεργασίας Title.setText(item_notes+" ("+String.valueOf(item_xcounter) +" σημαντικές επιδόσεις)"); edit.settext(string.valueof(item_notes)); if (item_id<6) Delete.setVisibility(View.INVISIBLE); //Διαγραφή Βέλους και κλείσιμο διαλόγου 4.2.4. Διαχείριση Σημειώσεων Η διαχείριση των σημειώσεων του χρήστη γίνεται στις κλάσεις SessionsActivity.java και TargetActivity.java με παρόμοιο τρόπο και στις δύο περιπτώσεις. Αφού καθοριστεί το Id της προπόνησης, ανακτώνται οι σημειώσεις της και τα χαρακτηριστικά της και προβάλλονται σε edittext και TextView μέσα σε έναν διάλογο. Για την προσθήκη ή διαγραφή σημειώσεων, ο χρήστης πληκτρολογεί/διαγράφει κείμενο στο ίδιο πλαίσιο και αποθηκεύεται μαζί με το προηγούμενο πατώντας το κουμπί της αποθήκευσης. 56
Απόσπασμα 10 //Αποστολή ερωτήματος στην βάση και επιστροφή Σημείωσης cursor = mysqliteadapter.queuesessions_byid(getintent().getlongextra("sessionid",-1)); if (cursor!=null){ String Notes = cursor.getstring(cursor.getcolumnindexorthrow(sqliteadapter.key_sessions_notes)); cursor.movetofirst(); //Πλάσιο Σημείωσης final EditText Notepad = new EditText(TargetActivity.this); //Δημιουργία Διαλόγου και ρύθμιση παραμέτρων του AlertDialog.Builder NotepadDialog = new AlertDialog.Builder(TargetActivity.this); NotepadDialog.setTitle("Πρόχειρο"); NotepadDialog.setIcon(R.drawable.dnotepad); //Ρύθμιση παραμέτρων πλαισίου Σημείωσης και προβολή της σε αυτό LayoutParams NotepadLayoutParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); Notepad.setLayoutParams(NotepadLayoutParams); Notepad.setText(Notes); //Δημιοργία Layout Διαλόγου και προσθήκη πλαισίου σημειώσεων σε αυτό LinearLayout layout = new LinearLayout(TargetActivity.this); layout.setorientation(linearlayout.vertical); layout.addview(notepad); NotepadDialog.setView(layout); //Ρύθμιση πλήκτρου Αποθήκευση Διαλόγου NotepadDialog.setNeutralButton("Αποθήκευση", new DialogInterface.OnClickListener() { //Ενημέρωση βάσης με νέα τιμή σημείωσης public void onclick(dialoginterface arg0, int arg1) { final String value1 = Notepad.getText().toString(); mysqliteadapter.updatesession_byid(getintent().getlongextra("sessionid", -1), value1, 0); updatelist(); ); //Ρύθμιση πλήκτρου Άκυρο Διαλόγου NotepadDialog.setNegativeButton("Άκυρο", new DialogInterface.OnClickListener() { public void onclick(dialoginterface arg0, int arg1) { ); //Εμφάνιση Διαλόγου στην οθόνη NotepadDialog.show(); 57
4.2.5. Μετακίνηση Ιστορικού στην κάρτα μνήμης Η λειτουργία αυτή περιλαμβάνεται στην κλάση MainActivity.java και αφού ο χρήστης πατήσει το κουμπί Menu της συσκευής του. Στο σημείο αυτό θα εξεταστεί πρώτα η δημιουργία ενός menu μέσω της γλώσσας xml. Η περιγραφή του μενού για την μετακίνηση του ιστορικού στην κάρτα μνήμης γίνεται στο αρχείο menu_main.xml και βρίσκεται στον φάκελο res\menu του project. Απόσπασμα 11 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:title="mετακίνηση Ιστορικού" android:icon="@drawable/copy"> <menu> <item android:id="@+id/menu_copydb" android:title="στην κάρτα μνήμης" android:icon="@drawable/copy"/> </menu> </item><item android:id="@+id/menu_main" android:icon="@drawable/info" android:title="σχετικά" /> </menu> Παρατηρείται πως η ιδιότητα android:icon περιγράφει το εικονίδιο ενός αντικειμένου, ενώ η android:title το κείμενο που θα εμφανίζεται μαζί του. Απόσπασμα 12 //Γέμισμα μενού από αρχείο xml @Override public boolean oncreateoptionsmenu(menu menu){ MenuInflater menuinflater = getmenuinflater(); menuinflater.inflate(r.menu.menu_main, menu); return true; //Συμπεριφορά σε κλικ αντικειμένου μενού @Override public boolean onoptionsitemselected(menuitem item){ switch (item.getitemid()) { //Μετακίνηση Ιστορικού case R.id.menu_copyDB:{ try {new ExportDatabaseFileTask().execute(""); catch(exception ex) {Log.e ("Error in MainActivity",ex.toString());; break; return super.onoptionsitemselected(item); Έτσι όταν ο χρήστης πατήσει το αντικείμενο με τίτλο Μετακίνηση Ιστορικού θα αρχίσει η διαδικασία μετακίνησής του. 58
Απόσπασμα 13 private class ExportDatabaseFileTask extends AsyncTask<String, Void, Boolean> private final ProgressDialog dialog = new ProgressDialog(ctx); //Έναρξη UI Thread protected void onpreexecute() { this.dialog.setmessage("το ιστορικό μετακινείται..."); this.dialog.show(); // Καθορισμός προορισμού και προέλευσης (στο thread) protected Boolean doinbackground(final String... args) { File dbfile = new File(Environment.getDataDirectory() + "/data/android.archer.test/databases/μfitadb"); File exportdir = new File(Environment.getExternalStorageDirectory(), ""); if (!exportdir.exists()) { exportdir.mkdirs(); File file = new File(exportDir, dbfile.getname()); try { file.createnewfile(); this.copyfile(dbfile, file); return true; catch (IOException e) { Log.e("mypck", e.getmessage(), e); return false; //Μηνύματα UI Thread στο τελος του thread protected void onpostexecute(final Boolean success) { if (this.dialog.isshowing()) { this.dialog.dismiss(); if (success) { Toast.makeText(ctx, "Το Ιστορικό μετακινήθηκε με επιτυχία.", Toast.LENGTH_SHORT).show(); dbadapter.deleteshot_bysessionid(0); dbadapter.deletesession_byid(0); else {Toast.makeText(ctx, "Το Ιστορικό δεν μπόρεσε να μετακινηθεί!", Toast.LENGTH_SHORT).show(); //Μετακίνηση void copyfile(file src, File dst) throws IOException { FileChannel inchannel = new FileInputStream(src).getChannel(); FileChannel outchannel = new FileOutputStream(dst).getChannel(); try { inchannel.transferto(0, inchannel.size(), outchannel); finally { if (inchannel!= null) inchannel.close(); if (outchannel!= null) outchannel.close(); Η κλάση ExportDatabaseFileTask() είναι αυτή που αναλαμβάνει την μετακίνηση της Βάσης Δεδομένων στην κάρτα μνήμης. Βρίσκεται μέσα στο αρχείο MainActivity.java. 59
4.2.6. Διαχείριση Προπονήσεων Οι λειτουργίες που μπορεί να ασκηθούν στις προπονήσεις περιλαμβάνονται στην κλάση SessionsActivity.java. Αρχικά ανακτώνται από την βάση δεδομένων και έπειτα προβάλλονται σε listview. Απόσπασμα 14 //Δήλωση λίστας Προπονήσεων SessionList = (ListView) findviewbyid(r.id.list); //Ανάκτηση Προπονήσεων από ΒΔ cursor = dbadapter.queue_sessions(true); //Ανάθεση στοιχείων Προπονήσεων στις θέσεις της λίστας String[] columns = new String[]{SQLiteAdapter.KEY_SESSIONS_DATE, SQLiteAdapter.KEY_ENDS_DISTANCE, SQLiteAdapter.KEY_SESSIONS_NOTES, SQLiteAdapter.SUM_SESSION_SCORE_AS, SQLiteAdapter.KEY_SESSIONS_ENDS; int[] to = new int[]{r.id.row_sessions1, R.id.row_sessions2, R.id.row_sessions3, R.id.row_sessions4, R.id.row_sessions5 ; cursoradapter =new SimpleCursorAdapter(this, R.layout.sessions_row, cursor, columns, to); //Εμφάνιση Προπονήσεων και στοιχείων τους στην λίστα SessionList.setAdapter(cursorAdapter); To long-click σε ένα στοιχείο της λίστας επιτρέπει την διαγραφή μιας προπόνησης μέσω διαλόγου με κατάλληλα widget: Απόσπασμα 15 //Διαχείριση κλικ πλήκτρου διαγραφής Προπόνησης public void onclick(dialoginterface arg0, int arg1) { //Ανάκτηση ΙD Προπόνησης από ΒΔ Cursor cursor = (Cursor) parent.getitematposition(position); //Διαγραφή εξαρτήσεων από ΒΔ dbadapter.deleteshot_bysessionid(item_id); //Διαγραφή Προπόνησης από BΔ dbadapter.deletesession_byid(item_id); updatelist(); Λόγω εξαρτήσεων και έλλειψης υποστήριξης ξένων κλειδιών από την SQLite, διαγράφονται πρώτα οι βολές μιας προπόνησης και μετά η προπόνηση ή ίδια. Οι εντολές διαγραφής τους στο αρχείο SQLiteAdapter.java είναι: 60
Απόσπασμα 16 //Διαγραφή Προπόνησης public void deletesession_byid(long item_id){ if (item_id!=0) sqlitedatabase.delete (TABLE_SESSIONS, KEY_SESSIONS_ID + " = " +item_id, null); //Αν το ID ισούται με 0 τότε σβήσε όλες τις Προπονήσεις else sqlitedatabase.delete(table_sessions, null, null); //Διαγραφή Βολών Προπόνησης public void deleteshot_bysessionid(long item_id){ if (item_id!=0) sqlitedatabase.delete (TABLE_SHOTS, KEY_SESSIONS_ID + " = " + item_id, null); //Αν το ID ισούται με 0 τότε σβήσε όλες τις Βολές else sqlitedatabase.delete(table_shots, null, null); Η εκκίνηση διαμοιρασμού της επίδοσης σε μια προπόνηση γίνεται μέσω του πλήκτρου που υπάρχει στον διάλογο. Απόσπασμα 17 //Καθορισμός συμπεριφοράς κουμπιού Share! SessionsDialog.setNegativeButton("Share!", new DialogInterface.OnClickListener() { public void onclick(dialoginterface arg0, int arg1) { //Μήνυμα προς διαμοιρασμό final String message = (String.valueOf(item_date)+": " +String.valueOf(distance)+"μέτρα, " +String.valueOf(ends)+" ends, " +String.valueOf(score)+" βαθμοί"); //Καθορισμός διαμοιρασμού Intent share = new Intent(Intent.ACTION_SEND); share.settype("text/plain"); share.putextra(intent.extra_text, "μfita - "+ message); //Έναρξη διαμοιρασμού startactivity(intent.createchooser(share, "Share!")); ); 4.2.7. Καταχώρηση Βολών Η καταχώρηση των βολών γίνεται στην κλάση TargetActivity.java και με την βοήθεια του custom view TargetView.java.Εκεί δηλώνονται οι διαστάσεις και περιεχόμενα του custom view. Πριν περιγραφεί κώδικας σε java, αξίζει να εξεταστεί η δομή των δύο παραπάνω. Η κατασκευή του TargetView γίνεται στο αρχείο target_view.xml που βρίσκεται στον φάκελο res/layout του project. 61
Απόσπασμα 18 <android.archer.test.targetview android:id="@+id/mytargetview" android:layout_width="300dip" android:layout_height="300dip" android:layout_gravity="center_horizontal" android:background="@drawable/target_cancel" > </android.archer.test.targetview> Tα περιεχόμενα της δραστηριότητας TargetActivity περιγράφονται στο αρχείο target_form.xml που βρίσκεται επίσης στον φάκελο res/layout του project. Εκεί μέσα δηλώνεται και το custom view. Απόσπασμα 19 <?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <View android:id="@+id/target" android:layout_width="300dip" android:layout_height="350dip" /> </merge> Συμπερασματικά, πρόκειται για 2 αρχεία.xml από τα οποία το στο ένα γίνεται αναφορά μέσα από άλλο. Στην συνέχεια θα εξεταστεί ο τρόπος με τον οποίο εισάγεται μια βολή. Η μέθοδος που είναι υπεύθυνη για την λειτουργία αυτή είναι η ontouchevent, της οποίας ο σκοπός είναι ο εντοπισμός ενός gesture αφής πάνω στην οθόνη της συσκευής. H TargetView καλεί 2 interface κατά την διάρκεια του κύκλου λειτουργίας της. Το Ιnterface InsertShotsListener ενημερώνει την TargetActivity με τα δεδομένα που θα αποθηκευτούν στην Βάση Δεδομένων και το ViewWasTouchedListener ενημερώνει το UI με τις βολές του χρήστη. Απόσπασμα 20 public interface ViewWasTouchedListener { public void onviewtouched(int points, int ShotNo); Απόσπασμα 21 public interface InsertShotsListener { public void oninsertshotstapped(int points, int ShotNo, int end, float shotx, float shoty, long sessionid); Τα Interface με την σειρά τους στέλνουν τα δεδομένα που δέχτηκαν στις κλάσεις που τα καλούν. Στην συγκεκριμένη περίπτωση στην TargetActivity.java.Η μέθοδος οntargettapped ενημερώνει το UI κάθε φορά που ο χρήστης εισάγει μια βολή στον στόχο. Η αντιστοίχηση στο UI γίνεται με βάση τον αριθμό της βολής. 62
Απόσπασμα 22 public void ontargettapped(int points, int ShotNo) { final TextView ScoreTextView ; //Ενημέρωση TextView ανάλογα με τον αριθμό βολής switch (ShotNo){ case (5): { ScoreTextView = (TextView) findviewbyid(r.id.s6); ScoreTextView.setText(String.valueOf(points)); break; case (4): { ScoreTextView = (TextView) findviewbyid(r.id.s5); ScoreTextView.setText(String.valueOf(points)); break; case (3): { ScoreTextView = (TextView) findviewbyid(r.id.s4); ScoreTextView.setText(String.valueOf(points)); break; case (2): { ScoreTextView = (TextView) findviewbyid(r.id.s3); ScoreTextView.setText(String.valueOf(points)); break; case (1): { ScoreTextView = (TextView) findviewbyid(r.id.s2); ScoreTextView.setText(String.valueOf(points)); break; case (0): { ScoreTextView = (TextView) findviewbyid(r.id.s1); ScoreTextView.setText(String.valueOf(points)); Από την άλλη πλευρά, για την αποστολή των δεδομένων στην Βάση Δεδομένων καλείται το Interface oninsertshotstapped. 63
Απόσπασμα 23 public void oninsertshotstapped(int points, int ShotNo, int end, float x, float y, long sessionid) { //Καθαρισμός UI βαθμολογίας βολών Score1.setText("_"); Score2.setText("_"); Score3.setText("_"); Score4.setText("_"); Score5.setText("_"); Score6.setText("_"); //UI Ενημέρωση συνολογικής βαθμολογίας Total= Total + points; TotalTextView.setText(String.valueOf(Total)); //UI Ενημέρωση αριθμού End EndTextView.setText(String.valueOf(end+1)); //Ενημέρωση ΒΔ mysqliteadapter.insertshot(points, end, sessionid, ShotNo, x, y); mysqliteadapter.updatesession_byid(sessionid, null, end); //Ενημέρωση αριθμού end CurrentEnd=end; //Εμφάνιση διαλόγου επιδόσεων μετά την τελευταία βολή if (ShotNo == 0) makearrowsdialog(); Η συνάρτηση makearrowsdialog (Απόσπασμα 24) επιτρέπει στον χρήστη να δηλώσει ποια βέλη έφεραν καλές επιδόσεις εφόσον έχει ολοκληρώσει με τις βολές του τρέχοντος end. Μέσω ενός διαλόγου που περιέχει ένα gridview με τα επιλεγμένα βέλη του χρήστη δίνεται η δυνατότητα να σημειωθούν βέλη που φέρανε σημαντικές επιδόσεις για τον χρήστη. 64
Απόσπασμα 24 public void makearrowsdialog(){ //Δημιουργία Διαλόγου και ρύθμιση παραμέτρων του final Dialog ArrowsDialog = new Dialog(TargetActivity.this); ArrowsDialog.requestWindowFeature(Window.FEATURE_LEFT_ICON); ArrowsDialog.setContentView(R.layout.mark_arrows_dialog); ArrowsDialog.setTitle("Σημαντικές Επιδόσεις"); ArrowsDialog.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.dthumbsup); //Δήλωση λίστας επιλεγμένων Βελών GridView marklist = (GridView) ArrowsDialog.findViewById(R.id.marklist); //Κλείσιμο διαλόγου final Button closedialog = (Button)ArrowsDialog.findViewById(R.id.button_mark_arrows_close); closedialog.setonclicklistener(new OnClickListener() { ); public void onclick(view v) { ArrowsDialog.dismiss(); //Ανάκτηση επιλεγμένων Βελών από την ΒΔ και ανάθεσή τους στις θέσεις //της λίστας cursor = mysqliteadapter.queue_equiped_arrows(); if (cursor!=null){ String[] from = new String[]{SQLiteAdapter.KEY_ARROWS_NOTE; int[] to = new int[] {R.id.Arrow_tv; cursoradapter = new SimpleCursorAdapter(this, R.layout.arrow_dialog_row, cursor, from, to); //Εμφάνιση Βελών στην λίστα marklist.setadapter(cursoradapter); //Ρύθμιση συμπεριφοράς long-click στοιχείων λίστας marklist.setonitemlongclicklistener(new GridView.OnItemLongClickListener(){ public boolean onitemlongclick(adapterview<?> parent, View item, int position,long id) { //Εμφάνιση μηνύματος και απόκρυψη βέλους που πατήθηκε Toast.makeText(TargetActivity.this, "+1", Toast.LENGTH_SHORT).show(); item.setvisibility(view.invisible); //Ανάκτηση ID Βέλους και ενημέρωση ΒΔ Cursor cursor = (Cursor) parent.getitematposition(position); final int item_id = cursor.getint(cursor.getcolumnindex (SQLiteAdapter.KEY_SHOTS_ID)); mysqliteadapter.updatearrows_xcounter(item_id); return true; ); //Εμφάνιση Διαλόγου ArrowsDialog.show(); 65
Τα βέλη που ανακτώνται κατά την διάρκεια της εκτέλεσης της makearrowsdialog() δύναται να επιλεγούν πριν την εκτέλεση της ArrowsActivity.java, κατά την διάρκεια της NewSessionActivity.java όπως παρουσιάζεται στο Απόσπασμα 25. Απόσπασμα 25 //Δήλωση λίστας επιλογής Βελών choosearrowlist = (ListView) findviewbyid(r.id.choose_arrows_lv); //Ανάκτηση Βελών από ΒΔ και ανάθεσή τους στις θέσεις τις λίστας cursor = mysqliteadapter.queue_arrows(true); String[] from1 = new String[]{SQLiteAdapter.KEY_ARROWS_NOTE, SQLiteAdapter.KEY_ARROWS_XCOUNTER, SQLiteAdapter.KEY_ARROWS_QUIVER; int[] to1 = new int[]{r.id.text1, R.id.text2, R.id.text3 ; cursoradapter =new SimpleCursorAdapter(this, R.layout.arrows_row, cursor, from1, to1); //Εμφάνιση Βελών στην λίστα choosearrowlist.setadapter(cursoradapter); //Ενεργοποίηση δυνατότητας κλικ σε στοιχεία της λίστας choosearrowlist.setonitemclicklistener(listcontentonitemclicklistener); //... //Ρύθμιση συμπεριφοράς κλικ στοιχείου της λίστας ListView.OnItemClickListener listcontentonitemclicklistener = new ListView.OnItemClickListener(){ public void onitemclick(adapterview<?> parent, View view, int position,long id) { //Ανάκτηση ΙD Βέλους και κατάσταση επιλογής από ΒΔ Cursor cursor = (Cursor) parent.getitematposition(position); final int item_id = cursor.getint(cursor.getcolumnindex(sqliteadapter.key_arrows_id)); final String quiver = cursor.getstring(cursor.getcolumnindex(sqliteadapter.key_arrows_quiver)); //Ενημέρωση ΒΔ και λίστας mysqliteadapter.updatequiver(item_id, quiver); updatelist(); ; Τέλος, θα εξεταστεί ο τρόπος με τον οποίο γίνεται η αποτύπωση των βολών πάνω στον εικονικό στόχο. Αυτό συμβαίνει στην custom view TargetView.java - που έχει ήδη αναφερθεί προηγουμένως - και συγκεκριμένα στην μέθοδο ondraw. 66
Απόσπασμα 26 @Override public void ondraw(canvas canvas){ super.ondraw(canvas); //Δημιουργία "πινέλου" Paint p = new Paint(); p.setantialias(true); p.setcolor(color.green); p.setstyle(paint.style.fill); p.setstrokewidth(1); //Δημιουργία "πινέλου" Paint cover = new Paint(); cover.setantialias(true); cover.setcolor(color.black); cover.setstyle(paint.style.fill); cover.setstrokewidth(1); //Εάν η προπόνηση έχει ενακτηθεί από το Ιστορικό if (NewSession==false) { //Ανέκτησε τις συντεταγμένες των βολών της cursor=mysqliteadapter.queue_shots_bysessionid(sessionid); cursor.movetofirst(); //Και ζωγράφισε βούλες while (cursor.isafterlast() == false) { canvas.drawcircle(cursor.getfloat(5),cursor.getfloat(6),r+1,p); canvas.drawcircle(cursor.getfloat(5),cursor.getfloat(6),r,cover); cursor.movetonext(); canvas.drawcircle(20,279,30,cover); invalidate(); cursor.deactivate(); //Αλλιώς ζωγράφισε βουλές στα σημεία αφής του χρήστη else{ for (int i=0;i<=shotno+1;i++) { canvas.drawcircle(shotx[i], shoty[i], r+1, p); canvas.drawcircle(shotx[i], shoty[i], r, cover); canvas.drawcircle(0,0,10,cover); invalidate(); canvas.restore(); Εάν οι επιδόσεις φορτωθούν από την βάση δεδομένων, τότε ανακτώνται οι συντεταγμένες των βολών και στην συνέχεια ζωγραφίζονται οι βούλες. Αν πρόκειται για νέα προπόνηση, οι βούλες ζωγραφίζονται στα σημεία που άγγιξε ο χρήστης. Παρατηρείται πως χρησιμοποιήθηκαν 2 πινέλα με διαφορετικό χρώμα το καθένα. Αυτό συμβαίνει για να διακρίνονται ευκολότερα οι βολές στους διάφορους δακτυλίους του στόχου. Στο επόμενο κεφάλαιο οι παραπάνω λειτουργίες τίθενται σε εφαρμογή και παρουσιάζονται με τον τρόπο που θα τις αντιληφθεί ο τελικός χρήστης. 67
5. ΠΑΡΟΥΣΙΑΣΗ EΦΑΡΜΟΓΉΣ Σε αυτό το κεφάλαιο θα γίνει η παρουσίαση της εφαρμογής μfita στην τελική της μορφή. Ενώ στα προηγούμενα κεφάλαια εξετάστηκε η σχεδίαση της εφαρμογής και παρουσιάστηκε η υλοποίηση των βασικότερων λειτουργιών της μέσω κώδικα, στο παρών θα παρουσιαστεί ο τρόπος λειτουργίας της και οι ιδιότητές της, μέσω εικόνων και επεξηγήσεων, εξετάζοντάς την από την πλευρά του χρήστη και όχι ενός προγραμματιστή. Η σειρά παρουσίασης των λειτουργιών της εφαρμογής θα ακολουθήσει έναν τυπικό κύκλο λειτουργίας της και θα γίνει μέσω εικονικής συσκευής, που παρέχεται από το Android SDK. 5.1. Αρχική οθόνη Αφού κάνουμε κλικ στο εικονίδιο της εφαρμογής, μεταφερόμαστε στην αρχική οθόνη. Από εδώ ο χρήστης μπορεί να εκτελέσει τις τέσσερις βασικές λειτουργίες που προσφέρει η εφαρμογή. Εικόνα 24: Αρχική οθόνη Τα κουμπιά που περιλαμβάνει είναι τα εξής: 1. Πάμε! (έναρξη καταχώρησης επιδόσεων) 3. Ιστορικό (επιδόσεων χρήστη) 2. Bέλη (διαχείριση βελών) 4. Στατιστικά (επιδόσεων ιστορικού) Επιπρόσθετα παρέχεται ο σύνδεσμος Βοήθεια που παρέχει στον χρήστη πληροφορίες Βοήθειας. Έτσι αν ο χρήστης πατήσει στον συγκεκριμένο σύνδεσμο θα ανοίξει ένα μήνυμα με πληροφορίες βοήθειας(εικόνα 25). Το μενού της αρχικής οθόνης περιλαμβάνει τα αντικείμενα Μετακίνηση Ιστορικού και Σχετικά (Εικόνα 27). Εφόσον ο χρήστης επιθυμεί να μετακινήσει το ιστορικό των επιδόσεών του και αγγίξει το αντικείμενο Μετακίνηση Ιστορικού θα κληθεί να επιλέξει σε ποιο μέσο θα γίνει η μετακίνηση (Εικόνα 26), δηλαδή στην κάρτα μνήμης, και αφού ολοκληρωθεί επιτυχώς η μετακίνηση ή όχι θα ενημερωθεί με κατάλληλο μήνυμα. 68
Το αντικείμενο Σχετικά περιλαμβάνει πληροφορίες σχετικές με την ανάπτυξη της εφαρμογής. Εικόνα 25: Βοήθεια Εικόνα 26: Μετακίνηση Ιστορικού Εικόνα 27: Μενού αρχικής οθόνης 5.2. Καταχώρηση Επιδόσεων Για να αρχίσει ο χρήστης να καταχωρεί τις επιδόσεις του θα πρέπει να πατήσει το κουμπί Πάμε!. Μόλις πατηθεί θα μεταφερθεί σε διαφορετική οθόνη που του επιτρέπει να επιλέξει την απόστασή του από τον στόχο καθώς και τα βέλη που θα χρησιμοποιήσει στην προπόνησή του (Εικόνα 28). Η οθόνη περιλαμβάνει ένα πλαίσιο επιλογής της απόστασης, μια λίστα με τα καταχωρημένα βέλη του και ένα πλαίσιο εισαγωγής κειμένου. Επιπρόσθετα, πατώντας το πλήκτρο Menu της συσκευής του μπορεί να προβάλει ένα βοηθητικό κείμενο για την τρέχουσα οθόνη. 69
Εικόνα 28: Επιλογές νέας προπόνησης Εικόνα 29: Επιλογή απόστασης Κάνοντας κλικ στο πεδίο της απόστασης, εμφανίζεται το σύνολο των αποστάσεων από τις οποίες ο χρήστης μπορεί να επιλέξει μια (Εικόνα 30). Για να επιλέξει ο χρήστης τα βέλη που θα χρησιμοποιήσει το μόνο που χρειάζεται να κάνει, είναι να αγγίξει τα βέλη που επιθυμεί, στην λίστα που εμφανίζονται (Εικόνα 30). Σε αυτήν προβάλλονται, επίσης, πληροφορίες των βελών όπως το όνομά του και ο αριθμός των σημαντικών του επιδόσεων. Την κατάσταση επιλογής ενός βέλους την εκφράζει χαρακτηριστικά ένα ή. Εικόνα 30: Επιλογή βελών Εικόνα 31: Εισαγωγή σημείωσης Στο κάτω μέρος της οθόνης υπάρχει ένα πλαίσιο που επιτρέπει τον χρήστη να εισάγει μια μικρή σημείωση για την προπόνηση. Αν κάνει κλικ εκεί θα εμφανιστεί το πληκτρολόγιο για την εισαγωγή 70
της σημείωσής του (Εικόνα 31). Αφού τελειώσει με την πληκτρολόγηση μπορεί να πατήσει Done από το πληκτρολόγιο ή Πάμε! για να αποθηκευτεί η σημείωσή του και να εκκινηθεί η διαδικασία δήλωσης των επιδόσεων του. Αφού ο χρήστης πατήσει Done ή Πάμε! Μεταφερόμαστε στην οθόνη του στόχου. Η οθόνη αυτή περιέχει τον στόχο τοξοβολίας μαζί με τις πληροφορίες της προπόνησης στο πάνω μέρος και την βαθμολογία των βολών στο κάτω μέρος. Εικόνα 32: Εισαγωγή βολής Εικόνα 33: Αναίρεση βολής Για να γίνει εισαγωγή μιας βολής ο χρήστης καλείται απλά να αγγίξει στο αντίστοιχο σημείο του εικονικού στόχου με αυτό της βολής του πάνω στον πραγματικό. Μόλις αγγίξει το σημείο αυτό, στο κάτω μέρος θα εμφανιστεί η βαθμολογία της βολής(εικόνα 32). Ο χρήστης μπορεί να αναιρέσει την βολή του σε περίπτωση λανθασμένης εισαγωγής της, αγγίζοντας το βελάκι αριστερά του στόχου (Εικόνα 33). Εφόσον ο χρήστης εισάγει επιτυχώς και τις 6 βολές του end εμφανίζεται μήνυμα που τον παροτρύνει να αγγίξει ξανά για να γίνει αποθήκευση του end (Εικόνα 34). Ωστόσο μπορεί να αγγίξει το βελάκι για να κάνει κάποια διόρθωση. 71
Εικόνα 34: Αποθήκευση end Αφού ο χρήστης αποθηκεύσει το end του, θα εμφανιστεί διάλογος που του επιτρέπει να δηλώσει αν κάποιο από τα επιλεγμένα βέλη του έχει φέρει επίδοση που αυτός θεωρεί σημαντική (Εικόνα 35). Για να γίνει αυτό, αρκεί να πατήσει παρατεταμένα στα βέλη που επιθυμεί τα οποία αφαιρούνται από τη λίστα για αποφυγή λαθών και τελικά να πατήσει Κλείσιμο (Εικόνα 36). Εικόνα 35: Διαλογος Σημαντικών Επιδόσεων Εικόνα 36: Δήλωση σημαντικών επιδόσεων Αμέσως μετά παρατηρείται πως ο μετρητής των end έχει αυξηθεί και η ένδειξη του σκορ έχει ενημερωθεί με την συνολική βαθμολογία. Κατά την διάρκεια όλων των παραπάνω, ο χρήστης μπορεί να κρατήσει μικρές σημειώσεις για την 72
προπόνησή του, να επισκοπήσει τις βαθμολογίες των βολών που έκανε κατά την διάρκειά της και να πάρει βοήθεια για την παρούσα οθόνη, πατώντας το πλήκτρο μενού της συσκευής του (Εικόνα 37). Εικόνα 37: Μενού οθόνης στόχου Θέλοντας ο χρήστης να μελετήσει τις βαθμολογίες όλων των βολών που έκανε μέχρι στιγμής σε αυτήν την προπόνηση, θα χρειαστεί να πατήσει στο αντικείμενο Λίστα βολών. Στην συνέχεια θα εμφανιστεί αναδυόμενο μήνυμα που θα τις περιέχει με τη σειρά (Εικόνα 38). Για να επιστρέψει ο χρήστης στην οθόνη του στόχου μπορεί να πατήσει το πλήκτρο Back της συσκευής του. Πατώντας στο αντικείμενο Πρόχειρο, ο χρήστης μεταφέρεται στο πρόχειρο όπου μπορεί να κρατήσει σημειώσεις και να τις μελετήσει αργότερα (Εικόνα 39). Στο πλαίσιο εισαγωγής κειμένου εμφανίζονται επίσης και οι σημειώσεις που προστέθηκαν κατά την διαδικασία παραμετροποίησης της προπόνησης του που αναφέρθηκε νωρίτερα. Αφού ο χρήστης πατήσει μέσα στο πλαίσιο εισαγωγής κειμένου, προσθέσει τις σημειώσεις του με την βοήθεια του εικονικού πληκτρολογίου, μπορεί να πατήσει Αποθήκευση για την αποθήκευσή τους και κλείσιμο του Πρόχειρο. Εάν δεν επιθυμεί να κάνει κάποια αλλαγή στις σημειώσεις, μπορεί να πατήσει Άκυρο ή το πλήκτρο Back της συσκευής του. 73
Εικόνα 38: Λίστα βολών Εικόνα 39: Πρόχειρο Αφού ο χρήστης αποθηκεύσει όσα end θέλει, μπορεί να τερματίσει μια προπόνηση πατώντας το πλήκτρο Back της συσκευής του, όσο βρίσκεται στην οθόνη στόχου. Θα εμφανιστεί μήνυμα για επιβεβαίωση εξόδου (Εικόνα 40). Με την αποδοχή του η προπόνηση αποθηκεύεται στο Ιστορικό και γίνεται διαθέσιμη για επισκόπηση, ενώ με την άρνησή του επιστρέφουμε στην οθόνη στόχου. Εικόνα 40: Τερματισμός προπόνησης Αφού γίνει έξοδος από την προπόνηση μεταφερόμαστε πάλι στην αρχική οθόνη της εφαρμογής. Τέλος αναφέρεται πως η παροχή βοήθειας είναι παρόμοια με αυτή της αρχικής οθόνης και για αυτό δεν εξετάζεται περαιτέρω. 74
5.3. Διαχείριση Βελών Η διαχείριση των βελών του χρήστη γίνεται προσβάσιμη πατώντας το κουμπί Βέλη της αρχικής οθόνης (Εικόνα 24). Στην οθόνη που θα εμφανιστεί διακρίνονται μια λίστα με τα βέλη του χρήστη και ένα πλαίσιο εισαγωγής κειμένου στο κάτω μέρος της οθόνης με ένα κουμπί να το συνοδεύει από τα δεξιά του. Η λίστα περιλαμβάνει 6 προεπιλεγμένα βέλη τα οποία η εφαρμογή εισάγει αυτόματα και μπορούν να χρησιμοποιηθούν πλήρως από τον χρήστη, χωρίς όμως να μπορούν να διαγραφούν. Εικόνα 41: Οθόνη διαχείρισης βελών Στα δεδομένα που προβάλλονται στην λίστα, φαίνονται το όνομα του βέλους, ο αριθμός των σημαντικών του επιδόσεων και ένα σύμβολο που δηλώνει αν είναι επιλεγμένο ή όχι, το οποίο αλλάζει με τον ίδιο τρόπο που περιγράφηκε και για την λίστα επιλογής βελών της προηγούμενης ενότητας. Εκτός των προκαθορισμένων βελών ο χρήστης μπορεί να εισάγει και τα δικά του βέλη. Το πλαίσιο εισαγωγής κειμένου που υπάρχει στο κάτω μέρος δέχεται το όνομα του βέλους, το οποίο πρέπει να συμπληρωθεί υποχρεωτικά. Σε αντίθετη περίπτωση εμφανίζεται κατάλληλο μήνυμα (Εικόνα 42). Αφού πληκτρολογήσουμε το όνομα του βέλους (Εικόνα 43), πατώντας Εισαγωγή ή Done, το νέο βέλος προστίθεται στην λίστα μαζί με τα υπόλοιπα (Εικόνα 44) με μηδενικές σημαντικές επιδόσεις οι οποίες μπορούν να δηλωθούν κατά την διάρκεια μιας προπόνησης, όπως έχει ήδη αναφερθεί στην προηγούμενη ενότητα. 75
Εικόνα 42: Μηνυμα κενού ονόματος Εικόνα 43: Ονομασία βέλους Εικόνα 44: Εισαγωγή βέλους Στην συνέχεια μπορούμε να επεξεργαστούμε κάποιο βέλος πατώντας παρατεταμένα πάνω του. Θαεμφανιστεί ένα αναδυόμενο παράθυρο στο οποίο μπορούμε να μετονομάσουμε, διαγράψουμε και επαναφέρουμε τον μετρητή σημαντικών του επιδόσεων (Εικόνα 45). Έχοντας επιλέξει το βέλος που μόλις προσθέσαμε παρατηρούμε πως δεν μπορούμε να του κάνουμε Επαναφορά καθώς ακόμα δεν έχει σημειώσει σημαντικές επιδόσεις. 76
Εικόνα 45: Επεξεργασία νέου βέλους Εικόνα 46: Μετονομασία βέλους Ωστόσο πατώντας πάνω στο πλαίσιο κειμένου μπορούμε να του αλλάξουμε το όνομα (Εικόνα 46) χρησιμοποιώντας το εικονικό πληκτρολόγιο και πατώντας Αποθήκευση να αποθηκεύσουμε τις αλλαγές που κάναμε (Εικόνα 48). Πατώντας Διαγραφή, το βέλος διαγράφεται από την λίστα βελών. Σε βέλος που έχει επιτύχει σημαντικές επιδόσεις μπορούμε να κάνουμε Επαναφορά (Εικόνα 49), ωστόσο αν το βέλος έχει εισαχθεί αυτόματα από την εφαρμογή δεν μπορεί να διαγραφεί (Εικόνα 54). Εικόνα 47: Επεξεργασία βέλους εφαρμογής Εικόνα 48: Αποθήκευση βέλους 77
Εικόνα 49: Επαναφορά βέλους Τέλος από το Menu\Εναλλαγή Ταξινόμησης (Εικόνα 51) μπορούμε να αλλάξουμε την ταξινόμηση της λίστας δείχνοντας πρώτα τα βέλη με τις περισσότερες σημαντικές επιδόσεις (Εικόνα 50) είτε βάζοντάς τα σε σειρά ανάλογα με την σειρά εισαγωγής τους (προκαθορισμένη). Εικόνα 51: Μενού οθόνης βελών Εικόνα 50: Ταξινόμηση βελών Σημειώνεται πως το Menu\Boήθεια λειτουργεί με τον ίδιο τρόπο που λειτουργεί αυτό της αρχικής οθόνης (Εικόνα 25). 78
5.4. Διαχείριση Ιστορικού Οι αποθηκευμένες προπονήσεις μπορούν προβληθούν και να επεξεργαστούν μέσω του Ιστορικού. Για την μετάβαση του χρήστη σε αυτό πατάμε το κουμπί Ιστορικό της αρχικής οθόνης (Εικόνα 24). Η οθόνη του Ιστορικού περιλαμβάνει μια λίστα με τις αποθηκευμένες προπονήσεις και ένα κουμπί από πάνω της (Εικόνα 53). Το κουμπί αποτελεί συντόμευση και οδηγεί τον χρήστη στην οθόνη επιλογής ρυθμίσεων μιας νέας προπόνησης. Τα στοιχεία μιας προπόνησης που προβάλει η λίστα είναι η ημερομηνία και ώρα δημιουργίας της, η απόσταση από τον στόχο, η βαθμολογία της, ο αριθμός των end και μέρος από τις σημειώσεις που κρατήθηκαν κατά την διάρκειά της. Εικόνα 53: Οθόνη ιστορικού Εικόνα 52: Επεξεργασία προπόνησης Για την προβολή όλων των σημειώσεων ο χρήστης θα πρέπει να μεταβεί στην επεξεργασία της, κάνοντας παρατεταμένο κλικ πάνω σε μια προπόνηση της λίστας. Θα εμφανιστεί αναδυόμενο(εικόνα 52) παράθυρο που περιέχει μερικά στοιχεία της προπόνησης, ένα πλαίσιο κειμένου με τις σημειώσεις της προπόνησης και 3 κουμπιά που επιτρέπουν στο χρήστη να κάνει διαγραφή της προπόνησης, αποθήκευση τυχών αλλαγών στις σημειώσεις της και Share της επίδοσής της. Πατώντας πάνω στο πλαίσιο κειμένου μπορούμε να προσθέσουμε σημειώσεις με χρήση του εικονικού πληκτρολογίου (Εικόνα 54) και να τις αποθηκεύσουμε (Εικόνα 55) πατώντας Αποθήκευση. 79
Εικόνα 54: Επεξεργασία σημειώσεων Εικόνα 55: Αποθήκευση σημειώσεων Πατώντας Share! Εμφανίζεται ένας διάλογος που μας επιτρέπει να επιλέξουμε τον τρόπο με τον οποίο θέλουμε να διαμοιραστούμε την επίδοση που κάναμε. Αφού επιλέξουμε με ποια εφαρμογή θέλουμε να κάνουμε διαμοιρασμό εμφανίζονται οι πληροφορίες που θα μοιραστούμε (Εικόνα 56) τις οποίες μπορούμε στην συνέχεια να μοιραστούμε φυσικά. Ενώ πατώντας Διαγραφή, η τρέχουσα προπόνηση διαγράφεται και αφαιρείται από το Ιστορικό. Για την λεπτομερή επισκόπηση μιας προπόνησης χρειάζεται να πατήσουμε απλά πάνω σε ένα στοιχείο της λίστας. Με αυτόν τον τρόπο μεταφερόμαστε στην οθόνη του στόχου, που έχει αναφερθεί σε προηγούμενη ενότητα, όπου φορτώνονται όλες οι πληροφορίες της προπόνησης που επιλέξαμε. Έτσι αν επιλέξουμε με παρατεταμένο κλικ μια προπόνηση στο πάνω μέρος του της οθόνης του στόχου θα εμφανίζονται η απόσταση της προπόνησης που επιλέξαμε, η συνολική της βαθμολογία και ο αριθμός των end. Ενώ παράλληλα στον ίδιο τον στόχο θα έχουν σημαδευτεί οι επιδόσεις των βολών της (Εικόνα 57). 80
Εικόνα 56: Share προπόνησης Εικόνα 57: Φορτωμένη προπόνηση Επιπρόσθετα μπορούμε να χρησιμοποιήσουμε τις λειτουργίες του μενού κανονικά, όπως θα γινόταν και σε μια νέα προπόνηση, διαδικασία που περιγράφηκε στην ενότητα της Καταχώρησης Επιδόσεων. Για την επιστροφή στο Ιστορικό πατάμε απλά το πλήκτρο Back της συσκευής μας. Τέλος, μπορούμε να χρησιμοποιήσουμε το Menu\Εναλλαγή ταξινόμησης για να ταξινομήσουμε τις προπονήσεις ανάλογα με την απόσταση και ανάλογα με την ημερομηνία δημιουργίας τους (Εικόνα 59). To Menu\Bόηθεια παρέχει θέματα βοήθειας με τρόπο που έχει αναφερθεί. Εικόνα 58: Μενού οθόνης ιστορικού Εικόνα 59: Ταξινόμηση ιστορικού 81