Mobile Applications at NOCCCD Brad Rippe NOCCCD. Goal Provide insight into developing and deploying...

Post on 22-Dec-2015

219 views 0 download

Tags:

Transcript of Mobile Applications at NOCCCD Brad Rippe NOCCCD. Goal Provide insight into developing and deploying...

Mobile Applications at NOCCCD

Brad RippeNOCCCD

Goal

Provide insight into developing and deploying mobile applications with

Sungard’s Mobile Connection.

Brad RippeIT Project Leader

North Orange County Community College District

brippe@nocccd.edu

Smartphone StatisticsTypes of Smartphones

iPhone 40%Blackberry 36%Android 22%Other 2%

Source: University Colorado Boulder

Source: Google Analytics

Mobile Connection 1.0

• 1.0 Release• Support multiple mobile platforms • Built on Open Source Software• Integrates with LDAP and Banner Data• Quick Start

• m-Apps (Feeds, Grades, Schedule, Restaurant)

What features?

22 College/University iPhone appsNews - 21Directory - 18Maps - 18Events - 13Videos - 9Courses - 6Sports - 6Photos - 5Library - 5Twitter - 4

8 vendor solutionsUniversity Texas at Austin; Stanford; Harvard; Boston College; Saddleback; Irvine Valley College; Mt. Hood College; Rice University; more

1.0 Planned Features

• m-Apps• Student’s Daily Schedule• Grades• Restaurants• News Feed• Staff Directory• Class Schedule• Campus Map

Mobile Connection 1.0.1

• Java Development Kit (JDK) 1.6.21+• Grails 1.3.6 - http://www.grails.org

• Spring• Hibernate • Groovy

• Rhodes Framework 2.2.5 - http://rhomobile.com/projects/rhodes

• Ruby/Rails• Android SDK and NDK • Blackberry JDE• iOS SDK/Xcode

Android Requirements

• Android SDK Android 2.2, API 8http://developer.android.com/sdk/index.html

• Android NDK r4bWindows - http://dl.google.com/android/ndk/android-ndk-r4b-windows.zipMac - http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zipLinux - http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip

API

MC Architecture

request

Luminis IV LDAP

response

Banner

Mobile Server

NOCCCD Basic Configuration

“The Plan”

3 institutions3 platforms~ 4 months

Setting up the “Team”

District/SCE

Cypress

Fullerton

TEST

Collaborating

Collaborating

Repository Structure

MC Directory Structure

Android Emulator

# Android config - android doesn't respond to localhostsecurity_service_url =

'http://10.0.2.2:8001/mobileserver/rest/security'grade_service_url = 'http://10.0.2.2:8001/mobileserver/rest/grade'schedule_service_url = 'http://10.0.2.2:8001/mobileserver/rest/schedule'feed_service_url = 'http://10.0.2.2:8001/mobileserver/rest/feed/'

http://bit.ly/psZ8G7

News Feeds

Updated Feed

Feed Client

2.

Feed – show.erb<form action="<%= url_for :action => :index %>"> <select name="id" onchange="submit()"> <% if ::Rho.get_app.feedId && ::Rho.get_app.feedId == 'cypress'%> <option selected value="cypress">Cypress College News</option> <% else %> <option value="cypress">Cypress College News</option> <%end%> <% if ::Rho.get_app.feedId && ::Rho.get_app.feedId == 'fullerton'%> <option selected value="fullerton">Fullerton College News</option> <% else %> <option value="fullerton">Fullerton College News</option> <%end%></select></form><hr />… More …

Feed – application.rbrequire 'rho/rhoapplication'

class AppApplication < Rho::RhoApplication attr_accessor :feedId

# more code in here def initialize super endend

Feed – feed_controller.rbdef index ::Rho.get_app.feedId = @params['id'] url = "#{@serviceUrl}" url << "/#{::Rho.get_app.feedId}.json"

#More code result = Rho::AsyncHttp.get( :url => url,

:callback => (url_for :action => :feed_callback))

redirect :action => :wait end

