├── web-service ├── .gitignore ├── favicon.ico ├── index.yaml ├── app.yaml ├── static │ └── index.html ├── main.py └── LICENSE ├── android ├── PhysicalWeb │ ├── app │ │ ├── .gitignore │ │ ├── version.properties │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values │ │ │ │ │ │ ├── themes.xml │ │ │ │ │ │ ├── dimens.xml │ │ │ │ │ │ ├── colors.xml │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── drawable-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_notification.png │ │ │ │ │ │ ├── settings_xxhdpi.png │ │ │ │ │ │ ├── menu_item_background.9.png │ │ │ │ │ │ └── found_beacon_card.xml │ │ │ │ │ ├── values-w820dp │ │ │ │ │ │ └── dimens.xml │ │ │ │ │ ├── anim │ │ │ │ │ │ ├── fade_in_activity.xml │ │ │ │ │ │ ├── fade_out_fragment.xml │ │ │ │ │ │ ├── fade_in_and_slide_up.xml │ │ │ │ │ │ └── fade_in_and_slide_up_fragment.xml │ │ │ │ │ ├── layout │ │ │ │ │ │ ├── activity_main.xml │ │ │ │ │ │ ├── fragment_nearby_devices.xml │ │ │ │ │ │ ├── fragment_about.xml │ │ │ │ │ │ ├── fragment_beacon_config.xml │ │ │ │ │ │ └── list_item_nearby_device.xml │ │ │ │ │ └── menu │ │ │ │ │ │ └── main.xml │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ │ └── physical_web │ │ │ │ │ └── org │ │ │ │ │ └── physicalweb │ │ │ │ │ ├── AboutFragment.java │ │ │ │ │ ├── Device.java │ │ │ │ │ ├── UrlShortener.java │ │ │ │ │ ├── BeaconHelper.java │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ ├── NearbyDevicesAdapter.java │ │ │ │ │ ├── NearbyDevicesFragment.java │ │ │ │ │ ├── DeviceDiscoveryService.java │ │ │ │ │ ├── MetadataResolver.java │ │ │ │ │ ├── BeaconConfigFragment.java │ │ │ │ │ └── BeaconConfigHelper.java │ │ │ └── androidTest │ │ │ │ └── java │ │ │ │ └── physical_web │ │ │ │ └── org │ │ │ │ └── physicalweb │ │ │ │ └── ApplicationTest.java │ │ ├── libs │ │ │ ├── volley.aar │ │ │ ├── uribeacon-library.aar │ │ │ ├── google-api-client-1.19.0.jar │ │ │ ├── google-http-client-1.19.0.jar │ │ │ ├── google-http-client-android-1.19.0.jar │ │ │ └── google-api-services-urlshortener-v1-rev33-1.19.0.jar │ │ ├── proguard-rules.pro │ │ ├── build.gradle │ │ └── app.iml │ ├── settings.gradle │ ├── .gitignore │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── build.gradle │ ├── PhysicalWeb.iml │ ├── gradle.properties │ ├── gradlew.bat │ └── gradlew └── LICENSE ├── documentation ├── images │ ├── example.png │ ├── uribeacon1.png │ ├── android_walkthrough_1.png │ ├── android_walkthrough_2.png │ ├── android_walkthrough_3.png │ ├── android_walkthrough_4.png │ ├── android_walkthrough_5.png │ └── physical_web_icon_white.png ├── getting_started.md ├── android_client_walkthrough.md ├── technical_overview.md └── introduction.md ├── README.md └── LICENSE /web-service/.gitignore: -------------------------------------------------------------------------------- 1 | .pyc 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | .idea -------------------------------------------------------------------------------- /android/PhysicalWeb/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /web-service/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/web-service/favicon.ico -------------------------------------------------------------------------------- /android/PhysicalWeb/app/version.properties: -------------------------------------------------------------------------------- 1 | #Tue Sep 30 16:18:55 PDT 2014 2 | MAJOR=0 3 | MINOR=1 4 | BUILD=422 5 | PATCH=0 6 | -------------------------------------------------------------------------------- /documentation/images/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/documentation/images/example.png -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /documentation/images/uribeacon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/documentation/images/uribeacon1.png -------------------------------------------------------------------------------- /android/PhysicalWeb/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/libs/volley.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/libs/volley.aar -------------------------------------------------------------------------------- /documentation/images/android_walkthrough_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/documentation/images/android_walkthrough_1.png -------------------------------------------------------------------------------- /documentation/images/android_walkthrough_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/documentation/images/android_walkthrough_2.png -------------------------------------------------------------------------------- /documentation/images/android_walkthrough_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/documentation/images/android_walkthrough_3.png -------------------------------------------------------------------------------- /documentation/images/android_walkthrough_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/documentation/images/android_walkthrough_4.png -------------------------------------------------------------------------------- /documentation/images/android_walkthrough_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/documentation/images/android_walkthrough_5.png -------------------------------------------------------------------------------- /documentation/images/physical_web_icon_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/documentation/images/physical_web_icon_white.png -------------------------------------------------------------------------------- /android/PhysicalWeb/app/libs/uribeacon-library.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/libs/uribeacon-library.aar -------------------------------------------------------------------------------- /android/PhysicalWeb/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/PhysicalWeb/app/libs/google-api-client-1.19.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/libs/google-api-client-1.19.0.jar -------------------------------------------------------------------------------- /android/PhysicalWeb/app/libs/google-http-client-1.19.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/libs/google-http-client-1.19.0.jar -------------------------------------------------------------------------------- /android/PhysicalWeb/app/libs/google-http-client-android-1.19.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/libs/google-http-client-android-1.19.0.jar -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/drawable-xxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/src/main/res/drawable-xxhdpi/ic_notification.png -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/drawable-xxhdpi/settings_xxhdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/src/main/res/drawable-xxhdpi/settings_xxhdpi.png -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/drawable-xxhdpi/menu_item_background.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/src/main/res/drawable-xxhdpi/menu_item_background.9.png -------------------------------------------------------------------------------- /android/PhysicalWeb/app/libs/google-api-services-urlshortener-v1-rev33-1.19.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/physical-web/master/android/PhysicalWeb/app/libs/google-api-services-urlshortener-v1-rev33-1.19.0.jar -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /android/PhysicalWeb/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip 7 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #1C47C1 4 | #099F39 5 | #545454 6 | #CCCCCC 7 | #4285f4 8 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/drawable-xxhdpi/found_beacon_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 9 | 10 | 11 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/androidTest/java/physical_web/org/physicalweb/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package physical_web.org.physicalweb; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /web-service/index.yaml: -------------------------------------------------------------------------------- 1 | indexes: 2 | 3 | # AUTOGENERATED 4 | 5 | # This index.yaml is automatically updated whenever the dev_appserver 6 | # detects that a new type of query is run. If you want to manage the 7 | # index.yaml file manually, remove the above marker line (the line 8 | # saying "# AUTOGENERATED"). If you want to manage some indexes 9 | # manually, move them above the marker line. The index.yaml file is 10 | # automatically uploaded to the admin console when you next deploy 11 | # your application using appcfg.py. 12 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/anim/fade_in_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/anim/fade_out_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | -------------------------------------------------------------------------------- /android/PhysicalWeb/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:0.12.2' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/anim/fade_in_and_slide_up.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/layout/fragment_nearby_devices.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/anim/fade_in_and_slide_up_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 16 | -------------------------------------------------------------------------------- /android/PhysicalWeb/PhysicalWeb.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /android/PhysicalWeb/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /web-service/app.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2014 Google Inc. All rights reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | application: url-caster 18 | version: 1 19 | runtime: python27 20 | api_version: 1 21 | threadsafe: yes 22 | 23 | handlers: 24 | - url: /favicon\.ico 25 | static_files: favicon.ico 26 | upload: favicon\.ico 27 | 28 | - url: /index\.html 29 | static_files: static/index.html 30 | upload: static/index\.html 31 | 32 | - url: .* 33 | script: main.app 34 | 35 | libraries: 36 | - name: webapp2 37 | version: "2.5.2" 38 | 39 | - name: lxml 40 | version: "2.3.5" 41 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Physical Web 5 | Edit Urls 6 | About 7 | Address 8 | Url 9 | SAVE URL 10 | Version 11 | favicon for the given url for this entry 12 | Searching 13 | Beacon Found! 14 | Saving to Beacon 15 | Url Saved! 16 | Edit Urls 17 | Nearby Beacons 18 | 19 | 20 | Beacon Nearby 21 | Beacons Nearby 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/layout/fragment_about.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | 18 | 26 | 27 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "20.0.0" 6 | 7 | //auto versioning logic 8 | def versionPropertiesFile = file('version.properties') 9 | if (versionPropertiesFile.canRead()) { 10 | def Properties properties = new Properties() 11 | properties.load(new FileInputStream(versionPropertiesFile)) 12 | def build = properties['BUILD'].toInteger() + 1 13 | properties['BUILD'] = build.toString() 14 | properties.store(versionPropertiesFile.newWriter(), null) 15 | 16 | defaultConfig { 17 | applicationId "physical_web.org.physicalweb" 18 | minSdkVersion 18 19 | targetSdkVersion 21 20 | versionCode 1 21 | versionName "0.1.${build}" 22 | } 23 | } 24 | 25 | buildTypes { 26 | release { 27 | runProguard false 28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_7 33 | targetCompatibility JavaVersion.VERSION_1_7 34 | } 35 | } 36 | 37 | repositories{ 38 | flatDir { 39 | dirs 'libs' 40 | } 41 | } 42 | 43 | dependencies { 44 | compile 'com.android.volley:volley@aar' 45 | compile 'org.uribeacon:uribeacon-library@aar' 46 | compile 'com.android.support:appcompat-v7:20.0.+' 47 | compile files('libs/google-api-client-1.19.0.jar') 48 | compile files('libs/google-http-client-1.19.0.jar') 49 | compile files('libs/google-api-services-urlshortener-v1-rev33-1.19.0.jar') 50 | compile files('libs/google-http-client-android-1.19.0.jar') 51 | } 52 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 15 | 16 | 21 | 22 | 26 | 27 | 30 | 31 | 35 | 36 | 39 | 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##The Physical Web 2 | The Physical Web is an approach to unleash the core super power of the web: interaction on demand. People should be able to walk up to any smart device: e.g. a vending machine, a poster, a toy, a bus stop, a rental car, and not have to download an app first in order to use it. The user experience of using smart devices should be much like we use links on web, just tap and use. 3 | 4 | The Physical Web is, at it's base, a discovery service where URLs are broadcast and any nearby device can receive them. This takes the web we know and love and unlocks exciting new ways to interact. 5 | 6 | The URL is the fundamental building block of the web, giving remarkable flexibility of expression. It can be: 7 | 8 | * a web page with just a tiny paragraph of info 9 | * a fully interactive web page 10 | * a deep link into a native application. 11 | 12 | ##Why We're Doing This 13 | The number of smart devices is going to explode in number, both in our homes and in public spaces. Much like the web, there is going to be a 'long tail' of interactivity for smart devices. But the overhead of installing an app for each one just doesn't scale. We need a system that lets someone walk up and use a device with just a tap. The Physical web isn't about replacing native apps, it's about allowing interaction for the times when native apps just aren't practical. 14 | 15 | ##Open Design 16 | The Physical Web must be an open standard that everyone can use. This can't be a product that is locked down by a single company. Like many web specifications, this is an open source design that is being released early so everyone can experiment and comment on it. There is much to discuss and add to this specification. 17 | 18 | ##Start Here 19 | The best place to start is with the [Introduction](http://github.com/google/physical-web/blob/master/documentation/introduction.md) document 20 | 21 | If you'd like to jump right in, check out the [Getting started guide](http://github.com/google/physical-web/blob/master/documentation/getting_started.md) 22 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 37 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /documentation/getting_started.md: -------------------------------------------------------------------------------- 1 | # Getting started testing the Physical Web 2 | 3 | In order to get up and running you need two things: 4 | 5 | 1. A hardware beacon 6 | 2. Software on your phone/tablet to see that beacon. 7 | 8 | The software is the easiest thing to take care of. The source code is located in this repo. However, you can get the latest list of [Android releases.](https://github.com/google/physical-web/releases) Just make sure you go to Settings>Security>Unknown Sources and flip the checkbox on before you do. A walkthrough of the app [is here](http://github.com/google/physical-web/blob/master/documentation/android_client_walkthrough.md) 9 | 10 | The trickier thing is to get a beacon broadcasting a URL. For most BLE beacons on the market today, this is not very easy to do. We're working on getting a much simpler, maker-friendly device released through an online vendor. This beacon will allow you to set the URL easily through the app and should be available in November 2014. 11 | 12 | The simplest way, if you're in a hurry, is to get an [RFDuino](http://www.rfduino.com/) as it is available right now and can be programmed to broadcast a URL. Once you have the RFduino installed with it's libraries, this sketch will create a sample beacon, that broadcasts "ABC.com": 13 | 14 | #include 15 | 16 | uint8_t advdata[] = 17 | { 18 | 0x03, // length 19 | 0x03, // Param: Service List 20 | 0xD8, 0xFE, // URI Beacon ID 21 | 0x0A, // length 22 | 0x16, // Service Data 23 | 0xD8, 0xFE, // URI Beacon ID 24 | 0x00, // flags 25 | 0x20, // power 26 | 0x00, // http://www. 27 | 0x41, // 'A' 28 | 0x42, // 'B' 29 | 0x43, // 'C' 30 | 0x07, // .".com" 31 | }; 32 | 33 | void setup() { 34 | RFduinoBLE_advdata = advdata; 35 | RFduinoBLE_advdata_len = sizeof(advdata); 36 | RFduinoBLE.advertisementInterval = 1000; // advertise every 1000ms 37 | RFduinoBLE.begin(); 38 | } 39 | 40 | void loop() { 41 | RFduino_ULPDelay(INFINITE); // switch to lower power mode 42 | } 43 | 44 | Once this is up and running, the Physical Web app will be able to see it. 45 | 46 | If there are other maker-ish devices out there that can setup easily, please let us know so we can add them to this list. 47 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/java/physical_web/org/physicalweb/AboutFragment.java: -------------------------------------------------------------------------------- 1 | package physical_web.org.physicalweb; 2 | 3 | 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | import android.os.Bundle; 7 | import android.app.Fragment; 8 | import android.util.Log; 9 | import android.view.LayoutInflater; 10 | import android.view.Menu; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.TextView; 14 | 15 | public class AboutFragment extends Fragment { 16 | 17 | private static String TAG = "AboutFragment"; 18 | private static String TITLE_ABOUT = "About"; 19 | 20 | public AboutFragment() { 21 | } 22 | 23 | public static AboutFragment newInstance() { 24 | AboutFragment aboutFragment = new AboutFragment(); 25 | return aboutFragment; 26 | } 27 | 28 | private void initialize() { 29 | getActivity().getActionBar().setTitle(TITLE_ABOUT); 30 | initializeApplicationVersionText(); 31 | } 32 | 33 | private void initializeApplicationVersionText() { 34 | String versionName = ""; 35 | try { 36 | PackageInfo pInfo; 37 | pInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0); 38 | versionName = pInfo.versionName; 39 | } catch (PackageManager.NameNotFoundException e) { 40 | e.printStackTrace(); 41 | } 42 | 43 | TextView textView_applicationVersion = (TextView) getView().findViewById(R.id.textView_applicationVersion); 44 | textView_applicationVersion.setText(versionName); 45 | } 46 | 47 | 48 | ///////////////////////////////// 49 | // callbacks 50 | ///////////////////////////////// 51 | 52 | @Override 53 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 54 | setHasOptionsMenu(true); 55 | return inflater.inflate(R.layout.fragment_about, container, false); 56 | } 57 | 58 | @Override 59 | public void onResume() { 60 | super.onResume(); 61 | initialize(); 62 | } 63 | 64 | @Override 65 | public void onDetach() { 66 | super.onDestroy(); 67 | getActivity().getActionBar().setTitle(getString(R.string.title_nearby_beacons)); 68 | } 69 | 70 | @Override 71 | public void onPrepareOptionsMenu(Menu menu) { 72 | super.onPrepareOptionsMenu(menu); 73 | menu.findItem(R.id.action_config).setVisible(false); 74 | menu.findItem(R.id.action_about).setVisible(false); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/java/physical_web/org/physicalweb/Device.java: -------------------------------------------------------------------------------- 1 | package physical_web.org.physicalweb; 2 | 3 | import android.bluetooth.BluetoothDevice; 4 | import android.graphics.Bitmap; 5 | 6 | import org.uribeacon.beacon.UriBeacon; 7 | import java.util.ArrayList; 8 | 9 | public class Device { 10 | 11 | private BluetoothDevice mBluetoothDevice; 12 | private UriBeacon mUriBeacon; 13 | private MetadataResolver.DeviceMetadata mDeviceMetadata; 14 | public ArrayList mRssiHistory; 15 | private int MAX_LENGTH_RSSI_HISTORY = 6; 16 | private String mLongUrl; 17 | private String mShortUrl; 18 | 19 | public Device(UriBeacon uriBeacon, BluetoothDevice bluetoothDevice, int rssi) { 20 | mUriBeacon = uriBeacon; 21 | mBluetoothDevice = bluetoothDevice; 22 | mRssiHistory = new ArrayList<>(); 23 | initializeUrl(); 24 | } 25 | 26 | private void initializeUrl() { 27 | if (mUriBeacon == null) { 28 | return; 29 | } 30 | 31 | String longUrl = null; 32 | String shortUrl = null; 33 | String url = mUriBeacon.getUriString(); 34 | // If this is a shortened url 35 | if (UrlShortener.isShortUrl(url)) { 36 | shortUrl = url; 37 | // Expand the url to it's original url 38 | longUrl = UrlShortener.lengthenShortUrl(url); 39 | } 40 | else { 41 | longUrl = url; 42 | } 43 | mShortUrl = shortUrl; 44 | mLongUrl = longUrl; 45 | } 46 | 47 | public BluetoothDevice getBluetoothDevice() { return mBluetoothDevice; } 48 | public UriBeacon getUriBeacon() { return mUriBeacon; } 49 | public MetadataResolver.DeviceMetadata getMetadata() { return mDeviceMetadata; } 50 | public String getShortUrl() { return mShortUrl; } 51 | public String getLongUrl() { return mLongUrl; } 52 | public void setMetadata(MetadataResolver.DeviceMetadata deviceMetadata) { mDeviceMetadata = deviceMetadata; } 53 | private ArrayList getRssiHistory() { return mRssiHistory; } 54 | 55 | public void updateRssiHistory(int rssi) { 56 | getRssiHistory().add(rssi); 57 | if (getRssiHistory().size() > MAX_LENGTH_RSSI_HISTORY) { 58 | getRssiHistory().remove(0); 59 | } 60 | } 61 | 62 | public int calculateAverageRssi() { 63 | if (getRssiHistory().size() == 0) { 64 | return 0; 65 | } 66 | int rssiSum = 0; 67 | for (int rssi : getRssiHistory()) { 68 | rssiSum += rssi; 69 | } 70 | return (rssiSum / getRssiHistory().size()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /android/PhysicalWeb/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /documentation/android_client_walkthrough.md: -------------------------------------------------------------------------------- 1 | ##Physical Web Android Client Walkthrough 2 | An Introduction to the Physical Web Android Client 3 | 4 | We start with a high level-description of the user flows and then dive into and detail the specifics of each screen. 5 | 6 | The overall user flow of the app is fairly simple: 7 | 8 | * The app listens for nearby beacons. 9 | * The app then shows the user a notification about any found beacons. 10 | * The user can then tap the notification, which brings up a list of the found beacons. 11 | * The user can then tap one of the items in the list, which then opens the web page for that beacon. 12 | 13 | But let’s view an example with screenshots. When you first run the app, you'll be greeted with a screen like this, which is a list of nearby found beacons. 14 | 15 | ![Figure 1](https://raw.githubusercontent.com/google/physical-web/master/documentation/images/android_walkthrough_1.png) 16 | 17 | It’s probable that you don't have any beacons configured at the moment, so you'll likely see an empty list in the above screen. So that brings us to the next flow which is configuration. 18 | 19 | Tap the over flow menu button in the top right corner (the vertical ellipsis thing). This brings up the menu. Tap "Edit Urls". 20 | 21 | ![Figure 2](https://raw.githubusercontent.com/google/physical-web/master/documentation/images/android_walkthrough_2.png) 22 | 23 | This opens the configuration screen that will start searching for beacons nearby that are ready to be configured. 24 | 25 | ![Figure 3](https://raw.githubusercontent.com/google/physical-web/master/documentation/images/android_walkthrough_3.png) 26 | 27 | To make a beacon configurable, press its button. It should beep. If all goes well, the app will have found the configurable beacon and tell you so. Sometimes this can be a little slow (but any longer than 3 seconds or so, just press the back button and then re-tap the "Edit Urls" menu button). 28 | 29 | ![Figure 4](https://raw.githubusercontent.com/google/physical-web/master/documentation/images/android_walkthrough_4.png) 30 | 31 | Now you can enter a new url into the text field and press either the keyboard "DONE" button or exit the keyboard and tap "SAVE URL" to write that new url to the beacon.  You should hear a confirmation beep from the beacon and also see a toast onscreen telling you that the url was saved to the beacon. You'll then be taken back to the list of nearby beacons that should update shortly with your newly programmed beacon. 32 | 33 | We started the first flow with the list of beacons, but really once the app is loaded it runs a background scanner (that turns off when your screen is off). This scanner creates a notification that indicates how many beacons have been found nearby, and hides the notification if that number is zero. 34 | 35 | ![Figure 5](https://raw.githubusercontent.com/google/physical-web/master/documentation/images/android_walkthrough_5.png) 36 | 37 | If you tap the notification, it will bring you back to the list of the nearby beacons, which you can then use to launch the various beacon urls or configure beacons as mentioned above. 38 | 39 | So that’s it! Happy Physical Webbing! 40 | 41 | Please note that this app has been targeting Android L release (21) and has been tested primarily on the Nexus 5. 42 | -------------------------------------------------------------------------------- /web-service/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 18 | 19 | 20 | 21 | 49 | 50 | 51 | 52 |

Device List

53 | 54 |

/resolve-scan

55 |

Request Data

56 | 96 |

Request Data

97 |

 98 |     
 99 |     
100 |     

Add Device

101 |
102 | 103 | 104 | 105 |
106 | 107 | -------------------------------------------------------------------------------- /android/PhysicalWeb/app/src/main/res/layout/fragment_beacon_config.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 25 | 26 | 35 | 36 | 46 | 47 | 56 | 57 | 66 | 67 | 77 | 78 | 86 | 87 |