• Save
WebWorks Development for BlackBerry PlayBook and Smartphones
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

WebWorks Development for BlackBerry PlayBook and Smartphones

  • 12,859 views
Uploaded on

One way to create apps for the PlayBook is using HTML standards that are packaged into a file that can be executed on the PlayBook. This uses an SDK called WebWorks provided by RIM. Here is an......

One way to create apps for the PlayBook is using HTML standards that are packaged into a file that can be executed on the PlayBook. This uses an SDK called WebWorks provided by RIM. Here is an overview of that platform.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
12,859
On Slideshare
12,441
From Embeds
418
Number of Embeds
10

Actions

Shares
Downloads
0
Comments
0
Likes
14

Embeds 418

http://www.blackberrycool.com 227
http://www.bjxiaoc.cn 88
http://gadgetan.com 32
http://www.52digital.com 24
http://www.zarblackberry.com 19
https://si0.twimg.com 11
http://www.techgig.com 9
http://zarblackberry.com 6
http://mobile.aypcservices.com 1
https://twimg0-a.akamaihd.net 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. 1
  • 2. BlackBerry WebWorksApplication PlatformOverview 2
  • 3. What is BlackBerry WebWorks? BlackBerry WebWorks is an application platform that enables developers to create standalone applications using modern and standardized web technologies. WebWorks applications can be fully-featured “Super Apps” through their ability to integrate with native BlackBerry and PlayBook features.
  • 4. BlackBerry Programming ModelsApplication power Simplicity of development and maintenance • Hitting the sweet spot means • The richness of device access and reuse of assets • The simplicity of the browser programming model
  • 5. Developer Spectrum Native-based UI Browser-based UI Functionality provided by BlackBerry OS Functionality provided by Browser EngineNative Application WebWorks Platform BlackBerry Browser• Where in the spectrum do developers gravitate to? • Do they create a Native application (Highly functional)? • Do they create Web content for the Browser (Flexible UI and low cost)? • Or a mix of the two? 5
  • 6. Web = Platform Plurality BlackBerry Smartphone BlackBerry PlayBook• It’s a diverse world out there for developers!• Strong Web standards offer support across multiple platforms • Reuse Web assets and developer skills to create BlackBerry apps• Each platform seeing growth in access to native functionality • Access the richness and differentiators of each platform
  • 7. Real World Examples Hollywood Bowl (LA Philharmonic) Loca FM Guitar Chords(Vanatur World Mobile) (My App Catalog) Superheroes Alliance Campus Party (Uken Games) (Contento Media) Sea-Web (Nitobi)
  • 8. Features andCapabilities 8
  • 9. What Can a WebWorks App Do? Services & Content BROWSER WEB ENGINE SERVICES APPLICATION INTEGRATION PUSH SYSTEM EVENTS File MENUS GPS STORAGE System SQLite
  • 10. Web Platform Powered by WebKit• WebKit rendering engine added to BlackBerry® 6 and BlackBerry Tablet OS • BlackBerry WebWorks applications benefit from strengths of WebKit • Combine the power of HTML5 and CSS3 with JavaScript APIs http://entanglement.gopherwoodstudios.com/light
  • 11. PlayBook Web Platform• Improved high fidelity WebKit browser engine • Better support of HTML5 and CSS3 standards• Package existing Flash content into a PlayBook application • Full support of Adobe Flash 10.1• Faster hardware • 1Ghz dual core processor • 1Gb Ram
  • 12. Architecture 12
  • 13. Architecture: How Does it Work?• User interface – Powered by Web – HTML and CSS Your app WebKit Engine• Application logic WebWorks Platform – JavaScript® BlackBerry Platform – WebWorks APIs – Access to Platform OS BBM Security Push Monetization PIM Background Media Storage Multi-Tasking Hardware Compression …
  • 14. Market for WebWorks Applications• BlackBerry WebWorks applications are supported on – BlackBerry PlayBook – BlackBerry 6 – BlackBerry Device Software version 5.0 http://us.blackberry.com/developers/choosingtargetos.jsp
  • 15. Development Tools 15
  • 16. How do you build BlackBerry WebWorksApplications?1. Setup Development Environment2. Write application content (HTML, CSS, JavaScript files)3. Create a ZIP archive containing these Web assets4. Package your application using the WebWorks SDK
  • 17. BlackBerry WebWorks SDK Development Tools PlayBook Development BlackBerry PlayBook Adobe AIR SDK Deploy *.bar BlackBerry WebWorks SDK for PlayBook WebWorks ApplicationArchive (ZIP) Java SDK Deploy *.cod Smartphone Development BlackBerry WebWorks SDK BlackBerry Smartphone
  • 18. Required Development Tools• Adobe AIR SDK • http://www.adobe.com/products/air/sdk/• BlackBerry WebWorks SDK for Tablet OS • http://us.blackberry.com/developers/tablet/webworks.jsp• VMware Player • http://www.vmware.com/products/player/• BlackBerry PlayBook Simulator • http://us.blackberry.com/developers/tablet/webworks.jsp
  • 19. Installing the AdobeAIR SDK 19
  • 20. Step 1: Installing the Adobe AIR SDK• Download the AIR SDK from Adobe’s website: • http://www.adobe.com/products/air/sdk/
  • 21. Step 1: Installing the Adobe AIR SDK
  • 22. Setting Up TheWebWorks SDK ForPlayBook 22
  • 23. Step 2: Setting up the SDK• Download the BlackBerry WebWorks SDK for Tablet OS: • http://us.blackberry.com/developers/tablet/webworks.jsp
  • 24. Step 2: Setting up the SDK
  • 25. Step 2: Setting up the SDK• Enter the location of where you extracted the contents of the AIR SDK in Step 1
  • 26. Step 2: Setting up the SDK
  • 27. Installing VMwarePlayer 27
  • 28. Step 3: Installing VMware Player• Download the VMware player from VMwares website: • http://www.vmware.com/products/player/
  • 29. Step 3: Installing VMware Player
  • 30. Step 3: Installing VMware Player• VMware installation requires a system restart• Coffee break …
  • 31. BlackBerryPlayBook Simulator 31
  • 32. Step 4: Setting Up The Simulator
  • 33. Step 4: Setting Up The Simulator
  • 34. Step 4: Setting Up The Simulator
  • 35. Step 4: Setting Up The Simulator• Browse to location where you installed simulator ISO file • C:device simulators<simulator name><ISO file>
  • 36. Step 4: Setting Up The Simulator
  • 37. Step 4: Setting Up The Simulator
  • 38. Step 4: Setting Up The Simulator
  • 39. Step 4: Setting Up The Simulator
  • 40. Step 4: Setting Up The Simulator
  • 41. Step 4: Setting Up The Simulator
  • 42. Step 4: Setting Up The Simulator To direct input to virtual machine, press CTRL + G To return to your computer, press CTRL + ALT
  • 43. Step 4: Setting Up The Simulator
  • 44. Step 4: Setting Up The Simulator
  • 45. Writing An App“Hello World” 45
  • 46. Start Writing Code• Open your favorite text editor• Create a new file named index.html• Add the following HTML content to this file: <html> <head> <style type="text/css"> body { font-size: 5em; } </style> </head> <body> <p> Hello World </p> </body> </html>
  • 47. Start Writing Code• Create a second file named config.xml• Add the following XML content to this file:<?xml version="1.0" encoding="UTF-8"?><widget xmlns="http://www.w3.org/ns/widgets" xmlns:rim="http://www.blackberry.com/ns/widgets" version="1.0.0.0"> <name>helloWorld</name> <content src="index.html"/></widget>
  • 48. Start Writing Code• Create an archive (ZIP) named helloWorld.zip containing the index.html and config.xml files
  • 49. Start Writing Code• Run the BlackBerry WebWorks Packager (bbwp.exe) • Packages the helloWorld.zip file into a helloWorld.bar PlayBook applicationC:Program FilesResearch In MotionBlackBerry WebWorks Packager for PlayBookbbwp>bbwp "c:sandboxweb appshelloWorldhelloWorld.zip"[INFO] Parsing command line options[INFO] Parsing bbwp.properties[INFO] Validating WebWorks archive[INFO] Parsing config.xml[WARNING] Failed to find a <feature> element[WARNING] Failed to find the <author> element[INFO] Populating application source[INFO] Compiling WebWorks application[INFO] Packaging the bar file[INFO] Bar packaging complete[INFO] WebWorks application packaging complete
  • 50. Start Writing Code
  • 51. Deploying AnApplication 51
  • 52. Deploying Your Application
  • 53. Deploying Your Application
  • 54. Deploying Your Application• Use the BlackBerry Tablet OS SDK • Installed as part of the WebWorks SDK for PlayBook• Open a command prompt and navigate to: • C:Program FilesResearch In MotionBlackBerry WebWorks Packager for PlayBookbbwpblackberry-tablet-sdk• Contains developer tools for BlackBerry Tablet OS: • binblackberry-packager • binblackberry-deploy • binblackberry-signer
  • 55. Deploying Your Applicationblackberry-deploy -installApp -device <device IP>-package <BAR file path> -password <device password>C:Program FilesResearch In MotionBlackBerry WebWorks Packager for PlayBookbbwpblackberry-tablet-sdk>blackberry-deploy-installApp -device 192.168.198.134 -package "c:sandboxweb appshelloWorldbinhelloWorld.bar" -password passSending Install request...Info: Action: InstallInfo: File size: 40731Info: Installing ...actual_dname::helloWorld1a833da63a6b7e2098dae6d0662e1.MjA5OGRhZTZkMDY2MmUxICAgICAactual_id::MjA5OGRhZTZkMDY2MmUxICAgICAactual_version::1.0.0.0result::success
  • 56. Deploying Your Application
  • 57. Deploying Your Application
  • 58. “My First App” 58
  • 59. Configuration Document (config.xml)• XML document based on W3C spec • http://www.w3.org/TR/widgets/#configuration-document0• Used to define system properties and application permissions • Application name, description, version and icon • Maintains a list of domain and feature permissions• See “Code sample: Creating a BlackBerry WebWorks configuration document” for full details • http://bit.ly/fdOiO6
  • 60. Configuration Document (config.xml)• Define visual characteristics for your application <?xml version="1.0" encoding="UTF-8"?> <widget xmlns="http://www.w3.org/ns/widgets" version="1.0.0.0"> <name>helloWorld</name> <icon src="icon.png"/> <content src="index.html"/> </widget>
  • 61. Configuration Document (config.xml)• Display live content from your Website• Define the <content> element to be a remote URL instead of a local HTML file<?xml version="1.0" encoding="UTF-8"?><widget xmlns="http://www.w3.org/ns/widgets" version="1.0.0.0"> <name>devBlog</name> <icon src="icon.png"/> <content src="http://devblog.blackberry.com/"/></widget>
  • 62. Configuration Document (config.xml)• Without granting explicit permission to access remote domains, application is unable to retrieve content:
  • 63. Configuration Document (config.xml)• Grant domain permission in config.xml file • Create <access> elements for all required domains <?xml version="1.0" encoding="UTF-8"?> <widget xmlns="http://www.w3.org/ns/widgets" version="1.0.0.0"> <name>devBlog</name> <icon src="icon.png"/> <content src="http://devblog.blackberry.com/"/> <access uri="http://devblog.blackberry.com/" subdomains="true"/> <access uri="http://www.youtube.com/" subdomains="true"/> <access uri="http://www.twitter.com/" subdomains="true"/> <access uri="*" subdomains="true"/> </widget>
  • 64. Configuration Document (config.xml)• Remote content can now be accessed:
  • 65. Live vs. Local Web Content• A WebWorks application does not need an active network connection • Created using Web technologies, but designed to function offline• Web assets of your application can be local: <a href="local:///index.html">Home</a> <a href="file:///accounts/1000/shared/camera/IMG_01.jpg"> Camera Pic</a>• Can also use live resources to populate content dynamically <img src="http://www.mysite.com/image1.png"/>
  • 66. Going Remote: AJAX Example• Use XmlHttpRequest object to retrieve web content • Can retrieve local (embedded) or remote content • Remember to whitelist any remote domains used //ajax.js: var req; function handleResponse() { if (req.readyState == 4) { if ((req.status == 200 || req.status == 0)) { var ele = document.getElementById("remoteContent"); ele.innerHTML = req.responseText; } } } function getContent() { req = new XMLHttpRequest(); req.open(GET, http://devblog.blackberry.com, true); req.onreadystatechange = handleResponse; //async callback req.send(null); }
  • 67. Making It Look Good• CSS 3 is a standardized technology • Supported consistently across different platforms and browser engines • Allows you to design great looking application UI with less code border-radius: 20px; box-shadow: .2em .2em .5em #000; @font-face { font-family: myCustomFont; src: url(myCustomFont.otf); }• Great learning resources available: • http://www.css3.info/preview • NetTuts: http://bit.ly/aC5yjS
  • 68. CSS3 Media Queries• Use Media Queries to target CSS against different screen sizes • Support both BlackBerry PlayBook and BlackBerry Smartphone applications with same CSS. • Easier management of multiple platforms with single code base /* BlackBerry Playbook */ @media (min-width:480px) and (max-width:1024px) { body { font-family: Calibri; font-size: 2em; } } /* BlackBerry Torch 9800 */ @media (max-width:360px) and (max-height:480px) { body { font-family: Verdana; font-size: 1em; } }
  • 69. CSS3 Media Query: Real World Example http://colly.com/ 360x480 1024x600
  • 70. Using HTML5 In Your Application• HTML5 is a standardized technology • Supported consistently across different platforms and engines • Enhancements to existing standard allow integration with platform• See “HTML reference – BlackBerry browser” documentation • Complete list of BlackBerry supported HTML5 elements • http://bit.ly/aGFoub• Many great HTML5 learning resources available online • http://diveintohtml5.org/ • http://html5demos.com • http://www.w3schools.com/html5/default.asp • http://www.html5test.com
  • 71. HTML5 Session & Local Storage• Save name-value pairs (String) for offline use • Session data persists while application remains open • Local data persists even after restarting application • http://dev.w3.org/html5/webstorage/ function saveSession() { window.sessionStorage.clear(); window.sessionStorage.setItem("Greeting", "Hello World"); var key = window.sessionStorage.key(0); //"Greeting" var value = window.sessionStorage.getItem(key); //"Hello World" key = key + "_FR"; //"Greeting_FR" value = "Bonjour Monde"; window.sessionStorage.setItem(key, value); var num = window.sessionStorage.length; //2 entries }
  • 72. WebKit Browser Developer Tools• Chrome •  “Tools”  “Developer Tools”  [Storage]
  • 73. Asynchronous Web DB• Relational database powered by SQLite • http://www.w3.org/TR/webdatabase/function initDBSchema(database){ if (database) { database.transaction(function(tx) { var SQL = "CREATE TABLE IF NOT EXISTS Messages (id INTEGER " + " PRIMARY KEY, message TEXT, created TIMESTAMP)"; //The following method occurs asynchronously. Requires callback // methods to correctly perform next actions (e.g. INSERT statements) tx.executeSql(SQL, [], firstCreateComplete, handleSQLError); }, handleTransactionError); }}function createDB(){ var dbSize = 2 * 1024 * 1024; db = window.openDatabase("WebDB", "1.0", "Example", dbSize, initDBSchema);}
  • 74. HTML5 Media• Canvas • Use JavaScript to render 2D images on an HTML drawing surface • See “SketchPad” sample application: http://bit.ly/hz67JX http://jsway.se/m/ http://sebleedelisle.com/demos/html5landscape.html
  • 75. Multimedia: Audio & Video• Audio/Video • Embed audio or video content directly your Web application • Programmatic access to element methods and properties function playSound(audio_file) { var ele = document.getElementById("audio"); ele.src = "local:///files/" + audio_file; ele.play(); } ... <audio preload="auto" style="visibility: hidden;" id="audio"></audio> <div class="pianokey" onclick="playSound(C.mp3)"></div> <div class="pianokey" onclick="playSound(Csharp.mp3)"></div> <div class="pianokey" onclick="playSound(D.mp3)"></div>
  • 76. Multimedia: Flash 10.1• Take advantage of Flash 10.1 support • Embed local or remote content directly your Web application <!-- Remote URI: --> <object width="640" height="385"> <param name="movie" value="http://www.youtube.com/v/eAaez_4m9mQ?fs=1&amp;hl=en_US"> </param> <embed src="http://www.youtube.com/v/eAaez_4m9mQ?fs=1&amp;hl=en_US" width="640" height="385"> </embed> </object> <!– Embedded SWF: --> <object width="500" height="300"> <param name="movie" value="5-snowflakes.swf"></param> <embed src="5-snowflakes.swf" width="500" height="300"></embed> </object> Sample courtesy of http://www.swfspot.com/swfspot/samples/flash8/Falling_Snowflakes
  • 77. Accelerometer• Additional mechanism for user interaction besides screen • http://dev.w3.org/geo/api/spec-source-orientation.html#motion_event window.addEventListener("devicemotion", function(event) { //Acceleration measured in m/s^2 var x = event.accelerationIncludingGravity.x; var y = event.accelerationIncludingGravity.y; var z = event.accelerationIncludingGravity.z; // A BlackBerry PlayBook lying flat on the Earth’s surface // (facing up) should have an acceleration of: // { x : 0, y : 0, z : 9.81 } }, true);
  • 78. Orientation• Event raised when user turns PlayBook left or right • UI can be changed to switch between Landscape and Portrait layout window.onorientationchange = function() { switch(window.orientation) { case 0: alert("Top side up :" + window.orientation); break; case 90: alert("Left side up :" + window.orientation); break; case -90: alert("Right side up :" + window.orientation); break; } }
  • 79. Touch Screen Events• Override default behavior with custom events handlers • See “Sample Code – SketchPad Application” http://bit.ly/hz67JX document.ontouchstart = function(event) { //Tell browser engine not to scroll/span/zoom when user touches screen: event.preventDefault(); //Get first in collection of all active TouchStart events: var touchEvent = event.changedTouches[0]; //Process the event alert("TouchStart: " + touchEvent.pageX + "," + touchEvent.pageY); }
  • 80. 3rd Party Frameworks• Touch optimized Web frameworks support multiple platforms • Examples: jQuery Mobile/UI, Sencha Touch, Dojo, AlphaSoftware• Improve the UI and functionality of your application • Save time and money by using existing code! Sencha Touch jQuery Mobile http://touchsolitaire.mobi/app/ http://jquerymobile.com/demos/
  • 81. “BlackBerry PlayBook Integration” 81
  • 82. Web Works JavaScript APIs• Custom objects that can connect browser engine with underlying Java code • BlackBerry WebWorks apps can be more than just web content • Enables “Super App” functionality http://www.blackberry.com/developers/docs/webworks/api/playbook/
  • 83. JavaScript API: blackberry.app• Use blackberry.app to read data from config.xml file • Example: Styling an ‘About’ feature in your app with CSS3 function setValue(id, message) { document.getElementById(id).innerHTML = message; } function showAbout() { setValue("version", blackberry.app.version); setValue("copyright", blackberry.app.copyright); setValue("author", "By: " + blackberry.app.author); setValue("name", blackberry.app.name); }
  • 84. Web Works JavaScript APIs• Grant API permission in config.xml file • Create an <feature> element for any required APIs <?xml version="1.0" encoding="UTF-8"?> <widget xmlns="http://www.w3.org/ns/widgets" version="1.0.0.0"> <name>helloWorld</name> <icon src="icon.png"/> <content src="index.html"/> <feature id="blackberry.app" required="true" version="1.0.0.0"/> </widget>• Missing <feature> definitions may result in runtime ‘undefined’ errors
  • 85. Web Works JavaScript APIs• Even remote Web content can use WebWorks APIs • Create a <feature> element within the <access> element • Cannot be done with <access uri="*"> <?xml version="1.0" encoding="UTF-8"?> <widget xmlns="http://www.w3.org/ns/widgets" version="1.0.0.0"> <name>helloWorld</name> <icon src="icon.png"/> <content src="http://devblog.blackberry.com"/> <access uri="http://devblog.blackberry.com" subdomains="true"> <feature id="blackberry.app" required="true" version="1.0.0.0"/> </access> </widget>
  • 86. JavaScript API: blackberry.app.event• Detect when user has moved the application to the background and/or foreground function handleBackground() { document.getElementById("mainElement").className = "background"; } function handleForeground() { document.getElementById("mainElement").className = "normal"; } blackberry.app.event.onBackground(handleBackground); blackberry.app.event.onForeground(handleForeground);
  • 87. JavaScript API: blackberry.invoke• Launch other Tablet OS applications function openVideoCamera() { var args = new blackberry.invoke.CameraArguments(); args.view = blackberry.invoke.CameraArguments.VIEW_RECORDER; blackberry.invoke.invoke(id, args); } ... <button onclick="openVideoCamera()">Open Video Camera</button>
  • 88. JavaScript API: blackberry.system• Retrieve information about the current state of the Tablet OSfunction getNHLscores() { var data; //Get live data when network connection is available // Otherwise, use last saved values. // hasDataCoverage() is similar to "navigator.onLine" if (blackberry.system.hasDataCoverage()) { data = callWebService("http://test.sports.com/ws?t=NHL"); saveToDB("NHL", data); } else { data = getFromDB("NHL"); } displayScores(data);}
  • 89. JavaScript API: blackberry.system.event• Read information about battery level and state function handleBatteryLevel(level) { document.getElementById("level").style.width = level + "%"; } ... blackberry.system.event.deviceBatteryLevelChange(handleBatteryLevel); ... <div class="batteryLevelBar"> <div id="level" class="batteryLevel">&nbsp;</div> </div>
  • 90. JavaScript API: blackberry.ui• Display custom and standard Tablet OS Dialog windowsfunction dialogCallBack(index) { alert("Button index selected: " + index);}function customDialog() { var question = "Have you created a BlackBerry PlayBook application?"; var buttons = new Array("Yes", "No", "Soon"); var ops = { title : "Answer:", size : blackberry.ui.dialog.SIZE_MEDIUM, position : blackberry.ui.dialog.LOC_CENTER }; blackberry.ui.dialog.customAsk(question, buttons, dialogCallBack, ops);}...<button onclick="customDialog()">Ask Question (Custom Dialog)</button>
  • 91. Migrating contentto the BlackBerryPlayBook Platform 91
  • 92. Supporting BlackBerry Smartphones and PlayBook• Web makes supporting different platforms easy • Relative sizes (fonts, page elements, margins/padding) • Content can be designed to be scalable Platform Screen Size Screen Resolution BlackBerry Torch 9800 3.2” HVGA 480 x 360 BlackBerry PlayBook 7” LCD 1024 x 600 Desktops 17” - 32” + 1024 x 768 – 1920 x 1068 + iPad 9.7” LCD 1024 x 768 Future Smartphones ? ? & Tablets
  • 93. Re-Using Your Existing Web Assets• Step 1: Direct your app to load your Website directly • Make any necessary adjustments to suit screen size <?xml version="1.0" encoding="UTF-8"?> <widget xmlns="http://www.w3.org/ns/widgets" version="1.0.0.0"> <name>myGreatApp</name> <icon src="my_great_app_icon.png"/> <content src="http://mygreatsite.com"/> <access uri="http://mygreatsite.com" subdomains="true"/> </widget>
  • 94. Re-Using Your Existing Web Assets• Step 2: Move remote Web content into standalone application <?xml version="1.0" encoding="UTF-8"?> <widget xmlns="http://www.w3.org/ns/widgets" version="1.0.0.0"> <name>myGreatApp</name> <icon src="my_great_app_icon.png"/> <content src="http://mygreatsite.com"/> <content src="index.html"/> </widget> Web Server myGreatSite.bar
  • 95. Re-Using Your Existing Web Assets• Step 3: Start taking advantage of local features • Support platform-specific features using JavaScript WebWorks APIs function handleBatteryLevel(level) { if (level < 25) { if (confirm("Battery level below 25%. Close?")) { blackberry.app.exit(); } } } blackberry.system.event.deviceBatteryLevelChange(handleBatteryLevel); ... <h1>My Great Site</h1> ...
  • 96. Re-Using Your Existing Web Assets• Step 4: Publish your content in BlackBerry App World• BlackBerry App World • Free to register and submit apps • 70 Countries, 21 Currencies, 6 Languages • PayPal, Credit Card, Carrier Billing • Over 35 million App World users (2+ million app downloads per day) • Over 75% of app downloads are OS 5.0+• Free BlackBerry PlayBook Tablet Offer http://us.blackberry.com/developers/tablet/playbook_offer.jsp
  • 97. Q&AThank You! 97