Software Engineering of Geospatial Video Database iPhone

advertisement
Software Engineering of a Geospatial Video
Database and iPhone Application
John McCoey
Advisor: Dr. Thomas Way
Completed: Summer 2010
This Independent Study final report is submitted in partial fulfillment
of the requirements for the degree of
M.S. in Computer Science
Department of Computing Sciences
Villanova University
Villanova, Pennsylvania
U.S.A.
ABSTRACT
Geospatially tagged media can be an extremely useful source for understanding and virtually
exploring a given location with more detail than a map alone can provide. Currently, there is
a large assortment of applications in the iPhone App Store which offer the ability to tag
images with coordinate-based location metadata. This metadata gives users the ability to
search for images which may be of interest based on location. However, while both images
and video can be captured from the iPhone, there is no such available application for video
media. The YouTube API can tag geospatial locations to videos; however most videos found
currently on the site are improperly tagged, and are therefore cannot be applied in any useful
manner. Using the agile software engineering approach, I have planned, designed, and
implemented a geospatially tagged database which allows for the uploading and searching of
media captured from iPhone devices. Because all media in the database originates from the
GPS enabled iPhone, the user is ensured the proper geospatial reference information is
available. This study will focus on software engineering a prototype to a fully developed
system from the research and planning stages through design, implementation, and testing.
i
ACKNOWLEDGEMENTS
I would like to thank Dr. Way of the Villanova University Computing Sciences Department
for his help and guidance throughout my Independent Study.
ii
CONTENTS
Introduction
1
Chapter 1 Research and Design
1.1
Sprint 0: Ramp-up
1.2
Objective C
1.3
Database
1.4
Setup
1.4.1 WampServer
1.4.2 Subversion
1.5
Application Design
1.6
Database Design
1.6.1 Database Creation
2
2
2
2
3
4
4
5
5
6
Chapter 2 Development
2.1
Sprint 1
2.1.1 Sprint 1 Issues
2.1.2 YouTube Objective-C Library
2.2
Sprint 2
2.2.1 Linking the GData Project
2.2.2 Side Channel Approach
2.2.3 Location
2.2.4 Insert PHP
2.2.5 Search PHP
2.2.6 Search and Map Pages
2.2.7 Map Pins
2.2.8 Video Playback
7
7
7
8
8
8
9
9
10
10
11
12
13
Chapter 3 Wrap up
3.1 Sprint 3
3.2 Testing Results
3.3 Future Work
14
14
14
15
Conclusion
16
References
17
Appendices
20
iii
INTRODUCTION
The main goal of this research is to design and create an application using the Apple iPhone
SDK. The application will both record and displays geospatially tagged media in a manner
which enhances the overall value of the data. Additionally, we will look at different
databases’ handling of geospatial indexing and searching, all while using an agile approach
to Software Engineering.
Geospatially tagged media is a form of standard media which has some information about its
location, or geospatial information, associated with it. Geospatial information can refer to a
single latitude/longitude coordinate, or some form of a wider area, generally made up of a
group of coordinates. In more advanced examples, a geospatial tag may take into account the
altitude, heading, and other spatial variables to determine the location of an object.
With countless new smart phones, such as the Apple iPhone, becoming more prevalent
among cell phone owners, users constantly have access to the internet and endless data about
the world surrounding them. The most influential aspect of these smart phones is the way in
which users can share data amongst themselves, making observation data more available and
useful than ever before. The location where data is recorded immediately gives background
information to the media.
There are two main scenarios that drive the idea behind the application we are designing.
The first is a user who is interested in a certain area, whether it is somewhere they currently
are, or another location they are interested in, and would like more information about it. This
is where past images, videos, and other media recorded at a given location can give the user a
better picture of the area than a map. The second scenario is the exact opposite, where a user
looks at a certain video, and wants to know more about the environment in which it was
captured, or find more similar videos based on that location. Our single application aims to
solve both of these problems.
In order to ensure completion of at least a prototype application, our project needs detailed
designing and planning. However, due to the nature of the research and a lack of knowledge
of the existing technologies, we need the ability to change and adapt quickly to any problems
or design changes. The Agile Method to Software Engineering [1] promotes a quick start
with constant redesign to ensure a working application.
To make an application for the iPhone, a developer must use the iPhone SDK, which runs
through Apple’s XCode IDE, using the Objective-C language [2]. This is our first
experience with the language, and we will spend a good amount of preparation time just
learning the basics of the language.
The most important aspect of any of the media we capture in relation to this research is its
location. Therefore, we must make sure to choose a stable database which can quickly and
accurately handle geospatial information. This decision, as well as research into which other
technologies would be best suited for our needs, and the basics of the Objective-C language,
starts the preparation step of our research.
1
CHAPTER 1
Research and Design
1.1 Sprint 0: Ramp-up
When we decided to write an application, the iPhone was an easy choice for two reasons.
First, we already have the hardware required to develop and test the application, and
secondly, the iPhone is one of the fastest growing and most popular application markets right
now. We begin our project by outlining the proposal and creating a website with a rough
outline of our schedule, split into four sprints, available at http://csc.villanova.edu/~jmccoey.
As stated before, we are following an agile approach to software engineering, and therefore
our focus is more on implementing a working product than on full up front software design.
We still need to plan accordingly, but are ready for any changes ahead. For the first RampUp Sprint, we are following the schedule shown in [Appendix A].
1.2 Objective-C
Because we have no prior experience with application development for the iPhone, we start
on the project by researching and learning the basics of the language and the specific skills
we will need for the application. We start by following the first few chapters of Sams Teach
Yourself: iPhone Application Development [3]. Because we know the application will have
to include location services and video playback, we are focused more on the chapters later in
the book which apply to those topics.
Objective-C is an object oriented language specifically used for application development on
the Apple Mac OS and iOS, the iPhone operating system. The iPhone uses a special Cocoa
Touch API within the Objective-C languages for generating and handling a graphical
interface for user input. It is an expansion upon the C language, and accepts C code as valid
syntax. This means a programmer must control memory management, given that object
variables are pointers which can quickly fill the iPhone’s memory if not properly released
[4]. While the Cocoa API makes the user interface very simple to design within Xcode,
some of the intricacies left over from the C language give Objective-C a very steep learning
curve.
Objective-C can be downloaded for free, along with the Xcode IDE, however it can only be
run on Apple Mac OS X. In addition, there is a $99 yearly fee to join the Apple Developer
Program, which is required to deploy an application to any Apple device. It is the only way
to get an application onto an iPhone, including a personal iPhone used solely for
development and testing purposes.
1.3 Database
Selecting Objective-C as the main language for the application is not much of a choice,
beyond the initial decision to develop for the iPhone. However, we must decide between
many different databases, all of which have distinct advantages and disadvantages.
2
Some of the most popular database systems include Oracle 11g, MySQL, SQLServer, and
PostgreSQL. All of these databases support geospatial indexing, in various different ways,
and each would be more than sufficient for our application’s needs. Oracle 11g Enterprise
Edition is one of the strongest, and one which we have used before in other development
projects. The Express Edition of Oracle is free, except the geospatial functions of 11g are not
included. MySQL, which was recently purchased by Oracle, is free and supports more than
enough geospatial functions to complete our research. While MySQL cannot handle some of
the more complex features of databases, the general insert and select statements we are going
to be using, were built for speed. We will use the MySQL database because it has all the
features we need, and is extremely fast, while remaining very simple and easy to use.
There are several ways to create geospatial objects in the MySQL database, but perhaps the
most elegant, especially for single coordinate points, is the Well-Known Text, or WKT,
string format. WKT is a standard string format regulated by the Open Geospatial
Consortium to display geographic points, polygons, linestrings, and more in simple plain text
[5]. In MySQL, a spatially indexed column of GEOM objects can be populated using the
GeomFromText(WKT) method. A valid WKT is written as follows:
POINT(longitude latitude)
POLYGON((long1 lat1,long2 lat2,long3 lat3,long4 lat4,long1, lat1))
The longitude always comes before the latitude as it follows the (x, y) coordinate plane,
where the x value is longitude and the y value is latitude. For a single point, only a space
separates the values of the coordinate. The same is true for each coordinate of a polygon,
with a comma separating each of the corner points, and the first point repeating at the end to
close the polygon.
1.4 Setup
Since we have decided on a database, the next step before coding the application is setting up
the systems and environment we will be using to develop and host the project. We do not
have access to a dedicated server, and must use our own system to host the database and
server. Therefore, our entire system environment consists of three components. The first,
and most obvious, is the iPhone itself, which will host the application.
The iPhone we are using is a 3GS model, running the new iPhone operating system, iOS4.
iOS4 was released in the middle of our application development, so we needed to upgrade
our SDK and Xcode IDE at that time. This initially caused a few problems with memory
management and project references, but after reinstalling Xcode, we were able to make the
change.
Our application will be written and compiled within the Xcode IDE on our second system, a
Mac Mini running Mac OS X Snow Leopard. The OS X system can host our MySQL
database as well, but we are opting to use for a third Windows 7 PC instead. This is mostly
because we are more familiar with configuring the network and system settings within the
3
Windows operating system. Due to our unfamiliarity with the operating system, we want to
limit our OS X usage to the minimum necessary Xcode development.
1.4.1 WampServer
In order to easily create and have full access to a MySQL instance, we choose to download
and install WampServer 2.0. Wamp stands for Windows Apache MySQL PHP, and is
available as a free download under the GPL license [6]. Once installed, we can create a
quick temporary database using the included phpMyAdmin tool to familiarize with the
system.
The problem with hosting our own database on a non dedicated server is that the dynamic IP
address of our router will unpredictably change over time. To handle this, we must do two
things. First, we will register with DyDNS to create a dynamic DNS hostname which
forwards all requests to our router’s IP address [7]. DyDNS allows us to create the site
http://mccoey.selfip.net to always refer to our WampServer system. We need to make a few
changes in our local wireless router to maintain the correlation between our URL and router
IP address and to enable access from outside the network. The Linksys E1000 router which
we are using has an option for DDNS, or Dynamic Domain Name System, in order to keep
track of our IP Address. After setup, whenever the external IP address for our router
changes, a notification is sent to the DyDNS site to update the reference from the URL
http://mccoey.selfip.net to the correct new IP address. This ensures we constantly have
access to the router at that location. Secondly, once any request reaches the router, it needs
to be routed to our Windows 7 PC, and not any of the other systems connected to the wireless
router.
By assigning the Windows 7 host environment a static IP address within the local area
network adapter settings, we can use the Port Forwarding feature of our router to ensure all
requests of a certain type are directed to the Windows 7 System and can reach our
WampServer and MySQL database. Within the wireless router configuration, we forward
the ports 8080 and 3306, for Apache Server and MySQL, respectively, to the Windows 7
system.
1.4.2 Subversion
Although our development team consists of only one person, it is still important to maintain
updates, changes, and the latest code revisions in subversion. Luckily, most of our code will
be written in the Xcode IDE, which contains its own built in Subversion client. For the small
amounts of PHP code, as well as any diagrams and documentation from our WampServer,
we will use the free open source program Tortoise SVN [8].
These subversion clients must point to a subversion repository. One of the easiest
repositories to use is one maintained by the open source site SourceForge.net, although it
requires some time for a repository to be approved after creating a new account. To avoid
waiting, we are going to create a new folder to house our project on an existing SourceForge
repository we previously created and used for another class [9].
4
1.5 Application Design
Now that the setup of all of our systems is completed, we are ready to focus on the
application and database design and implementation. Based on the requirements we laid out
for the iPhone application, we designed three separate use cases for our entire system, found
in [Appendices D, E, F]. Each one of these diagrams a system architecture for how the
application will react to a user uploading media, a user searching for media on the map, and a
user playing back or viewing the media found on the map.
For the application, we create a design which includes
three pages; one to handle input of media, one for search
options, and finally one with a map or globe display.
There is no necessary order for the user to view the
different pieces of the application, and each will be
accessible at all times.
The first page we will work on, and therefore the first we
design, is the page which allows a user to upload a video
or image to the database.
The upload page requires four pieces of information: the
name of the media, a description, the media itself, and the
current location. At this time, we are choosing to select
only the current location at the time of upload, and to
leave any option to select a location for a previously
recorded image or video for a future iteration, therefore
that is not in our design.
For the search options page and the map page we will
create temporary placeholders in our design. We have a
general idea of how they will work, although at this time
we have not fully developed the design and style.
Figure 1.1
1.6 Database Design
We next design our database system using a rough ER Diagram, shown in Figure 1.2, with
options for future expansion of our application. The motive is that multiple users will have
access to this application on their iPhone, each having an individual username specifically for
MediaMap, our application. Each user is also associated with one or more account entries
which store a user’s external usernames and passwords for various sites, such as YouTube.
5
Figure 1.2
Based on this design, a user can also add other users as a friend. Each user media entry in
the database is associated with the user who uploaded it. Any media uploaded by the user
has a location and a type, at this time either photo or video.
1.6.1 Database Creation
To create the database, we simply use the phpMyAdmin tool included with WampServer.
This lets us manually add tables to a new database to create this format. An image of our
completed database is listed in [Appendix G]. When creating the location table, we must
create a geospatial index on the location column. To do this, we select the column GEOM
type, which will accept all forms of WKT geometries [10][11][12].
While we currently support only single points for the location of media, we wanted to leave
open the option for line strings or polygons. These could be particularly useful for video
which may have been recorded over a series of location, rather than a single coordinate point.
These geometries may be particularly useful for video which was recorded over a series of
locations, or while traveling, rather than a stationary point.
6
CHAPTER 2
Development
2.1 Sprint 1
The first development sprint follows the schedule found in [Appendix B]. The first few tasks
scheduled in this Sprint are remaining tasks from the Sprint 0: Ramp-Up phase of the project,
which was not fully completed on time due to some difficulties in the initial database and
port forwarding setup. These tasks took longer than expected to finish, and consequently
pushed other tasks back. The goals of Sprint 1 are to wrap up the remaining Sprint 0 tasks
and create the upload segment of the application.
At the end of this sprint, we hope to select an existing image or video from the iPhone Photo
Library or capture a new video or image and upload it into our database. Because there are
already several available applications which map the location of images from the iPhone, we
decided to start with videos. The initial design shows that we will encode the iPhone video
to Base64 and send it through an HTTP POST request to the PHP server [13]. From the
server, the PHP YouTube API uploads the video, and returns the resulting video URL [14].
At this point, the URL will be inserted into the database’s Media table, along with the user id,
location, and other video information. As stated earlier, for the location, we are currently
using only the iPhone location data available at the time of upload.
The user interface is created very easily using the Xcode Interface Builder, which is by far
our favorite part of using the Xcode IDE. It quickly lets you add and configure any number
of interface components and effortlessly connect them to outlets in the back end code, and
took only a few minutes to learn.
2.1.1 Sprint 1 Issues
Unlike the Interface Builder, however, we have several problems using the Objective-C
language itself to develop the back end of our application. It took much longer than expected
to learn the language, and even still requires looking up almost every line of code in the API
[15]. A lot of the difficulties we are encountering within the Objective-C language come
from its roots in the C language, such as the existence of pointers, and a lack of an automatic
garbage collection. Also, the long syntax and confusing variable declarations, instantiations,
and method calls make it difficult to guess which methods should be called, and how to find
new methods.
As easy as it is to complete the user interface, and even to program it to select and capture
media, getting that media into a variable which could be converted to bytes is much more
difficult. Once we get a mutable object, we still have trouble using a Base64 Encoder class
to get the data from the iPhone to our PHP server [16]. At this time, the two week Sprint is
coming to a close, and we still do not have any way to get the media we are capturing from
the iPhone to the PHP server.
7
2.1.2 YouTube Objective-C Library
As we search for more information on how to upload data to the PHP server, we discovered
that the YouTube API is available in Objective-C as well. It does not have much
documentation, but looks like it allows for a direct upload from the iPhone to YouTube. This
eliminates the need to send any encoded data to the PHP server, and we can pass along the
URL instead [17] [18].
2.2 Sprint 2
In Sprint 2, we have to redesign our overall schedule to account for the issues we ran into in
Sprint 1. A few requirements of our application change to use the YouTube Objective-C
library instead of passing the bytes to the PHP server for uploading videos. As we mentioned
earlier, uploading images to Flickr was really a secondary task, and in order to get a working
prototype, we are going to abandon the images portion for the current version. However, we
will leave the user interface for selecting images as well as the code for uploading media
using Base64 Encoding and PHP simply commented out in the code for future development.
The schedule for this sprint, found in [Appendix C], has been modified to make sure that we
will complete a working prototype at the end of the Sprint. As this is the last full
development sprint, with Sprint 3 reserved for testing and improvements, we must ensure
that the most important aspects of the application which demonstrate uploading and
searching for videos are completed.
2.2.1 Linking the GData Project
With this redesign, we first add the Google Data API to the Objective C code. There are two
ways to do this; the first is to link the project to the iPhone Static library, and the second is to
compile the source files directly into the iPhone application [19]. The first option, to
statically link the two projects, is the most efficient, as it requires less space and compilation
time for the iPhone application.
We try to link the two projects, but almost immediately run into problems when the entire
project will not compile. We are unsure of the reason, as it may have been some
environment variables, but it will not allow us to continue. Instead, we follow the second
method of compiling the code directly into the iPhone project. This will increase the amount
of code to be moved to the iPhone as well as the compilation time, but includes only the parts
of the API which we need.
After several trying to add the library several times, we finally got the code to compile and
start to work on uploading videos. However, the documentation for the Objective-C version
of the API is not very complete; including only a single example file of how to get the upload
to work. After several more days of trying, we have wasted too much time trying to get the
videos to upload, and need to move onto another option.
8
2.2.2 Side Channel Approach
In an effort to complete the project on time, we eliminate the upload functionality of the
application. Instead we quickly include another text field between the name and description
fields which holds the end of a YouTube
URL.
A URL link to every YouTube video is
standard formatted as
http://www.youtube.com/watch?v=ID,
where ID is the unique identifier for the
given video. Because the beginning of the
URL is always the same, the unique
identifier is all that we need to store in our
database. It will also make it easier if
YouTube ever changes the format of the
URL, as we will only need to change it in
one location, on the playback within of our
application.
The iPhone’s camera application natively
features the ability to upload videos to
YouTube, and because this is not a part of
the research we are trying to prove, we
utilize that built-in function to upload a
video captured outside of MediaMap to
YouTube. Once the video has been
uploaded, we follow the “Share video with
friends” link to see what the full YouTube
URL looks like. At this time, we copy the
Figure 2.1
unique video ID, open our MediaMap
application, and paste the ID into our new
text field. By doing this, we eliminate the need to upload the videos from within the
application, and instead can pass the information from the upload page on to our PHP server
as a unique text id.
2.2.3 Location
When the user clicks submit on the upload page, the MediaMap application gets the current
location, formats it as a WKT POINT String, and forwards it, along with the name, media
type, description, and YouTube link to our PHP server. To get the location using the iPhone,
we must be running the iPhone’s Location Manager device. The Location Manager can be
initialized with different settings to control how often the location is updated, and how
accurate the resulting coordinate is. We use the most accurate location type, and save the
latitude and longitude every time an update is received. This process of updating location
starts as soon as the application loads.
9
If it is the first time the user has opened the application, they are prompted with a dialog box
asking for permission to use the location services, and a purple arrow will appear in the status
bar to indicate the GPS is active. When the user clicks the “Upload Media” button, the most
recent coordinate is converted to the POINT(longitude latitude) string format, and sent with
the rest of the data as parameters to an HTTP GET request [20].
2.2.4 PHP Insert
Within the PHP WampServer on our Windows 7 system, there are two files, insert.php and
search.php, allowing a connectection via a mysql_connect statement to our database. We
then create and execute two INSERT SQL statements [21]. The first satment inserts the
video into the Media table. This creates a new unique media id number and adds the user id,
which at this time is only our single user, and therefore always 1, the link, name, date, size,
description, and type. Because we uploaded outside of the application and therefore do not
know any statistics about this video except for the form filled out by the user, we enter 0 for
the size and cannot insert the length, rating, or thumbnail, which are all left as null.
When the data is inserted into the Media table, it returns the unique media id created for that
row. That id is then used to record and associate the location of the media in the Location
table. The media id is inserted and uses MySQL’s GeomFromText method to create a
MySQL GEOM object from the WKT String. Because the Location table is geospatially
indexed, we will later be able to quickly search all media based on location [10].
2.2.5 Search PHP
The search.php page is a bit more complicated than the insert.php page, although was written
using only one advanced SQL SELECT statement. Again using mysql_connect a connection
to the database is created, and a SELECT statement is executed to get the videos which meet
our search requests. The PHP returns the results to the requestor in basic XML format [21].
This XM response will be parsed on the iPhone to determine the location and information for
all found media.
The search.php parameters consist of only the bounding box of the search area as a
POLYGON WKT String and the media type we are searching for; in this case ‘VIDEO.’
Any other search criteria could be easily added later with a modification to the PHP
parameters and SELECT statement.
The SQL SELECT statement we create searches based on location by using the MySQL
MBRContains method which returns 1 if a GEOM is within a given bounding box. By
providing the bounding box of the visible area of the map, we find the locations within the
visible area. The SQL statement selects the media information of all media from the Media
table by using a JOIN with the Location table based on the unique media id fields. Each row
of data is transformed into an XML entry and sent as a whole back to the iPhone application
[10][11].
10
2.2.6 Search and Map Pages
The Search Options and Map pages
were not designed prior to this Sprint,
and so we must now design and
create them at the same time. The
Map page is simple in that it only
contains exactly what its names
states: a map. On the other hand, the
Search Options page lists the set of
all available options for a user query.
In order to complete this page, we
first define what those searchable
options are. Because we ran out of
time due to the problems of earlier
sprints, we must adapt so that our
application handles only one type of
search, to return all videos based on
location. However, we still design
and create the Search Options page
through Interface Builder to visualize
what options a future iteration may
have.
Figure 2.2
This Search Page shown here is
included in the current version of the application, although there is no code behind any of the
interface components to change search options. It is merely a placeholder as an idea of how
the final application may function.
The options we include allow the user to decide if they want to search for all media, or just
media available within the current view area. This will be more useful in a future iteration
when there is another way to view the media besides the map, such as a table or list. The
user will also decide if they want the search to include videos, photos, or both, and will be
able to list keywords to narrow the search.
The bottom section allows the user to select if they want to see only media they personally
uploaded, or media uploaded by friends, all users, or any combination of choices. This again
is simply another way to narrow a search to meet a user’s particular needs.
2.2.7 Map Pins
Once the Insert and Search PHP pages are complete, most of the backend functionality of
searching videos is in place. The only step left to have a working prototype is to take
11
advantage of the information returned from the database query by applying it visually to the
Map Page.
The design for this page is basically just a simple MKMapView from the Cocoa Touch
library. This was the easiest of the three pages to design because the hard work of loading
the Google Earth view and enabling moving and zooming through finger gestures is already
done by the SDK. We simply choose a few settings, making sure to enable the blue blinking
dot to show the user’s current position, and set the MapType to “Hybrid”, which is a mix of
the road map and satellite views. Within just a few minutes, the view was set and ready for
our Map Pin modifications.
Next we had to add pins to the map based on the response data from the PHP on the
WampServer. The iPhone SDK comes with a built in XML Parser, which we were able to
easily use to extract the data from the
XML string. The iPhone SDK provides
an interface MKPinAnnotationView,
but no default implementation of an
MKAnnotation, so we were required to
implement our own MapPin class in
order to create and add pins to the
MapView [1]. We create an
MKAnnotation class, which gives us the
ability to drop a pin at any given
coordinate and display a default popup
with a user defined title and subtitle
[22].
However, for the MediaMap
application, we need to customize the
MKAnnotation to hold more
information than those two fields. To
do this, we override the
MKAnnotationView class in order to
change the methods which get called
when a pin is created [23]. By
changing the viewForAnnotation
method, we add an icon image for the
leftCalloutView and an arrow button for
the right callout view.
Figure 2.3
The leftCalloutView image, in this case
a YouTube icon, we use to alert the user
about the type of media each pin represents. The rightCalloutView button, seen as a blue
right pointing arrow, can be clicked to show more information. In the case of video media, it
will open the YouTube link for playback.
12
2.2.8 Video Playback
Video playback on the iPhone is relatively simple. Because there is a built-in YouTube
player, all we need to do is open the link, and the player will automatically be launched.
There are several other ways to play the video, but this was the easiest and, in our case, most
practical. The only issue with this method is that it must leave the application to launch the
player so that when the video is over, the user needs to open the MediaMap application back
up to continue.
One other video palyback method that addresses this issue and generally creates a better
experience for the user is to create a WebUIView which shows the thumbnail of the video.
When the thumbnail is clicked, the default YouTube player is launched, only this time from
within the WebUIView, which remains inside of the application [24]. Then when the video
ends, it returns the user back directly to the MediaMap Map Page.
The only problem with this method is that it required one more user click. We determined
that there was not enough space within the MediaMap Map Page to insert a WebUIView
without ruining the usability of the map itself. We investigated ways to hide the WebUIView
and force a click without the user’s knowledge, but could not find a suitable method to
achieve that goal.
13
CHAPTER 3
Completion
3.1 Sprint 3
With the playback of a video on the click of a Map Pin, our first prototype design is
completed. Sprint 3 is reserved for testing and enhancement work; however, due to some of
the setbacks early on in the project, we entered Sprint 3 already well behind schedule. In
order to finish the prototype, the length of Sprint 2 was extended, and leaves only time for
testing in Sprint 3.
To test the application, we run several iterations through the entire program flow, from
uploading a video, to searching for and viewing a video. We must make sure to use various
combinations of input characters on the upload page and to upload from different locations to
make sure the GPS is updating correctly.
3.2 Testing Results
One problem we notice right away when we start to test our application was that no matter
where the user or the pins are on the screen, the MapView always starts at the furthest zoom
level, so that the entire globe is visible. Because all of our test pins are recorded in the
Philadelphia area, it takes a lot of zooming for the user to see the difference between the
multiple pins. We did find methods online to select an initial zoom area, but were unable to
implement that before the submission of this project [25].
As far as user input goes, the name and description are URL Encoded before being sent to the
PHP servers, so anything we tested successfully makes it through the network and into our
database. The one field that matters is our side channel method for adding videos. If a bad
value is entered, the insert works with no problem, but playback from the Map View fails, as
expected, because of the bad URL. The location updates work perfectly fine as well, and is
very accurate as long as the phone has service other than WiFi. With WiFi mode only, it still
picks the correct general location, but is nowhere near as accurate as the GPS. To make sure
other areas besides Philadelphia work properly, we input different coordinates manually into
the database, including special cases such as POINT(0 0) and POINT(-180 90).
We are pleasantly surprised with how quickly the entire system runs. We added a “Shake to
reload” feature to the maps to allow a user to shake the iPhone and populate the screen with
the latest database information. We found that after inserting information into the database,
it shows up in the search query almost instantly, or at least as fast as we can switch to the
Map Page and shake the iPhone.
One bug that we have been unable to solve is a memory leak somewhere. As we mentioned
earlier, Objective-C relies heavily on the C language and pointers without the use of an
automatic garbage collector. Therefore, it is the programmer’s responsibility to find and
remove any unused pointers and allocated memory. Somewhere our code does not handle
14
the memory allocation and release correctly, and the application will sometimes, particularly
after several requests, run out of memory and crash.
3.3 Future Work
The prototype version of MediaMap that we are submitting as the result of this Independent
Study is far from a complete application. There are several missing features, most notably
the inability to upload any media, the inclusion of videos only, and the lack of functionality
on the Search Page. But in the short two month period of time, we created a working
application from design to prototype that proves the possibility of a geospatially aware video
database which can be viewed and queried by location on the iPhone Map View.
With that said, there are some definite areas of expansion, besides the pieces which have
already been listed as incomplete. As mentioned earlier, we created five database tables, but
for the most part, only access two of them, media and location. The ultimate goal of this
application is to act as an additional form of social networking information. A user will add
and remove friends, and share videos and other media captured from their phone directly
with other users. Our current setup has only one user, and it is the default for all media
added to the database, but we left the database structure open to more users. The ability to
create a MediaMap account which would store all of the user information and other websites’
account usernames and passwords opens up the possibility for a single sign on application
which allows a user to update multiple different sites with more types of media than video
from within the single application.
One feature we missed from the Map View during testing was the ability to type in any
address and have the globe immediately navigate to that location. In the current iteration, the
user is presented with a globe and must manually navigate to anywhere they want to do. It
would be a huge enhancement to incorporate more features into MediaMap, such as reverse
geocoding, searching by address, and directions. Or, in a much later iteration, we would
hope to integrate directly with the built-in Google Maps application which already has these
features. Currently, it is not possible to modify the built-in maps or other standard iPhone
applications at all, and that option may never be possible.
The most valuable part of the application is its openness to modification and expansion. In a
future iteration, the application could also interact with more sites than just YouTube or
Flickr, for instance updating a user’s Facebook or Twitter account when a new media is
posted. We could also allow for plaintext notes to be posted, which could take the form of a
Facebook status update marked with a location of the user’s position. Some other types of
media which we did not include at all in our initial prototype, but are available for capture on
the iPhone include audio, drawings, weather and traffic updates, contact information, and
calendar events. An ideal complete application would allow for the creation and sharing of
any data found on the iPhone as a form of communication among both friends and strangers.
The map could populate with information about the area, such as Wikipedia and News
articles, as well as user submitted content. The inspiration would be to make MediaMap the
ultimate resource for discovering any and all kinds of information about a particular location
of interest.
15
CONCLUSION
The goal of this research was to follow a structured agile software engineering process to
design from the ground up a prototype application for the Apple iPhone to interact valuably
with a geospatial video database. The goal of developing an iPhone application was to learn
the Objective-C language and mobile development and networking. At the same time we
learned how to design and schedule a project, while overcoming changes and obstacles to
create a working product in a short amount of time. The MediaMap application serves as an
example of the value of mobile applications, and is a first step towards a expansive and
comprehensive location-aware social network hub.
In designing this prototype, we learned the Objective-C and PHP languages, the MySQL
geospatial database functions, and enhance our SQL and networking skills. We discovered
and approached problems with agile solutions, and adapted our needs to fit the scheduled end
date. The completed project is far from perfect, but accurately demonstrates the capabilities
required for such an application exist currently. With more time and a better knowledge of
the skill set, particularly of the Objective-C language and iPhone development, we believe it
is completely possible to create a full working application based on our designs.
With all of these things in mind, the immediate future goal is to continue development as
currently designed to add the actual uploading of both video and images without the use of a
side channel. After that, the next step would be to enhance the user account feature and
implement the functionality behind the Search Options page. After that, MediaMap remains
a work in progress, and leaves the door wide open for future creativity and expansion.
16
REFERENCES
[1]
I. Sommerville, Software Engineering, 8th ed., New York, New York: AddisonWesley, 2007.
[2]
Apple, Inc. “iPhone Dev Center”, Apple Developer Pages, 2010. [Online Software
Download]. Available: http://developer.apple.com/iphone/index.action. [Accessed:
May 12, 2010].
[3]
J. Ray and S. Johnson, J. Ray and S. Johnson, Sams Teach Yourself: iPhone
Application Development. Indianapolis, Indiana: Sams Publishing, 2010.
[4]
C. Dempsey, “Methods for Creating Spatial Databases,” GIS Lounge. Sept. 29, 2006.
[Online]. Available: http://gislounge.com/methods-for-creating-spatial-databases/.
[Accessed: May 21, 2010].
[5]
Wikipedia, “Open Geospatial Consortium”, Wikipedia: The Free Encyclopedia. June
4, 2010. [Online]. Available:
http://en.wikipedia.org/wiki/Open_Geospatial_Consortium. [Accessed July 19, 2010].
[6]
R. Bourdon, Wamp Server 2.0i. GPL License, July 11, 2009. [Online Download].
Available: http://www.wampserver.com. [Accessed: May 23, 2010].
[7]
Dyn Inc., “Dynamic DNS Free”, Dynamic DNS. Dynamic Hostname. 2010. [Online
Software]. Available: http://www.dyndns.com. [Accessed: May 23, 2010].
[8]
CollabNet. “Tortoise SVN,” Tigris.org. Subversion 1.6, May 2010. [Online Software
Download]. Available: http://tortoisesvn.tigris.org/. [Accessed May 24, 2010].
[9]
Geeknet, Inc. “SourceForge,” SourceForge.net. May 2010. [Online Software].
Available: https://sourceforge.net/. [Accessed May 24, 2010] Project Link:
https://team5hangman.svn.sourceforge.net/svnroot/team5hangman/MediaMap/.
[10] Oracle, “Introduction to MySQL Spatial Support,” MySQL Documentation. 11.16.1,
2010. [Online]. Available: http://dev.mysql.com/doc/refman/5.0/en/gisintroduction.html. [Accessed: June 16, 2010].
[11] Oracle, “Introduction to MySQL Spatial Support,” MySQL Documentation. 11.17.1 –
11.17.7, 2010. [Online]. Available: http://dev.mysql.com/doc/refman/5.1/en/spatialextensions.html. [Accessed: June 16, 2010].
[12] “Setting up Fields in your phpMyAdmin database tables,” PHP Tutorials, [Online].
Available: http://www.homeandlearn.co.uk/php/php12p3.html. [Accessed: May 24,
2010].
17
[13] “How to transfer recorded video from iPhone 3GS,” iPhone Development Exchange,
Sept. 13, 2010. [Online]. Available: http://www.iphonedevx.com/?p=192. [Accessed:
June 18, 2010].
[14] Google, “Developer’s Guide: PHP,” YouTube APIS and Tools, Uploading Videos,
2010. [Online]. Available:
http://code.google.com/apis/youtube/2.0/developers_guide_php.html#Uploading_Vid
eos. [Accessed: July 3, 2010].
[15] Apple, Inc., “iOS Reference Library”, Apple Developer Pages. 2010. [Online].
Available: http://developer.apple.com/iphone/library/navigation/index.html.
[Accessed: May 15, 2010].
[16] ohiyo1234, “Have problem with base64 Endcoder/decoder,” iPhone SDK
Development Forum, Oct. 27, 2008. [Online]. Available:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/5752-have-problembase64-endcoder-decoder.html [Accessed: June 17, 2010].
[17] K. Yong, “YouTubeAPIS + iPhone = Cool mobile apps,” YouTube API Blog: News
and Notes for Developers, Feb. 5, 2010. [Online]. Available:
http://apiblog.youtube.com/2009/02/youtube-apis-iphone-cool-mobile-apps.html.
[Accessed: July 2, 2010].
[18] Google, “GData Objective-C Client Library,” Google Code, Google Data APIS
Objective-C Client Library, Release 1.10.0, Date of publication. [Online Download].
Available: http://code.google.com/p/gdata-objectivecclient/downloads/detail?name=gdata-objectivec-client-1.10.0.zip&can=2&q=.
[Accessed: July 2, 2010].
[19] pdm, “Google’s GData Objective-C Client Library – iPhone SDK,” iPhone SDK
Development Forum, Aug. 29, 2008. [Online]. Available:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/3148-googles-gdataobjective-c-client-library-iphone-sdk.html [Accessed: June 29, 2010].
[20] Digital Fish, Inc., “HTTPFileUploadSample,” CocoaDev, Dec. 3, 2008. [Online].
Available: http://www.cocoadev.com/index.pl?HTTPFileUploadSample [Accessed:
June 15, 2010].
[21] W3Schools, “PHP Tutorial”, w3schools.com, 2010. [Online]. Available: http://
www.w3schools.com/php/default.asp [Accessed: June 25, 2010].
[22] Rupert, “iPhone Note #14: Drawing a Point, Line, Polygon on top of MKMapview,”
iPhone And GIS Development Notes, Oct 2, 2009. [Online]. Available:
http://www.gisnotes.com/wordpress/2009/10/iphone-devnote-14-drawing-a-pointline-polygon-on-top-of-mkmapview/. [Accessed: July 7, 2010].
18
[23] J. Barros, “Getting Oriented with MapKit: Everything you need to get started with the
new mapping framework,” slideshare, Nov. 2009. [Online]. Available:
http://www.slideshare.net/360conferences/getting-oriented-with-mapkit-everythingyou-need-to-get-started-with-the-new-mapping-framework. [Accessed: July 12,
2010].
[24] Boydlee, “Auto playing a YouTube video inside WebUIView iPhone Objective-C
SDK,” Lemonade Stand, Feb. 3, 2010. [Online]. Available:
http://blog.lemonadestand.com.au/post/auto-playing-a-youtube-video-insidewebuiview-iphone-objective-c-sdk/23. [Accessed: July 14, 2010].
[25] Troy, “Set the Zoom Level of an MKMapView,” Backspace Prologue: Mistakes and
learnings of an iPhone developer, Jan. 22, 2010. [Online]. Available:
http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/. [Accessed:
July 10, 2010].
[26] “Tutorial: Using phpMyAdmin to manage mySQL,” Vision Master Designs, July 25,
2008. [Online]. Available: http://visionmasterdesigns.com/tutorial-usingphpmyadmin-to-manage-mysql/. [Accessed: May 24, 2010].
[27] B. Wilson, “Google opens its APIS to iPhone SDK,” CNET, Mar. 20, 2008. [Online].
Available: http://reviews.cnet.com/8301-19512_7-10115433-233.html. [Accessed:
June 29, 2010].
19
APPENDIX A
Sprint 0 Schedule
20
APPENDIX B
Sprint 1 Schedule
21
APPENDIX C
Sprint 2 Schedule
22
APPENDIX D
Upload Use Case
23
APPENDIX E
Search Use Case
24
APPENDIX F
View Use Case
25
APPENDIX G
Database Creation
26
APPENDIX H
PHP Code
SVN: https://team5hangman.svn.sourceforge.net/svnroot/team5hangman/MediaMap/PHP/
insert.php
<?php
$type = $_GET["type"];
$name = $_GET["name"];
$desc = $_GET["desc"];
$link = $_GET["link"];
$loc = $_GET["loc"];
date_default_timezone_set("America/New_York");
$date = date("Y-m-d");
$connect = mysql_connect('mccoey.selfip.net', <removed>, <removed>);
if (!$connect) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db('mediamap');
mysql_query("INSERT INTO mediamap.media (USER_ID,
LINK,
NAME,
DATE,
SIZE,
DESCRIPTION,
TYPE )
VALUES ('1', '" . $link . "', '".$name."',
'".$date."', '0', '".$desc."', '".$type."');");
$mediaId = mysql_insert_id();
mysql_query("INSERT INTO mediamap.location (
MEDIA_ID,
GEOTAG )
VALUES ('".$mediaId."',
GeomFromText('".$loc."'));"
);
printf("Insert Successful");
?>
27
search.php
<?php
$type = $_GET["type"];
$BBOX = $_GET['BBOX'];
date_default_timezone_set("America/New_York");
$date = date("Y-m-d");
$connect = mysql_connect('mccoey.selfip.net', <removed>, <removed>);
if (!$connect) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db('mediamap');
$result = mysql_query("SELECT NAME, LINK, DESCRIPTION, DATE,
X(GEOTAG) AS 'X', Y(GEOTAG) AS 'Y'
FROM mediamap.media
JOIN mediamap.location ON
mediamap.media.MEDIA_ID=mediamap.location.MEDIA_ID
WHERE 1=MBRContains(GeomFromText('".$BBOX."'),
GEOTAG)");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
echo "<entries>";
while($row = mysql_fetch_array($result))
{
echo "<entry>";
echo "<name>".$row['NAME']."</name>";
echo "<type>".$type."</type>";
echo "<description>".$row['DESCRIPTION']."</description>";
echo "<date>".$row['DATE']."</date>";
echo "<link>".$row['LINK']."</link>";
echo "<geom>POINT(".$row['X']." ".$row['Y'].")</geom>";
echo "<lat>".$row['X']."</lat>";
echo "<lon>".$row['Y']."</lon>";
echo "</entry>";
}
echo "</entries>";
?>
28
APPENDIX I
Objective-C Code
SVN: https://team5hangman.svn.sourceforge.net/svnroot/team5hangman/MediaMap/Classes
UploadView.m
#import "UploadView.h"
#import <CoreLocation/CoreLocation.h>
@implementation UploadView
@synthesize selectVideo;
@synthesize videoCamera;
@synthesize selectImage;
@synthesize imageCamera;
@synthesize upload;
@synthesize fileName;
@synthesize tempLink;
@synthesize fileDescription;
@synthesize thumbnailImage;
@synthesize backgroundButton;
@synthesize locMan;
NSData *webData;
CLLocation *currentLoc;
#pragma mark GUI
- (IBAction)keyboardClose:(id)sender
{
[fileName resignFirstResponder];
[fileDescription resignFirstResponder];
[tempLink resignFirstResponder];
}
#pragma mark Video
- (void)pickVideo:(UIImagePickerControllerSourceType)sourceType {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = NO;
picker.sourceType = sourceType;
picker.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeMovie];
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (IBAction)selectVideoPressed:(id)sender
{
[self pickVideo:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
}
- (IBAction)videoCameraPressed:(id)sender
{
[self pickVideo:UIImagePickerControllerSourceTypeCamera];
}
#pragma mark Image
- (void)pickImage:(UIImagePickerControllerSourceType)sourceType {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = sourceType;
[self presentModalViewController:picker animated:YES];
[picker release];
}
29
- (IBAction)selectImagePressed:(id)sender
{
[self pickImage:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
}
- (IBAction)imageCameraPressed:(id)sender
{
[self pickImage:UIImagePickerControllerSourceTypeCamera];
}
#pragma mark ImagePicker
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//Check if video or image
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:@"public.movie"])
{
NSLog(@"Found a movie.");
thumbnailImage.image = [UIImage imageNamed:@"movie.png"];
//videoInfo = info;
}
else if ([mediaType isEqualToString:@"public.image"])
{
NSLog(@"Found an image.");
UIImage *origImage = [info
objectForKey:UIImagePickerControllerOriginalImage];
thumbnailImage.image = origImage;
webData = UIImagePNGRepresentation(origImage);
[origImage release];
}
[picker dismissModalViewControllerAnimated:YES];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissModalViewControllerAnimated:YES];
}
#pragma mark Upload
-(void)uploadPressed:(id)sender
{
//Get current Location as WKT String
NSString *wktStr = [self getLocation];
//Get Title and Description
NSString *titleStr = fileName.text;
NSString *descStr = fileDescription.text;
NSString *temp = tempLink.text;
NSString *urlStr;
if([titleStr isEqualToString:@""]) {
NSLog(@"NULL Title");
titleStr = [[NSString alloc] initWithString:@"No Title"];
}
if([descStr isEqualToString:@""]) {
NSLog(@"NULL desc");
descStr = [[NSString alloc] initWithString:@"No Description" ];
}
30
//if ([temp isEqualToString:@""]) {
if(temp == NULL) {
//Upload Video link to to database
//At this time, all videos are ?v=NmxOjfqlb0o
urlStr = [[NSString alloc]
initWithFormat:@"http://mccoey.selfip.net:8080/insert.php?
type=VIDEO&name=%@&desc=%@&loc=%@&link=NmxOjfqlb0o", titleStr,
descStr, wktStr];
}
else {
//Upload Video link to to database
urlStr = [[NSString alloc]
initWithFormat:@"http://mccoey.selfip.net:8080/insert.php?
type=VIDEO&name=%@&desc=%@&loc=%@&link=%@", titleStr, descStr,
wktStr, temp];
}
NSLog(@"URL: %@", urlStr);
NSURL *url = [[NSURL alloc] initWithString: [urlStr
stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
NSLog(@"%@", [url absoluteString]);
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
NSHTTPURLResponse *response;
NSError *error;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response
error: &error];
NSLog(@"Status Code: %d", [response statusCode]);
NSLog(@"Status: %d", [response observationInfo]);
//Clear all
fileName.text = @"";
fileDescription.text = @"";
tempLink.text = @"";
thumbnailImage.image = NULL;
NSLog(@"Done uploading");
}
/* getLocation returns the current location
* as a wktString singular POINT
*/
- (NSString *) getLocation {
NSLog(@"getLocation");
NSLog(@"POINT(%f %f)", currentLoc.coordinate.latitude,
currentLoc.coordinate.longitude);
return [[NSString alloc] initWithFormat:@"POINT(%f %f)",
currentLoc.coordinate.latitude, currentLoc.coordinate.longitude];
}
// Implement viewDidLoad to do additional setup after loading the view, typically
from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyBest;
[locMan startUpdatingLocation];
}
#pragma mark Location
31
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
if(error.code == kCLErrorDenied) {
[manager stopUpdatingLocation];
[locMan release];
locMan = nil;
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation
*)oldLocation
{
NSLog(@"Updating location (%f, %f)", newLocation.coordinate.latitude,
newLocation.coordinate.longitude);
currentLoc = [[CLLocation alloc]
initWithLatitude:newLocation.coordinate.latitude
longitude:newLocation.coordinate.longitude];
}
#pragma mark - (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[selectVideo release];
[videoCamera release];
[selectImage release];
[imageCamera release];
[upload release];
[fileName release];
[tempLink release];
[fileDescription release];
[thumbnailImage release];
[backgroundButton release];
[webData release];
[devKey release];
[locMan release];
[super dealloc];
}
@end
MapView.m
#import "MapView.h"
#import "MapPin.h"
#import <MapKit/MapKit.h>;
@implementation MapView;
@synthesize map;
@synthesize webView;
NSMutableString *mediaName;
NSMutableString *description;
NSMutableString *link;
32
BOOL onName;
BOOL onDesc;
BOOL onLink;
BOOL onLat;
BOOL onLon;
double lat;
double lon;
MapPin *pin;
// Implement viewDidLoad to do additional setup after loading the view, typically
from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
map.delegate = self;
[self searchForMedia];
}
- (void)viewDidAppear: (BOOL)animated {
[self becomeFirstResponder];
[super viewDidAppear:animated];
}
-(void)searchForMedia
{
NSString *urlStr = [[NSString alloc]
initWithFormat:@"http://mccoey.selfip.net:8080/search.php?
type=VIDEO&BBOX=%@", @"POLYGON((-180 90,180 90,180 -90,-180 -90,-180
90))"];
NSURL *url = [[NSURL alloc] initWithString: [urlStr
stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding]];
NSLog(@"%@", [url absoluteString]);
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
NSHTTPURLResponse *response;
NSError *error;
//Get XML reply in String format and then change to NSData for NSXMLParser
NSData *reply = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response error: &error];
NSString *stringReply = (NSString *)[[NSString alloc] initWithData:reply
encoding:NSUTF8StringEncoding];
NSData *xmlData = [stringReply dataUsingEncoding: NSUTF8StringEncoding];
NSLog(@"XML: %@", stringReply);
//Parse and Add points
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:xmlData];
[xmlParser setDelegate:self];
[xmlParser parse];
}
-(void)updateBounds {
/* this code borrowed from deadroxy at:
* http://stackoverflow.com/questions/2081753/getting-the* bounds-of-an-mkmapview
*/
//To calculate the search bounds...
//First we need to calculate the corners of the map so we get the points
CGPoint nePoint = CGPointMake(map.bounds.origin.x + map.bounds.size.width,
map.bounds.origin.y);
CGPoint swPoint = CGPointMake((map.bounds.origin.x), (map.bounds.origin.y +
map.bounds.size.height));
33
//Then transform those point into lat,lng values
CLLocationCoordinate2D neCoord;
neCoord = [map convertPoint:nePoint toCoordinateFromView:map];
CLLocationCoordinate2D swCoord;
swCoord = [map convertPoint:swPoint toCoordinateFromView:map];
/* End Borrowed Code */
NSLog(@"NE: %f",neCoord);
NSLog(@"SW: %f",swCoord);
[NSThread sleepForTimeInterval:5.0];
[self updateBounds];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
[mediaName release];
[description release];
[link release];
}
#pragma mark parser
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"name"]) {
onName = YES;
}
if ([elementName isEqualToString:@"description"]) {
onDesc = YES;
}
if ([elementName isEqualToString:@"link"]) {
onLink = YES;
}
if ([elementName isEqualToString:@"lat"]) {
onLat = YES;
}
if ([elementName isEqualToString:@"lon"]) {
onLon = YES;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// only log the text of a node if it's a "screen_name" node
if( onName ) {
mediaName = [[NSMutableString alloc] initWithString:string];
34
NSLog(@"String: %@", mediaName);
}
if( onDesc ) {
description = [[NSMutableString alloc] initWithString:string];
NSLog(@"String: %@", description);
}
if( onLink ) {
link = [[NSMutableString alloc] initWithString: string];
NSLog(@"String: %@", mediaName);
}
if( onLat ) {
lat = [string doubleValue];
}
if( onLon ) {
lon = [string doubleValue];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"entry"]) {
//Create Pin
CLLocationCoordinate2D coordinate;
coordinate.latitude = lat;
coordinate.longitude = lon;
pin = [[MapPin alloc] initWithCoordinates:coordinate
placeName:mediaName description:description link:link];
[map addAnnotation:pin];
}
if ([elementName isEqualToString:@"name"]) {
onName = NO;
}
if ([elementName isEqualToString:@"description"]) {
onDesc = NO;
}
if ([elementName isEqualToString:@"link"]) {
onLink = NO;
}
if ([elementName isEqualToString:@"lat"]) {
onLat = NO;
}
if ([elementName isEqualToString:@"lon"]) {
onLon = NO;
}
}
#pragma mark mapView
-(MKPinAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id
<MKAnnotation>)annotation
{
if(map.userLocation == annotation){
return nil;
}
MKPinAnnotationView *annView = (MKPinAnnotationView *) [self.map
dequeueReusableAnnotationViewWithIdentifier:@"id"];
if(annView == nil){
annView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier: @"id"] autorelease];
annView.canShowCallout = YES;
annView.rightCalloutAccessoryView = [UIButton
buttonWithType:UIButtonTypeDetailDisclosure];
35
annView.leftCalloutAccessoryView = [[[UIImageView alloc]
initWithImage:[UIImage imageNamed:@"youtube.png"]]
autorelease];
}
return annView;
}
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
MapPin *tempPin = [view annotation];
NSString *fullLink= [[NSString alloc] initWithFormat:
@"http://www.youtube.com/watch?v=%@", [tempPin link]];
NSLog(@"View Tapped: %@", fullLink);
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:fullLink]];
[fullLink release];
[tempPin release];
}
//refresh on shake
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if(event.type == UIEventSubtypeMotionShake)
{
NSLog(@"SHAKE");
[self searchForMedia];
}
}
-(BOOL) canBecomeFirstResponder {
return YES;
}
#pragma mark Video
@end
36
Download