Mobiltelefonapplikationer med Java ME: Lektion 12

Idag: Location-API:et programmen SimpleGPSTest1, SimpleGPSTest2 och GPSTest2.
Programmet använder Location-API:et (GPS), och är dessutom ett exempel på ett lite större program än vad vi sett hittills.

Ljudspåret är inte klart än!

Klicka på startknappen i den lilla mediespelaren ovan för att lyssna på lektionen. (Man kan behöva vänta en stund på att ljudfilen laddas ner.) Om mediespelaren inte syns, eller om det inte fungerar av något annat skäl, kan man klicka här för att ladda ner mp3-filen (ca xx minuter, ca xx megabyte). Beroende på hur webbläsaren är konfigurerad kan det kräva ett separat mp3-spelarprogram av något slag.

Bild 1: Telefoner med inbyggd GPS-mottagare

Telefonen till vänster, Sony Ericsson W760i, är ett exempel på en telefon med inbyggd GPS-mottagare. (Från 2008.)

Sony Ericsson W760i och W800i

Bild 2: GPS-mottagaren kan hitta var man är

Från Java kan man få fram aktuell position.

Aktuell position

Bild 3: Ett Java-program kan använda det, till exempel för att rita en karta

Java-programmet kan använda informationen från GPS-mottagaren, till exempel för att rita en karta över var man varit:

En karta

Bild 4: Location-API:et

Klasserna i Location-API:et

Bild(er) 5: Programmet SimpleGPSTest1: LocationProvider

SimpleGPSTest-1.png     SimpleGPSTest-2.png

Bild(er) 6: Programmet SimpleGPSTest1: Location

SimpleGPSTest-3.png     SimpleGPSTest-4.png     SimpleGPSTest-5.png

Bild(er) 7: Programmet SimpleGPSTest1: Koordinater

SimpleGPSTest-6.png     SimpleGPSTest-7.png

Bild 8: Att simulera GPS-koordinater i emulatorn

SimpleGPSTest-8.png

Bild(er) 9: Simulerade och riktiga koordinater

SimpleGPSTest-9.png     SimpleGPSTest-w760i

"Bild" 10: Programmet SimpleGPSTest1

