152
Τ.Ε.Ι. ΚΑΒΑΛΑΣ ΤΜΗΜΑ ΣΧΟΛΗ ΔΙΟΙΚΗΣΗΣ ΔΙΑΧΕΙΡΙΣΗΣ ΚΑΙ ΟΙΚΟΝΟΜΙΑΣ ΠΛΗΡΟΦΟΡΙΩΝ Εκπονηθείσα πτυχιακή εργασία απαραίτητη για την κτήση του βασικού πτυχίου ΣΧΕΔΙΑΣΜΟΣ ΚΑΙ ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΗΣ ΛΟΓΙΣΜΙΚΟΥ ANDROID ΓΙΑ ΥΠΕΝΘΥΜΙΣΗ ΗΜΕΡΗΣΙΑΣ ΛΗΨΗΣ ΦΑΡΜΑΚΕΥΤΙΚΩΝ ΣΚΕΥΑΣΜΑΤΩΝ Λάμπρος Μάρκου ΑΠΡΙΛΙΟΣ 2015 ΕΠΙΒΛΕΠΩΝ ΚΑΘΗΓΗΤΗΣ Δρ. Βασίλειος Μαρδύρης

TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Τ.Ε.Ι. ΚΑΒΑΛΑΣ ΤΜΗΜΑ

ΣΧΟΛΗ ΔΙΟΙΚΗΣΗΣ ΔΙΑΧΕΙΡΙΣΗΣ

ΚΑΙ ΟΙΚΟΝΟΜΙΑΣ ΠΛΗΡΟΦΟΡΙΩΝ

Εκπονηθείσα πτυχιακή εργασία απαραίτητη για την κτήση του βασικού πτυχίου

ΣΧΕΔΙΑΣΜΟΣ ΚΑΙ ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΗΣ ΛΟΓΙΣΜΙΚΟΥ ANDROID ΓΙΑΥΠΕΝΘΥΜΙΣΗ ΗΜΕΡΗΣΙΑΣ ΛΗΨΗΣ ΦΑΡΜΑΚΕΥΤΙΚΩΝ ΣΚΕΥΑΣΜΑΤΩΝ

Λάμπρος Μάρκου

ΑΠΡΙΛΙΟΣ 2015

ΕΠΙΒΛΕΠΩΝ ΚΑΘΗΓΗΤΗΣ

Δρ. Βασίλειος Μαρδύρης

Page 2: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση και συνάμα τηκορύφωση των προπτυχιακών μου σπουδών στο Τ.Ε.Ι Καβάλας στη ΣχολήΔιοίκησης και Οικονομίας στο τμήμα Διαχείρισης Πληροφοριών. Θα ήθελανα ευχαριστήσω όλους όσους συνέβαλαν στη περάτωση της πτυχιακήςαυτής εργασίας και ιδιαίτερα το Δρ. Βασίλειο Μαρδύρη, τόσο για τηναποδοχή του ως επιβλέπων καθηγητής, όσο και για την ώθηση γιαενασχόληση με το προκείμενο θέμα και τις μετέπειτα συμβουλές καικατευθυντήριες γραμμές για τη δημιουργία μίας πληρέστερης εργασίας.

Page 3: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Σελίδα 1 από 150

ΠΕΡΙΕΧΟΜΕΝΑ

Εισαγωγή 5

Κεφάλαιο 1: Παρουσίαση του Android OS

1.1 Σκοπός και στόχος της εφαρμογής 6

1.2 Η απήχηση του Android OS και το μερίδιο της αγοράς 6

1.3 Ιστορική αναδρομή και τομείς εφαρμογής του λειτουργικού 7

1.4 Η αρχιτεκτονική του λειτουργικού συστήματος Android 10

1.4.1 Linux Kernel 12

1.4.2 Libraries 12

1.4.3 Dalvik Debug Monitor Server & Android Runtime 12

1.4.4 Android Run Time 13

1.4.5 Application Framework 13

1.4.6 Applications 14

1.5 Δυνατότητες φορητότητας εφαρμογών λειτουργικού

Android σε λοιπές πλατφόρμες 14

1.5.1 Microsoft Windows Mobile 15

1.5.2 BlackBerry OS 15

1.5.3 iOS 16

1.5.4 Mac OS X 16

1.5.5 Linux – Ubuntu 17

1.5.6 Microsoft Windows 17

1.5.7 Chrome OS 18

1.5.8 Firefox OS 18

Κεφάλαιο 2: Εξέταση παρόμοιων εφαρμογών

2.1 Προϋπάρχουσες εφαρμογές και χρησιμότητα αυτών 19

2.2 Εφαρμογές με πληρέστερη κάλυψη 21

Page 4: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Περιεχόμενα

Σελίδα 2 από 150

Κεφάλαιο 3: Ανατομία Android OS και MedReminder

3.1 Δομή μίας εφαρμογής Android σε προγραμματιστικό

Περιβάλλον 24

3.1.1 Gradle Scripts 26

3.1.2 *.java αρχεία 27

3.1.3 AndroidManifest.xml 29

3.1.4 Values / String.xml 30

3.1.5 Menu.xml 30

3.1.6 Layout.xml 31

3.1.7 Drawable 33

3.1.8 Δραστηριότητες ( Activities ) 34

3.1.9 Υπηρεσίες ( Services ) 35

3.1.10 Προθέσεις ( Intents ) 36

3.1.11 Δέκτες Μετάδοσης ( Broadcast Receivers ) 37

3.1.12 Πάροχοι Περιεχομένων ( Content Providers ) 37

3.1.13 Θραύσματα ( Fragments ) 38

3.2 Πλατφόρμα προγραμματισμού Android Studio 39

3.2.1 Εγκατάσταση εφαρμογής 39

3.2.2 Χρήση και περιγραφή οθόνης προγραμματιστή 40

3.2.3 Δημιουργία μίας εφαρμογής και απαιτήσεις 41

3.2.4 Δημιουργία εικονικής συσκευής 42

3.2.5 Δημιουργία περιεχόμενων αρχείων 43

3.2.6 Εκτέλεση και περάτωση σχεδιασμού μίας εφαρμογής 44

3.3 Εργαλεία Αποσφαλμάτωσης ( Debugging ) 46

3.3.1 Logcat 48

3.3.2 Android Debug Bridge 50

3.3.3 Dalvik Debug Monitor Server 51

3.4 Η δομή της εφαρμογής MedReminder 53

3.4.1 Gradle Script – module:app 53

3.4.2 AndroidManifest 54

Page 5: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 3 από 150

3.4.3 Drawable 57

3.4.4 Values 57

3.4.5 Menu 59

3.4.6 Layout 60

3.4.7 Κλάσεις 70

3.4.7.1 OnBootReceiver.java 70

3.4.7.2 ComDialogFragment.java 70

3.4.7.3 DatePickerFragment.java 72

3.4.7.4 TimePickerFragment.java 73

3.4.7.5 MedListActivity.java 75

3.4.7.6 NewMedReminder.java 82

3.4.7.7 NotificationService.java 89

3.4.7.8 ReminderDb.java 96

Κεφάλαιο 4: Εγχειρίδιο χρήσεως

4.1 Χρήση για πρώτη φορά 107

4.2 Περιγραφή και χρήση μονής ειδοποίησης 107

4.3 Τρόποι ειδοποίησης μονής ειδοποίησης 110

4.4 Περιγραφή και χρήση επαναλαμβανόμενων ειδοποιήσεων 111

4.5 Τρόποι ειδοποίησης επαναλαμβανόμενων ειδοποιήσεων 113

Κεφάλαιο 5: Συμπεράσματα

5.1 Συμπεράσματα σχεδιασμού της εφαρμογής 115

5.2 Προοπτικές μελλοντικής αξιοποίησης αυτής 116

Βιβλιογραφία 117

Παράρτημα 119

Page 6: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Περιεχόμενα

Σελίδα 4 από 150

Κατάλογος Πινάκων

2.1.1 Προϋπάρχουσες εφαρμογές 19

3.1.1 Δομή μίας εφαρμογής Android 24

3.1.6.1 Είδη Layout 31

3.1.6.2 Είδη χειριστών 32

3.1.8.1 Κλήσεις δραστηριοτήτων 35

3.1.9.1 Κλήσεις υπηρεσιών 36

Page 7: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Σελίδα 5 από 150

ΕΙΣΑΓΩΓΗ

Στη παρούσα πτυχιακή εργασία παρουσιάζεται συνοπτικά το λειτουργικό

σύστημα για κινητές συσκευές Android, όπως και αναλύεται η χρήση του

προγράμματος Android Studio ( https://developer.android.com/sdk/index.html )

για την ανάπτυξη εφαρμόγων στη πλατφόρμα ανοιχτού κωδικα Google SDK (

Software Development Kit ). Περεταίρω παρουσιάζεται και αναλύεται η δομή μίας

εφαρμογής σε περιβάλλον Android Studio, όπως και παρατίθενται παρόμοιες

εφαρμογές και δυνατότητες φορητότητας σε έτερα λειτουργικά συστήματα ( Mac

OS X, Microsoft Windows, Linux, iOS, Blackberry OS, Crome OS, Firefox OS ).

Η συγκεκριμένη εφαρμογή είναι η MedReminder ( Υπενθύμιση Φαρμάκων ) και

απευθύνεται σε ανθρώπους άνω της μέσης ηλικίας, κυρίως, ή

οποιονδήποτε/οποιαδήποτε λαμβάνει φαρμακευτικά σκευάσματα και επιθυμεί να

λαμβάνει μία υπενθύμιση για το χρονικό πλαίσιο λήψης αυτών, είτε ως μορφή

ασφαλιστικής δικλείδας για την έγκαιρη λήψη των απαιτούμενων σκευασμάτων

ή ως μία εκδηλωμένη αδυναμία ενθύμισης.

Page 8: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Σελίδα 6 από 150

ΚΕΦΑΛΑΙΟ 1: Παρουσίαση του Android OS

1.1) Σκοπός και στόχος της εφαρμογής

Σκοπός της πτυχιακής αυτής εργασίας είναι η ανάπτυξη μίας εφαρμογής για

κινητές συσκευές ( phones, phablets, tablets ) με λειτουργικό σύστημα Android

μέσω της οποίας θα είναι δυνατή η δημιουργία ειδοποιήσεων για λήψη

φαρμακευτικών σκευασμάτων από ανθρώπους κάθε ηλικίας και φύλου, με

απαράμιλλη απλότητα και ευκολία χρήσεως. Στόχος της παρούσας εργασίας

είναι η προσθήκη ακόμη μίας δωρεάν εφαρμογής στο Play Store, ή σε

οποιοδήποτε ιστότοπο διανέμονται εφαρμογές λειτουργικού συστήματος

Android, για τη μείωση των πιθανοτήτων αποτυχίας ενθύμισης λήψεως

οποιουδήποτε φαρμακευτικού σκευάσματος. Τη τεχνολογική εποχή την οποία

διανύουμε το μεγαλύτερο ποσοστό των ανθρώπων ανά το κόσμο έχει ένα έξυπνο

τηλέφωνο ( smartphone ) και εκεί ακριβώς ωθούμαι για τη παραπάνω εφαρμογή,

όπως και λοιποί δημιουργοί εφαρμογών, καθότι ο παραδοσιακός τρόπος

καταγραφής καθηκόντων σε μπλοκ, ντοσιέ αντιμετωπίζεται ως μία χρονοβόρα,

δαπανηρή και ανασφαλής τακτική, συνεπώς καταφεύγουμε στη χρήση των

κινητών συσκευών ως το προσωπικό μας θυσαυροφυλάκιο, organizer,

υπενθυμιτή.

1.2) Η απήχηση του Android OS και το μερίδιο της αγοράς

Το λειτουργικό Android της Google όντας το δημοφιλέστερο λειτουργικό τη στιγμή

αυτή με απήχηση 81% παγκοσμίως [ 1 ] και ένα 3% των λοιπών εταιρειών

παρεμφερών λειτουργικών συστημάτων Android ( CyanogenMod -

http://www.cyanogenmod.org/ ), είναι το λειτουργικό σύστημα με τις μεγαλύτερες

δυνατότητες τροποποίησης και ενσωμάτωσης νέων ιδιοαναπτυσόμενων

Page 9: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 7 από 150

εφαρμογών και βελτιστοποιήσεων με ενεργή συνδρομή από τους χρήστες του.

Παράλληλα, λόγω της ελεύθερης αυτής διανομής του υπάρχουν διαθέσιμες

κινητές τηλεφωνικές συσκευές με αρχική τιμή από 29 ευρώ κατασκευασμένες

στην Ινδία με βέβαια παλαιότερη έκδοση του λειτουργικού Android τη

Gingerbread 2.3.x ( Google ) και περιορισμένες δυνατότητες χρήσεως, λόγω

χαμηλής λειτουργικής μνήμης. Οι αναφερόμενες συσκευές προορίζονται κυρίως

για νέους και απείρους χρήστες της διαδικτυακής εμπειρίας και για

αναπτυσόμενες χώρες, π.χ. Αφρική.

Η τελευταία έκδοση του λειτουργικού Android της Google είναι η έκδοση Lollipop

5.0.2 [ 2 ], που παρουσιάστηκε τη 19η του Δεκέμβρη και είναι διαθέσιμη για τις

υποστηριζόμενες κινητές συσκευές που φέρουν τις ανάλογες απαιτήσεις σε

hardware και σαφώς των εταιρειών που έχουν παραμετροποιήσει το Lollipop

5.0.2 ούτος ώστε να είναι δυνατή η εκτέλεση του λειτουργικού από τις εκάστοτε

συσκευές της ανάλογης εταιρείας. Σύμφωνα με τις τελευταίες αναφορές [ 1 ]

υπάρχει αδυναμία υιοθέτησης, επέκτασης ή αναβάθμισης των παλαιότερων

κινητών συσκευών στη τελευταία έκδοση του λειτουργικού συστήματος, με

αποτέλεσμα οι εγγεγραμένες συσκευές στο Play Store με έκδοση Lollipop 5.0.x

να ανέρχονται σε 1,6%, οι αντίστοιχες του KitKat 4.4.x στο 39,7%, αντιστοίχως

και δημοφιλέστερη η JellyBean 4.x με 44,5%. Ακολουθούν η Ice Cream

Sandwich 4.0.x με 6,4%, η Gingerbread 2.3.x με 7,4% και τέλος η Froyo 2.2.x με

0,4%. Αξίζει να αναφερθεί ότι οι πωλήσεις συσκευών με λειτουργικό Android

ξεπέρασαν το συνολικό αριθμό πωλήσεων συσκευων με λειτουργικό Microsoft

Windows, iOS, Mac OS X το προηγούμενο έτος [ 1 ].

1.3) Ιστορική αναδρομή και τομείς εφαρμογής του λειτουργικού

Το λειτουργικό Android αλληλεπιδρά με το χρήστη βασιζόμενο σε αισθητήρες

επαφής, προσομοιώνοντας ανθρώπινες καθημερινές κινήσεις όπως “ χτύπημα ”

ή “ σύρσιμο ” επάνω στις οθόνες αφής που είναι εξοπλισμένες οι κινητές

Page 10: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

1 Παρουσίαση του Android OS

Σελίδα 8 από 150

συσκευές. Κατά την εκκίνηση του λειτουργικού σε μία συσκευή εμφανίζεται η

αρχική οθόνη, η οποία μπορεί να φιλοξενίσει πληθώρα συντομεύσεων

εφαρμογών και widget με αυτόματη ενημέρωση μέσω διαδικτύου για το

ηλεκτρονικό ταχυδρομείο του χρήστη, καιρικές συνθήκες κ.α. Η αρχική οθόνη

μπορεί να αποτελείται από περισσότερες από μία οθόνες με διαφορετική

εμφάνιση και χρήσεις, τις οποίες μπορεί ο χρήστης να εναλλάσει με απλό “

σύρσιμο ”. Επίσης στη κορυφή της οθόνης βρίσκεται η Status Bar ( μπάρα

κατάστασης ), την οποία μπορεί ο χρήστης να “ σύρει ” κατά πλάτος της οθόνης

αποκαλύπτοντας πληροφορίες συνήθως συνδεσιμότητας της συσκευής και από

την έκδοση JellyBean 4.1.x υποστηρίζονται εκτενέστερες ενημερώσεις για

αναπάντητες κλήσεις, ενημερώσεις από εφαρμογές και μερική παρουσίαση

κειμένου από το ληφθέν γραπτό μήνυμα. Εφόσον ο χρήστης έχει στη κατοχή του

μία συσκευή με λειτουργικό Android της Google, φέρει τη δυνατότητα λήψεως

εφαρμογών από το Play Store, ειδάλως είτε θα χρειαστεί να καταβάλει κάποιο

αντίτιμο χρήσεως της υπηρεσίας ή θα αναζητήσει άλλους ιστότοπους διανομής

εφαρμογών Android.

Η γέννεση για το λειτουργικό Android ξεκίνησε το 2003 από την εταιρεία Android

inc με ιδρυτές τους Andy Rubin, Rich Miner, Nick Sears και Chris White με στόχο

τη δημιουργία λειτουργικών συστημάτων για τη βελτίωση της εικονικής

απεικόνισης στις φωτογραφικές μηχανές. Ακολούθησε η σχεδίαση

ανταγωνιστικού λειτουργικού για κινητές συσκευές, ενάντια στα λειτουργικά

συτήματα Symbian και Microsoft Windows Mobile έως ότου εξαγοράστηκε από

τη Google, η οποία έφτασε στη πρώτη έκδοση του λειτουργικού Android, χάρη

σε εκτενέστερες συνεργασίες με προμηθευτές hardware & software, το 2008 με

το Alpha 1.0 [ 2 ]. Το έκδοση Alpha 1.0 χρησιμοποιήθηκε στο HTC Dream [ Εικόνα

3.1.] και υπήρξε υποστήριξη μέχρι και το Android Donut 1.6. Η Google είχε

αποφασίσει από το 2009 να δίνει ονόματα γλυκών στα λειτουργικά της

συστήματα. Το πρώτο κινητό τηλέφωνο της Google, παραγωγής HTC,

παρουσιάστηκε το 2010 και ήταν το Nexus One [ Εικόνα 3.2 ] με λειτουργικό

σύστημα το Android Eclair 2.1. Αυτή ήταν η εκκίνηση για τη σειρά Nexus με τη

τελευταία ναυαρχίδα Nexus 6 [ Εικόνα 3.3 ] phablet τηλεφωνική κινητή συσκευή

και τη Nexus 9 [ Εικόνα 3.4 ] ως tablet, οπως και συκευές για αλληλεπίδραση στις

Page 11: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 9 από 150

οθόνες τηλεοράσεων με το Android TV, στα οχήματα με το Android Auto και με

συσκευές που τις εξοπλιζόμαστε π.χ. ρολόι με το Android Wear. Παράλληλα

προσφέρει πληθώρα εφαρμογών βελτιστοποιήσης των δυνατοτήτων του

hardware κάθε κινητής συσκευής, όπως και εφαρμογές φωνητικής αναγνώρισης

[ 1 ], μεταφραστές και λεξικά κ.α. προς διευκόλυνση της ανθρώπινης

καθημερινότητας.

Εικόνα 1.3.1 – HTC Dream One Εικόνα 1.3.2 – Nexus One

Page 12: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

1 Παρουσίαση του Android OS

Σελίδα 10 από 150

Εικόνα 1.3.3 – Nexus 6 Εικόνα 1.3.4 – Nexus 9

1.4) Η αρχιτεκτονική του λειτουργικού συστήματος Android

Ο σχεδιασμός του Android βασίζεται στις γλώσσες προγραμματισμού C, C++ και

Java. Χρησιμοποιείται ένας μονολιθικός πυρήνας ( Linux Kernel ), μία

τροποποιημένη έκδοση του αντίστοιχου πυρήνα που χρησιμοποιείται στο

λειτουργικό σύστημα Linux. Το λειτουργικό Android είναι συμβατό με δύο

αρχιτεκτονικές, την ARM architecture ( ARMv7 μέχρι και την έκδοση KitKat 4.4.x,

ARMv8 από την έκδοση Lollipop 5.0.x ), όπως και (Intel)x86 ( 2012 ) και

αρχιτεκτονική MIPS.Η αρχιτεκτονική του λειτουργικού συστήματος Android

συνοψίζεται στη παρακάτω εικόνα. [ Εικόνα 1.4.1 ].

Page 13: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 11 από 150

Εικόνα 1.4.1 – Android Architecture

Συνεπώς το λειτουργικό Android δομείται από πέντε ομάδες με κάθετη ιεραρχία

και ανοδική εξέλιξη εξάρτησης. Οι ομάδες αυτές εν συντομία είναι:

Ο πυρήνας Linux (Linux Kernel)

Οι εγγενείς και οι προηγμένες βιβλιοθήκες (Libraries)

Η εικονική μηχανή Dalvik (Dalvik VM) - Android Runtime (ART) με

υποστήριξη 32bit & 64bit

Ο χρόνος εκτέλεσης (Android Runtime)

Το πλαίσιο εφαρμογής (Application Framework)

Page 14: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

1 Παρουσίαση του Android OS

Σελίδα 12 από 150

1.4.1) Linux Kernel

Η τροποιημένη έκδοση του πυρήνα του Linux, έχει βελτιστοποιηθεί για χρήση σε

κινητές συσκευές και υποστηρίζει βασικά πακέτα διεργασιών και λειτουργιών

όπως τη διαχείρηση της λειτουργικής μνήμης, τους οδηγούς της συσκευής, τη

διαχείρηση διεργασιών ( διεπαφών δικτύωσης, λειτουργικής ασφάλειας )

υποστηρίζοντας συνδεσιμότητα τυπου GSM, Bluetooth, GPRS, κ.α., όπως και

διάφορους αισθητήρες ( accelerometer, proximity, κ.α.).

1.4.2) Libraries

Οι βιβλιοθήκες χρησιμοποιούνται στο πλαίσιο του κώδικα του Android για τις

εμπεριεχόμενές τους λειτουργίες προσφέροντας τα επιθυμητά αποτελέσματα

στην εκάστοτε εφαρμογή. Οι βιβλιοθήκες εγγράφονται με τις γλώσσες

προγραματισμού C και C++ , που αποτελούν τα APIs (Application Programming

Interface). Άξιες αναφοράς είναι η βιβλιοθήκη Surface Manager, η οποία

διαχειρίζεται το σύστημα παραγωγής γραφικών σε πολλαπλές εφαρμογές. Η

βιβλιοθήκη SGL, η οποία ευθύνεται για τη δημιουργία των δυσδιάστατων

γραφικών και για τα τρισδιάστατα γραφικά οι βιβλιοθήκες OpenGL/ES.

Σημαντικότατη η βιβλιοθήκη SQLite για μια ισχυρή βάση δεδομένων που απαιτεί

κάθε καλή εφαρμογή.

1.4.3) Dalvik Debug Monitor Server & Android Run Time

Καθότι το σύνολο μίας εφαρμογής Android διέπεται από γλώσσα

προγραμματισμού Java, απαιτείται η χρησιμοποίηση της Java Virtual Machine (

JVM ). Επειδή όμως το παραγόμενο αποτέλεσμα δεν είναι αναγνωρίσιμο από το

Page 15: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 13 από 150

λειτουργικό σύστημα υπάρχει η Dalvic Virtual Machine, η οποία μετατρέπει το

παραγόμενο αποτέλεσμα από τη JVM σε αναγνωρίσιμο **.dex ( Dalvic

Executable ) εκτελέσιμο αρχείο. Ένα τέτοιο αρχείο δημιουργείται για κάθε

εφαρμογή και η εκτέλεση τους γίνεται παράλληλα για βέλτιστη απόδοση. Από το

Lollipop 5.0.x η Google προχώρησε σε αντικατάσταση του Dalvic Virtual Machine

με το project Volta στο Android Run Time ( ART ), το οποίο εναποθέτει τη

δημιουργία του εκτελέσιμου αρχείου αμέσως μετά την εγκατάσταση της εκάστοτε

εφαρμογής, το οποίο καλεί όποτε το απαιτεί ο χρήστης, εν αντιθέσει με το

προαναφερόμενο Dalvic που παράγει με κάθε κλήση νέο εκτελέσιμο αρχείο.

1.4.4) Android Run Time

Το Android Runtime ( ART ) αποτελεί το χρονικό πλαίσιο συνεργασίας του Dalvic

Virtual Machine, όπου απαιτείται, και των βιβλιοθηκών για να παράγουν το

αντίστοιχο αποτέλεσμα που απαίτησε ο χρήστης, είτε αυτό πρόκειται για μία ή

πολλαπλές εφαρμογές.

1.4.5) Application Framework

Στο Application Framework γίνεται η αλληλεπίδραση του συνόλου των

εφαρμογών, των υπηρεσιών των οποίων περιέχουν και των βασικών

βιβλιοθηκών του λειτουργικού συστήματος, με προυπόθεση να μην παραβιάζεται

η πολιτική ασφάλειας του Application Framework. Άξιες αναφοράς οντότητες στο

Application Framework είναι η View System, με τη οποία γίνεται η χρήση

πλαισίων, λιστών, checkboxes, κ.α.. Επίσης η Resource Manager, η οποία

ευθύνεται για οποιαδήποτε γραφική απεικόνιση στο αντίστοιχο περιβάλλον,

όπως και η Activity Manager η οποία αποθηκεύει το κύκλο ζωής της εκάστοτε

εφαρμογής και οποιεσδήποτε μεταβάσεις μεταξύ των φάσεών της. [ Εικόνα

1.4.5.1].

Page 16: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

1 Παρουσίαση του Android OS

Σελίδα 14 από 150

Εικόνα 1.4.5.1 – Android application Life Cycle

1.4.6) Applications

Το επίπεδο του Application είναι το πλαίσιο στο οποίο θα εισάγουμε το κώδικα

της προσδοκώμενης εφαρμογής μας.

1.5) Δυνατότητες φορητότητας εφαρμογών λειτουργικού Android σελοιπές πλατφόρμες

Μία εφαρμογή για λειτουργικό Android είναι δυνατόν να χρησιμοποιηθεί και σε

διαφορετικές πλατφόρμες είτε με επεκτάσεις ( extensions ) στο περιηγητή Crome,

ανάλογες για κάθε λειτουργικό σύστημα ( Mac OS, iOS, Windows, Windows

Mobile,κ.α. ) ή με εφαρμογές που περιέχουν Android προσομοιωτή ( emulator )

για το εκάστοτε λειτουργικό σύστημα. Παρατίθενται οι κορυφαίες και πιο

λειτουργικές επιλογές εφαρμογών για να επιτευχθεί η ζητούμενη φορητότητα

οποιασδήποτε εφαρμογής Android.

Page 17: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 15 από 150

1.5.1) Microsoft Windows Mobile

Δυστυχώς για τους κατόχους κινητών συσκευών με λειτουργικό Windows Mobile

δεν υπάρχει κάποιος τρόπος το ιδίο λειτουργικό να υποστηρίξει εφαρμογές

Android. Η Microsoft ανέφερε ότι προθυμοποιούταν να σχεδιάσει μία εφαρμογή

για να είναι εφικτή η υποστήριξη, όμως λόγω της αντιπαλότητας με τη Google και

την Apple και δεδομένου ότι το μερίδιο αγοράς του λειτουργικού της ( Windows

Mobile ) είναι πολύ χαμηλό και αντίστοιχο είναι το επίπεδο δημιουργίας

εφαρμογών για το λειτουργικό της σύστημα, δεν θα προχωρήσει στη

πραγματοποίηση της δυνατότητας αυτής, καθότι οι χρήστες θα χρησιμοποιούν

εφαρμογές από το Play Store και κανένας προγραμματιστής δεν θα ασχολείται