Feed – Config.groovyfeed.location = [ cypress:"http://cypresscollege.edu/rss.xml", fullerton:"http://www.fullcoll.edu/rss.xml",sce:"http://sce.edu/rss.xml]sghe { plugins { banner { jdbc { … } } }}

Back Issue

Back Issue – feed_controller.rbdef index ::Rho.get_app.feedId = @params['id'] url = "#{@serviceUrl}" url << "/#{::Rho.get_app.feedId}.json"

#More code

result = Rho::AsyncHttp.get(:url => url, :callback => (url_for :action => :feed_callback))

redirect :action => :wait end

Back Issue – feed_controller.rb# Original Methoddef feed_callback app_info "feed_callback: #{@params}“ # log feedId # parse json response

# send browser to show view but still have wait in history?? WebView.navigate(url_for :action => :show)end

Fix Back Issuedef feed_callback app_info "feed_callback: #{@params}“ # parse json response

# send browser to show_feed method WebView.navigate(url_for :action => :show_feed)end

def show_feed render :action => :show, :back => '/app/Mshell'end

http://bit.ly/p44ghq

MC 1.1.1 – Back Issue

def index feedId = @params['id‘] Rho::AsyncHttp.get( :url => url, :callback => (url_for :action => :feed_callback)) @response["headers"]["Wait-Page"] = "true" redirect :action => :wait end

app_info or app_error

• Android• rake emulator:android:getlog

• BlackBerry• C:\Users\<username>\net\rim\fledge-2\3.0.0.118\

sdcard\Rho\<application_name>\RhoLog.txt

• iPhone• /Users/<username>/Library/Application

Support/iPhone Simulator/4.3/Applications/<GUID>/Documents/RhoLog.txt

Server Side Of Things

Class Schedule Plugin

ClassScheduleUrlMappings

class ClassScheduleUrlMappings {static mappings = {"/rest/getCampuses"(controller:"search",

action:"getCampuses")"/rest/getAllTerms"(controller:"search", action:"getAllTerms")// continued…}

}

SearchControllerclass SearchController { def classScheduleService def getCampuses = { if ( classScheduleService == null ) { // code here, handle null classScheduleService } else { def camps = classScheduleService.getCampuses() if (camps != null && camps.size() > 0) { response.setContentType("text/json") render camps as JSON } else { // send no information 404 error } } } …

ClassScheduleServiceclass ClassScheduleService { def dataSourceBanner //defined in the server’s Config.groovy file def getCampuses() { def sql = Sql.newInstance (dataSourceBanner) def query = " " "select stvcamp_code, stvcamp_desc from stvcamp where stvcamp_code in ('1', '2', '3') order by stvcamp_desc" " " def campuses = [] // list of Campus objects try { sql.eachRow(query) { def campus = new Campus() campus.campusCode = it.stvcamp_code campus.campusDesc = it.stvcamp_desc campuses.add(campus) } } catch(Exception e) { log.error "Exception ${query} - ${e}“ } return campuses } // end getCampuses

ClassSchedule Request

GrailsDispatcherServlet

/service/rest/getCampuses

SearchController

Campus

ClassScheduleServiceresponse

request

Automatic Marshallingimport grails.converters.*class SearchController { def getCampuses = { if ( classScheduleService == null ) { // code here, handle null classScheduleService } else { def camps = classScheduleService.getCampuses() if (camps != null && camps.size() > 0) { response.setContentType("text/json") render camps as JSON } else { // send no information 404 error } } } …

1

2

JSON output?

[{"class":"edu.nocccd.Campus","id":null,"campusCode":"1","campusDesc":"Cypress College"},

{"class":"edu.nocccd.Campus","id":null,"campusCode":"2","campusDesc":"Fullerton College"},

{"class":"edu.nocccd.Campus","id":null,"campusCode":"3","campusDesc":"School of Continuing Education"}]

Server BootStrap.groovyimport grails.converters.JSONimport org.codehaus.groovy.grails.plugins.GrailsPluginUtilsimport edu.nocccd.Campusclass BootStrap {

def init = { } def destroy = { }}

Init – Override Convertersclass BootStrap { def init = { servletContext -> JSON.registerObjectMarshaller(Campus) { def returnArray = [:] returnArray['campusCode'] = it.campusCode returnArray['campusDesc'] = it.campusDesc return returnArray } // continued for each domain object } …}

Result JSON

[{"campusCode":"1","campusDesc":"Cypress College"},{"campusCode":"2","campusDesc":"Fullerton College"},{"campusCode":"3","campusDesc":"School of Continuing Education"}]

Objects with in Objects

• Sections• Multiple buildings• Multiple meeting times

• Default converters • Skip internal data

render sections as JSON

MATH 030 F Bldg 1

Bldg 2

Meet 2

Meet 1

MATH 100 F

SearchControllerdef sections = classScheduleService.getSections(cCode, tCode, subCode, courNum)if (sections != null && sections.size() > 0) { def sectionList = new ArrayList() sections.each { section -> def sectionMap = new HashMap() sectionMap.put "crn", section.crn def bldgs = new ArrayList() // Done for meetings too! section.buildings.each { bldg -> def bldgMap = new HashMap() bldgMap.put "bldgCode", bldg.bldgCode bldgMap.put "bldgDesc", bldg.bldgDesc bldgMap.put "roomCode", bldg.roomCode bldgs.add bldgMap } sectionMap.put "bldgs", bldgs } sectionList.add sectionMap

JSON Response[{"instructor":"Danufsky, Joshua","wDropDate":"11/20/2011","waitAvailable":10,"bldgs":[{"roomCode":"624","bldgDesc":"Math/Comp Science - FC","bldgCode":"600"}] ,"meetings":[{"startDate":"08/15/2011","wednesday":null,"thursday":null,"monday":null,"sunday":null,"beginTime":null,"saturday":null,"endDate":"12/16/2011","friday":null,"tuesday":null,"endTime":null,"arrangedHrs":"Plus arranged hours"},{"startDate":"08/15/2011","wednesday":" Wed ","thursday":null,"monday":" Mon ","sunday":null,"beginTime":"1:00","saturday":null,"endDate":"12/16/2011","friday":null,"tuesday":null,"endTime":"2:50 PM","arrangedHrs":null}]]

Render Results

Mobile Server

•Apache Tomcat 6.0.32• Run Non-Root User• Apache JMeter• JVM Options• VisualVM

http://visualvm.java.net/

PSI-Probe

http://code.google.com/p/psi-probe/

Tips - Build for Devices

• Rhoconfig.txt• MaxLogFileSize=0 to 50• MinSeverity=1 to 3• local_server_port=8080

• build.yml • version: 1.0 to 1.0.0

rake device:android:production

version: 1.0AndroidManifest.xml

<manifest xmlns:android='http://schemas.android.com/apk/res/android' package='com.north_orange_county_community_college_district.cypresscollege' android:installLocation='auto' android:versionCode='26' android:versionName='2.2.5'>…</manifest>

version: 1.0.0AndroidManifest.xml

<manifest xmlns:android='http://schemas.android.com/apk/res/android' package='com.north_orange_county_community_college_district.cypresscollege' android:installLocation='auto' android:versionCode='10000' android:versionName='1.0.0'>…</manifest>

Demo

Mobile Connection

• Version 1.1.1• mApps

• Campus Directory• Event Calendar• Campus Map

• iPad Support• JQuery Mobile• Active Directory Support

1.1 Release Notes - http://bit.ly/oq90m6

Things to Take Away

• Collaborative Environment• Team Commitment• Developer Environment• JQuery Mobile• Steering Committee• Limited Feature Set

Questions

ResourcesGrails Tutorialhttp://www.ibm.com/developerworks/java/library/j-grails02128/Ruby Tutorialhttp://www.ruby-lang.org/en/documentation/quickstart/RhoMobile Docshttp://docs.rhomobile.com/JMeterhttp://jakarta.apache.org/jmeter/PSI-Probehttp://code.google.com/p/psi-probe/VisualVMhttp://visualvm.java.net/NOCCCD Mobile Appshttp://www.nocccd.edu/mobile