Ett första försök som inte fungerar helt perfekt: SimpleGPSTest1.java

    1   // SimpleGPSTest1 -- a program that tests your GPS using the Java ME Location API
    2   // By Thomas Padron-McCarthy (padrone@lysator.liu.se)
    3   // Latest change to this file: March 31, 2009
    4   // No copyright. No warranty. No nothing. Share and enjoy!
    5   
    6   import javax.microedition.midlet.*;
    7   import javax.microedition.lcdui.*;
    8   import javax.microedition.location.*;
    9   
   10   public class SimpleGPSTest1 extends MIDlet implements CommandListener {
   11       private Display display;
   12       private Form form = new Form("Simple GPS Test");
   13       private Command get_lp_command = new Command("Get LP", "Get Location Provider", Command.SCREEN, 1);
   14       private Command get_location_command = new Command("Get Location", Command.SCREEN, 0);
   15       private Command get_coordinates_command = new Command("Get Coordinates", Command.SCREEN, 1);
   16       private Command exit_command = new Command("Exit", Command.EXIT, 2);
   17   
   18       public SimpleGPSTest1() { }
   19   
   20       public void destroyApp(boolean unconditional) { }
   21   
   22       public void pauseApp() { }
   23   
   24       public void startApp() {
   25           display = Display.getDisplay(this);
   26           display.setCurrent(form);
   27   
   28           form.addCommand(get_lp_command);
   29           form.addCommand(get_location_command);
   30           form.addCommand(get_coordinates_command);
   31           form.addCommand(exit_command);
   32           form.setCommandListener(this);
   33   
   34           display.setCurrent(form);
   35       }
   36   
   37       public void commandAction(Command c, Displayable s) {
   38           if (c == exit_command) {
   39               destroyApp(true);
   40               notifyDestroyed();
   41           }
   42           else if (c == get_lp_command) {
   43               get_lp();
   44           }
   45           else if (c == get_location_command) {
   46               get_location();
   47           }
   48           else if (c == get_coordinates_command) {
   49               get_coordinates();
   50           }
   51           else {
   52               Alert alert = new Alert("Internal error", "This can't happen!", null, null);
   53               alert.setTimeout(Alert.FOREVER);
   54               display.setCurrent(alert);
   55           }
   56       } // commandAction
   57   
   58       private LocationProvider lp;
   59   
   60       private void get_lp() {
   61           try {
   62               lp = LocationProvider.getInstance(null);
   63               StringItem item = new StringItem("Location Provider: ", "" + lp);
   64               form.append(item);
   65           }
   66           catch(LocationException e) {
   67               Alert alert = new Alert("LocationException",
   68                                       "There was a location problem when trying to get a location provider: " + e,
   69                                       null, null);
   70               alert.setTimeout(Alert.FOREVER);
   71               display.setCurrent(alert);
   72           }
   73           catch(Throwable e) {
   74               Alert alert = new Alert("Throwable", "Some other, unexpected problem occured when trying to get a location provider: " + e,
   75                                       null, null);
   76               alert.setTimeout(Alert.FOREVER);
   77               display.setCurrent(alert);
   78           }
   79       }
   80   
   81       private Location location;
   82   
   83       private void get_location() {
   84           if (lp == null) {
   85               Alert alert = new Alert("Wrong!", "You need to get a location provider before you can get a location.",
   86                                       null, null);
   87               alert.setTimeout(Alert.FOREVER);
   88               display.setCurrent(alert);
   89           }
   90           else {
   91               try {
   92                   StringItem waiting_item = new StringItem("Trying to get a location...", "");
   93                   form.append(waiting_item);
   94                   location = lp.getLocation(-1); // Here is a possible problem...
   95                   StringItem location_item = new StringItem("Location: ", "" + location);
   96                   form.append(location_item);
   97                   StringItem valid_item = new StringItem("Location isValid(): ", "" + location.isValid());
   98                   form.append(valid_item);
   99               }
  100               catch(LocationException e) {
  101                   Alert alert = new Alert("LocationException",
  102                                           "There was a location problem when trying to get a location: " + e,
  103                                           null, null);
  104                   alert.setTimeout(Alert.FOREVER);
  105                   display.setCurrent(alert);
  106               }
  107               catch(InterruptedException e) {
  108                   Alert alert = new Alert("InterruptedException", "Reached timeout when trying to get a location: " + e,
  109                                           null, null);
  110                   alert.setTimeout(Alert.FOREVER);
  111                   display.setCurrent(alert);
  112               }
  113               catch(SecurityException e) {
  114                   Alert alert = new Alert("SecurityException", "You weren't allowed to get a location: " + e,
  115                                           null, null);
  116                   alert.setTimeout(Alert.FOREVER);
  117                   display.setCurrent(alert);
  118               }
  119               catch(Throwable e) {
  120                   Alert alert = new Alert("Throwable", "Some other, unexpected problem occured when trying to get a location: " + e,
  121                                           null, null);
  122                   alert.setTimeout(Alert.FOREVER);
  123                   display.setCurrent(alert);
  124               }
  125           }
  126       } // get_location
  127   
  128       private void get_coordinates() {
  129           if (location == null) {
  130               Alert alert = new Alert("Wrong!", "You need to get a location before you can get the coordinates.",
  131                                       null, null);
  132               alert.setTimeout(Alert.FOREVER);
  133               display.setCurrent(alert);
  134           }
  135           else if (location.isValid() == false) {
  136               Alert alert = new Alert("Wrong!", "You need to get a valid location before you can get the coordinates.",
  137                                       null, null);
  138               alert.setTimeout(Alert.FOREVER);
  139               display.setCurrent(alert);
  140           }
  141           else {
  142               QualifiedCoordinates qc = location.getQualifiedCoordinates();
  143               double latitude = qc.getLatitude();
  144               double longitude = qc.getLongitude();
  145               double accuracy = qc.getHorizontalAccuracy();
  146   
  147               StringItem latitude_item = new StringItem("Latitude: ", "" + latitude);
  148               form.append(latitude_item);
  149               StringItem longitude_item = new StringItem("Longitude: ", "" + longitude);
  150               form.append(longitude_item);
  151               StringItem accuracy_item = new StringItem("Accuracy: ", "" + accuracy);
  152               form.append(accuracy_item);
  153           }
  154       } // get_coordinates
  155   
  156   } // SimpleGPSTest1

"Bild" 11: Programmet SimpleGPSTest2