με τη δημιουργία εφαρμογών στη πλατφόρμα της Microsoft Windows Mobile [ 3

].

1.5.2) Blackberry OS

Ευτυχώς για τους χρήστες κινητών συσκευών λειτουργικού Blackberry, υπάρχει

εν μέρει μία λύση για τη χρησιμοποίηση εφαρμογών Android στη πλατφόρμα

τους. Προαπαίτηση για τη λειτουργική ευκολία αυτή είναι η έκδοση του

λειτουργικού τους να είναι από τη 10.2.x ή νεότερη. Εφόσον ικανοποιείται η

παράμετρος αυτή τότε κατεβάζοντας τη εφαρμογή Snap

(http://redlightoflove.com/snap/ ), την μεταφορτώνετε από τον οικιακό σας

υπολογιστή με χρήση καλωδίου τύπου USB, και το αντίστοιχο πρόγραμμα

διαχείρισης για τις συσκευές BlackBerry, στη κινητή σας συσκευή, την

εγκαθιστάτε και έπειτα απολαμβάνετε τις εφαρμογές Android μέσω της

εφαρμογής Snap ( παρέχεται πρόσβαση δίχως επιπλέον χρεώσεις στο Play

Store ).

Page 18: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

1 Παρουσίαση του Android OS

Σελίδα 16 από 150

1.5.3) iOS

Κάτοχοι iPhone και iPad, υπάρχει και για εσάς μία μερική λύση. Βάση της

απήχησης και διάχυσης του λειτουργικού και των κινητών συσκευών της Apple,

η εταιρεία Myriad προσφέρει την εφαρμογή Alien Dalvik (

http://www.myriadgroup.com/products/device-solutions/mobile-software/alien-

dalvik/ ), η ομοιότητα με την εικονική μηχανή του Android συμβαίνει καθότι είναι

παρόμοια με προσανατολισμένη αρχιτεκτονική για εκτέλεση σε περιβάλλον iOS,

το οποίο διατίθεται δωρεάν στο App Store και ο χρήστης, έπειτα από την

εγκατάσταση και έναρξη της εφαρμογής επιλέγει το “Connect ” και επιλέγει το “

Android Mobile Browser ”. Το μόνο αρνητικό είναι ότι πρέπει να βρείτε τα

εκτελέσιμα αρχεία των εφαρμογών Android ( *.apk ).

1.5.4) Mac OS X

Για παρόμοιους λόγους υπάρχει η δυνατότητα χρησιμοποίησης εφαρμογών

Android και στους υπολογιστές με λειτουργικό Mac OS, αφότου αναπτύχθηκε

από την Apple. Η αναφερόμενη εφαρμογή είναι η Genymotion (

https://www.genymotion.com/#!/download ), η οποία απαιτεί εγγραφή στο Cloud

Genymotion για να ληφθεί η εφαρμογή, καθότι δίνονται κωδικοί χρήσεως για την

εφαρμογή, απαιτείται λειτουργικό Mac OS X 10.6 ή ανώτερο. Εφόσον επιτευχθεί

η εγκατάσταση της εφαρμογής πρέπει να κατασκευάσετε μία εικονική συσκευή

και εφόσον εκπληρώσετε και αυτό το στάδιο έπειτα έχετε το δικό σας περιβάλλον

Android στο Mac σας περιβάλλον. Πάλι τα εκτελέσιμα αρχεία των εφαρμογών

Android ( *.apk ) πρέπει να τις εντοπίσετε μόνοι σας.

Page 19: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 17 από 150

1.5.5) Linux - Ubuntu

Η λειτουργία εφαρμογών Android σε περιβάλλον λειτουργικού Ubuntu

επιτυγχάνεται μέσω του περιηγητή Crome της Google, και μέσω της επέκτασης (

extension ) ARChon (http://www.omgubuntu.co.uk/2014/09/install-android-apps-

ubuntu-archon ). Απαιτείται έκδοση Crome 37 ή νεότερη και εφόσον

μεταφορτώσετε την επέκταση και ενεργοποιήσετε την επιλογή στις επεκτάσεις

του Crome “ για προχωρημένους ” πρέπει επακολούθως να φορτώσετε την

επέκταση χειροκίνητα και έπειτα να εισάγετε κάποιες γραμμές κώδικα για να

καταστεί λειτουργική η εφαρμογή που μεταφορτώσατε. Η διαδικασία είναι σχετικά

απλή και αφότου ικανοποιηθούν οι παραπάνω προϋποθέσεις η επέκταση

ARChon μπορεί να εγκατασταθεί, χειροκίνητα, με επιτυχία και να ανοίξετε τον

κόσμο του Android στο περιβάλλον του περιηγητή σας.

1.5.6) Microsoft Windows

Για τους χρήστες του λειτουργικού Windows XP ή ανώτερου, δεν θα μπορούσε

να είναι πιο εύκολη η πρόσβασή σας σε εφαρμογές Android. Η εφαρμογή που

χρειάζεστε είναι η BlueStacks ( http://www.bluestacks.com/ ), η οποία διατίθεται

δωρεάν, εγκαθίσταται με τέσσερα ( 4 ) κλικ επακριβώς και εμπεριέχει απευθείας

σύνδεση με το Play Store για να χρησιμοποιήσετε οποιαδήποτε εφαρμογή

επιθυμείτε.

Page 20: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

1 Παρουσίαση του Android OS

Σελίδα 18 από 150

1.5.7) Chrome OS

Λογικό είναι τα CromeBooks με Crome OS της Google να υποστηρίζουν

εφαρμογές Android. Η επέκταση ( extension ) που χρειάζεστε είναι το Twerk (

https://chrome.google.com/webstore/detail/twerk/jhdnjmjhmfihbfjdgmnappnoaeh

nhiaf ), το οποίο μετατρέπει τα εκτελέσιμα αρχεία των εφαρμογών Android ( *.apk

) σε ενεργές εφαρμογές στο Book σας και μάλιστα μπορείτε να την

παραμετροποιήσετε όπως επιθυμείτε. Εφόσον εγκαταστήσετε την επέκταση του

Twerk, έπειτα την εκκινείτε, επιλέγετε το ( *.apk ) αρχείο προς μετατροπή και το

παραγόμενο αποτέλεσμα θα είναι μια άλλη επέκταση την οποία θα πρέπει να

φορτώσετε χειροκίνητα στο Crome και έπειτα απολαμβάνετε την εφαρμογή σας.

Η διαδικασία και η μέθοδος είναι παρόμοια με αυτήν στο λειτουργικό Ubuntu.

1.5.8) Firefox OS

Τέλος, έχουμε το πιο πρόσφατο ελεύθερο λειτουργικό σύστημα της εταιρείας

Mozilla, το Firefox OS. Παρότι το πλήθος των υποστηριζόμενων κινητών

συσκευών είναι περιορισμένο ( https://www.mozilla.org/el/firefox/os/devices/ ) και

στο τύπο των smartphones μόνο, παρέχεται η δυνατότητα εκτέλεσης εφαρμογών

Android μέσω του Open Mobile ACL ( Application Compatibility Layer ). Πρόκειται

για μία πλατφόρμα διασύνδεσης, δίχως να επηρεάζει αισθητά τους πόρους και

τη διάρκεια της μπαταρίας της εκάστοτε συσκευής, παρέχοντας παράλληλα και

την εφαρμογή AppMall, η οποία περιέχει ευρύτατο φάσμα δωρεάν εφαρμογών

για όλα τα λειτουργικά συστήματα. Η λήψη (http://www.openmobileww.com/#!acl-

for-firefox-os/cw07) αυτής πραγματοποιείται με ένα ( 1 ) κλικ και απίστευτη

ευκολία έχετε πρόσβαση σε πολλαπλές εφαρμογές λειτουργικού Android.

Page 21: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Σελίδα 19 από 150

ΚΕΦΑΛΑΙΟ 2: Εξέταση παρόμοιων εφαρμογών

2.1) Προυπάρχουσες εφαρμογές και χρησιμότητα αυτών

Η καλύτερη ιδέα για μία εφαρμογή είναι ο εντοπισμός μίας ανάγκης προς κάλυψη

και η έξυπνη προσέγγιση αυτής, κοινώς καινοτομία. Οι εφαρμογές

δημιουργούνται για να καλύψουν ανθρώπινες ανάγκες σε κάποιο τομέα, ο κάθε

άνθρωπος μπορεί να αντιμετωπίζει διαφορετικά προβλήματα στον ίδιο τομέα,

συνεπώς παράγονται παρόμοιες εφαρμογές για κάποιο πρόβλημα με

διαφορετικά σημεία προσέγγισης και τρόπους λύσεις, από τις οποίες ο χρήστης

κινητής συσκευής λειτουργικού Android δύναται να επιλέξει αυτήν που επιλύει το

εκάστοτε πρόβλημά του. Δεν θα μπορούσε λοιπόν να διαφέρει και η εφαρμογή

για υπενθύμιση φαρμακευτικών σκευασμάτων. Παραθέτω πλήρη καταγραφή

συναφών εγγεγραμένων δωρεάν εφαρμογών στο Play Store της Google και

επιλέγω πέντε ( 5 ) εξ’ αυτών ως σημαντικότερες.

Ο συνολικός αριθμός αυτών ανέρχεται στις πενήντα πέντε ( 55 ) εφαρμογές και

είναι:

Όνομα Εφαρμογής Σύνδεσμος Play Store

Medicine Time! http://goo.gl/LzV0UY

Drugs.com Medication Guide http://goo.gl/kPzumq

Medicine Tracker http://goo.gl/kR6U5D

My PillBox(Meds&Pill Reminder) http://goo.gl/ZO8O3L

Medicine Alarm Reminder http://goo.gl/U7g7Jd

Medicine Man http://goo.gl/m3AvlI

Rx Medicine Reminder http://goo.gl/F15akt

Ιατρική Υπενθύμιση http://goo.gl/QTl7Fv

Page 22: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

2 Εξέταση παρόμοιων εφαρμογών

Σελίδα 20 από 150

Medicine Scheduler http://goo.gl/WLL2E0

Pill Reminder – Medicine Timer http://goo.gl/eTdSqT

Medicine Reminder http://goo.gl/mGUPag

Medicine Reminder Lite http://goo.gl/Om2Hp9

Medicine Remember http://goo.gl/3dpn0l

MediSafe Meds & Pill Reminder http://goo.gl/ubdZ5x

Med Helper Pill Reminder http://goo.gl/R6rrB7

Pill Reminder http://goo.gl/EMoCyg

AnyTimer Pill Reminder http://goo.gl/K1xqrW

Pill Reminder http://goo.gl/J8tAOM

Pill Organizer (Reminder) http://goo.gl/sQy5Wf

Pill (Medicine) Reminder http://goo.gl/sv5Iwk

MyPersonalNurse Pill Reminder http://goo.gl/PNCfQH

Med OClock Pill Organizer http://goo.gl/eUAMju

Get Pills http://goo.gl/4N1WcK

Pill Box http://goo.gl/B0HZDW

Pills on the Go http://goo.gl/fnjxfm

Pill Reminder http://goo.gl/x8Bo0R

Take a pills http://goo.gl/H76pW5

EZ Pill Reminder http://goo.gl/hQInLB

Pill Reminder – MedRem http://goo.gl/44ighG

Pill Reminder http://goo.gl/2rNPj4

Medica: Meds & Pills Reminders http://goo.gl/86VV5x

Visual Pill Reminders http://goo.gl/dYyJ87

Pill Manager http://goo.gl/NnyhUi

NFC Talking Pill Reminder http://goo.gl/EPtDka

Pillinator – Pille Erinnerung http://goo.gl/3mOGH1

Page 23: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 21 από 150

Πίνακας 2.1.1 – Προϋπάρχουσες εφαρμογές

2.2) Εφαρμογές με πληρέστερη κάλυψη

Οι πέντε ( 5 ) καλύτερες, κατά προσωπική μου άποψη είναι οι εξής:

Drugs.com Medication Guide ( http://goo.gl/kPzumq ), καθότι παρέχεται

υποστήριξη από το Android Froyo 2.2 και έπειτα, καλύπτοντας σχεδόν το

100% των ενεργών συσκευών εγγεγραμένων στο Play Store. Εκκινώντας

η εφαρμογή παρουσιάζει ένα ευρύ φάσμα από επιλογές από αναζήτηση

φαρμάκου με φωνητική υποστήριξη έως και ομάδες υποστήριξης,

τιμοκαταλόγους και έλεγχο συμπτωμάτων. Το μειονέκτημα είναι ότι απαιτεί

διαδικτυακή σύνδεση για κάθε λειτουργία του και δημιουργία λογαριασμού

στην αντίστοιχη εταιρεία. Δεν κρίνεται εύκολη η χρήση του και ιδίως για

χρήστες μη εξοικειωμένους με τη τεχνολογία.

AnyTimer Pill Reminder ( http://goo.gl/K1xqrW ) , επειδή το μέγεθος της

είναι 2,7 megabyte, παρέχεται υποστήριξη από το Android Froyo 2.2 και

επίσης καλύπτει σχεδόν το 100% των ενεργών συσκευών εγγεγραμένων

Pill Reminder http://goo.gl/XvgFd7

Did I Take the Pill http://goo.gl/duQaZ4

Pills Reminder Free – MedAlarm http://goo.gl/aqMqH9

Pill Reminder http://goo.gl/08ys5D

Medidoz Pill Reminder http://goo.gl/oAg11W

Pills Reminder http://goo.gl/1xLikB

Pill Reminder http://goo.gl/rrJgMX

Take your pills! http://goo.gl/XfmtUy

Med Minder http://goo.gl/frVAaX

Page 24: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

2 Εξέταση παρόμοιων εφαρμογών

Σελίδα 22 από 150

στο Play Store. Εκκινώντας την εφαρμογή εμφανίζονται οι τυχόν

προγραμματισμένες υπενθυμίσεις με ημερομηνία και ώρα. Με

παρατεταμένη επιλογή μίας εξ’ αυτών μπορεί η ειδοποίηση να

απενεργοποιηθεί, να υπερπηδηθεί η επόμενη ειδοποίηση ή να διαγραφεί.

Η προσθήκη φαρμάκων γίνεται από την μπάρα δράσεως ( action bar )

καθώς και πληθώρα ρυθμίσεων προτίμησης, όπως ήχος ειδοποίησης,

ενεργοποίηση δόνησης και φανού LED κατά την ειδοποίηση κ.α. Για τη

ρύθμιση υπενθύμισης προσφέρει είτε επανάληψη ανά χρονικά διαστήματα

με σταθερό χρόνο επανάληψης ή επαναλήψεις ανά χρονικά διαστήματα

καθορισμένα από το χρήστη. Η χρήση της είναι ελαφρώς φιλικότερη από

τη προηγούμενη, αλλά καθ’ όλα χρήσιμη για ένα μέτρια εξοικειωμένο

χρήστη.

My PillBox (Meds&Pill Reminder) ( http://goo.gl/ZO8O3L ), καθότι το

μέγεθος της είναι 1,9 megabyte, παρέχεται υποστήριξη από το Android

Froyo 2.2 και επίσης καλύπτει σχεδόν το 100% των ενεργών συσκευών

εγγεγραμένων στο Play Store. Εκκινώντας η εφαρμογή εμφανίζει την

τωρινή ημερομηνία και τέσσερις ( 4 ) επιλογές για ορισμό υπενθύμισης,

εμφάνιση της λίστας των ορισμένων φαρμάκων καθώς και πρόγραμμα

επόμενων συναντήσεων με ιατρούς, εφόσον το ορίσει ο χρήστης. Παρέχει

παράλληλα στη μπάρα δράσης ( action bar ) επιλογές τροποποιήσεων

προτίμησης, όπως τύπο ειδοποίησης, δόνηση μαζί με τόνο επιλογής από

λίστα κ.α. Στον ορισμό ειδοποίησης παρέχεται συγκεκριμενοποίηση τύπου

φαρμάκου ( κάψουλα, χάπι, κ.α. ) καθώς και διευκρίνιση για το είδος της

λήψεως. Σχετικά απλή στη χρήση με μεσαία απαίτηση εξοικείωσης από το

χρήστη.

Med Minder ( http://goo.gl/frVAaX ), αυτή η εφαρμογή είναι εξαιρετικό

παράδειγμα απλότητας και ευχρηστότητας. Το μέγεθός εξαιρετικά μικρό,

μόλις 193 kilobyte με υποστήριξη από Android Eclair 2.0. Αναμφισβήτητη

κάλυψη κάθε συσκευής με λειτουργικό Android ανά τον κόσμο.

Page 25: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 23 από 150

Εκκινώντας η εφαρμογή έχει τρεις ( 3) επιλογές ορισμός νέου φαρμάκου,

εμφάνιση της λίστας ορισμένων φαρμάκων, ρυθμίσεις και τις ενδεχόμενες

ειδοποιήσεις με την επιλεγμένη ώρα. Οι ρυθμίσεις περιλαμβάνουν τη

ρύθμιση ξυπνητηριού κατά την επιθυμία του χρήστη και επιλέγοντας τον

ορισμό νέου φαρμάκου, εμφανίζονται πλαίσια εισαγωγής ονόματος

φαρμάκου, επιλογή αριθμού επαναλήψεων με αντίστοιχη ρύθμιση ώρας,

όπως και ημερολογιακή διάταξη για επανάληψη. Με παρατεταμένη

επιλογή μίας υπενθύμισης, στην αρχική οθόνη, οδηγείται ο χρήστης στο

παράθυρο ορισμού νέου φαρμάκου, όπου και παραμετροποιεί ό,τι

επιθυμεί. Απόλυτα φιλικό γραφικό περιβάλλον και ελάχιστη ανάγκη

κατανόησης και εξοικείωσης με το πρόγραμμα από το χρήστη.

Pill Reminder ( http://goo.gl/3j2vYE ), πρόκειται για την απλούστερη

εφαρμογή του είδους της. Πολύ μικρή σε μέγεθος μόλις 210 kilobyte με

υποστήριξη από το Android Cupcake 1.5 και έπειτα. Εκκινώντας την

εφαρμογή εμφανίζονται τρία πλαίσια καθορισμού ώρα ειδοποιήσεως και

επιβεβαίωση αυτού με ένα κουμπί παραπλεύρως. Στη μπάρα δράσης (

action bar ) προσφέρεται η επιλογή των ρυθμίσεων βάσει των οποίων ο

χρήστης μπορεί να καθορίσει το χρονικό κύκλο επανάληψης, τον

επιθυμητό ήχο ειδοποίησης από μία λίστα και επιλογές δόνησης και

λυχνίας LED. Απόλυτα φιλική προς το χρήστη με μηδαμινές απαιτήσεις

γνώσεων, ίσως ό,τι κοντινότερο στη δική μου στοχευμένη εφαρμογή.

Page 26: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Σελίδα 24 από 150

ΚΕΦΑΛΑΙΟ 3: Ανατομία Android OS και MedReminder

Στο προκείμενο κεφάλαιο παρατίθενται η δομή μίας εφαρμογής σε λειτουργικό

Android, καθώς και τις ενδιάμεσες διεργασίες για την εκτέλεση μίας εφαρμογής,

όπως και τη πλατφόρμα υλοποίησης κώδικα Android της Google ( Android Studio

) με το προεισαχθέν πρόγραμμα HelloWorld. Τέλος, παρουσιάζεται η εφαρμογή

MedReminder ( Υπενθύμιση Φαρμάκων ).

3.1) Δομή μίας εφαρμογής Android σε προγραμματιστικό

περιβάλλον

Η ανατομία μίας εφαρμογής Android, σε προγραμματιστικό περιβάλλον

αποτελείται αποτελείτε από οκτώ ( 8 ) διαχειρίσημους φακέλους ( Eclipse ), ή στο

χρησιμοποιηθέν πρόγραμμα ( Android Studio ) από επτά ( 7 ) διαχειρίσημους

φακέλους.

Eclipse Android Studio Περιγραφή

src java Περιέχουν τα αρχεία *.java,

με τα οποία εκκινεί η

εφαρμογή μετά από

επιλογή του χρήστη

Page 27: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 25 από 150

gen Gradle Scripts Περιέχουν το *.R αρχείο, το

οποίο παράγεται και

ενημερώνεται αυτόματα

περιέχοντας όλους τους

χρησιμοποιήσιμους πόρους

στην εφαρμογή

bin Gradle Scripts Περιέχουν τα *.apk αρχεία,

που παράγονται κατά τη

διάρκεια της κατασκευής της

εφαρμογής και ό,τι άλλο

απαιτείται για

χρησιμοποίηση αυτής

res/drawable Res/drawable Περιέχουν εικόνες

διαφορετικής πυκνότητας

(*.png, etc) για την

υποστήριξη πολλαπλών

οθονών

res/layout res/layout Περιέχουν τα *.xml αρχεία

που περιλαμβάνουν το

εικονικό περιβάλλον του

χρήστη

res/menu res/menu Περιέχουν τα *.xml αρχεία

για τη διαχείριση της action

bar

Page 28: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 26 από 150

Πίνακας 3.1.1 – Δομή μίας εφαρμογής Android

3.1.1) Gradle Scripts

Τα Gradle Scripts αποτελούνται από έξι ( 6 ) διαχειρίσιμα αρχεία κειμένου σε

Groovy syntax (http://groovy-lang.org/ ) γραφή. Δύο εξ’ αυτών περιέχουν ένα

σύνολο εργαλείων κατασκευής της εφαρμογής και το άλλο του συνολικού project.

Αυτό, συμβαίνει διότι σε κάθε project του Android Studio μπορούν να περιέχονται

περισσότερες από μία εφαρμογές. Στο gradle script της εφαρμογής ορίζονται οι

εκδόσεις λειτουργικού Android ( συμβατότητας, παρούσας χρήσεως ), εξαρτήσεις

από πλεονάζουσες βιβλιοθήκες για διάφορες ανάγκες της εφαρμογής, καθώς και

το εργαλείο ProGuard, το οποίο χρησιμοποιείται στις διαδικασίες

αποσφαλμάτωσης και παραγωγής υπογεγραμένου εκτελέσιμου αρχείου ( *.apk

). Επίσης υπάρχει ένα αρχείο ( 1 ) ρυθμίσεων των scripts που εμπεριέχει τις

ενυπάρχουσες εφαρμογές και τα υπόλοιπα τρία ( 3 ) αφορούν τους κανόνες και

ρυθμίσεις του ProGuard [ 4 ].

Apply plugin: ‘com.android.application’

android {

compileSdkVersion 21

res/values res/values Περιέχουν τα *.xml αρχεία,

που περιέχουν πόρους

όπως strings, διγλωσσίες,

διαμετρήσεις, κ.α.

AndroidManifest.xml manifests Περιέχουν τα θεμελιώδη

χαρακτηριστικά της

εφαρμογής, καθώς και τη

συγκεκριμενοποίηση της

χρήσης των πόρων της (

content provider, κ.α.)

Page 29: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 27 από 150

buildToolsVersion “21.1.2”

defaultConfig {

applicationId “lamarko.android.helloworld”

minSdkVersion 15

targetSdkVersion 21

versionCode 1

versionName “1.0”

}

buildTypes {

release {

minifyEnabled true

proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’

}

}

}

dependencies {

compile fileTree(dir: ‘libs’, include: [‘*.jar’])

compile ‘com.android.support:appcompat-v7:21.0.3’

}

3.1.2) *.java αρχεία

Τα *.java αρχεία είναι οι δραστηριότητες, οι οποίες παραθέτονται σε επακόλουθο

υποκεφάλαιο. Άξιοι αναφοράς είναι οι χειριστές γεγονότων ( event handlers ), οι

οποίοι χρησιμοποιούνται για να συλλέξουν δεδομένα από τις δραστηριότητες του

χρήστη, από την εισαγωγή κειμένου, πίεση κουμπιών, κ.α.. Εν συντομία

παρατίθενται οι χειριστές δεδομένων με τις χρήσεις τους [ 4 ].

OnClickListener(): Καλείται όταν ο χρήστης πιέσει κάποιο κουμπί

OnLongClickListener(): Καλείται όταν ο χρήστης πιέσει κάποιο κουμπί για

παραπάνω από δύο δευτερόλεπτα

OnFocusChangeListener(): Καλείται όταν ο χρήστης πιέσει ή

αποδεσμεύσει κάποιο κουμπί της κινητής του συσκευής

Page 30: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 28 από 150

OnTouchListener(): Καλείται όταν ο χρήστης πιέσει/αποδεσμεύσει ή σύρει

το δάχτυλο του επάνω στην επιφάνεια της οθόνης

OnMenuItemClickListener(): Καλείται όταν ο χρήστης επιλέξει κάποια

επιλογή από το menu ή action bar

package lamarko.android.helloworld;

import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;

public class MainActivity extends ActionBarActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.menu_main, menu);return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {

// Handle action bar item clicks here. The action bar will

// automatically handle clicks on the Home/Up button, so long

// as you specify a parent activity in AndroidManifest.xml.

int id = item.getItemId();

//noinspection SimplifiableIfStatement

Page 31: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 29 από 150

if (id == R.id.action_settings) {

return true;

}

return super.onOptionsItemSelected(item);

}

}

3.1.3) AndroidManifest.xml

Οποιοσδήποτε πόρος χρησιμοποιηθεί στην εφαρμογή, πρέπει να δηλωθεί στο

Manifest καθότι η εφαρμογή μέσω αυτού “ επικοινωνεί ” η εφαρμογή με το

λειτουργικό Android. Κάθε πόρος λαμβάνει μοναδικό αναγνωριστικό αριθμό ( ID

). Οι αναφερόμενοι πόροι μπορεί να είναι υπηρεσίες ( Services ), πάροχος

περιεχομένου ( Content Provider ), προθέσεις ( Intents ), κ.α. Με τις δηλώσεις

αυτές γνωστοποιούνται στο λειτουργικό Android τα δικαιώματα που θα έχει η

εφαρμογή ( κοινή χρήση αρχείων & υπηρεσιών ), όπως και εάν μπορεί να

αλληλεπιδρά με έτερες εφαρμογές , καθώς και την ελάχιστη απαίτηση

λειτουργικού Android ( Eclipse – Android Studio στο Gradle Scipts ) [ 4 ].

<?xml version=”1.0” encoding=”utf-8”?>

<manifest xmlns:android=”http://schemas.android.com/apk/res/android”package=”lamarko.android.helloworld” >

<application

android:allowBackup=”true”android:icon=”@mipmap/ic_launcher”android:label=”@string/app_name”android:theme=”@style/AppTheme” >

<activity

android:name=”.MainActivity”android:label=”@string/app_name” >

<intent-filter>

<action android:name=”android.intent.action.MAIN” />

Page 32: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 30 από 150

<category android:name=”android.intent.category.LAUNCHER” />

</intent-filter>

</activity>

</application>

</manifest>

3.1.4) Values/String.xml

Ένα αρχείο stings.xml μπορεί να περιέχει ονομασίες άλλων string, ονομασίες

κουμπιών, λιστών κ.α.[ 4 ]

<resources>

<string name=”app_name”>HelloWorld</string>

<string name=”hello_world”>Hello world!</string>

<string name=”action_settings”>Settings</string>

</resources>

3.1.5 ) Menu.xml

Ένα αρχείο menu.xml μπορεί να περιέχει τις λειτουργίες που μπορεί να επιτελέσει

η μπάρα δράσης ( action bar ) , συνήθως πρόκειται για κουμπιά ρυθμίσεων και

σχετικών πληροφοριών σχετικά με την εφαρμογή [ 4 ].

<menu xmlns:android=”http://schemas.android.com/apk/res/android”xmlns:app=”http://schemas.android.com/apk/res-auto”xmlns:tools=”http://schemas.android.com/tools” tools:context=”.MainActivity”>

<item android:id=”@+id/action_settings” android:title=”@string/action_settings”android:orderInCategory=”100” app:showAsAction=”never” />

</menu>

Page 33: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 31 από 150

3.1.6) Layout.xml

Ένα layout.xml αρχείο περιέχει το εικονικό γραφικό περιβάλλον του χρήστη με

οποιαδήποτε αναπαράσταση στοιχείων έχει επιλέξει ο δημιουργός της εκάστοτε

εφαρμογής. Οποιοδήποτε γραφικό, εικονίδιο, σχήμα, κουμπί, λίστα εμφανίζεται

στην οθόνη σας είναι στοιχειοθετημένο σε αρχείο *layout.xml ( π.χ. συντομεύσεις

). Παρατίθενται είδη layout και είδη χειριστών ( κουμπιά ), που θα συναντήσετε

στις κινητές συσκευές σας και κώδικας της προυπάρχουσας εφαρμογής

HelloWorld! [ 4 ], [ 5 ].

Είδη Layout Περιγραφή

Linear Layout Το layout ευθυγραμμίζει στην οθόνη, τα στοιχεία που

περιέχει οριζόντια ή κάθετα, καθ’ επιλογήν του

δημιουργού

Relative Layout Το layout τοποθετεί τα στοιχεία που περιέχει σε σχετικές

θέσεις στη συμμετρία της οθόνης

Table Layout Το layout τοποθετεί τα στοιχεία που περιέχει σε σειρές

και στήλες

Absolute Layout Το layout επιτρέπει στο δημιουργό να τοποθετήσει σε

όποια θέση επιθυμεί τα ενυπάρχοντα στοιχεία

Frame Layout Το layout είναι ένα σύμβολο που κατόπιν επιλογής από

το χρήστη εμφανίζει ένα αντικείμενο

List View Το layout εμφανίζει μία λίστα με δυνατότητα κύλισης από

τα ενυπάρχοντα στοιχεία σε αυτό

Page 34: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 32 από 150

Grid View Το layout εμφανίζει τα περιεχόμενα στοιχεία του σε ένα

δυσδιάστατο πλέγμα με δυνατότητα κύλισης

Πίνακας 3.1.6.1 – Είδη Layout

Είδη χειριστών Περιγραφή

TextView Χειριστής που εμφανίζει στο χρήστη

προκαθορισμένο κείμενο

EditText Χειριστής που επιτρέπει εισαγωγή δεδομένων

στο χρήστη

AutoCompleteTextView Χειριστής που εμφανίζει λέξεις που ταιριάζουν με

τους χαρακτήρες που εισάγει ο χρήστης στο

EditText

Button Χειριστής που όταν πιεστεί εκτελείται μία

ενέργεια

ImageButton Χειριστής με γραφική απεικόνιση, που όταν

πιεστεί εκτελείται μία ενέργεια

CheckBox Χειριστής με δυνατότητα επιλογής/αποεπιλογής

αντικειμένου

ToggleButton Χειριστής με δυνατότητα επιλογής/αποεπιλογής

και φωτεινή ένδειξη

RadioButton Χειριστής με δυνατότητα επιλογής/αποεπιλογής

RadioGroup Σύνολο χειριστών RadioButton

ProgressBar Χειριστής που δείχνει τη πρόοδο ολοκλήρωσης

μίας διεργασίας

Spinner Χειριστής που εμφανίζει μία λίστα με αντικείμενα

προς επιλογή ενός εξ αυτών

Page 35: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 33 από 150

TimePicker Χειριστής που εμφανίζει την ώρα σε 12ωρη ή

24ωρη μορφή για να επιλέξει ο χρήστης

DatePicker Χειριστής που εμφανίζει την ημερομηνία για να

επιλέξει ο χρήστης

Πίνακας 3.1.6.2 – Είδη χειριστών

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”xmlns:tools=”http://schemas.android.com/tools” android:layout_width=”match_parent”android:layout_height=”match_parent”

android:paddingLeft=”@dimen/activity_horizontal_margin”android:paddingRight=”@dimen/activity_horizontal_margin”android:paddingTop=”@dimen/activity_vertical_margin”android:paddingBottom=”@dimen/activity_vertical_margin”

tools:context=”.MainActivity”>

<TextView android:text=”@string/hello_world” android:layout_width=”wrap_content”android:layout_height=”wrap_content” />

</RelativeLayout>

3.1.7) Drawable

Ένα αρχείο drawable περιέχει τις εικόνες ( *.png, *.gif, η και *.xml

προσαρμοσμένα σε bitmaps ) για την υποστήριξη πολλαπλών οθονών, τόσο στα

εικονίδια εκκίνησης της εφαρμογής όσο και αυτών που εμφανίζονται σε αυτήν.

Για να βρούμε το μέγεθος μίας οθόνης, αρκεί απλώς μετρήσουμε τη διαγώνιό της.

Το μέγεθος της οθόνης στις συμβατές συσκευές με λειτουργικό Android, έχει

καθοριστεί στα μεγέθη: μικρό ( 426 dp x 320 dp ), κανονικό ( 470 dp x 320 dp ),

μεγάλο ( 640 dp x 480 dp ) και πολύ μεγάλο ( 960 dp x 720 dp ). Με μεγέθη

ανάλυσης οθόνης ( συνολικός αριθμός φυσικών pixel ), για τα παλαιότερα

μοντέλα κινητών συσκευών να κυμαίνονται από 480 x 800 pixels και με νεότερα

Page 36: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 34 από 150

μοντέλα και με τη συνδρομή των tablets η μέγιστη ανάλυση κυμαίνεται στα 1920

x 1080 pixels. Η πυκνότητα ( dots per inch ) μίας οθόνης καθορίζεται από

διαμοιραζόμενα pixels στο φυσικό πλάτος και ύψος αυτής. Η Google έχει

καθορίσει τα επίπεδα πυκνότητας οθονών στις εξής κατηγορίες: χαμηλή ( 120dpi

), μεσαία ( 160dpi ), μεγάλη ( 240dpi ), πολύ μεγάλη ( 320 dpi), πολύ πολύ μεγάλη

( 480 dpi ) και, τέλος, πολύ πολύ πολύ μεγάλη ( 640 dpi ).

Η πυκνότητα μίας οθόνης έχει σημαντικό αντίκτυπο για την εμφάνιση των

εικονιδίων από μια προκείμενη εφαρμογή. Σε μία μικρής ανάλυσης οθόνη ένα

πλαίσιο κειμένου θα εμφανίζεται πολύ μεγαλύτερο από ότι θα έπρεπε και

αντιστοίχως πολύ μικρό σε μία οθόνη μεγαλύτερης πυκνότητας. Για το λόγο αυτό

πρέπει να χρησιμοποιούμε pixel ανεξάρτητης πυκνότητας ( density independent

pixel ) για να καθορίσουμε τις διαστάσεις του layout και τη θέση των εικονιδίων

χωρίς να επηρεάζονται από τη πυκνότητα της εκάστοτε οθόνης. Ένα ( 1 ) pixel

ανεξάρτητης πυκνότητας σε μία οθόνη 240 dpi ( dots per inch ) αντιστοιχεί σε 1,5

πραγματικά/φυσικά pixels ( pixels = dp * ( dpi / 160 ) ).

drawable - xxhdpi drawable – mdpi

3.1.8) Δραστηριότητες ( Activities )

Δραστηριότητα αποτελεί το περιβάλλον στο οποίο ένας χρήστης πληκτρολογεί

ένα γραπτό μήνυμα. Η επιλογή του παραλήπτη του μηνύματος αποτελεί μία

δεύτερη δραστηριότητα. Γενικότερα, δραστηριότητα είναι ένα γραφικό

περιβάλλον χρήστη ( user interface ). Μία εφαρμογή περιέχει τόσες

δραστηριότητες όσα είναι τα διαφορετικά περιβάλλοντα του χρήστη. Κάθε

εφαρμογή έχει ένα Κύκλο Ζωής, κατά τον οποίο διαχειρίζεται τις ανάλογες

δραστηριότητες για να π.χ. επαναφέρει την εφαρμογή στο τρέχων

παράθυρο/οθόνη του χρήστη. Παρακάτω παρατίθενται οι κλήσεις στο φάσμα

ζωής μίας εφαρμογής [ 5 ].

Page 37: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 35 από 150

Πίνακας 3.1.8.1 – Κλήσεις δραστηριοτήτων

3.1.9) Υπηρεσίες ( Services )

Μία υπηρεσία είναι μία διεργασία κάποιας εφαρμογής που εκτελείται παράλληλα

με λοιπές, δίχως αλληλεπίδραση με τη χρήση και αφορά διεργασίες που

επιθυμούμε να διατηρούνται ακόμη και όταν τεθεί σε αναμονή η δραστηριότητα,

η οποία την εκκίνησε. Π.χ. μία δημοφιλείς εφαρμογή για διαδικτυακό ραδιόφωνο,

το Tune in Radio στο οποίο εφόσον επιλέξουμε το σταθμό της αρεσκείας μας,

μπορούμε να αναγνώσουμε το μήνυμά μας δίχως να διακοπεί η ροή του

ραδιοφωνικού προγράμματος. Μία υπηρεσία, λοιπόν έχει δύο ( 2 ) φάσεις ζωής

και έξι ( 6 ) κλήσεις, οι οποίες παρατίθενται παρακάτω [ 5 ].

Κλήσεις Περιγραφή φάσης

onCreate() Η πρώτη κλήση, που γίνεται κατά την δημιουργία της

δραστηριότητας

onStart() Η κλήση, με την οποία η δραστηριότητα εμφανίζεται στην

οθόνη του χρήστη

onResume() Η κλήση, κατά την οποία ο χρήστης χρησιμοποιεί τη

δραστηριότητα

onPause() Κατά τη φάση αναμονής, έστω η Α δραστηριότητα της

εφαρμογής δεν είναι στο ενεργό παράθυρο της οθόνης του

χρήστη, έως ότου επανακληθεί όταν ο χρήστης θέσει σε

αναμονή την Β δραστηριότητα στην οποία βρισκόταν

onStop() Η κλήση, κατά την οποία η δραστηριότητα δεν είναι πλέον

ορατή στο χρήστη

onDestroy() Η κλήση με την οποία η διαδικασία καταστρέφεται από το

σύστημα

onRestart() Η κλήση μετά από την οποία επανεκκιννεί η δραστηριότητα

Page 38: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 36 από 150

Πίνακας 3.1.9.1 – Κλήσεις υπηρεσιών

3.1.10 ) Προθέσεις ( Intents )

Με τις προθέσεις γίνεται η μετάβαση από τη μία οθόνη ( γραφικό περιβάλλον )

του χρήστη στην επόμενη. Γεφυρώνουν, δηλαδή την επικοινωνία των

δραστηριοτήτων και των υπηρεσιών με δραστηριότητες και υπηρεσίες στην ίδια

εφαρμογή ή και σε άλλες, όπως και τη μεταφορά πληροφοριών ( π.χ. “ χτύπημα”

χρήστη σε επιλογή ) σε όποια εφαρμογή χρειάζεται. Οι προθέσεις

χρησιμοποιούνται σε όλες τις διεργασίες που επιτελούνται στο λειτουργικό

Android. Π.χ. όταν θέλετε να ανοίξετε μία φωτογραφία και έχετε δύο εφαρμογές

επεξεργασίας φωτογραφιών, η εφαρμογή που χρησιμοποιείτε για την προβολή

αυτής θα στείλει μαζί με την εντολή “άνοιγμα” και την ανάλογη πρόθεση για τη

Κατάσταση/Κλήση Περιγραφή

onCreate() Στη φάση αυτή καλείται από το σύστημα η υπηρεσία

χρησιμοποιώντας την onStartCommand()

onStartCommand() Η κλήση αυτή, υποκινούμενη από μία δραστηριότητα,

καλεί με τη σειρά της την StartService(), η οποία εκκινά

τη ζητούμενη υπηρεσία.

onBind() Η κλήση αυτή καλείται από το σύστημα, όταν κάποια

άλλη διεργασία ή δραστηριότητα θέλει να “δεθεί” με τη

παρούσα υπηρεσία, εκτελώντας την bindService()

onUnBind() Η κλήση αυτή χρησιμοποιείται όταν έχουν αποσυνδεθεί

όλες οι διεργασίες ή δραστηριότητες

onReBind() Η κλήση αυτή καλείται εφόσον στη παρούσα υπηρεσία

είχαν αποσυνδεθεί όλες οι δραστηριότητες/διεργασίες

και αιτούνται να συνδεθούν νέες

onDestroy() Στη φάση αυτή, η υπηρεσία δεν χρησιμοποιείται πλέον

και τερματίζει

Page 39: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 37 από 150

κατάλληλη επιλογή προγράμματος επεξεργασίας φωτογραφιών. Επίσης

υπάρχουν κατηγορίες προθέσεων οι Explicit Intents ( κυρίως για αναφορές

λειτουργίας της ίδια της εφαρμογής στην εφαρμογή ) και οι Implicit Intents (

προσθήκη δίχως καθορισμένη χρήση στην ίδια την εφαρμογή, χρήση για

ενεργοποίηση άλλων εφαρμογών ). Παράλληλα, υπάρχει ξεχωριστός τύπος

αντικειμένου προθέσεως για εφαρμογές ( Context.startActivity() ), υπηρεσίες (

context.startService() ) και δέκτες μετάδοσης ( Context.sendBroadcast() ) [ 4 ].

3.1.11) Δέκτες Μετάδοσης ( Broadcast Receivers )

Οι δέκτες μετάδοσης, γνωστοί και αυτοί ως intents, έχουν διαφορετικό

αρμοδιότητες από τις προθέσεις και μάλιστα αμφίδρομες. Οι δέκτες μετάδοσης

μπορούν να ειδοποιήσουν μία υπηρεσία ή μία δραστηριότητα μίας εφαρμογής ή

να λάβουν ενημέρωση από τις προαναφερθείσες και να οφείλουν να

ειδοποιήσουν λοιπές εφαρμογές για τη διεργασία που την εκκίνησε. Π.χ. υπάρχει

δέκτης μετάδοσης, ο γνωστότερος, ο οποίος μας ειδοποιεί όταν ολοκληρώνεται

η φόρτιση της μπαταρίας μας ( android.intent.action.BATTERY_CHARGED )

όπως και ο δέκτης αναφοράς σφάλματος μίας εφαρμογής

( android.intent.action.BUG_REPORT ) [ 4 ].

3.1.12) Πάροχοι Περιεχομένων ( Content Providers )

Ένας πάροχος περιεχομένου μεταφέρει δεδομένα από μία εφαρμογή σε άλλες

κατ’ απαίτηση. Διαφέρει από την προαναφερθείσα πρόθεση, καθότι ο πάροχος

περιεχομένου μεταφέρει δεδομένα στην εκάστοτε εφαρμογή που έχει εισαχθεί η

απαίτησή τους για μεταφορά κατά την εγγραφή της εφαρμογής. Τέτοια είδη

δεδομένων είναι οι τηλεφωνικές επαφές στη συσκευή σας, ή βάσεις δεδομένων

SQLite εφαρμογών[ 4 ].

Page 40: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 38 από 150

3.1.13) Θραύσμα ( Fragments )

Το θραύσμα είναι μία υποδραστηριότητα, η οποία εμφωλεύεται σε

δραστηριότητες και εμφανίζεται και εξαφανίζεται, έπειτα από αλληλεπίδραση με

το χρήστη στο γραφικό περιβάλλον της οθόνης της συσκευής του. Ένα θραύσμα

δεν καλύπτει πλήρως την οθόνη του χρήστη, εκτός εάν απαιτείται, μπορεί να

συνδιαστεί με έτερα θραύσματα στην ίδια δραστηριότητα, έχει δική του γραφική