Metoden get_location ur klassen SimpleGPSTest2 från filen SimpleGPSTest2.java:

 
    1       private void get_location() {
    2           if (lp == null) {
    3               Alert alert = new Alert("Wrong!", "You need to get a location provider before you can get a location.",
    4                                       null, null);
    5               alert.setTimeout(Alert.FOREVER);
    6               display.setCurrent(alert);
    7           }
    8           else {
    9               Runnable r = new Runnable() {
   10                       public void run() {
   11   
   12                           try {
   13                               StringItem waiting_item = new StringItem("Trying to get a location...", "");
   14                               form.append(waiting_item);
   15                               location = lp.getLocation(-1);
   16                               StringItem location_item = new StringItem("Location: ", "" + location);
   17                               form.append(location_item);
   18                               StringItem valid_item = new StringItem("Location isValid(): ", "" + location.isValid());
   19                               form.append(valid_item);
   20                           }
   21                           catch(LocationException e) {
   22                               Alert alert = new Alert("LocationException",
   23                                                       "There was a location problem when trying to get a location: " + e,
   24                                                       null, null);
   25                               alert.setTimeout(Alert.FOREVER);
   26                               display.setCurrent(alert);
   27                           }
   28                           catch(InterruptedException e) {
   29                               Alert alert = new Alert("InterruptedException", "Reached timeout when trying to get a location: " + e,
   30                                                       null, null);
   31                               alert.setTimeout(Alert.FOREVER);
   32                               display.setCurrent(alert);
   33                           }
   34                           catch(SecurityException e) {
   35                               Alert alert = new Alert("SecurityException", "You weren't allowed to get a location: " + e,
   36                                                       null, null);
   37                               alert.setTimeout(Alert.FOREVER);
   38                               display.setCurrent(alert);
   39                           }
   40                           catch(Throwable e) {
   41                               Alert alert = new Alert("Throwable", "Some other, unexpected problem occured when trying to get a location: " + e,
   42                                                       null, null);
   43                               alert.setTimeout(Alert.FOREVER);
   44                               display.setCurrent(alert);
   45                           }
   46   
   47                       } // run
   48                   }; // Runnable
   49               Thread t = new Thread(r);
   50               t.start();
   51           }
   52       } // get_location

Bild(er) 12: Programmet GPSTest2: Criteria

Programmet finns här: GPSTest2.java

GPSTest2 i emulatorn     GPSTest2 i emulatorn     GPSTest2 i emulatorn

Bild(er) 13: Programmet GPSTest2: LocationProvider

GPSTest2 i emulatorn     GPSTest2 i emulatorn     GPSTest2 i emulatorn     GPSTest2 i emulatorn

Bild(er) 14: Programmet GPSTest2: Location

GPSTest2 i emulatorn     GPSTest2 i emulatorn     GPSTest2 i emulatorn     GPSTest2 i emulatorn

Bild(er) 15: Programmet GPSTest2: Kartor och markeringar

GPSTest2 i emulatorn     GPSTest2 i emulatorn     GPSTest2 i emulatorn

Bild(er) 16: Riktiga kartor

GPSTest2 på riktigt     GPSTest2 på riktigt

Bild(er) 17: Mätfel

Här har telefonen legat stilla, först mitt ute på en fotbollsplan (dvs med bra sikt till GPS-satelliterna), och sen inomhus (dvs med dålig sikt till GPS-satelliterna).

GPSTest2 på riktigt     GPSTest2 på riktigt

Läsanvisningar

Man kan läsa mer om Location-API:et och GPS i kapitel 27, Know Where You Are, i den nya kursboken Kicking Butt with MIDP and MSA.

Den gamla kursboken Beginning J2ME tar inte upp Location-API:et.

Programmeringsövningar

  1. Provkör programmen SimpleGPSTest2 och GPSTest2, först i emulatorn och sen, om du har en sån, i en riktig GPS-telefon. Fungerar det?
  2. Vad händer om man försöker köra programmen på en telefon som inte har GPS?
  3. Studera programmet SimpleGPSTest2. Kunde man tänkt lite mer objektorienterat, och till exempel gjort en egen Alert-klass som ärver från vanliga Alert, i stället för att upprepa samma kod varje gång ett felmeddelande ska skrivas ut? Eller kanske bara samlat det i en metod?
  4. Studera programmet GPSTest2. Det är ett lite större program, med fler klasser, och lite mer objektorienterat tänkt. Till exempel finns nu klassen MyAlert, som ärver från den vanliga Alert-klassen och anpassar den lite. Här år några andra klasser man kan titta på: Vad kunde ha gjorts bättre i det här programmet, så att programmet blir lättare att förstå och arbeta vidare med?
  5. Med programmet GPSTest2 kan man prova hur snabb och noggrann en telefons GPS är, och vilken inverkan olika värden på Criteria har. Om du har tillgång till en eller flera GPS-telefoner, undersök hur de beter sig. Lika eller olika? Bra eller dåligt?

Föregående lektion | Lektionslista | Nästa lektion


Thomas Padron-McCarthy (Thomas.Padron-McCarthy@oru.se), 31 mars 2009