απεικόνιση ( layout/*.xml ), όπως και δικό του κύκλο ζωής [ Εικόνα 3.1.13.1 ] [ 4

].

Εικόνα 3.1.13.1 – Fragment Life Cycle

Page 41: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 39 από 150

3.2) Πλατφόρμα προγραμματισμού Android Studio

Όπως προαναφέρθηκε, το επιλεχθέν πρόγραμμα ανάπτυξης του κώδικα είναι το

Android Studio, του οποίου η λήψη πραγματοποιείται από τον εξής σύνδεσμο -

https://developer .android.com/sdk/index.html - και η εγκατάσταση αυτής είναι

απλούστατη [ Εικόνα 3.2.1 ]. Εκτελείτε το μεταφορτωμένο αρχείο, επιλέγετε το

τόπο αποθήκευσης και επιτελείται η εγκατάσταση.

3.2.1) Εγκατάσταση εφαρμογής

Έπειτα στην ιστοσελίδα λήψεως, εμφανίζεται μία σειρά οδηγιών κατά την οποία

προτρέπεστε να προχωρήσετε σε λήψη του Java Development Kit (

http://www.oracle.com/technetwork/java/ javase/downloads/index.html ), το

οποίο θα είναι της ίδιας εκδόσεως με αυτή της Java που έχετε ήδη εγκατεστημένη

στον υπολογιστή σας ( πιο πρόσφατη Java 8 ). Αμέσως μετά, προτρέπεστε να

εκκινήσετε τον SDK Manager για να γίνει λήψη των ανάλογων Android SDK

Tools, Platform tools και Build tools. Υπάρχουν προεπιλεγμένες οι πιο

πρόσφατες εκδόσεις, όμως μπορείτε να επιλέξετε και παλαιότερες εκδόσεις του

Android ( π.χ. Android 4.1.2 Jelly Bean ). Επίσης στο τέλος του παραθύρου του

Android SDK, υπάρχει ο κατάλογος Extras, από τον οποίο πρέπει να επιλέξετε

το Google Support Library, Google Support Repository [ Εικόνα 3.2.1.1 ], [ Εικόνα

3.2.1.2 ].

Εικόνα 3.2.1 Εικόνα 3.2.1.1 Εικόνα 3.2.1.2

Page 42: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 40 από 150

3.2.2) Χρήση και περιγραφή οθόνης προγραμματιστή

Εφόσον περατωθούν τα παραπάνω βήματα, το Android Studio είναι έτοιμο να

δεχτεί το κώδικά σας. Σαν προυπάρχουσα εφαρμογή υπάρχει η HelloWorld. Στο

παράθυρο της εφαρμογής βλέπετε πολλαπλά παράθυρα και καρτέλες.

Περιμετρικά του παραθύρου υπάρχουν καρτέλες με διάφορες χρήσεις εκ των

οποίων οι βασικότερες είναι η Project και Gradle Console. Η μεν Project εμφανίζει

τη δομή της εφαρμογής σας και η δε Gradle Console εμφανίζει το αποτέλεσμα

του συγχρονισμού της εφαρμογής σας με το Gradle build tool, όπως και το

παράθυρο του Dalvik Debug Monitor Server με περιεχόμενα παράθυρα αυτά του

Logcat ( εργαλεία αποσφαλμάτωσης ) και το μητρώο συνδεδεμένων εικονικών

και φυσικών συσκευών. Στο άνω μέρος του κυρίου παραθύρου του Android

Studio υπάρχει σειρά καρτελών και εικονιδίων, από τα οποία μπορείτε να

προβείτε σε ενέργειες που εκτείνονται από δημιουργία νέας εφαρμογής, έλεγχος

κώδικα, αποσφαλμάτωσης, εκκίνησης της εφαρμογής, διαχείρισης εικονικών

συσκευών, κ.α. [ Εικόνα 3.2.2.1 ], [ Εικόνα 3.2.2.2]. [ 6 ]

Εικόνα 3.2.2.2 Εικόνα 3.2.2.1

Page 43: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 41 από 150

3.2.3) Δημιουργία μίας εφαρμογής και απαιτήσεις

Για δημιουργία νέας εφαρμογής, επιλέγετε File -> New Project και στο νέο

παράθυρο δημιουργίας εισάγετε το όνομα της εφαρμογής και διαχειρίζεστε το

τόπο αποθήκευσης αυτής. Έπειτα επιλέγετε το είδος των συσκευών που θέλετε

να υποστηρίζει η εφαρμογή σας και τη χαμηλότερη έκδοση Android που θέλετε

να υποστηρίζει η εφαρμογή σας. Προτείνεται η τελευταία έκδοση ( Lollipop 5.0.2

). Στη συνέχεια επιλέγετε μία δραστηριότητα για την εφαρμογή σας, εάν το

επιθυμείτε ή εάν γνωρίζετε το ακριβές πεδίο εφαρμογής της. Τυπικά επιλέγετε το

Blank Activity. Τέλος, ορίζετε το όνομα της δραστηριότητας, το τίτλο της

εφαρμογής καθώς και τις ονομασίες των γραφικών απεικονίσεων και των μενού

επιλογών. Με τον τρόπο αυτό έχετε δημιουργήσει μία εφαρμογή. Για να μπορέσει

όμως να εκτελεστεί μία εφαρμογή απαιτείται, εκτός από το Android Software

Development Kit που εγκαταστήσατε προγενέστερα, και μία συσκευή ( εικονική ή

φυσική ) στην οποία θα τρέξει η εφαρμογή σας [ Εικόνα 3.2.3.1 ], [ Εικόνα 3.2.3.2

], [ Εικόνα 3.2.3.3 ], [ Εικόνα 3.2.3.4 ].

Εικόνα 3.2.3.1 / 3.2.3.3 Εικόνα 3.2.3.2 / 3.2.3.4

Page 44: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 42 από 150

3.2.4) Δημιουργία εικονικής συσκευής

Για την δημιουργία μίας εικονικής συσκευής επιλέγετε το εικονίδιο διαχείρισης

εικονικών συσκευών στο άνω μέρος του παραθύρου του Android Studio. Στο

νέο παράθυρο επιλέγετε τη δημιουργία νέας εικονικής συσκευής και έπειτα

επιλέγετε το είδος της συσκευής ( phone, tablet, wear, TV ) που επιθυμείτε να

δημιουργήσετε και τις αντίστοιχες διαστάσεις μεγέθους, ανάλυσης και

πυκνότητας οθόνης. Τέλος, επιλέγετε την επιθυμητή έκδοση λειτουργικού

Android ( Lollipop 5.0.2 ) και πριν το τελικό κλικ αποεπιλέξτε το Use Host GPU.

Με τον τρόπο αυτό έχετε δημιουργήσει μία εικονική συσκευή για να εκτελεστεί σε

αυτή η εφαρμογή σας [ Εικόνα 3.2.4.1 ], [ Εικόνα 3.2.4.2 ], [ Εικόνα 3.2.4.3 ], [

Εικόνα 3.2.4.4 ].

Εικόνα 3.2.4.1 / 3.2.4.3 Εικόνα 3.2.4.2 / 3.2.4.4

Page 45: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 43 από 150

3.2.5) Δημιουργία περιεχόμενων αρχείων

Σε περίπτωση που θέλετε να δημιουργήσετε νέες κλάσεις java, γραφικές

απεικονίσεις ( layouts ), κ.ο.κ. αρκεί να έχετε εμφανή τη δομή της εφαρμογής σας

( Project καρτέλα ) και να επιλέξετε με δεξί κλικ τον υποφάκελο στον οποίο θέλετε

να δημιουργήσετε κάποιο νέο περιεχόμενο. Για παράδειγμα για τη δημιουργία

ενός νέου layout, αρκεί να επιλέξετε με δεξί κλικ τον υποφάκελο layout, να

σύρουμε το κέρσορα στην επιλογή New και έπειτα στο Layout resource file. Στο

νέο παράθυρο εισάγετε το επιθυμητό όνομα του layout και στην επιλογή root

element, εισάγετε το είδος του layout ( Linear Layout, Frame Layout, κ.α. ) που

επιθυμείτε. Αντιστοίχως για ένα θραύσμα ( fragment ) επιλέγετε με, πρώτα ένα

αριστερό κλικ τον υποφάκελο java και έπειτα με δεξί κλικ το πρώτο υποφάκελο.

Πάλι επιλέγετε New και σύρετε το κέρσορα στην επιλογή Fragments και Blank

Fragment. Εισάγουμε την επιθυμητή ονομασία και ολοκληρώθηκε η διαδικασία

της δημιουργίας. Παρόμοιες ενέργειες επιτελούνται και για τη δημιουργία

κλάσεων ( java class ). Παρατίθενται εικόνες από τη δημιουργία λοιπών επιλογών

[ Εικόνα 3.2.5.1 ], [ Εικόνα 3.2.5.2 ], [ Εικόνα 3.2.5.3 ], [ Εικόνα 3.2.5.4 ].

Εικόνα 3.2.5.1 Εικόνα 3.2.5.2

Page 46: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 44 από 150

Εικόνα 3.2.5.3 Εικόνα 3.2.5.4

3.2.6) Εκτέλεση και περάτωση σχεδιασμού μίας εφαρμογής

Για να εκκινήσει μία εφαρμογή, επιλέγετε το εικονίδιο στο άνω μέρος του

παραθύρου του Android Studio. Έπειτα εμφανίζεται το παράθυρο επιλογής

συσκευής ( φυσικής ή εικονικής ) [ Εικόνα 3.2.6.1 ] για να εγκατασταθεί η

εφαρμογή. Εάν πρόκειται για εικονική θα εμφανιστεί ένα νέο παράθυρο και θα

εκκινήσει η προδημιουργημένη εικονική συσκευή σας [ Εικόνα 3.2.6.2 ] και

αμέσως θα εμφανιστεί η εφαρμογή σας. Εφόσον η εφαρμογή σας εκτελείται δίχως

προβλήματα και επιπλέον επιθυμείτε να τη δημοσιεύσετε, πρέπει πρώτα να την

αποσφαλματώσετε με το εικονίδιο Debug [ Εικόνα 3.2.6.3 ] [ Εικόνα 3.2.6.4 ]

δίπλα από αυτό της εκτελέσεως της εφαρμογής, αφότου, όμως πρώτα

δημιουργήσετε ένα *.apk ( Android Application Package ). Η παραπάνω ενέργεια

επιτελείται επιλέγοντας από τη προαναφερθείσα σειρά καρτελών και εικονιδίων

με την επιλογή του Build και έπειτα του Generate Signed APK [ Εικόνα 3.2.6.5 ],

[ Εικόνα 3.2.6.6 ]. Οι προαναφερθείσες εργασίες παρατίθενται γραφικά, καθότι η

διαδικασία περατώσεως αυτών απαιτεί μεγαλύτερο επίπεδο γνώσεως και

εξοικείωσης με το πρόγραμμα [ 6 ].

Page 47: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 45 από 150

Εικόνα 3.2.6.1 Εικόνα 3.2.6.2

Εικόνα 3.2.6.3 - Εικόνα 3.2.6.4

Page 48: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 46 από 150

Εικόνα 3.2.6.5 - Εικόνα 3.2.6.6

3.3) Εργαλεία Αποσφαλμάτωσης ( Debugging )

Μετά το πέρας της ολοκλήρωσης της συγγραφής της εφαρμογής, απαιτείται από

το προγραμματιστή να δοκιμάσει τη λειτουργικότητα της εφαρμογής για τον

εντοπισμό και εξάλειψη ενδεχόμενων σφαλμάτων ( bugs ). Σε αντίθετη

περίπτωση, οι χρήστες που θα αποκτήσουν την αναφερόμενη εφαρμογή, όχι

μόνο θα δυσαρεστηθούν αλλά και θα έχουν μία εφαρμογή η οποία δεν επιτελεί

το ό,τι υπόσχεται. Ειδικότερα και όταν η εφαρμογή στοχεύει σε μία ευαίσθητη

κοινωνική ομάδα, κυρίως, θα πρέπει να είναι αψεγάδιαστη και δοκιμασμένη για

υποστήριξη σε πολλαπλές συσκευές/οθόνες και εξαντλώντας κάθε τρόπο

χρήσεως όσο απίθανος και αν είναι αυτός.

Η αποσφαλμάτωση λοιπόν επιτελείται με την εξής διαδικασία στο περιβάλλον

ανάπτυξης εφαρμογών IDE ( Integrated Development Enviroment ) Android

Studio. Στο εν λόγω πρόγραμμα έχουμε δυνατότητα να αποσφαλματίσουμε είτε

σε μία εικονική συσκευή ( AVD ), ή σε μία φυσική κινητή συσκευή με λειτουργικό

Android. Το Android Studio παρέχει, παράλληλα με την επιλογή συσκευής για

αποσφαλμάτωση και ορισμένα εργαλεία για να επιτελεστεί αυτή. Τέτοια είναι το

Android Debug Brigde ( abd ), το Dalvik Debug Monitor Server ( ddms ), τη

καταγραφή συμβάντων ( System Log ) και το Logcat. Η περιγραφή αυτών θα

Page 49: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 47 από 150

ακολουθήσει μετέπειτα. Για την αποσφαλμάτωση μίας εφαρμογής, το Android

Studio κατασκευάζει ένα αντίγραφο της μορφοποιημένης σε ( *.apk ) εφαρμογής

σας και την εγκαθιστά και την εκκινεί στην εικονική συσκευή ή φυσική συσκευή.

Εάν επρόκειτο για φυσική συσκευή απαιτείται ο ανάλογος οδηγός ( driver ) για να

αναγνωριστεί η συσκευή στον υπολογιστή σας. Εάν αυτή είναι συσκευή της

Google ( π.χ. Nexus 5 ), τότε ανοίγετε τα SDK – Tools και επιλέγετε και

μεταφορτώνετε το Google USB Driver, σε αντίθετη περίπτωση ( HTC One )

χρειάζεται να εγκαταστήσετε τον ανάλογο οδηγό για τη φυσική σας κινητή

συσκευή. Επίσης θα πρέπει να ενεργοποιήσετε την επιλογή για προγραμματιστές

-> USB Debugging, η οποία βρίσκετε σε μία υποκατηγορία των ρυθμίσεων της

φυσικής συσκευής σας.

Συνεχίζοντας με την αποσφαλμάτωση για την εκκινήσουμε, επιλέγετε την επιλογή

Debug στην γραμμή εργαλείων και εμφανίζεται το πλαίσιο επιλογής της

συσκευής που θα τελεστεί η αποσφαλμάτωση. Μετά την ολοκλήρωση της

αποσφαλμάτωσης της εφαρμογής, θα εμφανιστεί ένα παράθυρο με τρεις ( 3 )

καρτέλες. Η πρώτη με ονομασία Debugger θα περιλαμβάνει τις μεταβλητές και

λοιπά στοιχεία ( μεταβλητές από τις βιβλιοθήκες, κατασκευαστές, χειριστές, κ.α.

) που εμπεριέχει η εφαρμογή σας. Η επόμενη με όνομα Console θα εμφανίσει τις

πληροφορίες της συσκευής που χρησιμοποιήσατε, και η Τρίτη είναι η καρτέλα

του Logcat, ή οποία περιλαμβάνει τις πληροφορίες από τη καταγραφή γεγονότων

συστήματος. Εάν η χρήση του Logcat δεν αρκεί για τον εντοπισμό και εξάλειψη

των σφαλμάτων, τότε υπάρχει η δυνατότητα προγραμματισμού με σημεία

διακοπής ( Breakpoints ).

Ο προγραμματισμός με σημεία διακοπής συνδράμει στην αναλυτικότερη εξέταση

κάποιου σφάλματος. Για τεθεί ένα σημείο διακοπής, επιλέγετε στο αντίστοιχο

αρχείο τη γραμμή του κώδικα και πατάτε τη κίτρινη λυχνία εκ αριστερά της

γραμμής και επιλέγετε τη προσθήκη ενός σημείου διακοπής. Επιπλέον με τη

προσθήκη ενός σημείου διακοπής μπορείτε να εκτελέσετε την αποσφαλμάτωση

της εφαρμογής μέχρι εκείνο το σημείο για να βεβαιωθούμε ότι δεν δημιουργούνται

λοιπά σφάλματα ή, ακόμη και ολόκληρη την εφαρμογή. Για την επεξεργασία των

σημείων διακοπής αρκεί να επιλέξουμε το View Breakpoints και θα εμφανιστεί

Page 50: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 48 από 150

ένα παράθυρο, στο οποίο μπορείτε να εξετάσετε τις περιεχόμενες μεταβλητές και

κλήσεις κλάσεων και έπειτα να επανεκκινήσετε την εφαρμογή [ Εικόνα 3.3.1 ], [

Εικόνα 3.3.2] Εφόσον ολοκληρωθεί με επιτυχία η εξάλειψη των σφαλμάτων, η

εφαρμογή σας είναι έτοιμη να δημοσιευτεί ή να διαμοιραστεί στο αγοραστικό

κοινό [ 7 ].

Εικόνα 3.3.1 – Breakpoint Εικόνα 3.3.2 – Examine variables

3.3.1) Logcat

Παρατίθεται μία αναφορά για τη χρήση του εργαλείου Logcat. Το εργαλείο Logcat

χρησιμοποιείται για τη καταγραφή συμβάντων κατά της διαδικασία της

αποσφαλμάτωσης μίας εφαρμογής. Τα συλλεγόμενα δεδομένα προβάλλονται

στη προαναφερόμενη καρτέλα του Logcat. Εάν υπάρχει κάποιο σφάλμα στο

κώδικά σας θα εμφανιστούν ορισμένες εξαιρέσεις ( exceptions ) τις οποίες θα

πρέπει να διαχειριστείτε για να αγνοηθούν κατά την αποσφαλμάτωση και

μετέπειτα λειτουργία της εφαρμογής σας. Η ενδεχόμενες εξαιρέσεις ή

προβλήματα απεικονίζονται με χρωματικά με ανάλογα χρώματα για τη

σοβαρότητα του σφάλματος. Η συνηθέστερη εξαίρεση είναι η “

NullPointerException”, η οποία εμφανίζεται όταν γίνεται προσπέλαση κάποιας

μεταβλητής με όρισμα τιμής “Null”, δηλαδή μηδενική τιμή. Για να αντιμετωπίσουμε

τη συγκεκριμένη, δηλαδή να εντοπίσουμε το υπαίτιο αντικείμενο, αρκεί να

χρησιμοποιήσουμε τη κλάση Log, με την οποία θα εμφανίσουμε στο Logcat τις

ανάλογες πληροφορίες που χρειαζόμαστε από το συγκεκριμένο αντικείμενο που

Page 51: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 49 από 150

δημιουργεί την εξαίρεση. Υπάρχουν διάφορες μέθοδοι στη κλάση Logcat, κατά

συνθήκη με τις πληροφορίες που αναζητούμε.

a) Log.v(): verbose

b) Log.d(): debug

c) Log.i(): info

d) Log.w(): warn

e) Log.e(): error

Για τη συγκεκριμένη περίπτωση απαιτείται η Log.d() μέθοδος, η οποία θα μας

αποδώσει το περιεχόμενο ( null / not null ) του αναφερόμενου αντικειμένου με την

υπαγόμενη εξαίρεση. Για να γίνει αυτό στην αρχή της της τάξης με την εξαίρεση

προσθέτετε το private static final String TAG = “ Όνομα_Κλάσης ”; και έπειτα την

αρχικοποίηση της μεθόδου με Log.d(TAG,“ index” + I ); - ( Log.d ( string

αναφοράς, string είδος μηνύματος, throwable i), όπου I = null / not null) η οποία

θα εμφανίσει στο Logcat στην επόμενη δοκιμή αποσφαλμάτωσης το

περιεχόμενο του αναφερόμενου αντικειμένου σε τιμές null / not null [ Εικόνα

3.3.1.1 ] [ 8 ].

Εικόνα 3.3.1.1 – Logcat View

Page 52: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 50 από 150

3.3.2) Android Debug Bridge

Το Android Debug Bridge ( adb ) είναι ένα αφανές εργαλείο, το οποίο κάνει εφικτή

τη σύνδεση της εικονικής ή φυσικής συσκευής με το Android Studio. Πρόκειται

για ένα πρόγραμμα εξυπηρετητή – πελάτη με τρία ( 3 ) λειτουργικά μέρη.

1) Μία πλατφόρμα πελάτη, η οποία ενυπάρχει στα εργαλεία του Android

Studio και πιο συγκεκριμένα στο φάκελο του Software Development Kit

στον υπολογιστή σας. Η πλατφόρμα αυτή ενεργοποιείται είτε αυτόματα

από κάποια κλήση εικονικής ή φυσικής συσκευής είτε χειροκίνητα, όπως

θα δούμε παρακάτω.

2) Μια πλατφόρμα εξυπηρετητή, η οποία εκτελείται στο παρασκήνιο και

ευθύνεται για τη επικοινωνία μεταξύ του πελάτη και του adb deamon (

δαίμονα ), η οποία με τη σειρά της εκτελείται στην εικονική ή φυσική

συσκευή.

3) Τέλος ένα δαίμονας ( deamon ), ο οποίος εκτελείται σε κάθε εικονική ή

φυσική συσκευή που χρησιμοποιείται από το Android Studio.

Κατά την εκκίνηση ενός adb πελάτη ( συσκευή ), αναζητεί έναν ενεργό adb

εξυπηρετητή και σε περίπτωση που δεν υπάρχει ένας, δημιουργείται. Κατά τη

δημιουργία του ο εξυπηρετητής συνδέεται με τη τοπική θύρα TCP ( Transmission

Control Protocol ) 5037, στην οποία επικοινωνεί με κάθε πλατφόρμα adb πελάτη.

Έπειτα ο εξυπηρετητής εδραιώνει επικοινωνία με τους υπάρχοντες adb πελάτες,

εφόσον υπάρχει σε αυτές ένας adb δαίμονας, ελέγχοντας σειριακά ένα εύρος

θυρών ( 5555 – 5585 ) στις οποίες λειτουργούν το σύνολο των εικονικών και

φυσικών συσκευών. Αφότου επιτευχθεί η σύνδεση των adb πελατών με τον adb

εξυπηρετητή, παρέχεται πλήθος εντολών για την αμεσότερη και πληρέστερη

διαχείριση των συσκευών. Ενδεικτικά παρατίθεται η εντολή για την εκτέλεση της

προεπιλεγμένης εφαρμογής στο Android Studio.

Adb –s emulator-5556 install helloWorld.apk

Page 53: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 51 από 150

Η εντολή είναι η adb [ - d | - e | - s <serialNumber> ] <command>,

όπου - d είναι μία απευθείας εντολή στη μοναδική συνδεδεμένη φυσική συσκευή,

η –e είναι η απευθείας εντολή στη μοναδική εικονική συσκευή και η –s

<serialNumber> που είναι η απευθείας εντολή σε μία φυσική / εικονική συσκευή

με τον ανάλογο σειριακό αριθμό σύνδεσής της [ 9 ].

3.3.3) Dalvik Debug Monitor Server

Ακόμη ένα εργαλείο για την αποσφαλμάτωση εφαρμογών που προσφέρει το

Software Development Kit του Android, είναι το Dalvik Debug Monitor Server (

DDMS ), το οποίο προσφέρει μεταξύ άλλων υπηρεσιών, το εργαλείο Logcat,

παρέχει φωτογραφία του παραθύρου του DDMS, προσομοιώνει δεδομένα

θέσεων, παρέχει πληροφορίες εισερχομένων κλήσεων και των διεργασιών και

νημάτων ( threads ) [ Εικόνα 3.3.3.1 ].

Εικόνα 3.3.3.1 – DDMS with Debugger

Page 54: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 52 από 150

Στο πλαίσιο ασφάλειας και ιδιωτικότητας των δεδομένων της κάθε εφαρμογής,

δημιουργείται μία εικονική μηχανή ( Virtual Machine ) για κάθε πακέτο διεργασίων

της εκάστοτε εφαρμογής. Κάθε εικονική μηχανή έχει το δική της μοναδική θύρα

σύνδεσης με έναν αποσφαλματωτή.

Εκκινώντας ο DDMS συνδέεται με το adb ( Android Debug Bridge ). Κατά τη

σύνδεση μία συσκευής ( εικονική / φυσική ), μία ενυπάρχουσα εικονική μηχανή

που ελέγχει την επικοινωνία μεταξύ DDMS και adb, ειδοποιεί το DDMS για το

πότε μία εικονική μηχανή στη συνδεδεμένη συσκευή εκκινά και πότε

εγκαταλείπεται. Εφόσον λειτουργεί κάποια εφαρμογή στη συνδεδεμένη συσκευή

και συνεπώς λειτουργεί και η εικονικής της μηχανή, ο DDMS λαμβάνει το

μοναδικό αναγνωριστικό ( ID ) της εικονικής μηχανής, μέσω του adb και έπεται η

σύνδεση ενός απασφαλματωτή με την εικονική μηχανή, μέσω του adb δαίμονα

που θα πρέπει να υπάρχει στη συσκευή. Με τον τρόπο αυτό μπορεί, πλέον, να

επικοινωνήσει η εικονική μηχανή της εφαρμογής με το DDMS.

Ο DDMS μπορεί να διαχειρίζεται πληροφορίες από πολλαπλούς

αποσφαλματωτές ενώ, όπως προαναφέρθηκε, η εικονική μηχανή μίας

εφαρμογής δέχεται μόνον ένα αποσφαλματωτή. O DDMS αναθέτει

αποσφαλματωτές στις μοναδικές θύρες των εικονικών συσκευών με αύξων

σειριακό αριθμό 8600 κ.ο.κ., στους οποίους μεταφέρονται όλα τα δεδομένα των

αντιστοίχων εικονικών μηχανών. Παράλληλα ο DDMS διαθέτει μία έτερη

προεπιλεγμένη θύρα επικοινωνίας ( 8700 ) στην οποία εφόσον τοποθετηθεί

αποσφαλματωτής υπάρχει η δυνατότητα να μεταφερθούν στη θύρα αυτή τα

δεδομένα από όλες τις εικονικές μηχανές των διαφόρων εφαρμογών σε μία

συσκευή και να αποσφαλματωθούν στη θύρα αυτή [ 10 ].

Page 55: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 53 από 150

3.4) Η δομή της εφαρμογής MedReminder

Η εφαρμογή MedReminder αποτελείται από τέσσερα ( 4 ) αρχεία layout resource,

δύο ( 2 ) αρχεία menu resource, οκτώ ( 8 ) κλάσεις, δύο ( 2 ) αρχεία value resource

/ strings, καθώς και τα αναμενόμενα αρχεία στον υποφάκελο values dimens και

styles, όπως και τις drawable icons ( *.png ) και το AndroidManifest και το τέλος

τα Gradle Scripts. Επιπλέον παρατίθεται σε πλήρη έκταση το κάθε μέρος του

κώδικα στο κεφάλαιο του παραρτήματος. Οφείλω να αναφέρω τη χρησιμότητα

του Android Lint, εργαλείο πρόβλεψης εισαγωγής κώδικα, της πλατφόρμας

Android Studio.

3.4.1) Gradle Script – module: app

Στο Gradle script για τη συγκεκριμένη εφαρμογή παρατίθενται οι πληροφορίες

για την έκδοση του λειτουργικού Android στην οποία σχεδιάστηκε η εφαρμογή (

21 – Lollipop 5.0.x ), τη συμβατότητα του ισχύοντος σχεδιασμού έως και την

έκδοση 14 – Ice Cream Sandwich 4.0.x, καθώς και τη δυνατότητα

αποσφαλμάτωσης μέσω της τιμής “ true ” των proguardFiles και τέλος, δηλώνεται

η προσθήκη της βιβλιοθήκης υποστηρίξεως “ support-v4 ” για π.χ. για χρήση

θραυσμάτων ( fragments ).

apply plugin: 'com.android.application'

android {compileSdkVersion 21

buildToolsVersion "21.1.2"

defaultConfig {applicationId "lamarko.android.medicinereminder"

minSdkVersion 14

targetSdkVersion 21

Page 56: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 54 από 150

versionCode 1

versionName "1.0"

}buildTypes {

release {minifyEnabled trueproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-

rules.pro'

}}

}

dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])compile 'com.android.support:appcompat-v7:21.0.3'

compile "com.android.support:support-v4:21.0.3"

}

3.4.2) AndroidManifest

Στο αρχείο του AndroidManifest προστίθενται το σύνολο των κλήσεων ( intents,

receivers, κ.α. ) που πρέπει να δηλωθούν, εφόσον επιθυμείται η χρήση τους. Εν

προκειμένου στο παρακάτω απόσπασμα ζητείται, με σειρά παράθεσης η άδεια

να επαναρυθμίζονται αυτόματα οι ώρες ειδοποίησης για τις δεδομένες,

εγγεγραμένες υπενθυμίσεις του χρήστη, έπειτα η άδεια να χρησιμοποιηθεί ο

μηχανισμός δονήσεως για την ειδοποίηση του χρήστη και τέλος ο μηχανισμός (

intent ) μέσω του οποίου η εφαρμογή μπορεί να σημάνει μία ειδοποίηση για το

χρήστη.

<uses-permission

android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Page 57: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 55 από 150

<uses-permission

android:name="android.permission.VIBRATE" />

<uses-permission

android:name="android.permission.SET_ALARM" />

Έπειτα υπάγονται οι αντίστοιχες κλήσεις για την εφαρμογή, η οποία περιέχει δύο

( 2 ) δραστηριότητες. Με σειριακή έκθεση αποτυπώνονται το εικονίδιο, ονομασία

και οπτικό θέμα της εφαρμογής, ακολουθούμενα από το όνομα της πρώτης

δραστηριότητας με τη ακόλουθη πρόθεση < intent-filter > δήλωσης ότι η

δραστηριότητα αυτή θα πρέπει να εμφανίζεται στο χρήστη, όταν εκκινεί η

εφαρμογή. Ακολουθεί η δεύτερη δραστηριότητα, η οποία δηλώνει ότι εκκινεί μέσω

της πρώτης δραστηριότητας και μέσω του < meta-data > πεδίου επιστρέφει και

δεδομένα στη γονεϊκή, πρώτη δραστηριότητα. Στη συνέχεια υπάρχει το πεδίο των

υπηρεσιών < services > στο οποίο αναφέρεται η κλάση ( NotificationService )

μέσω της οποίας καλείται και χρησιμοποιείται η δυνατότητα ειδοποίησης του

χρήστη. Καταληκτικά στο πεδίο του δέκτη < receiver > καλείται η κλάση

OnBootReceiver, και έπειτα με μία πρόθεση < intent-filter >, η οποία ειδοποιεί το

δέκτη ότι επιτελέστηκε η εκκίνηση του λειτουργικού συστήματος.

<application

android:allowBackup="true"android:icon="@drawable/medr"android:label="@string/app_name"android:theme="@style/AppTheme" >

<activity

android:name=".MedListActivity"android:label="@string/app_name" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

Page 58: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 56 από 150

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity

android:name=".NewMedReminder"android:label="@string/title_activity_new_reminder"android:parentActivityName=".MedListActivity" >

<meta-data

android:name="android.support.PARENT_ACTIVITY"android:value=".MedListActivity" />

</activity>

<service

android:name="lamarko.android.medicinereminder.NotificationService" />

<receiver

android:name=".OnBootReceiver" >

<intent-filter>

<action

android:name="android.intent.action.BOOT_COMPLETED" />

</intent-filter>

</receiver>

</application>

Page 59: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 57 από 150

3.4.3) Drawable

medr – xxhdpi medr – mdpi

3.4.4) Values

Στο φάκελο values περιέχονται τα αρχεία dimens.xml / strings.xml / styles.xml.

Στο dimens.xml ορίζονται strings με προρυθμισμένες τιμές, που σκοπό έχουν την

ομοιόμορφη διευθέτηση των παραμέτρων των layout.

<resources>

<!-- Default screen margins, per the Android Design guidelines. -->

<dimen name="activity_horizontal_margin">16dp</dimen>

<dimen name="activity_vertical_margin">16dp</dimen>

<dimen name="font_size">15sp</dimen>

</resources>

Στο Styles.xml ορίζονται οι γραφικές απεικονίσεις των layout και των menu.

<resources>

<!-- Base application theme. -->

<style name="AppTheme"parent="Theme.AppCompat.Light.DarkActionBar">

<!-- Customize your theme here. -->

Page 60: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 58 από 150

</style>

</resources>

Στο Strings.xml περιέχονται strings, τα οποία περιέχουν επιθυμητά σύνολα

αλφαριθμητικών τιμών για πληροφόρηση και καθοδήγηση του χρήστη. Στη

παρούσα εφαρμογή παρέχεται υποστήριξη στην αγγλική και ελληνική γλώσσα.

Αγγλική γλώσσα

<resources>

<string name="app_name">MedReminder</string><string name="action_settings">Settings</string><string name="title_activity_new_reminder">New

Reminder</string><string name="add_medicine">Add Medicine Reminder</string><string name="title">Name of Medicine</string><string name="date">Date</string><string name="add_med">Add Med</string><string name="time">Time</string><string name="repeatloop">Choose usage times</string><string name="eighthours">Every 8h</string><string name="twelvehours">Every 12h</string><string name="twentyfourhours">Every 24h</string><string name="rep_loops">Repeating Loops</string><string name="not_8h">Every 8h for your</string><string name="not_12h">Every 12h for your</string><string name="not_24h">Every 24h for your</string><string name="not_now">Prepare and take your</string><string name="not_1h">One hour until your</string>

</resources>

Page 61: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 59 από 150

Ελληνική γλώσσα

3.4.5) Menu

Η ύπαρξη των δύο ( 2 ) αρχείων menu δεν έχει ουσιαστική σημασία, καθότι στη

προκείμενη εφαρμογή δεν χρησιμοποιείται η μπάρα δράσης ( action bar ), καθώς

οι ενέργειες επιτελούνται με κουμπιά ( buttons ). Το med_menu.xml και

new_med_menu.xml έχουν το ίδιο περιεχόμενο, παρατίθενται εν συντομία. Το id

πρόκειται για το αναγνωριστικό του αντικειμένου της μπάρας και το (

android:showAsAction= “never” ) απαγορεύει την εμφάνιση αυτού στην

εφαρμογή.

<item

android:id="@+id/action_settings"android:orderInCategory="100"app:showAsAction="never"android:title="@string/action_settings"/>

<resources>

<string name="app_name">MedReminder</string><string name="action_settings">Ρυθμίσεις</string><string name="title_activity_new_reminder">New

Reminder</string><string name="add_medicine">Προσθήκη Υπενθύμισης

Φαρμάκου</string><string name="title">Όνομα Φαρμάκου</string><string name="date">Ημ/νία</string><string name="add_med">Προσθήκη Υπενθύμισης</string><string name="time">Ώρα</string><string name="repeatloop">Επιλογές Επανάληψης</string><string name="eighthours">Κάθε 8 ώρες</string><string name="twelvehours">Κάθε 12 ώρες</string><string name="twentyfourhours">Κάθε 24 ώρες</string><string name="rep_loops">Καθορισμένες Επαναλήψεις</string><string name="not_8h">Κάθε 8 ώρες για το</string><string name="not_12h">Κάθε 12 ώρες για το</string><string name="not_24h">Κάθε 24 ώρες για το</string><string name="not_now">Λάβετε το</string><string name="not_1h">Ακόμη μία ώρα για το</string>

</resources>

Page 62: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 60 από 150

3.4.6) Layout

Υπάρχουν τέσσερα ( 4 ) layout στην εφαρμογή, το med_list.xml, το

med_list_fragment.xml, το new_med.xml και το new_med_fragment.xml. Θα

παρατεθούν αντιστοίχως με τη σειρά εμφάνισης.

Το med_list.xml περιέχει ένα < Frame Layout >, με το μοναδικό αναγνωριστικό (

id ) για το layout, με τις διαστάσεις του Frame Layout ( width, height ) να

ταυτίζονται με το μέγεθος της οθόνης ( match_parent ). Το layout αυτό θα

αποτελούσε το αρχικό layout της εφαρμογής, όμως λόγω της χρήσεως του

PlaceHolderFragment λαμβάνει τα ινία το ακόλουθο. Τέλος περιέχει το (

tools:ignore= “MergeRootFrame” ) στοιχείο που αποτρέπει το Android Lint να

εμφανίσει μήνυμα σφάλματος.

<FrameLayout

xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="lamarko.android.medicinereminder.NewMedReminder"tools:ignore="MergeRootFrame" />

Το med_list_fragment.xml περιέχει < Linear Layout >, με το αντίστοιχο ( id ) και

αντίστοιχες διαστάσεις πλάτους / μήκους να κατακλείουν την οθόνη. Για την

τοποθέτηση των αντικειμένων ( orientation ) στο layout χρησιμοποιείται κάθετη (

vertical ) τακτοποίηση και αποδίδεται χρώμα φόντου χρυσό. Το συγκεκριμένο

layout είναι το αρχικό layout όταν εκκινεί η εφαρμογή. Έπειτα υπάρχει ένα κουμπί

( button ) με αντίστοιχο μοναδικό αναγνωριστικό id για το κώδικα, διαστάσεις

ύψους / πλάτους, όπου το ύψους περικλύει το περιεχόμενο ( wrap_content )

αυτού και το πλάτος σε όλο το μήκος της οθόνης ( match_parent ). Έπειτα κατά

το πάτημά του ( onClick= “NewReminder” ) δηλώνεται η μέθοδος στην οποία θα

Page 63: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 61 από 150

κατευθυνθεί με τις ανάλογες ακολουθούμενες ενέργειες. Ακολουθεί ένα πλαίσιο

απλής απεικόνισης γραμμής ( holo_orange_light ) με οριοθέτηση διακένων (

marginBottom, marginTop ) σε density independent pixels ( 7dip, 10dip ).

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/linlayout_main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="#F5F5DC"

tools:context="lamarko.android.medicinereminder.MedListActivity$PlaceholderFragment" >

<Button

android:id="@+id/add_med"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="NewReminder"android:text="@string/add_medicine" />

<View

android:layout_width="fill_parent"android:layout_height="3dip"android:layout_marginBottom="7dip"android:layout_marginTop="10dip"android:background="@android:color/holo_orange_light" />

Εν συνεχεία υπάρχει νέο εμφωλευμένο < Linear Layout > με παρόμοια

χαρακτηριστικά δόμησης με αυτά του αρχικού, του οποίου η χρήση αφορά τις

ήδη υπάρχουσες ειδοποιήσεις. Έχοντας κλείσει το προηγούμενο Linear Layout,

Page 64: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 62 από 150

εμφωλεύεται εκ νέου έτερο < Linear Layout > με τις διαστάσεις αυτού να

επικαλύπτουν τη διαθέσιμη οθόνη και τη προσθήκη μίας εικόνας ( ImageView ),

η οποία λαμβάνει τροποποίηση για να εμφανίζεται στο μέσο της διαθέσιμης

οθόνης ( scaleType= “fitCenter” ) και δυνατότητα προσαρμοστικότητας σε

πιθανές αλλαγές του διαθέσιμου χώρου στην οθόνη ( adjustViewBounds= “true”

).

<LinearLayout

android:id="@+id/layout_dump"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" >

</LinearLayout>

<LinearLayout

android:layout_width="fill_parent"android:layout_height="fill_parent">

<ImageView

android:layout_width="fill_parent"android:layout_height="fill_parent"android:adjustViewBounds="true"android:scaleType="fitCenter"android:src="@drawable/main_pic"/>

</LinearLayout>

</LinearLayout>

Το new_med.xml είναι πανομοιότυπο με το med_list.xml με μόνη διαφορά ότι το

new_med.xml αποτελούσε το αρχικό layout της κλάσης < NewMedReminder.java

>. Παρομοίως παρακάμπτεται λόγω του PlaceHolderFragment.

Page 65: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 63 από 150

<FrameLayout

xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="lamarko.android.medicinereminder.NewMedReminder"tools:ignore="MergeRootFrame" />

Τέλος, το new_med_fragment.xml αποτελεί το layout που εμφανίζεται στο

χρήστη μετά το πάτημα του κουμπιού “ Προσθήκη Υπενθύμισης Φαρμάκου ” στο

med_list_fragment.xml. Στο συγκεκριμένο layout υπάρχει ένα < Linear Layout >

με διαστάσεις να επεκτείνεται σε όλη την οθόνη με διάκενα από αυτήν ( padding

Bottom / Left / Right /Top – 10dp / 5dp / 10dp ), κάθετη τακτοποίηση αντικειμένων

και χρώμα φόντου μπεζ. Εμφωλεύεται νέο Linear Layout με διαστάσεις πλάτους

να ταιριάζουν με αυτό του προηγούμενου Linear Layout ( fill_parent ) και ύψος

να τυλίγει τα περιεχόμενα αντικείμενα. Το < Linear Layout > αυτό περιέχει ένα

πλαίσιο εμφάνισης κειμένου ( TextView ) με αντίστοιχα δικά του χαρακτηριστικά

id, διαστάσεων, διακένων και μέγεθος γραμματοσειράς απεικονιζόμενου κειμένου

( textSize ), ένα πλαίσιο εισαγωγής κειμένου από το χρήστη ( Όνομα Φαρμάκου

) με αντίστοιχα χαρακτηριστικά με το πλαίσιο κειμένου και επιπρόσθετα το “ems

, autoText ” όπου το πρώτο ορίζει το μέγεθος της γραμματοσειράς και το δεύτερο

διορθώνει αυτόματα την ορθογραφία της εισαγμένης λέξης, και ένα < checkbox >

( Επιλογές Επανάληψης ) με αντίστοιχα χαρακτηριστικά διαστάσεων και γραφής

με τη διαφοροποίηση ότι όταν επιλεχθεί ενεργοποιείται η μέθοδος “

indefiniteAction ” ( onClick= “ indefiniteAction ”).

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="10dp"

Page 66: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 64 από 150

android:paddingLeft="5dp"android:paddingRight="5dp"android:paddingTop="10dp"android:orientation="vertical"android:background="#EEE8AA"

tools:context="lamarko.android.medicinereminder.NewMedReminder$PlaceholderFragment" >

<LinearLayout

android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<TextView

android:id="@+id/vtitle"android:maxLength="100"android:layout_width="90dp"android:layout_height="wrap_content"android:paddingBottom="10dp"android:text="@string/title"android:textSize="@dimen/font_size"/>

<EditText

android:id="@+id/etitle"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="0.55"android:ems="10"android:inputType="text"android:maxLength="30"

Page 67: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 65 από 150

android:autoText="true" />

<CheckBox

android:id="@+id/repeatloop"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="indefiniteAction"android:text="@string/repeatloop"android:layout_weight="0.05"android:textSize="12sp" />

</LinearLayout>

Με την ολοκλήρωση του άνω Linear Layout, δημιουργείται νέο εμφωλευμένο στο

αρχικό, το οποίο διαθέτει τα ίδια χαρακτηριστικά διαστάσεων με το προηγούμενο

και περιέχει ένα πλαίσιο κειμένου ( Ημ/νία ) με ανάλογα ατομικά χαρακτηριστικά

id, διαστάσεων, διακένων και μεγεθών γραμματοσειράς και ένα πλαίσιο

εισαγωγής κειμένου και αυτό με τα αντίστοιχα χαρακτηριστικά με επιπλέον το ότι

όταν επιλεγεί για την επεξεργασία θα εκκινήσει η ανάλογη μέθοδος “

datePickerAction ” (onclick=“ datePickerAction ” ), η οποία με τη σειρά της καλεί

ένα DatePickerDialog.

<LinearLayout

android:id="@+id/linlayout_date"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<TextView

android:id="@+id/vdate"android:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"

Page 68: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 66 από 150

android:paddingBottom="15dp"android:text="@string/date"android:textSize="15sp"/>

<EditText

android:id="@+id/edate"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="3"android:ems="10"android:inputType="date"android:focusable="false"android:onClick="datePickerAction" />

</LinearLayout>

Με την ολοκλήρωση του άνω Linear Layout, δημιουργείται νέο εμφωλευμένο στο

αρχικό, το οποίο διαθέτει τα ίδια χαρακτηριστικά διαστάσεων με το προηγούμενο

και περιέχει ένα πλαίσιο κειμένου ( Ώρα ) με ανάλογα ατομικά χαρακτηριστικά id,

διαστάσεων, διακένων και μεγεθών γραμματοσειράς και ένα πλαίσιο εισαγωγής

κειμένου και αυτό με τα αντίστοιχα χαρακτηριστικά με επιπλέον το ότι όταν

επιλεγεί για την επεξεργασία θα εκκινήσει η ανάλογη μέθοδος “ timePickerAction

” (onclick=“ timePickerAction ” ), η οποία με τη σειρά της καλεί ένα

TimePickerDialog.

<LinearLayout

android:id="@+id/linlayout_time"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

Page 69: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 67 από 150

<TextView

android:id="@+id/vtime"android:layout_weight="1"android:layout_width="0dp"android:layout_height="wrap_content"android:paddingBottom="15dp"android:text="@string/time"android:textSize="15sp"/>

<EditText

android:id="@+id/etime"android:layout_weight="3"android:layout_width="0dp"android:layout_height="wrap_content"android:ems="10"android:inputType="time"android:focusable="false"android:onClick="timePickerAction" />

</LinearLayout>

Ακολουθεί μία μπάρα χρώματος ( holo_orange_light ) πορτοκαλί, με φυσικά

αντίστοιχα απαιτούμενα χαρακτηριστικά. Η μπάρα αυτή είναι ορατή ( visibility=“

gone ” ) μόνον όταν έχει επιλεγεί το < checkbox > ( Επιλογές Επανάληψης ).

<View

android:id="@+id/view_bar1"android:layout_width="fill_parent"android:layout_height="1dip"android:layout_marginBottom="5dip"android:layout_marginTop="5dip"android:background="@android:color/holo_orange_light"android:visibility="gone" />

Page 70: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 68 από 150

Ακολουθεί ένα τελικό εμφωλευμένο < Linear Layout > που περιέχει όλα τα

αναγκαία χαρακτηριστικά, μία μπάρα χρώματος πορτοκαλί με συνεχή παρουσία

και ένα κουμπί ( Προσθήκη Φαρμάκου ) το οποίο έχει τα απαραίτητα στοιχεία και

στο πάτημά του καλεί τη μέθοδο SaveReminderData (

onClick=“SaveReminderData” ), η οποία αποθηκεύει τα δεδομένα σε μία βάση

δεδομένων.

</LinearLayout>

<View

android:layout_width="fill_parent"android:layout_height="3dip"android:layout_marginBottom="10dip"android:layout_marginTop="10dip"android:background="@android:color/holo_orange_light" />

<LinearLayout

android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<Button

android:id="@+id/add_med"android:layout_width="match_parent"android:layout_height="match_parent"android:text="@string/add_med"android:onClick="SaveReminderData" />

</LinearLayout>

</LinearLayout>

Page 71: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 69 από 150

Έχουμε όμως και το Linear Layout που δημιουργείται για τις επιλογές του <

checkbox > ( Επιλογές Επανάληψης ), με εμφάνιση αυτού όταν επιλεγεί το

checkbox. Το τελευταίο αυτό Layout περιέχει τρία ( 3 ) checkboxes ( 8 ώρες, 12

ώρες, 24 ώρες ) τα οποία περιέχουν διαστάσεις ύψους / πλάτους τυλίγματος του

περιεχομένου τους και όταν επιλεχθούν καλούν αντιστοίχως τις εξής μεθόδους

EightHourAction, TwelveHourAction, TwentyfourHourAction (on click=“

EightHourAction ” / “ TwelveHourAction ” / “ TwentyfourHourAction ” ).

<LinearLayout

android:id="@+id/linlayout_repeat"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="gone" >

<CheckBox

android:id="@+id/eight_hours"android:layout_width="wrap_content"android:layout_height="wrap_content"android:checked="false"android:onClick="EightHourAction"android:text="@string/eighthours" />

<CheckBox

android:id="@+id/twelve_hours"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/twelvehours"android:onClick="TwelveHourAction" />

<CheckBox

android:id="@+id/twentyfour_hours"android:layout_width="wrap_content"

Page 72: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 70 από 150

android:layout_height="wrap_content"android:text="@string/twentyfourhours"android:onClick="TwentyfourHourAction" />

</LinearLayout>

3.4.7) Κλάσεις

3.4.7.1) OnBootReceiver.java

Η κλάση OnBootReceiver λαμβάνει ως υπερκλάση την BroadcasReceiver και

έχει ως μόνη της αρμοδιότητα να λάβει τη πρόθεση ( intent ) μέσω του δέκτη

μετάδοσης ( broadcast receiver ) όταν εκκινήσει η κινητή συσκευή (

AndroidManifest ) και έπειτα χρησιμοποιώντας τη δημόσια μέθοδο onReceive (

Context context, Intent intent ) να εκκινήσει μέσω νέας προθέσεως τη κλάση

NotificationService.java για να επαναλειτουργήσει η υπηρεσία ειδοποίησης του

χρήστη.

public class OnBootReceiver extends BroadcastReceiver {@Override

public void onReceive(Context context, Intent intent) {context.startService(new Intent(context, NotificationService.class));

}}

3.4.7.2) ComDialogFragment.java

Η κλάση / θρύσμα ComDialogFragment λαμβάνει ως υπερκλάση τη

DialogFragment για να εμφανίσει κάποιο μήνυμα στο χρήστη τόσο κατά τη

διάρκεια αλληλεπίδρασης αυτού με την εφαρμογή ( παράλειψη εισαγωγής

Page 73: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 71 από 150

ονόματος φαρμάκου ), όσο και για να ειδοποιήσει το χρήστη για τη

προγραμματισμένη ειδοποίησή του ( λήψη φαρμάκου ). Θέτεται η δημόσια

μέθοδος setMessage ( String message ), μέσω της οποίας μπορεί να κληθεί η

παρούσα κλάση από τις υπόλοιπες για την οποιαδήποτε προβολή μηνύματος.

Τα παραπάνω επιτυγχάνονται μέσω της μεθόδου / δομητή Dialog

onCreateDialog, η οποία χρησιμοποιώντας τον < AlertDialog.Builder > (

δυνατότητα προβολής τίτλου, 3 κουμπιά και λίστα αντικειμένων ) δομεί το

εκάστοτε μήνυμα / αντικείμενο, το οποίο επιστρέφει στην εκάστοτε

δραστηριότητα, που εμφανίζεται στην οθόνη του χρήστη, το οποίο με τη σειρά

του απομακρύνεται με το πάτημα του κουμπιού μέσω ενός χειριστή συμβάντος (

.setNegativeButton(“Ok”, new DialogInterface.OnClickListener() ).

public class ComDialogFragment extends DialogFragment {private String message = "";

public void setMessage(String message) {this.message = message;

}

@Override

public Dialog onCreateDialog(Bundle savedInstanceState) {// Use the Builder class for convenient dialog construction

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());builder.setMessage(this.message)

.setNegativeButton("Ok", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int id) {

// do nothing; just notify user.

}});

// Create the AlertDialog object and return it

return builder.create();}

}

Page 74: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 72 από 150

3.4.7.3 ) DatePickerFragment.java

Η κλάση / θραύσμα DatePickerFragment λαμβάνει ως υπερκλάση τη

DialogFragment και ως υποκλάση τη DatePickerDialog.OnDateSetListener. Στην

αρχή χρησιμοποιείται η μέθοδος / δομητής Dialog onCreateDialog , η οποία

παράγει ένα αντικείμενο < DatePickerDialog > με αρχικές τιμές την τρέχουσα

ημερομηνία και επιστρέφεται το αντικείμενο στη τρέχουσα δραστηριότητα. Στο

πλαίσιο αυτό ( new_med_fragment.xml ) ο χρήστης εισάγει την επιθυμητή

ημερομηνία για την ειδοποίησή του. Η έναρξη του DatePickerDialog

πραγματοποιείται με την υποκλάση / χειριστή συμβάντος

DatePickerDialog.OnDateSetListener και έπειτα με τη μέθοδο OnDateSet στο

πεδίο του < EditText > ( findViewById(R.id_edate) ) προβάλεται η επιλεχθείσα

ημερομηνία με μορφή κειμένου ( μέθοδος TextView – αντικείμενο tv ).

public class DatePickerFragment extends DialogFragment implementsDatePickerDialog.OnDateSetListener {

public Dialog onCreateDialog(Bundle savedInstanceState) {// Use the current date as the default date in the picker

final Calendar c = Calendar.getInstance();int year = c.get(Calendar.YEAR);int month = c.get(Calendar.MONTH);int day = c.get(Calendar.DAY_OF_MONTH);

// Create a new instance of DatePickerDialog and return it

return new DatePickerDialog(getActivity(), this, year, month, day);}

@Override

public void onDateSet(DatePicker view, int year, int monthOfYear, int

dayOfMonth) {

Page 75: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 73 από 150

TextView tv = (TextView) getActivity().findViewById(R.id.edate);tv.setText(dayOfMonth + "/" + (monthOfYear + 1) + "/" + year);

}}

3.4.7.4) TimePickerFragment.java

Η κλάση / θραύσμα TimePickerFragment λαμβάνει ως υπερκλάση τη

DialogFragment και ως υποκλάση τη TimePickerDialog.OnTimeSetListener.

Στην αρχή χρησιμοποιείται ο < Dialog onCreateDialog > , ο οποίος παράγει ένα

αντικείμενο TimePickerDialog με αρχικές τιμές την τρέχουσα ώρα και

επιστρέφεται το αντικείμενο του δομητή στην τρέχουσα δραστηριότητα. Στο

πλαίσιο αυτό ( new_med_fragment.xml ) ο χρήστης εισάγει την επιθυμητή ώρα

για την ειδοποίησή του. Η έναρξη του TimePickerDialog πραγματοποιείται με την

υποκλάση / χειριστή συμβάντος < TimePickerDialog.OnTimeSetListener > και

έπειτα με τη μέθοδο OnTimeSet στο πεδίο του < EditText > (

findViewById(R.id_etime) ) προβάλεται η επιλεχθείσα ώρα με μορφή κειμένου (

μέθοδος TextView – αντικείμενο tv ). Καθότι όμως χρησιμοποιείται δωδεκάωρη (

12ωρή ) μορφή ρολογιού χρησιμοποιούνται δύο ( 2 ) if / else περιπτώσεις.

if (hourOfDay > 11) {tmp_hour = tmp_hour - 12;AM_PM = "PM";

} else {AM_PM = "AM";

}

if (tmp_hour == 0) {tmp_hour = 12;

}

Page 76: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 74 από 150

Η πρώτη λαμβάνει σε μία tmp_hour μεταβλητή την ψηφιακή ώρα και μέσω της if

/ else καθορίζει εάν πρέπει στο ( TextView tv ) να εμφανιστεί το σύμβολο A.M. ή

P.M. ( Π.Μ. – Μ.Μ. ). Στη δεύτερη if ελέγχεται εάν η temp_hour φέρει αποτέλεσμα

μηδέν ( 0 ) από τη πρώτη και θέτει την ώρα 12η μεσημβρινή.

public class TimePickerFragment extends DialogFragment implementsTimePickerDialog.OnTimeSetListener {

public Dialog onCreateDialog(Bundle savedInstanceState) {// Use the current time as the default values for the picker

final Calendar c = Calendar.getInstance();int hour = c.get(Calendar.HOUR_OF_DAY);int minute = c.get(Calendar.MINUTE);

// Create a new instance of TimePickerDialog and return it

return new TimePickerDialog(getActivity(), this, hour, minute, false);}

public void onTimeSet(TimePicker view, int hourOfDay, int minute) {TextView tv = (TextView) getActivity().findViewById(R.id.etime);

.

.

.

String __hour = String.format("%02d", tmp_hour);String __min = String.format("%02d", minute);

tv.setText(__hour + ":" + __min + " " + AM_PM);}

}

Page 77: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 75 από 150

3.4.7.5 ) MedListActivity.java

Η κλάση MedListActivity έχει ως υπερκλάση την Activity. Η πρώτη κλάση είναι

αυτή που συναντάει ο χρήστης κατά την εκκίνηση της εφαρμογής ( δηλαδή το

layout αυτής ). Κατά την εκκίνηση της κλάσης δημιουργείται ένα αντίγραφο

κατάστασης ( savedInstanceState) που αποθηκεύεται δυναμικά, με σκοπό εάν

για κάποιο λόγο χρειαστεί ο χρήστης π.χ. να απαντήσει σε μία εισερχόμενη

κλήση, όταν περατωθεί αυτή να επιστρέψει ανέπαφη η εφαρμογή στην οθόνη του

χρήστη. Μαζί με το αντίγραφο κατάστασης φορτώνεται και το layout αυτής (

med_list.xml ). Έπειτα ελέγχεται εάν υπάρχει αντίγραφο κατάστασης και εφόσον

υπάρχει, πάντα, καλείται η κλάση FragmentManager, η οποιά αρχικοποιείται και

προσθέτει στο med_list.xml ένα θραύσμα ( .add(R.id.container, new

PlaceHolderFragment()).comit(); ). Ακολουθεί μία πρόθεση που εκκινεί την

παρεχόμενη υπηρεσία της NotificationService.class.

public class MedListActivity extends Activity {@Override

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.med_list);

if (savedInstanceState == null) {getFragmentManager().beginTransaction()

.add(R.id.container, new PlaceholderFragment()).commit();}

System.out.println("Start service");

Intent i = new Intent(this, NotificationService.class);startService(i);

}

Page 78: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 76 από 150

protected void onStart() {super.onStart();}

Η PlaceholderFragment κλάση λαμβάνει ως υπερκλάση τη Fragment. Μέσω της

< View onCreateView > δημιουργείται το θραύσμα / layout βάσει συγχωνεύσεως

του med_list.xml ( container ) και του med_list_fragment.xml.

public static class PlaceholderFragment extends Fragment {

public PlaceholderFragment() {}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {

View rootView = inflater.inflate(R.layout.med_list_fragment, container,false);

return rootView;}

}

Σε κάθε φάση συνέχισης ( Resume ) γίνεται ένας έλεγχος με μία if /else

κατάσταση, η οποία ελέγχει εάν το κουμπί ( add_med – Προσθήκη Υπενθύμισης

Φαρμάκου ) είναι ενεργό, που είναι και δημιουργεί ένα δυναμικό περιβάλλον

χρήστη ( buildDynamicUI ).

protected void onResume() {super.onResume();

Button add = (Button) findViewById(R.id.add_med);

if (! add.isEnabled()) {LinearLayout ll = (LinearLayout) findViewById(R.id.layout_dump);

Page 79: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 77 από 150

ll.removeAllViews();this.buildDynamicUI();add.setEnabled(true);

} else {LinearLayout ll = (LinearLayout) findViewById(R.id.layout_dump);ll.removeAllViews();this.buildDynamicUI();

}}

Στη μέθοδο buildDynamicUI, όπου δημιουργείται το δυναμικό γραφικό

περιβάλλον του χρήστη, το πρώτο που επιτελείται είναι να λάβει ένα αναγνώσιμο

αρχείο της βάσεως δεδομένων ( .getReadableDatabase() ). Έπειτα στη

μεταβλητή projection συγκεντρώνονται το όνομα, είδος επανάληψης ( repeat ) και

τα δύο strings της ημερομηνίας και ώρας σε μία (epoch ). Μετά χρησιμοποιούμε

τη κλάση cursor και τη δόμηση μίας < db.query >

(query(String table, String[] columns, String selection, String[] selectionArgs, Stri

ng groupBy, String having, String orderBy) με το string orderBy ( sortOrder ) να

λαμβάνει το ID της κάθε εγγραφής στη βάση δεδομένων.

private void buildDynamicUI() {ReminderDb memo = new ReminderDb(getBaseContext());SQLiteDatabase db = memo.getReadableDatabase();

String[] projection = {ReminderDb.COLUMN_NAME_MEDICINE_TITLE,ReminderDb.COLUMN_NAME_MEDICINE_EPOCH,ReminderDb.COLUMN_NAME_REPEAT

};

String sortOrder = ReminderDb.COLUMN_NAME_MEDICINE_ID + " ASC";

Page 80: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 78 από 150

Cursor c = db.query(ReminderDb.TABLE_NAME,projection,null,null,null,null,sortOrder

);

c.moveToFirst();

Ακολουθεί μία συνθήκη for, η οποία παραθέτει στο med_list_fragment.xml τις

υπάρχουσες εγγραφές στη βάση δεδομένων. Η κάθε εγγραφή, μέσω της μεθόδου

< TextView >, εμφανίζεται στο χρήστη έπειτα από παραμετροποιήσεις μεγέθους

γραμματοσειράς, διακένων και διαστάσεων. Για να εμφανιστεί, όμως το < Είδος

Επανάληψης > απαιτείται μία εμφωλευμένη if στην οποία εάν έχει επιλεγεί

επαναλαμβανόμενη επανάληψη ( checkbox ) τότε εμφανίζεται πάγιο κείμενο, σε

αντίθετη περίπτωση δημιουργείται ένα αντικείμενο της SimpleDateFormat, το

οποίο λαμβάνοντας την ώρα και ημερομηνία ( index_time - _epoch ) τα παραθέτει

σε 12ωρη μορφή μέσω του TextView.

private void buildDynamicUI() {ReminderDb memo = new ReminderDb(getBaseContext());SQLiteDatabase db = memo.getReadableDatabase();

String[] projection = {ReminderDb.COLUMN_NAME_MEDICINE_TITLE,ReminderDb.COLUMN_NAME_MEDICINE_EPOCH,ReminderDb.COLUMN_NAME_REPEAT

};

Page 81: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 79 από 150

String sortOrder = ReminderDb.COLUMN_NAME_MEDICINE_ID + " ASC";

Cursor c = db.query(ReminderDb.TABLE_NAME,projection,null,null,null,null,sortOrder

);

c.moveToFirst();

for (int i = 0; i < c.getCount(); i++) {int index_title =

c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_MEDICINE_TITLE);int index_time =

c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_MEDICINE_EPOC

H);int index_repeat =

c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_REPEAT);

TextView title = new TextView(this);title.setLayoutParams(new

LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT, 1f));

title.setFilters(new InputFilter[] { new InputFilter.LengthFilter(30)});title.setTextAppearance(this,

android.R.style.TextAppearance_Medium);title.setText(c.getString(index_title));title.setTextSize(15);

Page 82: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 80 από 150

title.setPadding(10, 5, 10, 5);

TextView time = new TextView(this);time.setLayoutParams(new

LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT, 3f));

time.setTextAppearance(this,android.R.style.TextAppearance_DeviceDefault_Small);

time.setTextSize(10);

String repeatloop = c.getString(index_repeat);

if (repeatloop.equals("N")) {SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm

a");

String tmp_date = sdf.format(newDate(Long.parseLong(c.getString(index_time))));

time.setText(tmp_date);} else if (repeatloop.equals("Y")) {

time.setText(R.string.rep_loops);}

time.setPadding(10, 5, 10, 5);

Τα παραπάνω δεδομένα εμφανίζονται στο < Linear Layout > ( id – layout_dump

) στο οποίο υπάρχει ένας χειριστής συμβάντος, κατά τον οποίο σε παρατεταμένη

επιλογή μίας εγγραφής, εκχωρείται ο τίτλος αυτής σε δύο μεταβλητές ( selection,

selectionArgs ) με τις οποίες καλείται μετέπειτα ένα εγγράψιμο αρχείο της βάσεως

δεδομένων, από το οποίο διαγράφεται η εγγραφή ( μέσω των selection,

selectionArgs ) και τέλος ενημερώνεται για τη διαγραφή αυτή η db.query.

Page 83: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 81 από 150

LinearLayout ll = (LinearLayout) findViewById(R.id.layout_dump);

LinearLayout lh = new LinearLayout(this);lh.setId(i);lh.setOrientation(LinearLayout.HORIZONTAL);lh.addView(title);lh.addView(time);

lh.setOnLongClickListener(new OnLongClickListener() {

@Override

public boolean onLongClick(View v) {String title = (String) ((TextView) ((ViewGroup)

v).getChildAt(0)).getText();

String selection =ReminderDb.COLUMN_NAME_MEDICINE_TITLE + " = ?";

String[] selectionArgs = {title,

};

ReminderDb memo = new ReminderDb(getBaseContext());SQLiteDatabase db = memo.getWritableDatabase();

ReminderDb.getID(getApplicationContext(), title);

db.delete(ReminderDb.TABLE_NAME, selection, selectionArgs);

v.setVisibility(View.GONE);

return false;}

Page 84: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 82 από 150

});

ll.addView(lh);

c.moveToNext();}

}

Καταληκτικά όταν πατηθεί το κουμπί ( Προσθήκη Υπενθύμισης Φαρμάκου ) από

το θραύσμα / layout ( onClick=“ New Reminder ” ) τότε μέσω μίας πρόθεσης

εκκινεί η NewMedReminder.class.

public void NewReminder(View v) {v.setEnabled(false);Intent i = new Intent(this, NewMedReminder.class);startActivity(i);

}

3.4.7.6) NewMedReminder.java

Με τον ίδιο ακριβώς τρόπο εκκινεί και η κλάση NewMedReminder.java, η οποία

έχει ως υπερκλάση την Activity. Η πρώτη κλάση εκκινεί με το new_med.xml το

οποίο συγχέεται με αυτό του θραύσματος ( PlaceholderFragment )

new_med_fragment.xml.

public class NewMedReminder extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.new_med);

Page 85: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 83 από 150

if (savedInstanceState == null) {getFragmentManager().beginTransaction()

.add(R.id.container, new PlaceholderFragment()).commit();}

}

public void onBackPressed() {finish();

}

public static class PlaceholderFragment extends Fragment {

public PlaceholderFragment() {}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {

View rootView = inflater.inflate(R.layout.new_med_fragment,container, false);

return rootView;}

}

Ακολουθεί η μέθοδος SaveReminderData ( κουμπί – Προσθήκης Υπενθύμισης ),

που βρίσκεται στο new_med_fragment.xml και λαμβάνει τα εισαγμένα στοιχεία

του χρήστη. Εφόσον υπάρχει κάποια παράληψη ( ParseException ) λ.χ. του

ονόματος του φαρμάκου με μία συνθήκη if ελέγχεται το παραπάνω και

εμφανίζεται στο χρήστη με ένα θραύσμα με περιεχόμενο μήνυμα από το

ComDialogFragment ( FragmentManager ). Τα αντίστοιχα θραύσματα

εμφανίζονται για τη παράληψη ημερομηνίας και ώρας, εφόσον δεν έχει επιλεγεί

το < checkbox Επιλογές Επανάληψης > ( if (! Repeat.isChecked() ) ). Σε αντίθετη

Page 86: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 84 από 150

περίπτωση λαμβάνεται το checkbox με τις επιθυμητές ώρες κυκλικής

επανάληψης ( 8, 12, 24 ).

public void SaveReminderData(View v) throws ParseException {v.setEnabled(false);CheckBox repeat = (CheckBox) findViewById(R.id.repeatloop);TextView title_view = (TextView) findViewById(R.id.etitle);TextView date_view = (TextView) findViewById(R.id.edate);TextView time_view = (TextView) findViewById(R.id.etime);

if (title_view.length() == 0) {v.setEnabled(true);ComDialogFragment t = new ComDialogFragment();t.setMessage("Εισάγετε φάρμακο - Insert medicine");t.show(this.getFragmentManager(), "badData");return;

}

if (! repeat.isChecked() ) {

if (time_view.length() == 0) {v.setEnabled(true);ComDialogFragment t = new ComDialogFragment();t.setMessage("Εισάγετε ώρα - Insert time");t.show(this.getFragmentManager(), "badData");return;

}

if ( date_view.length() == 0 ) {v.setEnabled(true);ComDialogFragment t = new ComDialogFragment();t.setMessage("Εισάγετε ημ/νία - Insert date");t.show(this.getFragmentManager(), "badData");

Page 87: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 85 από 150

return;}

.

. .

} else if (repeat.isChecked()) {CheckBox eighthours = (CheckBox) findViewById(R.id.eight_hours);CheckBox twelvehours = (CheckBox) findViewById(R.id.twelve_hours);CheckBox twentyfourhours= (CheckBox)

findViewById(R.id.twentyfour_hours);

Στη πρώτη περίπτωση η εντολή για προσθήκη των στοιχείων στη βάση

δεδομένων είναι ( .addReminder(Context context, String title, repeat Boolean,

eight_hours Boolean, twelve_hours Boolean, twentyfour_hours Boolean, date

string, time string ) :

ReminderDb.addReminder(getApplicationContext(),title_view.getText().toString(),false,false,false,false,date_view.getText().toString(),time_view.getText().toString()

);

Και στη περίπτωση επιλογής επαναληπτικών ειδοποιήσεων με παρόμοια δομή,

ακολουθούμενη από πρόθεση εκκίνησης της υπηρεσίας της

NotificationService.class:

else if (repeat.isChecked()) {CheckBox eighthours = (CheckBox) findViewById(R.id.eight_hours);

Page 88: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 86 από 150

CheckBox twelvehours = (CheckBox) findViewById(R.id.twelve_hours);CheckBox twentyfourhours= (CheckBox)

findViewById(R.id.twentyfour_hours);

ReminderDb.addReminder(getApplicationContext(),title_view.getText().toString(),true,eighthours.isChecked(),twelvehours.isChecked(),twentyfourhours.isChecked(),"0","0"

);

}

Intent i = new Intent(getApplicationContext(), NotificationService.class);startService(i);

finish();

Έπονται η μέθοδοι για την εμφάνιση του θραύσματος της ημερομηνίας (

datePickerAction ) και ώρας ( timePickerAction ). Στο timePicker και datePicker

η μέθοδος είναι παρόμοια με τη διαχείριση του FragmentManager καλείται ο,

αντιστοίχως, TimePickerFragment και DatePickerFragment με ανάλογες

ενέργειες στις οριζόμενες κλάσεις τους.

public void datePickerAction(View v) {DialogFragment frag = new DatePickerFragment();frag.show(this.getFragmentManager(), "datePicker");

}

Page 89: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 87 από 150

public void timePickerAction(View v) {DialogFragment frag = new TimePickerFragment();frag.show(this.getFragmentManager(), "timePicker");

}

Ακολουθεί η μέθοδος για το < checkbox Επιλογές Επανάληψης > ( onClick=“

indefiniteAction ” ) κατά την οποία και εφόσον είναι επιλεγμένο το checkbox

επικαλύπτονται οι επιλογές ημερομηνία και ώρα και εμφανίζονται μία λεπτή

πορτοκαλί μπάρα ( view_bar1 ) και οι επιλογές επανάληψης 8 ώρες, 12 ώρες, 24

ώρες. Σε αντίθετη περίπτωση τα επικαλυπτόμενα πεδία επιστρέφουν στη

προγενέστερη κατάστασή τους.

public void indefiniteAction(View v) {CheckBox c = (CheckBox) v;CheckBox eighthours = (CheckBox) findViewById(R.id.eight_hours);CheckBox twelvehours = (CheckBox) findViewById(R.id.twelve_hours);CheckBox twentyfourhours = (CheckBox)

findViewById(R.id.twentyfour_hours);View bar = (View) findViewById(R.id.view_bar1);LinearLayout l1 = (LinearLayout) findViewById(R.id.linlayout_date);LinearLayout l2 = (LinearLayout) findViewById(R.id.linlayout_time);LinearLayout l3 = (LinearLayout) findViewById(R.id.linlayout_repeat);

if ( c.isChecked() ) {l1.setVisibility(l1.GONE);l2.setVisibility(l2.GONE);eighthours.setChecked(true);eighthours.setEnabled(false);bar.setVisibility(v.VISIBLE);l3.setVisibility(l3.VISIBLE);

} else {

Page 90: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 88 από 150

l1.setVisibility(l1.VISIBLE);l2.setVisibility(l2.VISIBLE);eighthours.setChecked(false);eighthours.setEnabled(true);twelvehours.setChecked(false);twelvehours.setEnabled(true);twentyfourhours.setChecked(false);twentyfourhours.setEnabled(true);bar.setVisibility(v.GONE);l3.setVisibility(l3.GONE);

}}

Απομένουν οι μέθοδοι για τα checkboxes των 8 ωρών ( EightHourAction ), των

12 ωρών ( TwelveHourAction ) και των 24 ωρών ( TwentyfourHourAction ), στα

οποία με πανομοότυπο τρόπο κατά την επιλογή του ενός τα άλλα δύο βρίσκονται

σε διαθέσιμη κατάσταση.

public void EightHourAction(View v) {CheckBox eighthour = (CheckBox) v;CheckBox twelvehour = (CheckBox) findViewById(R.id.twelve_hours);CheckBox twentyfourhour = (CheckBox)

findViewById(R.id.twentyfour_hours);

if ( eighthour.isChecked() ) {twelvehour.setEnabled(true);twentyfourhour.setEnabled(true);

}}

public void TwelveHourAction(View v) {CheckBox twelvehour = (CheckBox) v;CheckBox eighthour = (CheckBox) findViewById(R.id.eight_hours);

Page 91: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 89 από 150

CheckBox twentyfourhour = (CheckBox)findViewById(R.id.twentyfour_hours);

if ( twelvehour.isChecked() ) {eighthour.setEnabled(true);twentyfourhour.setEnabled(true);

}}

public void TwentyfourHourAction(View v) {CheckBox twentyfourhour = (CheckBox) v;CheckBox eighthour = (CheckBox) findViewById(R.id.eight_hours);CheckBox twelvehour = (CheckBox) findViewById(R.id.twelve_hours);

if ( twentyfourhour.isChecked() ) {eighthour.setEnabled(true);twelvehour.setEnabled(true);

}}

3.4.7.7) NotificationService.java

Η NotificationService.class λαμβάνει ως υπερκλάση την IntentService.

Περιέχονται τρεις ( 3 ) ιδιωτικές και τελικές μεταβλητές, 2 για τις τιμές

ειδοποιήσεων και 1 για τη τιμή δονήσεως, και τρεις ( 3 ) ιδιωτικές στατικές για

τους κύκλους των επαναληπτικών ειδοποιήσεων.

public class NotificationService extends IntentService {private final int ONE_HOUR = 3600;private final int ONE_MINUTE = 60;private final int VIBRATE_TIME = 2000; // milliseconds

Page 92: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 90 από 150

private static int Aloopcounter = 0;private static int Bloopcounter = 0;private static int Cloopcounter = 0;

Ακολουθεί η μέθοδος Notify, η οποία δημιουργεί τις ειδοποιήσεις που

εμφανίζονται στη μπάρα κατάστασης. Στην ειδοποίηση αυτή περιέχεται, με τη

χρήση του NotificationCompat.Builder, το εικονίδιο της εφαρμογής, ο < τίτλος του

φαρμάκου > ( λαμβάνεται μέσω της προθέσεως από τον αντίστοιχο τύπο

ειδοποιήσεως ), όπως και το μήνυμα προς το χρήστη. Επίσης παρέχεται

υπηρεσία δονήσεως και υπηρεσία ηχητικής ειδοποιήσεως με προεπιλεγμένο

ήχο. Η δικλείδα εκκίνησης λήψεως αυτών είναι μία πρόθεση ( pendingmain -

getActivity(Context context, int requestCode, Intent intent, int flags) ), η οποία

λαμβάνει από τη βάση δεδομένων μέσω προθέσεως πάλι το τίτλο της

υπενθυμίσεως που βρίσκεται σε εκτέλεση τη δεδομένη στιγμή. Καταληκτικά, στο

κομμάτι αυτό του κώδικα το αντικείμενο notificationmanager (

NotificationManager ) έχοντας το τίτλο της υπενθύμισης, μέσω προθέσεως,

κατασκευάζει την ειδοποίηση.

private void Notify(Intent intent) {// Notification on drop down bar

PendingIntent pendingmain =PendingIntent.getActivity(getApplicationContext(), intent.getIntExtra("id", 0),intent, 0);

NotificationCompat.Builder notification = newNotificationCompat.Builder(getApplicationContext());

notification.setSmallIcon(R.drawable.medr);notification.setContentTitle(intent.getStringExtra("reminder"));notification.setContentText(intent.getStringExtra("string"));notification.setContentIntent(pendingmain);notification.setAutoCancel(true);

Page 93: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 91 από 150

NotificationManager notificationmanager = (NotificationManager)getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);

Uri soundUri =RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

Vibrator v = (Vibrator)getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);

v.vibrate(this.VIBRATE_TIME);

notification.setSound(soundUri);

notificationmanager.notify(intent.getIntExtra("id", 0), notification.build());}

Έπειτα λαμβάνεται μία συνδεδεμένη λίστα από τη βάση δεδομένων, στην οποία

υπάρχουν τα δεδομένα κάθε εγγεγραμένης ειδοποίησης στη βάση δεδομένων.

Μία μεταβλητή ( system_time ) η οποία περιέχει τον εκάστοτε τωρινό χρόνο του

συστήματος, η οποία χρησιμοποιείται στον ορισμό των επαναλαμβανόμενων

ειδοποιήσεων ( setInexactRepeating(int type, long triggerAtMillis, long

intervalMillis, PendingIntent operation) ), σαφώς χρησιμοποιείται πρόθεση (

pintent ) για να εκκινήσει το αντικείμενο του AlarmManager, ο οποίος εκκινεί την

ALARM_SERVICE.

@Override

protected void onHandleIntent(Intent intent) {Log.v("NotificationService", "Starting NotificationService run");

LinkedList<String[]> list;list = ReminderDb.getReminderTimes(getApplicationContext());long system_time = System.currentTimeMillis();

Page 94: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 92 από 150

// Alarm notification

AlarmManager arm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0);arm.setInexactRepeating(AlarmManager.RTC_WAKEUP, system_time +

60 * 1000,60000, pintent);

Αμέσως μετά υπάρχει μία συνθήκη for στην οποία το String [] data λαμβάνει σε

κάθε επανάληψη τα δεδομένα των διαφορετικών εγγραφών. Έπειτα με μία

συνθήκη if ελέγχεται εάν το < data[2] > ( repeat – επιλογές επανάληψης ) είναι

επιλεγμένο και εφόσον δεν είναι, σε μία long delta μεταβλητή αποθηκεύει την

εναπομείνασα ώρα ( data[1] – ώρα ) μέχρι την ειδοποίηση. Έπεται η πρόθεση (

intent1 ), η οποία ορίζει ότι θα εκκινεί η MedListActivity.class, όταν καλεστεί.

Ύστερα υπάγονται δύο if συνθήκες οι οποίες ελέγχουν την delta εάν είναι

μικρότερη του ενός λεπτού και μικρότερη της μία ώρας και εφόσον

ικανοποιούνται οι προϋποθέσεις αποστέλλονται τα απαιτούμενα δεδομένα στο

NotificationCompat.Builder ( data[0] – τίτλος ειδοποίησης ), λαμβάνοντας το ID

της συγκεκριμένης ειδοποίησης μέσω της μεδόδου getID της βάσης δεδομένων,

όπως και χρησιμοποιεί τις μεθόδους checkNotify / disableNotification της βάσης

δεδομένων. Άξιο αναφοράς είναι η χρήση διαφορετικής πρόθεσης για τις μονές

ειδοποιήσεις ( intent1), με την οποία όταν πατηθεί μία μονή ειδοποίηση στην

μπάρα κατάστασης θα μεταφερθεί ο χρήστης στην MedListActivity.class –

med_list_fragment.xml.

for (int i = 0; i < list.size(); i++) {String[] data = list.get(i);

if (data[2].equals("N")) {long delta = Long.parseLong(data[1]) - System.currentTimeMillis();

Log.v("NotificationService", "TIME REMAINING: " + delta);Log.v("NotificationService", "1 HOUR: " + this.ONE_HOUR * 1000);

Page 95: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 93 από 150

Log.v("NotificationService", "60 SECONDS" + this.ONE_MINUTE *1000);

Log.v("NotificationService", "In reminder loop");

Intent intent1 = new Intent(this, MedListActivity.class);intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

if ( delta < this.ONE_MINUTE * 1000 ) {Log.v("NotificationService", "IN 60");if (ReminderDb.checkNotify(getApplicationContext(), 1, data[0])) {

System.out.println("IN 1b");intent1.putExtra("string", data[0]);intent1.putExtra("reminder", "Λάβετε το - Now");intent1.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));this.Notify(intent1);ReminderDb.disableNotification(getApplicationContext(), 1,

data[0]);}

} else if ( delta < this.ONE_HOUR * 1000 && delta>this.ONE_MINUTE * 1000) {

Log.v("NotificationService", "IN 1");if (ReminderDb.checkNotify(getApplicationContext(), 2, data[0])) {

intent1.putExtra("string", data[0]);intent1.putExtra("reminder", "Ακόμη μία ώρα για το - 1h" );intent1.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));this.Notify(intent1);ReminderDb.disableNotification(getApplicationContext(), 2,

data[0]);}

}

Page 96: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 94 από 150

Εάν όμως το < data[2] – επιλογές επανάληψης > είναι επιλεγμένο τότε με τρεις

ακόμη if συνθήκες ελέγχεται ποια επιλογή από τις 8h -12h – 24h είναι επιλεγμένη.

Όταν βρεθεί η επιλεγμένη επιλογή ενεργοποιείται ένα μετρητής ( Xloopcounter )

με αντίστοιχα loops ολοκλήρωσης για κάθε επιλογή ( 8h – 480, 12h – 720, 24h –

1440 ). Βάση του setInexactReapeating εκτελείται ένα loop ανά λεπτό. Εφόσον

εκπληρωθούν τα απαιτούμενα loops πραγματοποιούνται οι ίδιες ενέργειες με τις

μονές ειδοποιήσεις πλην αυτών των μεθόδων της βάσης δεδομένων και της

χρήσης διαφορετικής προθέσεως ( intent – αρχική βάση onHandleIntent ).

} else if ( data[2].equals("Y") ) {

if ( data[3].equals("Y") ) {Log.v("NotificationService", "8h_reminder" + data[0]);

if (this.Aloopcounter == 480 ) {this.Aloopcounter = 0;

intent.putExtra("string", data[0]);intent.putExtra("reminder", "Κάθε 8 ώρες για το - 8h");intent.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));

this.Notify(intent);

}this.Aloopcounter += 1;

}

if ( data[4].equals("Y") ) {

Log.v("NotificationService", "12h_reminder" + data[0]);

Page 97: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 95 από 150

if ( this.Bloopcounter == 720) {this.Bloopcounter = 0;intent.putExtra("string", data[0]);intent.putExtra("reminder", "Κάθε 12 ώρες για το - 12h");intent.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));

this.Notify(intent);}

this.Bloopcounter += 1;}

if ( data[5].equals("Y") ) {

Log.v("NotificationService", "24h_reminder" + data[0]);

if ( this.Cloopcounter == 1440) {this.Cloopcounter = 0;intent.putExtra("string", data[0]);intent.putExtra("reminder", "Κάθε 24 ώρες για το - 24h");intent.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));

this.Notify(intent);}

this.Cloopcounter += 1;}

}}

Page 98: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 96 από 150

Log.v("NotificationService", "Ending NotificationService run");}

}

3.4.7.8) ReminderDb.java

Η τελευταία κλάση ReminderDb.java έχει ως υπερκλάση την SQLiteOpenHelper.

Παρατίθενται οι δημόσιες στατικές τελικές μεταβλητές για τη δόμηση της βάσεως

δεδομένων ( όνομα βάσης, όνομα πίνακα, κτλ. ). Έπεται η δήλωση sql script η

οποία θα χρησιμοποιηθεί για τη δημιουργία του πίνακα, όπως και το αντίστοιχο

για τη διαγραφή αυτού.

public class ReminderDb extends SQLiteOpenHelper {public static final int DATABASE_VERSION = 12;public static final String DATABASE_NAME = "reminder.db";public static final String TABLE_NAME = "reminder";public static final String COLUMN_NAME_MEDICINE_ID = "medicine_id";public static final String COLUMN_NAME_MEDICINE_EPOCH =

"medicine_epoch";public static final String COLUMN_NAME_MEDICINE_TITLE =

"medicine_title";public static final String COLUMN_NAME_REPEAT = "repeat";public static final String COLUMN_NAME_EIGHT_HOURS = "eight_hours";public static final String COLUMN_NAME_TWELVE_HOURS =

"twelve_hours";public static final String COLUMN_NAME_TWENTYFOUR_HOURS =

"twentyfour_hours";public static final String

COLUMN_NAME_REMINDER_ONE_HOUR_NOTIFICATION ="one_hour_notification";

Page 99: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 97 από 150

public static final String

COLUMN_NAME_REMINDER_ONE_MINUTE_NOTIFICATION ="one_minute_notification";

public static final String SQL_CREATE_TABLE ="CREATE TABLE " + ReminderDb.TABLE_NAME + " " +

ReminderDb.COLUMN_NAME_MEDICINE_ID + " INTEGER

PRIMARY KEY AUTOINCREMENT," +ReminderDb.COLUMN_NAME_MEDICINE_TITLE + " TEXT

UNIQUE ON CONFLICT IGNORE," +ReminderDb.COLUMN_NAME_REPEAT + " TEXT," +ReminderDb.COLUMN_NAME_EIGHT_HOURS + " TEXT," +ReminderDb.COLUMN_NAME_TWELVE_HOURS + " TEXT," +ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS + "

TEXT," +

ReminderDb.COLUMN_NAME_REMINDER_ONE_HOUR_NOTIFICATION + "

TEXT," +

ReminderDb.COLUMN_NAME_REMINDER_ONE_MINUTE_NOTIFICATION +" TEXT," +

ReminderDb.COLUMN_NAME_MEDICINE_EPOCH + " TEXT);";

public static final String SQL_DELETE_TABLE ="DROP TABLE IF EXISTS " + ReminderDb.TABLE_NAME;

Έπεται η μέθοδος δημιουργίας της μοναδικής και υπάρχουσας βάσης

δεδομένων ( ReminderDb.DATABASE_NAME =“reminder” ). Ακολουθούν οι

μέθοδοι που δημιουργούν και αναβαθμίζουν το πίνακα με τα παραπάνω sql

scripts.

Page 100: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 98 από 150

public ReminderDb(Context context) {super(context, ReminderDb.DATABASE_NAME, null,

ReminderDb.DATABASE_VERSION);}

@Override

public void onCreate(SQLiteDatabase db) {db.execSQL(SQL_CREATE_TABLE);

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {db.execSQL(ReminderDb.SQL_DELETE_TABLE);onCreate(db);

}

Αμέσως μετά υπάρχει η μέθοδος για τη προσθήκη ειδοποίησης ( στοιχεία από

new_med_fragment.xml ). Για το λόγω αυτό νέο αντικείμενο SQLiteDatabase (

db ), το οποίο λαμβάνει επεξεργάσιμο αντίγραφο της βάσης. Μέσω της

ContentValues προστίθενται οι επιλογές του χρήστη στα αντίστοιχα πεδία της

βάσεως, με έλεγχο για το αν έχει επιλεχθεί η < checkbox > Επιλογές

Επανάληψης ( repeat ) και έπειτα ποιο από τα 3 < checkboxes > ( 8h, 12h, 24h )

έχει επιλεγεί. Σε αντίθετη περίπτωση λαμβάνει το αντικείμενο τις

SimpleDateFormat, το οποίο είναι διμερές ( time & date -> epoch ) και έπειτα θέτει

αρνητικές τιμές στα πλαίσια των < checkboxes >.

public static void addReminder(Context context, String title,boolean repeat, boolean eight_hours,boolean twelve_hours, boolean twentyfour_hours, String

dateString,String timeString) throws ParseException {

ReminderDb reminderdb = new ReminderDb(context);

Page 101: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 99 από 150

SQLiteDatabase db = reminderdb.getWritableDatabase();

ContentValues values = new ContentValues();

values.put(ReminderDb.COLUMN_NAME_MEDICINE_TITLE, title);

if (repeat) {values.put(ReminderDb.COLUMN_NAME_REPEAT, "Y");values.put(ReminderDb.COLUMN_NAME_MEDICINE_EPOCH, "0");

if (eight_hours == true && twelve_hours == false && twentyfour_hours

== false) {values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS,

"N");} else if (eight_hours == false && twelve_hours == true &&

twentyfour_hours == false) {values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS,

"N");} else if (eight_hours == false && twelve_hours == false &&

twentyfour_hours == true) {values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS,

"Y");} else if (eight_hours == true && twelve_hours == true &&

twentyfour_hours == false) {values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "Y");

Page 102: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 100 από 150

values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS,"N");

} else if (eight_hours == true && twelve_hours == false &&twentyfour_hours == true) {

values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS,

"Y");} else if (eight_hours == false && twelve_hours == true &&

twentyfour_hours == true) {values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS,

"Y");} else if (eight_hours == true && twelve_hours == true &&

twentyfour_hours == true) {values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS,

"Y");}

} else if ( ! repeat) {SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm

a");Date d = sdf.parse(dateString + " " + timeString);long epoch = d.getTime();System.out.println("EPOCH:" + epoch);

values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS,

"N");

Page 103: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 101 από 150

values.put(ReminderDb.COLUMN_NAME_REPEAT, "N");values.put(ReminderDb.COLUMN_NAME_MEDICINE_EPOCH, epoch);values.put(ReminderDb.COLUMN_NAME_MEDICINE_TITLE, title);

}

Ακολούθως εισάγει και το όνομα του πίνακα και κλείνει το αντικείμενο της βάσης

( db ). Ύστερα συναντιέται η συνδεδεμένη λίστα στην οποία το οριζόμενο

αντικείμενο ( db ) λαμβάνει αναγνώσιμο αρχείο της βάσης. Το projection,

MedListActivity.class, λαμβάνει όλα τα ορίσματα από τη βάση και με τη χρήση

του Cursor, ταξινομείται κάθε εγγραφή ως προς την ημερομηνία και ώρα ( epoch

) στο αντικείμενό του. Έπειτα με μία for συνθήκη εισάγονται για κάθε εγγραφή τα

διαθέσιμα εξ’ αυτών στοιχεία σε αντίστοιχα, τα οποία ( τελευταία ) εισάγονται στο

string data, το οποίο με τη σειρά τα προσθέτει στη συνδεδεμένη λίστα ( list ).

public static LinkedList<String[]> getReminderTimes(Context context) {LinkedList<String[]> list = new LinkedList<String[]>();

ReminderDb reminderdb = new ReminderDb(context);SQLiteDatabase db = reminderdb.getReadableDatabase();

String[] projection = {ReminderDb.COLUMN_NAME_MEDICINE_TITLE,ReminderDb.COLUMN_NAME_MEDICINE_EPOCH,ReminderDb.COLUMN_NAME_REPEAT,ReminderDb.COLUMN_NAME_EIGHT_HOURS,ReminderDb.COLUMN_NAME_TWELVE_HOURS,ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS

};

String sortOrder = ReminderDb.COLUMN_NAME_MEDICINE_EPOCH + "

ASC";

Page 104: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 102 από 150

Cursor c = db.query(ReminderDb.TABLE_NAME,projection,null,null,null,null,sortOrder

);

c.moveToFirst();

for (int i = 0; i < c.getCount(); i++) {int index_title =

c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_MEDICINE_TITLE);int index_time =

c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_MEDICINE_EPOC

H);int index_repeat =

c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_REPEAT);int index_eight =

c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_EIGHT_HOURS);int index_twelve =

c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_TWELVE_HOURS);

int index_twentyfour =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_TWENTYFOUR_H

OURS);

String[] data = {c.getString(index_title),c.getString(index_time),

Page 105: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 103 από 150

c.getString(index_repeat),c.getString(index_eight),c.getString(index_twelve),c.getString(index_twentyfour)

};

list.add(data);

c.moveToNext();}

reminderdb.close();db.close();

return list;}

Καταλήγοντας την ανάλυση της κλάσης και του κώδικα, παραθέτονται τρεις ( 3 )

μέθοδοι. Η checkNotify, η οποία λαμβάνει με παρόμοιο με τον άνω τρόπο, ένα

αναγνώσιμο αρχείο της βάσης και βάσει της κλήσεως από τη

NotificationService.class, γίνεται η επιλογή της switch και καθορίζεται το string

newQuery. Έπειτα με μία συνθήκη if ελεγχεται το πλήθος του c και εφόσον

ικανοποιείται η συνθήκη η value λαμβάνει το c.getString (0 ) – title , και σε μία

εμφωλευμένη if συνθήκη εάν ο < title > είναι κενός επιστρέφει Boolean true και

τερματίζει η βάση, ειδάλλως επιστρέφει Boolean false. Η ακόλουθη μέθοδος

disableNotification έχει την ίδια δομή με τη παραπάνω δίχως τις τελευταίες if, το

query ( άνω newQuery ) και τη χρήση του Cursor. Τέλος η μέθοδος getID με

παρόμοια δομή με την άνω με διαφορετική sql query.

public static boolean checkNotify(Context context, int interval, String title) {ReminderDb reminderdb = new ReminderDb(context);SQLiteDatabase db = reminderdb.getReadableDatabase();String notification_check = null;

Page 106: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 104 από 150

switch(interval) {case 1:

notification_check =ReminderDb.COLUMN_NAME_REMINDER_ONE_MINUTE_NOTIFICATION;

break;case 2:

notification_check =ReminderDb.COLUMN_NAME_REMINDER_ONE_HOUR_NOTIFICATION;

break;

}

String newQuery = "SELECT " + notification_check + " FROM " +ReminderDb.TABLE_NAME + " WHERE " +

ReminderDb.COLUMN_NAME_MEDICINE_TITLE +" = \"" + title + "\";";

Cursor c = db.rawQuery(newQuery, null);

c.moveToFirst();

if (c.getCount() > 0) {String value = c.getString(0);

if ( value == null || value.equals("null") || value.equals("N")) {c.close();reminderdb.close();db.close();return true;

} else {c.close();reminderdb.close();

Page 107: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 105 από 150

db.close();return false;

}}

c.close();reminderdb.close();db.close();

return false;}

public static void disableNotification(Context context, int interval, String title) {ReminderDb reminderdb = new ReminderDb(context);SQLiteDatabase db = reminderdb.getReadableDatabase();String notification_check = null;

switch(interval) {case 1:

notification_check =ReminderDb.COLUMN_NAME_REMINDER_ONE_MINUTE_NOTIFICATION;

break;case 2:

notification_check =ReminderDb.COLUMN_NAME_REMINDER_ONE_HOUR_NOTIFICATION;

break;

}

Page 108: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

3 Ανατομία Android OS και MedReminder

Σελίδα 106 από 150

String query = "UPDATE " + ReminderDb.TABLE_NAME + " SET " +notification_check +

" = \"Y\" WHERE " +ReminderDb.COLUMN_NAME_MEDICINE_TITLE + " = " + "\"" + title + "\";";

db.execSQL(query);

reminderdb.close();db.close();

}

public static String getID(Context context, String title) {ReminderDb reminderdb = new ReminderDb(context);SQLiteDatabase db = reminderdb.getReadableDatabase();

String query = "SELECT " + ReminderDb.COLUMN_NAME_MEDICINE_ID

+ " FROM " + ReminderDb.TABLE_NAME + " WHERE " +ReminderDb.COLUMN_NAME_MEDICINE_TITLE + " = \"" + title + "\"

LIMIT 1;";

Cursor c = db.rawQuery(query, null);

c.moveToFirst();

String d = c.getString(0);

reminderdb.close();db.close();

return d;}

}

Page 109: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Σελίδα 107 από 150

ΚΕΦΑΛΑΙΟ 4: Εγχειρίδιο Χρήσεως

4.1) Χρήση για πρώτη φορά

Εφόσον η εγκατάσταση στη κινητή σας συσκευή ολοκληρώθηκε με επιτυχία,

είτε μέσω του ατομικού σας υπολογιστή με καλώδιο σύνδεσης τύπου USB, ή

μέσω του Play Store με τη λήψη του *.apk ( android application package ), θα

εμφανιστεί στην οθόνη της κινητής σας συσκευής το παρακάτω εικονίδιο της

εφαρμογής MedReminder. Αρκεί ένα “ χτύπημα ” στην οθόνη για την εκκίνησή

της, όπως και για τις λοιπές εφαρμογές, και αφότου εκκινήσει θα εμφανιστεί η

εξής οθόνη [ Εικόνα 4.1.1 ], εάν χρησιμοποιείτε την εφαρμογή για πρώτη φορά

ή κάποια διαδοχική χωρίς να έχετε θέσει κάποια υπενθύμιση.

4.2) Περιγραφή και χρήση μονής ειδοποίησης

Το μόνο αλληλεπιδρόμενο μέλος στην εφαρμογή τη δεδομένη στιγμή είναι το

κουμπί “ Προσθήκη “ Υπενθύμισης Φαρμάκου ” όπως και σαφώς η ανεξάρτητη

χρήση της μπάρας καταστάσεως ( status bar ) της κινητής σας συσκευής [ Εικόνα

4.2.1 ]. Επιλέγοντας το κουμπί “ Προσθήκη Υπενθύμισης Φαρμάκου ”

μεταβαίνετε στην παρακάτω οθόνη με τις επιλογές εισαγωγής “ Όνομα Φαρμάκου

”, “ Ημ/νία ”, “ Ώρα ” και στο δεξί μέρος του παραθύρου μία επιλογή checkbox (

επιλογή με “ χτύπημα ” ) ονόματι “ Επιλογές Επανάληψης ” , καθώς και στο τέλος

των επιλογών το κουμπί “ Προσθήκη Υπενθύμισης ” [ Εικόνα 4.2.2 ].

Page 110: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

4 Εγχειρίδιο Χρήσεως

Σελίδα 108 από 150

Εικόνα 4.1.1 Εικόνα 4.2.1 Εικόνα 4.2.2

Οι τρόποι χρήσης της εφαρμογής για να θέσετε μία υπενθύμιση είναι δύο:

Α - Εάν επιθυμείτε μία υπενθύμιση για μία φορά, τότε πιέστε το κενό πλαίσιο

παραπλεύρως του πλαισίου “ Όνομα Φαρμάκου ” και εισάγετε την ονομασία του

σκευάσματος για το οποίο επιθυμείτε να δημιουργήσετε μία ειδοποίηση.

Ακολούθως επιλέξτε το κενό πλαίσιο παραπλεύρως του πλαισίου “ Ημ/νία ” και

θα εμφανιστεί ένα νέο παράθυρο μικρότερο του παραθύρου της εφαρμογής στην

οθόνη σας το οποίο θα εμφανίζει τη τρέχουσα ημέρα, μήνα και έτος [ Εικόνα 4.2.3

]. Σύρετε την αριστερή στήλη καθέτως για τη διαχείριση των ημερών, τη μεσαία

στήλη καθέτως και πάλι για τη διαχείριση του μηνός και τη τελευταία, δεξιά στήλη

και πάλι καθέτως για να ορίσετε το επιθυμητό έτος. Σαν επιβεβαίωση της

επιλογής προβάλεται η οριζόμενη ημερομηνία στο άνω άκρο του μικρότερου

παραθύρου και για την αποθήκευση αυτής αρκεί να πατήσετε το κουμπί “ Τέλος

”, που βρίσκεται στο κάτω άκρο του μικρότερου παραθύρου ή ένα χτύπημα σε

οποιοδήποτε σημείο της οθόνης της συσκευής σας πλην της περιοχής του

Page 111: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 109 από 150

παραθύρου της “ Ημ/νίας ”. Έπειτα επιλέξτε το κενό πλαίσιο παραπλεύρως του

πλαισίου “ Ώρα ” και θα εμφανιστεί ένα νέο παράθυρο μικρότερο του παραθύρου

της εφαρμογής στην οθόνη σας το οποίο θα απεικονίζει ένα ψηφιακό ρολόι με

δωδεκάωρη μορφή ( 12 h ) και αντίστοιχη ένδειξη A.M. ( Προ Μεσημβρίας ) και

P.M. ( Μετά Μεσημβρίας ) [ Εικόνα 4.2.4 ].

Η ώρα που θα εμφανίζει είναι η ώρα τη δεδομένη στιγμή που χειρίζεστε την

εφαρμογή, για να θέσετε την επιθυμητή ώρα υπενθύμισης σύρετε την αριστερή

στήλη καθέτως για τη ρύθμιση της ώρας, έπειτα τη μεσαία στήλη καθέτως και

αυτή και τέλος τη τρίτη στήλη, δεξιά, για ορισμό A.M. ή P.M. στην ώρα της

ειδοποιήσεως. Για την αποθήκευση της προτιμώμενης ώρας υπενθύμισης αρκεί

να πατήσετε το κουμπί “ Τέλος ” ή ένα χτύπημα σε οποιοδήποτε σημείο της

οθόνης της κινητής σας συσκευής πλην της περιοχής του παραθύρου της “ Ώρας

” [ Εικόνα 4.2.5 ].

Έχοντας ολοκληρώσει τη διαδικασία του προγραμματισμού της ειδοποιήσεως το

μόνο που απομένει, είναι να πατήσετε το κουμπί “ Προσθήκη Υπενθύμισης ” και

η υπενθύμισή σας έχει ολοκληρωθεί. Θα παρατηρήσετε ότι μεταφερθήκατε στην

αρχική οθόνη με το κουμπί “ Προσθήκη Υπενθύμισης Φαρμάκου ” , όμως κάτω

από αυτό βρίσκεται στο αριστερό άκρο η ονομασία του φαρμακευτικού

σκευάσματός σας και στο δεξί άκρο η ορισμένη ώρα και ημερομηνία ειδοποίησης

[ Εικόνα 4.2.6 ]. Εάν έχετε κάνει λάθος σε κάποια παράμετρο μπορείτε να

διαγράψετε την ειδοποίηση πατώντας παρατεταμένα το πλαίσιο της υπενθύμισης

προς διαγραφή, και έπειτα να ετοιμάσετε μία νέα ακολουθώντας την ίδια

διαδικασία, από το σημείο Α .

Page 112: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

4 Εγχειρίδιο Χρήσεως

Σελίδα 110 από 150

Εικόνα 4.2.3 Εικόνα 4.2.4 Εικόνα 4.2.5 Εικόνα 4.2.6

4.3) Τρόποι ειδοποίησης μονής ειδοποιήσεως

Εφόσον όλα κύλησαν ομαλώς θα λάβετε δύο ειδοποιήσεις για τη συγκεκριμένη

υπενθύμιση. Μία ειδοποίηση στη μπάρα κατάστασης ( status bar ) της κινητής

συσκευής σας μία ( 1 ) ώρα πριν την ορισμένη ώρα και ημερομηνία που θα

αναφέρει ότι σε μία ώρα πρέπει να λάβετε το φαρμακευτικό σας σκεύασμα [

Εικόνα 4.3.1 ], η οποία θα συνοδεύεται από τόνο και δόνηση της κινητής

συσκευής σας, όπως και ειδοποίηση λυχνίας, ένα υπάρχει η δυνατότητα αυτή

στη συσκευή σας. Η δεύτερη ειδοποίηση θα είναι ένα λεπτό πριν την ορισμένη

ώρα και ημερομηνία ειδοποιήσεως, η οποία θα σας ενημερώνει ότι πρέπει να

πάρετε το φάρμακό σας. Θα εμφανιστεί και αυτή στη μπάρα κατάστασης ( status

bar ) της κινητής συσκευής και θα συνοδεύεται από τόνο και δόνηση της κινητής

συσκευής σας, όπως και ειδοποίηση λυχνίας, εάν υπάρχει η δυνατότητα αυτή

στη συσκευή σας [ Εικόνα 4.3.2 ] .

Page 113: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 111 από 150

Εικόνα 4.3.1 Εικόνα 4.3.2

4.4) Περιγραφή και χρήση επαναλαμβανόμενης

ειδοποίησης

Β – Εάν επιθυμείτε μία επαναλαμβανόμενη ειδοποίηση, τότε εφόσον πιέσετε το

πλαίσιο παραπλέυρως του πλαισίου “ Όνομα Φαρμάκου ” και εισάγετε το όνομα

του σκευάσματός σας, έπειτα “ χτυπήστε ” το κουτάκι στο δεξί και άνω μέρος της

οθόνης με όνομα “ Επιλογές Επανάληψης ”. Θα καταδυθεί ένα νέο παράθυρο

μικρότερο του αρχικού της εφαρμογής στο οποίο σας παρουσιάζονται τρεις ( 3 )

επιλογές επανάληψης [ Εικόνα 4.4.1 ]. Ι) Κάθε 8 ώρες ΙΙ) Κάθε 12 ώρες ΙΙΙ) Κάθε

24 ώρες. Εάν θέλετε επανάληψη ειδοποίησης από τη τωρινή ώρα κάθε 8 ώρες

απλώς πατάτε το κουμπί “ Προσθήκη Υπενθύμισης ” και επανέρχεστε στην

αρχική οθόνη της εφαρμογής, όπου βλέπετε το κουμπί “ Προσθήκη Υπενθύμισης

Page 114: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

4 Εγχειρίδιο Χρήσεως

Σελίδα 112 από 150

Φαρμάκου ” και κάτω από αυτό υπάρχει στο αριστερό άκρο της οθόνης το όνομα

του σκευάσματός σας και στο δεξί άκρο το μήνυμα “Ορισμένη Επανάληψη ” [

Εικόνα 4.4.2 ].

Σε περίπτωση που θέλετε επανάληψη ειδοποίησης από τη τωρινή ώρα κάθε 12

ώρες, πρέπει να “ χτυπήσετε ” το κουτάκι αριστερά από τη “ Κάθε 12 ώρες ” και

έπειτα να ακυρώστε την επιλογή “Κάθε 8 ώρες ” “ χτυπώντας ” το κουτάκι στα

αριστερά αυτής. Η επιβεβαίωση της σωστής διαδικασίας επιτυγχάνεται από τη

παρουσία ή μη αναλόγως της διαδικασίας επιλογής ή ακύρωσης του συμβόλου “

ν ” στα αντίστοιχα κουτάκια του παραθύρου της επαναλήψεως της ειδοποιήσεως.

Έπειτα πατάτε το κουμπί “ Προσθήκη Υπενθύμισης ” και επανέρχεστε στην

αρχική οθόνη της εφαρμογής, όπου βλέπετε το κουμπί “ Προσθήκη Υπενθύμισης

Φαρμάκου ” και κάτω από αυτό υπάρχει στο αριστερό άκρο της οθόνης το όνομα

του σκευάσματός σας και στο δεξί άκρο το μήνυμα “Ορισμένη Επανάληψη ”. Σε

περίπτωση που θέλετε επανάληψη ειδοποίησης από τη τωρινή ώρα κάθε 24

ώρες, πρέπει να “χτυπήσετε ” το κουτάκι αριστερά από τη “ Κάθε 24 ώρες ” και

έπειτα να ακυρώστε την επιλογή “Κάθε 8 ώρες” “χτυπώντας ” το κουτάκι στα

αριστερά αυτής.

Η επιβεβαίωση της σωστής διαδικασίας επιτυγχάνεται από τη παρουσία ή μη

αναλόγως της διαδικασίας επιλογής ή ακύρωσης του συμβόλου “ ν ” στα

αντίστοιχα κουτάκια του παραθύρου της επαναλήψεως της ειδοποιήσεως.

Έπειτα πατάτε το κουμπί “Προσθήκη Υπενθύμισης ” και επανέρχεστε στην

αρχική οθόνη της εφαρμογής, όπου βλέπετε το κουμπί “Προσθήκη Υπενθύμισης

Φαρμάκου ” και κάτω από αυτό υπάρχει στο αριστερό άκρο της οθόνης το όνομα

του σκευάσματός σας και στο δεξί άκρο το μήνυμα “Ορισμένη Επανάληψη ”. Σε

συνδιαστική περίπτωση μπορείτε να επιλέξετε και τις τρεις διαθέσιμες

επαναλήψεις υπενθύμισης, ακολουθώντας τη παραπάνω διαδικασία, δίχως τη

διαδικασία της ακύρωσης.

Σε περίπτωση που δεν επιθυμείτε τελικά, επαναλαμβανόμενη υπενθύμιση,

ακυρώστε το κουτάκι στο αριστερό μέρος του πλαισίου κειμένου “ Επιλογές

Επανάληψης ”. Εφόσον το ακυρώσετε θα επανεμφανιστούν τα πεδία “ Ημ/νία

και Ώρα ” και θα επανέρθετε στο προηγούμενο παράθυρο της εφαρμογής. Εάν

Page 115: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 113 από 150

έχετε κάνει λάθος σε κάποια παράμετρο μπορείτε να διαγράψετε την ειδοποίηση

πατώντας παρατεταμένα το πλαίσιο της υπενθύμισης προς διαγραφή, και έπειτα

να ετοιμάσετε μία νέα ακολουθώντας την ίδια διαδικασία, από το σημείο Β .

Εικόνα 4.4.1 Εικόνα 4.4.2

4.5) Τρόποι ειδοποίησης επαναλαμβανόμενων ειδοποιήσεων

Εφόσον όλα κύλησαν ομαλώς θα λαμβάνετε ειδοποιήσεις στα καθορισμένα

χρονικά πλαίσια αενάως ή μέχρις ότου διαγράψετε τις συγκεκριμένες

υπενθυμίσεις. Η ειδοποίηση θα σας ενημερώνει ότι πρέπει να πάρετε το φάρμακό

σας, στο προεπιλεγμένο χρονικό πλαίσιο. Θα εμφανιστεί στη μπάρα κατάστασης

( status bar ) της κινητής συσκευής και θα συνοδεύεται από τόνο και δόνηση της

κινητής συσκευής σας, όπως και ειδοποίηση λυχνίας, εάν υπάρχει η δυνατότητα

αυτή στη συσκευή σας [ Εικόνα 4.5.1 ]. Καταληκτικά για την έξοδό σας από την

εφαρμογή μπορείτε είτε να “ χτυπήσετε ” το κουμπί της επιστροφής ή το

αντίστοιχο κουμπί της αρχικής οθόνης της κινητής σας συσκευής.

Page 116: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

4 Εγχειρίδιο Χρήσεως

Σελίδα 114 από 150

Εικόνα 4.5.1

Page 117: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Σελίδα 115 από 150

ΣΥΜΠΕΡΑΣΜΑΤΑ

5.1) Συμπεράσματα σχεδίασης της εφαρμογής

Η δημιουργία και συγγραφή μίας εφαρμογής σε λειτουργικό Android απαιτεί

γνώση γλώσσας προγραμματισμού Java και μέρος της πολυπλοκότητας της

C++. Για τη κατανόηση της μεθόδου και του τρόπο δόμησης μίας οποιαδήποτε

εφαρμογής Android, υπάρχει πληθώρα οπτικοακουστικού υλικού με

καθοδηγήσεις κατανοητές ακόμη και εάν το ενδιαφερόμενο μέλος είναι αδαές από

προγραμματιστικής πλευράς. Η επιτελούμενη εφαρμογή εάν και όχι πολύπλοκη

μου επέτρεψε να κατανοήσω την ελευθερία σχεδιασμού που προσφέρει η

πλατφόρμα του Android Studio μέσω του Google SDK και ότι αναμφισβήτητα η

δημιουργία εφαρμογών για την αυτοματοποίηση ή διευκόλυνση κάποιων

διεργασιών που αντιμετωπίζουμε κάποιο πρόβλημα, θα επιφέρει μελλοντική

λύση σε συνανθρώπους μας που αντιμετωπίζουν το ίδιο πρόβλημα ή θα

αντιμετωπίσουν αργότερα στη ζωή τους.

Αποτελεί σαφώς κλάδο πλήρους ενασχόλησης, καθότι οι ανθρώπινες ανάγκες

γεννιούνται και κατακερματίζονται αένεα. Τη συγκεκριμένη εφαρμογή τη

χρησιμοποίησε και συνεχίζει να χρησιμοποιεί η οικογένειά μου, με μεγάλη

ευχαρίστηση καθώς μία υπενθύμιση για κάτι σημαντικό προσφέρει τόσο

αποφυγή κινδύνου διαταραχής του κύκλου δοσοληψίας όσο και ικανοποίηση

ενθύμισης λήψεως του σκευάσματος αυτού, ειδικότερα σε μεγαλύτερες ηλικίες.

Page 118: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

5 Συμπεράσματα

Σελίδα 116 από 150

5.2) Προοπτικές μελλοντικής αξιοποίησης αυτής

Επιθυμητό θα ήταν οι ηλικιωμένοι να είχαν την απλούστερη συσκευή με

λειτουργικό Android και όταν πήγαιναν στο φαρμακείο για την αγορά των

μηνιαίων κ.ο.κ. φαρμάκων τους ο/η φαρμακοποιός να περάτωνε το

προγραμματισμό λήψης αυτών ή και ο/η ιατρός μετά από κάποια ενδεχόμενη

επίσκεψη που θα επέβαλε συνταγογράφηση φαρμάκων, ως ενίσχυση του

οποιουδήποτε υπάρχοντος τρόπου υπενθύμισης λήψεως ( νοητική – γραφική ).

Φυσικά, η εφαρμογή επιδέχεται βελτιώσεων, μπορούν να τοποθετηθούν

περισσότερες ειδοποιήσεις πριν την καταληκτική για επιπρόσθετη προετοιμασία,

ή ακόμη και με προσθήκη πλαισίου σχολίων για χρησιμοποίηση σε κάποιο

ιδιωτικό ίδρυμα με ηλικιωμένους και να αντικαταστήσει το κλασσικό ντοσιέ

ονόματος – φαρμάκου – ώρα λήψεως. Όπως και ένα πρόγραμμα για την

αυτόματη ενημέρωση και ανταλλαγή σχολίων μεταξύ ιατρού/φαρμακοποιού και

χρήστη για τυχόν επιπλοκές ή απορίες ( απαίτηση εξοικίωσης με την τεχνολογία).

Εναλλακτικά μπορεί να χρησιμοποιήθει και ως απλός υπενθυμητής κάποιας

συνάντησης ή κάποιας ανειλλημένης υποχρέωσης ή ως κοινό ημερολόγιο με

δυνατότητας ειδοποίησης.

Page 119: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Σελίδα 117 από 150

ΒΙΒΛΙΟΓΡΑΦΙΑ

[1] Android ( operating system ) https://en.wikipedia.org/wiki/Android

_(operating_system), 2015

[2] Android version history, https://en.wikipedia.org/wiki/Android_version

_history, 2015

[3] James Rogerson, “Microsoft might put Android apps on Windows Phone,”

http://www.techradar.com/news/phone-and-communications/mobile-

phones/microsoft-might-bring-android-apps-to-windows-phone-1281244, 20

Ιανουαρίου, 2015, σελίδες 1 – 2.

[4] Android Package, https://developer.android.com/reference/android/

package-summary.html, 2015

[5] Tutorialspoint.com, “Android Tutorial,” Εκδόσεις tutorialspoint.com,

http://www.tutorialspoint.com/android/android_pdf_version.htm, 2014

[6] Build System Overview, https://developer.android.com/sdk/installing

/studio-build.html, 2015

[7] Debugging, https://developer.android.com/tools/debugging/index.html,

2015

[8] Logcat, https://developer.android.com/tools/help/logcat.html, 2015

[9] Android Debug Bridge, https://developer.android.com/tools/help/adb.html,

2015

[10] Dalvik Debug Monitor Server, https://developer.

android.com/tools/debugging/ddms.html, 2015

[11] Michael Burton, και Donn Felker, “Android Application Development For

Dummies 2nd Edition,” Hoboken, New Jersey, Εκδόσεις john Wiley & Sons,

2012, σελίδες 1 – 411.

Page 120: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Βιβλιογραφία

Σελίδα 118 από 150

[12] Wei-Meng Lee, “Beginning Android 4 Application Development,”

Hoboken, New Jersey, Εκδόσεις john Wiley & Sons, 2011, σελίδες 1 – 564.

Page 121: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Σελίδα 119 από 150

ΠΑΡΑΡΤΗΜΑ

MedReminder

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="lamarko.android.medicinereminder" >

<uses-permission

android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<uses-permission

android:name="android.permission.VIBRATE" />

<uses-permission

android:name="android.permission.SET_ALARM" />

<application

android:allowBackup="true"android:icon="@drawable/medr"android:label="@string/app_name"android:theme="@style/AppTheme" >

<activity

android:name=".MedListActivity"

Page 122: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 120 από 150

android:label="@string/app_name" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity

android:name=".NewMedReminder"android:label="@string/title_activity_new_reminder"android:parentActivityName=".MedListActivity" >

<meta-data

android:name="android.support.PARENT_ACTIVITY"android:value=".MedListActivity" />

</activity>

<service

android:name="lamarko.android.medicinereminder.NotificationService" />

<receiver

android:name=".OnBootReceiver" >

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED" />

</intent-filter>

</receiver>

</application>

</manifest>

med_list.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="lamarko.android.medicinereminder.MedListActivity"tools:ignore="MergeRootFrame"/>

Page 123: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 121 από 150

med_list_fragment.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/linlayout_main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="#F5F5DC"

tools:context="lamarko.android.medicinereminder.MedListActivity$PlaceholderFragment"

>

<Button

android:id="@+id/add_med"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="NewReminder"android:text="@string/add_medicine" />

<View

android:layout_width="fill_parent"android:layout_height="3dip"android:layout_marginBottom="7dip"android:layout_marginTop="10dip"android:background="@android:color/holo_orange_light" />

<LinearLayout

android:id="@+id/layout_dump"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" >

</LinearLayout>

<LinearLayout

android:layout_width="fill_parent"android:layout_height="fill_parent">

<ImageView

android:layout_width="fill_parent"android:layout_height="fill_parent"android:adjustViewBounds="true"android:scaleType="fitCenter"android:src="@drawable/main_pic"/>

</LinearLayout>

Page 124: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 122 από 150

</LinearLayout>

new_med.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="lamarko.android.medicinereminder.NewMedReminder"tools:ignore="MergeRootFrame" />

new_med_fragment.xml

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="10dp"android:paddingLeft="5dp"android:paddingRight="5dp"android:paddingTop="10dp"android:orientation="vertical"android:background="#EEE8AA"

tools:context="lamarko.android.medicinereminder.NewMedReminder$PlaceholderFragment" >

<LinearLayout

android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<TextView

android:id="@+id/vtitle"android:maxLength="100"android:layout_width="90dp"android:layout_height="wrap_content"

Page 125: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 123 από 150

android:paddingBottom="10dp"android:text="@string/title"android:textSize="@dimen/font_size"/>

<EditText

android:id="@+id/etitle"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="0.55"android:ems="10"android:inputType="text"android:maxLength="30"android:autoText="true" />

<CheckBox

android:id="@+id/repeatloop"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="indefiniteAction"android:text="@string/repeatloop"android:layout_weight="0.05"android:textSize="12sp" />

</LinearLayout>

<LinearLayout

android:id="@+id/linlayout_date"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<TextView

android:id="@+id/vdate"android:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:paddingBottom="15dp"android:text="@string/date"android:textSize="15sp"/>

<EditText

android:id="@+id/edate"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="3"

Page 126: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 124 από 150

android:ems="10"android:inputType="date"android:focusable="false"android:onClick="datePickerAction" />

</LinearLayout>

<LinearLayout

android:id="@+id/linlayout_time"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<TextView

android:id="@+id/vtime"android:layout_weight="1"android:layout_width="0dp"android:layout_height="wrap_content"android:paddingBottom="15dp"android:text="@string/time"android:textSize="15sp"/>

<EditText

android:id="@+id/etime"android:layout_weight="3"android:layout_width="0dp"android:layout_height="wrap_content"android:ems="10"android:inputType="time"android:focusable="false"android:onClick="timePickerAction" />

</LinearLayout>

<View

android:id="@+id/view_bar1"android:layout_width="fill_parent"android:layout_height="1dip"android:layout_marginBottom="5dip"android:layout_marginTop="5dip"android:background="@android:color/holo_orange_light"android:visibility="gone" />

<LinearLayout

android:id="@+id/linlayout_repeat"android:layout_width="match_parent"

Page 127: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 125 από 150

android:layout_height="wrap_content"android:orientation="vertical"android:visibility="gone" >

<CheckBox

android:id="@+id/eight_hours"android:layout_width="wrap_content"android:layout_height="wrap_content"android:checked="false"android:onClick="EightHourAction"android:text="@string/eighthours" />

<CheckBox

android:id="@+id/twelve_hours"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/twelvehours"android:onClick="TwelveHourAction" />

<CheckBox

android:id="@+id/twentyfour_hours"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/twentyfourhours"android:onClick="TwentyfourHourAction" />

</LinearLayout>

<View

android:layout_width="fill_parent"android:layout_height="3dip"android:layout_marginBottom="10dip"android:layout_marginTop="10dip"android:background="@android:color/holo_orange_light" />

<LinearLayout

android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<Button

android:id="@+id/add_med"android:layout_width="match_parent"android:layout_height="match_parent"android:text="@string/add_med"android:onClick="SaveReminderData" />

Page 128: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 126 από 150

</LinearLayout>

</LinearLayout>

med_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"tools:context="lamarko.android.medreminder.MedListActivity">

<item

android:id="@+id/action_settings"android:orderInCategory="100"app:showAsAction="never"android:title="@string/action_settings"/>

</menu>

new_med_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"tools:context="lamarko.android.medreminder.NewMedReminder">

<item

android:id="@+id/action_settings"android:orderInCategory="100"app:showAsAction="never"android:title="@string/action_settings"/>

</menu>

dimens.xml

<resources>

<dimen name="activity_horizontal_margin">16dp</dimen>

<dimen name="activity_vertical_margin">16dp</dimen>

<dimen name="font_size">15sp</dimen>

</resources>

Page 129: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 127 από 150

strings.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>

<string name="app_name">MedReminder</string>

<string name="action_settings">Settings</string>

<string name="title_activity_new_reminder">New Reminder</string>

<string name="add_medicine">Add Medicine Reminder</string>

<string name="title">Name of Medicine</string>

<string name="date">Date</string>

<string name="add_med">Add Med</string>

<string name="time">Time</string>

<string name="repeatloop">Choose usage times</string>

<string name="eighthours">Every 8h</string>

<string name="twelvehours">Every 12h</string>

<string name="twentyfourhours">Every 24h</string>

<string name="rep_loops">Repeating Loops</string>

<string name="not_8h">Every 8h for your</string>

<string name="not_12h">Every 12h for your</string>

<string name="not_24h">Every 24h for your</string>

<string name="not_now">Prepare and take your</string>

<string name="not_1h">One hour until your</string>

<string name="hello_blank_fragment">Hello blank fragment</string>

</resources>

strings-el.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>

<string name="app_name">MedReminder</string>

<string name="action_settings">Ρυθμίσεις</string>

<string name="title_activity_new_reminder">New Reminder</string>

<string name="add_medicine">Προσθήκη Υπενθύμισης Φαρμάκου</string>

<string name="title">Όνομα Φαρμάκου</string>

<string name="date">Ημ/νία</string>

<string name="add_med">Προσθήκη Υπενθύμισης</string>

Page 130: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 128 από 150

<string name="time">Ώρα</string>

<string name="repeatloop">Επιλογές Επανάληψης</string>

<string name="eighthours">Κάθε 8 ώρες</string>

<string name="twelvehours">Κάθε 12 ώρες</string>

<string name="twentyfourhours">Κάθε 24 ώρες</string>

<string name="rep_loops">Καθορισμένες Επαναλήψεις</string>

<string name="not_8h">Κάθε 8 ώρες για το</string>

<string name="not_12h">Κάθε 12 ώρες για το</string>

<string name="not_24h">Κάθε 24 ώρες για το</string>

<string name="not_now">Λάβετε το</string>

<string name="not_1h">Ακόμη μία ώρα για το</string>

<string name="hello_blank_fragment">Hello blank fragment</string>

</resources>

styles.xml

<resources>

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

</style>

</resources>

ComDialogFragment.java

package lamarko.android.medicinereminder;import android.app.AlertDialog;import android.app.Dialog;import android.app.DialogFragment;import android.content.DialogInterface;import android.os.Bundle;public class ComDialogFragment extends DialogFragment {

private String message = "";public void setMessage(String message) {

this.message = message;}

Page 131: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 129 από 150

@Override

public Dialog onCreateDialog(Bundle savedInstanceState) {AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());builder.setMessage(this.message)

.setNegativeButton("Ok", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int id) {}

});return builder.create();

}}

DatePickerFragment.java

package lamarko.android.medicinereminder;import java.util.Calendar;import android.app.Dialog;import android.app.DialogFragment;import android.app.DatePickerDialog;import android.os.Bundle;import android.widget.DatePicker;import android.widget.TextView;public class DatePickerFragment extends DialogFragment implementsDatePickerDialog.OnDateSetListener {

public Dialog onCreateDialog(Bundle savedInstanceState) {final Calendar c = Calendar.getInstance();int year = c.get(Calendar.YEAR);int month = c.get(Calendar.MONTH);int day = c.get(Calendar.DAY_OF_MONTH);return new DatePickerDialog(getActivity(), this, year, month, day);

}@Override

public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {TextView tv = (TextView) getActivity().findViewById(R.id.edate);tv.setText(dayOfMonth + "/" + (monthOfYear + 1) + "/" + year);

}}

Page 132: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 130 από 150

TimePickerFragment.java

package lamarko.android.medicinereminder;import java.util.Calendar;import android.app.Dialog;import android.app.DialogFragment;import android.app.TimePickerDialog;import android.os.Bundle;import android.widget.TextView;import android.widget.TimePicker;public class TimePickerFragment extends DialogFragment implementsTimePickerDialog.OnTimeSetListener {

public Dialog onCreateDialog(Bundle savedInstanceState) {final Calendar c = Calendar.getInstance();int hour = c.get(Calendar.HOUR_OF_DAY);int minute = c.get(Calendar.MINUTE);return new TimePickerDialog(getActivity(), this, hour, minute, false);

}public void onTimeSet(TimePicker view, int hourOfDay, int minute) {

TextView tv = (TextView) getActivity().findViewById(R.id.etime);int tmp_hour = hourOfDay;String AM_PM = null;if (hourOfDay > 11) {

tmp_hour = tmp_hour - 12;AM_PM = "PM";

} else {

AM_PM = "AM";

}

if (tmp_hour == 0) {

tmp_hour = 12;

}

String __hour = String.format("%02d", tmp_hour);

String __min = String.format("%02d", minute);

tv.setText(__hour + ":" + __min + " " + AM_PM);

}

}

Page 133: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 131 από 150

MedListActivity.java

package lamarko.android.medicinereminder;import java.text.SimpleDateFormat;import java.util.Date;import android.app.Activity;import android.app.Fragment;import android.content.Intent;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.os.Bundle;import android.text.InputFilter;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnLongClickListener;import android.view.ViewGroup.LayoutParams;import android.view.ViewGroup;import android.widget.Button;import android.widget.LinearLayout;import android.widget.TextView;public class MedListActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.med_list);

if (savedInstanceState == null) {getFragmentManager().beginTransaction()

.add(R.id.container, new PlaceholderFragment()).commit();}System.out.println("Start service");

Intent i = new Intent(this, NotificationService.class);startService(i);

}protected void onStart() {

Page 134: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 132 από 150

super.onStart();}protected void onResume() {

super.onResume();Button add = (Button) findViewById(R.id.add_med);if (! add.isEnabled()) {

LinearLayout ll = (LinearLayout) findViewById(R.id.layout_dump);ll.removeAllViews();this.buildDynamicUI();add.setEnabled(true);

} else {LinearLayout ll = (LinearLayout) findViewById(R.id.layout_dump);ll.removeAllViews();this.buildDynamicUI();

}}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.med_menu, menu);return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {int id = item.getItemId();if (id == R.id.action_settings) {

return true;}return super.onOptionsItemSelected(item);

}public static class PlaceholderFragment extends Fragment {

public PlaceholderFragment() {}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {

Page 135: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 133 από 150

View rootView = inflater.inflate(R.layout.med_list_fragment, container,false);

return rootView;}

}

public void NewReminder(View v) {v.setEnabled(false);Intent i = new Intent(this, NewMedReminder.class);startActivity(i);

}private void buildDynamicUI() {

ReminderDb memo = new ReminderDb(getBaseContext());SQLiteDatabase db = memo.getReadableDatabase();

String[] projection = {ReminderDb.COLUMN_NAME_MEDICINE_TITLE,ReminderDb.COLUMN_NAME_MEDICINE_EPOCH,ReminderDb.COLUMN_NAME_REPEAT

};String sortOrder = ReminderDb.COLUMN_NAME_MEDICINE_ID + " ASC";Cursor c = db.query(

ReminderDb.TABLE_NAME,projection,null,null,null,null,sortOrder

);c.moveToFirst();for (int i = 0; i < c.getCount(); i++) {

int index_title =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_MEDICINE_TITLE);

int index_time =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_MEDICINE_EPOCH);

int index_repeat =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_REPEAT);

TextView title = new TextView(this);

Page 136: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 134 από 150

title.setLayoutParams(newLinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT, 1f));

title.setFilters(new InputFilter[] { new InputFilter.LengthFilter(30)});title.setTextAppearance(this, android.R.style.TextAppearance_Medium);title.setText(c.getString(index_title));title.setTextSize(15);title.setPadding(10, 5, 10, 5);TextView time = new TextView(this);time.setLayoutParams(new

LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT, 3f));

time.setTextSize(10);String repeatloop = c.getString(index_repeat);if (repeatloop.equals("N")) {

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm a");String tmp_date = sdf.format(new Date(Long.parseLong(c.getString(index_time))));time.setText(tmp_date);

} else if (repeatloop.equals("Y")) {time.setText(R.string.rep_loops);

}time.setPadding(10, 5, 10, 5);LinearLayout ll = (LinearLayout) findViewById(R.id.layout_dump);LinearLayout lh = new LinearLayout(this);lh.setId(i);lh.setOrientation(LinearLayout.HORIZONTAL);lh.addView(title);lh.addView(time);lh.setOnLongClickListener(new OnLongClickListener() {

@Override

public boolean onLongClick(View v) {String title = (String) ((TextView) ((ViewGroup) v).getChildAt(0)).getText();String selection = ReminderDb.COLUMN_NAME_MEDICINE_TITLE + " = ?";String[] selectionArgs = {

title,};ReminderDb memo = new ReminderDb(getBaseContext());SQLiteDatabase db = memo.getWritableDatabase();ReminderDb.getID(getApplicationContext(), title);

Page 137: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 135 από 150

db.delete(ReminderDb.TABLE_NAME, selection, selectionArgs);

v.setVisibility(View.GONE);return false;

}

});

ll.addView(lh);c.moveToNext();

}}

}

NewMedReminder.java

package lamarko.android.medicinereminder;import java.text.ParseException;import android.app.Activity;import android.app.DialogFragment;import android.app.Fragment;import android.content.Intent;import android.os.Bundle;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.ViewGroup;import android.widget.CheckBox;import android.widget.LinearLayout;import android.widget.TextView;public class NewMedReminder extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.new_med);

Page 138: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 136 από 150

if (savedInstanceState == null) {getFragmentManager().beginTransaction()

.add(R.id.container, new PlaceholderFragment()).commit();}

}public void onBackPressed() {

finish();}

@Override

public boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.new_med_menu, menu);return true;

}@Override

public boolean onOptionsItemSelected(MenuItem item) {int id = item.getItemId();if (id == R.id.action_settings) {

return true;}return super.onOptionsItemSelected(item);

}public static class PlaceholderFragment extends Fragment {

public PlaceholderFragment() {}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {

View rootView = inflater.inflate(R.layout.new_med_fragment,container, false);

return rootView;}

}public void SaveReminderData(View v) throws ParseException {

v.setEnabled(false);CheckBox repeat = (CheckBox) findViewById(R.id.repeatloop);TextView title_view = (TextView) findViewById(R.id.etitle);TextView date_view = (TextView) findViewById(R.id.edate);TextView time_view = (TextView) findViewById(R.id.etime);

Page 139: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 137 από 150

if (title_view.length() == 0) {v.setEnabled(true);ComDialogFragment t = new ComDialogFragment();t.setMessage("Εισάγετε φάρμακο - Insert medicine");t.show(this.getFragmentManager(), "badData");return;

}if (! repeat.isChecked() ) {

if (time_view.length() == 0) {v.setEnabled(true);ComDialogFragment t = new ComDialogFragment();t.setMessage("Εισάγετε ώρα - Insert time");t.show(this.getFragmentManager(), "badData");return;

}if ( date_view.length() == 0 ) {

v.setEnabled(true);ComDialogFragment t = new ComDialogFragment();t.setMessage("Εισάγετε ημ/νία - Insert date");t.show(this.getFragmentManager(), "badData");return;

}ReminderDb.addReminder(

getApplicationContext(),title_view.getText().toString(),false,false,false,false,date_view.getText().toString(),time_view.getText().toString()

);} else if (repeat.isChecked()) {

CheckBox eighthours = (CheckBox) findViewById(R.id.eight_hours);CheckBox twelvehours = (CheckBox) findViewById(R.id.twelve_hours);CheckBox twentyfourhours= (CheckBox) findViewById(R.id.twentyfour_hours);

Page 140: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 138 από 150

ReminderDb.addReminder(getApplicationContext(),title_view.getText().toString(),true,eighthours.isChecked(),twelvehours.isChecked(),twentyfourhours.isChecked(),"0",

"0"

);}Intent i = new Intent(getApplicationContext(), NotificationService.class);startService(i);finish();

}public void datePickerAction(View v) {

DialogFragment frag = new DatePickerFragment();frag.show(this.getFragmentManager(), "datePicker");

}public void timePickerAction(View v) {

DialogFragment frag = new TimePickerFragment();frag.show(this.getFragmentManager(), "timePicker");

}public void indefiniteAction(View v) {

CheckBox c = (CheckBox) v;CheckBox eighthours = (CheckBox) findViewById(R.id.eight_hours);CheckBox twelvehours = (CheckBox) findViewById(R.id.twelve_hours);CheckBox twentyfourhours = (CheckBox) findViewById(R.id.twentyfour_hours);View bar = (View) findViewById(R.id.view_bar1);LinearLayout l1 = (LinearLayout) findViewById(R.id.linlayout_date);LinearLayout l2 = (LinearLayout) findViewById(R.id.linlayout_time);LinearLayout l3 = (LinearLayout) findViewById(R.id.linlayout_repeat);if ( c.isChecked() ) {

l1.setVisibility(l1.GONE);l2.setVisibility(l2.GONE);eighthours.setChecked(true);eighthours.setEnabled(false);bar.setVisibility(v.VISIBLE);l3.setVisibility(l3.VISIBLE);

Page 141: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 139 από 150

} else {l1.setVisibility(l1.VISIBLE);l2.setVisibility(l2.VISIBLE);eighthours.setChecked(false);eighthours.setEnabled(true);twelvehours.setChecked(false);twelvehours.setEnabled(true);twentyfourhours.setChecked(false);twentyfourhours.setEnabled(true);bar.setVisibility(v.GONE);l3.setVisibility(l3.GONE);

}}public void EightHourAction(View v) {

CheckBox eighthour = (CheckBox) v;CheckBox twelvehour = (CheckBox) findViewById(R.id.twelve_hours);CheckBox twentyfourhour = (CheckBox) findViewById(R.id.twentyfour_hours);if ( eighthour.isChecked() ) {

twelvehour.setEnabled(true);twentyfourhour.setEnabled(true);

}}public void TwelveHourAction(View v) {

CheckBox twelvehour = (CheckBox) v;CheckBox eighthour = (CheckBox) findViewById(R.id.eight_hours);CheckBox twentyfourhour = (CheckBox) findViewById(R.id.twentyfour_hours);if ( twelvehour.isChecked() ) {

eighthour.setEnabled(true);twentyfourhour.setEnabled(true);

}}public void TwentyfourHourAction(View v) {

CheckBox twentyfourhour = (CheckBox) v;CheckBox eighthour = (CheckBox) findViewById(R.id.eight_hours);CheckBox twelvehour = (CheckBox) findViewById(R.id.twelve_hours);if ( twentyfourhour.isChecked() ) {

eighthour.setEnabled(true);twelvehour.setEnabled(true);

}

Page 142: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 140 από 150

}}

OnBootReceiver.java

package lamarko.android.medicinereminder;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;public class OnBootReceiver extends BroadcastReceiver {

@Override

public void onReceive(Context context, Intent intent) {context.startService(new Intent(context, NotificationService.class));

}}

NotificationService.java

package lamarko.android.medicinereminder;import java.util.LinkedList;import android.app.AlarmManager;import android.app.IntentService;import android.app.NotificationManager;import android.app.PendingIntent;import android.content.Context;import android.content.Intent;import android.media.RingtoneManager;import android.net.Uri;import android.os.Vibrator;import android.support.v4.app.NotificationCompat;import android.util.Log;

public class NotificationService extends IntentService {private final int ONE_HOUR = 3600;private final int ONE_MINUTE = 60;private final int VIBRATE_TIME = 2000;private static int Aloopcounter = 0;

Page 143: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 141 από 150

private static int Bloopcounter = 0;private static int Cloopcounter = 0;public NotificationService() {

super("NotificationService");}private void Notify(Intent intent) {

PendingIntent pendingmain = PendingIntent.getActivity(getApplicationContext(),intent.getIntExtra("id", 0), intent, 0);

NotificationCompat.Builder notification = newNotificationCompat.Builder(getApplicationContext());

notification.setSmallIcon(R.drawable.medr);notification.setContentTitle(intent.getStringExtra("reminder"));notification.setContentText(intent.getStringExtra("string"));notification.setContentIntent(pendingmain);notification.setAutoCancel(true);NotificationManager notificationmanager = (NotificationManager)

getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);Vibrator v = (Vibrator)

getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);v.vibrate(this.VIBRATE_TIME);notification.setSound(soundUri);notificationmanager.notify(intent.getIntExtra("id", 0), notification.build());

}@Override

protected void onHandleIntent(Intent intent) {Log.v("NotificationService", "Starting NotificationService run");LinkedList<String[]> list;list = ReminderDb.getReminderTimes(getApplicationContext());long system_time = System.currentTimeMillis();AlarmManager arm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0);arm.setInexactRepeating(AlarmManager.RTC_WAKEUP, system_time + 60 * 1000,60000,

pintent);for (int i = 0; i < list.size(); i++) {

String[] data = list.get(i);if (data[2].equals("N")) {

long delta = Long.parseLong(data[1]) - System.currentTimeMillis();Log.v("NotificationService", "TIME REMAINING: " + delta);

Page 144: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 142 από 150

Log.v("NotificationService", "1 HOUR: " + this.ONE_HOUR * 1000);Log.v("NotificationService", "60 SECONDS" + this.ONE_MINUTE * 1000);Log.v("NotificationService", "In reminder loop");Intent intent1 = new Intent(this, MedListActivity.class);intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);if ( delta < this.ONE_MINUTE * 1000 ) {

Log.v("NotificationService", "IN 60");if (ReminderDb.checkNotify(getApplicationContext(), 1, data[0])) {

System.out.println("IN 1b");intent1.putExtra("string", data[0]);intent1.putExtra("reminder", "Λάβετε το - Now");intent1.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));this.Notify(intent1);ReminderDb.disableNotification(getApplicationContext(), 1, data[0]);

}} else if ( delta < this.ONE_HOUR * 1000 && delta> this.ONE_MINUTE * 1000) {

Log.v("NotificationService", "IN 1");if (ReminderDb.checkNotify(getApplicationContext(), 2, data[0])) {

intent1.putExtra("string", data[0]);intent1.putExtra("reminder", "Ακόμη μία ώρα για το - 1h" );intent1.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));this.Notify(intent1);ReminderDb.disableNotification(getApplicationContext(), 2, data[0]);

}}

} else if ( data[2].equals("Y") ) {if ( data[3].equals("Y") ) {

Log.v("NotificationService", "8h_reminder" + data[0]);if (this.Aloopcounter == 3 ) {

this.Aloopcounter = 0;intent.putExtra("string", data[0]);intent.putExtra("reminder", "Κάθε 8 ώρες για το - 8h");intent.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));this.Notify(intent);

}

Page 145: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 143 από 150

this.Aloopcounter += 1;}if ( data[4].equals("Y") ) {

Log.v("NotificationService", "12h_reminder" + data[0]);if ( this.Bloopcounter == 720) {

this.Bloopcounter = 0;intent.putExtra("string", data[0]);intent.putExtra("reminder", "Κάθε 12 ώρες για το - 12h");intent.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));this.Notify(intent);

}this.Bloopcounter += 1;

}if ( data[5].equals("Y") ) {

Log.v("NotificationService", "24h_reminder" + data[0]);if ( this.Cloopcounter == 1440) {

this.Cloopcounter = 0;intent.putExtra("string", data[0]);intent.putExtra("reminder", "Κάθε 24 ώρες για το - 24h");intent.putExtra("id", Integer.parseInt(10 +

ReminderDb.getID(getApplicationContext(), data[0])));this.Notify(intent);

}this.Cloopcounter += 1;

}}

}Log.v("NotificationService", "Ending NotificationService run");

}}

ReminderDB.java

package lamarko.android.medicinereminder;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;

Page 146: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 144 από 150

import java.util.LinkedList;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;

public class ReminderDb extends SQLiteOpenHelper {public static final int DATABASE_VERSION = 12;public static final String DATABASE_NAME = "reminder.db";public static final String TABLE_NAME = "reminder";public static final String COLUMN_NAME_MEDICINE_ID = "medicine_id";public static final String COLUMN_NAME_MEDICINE_EPOCH = "medicine_epoch";public static final String COLUMN_NAME_MEDICINE_TITLE = "medicine_title";public static final String COLUMN_NAME_REPEAT = "repeat";public static final String COLUMN_NAME_EIGHT_HOURS = "eight_hours";public static final String COLUMN_NAME_TWELVE_HOURS = "twelve_hours";public static final String COLUMN_NAME_TWENTYFOUR_HOURS = "twentyfour_hours";public static final String COLUMN_NAME_REMINDER_ONE_HOUR_NOTIFICATION =

"one_hour_notification";public static final String COLUMN_NAME_REMINDER_ONE_MINUTE_NOTIFICATION =

"one_minute_notification";public static final String SQL_CREATE_TABLE =

"CREATE TABLE " + ReminderDb.TABLE_NAME + " (" +ReminderDb.COLUMN_NAME_MEDICINE_ID + " INTEGER PRIMARY KEY

AUTOINCREMENT," +ReminderDb.COLUMN_NAME_MEDICINE_TITLE + " TEXT UNIQUE ON

CONFLICT IGNORE," +ReminderDb.COLUMN_NAME_REPEAT + " TEXT," +ReminderDb.COLUMN_NAME_EIGHT_HOURS + " TEXT," +ReminderDb.COLUMN_NAME_TWELVE_HOURS + " TEXT," +ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS + " TEXT," +ReminderDb.COLUMN_NAME_REMINDER_ONE_HOUR_NOTIFICATION + "

TEXT," +ReminderDb.COLUMN_NAME_REMINDER_ONE_MINUTE_NOTIFICATION + "

TEXT," +ReminderDb.COLUMN_NAME_MEDICINE_EPOCH + " TEXT);";

public static final String SQL_DELETE_TABLE ="DROP TABLE IF EXISTS " + ReminderDb.TABLE_NAME;

Page 147: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 145 από 150

public ReminderDb(Context context) {super(context, ReminderDb.DATABASE_NAME, null,

ReminderDb.DATABASE_VERSION);}

@Override

public void onCreate(SQLiteDatabase db) {db.execSQL(SQL_CREATE_TABLE);

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {db.execSQL(ReminderDb.SQL_DELETE_TABLE);onCreate(db);

}public static void addReminder(Context context, String title,

boolean repeat, boolean eight_hours,boolean twelve_hours, boolean twentyfour_hours, String dateString,String timeString) throws ParseException {

ReminderDb reminderdb = new ReminderDb(context);SQLiteDatabase db = reminderdb.getWritableDatabase();ContentValues values = new ContentValues();values.put(ReminderDb.COLUMN_NAME_MEDICINE_TITLE, title);if (repeat) {

values.put(ReminderDb.COLUMN_NAME_REPEAT, "Y");values.put(ReminderDb.COLUMN_NAME_MEDICINE_EPOCH, "0");if (eight_hours == true && twelve_hours == false && twentyfour_hours == false) {

values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS, "N");

} else if (eight_hours == false && twelve_hours == true && twentyfour_hours == false){

values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS, "N");

} else if (eight_hours == false && twelve_hours == false && twentyfour_hours == true){

values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS, "Y");

} else if (eight_hours == true && twelve_hours == true && twentyfour_hours == false) {

Page 148: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 146 από 150

values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS, "N");

} else if (eight_hours == true && twelve_hours == false && twentyfour_hours == true) {values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS, "Y");

} else if (eight_hours == false && twelve_hours == true && twentyfour_hours == true) {values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS, "Y");

} else if (eight_hours == true && twelve_hours == true && twentyfour_hours == true) {values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "Y");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS, "Y");

}} else if ( ! repeat) {

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm a");Date d = sdf.parse(dateString + " " + timeString);long epoch = d.getTime();System.out.println("EPOCH:" + epoch);values.put(ReminderDb.COLUMN_NAME_EIGHT_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWELVE_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS, "N");values.put(ReminderDb.COLUMN_NAME_REPEAT, "N");values.put(ReminderDb.COLUMN_NAME_MEDICINE_EPOCH, epoch);values.put(ReminderDb.COLUMN_NAME_MEDICINE_TITLE, title);

}try {

db.insert(ReminderDb.TABLE_NAME, "null", values);} catch (Exception e ) {}db.close();reminderdb.close();

}public static LinkedList<String[]> getReminderTimes(Context context) {

LinkedList<String[]> list = new LinkedList<String[]>();ReminderDb reminderdb = new ReminderDb(context);SQLiteDatabase db = reminderdb.getReadableDatabase();

Page 149: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 147 από 150

String[] projection = {ReminderDb.COLUMN_NAME_MEDICINE_TITLE,ReminderDb.COLUMN_NAME_MEDICINE_EPOCH,ReminderDb.COLUMN_NAME_REPEAT,ReminderDb.COLUMN_NAME_EIGHT_HOURS,ReminderDb.COLUMN_NAME_TWELVE_HOURS,ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS

};String sortOrder = ReminderDb.COLUMN_NAME_MEDICINE_EPOCH + " ASC";Cursor c = db.query(

ReminderDb.TABLE_NAME,projection,null,null,null,null,

sortOrder

);c.moveToFirst();for (int i = 0; i < c.getCount(); i++) {

int index_title =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_MEDICINE_TITLE);

int index_time =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_MEDICINE_EPOCH);

int index_repeat =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_REPEAT);

int index_eight =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_EIGHT_HOURS);

int index_twelve =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_TWELVE_HOURS);

int index_twentyfour =c.getColumnIndexOrThrow(ReminderDb.COLUMN_NAME_TWENTYFOUR_HOURS);

String[] data = {c.getString(index_title),c.getString(index_time),c.getString(index_repeat),c.getString(index_eight),c.getString(index_twelve),c.getString(index_twentyfour)

Page 150: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 148 από 150

};list.add(data);c.moveToNext();

}reminderdb.close();db.close();return list;

}public static boolean checkNotify(Context context, int interval, String title) {

ReminderDb reminderdb = new ReminderDb(context);SQLiteDatabase db = reminderdb.getReadableDatabase();String notification_check = null;switch(interval) {

case 1:notification_check =

ReminderDb.COLUMN_NAME_REMINDER_ONE_MINUTE_NOTIFICATION;break;

case 2:notification_check =

ReminderDb.COLUMN_NAME_REMINDER_ONE_HOUR_NOTIFICATION;break;

}String newQuery = "SELECT " + notification_check + " FROM " +

ReminderDb.TABLE_NAME + " WHERE " +ReminderDb.COLUMN_NAME_MEDICINE_TITLE +

" = \"" + title + "\";";Cursor c = db.rawQuery(newQuery, null);c.moveToFirst();if (c.getCount() > 0) {

String value = c.getString(0);

if ( value == null || value.equals("null") || value.equals("N")) {c.close();reminderdb.close();db.close();return true;

}

Page 151: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Πτυχιακή εργασία του Λάμπρου Μάρκου

Σελίδα 149 από 150

else { c.close();reminderdb.close();db.close();return false;

}}c.close();reminderdb.close();db.close();return false;

}public static void disableNotification(Context context, int interval, String title) {

ReminderDb reminderdb = new ReminderDb(context);SQLiteDatabase db = reminderdb.getReadableDatabase();String notification_check = null;

switch(interval) {case 1:

notification_check =ReminderDb.COLUMN_NAME_REMINDER_ONE_MINUTE_NOTIFICATION;

break;case 2:

notification_check =ReminderDb.COLUMN_NAME_REMINDER_ONE_HOUR_NOTIFICATION;

break;}String query = "UPDATE " + ReminderDb.TABLE_NAME + " SET " + notification_check +

" = \"Y\" WHERE " + ReminderDb.COLUMN_NAME_MEDICINE_TITLE + " = " + "\"" +title + "\";";

db.execSQL(query);reminderdb.close();db.close();

}public static String getID(Context context, String title) {

ReminderDb reminderdb = new ReminderDb(context);SQLiteDatabase db = reminderdb.getReadableDatabase();String query = "SELECT " + ReminderDb.COLUMN_NAME_MEDICINE_ID + " FROM " +

ReminderDb.TABLE_NAME + " WHERE " +ReminderDb.COLUMN_NAME_MEDICINE_TITLE + " = \"" + title + "\" LIMIT 1;";

Cursor c = db.rawQuery(query, null);

Page 152: TEI EMTdigilib.teiemt.gr/jspui/bitstream/123456789/2626/1/022015x05x111.p… · Η εκπόνηση της εργασίας αυτής αποτελεί την ολοκλήρωση

Παράρτημα

Σελίδα 150 από 150

c.moveToFirst();String d = c.getString(0);reminderdb.close();db.close();return d;

}}