Initial plugin
116
Android/AugmentedReality-Wikitude/Documentation/Documentation.md
Normal file
@@ -0,0 +1,116 @@
|
||||
## Wikitude PhoneGap Plugin Documentation
|
||||
by ``` Wikitude GmbH ```
|
||||
|
||||
|
||||
### DESCRIPTION
|
||||
***
|
||||
|
||||
This document describes all available PhoneGap bindings which exists in the Wikitude PhoneGap Plugin.
|
||||
|
||||
|
||||
#### Getting information about the device
|
||||
|
||||
###### isDeviceSupported
|
||||
Call ``` isDeviceSupported ``` to determinate if the current device is capable of launching ARchitect Worlds.
|
||||
|
||||
@param onSuccessCallback - A callback which gets called if the current device supports launching ARchitect Worlds
|
||||
@param onErrorCallback - An callback which gets called if the current device does not fulfil all needs to lauch ARchitect Worlds
|
||||
@param Plugin name - The name of the plugin you want to call a function
|
||||
@param Plugin function - The name of the function you want to call on the plugin
|
||||
@param options - No options
|
||||
|
||||
cordova.exec(deviceSupportedCallback, deviceNotSupportedCallback, "WikitudePlugin", "isDeviceSupported", [""]);
|
||||
|
||||
|
||||
#### Managing the ARchitectView
|
||||
|
||||
|
||||
###### open
|
||||
Call open to add the ARchitectView to your applications view hierarchy and loads the specified ARchitect World.
|
||||
|
||||
@param onSuccessCallback - A success callback
|
||||
@param onErrorCallback - An error callback
|
||||
@param Plugin name - The name of the plugin you want to call a function
|
||||
@param Plugin function - The name of the function you want to call on the plugin
|
||||
@param options - a dictionary containing two pairs:
|
||||
@pair apiKey : The Wikitude SDK Key provided to you after you purchased the Wikitude SDK or an empty string if you're using a trial version
|
||||
@pair filePath : A filepath to a local bundle resource or to a file on e.g. your dropbox
|
||||
|
||||
cordova.exec(architectWorldLaunchedCallback, architectWorldFailedLaunchingCallback, "WikitudePlugin", "open", [{ apiKey: myApiKey, filePath: worldPath}]);
|
||||
|
||||
###### close
|
||||
This call will remove the ARchitectView from the view hierarchy and also stops all ongoing Wikitude updates.
|
||||
|
||||
@param onSuccessCallback - A success callback
|
||||
@param onErrorCallback - An error callback
|
||||
@param Plugin name - The name of the plugin you want to call a function
|
||||
@param Plugin function - The name of the function you want to call on the plugin
|
||||
@param options - No options
|
||||
|
||||
cordova.exec(onWikitudeOK, onWikitudeError, "WikitudePlugin", "close", [""]);
|
||||
|
||||
###### show
|
||||
This call hides the ARchitectView, but keeps it alive in memory.
|
||||
|
||||
@param onSuccessCallback - A success callback
|
||||
@param onErrorCallback - An error callback
|
||||
@param Plugin name - The name of the plugin you want to call a function
|
||||
@param Plugin function - The name of the function you want to call on the plugin
|
||||
@param options - No options
|
||||
|
||||
cordova.exec(onWikitudeOK, onWikitudeError, "WikitudePlugin", "hide", [""]);
|
||||
|
||||
###### hide
|
||||
This call will show the ARchitectView again if it was hidden with the ``` hide ``` call.
|
||||
|
||||
@param onSuccessCallback - A success callback
|
||||
@param onErrorCallback - An error callback
|
||||
@param Plugin name - The name of the plugin you want to call a function
|
||||
@param Plugin function - The name of the function you want to call on the plugin
|
||||
@param options - No options
|
||||
|
||||
cordova.exec(onWikitudeOK, onWikitudeError, "WikitudePlugin", "show", [""]);
|
||||
|
||||
|
||||
|
||||
#### Interacting with the ARchitectView
|
||||
|
||||
###### callJavaScript
|
||||
This function will evaluate the passed JavaScript in the current ARchitect World context.
|
||||
|
||||
@param onSuccessCallback - A success callback
|
||||
@param onErrorCallback - An error callback
|
||||
@param Plugin name - The name of the plugin you want to call a function
|
||||
@param Plugin function - The name of the function you want to call on the plugin
|
||||
@param options - A JavaScript array with a JavaScript string at first position
|
||||
|
||||
cordova.exec(onWikitudeOK, onWikitudeError, "WikitudePlugin", "callJavascript", [js]);
|
||||
|
||||
###### onUrlInvoke
|
||||
This function will set an callback which gets called if you call ``` document.location = architectsdk://aRequestWithParameters?id=5&name=Poi5 ```.
|
||||
|
||||
@param onSuccessCallback - A callback which gets called every time you call ` architectsdk:// `
|
||||
@param onErrorCallback - An error callback
|
||||
@param Plugin name - The name of the plugin you want to call a function
|
||||
@param Plugin function - The name of the function you want to call on the plugin
|
||||
@param options - No options
|
||||
|
||||
cordova.exec(onUrlInvokeCallback, onWikitudeError, "WikitudePlugin", "onUrlInvoke", [""]);
|
||||
|
||||
###### setLocation
|
||||
This function allows you to set a location for your current ARchitectView
|
||||
|
||||
|
||||
@param onSuccessCallback - A success callback
|
||||
@param onErrorCallback - An error callback
|
||||
@param Plugin name - The name of the plugin you want to call a function
|
||||
@param Plugin function - The name of the function you want to call on the plugin
|
||||
@param options - A dictionary containing the new latitude, longitude, altitude, accuracy
|
||||
@pair lat : The new latitude
|
||||
@pair lon : The new longitude
|
||||
@pair alt : The new altitude
|
||||
@pair acc : The accuracy of the new locations
|
||||
|
||||
cordova.exec(onUrlInvokeCallback, onWikitudeError, "WikitudePlugin", "setLocation", [""]);
|
||||
|
||||
|
||||
110
Android/AugmentedReality-Wikitude/Plugin/README.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Augmented Reality - Wikitude SDK Plugin
|
||||
by Wikitude GmbH - [www.wikitude.com](http://www.wikitude.com)
|
||||
|
||||
Interested in advanced usage of the plugin and need assistance?
|
||||
[Register as a Wikitude developer](http://developer.wikitude.com) and get support in our forum.
|
||||
|
||||
For further questions visit us on www.wikitude.com or contact us via `phonegap <at> wikitude.com`
|
||||
|
||||
#### Important: This plugin runs on latest [PhoneGap 2.x](http://docs.phonegap.com/en/2.0.0/guide_getting-started_android_index.md.html#Getting%20Started%20with%20Android) only
|
||||
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
|
||||
The Wikitude PhoneGap Plugin enables web developers to embed an Augmented Reality view into their PhoneGap project. One can create a fully featured app with advanced Augmented Reality features, including Image Recognition, purely using HTML, CSS and Javascript.
|
||||
|
||||
###The Wikitude PhoneGap Plugin
|
||||
|
||||
* Available for iOS and Android
|
||||
* Simple and seamless native PhoneGap integration
|
||||
* Fully customizable Augmented Realty view
|
||||
* Includes the full feature set of the Wikitude SDK
|
||||
* AR content is purely written in HTML and JavaScript
|
||||
|
||||

|
||||
|
||||
###The Augmented Reality View
|
||||
From a technical point of view the SDK adds a UI component, similar to a web view. In contrast to a standard web view this AR view can render Augmented Reality content.
|
||||
|
||||
Note: Content developed for this AR View is written in JavaScript and HTML. The .html and .js files for this view are different from the PhoneGap .js and .html files. The AR engine working in the background is called ARchitect Engine and is powering the SDK.
|
||||
|
||||
###Further developer resources
|
||||
* [Full documentation and additional tutorials](http://forum.wikitude.com/documentation)
|
||||
* [Developer Forum](http://forum.wikitude.com/home)
|
||||
* [Wikitude SDK Download](http://forum.wikitude.com/download)
|
||||
* [Google+ Page for News](https://plus.google.com/u/0/103004921345651739447/posts)
|
||||
* [Developer Newsletter](http://www.wikitude.com/developer/newsletter)
|
||||
|
||||
|
||||
|
||||
##Prerequisites
|
||||
* Having set-up [PhoneGap 2.x](http://docs.phonegap.com/en/2.0.0/guide_getting-
|
||||
started_android_index.md.html#Getting%20Started%20with%20Android) project.
|
||||
* In case you didn't set `<uses-sdk android:minSdkVersion="8"/>` or higher in `AndroidManifest.xml` be aware that the Wikitude SDK runs only on Android 2.2+ devices (=Android SDK v8); you must not call the plugin on devices with lower SDK version.
|
||||
|
||||
## SETUP - 'Basic' Plugin
|
||||
|
||||
|
||||
1. Create a folder called `com/wikitude/phonegap` within your project's `src`- folder and copy `WikitudePlugin.java` into it
|
||||
|
||||
2. Add following line to your `res/xml/config.xml`
|
||||
|
||||
`<plugin name="WikitudePlugin" value="com.wikitude.phonegap.WikitudePlugin"/>`
|
||||
|
||||
3. Copy `WikitudePlugin.js` in `assets/www`-folder and ensure to include it in the related HTMLs.
|
||||
|
||||
|
||||
4. Download the [Wikitude SDK](http://www.wikitude.com), copy the wikitudesdk.jar in the Android-folder to your projects `libs`-folder and add it to your project's build path
|
||||
|
||||
5. Visit [Wikitude Developer Site](http://developer.wikitude.com) to find Samples and license your app to get rid of the watermarking
|
||||
|
||||
|
||||
|
||||
## Optional SETUP - 'Extended' Plugin (incl. Vuforia ImageRecognition)
|
||||
|
||||
####In case you use ImageRecognition in your project, you need to use this Extended Plugin instead of the Basic One.
|
||||
|
||||
Prerequisites: Having already set-up your [PhoneGap 2.x](http://docs.phonegap.com/en/2.0.0/guide_getting-started_android_index.md.html#Getting%20Started%20with%20Android) project.
|
||||
|
||||
1. Create a folder called `com/wikitude/phonegap` within your project's `src/` folder and opy `WikitudePlugin.java` and `WikitudePluginVuforia.java` into it.
|
||||
|
||||
2. Add following line to your `res/xml/config.xml`
|
||||
|
||||
3. Copy `WikitudePlugin.js` in `assets/www`-folder and ensure to include it in the related HTMLs.
|
||||
|
||||
`<plugin name="WikitudePlugin" value="com.wikitude.phonegap.WikitudePluginVuforia"/>`
|
||||
4. Download the [Wikitude SDK](http://www.wikitude.com), copy the wikitudesdk.jar in the Android-folder to your projects `libs`-folder and add it to your project's build path. Also copy the `libExtensionVuforia.so` into `libs/armeabi`
|
||||
|
||||
5. Download Vuforia SDK from [Qualcomm Vuforia Website](https://ar.qualcomm.at/qdevnet/) and copy `QCAR.jar` to your projects `libs`-folder and add it to your project's build. Also copy Vuforia's `libQCAR.so` to your `libs/armeabi`-folder
|
||||
|
||||
6. Visit [Wikitude Developer Site](http://developer.wikitude.com) to find Samples and license your app to get rid of the watermarking
|
||||
|
||||
## JAVASCRIPT INTERFACE
|
||||
|
||||
Its simple to use the Wikitude Plugin within your PhoneGap application.
|
||||
|
||||
We wrapped all ``` cordova.exec ``` calls into a separate JavaScript wrapper which handles location updates and some more functionality behind the scenes.
|
||||
|
||||
You will mainly work with the ``` WikitudePlugin ``` where all you have to do is to call ```Wikitude.isDeviceReady(successCallback, errorCallback)``` and in your successCallback, you can call ```WikitudePlugin.loadARchitectWorld(successCallback, errorCallback, "path/to/your/world")```.
|
||||
|
||||
|
||||
If you have purchased a Wikitude SDK license, you can enter you SDK Key in the ```WikitudePlugin.js``` file at line 9.
|
||||
|
||||
|
||||
## LICENSE
|
||||
|
||||
Copyright 2012 [Wikitude GmbH ](http://www.wikitude.com)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
427
Android/AugmentedReality-Wikitude/Plugin/WikitudePlugin.java
Normal file
@@ -0,0 +1,427 @@
|
||||
package com.wikitude.phonegap;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewManager;
|
||||
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import com.wikitude.architect.ArchitectUrlListener;
|
||||
import com.wikitude.architect.ArchitectView;
|
||||
import com.wikitude.architect.ArchitectView.ArchitectConfig;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Basic PhoneGap Wikitude ARchitect Plugin
|
||||
*
|
||||
* You must add "<plugin name="WikitudePlugin" value="com.wikitude.phonegap.WikitudePlugin"/>"
|
||||
* in config.xml to enable this plug-in in your project
|
||||
*
|
||||
* Also ensure to have wikitudesdk.jar in your libs folder
|
||||
*
|
||||
* Note:
|
||||
* This plug-in is written under Apache License, Version 2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @author Wikitude GmbH; www.wikitude.com
|
||||
*/
|
||||
public class WikitudePlugin extends Plugin implements ArchitectUrlListener {
|
||||
|
||||
/** PhoneGap-root to Android-app-assets folder ; e.g. use "assets/foo.html" as source if you want to load foo.html from your android-project's assets-folder */
|
||||
private static final String LOCAL_ASSETS_PATH_ROOT = "assets/";
|
||||
|
||||
/* various JSON-Object keys*/
|
||||
private static final String JSON_KEY_APIKEY = "sdkKey";
|
||||
private static final String JSON_KEY_FILE_PATH = "filePath";
|
||||
|
||||
private static final String JSON_KEY_LOCATION_ALTITUDE = "alt";
|
||||
private static final String JSON_KEY_LOCATION_ACCURACY = "acc";
|
||||
private static final String JSON_KEY_LOCATION_LATITUDE = "lat";
|
||||
private static final String JSON_KEY_LOCATION_LONGITUDE = "lon";
|
||||
|
||||
/* static action strings */
|
||||
|
||||
/**
|
||||
* opens architect-view (add to view stack)
|
||||
*/
|
||||
private static final String ACTION_OPEN = "open";
|
||||
|
||||
/**
|
||||
* closes architect-view (remove view stack)
|
||||
*/
|
||||
private static final String ACTION_CLOSE = "close";
|
||||
|
||||
/**
|
||||
* set visibility of architectView to visible (of present)
|
||||
*/
|
||||
private static final String ACTION_SHOW = "show";
|
||||
|
||||
/**
|
||||
* set visibility of architectView to invisible (of present)
|
||||
*/
|
||||
private static final String ACTION_HIDE = "hide";
|
||||
|
||||
/**
|
||||
* inject location information
|
||||
*/
|
||||
private static final String ACTION_SET_LOCATION = "setLocation";
|
||||
|
||||
/**
|
||||
* callback for uri-invocations
|
||||
*/
|
||||
private static final String ACTION_ON_URLINVOKE = "onUrlInvoke";
|
||||
|
||||
/**
|
||||
* life-cycle notification for resume
|
||||
*/
|
||||
private static final String ACTION_ON_RESUME = "onResume";
|
||||
|
||||
/**
|
||||
* life-cycle notification for pause
|
||||
*/
|
||||
private static final String ACTION_ON_PAUSE = "onPause";
|
||||
|
||||
/**
|
||||
* check if view is on view-stack (no matter if visible or not)
|
||||
*/
|
||||
private static final String ACTION_STATE_ISOPEN = "isOpen";
|
||||
|
||||
/**
|
||||
* opens architect-view (add to view stack)
|
||||
*/
|
||||
private static final String ACTION_IS_DEVICE_SUPPORTED = "isDeviceSupported";
|
||||
|
||||
/**
|
||||
* check if view is on view-stack (no matter if visible or not)
|
||||
*/
|
||||
private static final String ACTION_CALL_JAVASCRIPT = "callJavascript";
|
||||
|
||||
/**
|
||||
* the Wikitude ARchitectview
|
||||
*/
|
||||
private ArchitectView architectView;
|
||||
|
||||
/**
|
||||
* callback-Id of url-invocation method
|
||||
*/
|
||||
private String urlInvokeCallbackId = null;
|
||||
|
||||
/**
|
||||
* callback-id of "open"-action method
|
||||
*/
|
||||
private String openCallbackId = null;
|
||||
|
||||
@Override
|
||||
public PluginResult execute( final String action, final JSONArray args, final String callbackId ) {
|
||||
|
||||
/* hide architect-view -> destroy and remove from activity */
|
||||
if ( WikitudePlugin.ACTION_CLOSE.equals( action ) ) {
|
||||
if ( this.architectView != null ) {
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
removeArchitectView();
|
||||
}
|
||||
} );
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
}
|
||||
else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
/* return success only if view is opened (no matter if visible or not) */
|
||||
if ( WikitudePlugin.ACTION_STATE_ISOPEN.equals( action ) ) {
|
||||
if ( this.architectView != null ) {
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
/* return success only if view is opened (no matter if visible or not) */
|
||||
if ( WikitudePlugin.ACTION_IS_DEVICE_SUPPORTED.equals( action ) ) {
|
||||
if ( ArchitectView.isDeviceSupported( this.cordova.getActivity() ) ) {
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": this device is ARchitect-ready" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": Sorry, this device is NOT ARchitect-ready" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* life-cycle's RESUME */
|
||||
if ( WikitudePlugin.ACTION_ON_RESUME.equals( action ) ) {
|
||||
|
||||
if ( this.architectView != null ) {
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
WikitudePlugin.this.architectView.onResume();
|
||||
}
|
||||
} );
|
||||
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
}
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
|
||||
/* life-cycle's PAUSE */
|
||||
if ( WikitudePlugin.ACTION_ON_PAUSE.equals( action ) ) {
|
||||
if ( architectView != null ) {
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
WikitudePlugin.this.architectView.onPause();
|
||||
}
|
||||
} );
|
||||
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
}
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
|
||||
/* set visibility to "visible", return error if view is null */
|
||||
if ( WikitudePlugin.ACTION_SHOW.equals( action ) ) {
|
||||
|
||||
if ( this.architectView != null ) {
|
||||
this.architectView.setVisibility( View.VISIBLE );
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
/* set visibility to "invisible", return error if view is null */
|
||||
if ( WikitudePlugin.ACTION_HIDE.equals( action ) ) {
|
||||
|
||||
if ( this.architectView != null ) {
|
||||
this.architectView.setVisibility( View.INVISIBLE );
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
/* define call-back for url-invocations */
|
||||
if ( WikitudePlugin.ACTION_ON_URLINVOKE.equals( action ) ) {
|
||||
this.urlInvokeCallbackId = callbackId;
|
||||
PluginResult result = new PluginResult( PluginResult.Status.NO_RESULT, action + ": registered callback" );
|
||||
result.setKeepCallback( true );
|
||||
return result;
|
||||
}
|
||||
|
||||
/* location update */
|
||||
if ( WikitudePlugin.ACTION_SET_LOCATION.equals( action ) ) {
|
||||
if ( this.architectView != null ) {
|
||||
try {
|
||||
String arrStr = args.getString( 0 );
|
||||
JSONObject arr = new JSONObject( arrStr );
|
||||
final double lat = arr.getDouble( WikitudePlugin.JSON_KEY_LOCATION_LATITUDE );
|
||||
final double lon = arr.getDouble( WikitudePlugin.JSON_KEY_LOCATION_LONGITUDE );
|
||||
Object altObj = arr.get( WikitudePlugin.JSON_KEY_LOCATION_ALTITUDE );
|
||||
float alt = Float.MIN_VALUE;
|
||||
|
||||
if ( altObj != null && altObj instanceof Double ) {
|
||||
alt = ((Double)altObj).floatValue();
|
||||
}
|
||||
|
||||
final float altitude = alt;
|
||||
|
||||
final Double acc = arr.getDouble( WikitudePlugin.JSON_KEY_LOCATION_ACCURACY );
|
||||
if ( this.cordova != null && this.cordova.getActivity() != null ) {
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if ( acc != null ) {
|
||||
WikitudePlugin.this.architectView.setLocation( lat, lon, altitude, acc.floatValue() );
|
||||
} else {
|
||||
WikitudePlugin.this.architectView.setLocation( lat, lon, altitude );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
} catch ( Exception e ) {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": exception thrown, " + e != null ? e.getMessage() : "(exception is NULL)" );
|
||||
}
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": updated location" );
|
||||
}
|
||||
|
||||
/* return error if there is no architect-view active*/
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectview is not active" );
|
||||
}
|
||||
|
||||
if ( WikitudePlugin.ACTION_CALL_JAVASCRIPT.equals( action ) ) {
|
||||
if ( this.architectView != null ) {
|
||||
String logMsg = null;
|
||||
try {
|
||||
final String callJS = args.getString( 0 );
|
||||
logMsg = callJS;
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
WikitudePlugin.this.architectView.callJavascript( callJS );
|
||||
}
|
||||
} );
|
||||
|
||||
} catch ( JSONException je ) {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": exception thrown, " + je != null ? je.getMessage() : "(exception is NULL)" );
|
||||
}
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": called js, '" + logMsg + "'" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectview is not active" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* initial set-up, show ArchitectView full-screen in current screen/activity */
|
||||
if ( WikitudePlugin.ACTION_OPEN.equals( action ) ) {
|
||||
this.openCallbackId = callbackId;
|
||||
PluginResult result = null;
|
||||
String arrStr = null;
|
||||
|
||||
try {
|
||||
arrStr = args.getString( 0 );
|
||||
|
||||
// arrStr = arrStr.substring( 1, arrStr.length() - 1 );
|
||||
|
||||
JSONObject arr = new JSONObject( arrStr );
|
||||
|
||||
final String apiKey = arr.getString( WikitudePlugin.JSON_KEY_APIKEY );
|
||||
final String filePath = arr.getString( WikitudePlugin.JSON_KEY_FILE_PATH );
|
||||
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
WikitudePlugin.this.addArchitectView( apiKey, filePath );
|
||||
|
||||
/* call success method once architectView was added successfully */
|
||||
if ( WikitudePlugin.this.openCallbackId != null ) {
|
||||
PluginResult result = new PluginResult( PluginResult.Status.OK );
|
||||
result.setKeepCallback( false );
|
||||
WikitudePlugin.this.success( result, WikitudePlugin.this.openCallbackId );
|
||||
}
|
||||
} catch ( Exception e ) {
|
||||
/* in case "addArchitectView" threw an exception -> notify callback method asynchronously */
|
||||
WikitudePlugin.this.error( e != null ? e.getMessage() : "Exception is 'null'", WikitudePlugin.this.openCallbackId );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
} catch ( Exception e ) {
|
||||
result = new PluginResult( PluginResult.Status.ERROR, action + ": exception thown, " + e != null ? e.getMessage() : "(exception is NULL)" );
|
||||
result.setKeepCallback( false );
|
||||
return result;
|
||||
}
|
||||
|
||||
/* adding architect-view is done in separate thread, ensure to setKeepCallback so one can call success-method properly later on */
|
||||
result = new PluginResult( PluginResult.Status.NO_RESULT, action + ": no result required, just registered callback-method" );
|
||||
result.setKeepCallback( true );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* fall-back return value */
|
||||
return new PluginResult( PluginResult.Status.ERROR, "no such action: " + action );
|
||||
}
|
||||
|
||||
/**
|
||||
* called when url was invoked in architectView (by e.g. calling document.location = "myprotocoll://foo";
|
||||
* @param url the invoked url (e.g. "myprotocoll://foo")
|
||||
* @return true if call was handled properly
|
||||
*/
|
||||
@Override
|
||||
public boolean urlWasInvoked( String url ) {
|
||||
|
||||
/* call callback-method if set*/
|
||||
if ( this.urlInvokeCallbackId != null ) {
|
||||
try {
|
||||
/* pass called url as String to callback-method */
|
||||
PluginResult res = new PluginResult( PluginResult.Status.OK, url );
|
||||
res.setKeepCallback( true );
|
||||
this.success( res, this.urlInvokeCallbackId );
|
||||
return true;
|
||||
} catch ( Exception e ) {
|
||||
this.error( "invalid url invoked: " + url, this.urlInvokeCallbackId );
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* hides/removes ARchitect-View completely
|
||||
* @return true if successful, false otherwise
|
||||
*/
|
||||
private boolean removeArchitectView() {
|
||||
if ( this.architectView != null ) {
|
||||
/* fake life-cycle calls, because activity is already up and running */
|
||||
this.architectView.onPause();
|
||||
this.architectView.onDestroy();
|
||||
this.architectView.setVisibility( View.INVISIBLE );
|
||||
((ViewManager)this.architectView.getParent()).removeView( this.architectView );
|
||||
this.architectView = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Architect-Configuration required for proper set-up
|
||||
* @param apiKey
|
||||
* @return
|
||||
*/
|
||||
protected ArchitectConfig getArchitectConfig( final String apiKey ) {
|
||||
/* no special set-up required in default Wikitude-Plugin, further things required in advanced usage (e.g. Vuforia Image Recognition) */
|
||||
return new ArchitectConfig( apiKey );
|
||||
}
|
||||
|
||||
/**
|
||||
* add architectView to current screen
|
||||
* @param apiKey developers's api key to use (hides watermarking/intro-animation if it matches your package-name)
|
||||
* @param filePath the url (starting with http:// for online use; starting with LOCAL_ASSETS_PATH_ROOT if oyu want to load assets within your app-assets folder)
|
||||
* @throws IOException might be thrown from ARchitect-SDK
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void addArchitectView( final String apiKey, String filePath ) throws IOException {
|
||||
if ( this.architectView == null ) {
|
||||
this.architectView = new ArchitectView( (Activity)this.ctx.getContext() );
|
||||
|
||||
/* add content view and fake initial life-cycle */
|
||||
((Activity)this.ctx.getContext()).addContentView( this.architectView, new ViewGroup.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT ) );
|
||||
|
||||
/* fake life-cycle calls, because activity is already up and running */
|
||||
this.architectView.onCreate( getArchitectConfig( apiKey ) );
|
||||
this.architectView.onPostCreate();
|
||||
|
||||
/* register self as url listener to fwd these native calls to PhoneGap */
|
||||
this.architectView.registerUrlListener( WikitudePlugin.this );
|
||||
|
||||
/* load asset from local directory if prefix is used */
|
||||
if ( filePath.startsWith( WikitudePlugin.LOCAL_ASSETS_PATH_ROOT ) ) {
|
||||
filePath = filePath.substring( WikitudePlugin.LOCAL_ASSETS_PATH_ROOT.length() );
|
||||
}
|
||||
this.architectView.load( filePath );
|
||||
|
||||
/* also a fake-life-cycle call (the last one before it is really shown in UI */
|
||||
this.architectView.onResume();
|
||||
}
|
||||
}
|
||||
}
|
||||
383
Android/AugmentedReality-Wikitude/Plugin/WikitudePlugin.js
Normal file
@@ -0,0 +1,383 @@
|
||||
var WikitudePlugin = {
|
||||
|
||||
/**
|
||||
*
|
||||
* This is the SDK Key, provided to you after you purchased the Wikitude SDK from http://www.wikitude.com/developer/sdk
|
||||
* If you're having a trial version, leave this string empty
|
||||
*
|
||||
*/
|
||||
mySDKKey : "ENTER-YOUR-KEY-HERE",
|
||||
|
||||
/** true if architectview is open */
|
||||
isOpened : false,
|
||||
|
||||
/**
|
||||
*
|
||||
* called when user pressed back-button on Android device
|
||||
*
|
||||
*/
|
||||
backButtonCallback : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* Change the value of this variable to modify the location update rate
|
||||
*
|
||||
*/
|
||||
locationUpdateRate : 3000,
|
||||
|
||||
/**
|
||||
*
|
||||
* This variable represents if the current device is capable of running the Wikitude SDK
|
||||
*
|
||||
*/
|
||||
isDeviceSupported : false,
|
||||
|
||||
/**
|
||||
*
|
||||
* This watchID is used to shedule location updates
|
||||
*
|
||||
*/
|
||||
watchID : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* Callbacks to get device information if ARchitect Worlds can be launched
|
||||
*
|
||||
*/
|
||||
onDeviceSupportedCallback : null,
|
||||
onDeviceNotSupportedCallback : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* Callbacks to get notified if the ARchitect World finished launching or if something went wrong during the World launch
|
||||
*
|
||||
*/
|
||||
onARchitectWorldLaunchedCallback : null,
|
||||
onARchitectWorldFailedLaunchingCallback : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if PhoneGap reports that it has finished loading successfully.
|
||||
*
|
||||
*/
|
||||
isDeviceSupported: function(successCallback, errorCallback)
|
||||
{
|
||||
|
||||
WikitudePlugin.onDeviceSupportedCallback = successCallback;
|
||||
WikitudePlugin.onDeviceNotSupportedCallback = errorCallback;
|
||||
|
||||
|
||||
// PhoneGap is running, so the first thing we do is to check if the current device is capable of running the Wikitude Plugin
|
||||
cordova.exec(WikitudePlugin.deviceIsARchitectReady, WikitudePlugin.deviceIsNotARchitectReady, "WikitudePlugin", "isDeviceSupported", [""]);
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Declare what should happen when user pressed back-button while architect-view is opened.
|
||||
* If not declared/called or null: ARchitect-View is closed
|
||||
*
|
||||
*/
|
||||
onPressedBackButton : function(callback)
|
||||
{
|
||||
WikitudePlugin.backButtonCallback = callback;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if the Wikitude Plugin reports that the device is able to start the Wikitude SDK
|
||||
*
|
||||
*/
|
||||
deviceIsARchitectReady : function()
|
||||
{
|
||||
// We keep track of the device status
|
||||
WikitudePlugin.isDeviceSupported = true;
|
||||
|
||||
|
||||
if(WikitudePlugin.onDeviceSupportedCallback)
|
||||
{
|
||||
WikitudePlugin.onDeviceSupportedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if the Wikitude Plugin reports that the device is not able of starting the Wikitude SDK.
|
||||
*
|
||||
*/
|
||||
deviceIsNotARchitectReady : function()
|
||||
{
|
||||
WikitudePlugin.isDeviceSupported = false;
|
||||
|
||||
// In this case we notify the user that his device is not supported by the Wikitude SDK
|
||||
if(WikitudePlugin.onDeviceNotSupportedCallback)
|
||||
{
|
||||
WikitudePlugin.onDeviceNotSupportedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* =============================================================================================================================
|
||||
*
|
||||
* PUBLIC API
|
||||
*
|
||||
* =============================================================================================================================
|
||||
*/
|
||||
|
||||
/* Managing ARchitect world loading */
|
||||
|
||||
/**
|
||||
*
|
||||
* Call this function if you want to load an ARchitect World
|
||||
*
|
||||
* @param {String} worldPath The path to an ARchitect world ether on the device or on e.g. your dropbox
|
||||
*
|
||||
*/
|
||||
loadARchitectWorld : function(worldPath)
|
||||
{
|
||||
|
||||
// before we actually call load, we check again if the device is able to open the world
|
||||
if(WikitudePlugin.isDeviceSupported)
|
||||
{
|
||||
|
||||
// the 'open' function of the Wikitude Plugin requires a option dictionary with two keys:
|
||||
// @param {Object} options (required)
|
||||
// @param {String} options.sdkKey License key for the Wikitude SDK
|
||||
// @param {String} options.filePath The path to a local ARchitect world or to a ARchitect world on a server or your dropbox
|
||||
|
||||
cordova.exec(WikitudePlugin.worldLaunched, WikitudePlugin.worldFailedLaunching, "WikitudePlugin", "open", [{ sdkKey: WikitudePlugin.mySDKKey, filePath: worldPath}]);
|
||||
|
||||
|
||||
// We add an event listener on the resume and pause event of the application lifecycle
|
||||
document.addEventListener("resume", WikitudePlugin.onResume, false);
|
||||
document.addEventListener("pause", WikitudePlugin.onPause, false);
|
||||
|
||||
WikitudePlugin.isOpened = true;
|
||||
document.addEventListener("backbutton", WikitudePlugin.onBackButton, false);
|
||||
|
||||
// After we started loading the world, we start location updates
|
||||
WikitudePlugin.startLocationUpdates();
|
||||
|
||||
}else
|
||||
{
|
||||
// if the device is not able to start the Wikitude SDK, we notify the user again
|
||||
WikitudePlugin.deviceNotARchitectReady();
|
||||
}
|
||||
},
|
||||
|
||||
/* Managing the Wikitude SDK Lifecycle */
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to stop the Wikitude SDK and to remove the ARchitectView from the screen
|
||||
*
|
||||
*/
|
||||
close : function()
|
||||
{
|
||||
document.removeEventListener("pause", WikitudePlugin.onPause, false);
|
||||
document.removeEventListener("resume", WikitudePlugin.onResume, false);
|
||||
|
||||
WikitudePlugin.stopLocationUpdates();
|
||||
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "close", [""]);
|
||||
WikitudePlugin.isOpened = false;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to only hide the Wikitude SDK. All location and rendering updates are still active
|
||||
*
|
||||
*/
|
||||
hide : function()
|
||||
{
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "hide", [""]);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to show the Wikitude SDK if it was hidden before
|
||||
*
|
||||
*/
|
||||
show : function()
|
||||
{
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "show", [""]);
|
||||
},
|
||||
|
||||
/* Interacting with the Wikitude SDK */
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to call javascript which will be executed in the context of your ARchitect World
|
||||
*
|
||||
*
|
||||
* @param js The JavaScript that gets evaluated in context of the ARchitect World
|
||||
*
|
||||
*/
|
||||
callJavaScript : function(js)
|
||||
{
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "callJavascript", [js]);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to set a callback which will be invoked when the ARchitect World calls for example
|
||||
* document.location = "architectsdk://opendetailpage?id=9";
|
||||
*
|
||||
*
|
||||
* @param onUrlInvokeCallback A function which gets called when the ARchitect World invokes a call to "document.location = architectsdk://"
|
||||
*/
|
||||
setOnUrlInvokeCallback : function(onUrlInvokeCallback)
|
||||
{
|
||||
cordova.exec(onUrlInvokeCallback, WikitudePlugin.onWikitudeError, "WikitudePlugin", "onUrlInvoke", [""]);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* =============================================================================================================================
|
||||
*
|
||||
* Callbacks of public functions
|
||||
*
|
||||
* =============================================================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this callback to get notified if the world loaded successfully
|
||||
*
|
||||
*/
|
||||
worldLaunched : function()
|
||||
{
|
||||
if(WikitudePlugin.onARchitectWorldLaunchedCallback)
|
||||
{
|
||||
WikitudePlugin.onARchitectWorldLaunchedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this callback to get notified if the Wikitude SDK wasn't able to load the ARchitect World
|
||||
*
|
||||
*/
|
||||
worldFailedLaunching : function(err)
|
||||
{
|
||||
if(WikitudePlugin.onARchitectWorldFailedLaunchingCallback)
|
||||
{
|
||||
WikitudePlugin.onARchitectWorldFailedLaunchingCallback(err);
|
||||
}
|
||||
},
|
||||
|
||||
/* Lifecycle updates */
|
||||
|
||||
/**
|
||||
*
|
||||
* This function actually starts the PhoneGap location updates
|
||||
*
|
||||
*/
|
||||
startLocationUpdates : function()
|
||||
{
|
||||
|
||||
WikitudePlugin.watchID = navigator.geolocation.watchPosition(WikitudePlugin.onReceivedLocation, WikitudePlugin.onWikitudeError, { frequency: WikitudePlugin.locationUpdateRate });
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This callback gets called everytime the location did update
|
||||
*
|
||||
*/
|
||||
onReceivedLocation : function(position)
|
||||
{
|
||||
|
||||
// Every time that PhoneGap did received a location update, we pass the location into the Wikitude SDK
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "setLocation", [{ lat: position.coords.latitude, lon: position.coords.longitude, alt: position.coords.altitude, acc: position.coords.accuracy}]);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to stop location updates
|
||||
*
|
||||
*/
|
||||
stopLocationUpdates : function()
|
||||
{
|
||||
|
||||
// We clear the location update watch which was responsible for updating the location in a specific time interval
|
||||
navigator.geolocation.clearWatch(WikitudePlugin.watchID);
|
||||
WikitudePlugin.watchID = null;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application did become active.
|
||||
*
|
||||
*/
|
||||
onResume : function()
|
||||
{
|
||||
|
||||
// Call the Wikitude SDK that the application did become active again
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "onResume", [""]);
|
||||
|
||||
// And start continuing updating the user location
|
||||
WikitudePlugin.startLocationUpdates();
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
onPause : function()
|
||||
{
|
||||
|
||||
// Call the Wikitude SDK that the application did resign active
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "onPause", [""]);
|
||||
|
||||
// And stop all ongoing location updates
|
||||
WikitudePlugin.stopLocationUpdates();
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Android specific!
|
||||
* This function gets called if the user presses the back button.
|
||||
* You may define your own implementation by using WikitudePlugin.onPressedBackButton(method)
|
||||
*
|
||||
*/
|
||||
onBackButton : function()
|
||||
{
|
||||
if (WikitudePlugin.isOpened) {
|
||||
if (WikitudePlugin.backButtonCallback==null) {
|
||||
WikitudePlugin.close();
|
||||
document.removeEventListener("backbutton", WikitudePlugin.onBackButton, false);
|
||||
} else {
|
||||
WikitudePlugin.backButtonCallback();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
onWikitudeOK : function()
|
||||
{
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
onWikitudeError : function()
|
||||
{
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
report: function(id)
|
||||
{
|
||||
console.log("app report: " + id);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.wikitude.phonegap;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.qualcomm.QCAR.QCAR;
|
||||
import com.wikitude.architect.ArchitectView.ArchitectConfig;
|
||||
import com.wikitude.architect.VuforiaInterface;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Advanced Wikitude ARchitect Plugin (= Basic Plugin + Vuforia Image Recognition feature-set)
|
||||
*
|
||||
* You must add "wikitudesdk.jar" and "QCAR.lib" to your libs folder and build-path and have "libQCAR.so" in project's "libs/armeabi/" directory
|
||||
*
|
||||
* Also add "<plugin name="WikitudePlugin" value="com.wikitude.phonegap.WikitudePluginVuforia"/>"
|
||||
* (replace Basic-plugin entry if necessary)
|
||||
*
|
||||
* in config.xml to enable this plug-in in your project; Ensure your architectSDK key is Vuforia-ready
|
||||
*
|
||||
* Note:
|
||||
* This plug-in is written under Apache License, Version 2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @author Wikitude GmbH; www.wikitude.com
|
||||
*/
|
||||
public class WikitudePluginExtended extends WikitudePlugin {
|
||||
|
||||
|
||||
static {
|
||||
System.loadLibrary( "QCAR" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Architect-Configuration required for proper set-up
|
||||
* @param apiKey
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected ArchitectConfig getArchitectConfig( final String apiKey ) {
|
||||
final ArchitectConfig config = super.getArchitectConfig( apiKey );
|
||||
|
||||
/* required for Vuforia */
|
||||
config.setVuforiaInterface( new VuforiaServiceImplementation() );
|
||||
return config;
|
||||
}
|
||||
|
||||
/* required for Vuforia */
|
||||
private class VuforiaServiceImplementation implements VuforiaInterface {
|
||||
|
||||
@Override
|
||||
public void deInit() {
|
||||
QCAR.deinit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init() {
|
||||
return QCAR.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
QCAR.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
QCAR.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceChanged( final int arg0, final int arg1 ) {
|
||||
QCAR.onSurfaceChanged( arg0, arg1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated() {
|
||||
QCAR.onSurfaceCreated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInitParameters( final Activity activity, final int nFlags ) {
|
||||
QCAR.setInitParameters( activity, nFlags );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="lib" path="libs/wikitudesdk.jar"/>
|
||||
<classpathentry kind="lib" path="libs/cordova-2.0.0.jar"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>HelloWorld</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.wikitude.phonegapsamplehelloworld"
|
||||
android:versionCode="1"
|
||||
android:versionName="0.9" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="8"/>
|
||||
|
||||
<supports-screens
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:smallScreens="true"
|
||||
android:resizeable="true"
|
||||
android:anyDensity="true" />
|
||||
|
||||
<!--
|
||||
|
||||
Please check: Wikitude's AR does not need these permissions, maybe you need them anyway
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
||||
|
||||
-->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_GPS" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
|
||||
<!-- AHAU: required hardware components -->
|
||||
<uses-feature android:name="android.hardware.camera" android:required="true" />
|
||||
|
||||
<!-- you need to have a way to find users location -->
|
||||
<uses-feature android:name="android.hardware.location" android:required="true" />
|
||||
|
||||
<!-- you need to have a accelerometer -->
|
||||
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
|
||||
|
||||
<!-- you need to have a compass -->
|
||||
<uses-feature android:name="android.hardware.sensor.compass" android:required="true" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name" android:debuggable="true">
|
||||
<activity
|
||||
android:name="com.wikitude.phonegap.PhonegapSampleActivity"
|
||||
android:label="@string/app_name" android:configChanges="orientation|keyboardHidden|screenSize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="target-densitydpi=device-dpi, width = 540, user-scalable = 0" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>My ARchitect World</title>
|
||||
|
||||
|
||||
|
||||
<!-- Include the ARchitect library -->
|
||||
<script src="architect://architect.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
var label = null;
|
||||
|
||||
function createLabelAtLocation(geoLocation)
|
||||
{
|
||||
label = new AR.Label("No Text", 2, {onClick : function(){
|
||||
document.location = "architectsdk://didClickedOnLabel?text=HelloWorld";
|
||||
}});
|
||||
|
||||
var geoObject = new AR.GeoObject(geoLocation, {drawables: {cam: label}});
|
||||
}
|
||||
|
||||
function setupScene()
|
||||
{
|
||||
createLabelAtLocation( new AR.RelativeLocation(null, 100, 0, 0) );
|
||||
}
|
||||
|
||||
function didReceivedNewTextForLabel(text)
|
||||
{
|
||||
alert(text + " - text");
|
||||
if(label)
|
||||
{
|
||||
label.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onLoad="setupScene()">
|
||||
</body>
|
||||
|
||||
</html>
|
||||
5724
Android/AugmentedReality-Wikitude/SampleProjects/Basic/HelloWorld/assets/www/cordova-2.0.0.js
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
html,
|
||||
body {
|
||||
height:100%;
|
||||
font-size:12px;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
html {
|
||||
display:table;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color:#A7A7A7;
|
||||
background-image:linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
|
||||
background-image:-webkit-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
|
||||
background-image:-ms-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
|
||||
background-image:-webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
left bottom,
|
||||
color-stop(0, #A7A7A7),
|
||||
color-stop(0.51, #E4E4E4)
|
||||
);
|
||||
display:table-cell;
|
||||
font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif;
|
||||
text-transform:uppercase;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
.app {
|
||||
background-image:url(../img/cordova.png);
|
||||
background-repeat:no-repeat;
|
||||
margin:0px auto;
|
||||
width:275px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size:2em;
|
||||
font-weight:300;
|
||||
margin:0px;
|
||||
overflow:visible;
|
||||
padding:0px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.status {
|
||||
background-color:#333333;
|
||||
border-radius:4px;
|
||||
-webkit-border-radius:4px;
|
||||
color:#FFFFFF;
|
||||
font-size:1em;
|
||||
margin:0px auto;
|
||||
padding:2px 10px;
|
||||
text-align:center;
|
||||
width:100%;
|
||||
max-width:175px;
|
||||
}
|
||||
|
||||
.status.complete {
|
||||
background-color:#4B946A;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display:none;
|
||||
}
|
||||
|
||||
@keyframes fade {
|
||||
from { opacity: 1.0; }
|
||||
50% { opacity: 0.4; }
|
||||
to { opacity: 1.0; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes fade {
|
||||
from { opacity: 1.0; }
|
||||
50% { opacity: 0.4; }
|
||||
to { opacity: 1.0; }
|
||||
}
|
||||
|
||||
.blink {
|
||||
animation:fade 3000ms infinite;
|
||||
-webkit-animation:fade 3000ms infinite;
|
||||
}
|
||||
|
||||
/* portrait */
|
||||
/* @media screen and (max-aspect-ratio: 1/1) */
|
||||
.app {
|
||||
background-position:center top;
|
||||
height:100px; /* adds enough room for text */
|
||||
padding:180px 0px 0px 0px; /* background height - shadow offset */
|
||||
}
|
||||
|
||||
/* lanscape (when wide enough) */
|
||||
@media screen and (min-aspect-ratio: 1/1) and (min-width:445px) {
|
||||
.app {
|
||||
background-position:left center;
|
||||
height:140px; /* height + padding = background image size */
|
||||
padding-left:170px; /* background width */
|
||||
padding-top:60px; /* center the text */
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta name="viewport" content="width=320; user-scalable=no" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
|
||||
<title>PhoneGap and Wikitude</title>
|
||||
|
||||
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title">
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="cordova-2.0.0.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/WikitudePlugin.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="css/index.css" />
|
||||
<title>Hello Cordova</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<h1>Apache Cordova™</h1>
|
||||
<div id="deviceready">
|
||||
<p class="status pending blink">Connecting to Device</p>
|
||||
<p class="status complete blink hide">Device is Ready</p>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="cordova-2.0.0.js"></script>
|
||||
<script type="text/javascript" src="js/index.js"></script>
|
||||
<script type="text/javascript" src="js/WikitudePlugin.js"></script>
|
||||
<script type="text/javascript">
|
||||
app.initialize();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,383 @@
|
||||
var WikitudePlugin = {
|
||||
|
||||
/**
|
||||
*
|
||||
* This is the SDK Key, provided to you after you purchased the Wikitude SDK from http://www.wikitude.com/developer/sdk
|
||||
* If you're having a trial version, leave this string empty
|
||||
*
|
||||
*/
|
||||
mySDKKey : "ENTER-YOUR-KEY-HERE",
|
||||
|
||||
/** true if architectview is open */
|
||||
isOpened : false,
|
||||
|
||||
/**
|
||||
*
|
||||
* called when user pressed back-button on Android device
|
||||
*
|
||||
*/
|
||||
backButtonCallback : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* Change the value of this variable to modify the location update rate
|
||||
*
|
||||
*/
|
||||
locationUpdateRate : 3000,
|
||||
|
||||
/**
|
||||
*
|
||||
* This variable represents if the current device is capable of running the Wikitude SDK
|
||||
*
|
||||
*/
|
||||
isDeviceSupported : false,
|
||||
|
||||
/**
|
||||
*
|
||||
* This watchID is used to shedule location updates
|
||||
*
|
||||
*/
|
||||
watchID : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* Callbacks to get device information if ARchitect Worlds can be launched
|
||||
*
|
||||
*/
|
||||
onDeviceSupportedCallback : null,
|
||||
onDeviceNotSupportedCallback : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* Callbacks to get notified if the ARchitect World finished launching or if something went wrong during the World launch
|
||||
*
|
||||
*/
|
||||
onARchitectWorldLaunchedCallback : null,
|
||||
onARchitectWorldFailedLaunchingCallback : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if PhoneGap reports that it has finished loading successfully.
|
||||
*
|
||||
*/
|
||||
isDeviceSupported: function(successCallback, errorCallback)
|
||||
{
|
||||
|
||||
WikitudePlugin.onDeviceSupportedCallback = successCallback;
|
||||
WikitudePlugin.onDeviceNotSupportedCallback = errorCallback;
|
||||
|
||||
|
||||
// PhoneGap is running, so the first thing we do is to check if the current device is capable of running the Wikitude Plugin
|
||||
cordova.exec(WikitudePlugin.deviceIsARchitectReady, WikitudePlugin.deviceIsNotARchitectReady, "WikitudePlugin", "isDeviceSupported", [""]);
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Declare what should happen when user pressed back-button while architect-view is opened.
|
||||
* If not declared/called or null: ARchitect-View is closed
|
||||
*
|
||||
*/
|
||||
onPressedBackButton : function(callback)
|
||||
{
|
||||
WikitudePlugin.backButtonCallback = callback;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if the Wikitude Plugin reports that the device is able to start the Wikitude SDK
|
||||
*
|
||||
*/
|
||||
deviceIsARchitectReady : function()
|
||||
{
|
||||
// We keep track of the device status
|
||||
WikitudePlugin.isDeviceSupported = true;
|
||||
|
||||
|
||||
if(WikitudePlugin.onDeviceSupportedCallback)
|
||||
{
|
||||
WikitudePlugin.onDeviceSupportedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if the Wikitude Plugin reports that the device is not able of starting the Wikitude SDK.
|
||||
*
|
||||
*/
|
||||
deviceIsNotARchitectReady : function()
|
||||
{
|
||||
WikitudePlugin.isDeviceSupported = false;
|
||||
|
||||
// In this case we notify the user that his device is not supported by the Wikitude SDK
|
||||
if(WikitudePlugin.onDeviceNotSupportedCallback)
|
||||
{
|
||||
WikitudePlugin.onDeviceNotSupportedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* =============================================================================================================================
|
||||
*
|
||||
* PUBLIC API
|
||||
*
|
||||
* =============================================================================================================================
|
||||
*/
|
||||
|
||||
/* Managing ARchitect world loading */
|
||||
|
||||
/**
|
||||
*
|
||||
* Call this function if you want to load an ARchitect World
|
||||
*
|
||||
* @param {String} worldPath The path to an ARchitect world ether on the device or on e.g. your dropbox
|
||||
*
|
||||
*/
|
||||
loadARchitectWorld : function(worldPath)
|
||||
{
|
||||
|
||||
// before we actually call load, we check again if the device is able to open the world
|
||||
if(WikitudePlugin.isDeviceSupported)
|
||||
{
|
||||
|
||||
// the 'open' function of the Wikitude Plugin requires a option dictionary with two keys:
|
||||
// @param {Object} options (required)
|
||||
// @param {String} options.sdkKey License key for the Wikitude SDK
|
||||
// @param {String} options.filePath The path to a local ARchitect world or to a ARchitect world on a server or your dropbox
|
||||
|
||||
cordova.exec(WikitudePlugin.worldLaunched, WikitudePlugin.worldFailedLaunching, "WikitudePlugin", "open", [{ sdkKey: WikitudePlugin.mySDKKey, filePath: worldPath}]);
|
||||
|
||||
|
||||
// We add an event listener on the resume and pause event of the application lifecycle
|
||||
document.addEventListener("resume", WikitudePlugin.onResume, false);
|
||||
document.addEventListener("pause", WikitudePlugin.onPause, false);
|
||||
|
||||
WikitudePlugin.isOpened = true;
|
||||
document.addEventListener("backbutton", WikitudePlugin.onBackButton, false);
|
||||
|
||||
// After we started loading the world, we start location updates
|
||||
WikitudePlugin.startLocationUpdates();
|
||||
|
||||
}else
|
||||
{
|
||||
// if the device is not able to start the Wikitude SDK, we notify the user again
|
||||
WikitudePlugin.deviceNotARchitectReady();
|
||||
}
|
||||
},
|
||||
|
||||
/* Managing the Wikitude SDK Lifecycle */
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to stop the Wikitude SDK and to remove the ARchitectView from the screen
|
||||
*
|
||||
*/
|
||||
close : function()
|
||||
{
|
||||
document.removeEventListener("pause", WikitudePlugin.onPause, false);
|
||||
document.removeEventListener("resume", WikitudePlugin.onResume, false);
|
||||
|
||||
WikitudePlugin.stopLocationUpdates();
|
||||
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "close", [""]);
|
||||
WikitudePlugin.isOpened = false;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to only hide the Wikitude SDK. All location and rendering updates are still active
|
||||
*
|
||||
*/
|
||||
hide : function()
|
||||
{
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "hide", [""]);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to show the Wikitude SDK if it was hidden before
|
||||
*
|
||||
*/
|
||||
show : function()
|
||||
{
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "show", [""]);
|
||||
},
|
||||
|
||||
/* Interacting with the Wikitude SDK */
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to call javascript which will be executed in the context of your ARchitect World
|
||||
*
|
||||
*
|
||||
* @param js The JavaScript that gets evaluated in context of the ARchitect World
|
||||
*
|
||||
*/
|
||||
callJavaScript : function(js)
|
||||
{
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "callJavascript", [js]);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to set a callback which will be invoked when the ARchitect World calls for example
|
||||
* document.location = "architectsdk://opendetailpage?id=9";
|
||||
*
|
||||
*
|
||||
* @param onUrlInvokeCallback A function which gets called when the ARchitect World invokes a call to "document.location = architectsdk://"
|
||||
*/
|
||||
setOnUrlInvokeCallback : function(onUrlInvokeCallback)
|
||||
{
|
||||
cordova.exec(onUrlInvokeCallback, WikitudePlugin.onWikitudeError, "WikitudePlugin", "onUrlInvoke", [""]);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* =============================================================================================================================
|
||||
*
|
||||
* Callbacks of public functions
|
||||
*
|
||||
* =============================================================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this callback to get notified if the world loaded successfully
|
||||
*
|
||||
*/
|
||||
worldLaunched : function()
|
||||
{
|
||||
if(WikitudePlugin.onARchitectWorldLaunchedCallback)
|
||||
{
|
||||
WikitudePlugin.onARchitectWorldLaunchedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this callback to get notified if the Wikitude SDK wasn't able to load the ARchitect World
|
||||
*
|
||||
*/
|
||||
worldFailedLaunching : function(err)
|
||||
{
|
||||
if(WikitudePlugin.onARchitectWorldFailedLaunchingCallback)
|
||||
{
|
||||
WikitudePlugin.onARchitectWorldFailedLaunchingCallback(err);
|
||||
}
|
||||
},
|
||||
|
||||
/* Lifecycle updates */
|
||||
|
||||
/**
|
||||
*
|
||||
* This function actually starts the PhoneGap location updates
|
||||
*
|
||||
*/
|
||||
startLocationUpdates : function()
|
||||
{
|
||||
|
||||
WikitudePlugin.watchID = navigator.geolocation.watchPosition(WikitudePlugin.onReceivedLocation, WikitudePlugin.onWikitudeError, { frequency: WikitudePlugin.locationUpdateRate });
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This callback gets called everytime the location did update
|
||||
*
|
||||
*/
|
||||
onReceivedLocation : function(position)
|
||||
{
|
||||
|
||||
// Every time that PhoneGap did received a location update, we pass the location into the Wikitude SDK
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "setLocation", [{ lat: position.coords.latitude, lon: position.coords.longitude, alt: position.coords.altitude, acc: position.coords.accuracy}]);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to stop location updates
|
||||
*
|
||||
*/
|
||||
stopLocationUpdates : function()
|
||||
{
|
||||
|
||||
// We clear the location update watch which was responsible for updating the location in a specific time interval
|
||||
navigator.geolocation.clearWatch(WikitudePlugin.watchID);
|
||||
WikitudePlugin.watchID = null;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application did become active.
|
||||
*
|
||||
*/
|
||||
onResume : function()
|
||||
{
|
||||
|
||||
// Call the Wikitude SDK that the application did become active again
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "onResume", [""]);
|
||||
|
||||
// And start continuing updating the user location
|
||||
WikitudePlugin.startLocationUpdates();
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
onPause : function()
|
||||
{
|
||||
|
||||
// Call the Wikitude SDK that the application did resign active
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "onPause", [""]);
|
||||
|
||||
// And stop all ongoing location updates
|
||||
WikitudePlugin.stopLocationUpdates();
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Android specific!
|
||||
* This function gets called if the user presses the back button.
|
||||
* You may define your own implementation by using WikitudePlugin.onPressedBackButton(method)
|
||||
*
|
||||
*/
|
||||
onBackButton : function()
|
||||
{
|
||||
if (WikitudePlugin.isOpened) {
|
||||
if (WikitudePlugin.backButtonCallback==null) {
|
||||
WikitudePlugin.close();
|
||||
document.removeEventListener("backbutton", WikitudePlugin.onBackButton, false);
|
||||
} else {
|
||||
WikitudePlugin.backButtonCallback();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
onWikitudeOK : function()
|
||||
{
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
onWikitudeError : function()
|
||||
{
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
report: function(id)
|
||||
{
|
||||
console.log("app report: " + id);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
var app = {
|
||||
initialize: function() {
|
||||
this.bind();
|
||||
},
|
||||
bind: function() {
|
||||
document.addEventListener('deviceready', this.deviceready, false);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function extracts an url parameter
|
||||
*
|
||||
*/
|
||||
getUrlParameterForKey : function( url, requestedParam )
|
||||
{
|
||||
requestedParam = requestedParam.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
|
||||
var regexS = "[\\?&]"+requestedParam+"=([^&#]*)";
|
||||
var regex = new RegExp( regexS );
|
||||
var results = regex.exec( url );
|
||||
if( results == null )
|
||||
return "";
|
||||
else
|
||||
{
|
||||
var result = decodeURIComponent(results[1]);
|
||||
return result;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if you call "document.location = architectsdk://" in your ARchitect World
|
||||
*
|
||||
*
|
||||
* @param url The url which was called in ARchitect World
|
||||
*
|
||||
*/
|
||||
onClickInARchitectWorld : function(url)
|
||||
{
|
||||
|
||||
app.report("you clicked on a label with text: " + app.getUrlParameterForKey(url, 'text'));
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called it the Wikitude SDK is able to start an ARchitect World (the current device is supported by the Wikitude SDK)
|
||||
*
|
||||
*/
|
||||
onDeviceIsReadyCallback : function()
|
||||
{
|
||||
// The device is able to launch ARchitect World, so we load the 'Hello World' example
|
||||
WikitudePlugin.loadARchitectWorld("assets/world/HelloWorld.html");
|
||||
|
||||
// To be able to respond on events inside the ARchitect World, we set a onURLInvoke callback
|
||||
WikitudePlugin.setOnUrlInvokeCallback(app.onClickInARchitectWorld);
|
||||
|
||||
// This is a example how you can interact with the ARchitect World to pass in additional information
|
||||
// In this example, a JavaScript function gets called which sets a new text for a label
|
||||
WikitudePlugin.callJavaScript("didReceivedNewTextForLabel('Hello World')");
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets if the current device is not capable of running ARchitect Worlds
|
||||
*
|
||||
*/
|
||||
onDeviceIsUnsupportedCallback : function()
|
||||
{
|
||||
app.report('device is not supported');
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets if the ARchitect World finished loading
|
||||
*
|
||||
*/
|
||||
onARchitectWorldLaunchedCallback : function()
|
||||
{
|
||||
app.report('ARchitect World launched');
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets if the ARchitect failed loading
|
||||
*
|
||||
*/
|
||||
onARchitectWorldFailedLaunchingCallback : function(err)
|
||||
{
|
||||
app.report('ARchitect World failed launching');
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called when the Wikitude SDK is ready to start an ARchitect World (the current device is supported by the Wikitude SDK)
|
||||
*
|
||||
*/
|
||||
deviceready: function() {
|
||||
// note that this is an event handler so the scope is that of the event
|
||||
// so we need to call app.report(), and not this.report()
|
||||
app.report('deviceready');
|
||||
|
||||
// When PhoneGap finished loading we forward this event into the Wikitude SDK wrapper.
|
||||
// @param {function} A function which gets called if the device is able to launch ARchitect Worlds
|
||||
// @param {function} A function which gets called if the device is not able to launch ARchitect Worlds
|
||||
WikitudePlugin.isDeviceSupported(app.onDeviceIsReadyCallback, app.onDeviceIsUnsupportedCallback);
|
||||
|
||||
// set a callback on the WikitudePlugin to get informed when the ARchitect World finished loading
|
||||
WikitudePlugin.onARchitectWorldLaunchedCallback = app.onARchitectWorldLaunchedCallback;
|
||||
|
||||
// Set a callback on the WikitudePlugin to get informed when the ARchitect World failed loading
|
||||
WikitudePlugin.onARchitectWorldFailedLaunchingCallback = app.onARchitectWorldFailedLaunchingCallback;
|
||||
},
|
||||
report: function(id) {
|
||||
console.log("report:" + id);
|
||||
}
|
||||
};
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 217 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 478 KiB |
|
After Width: | Height: | Size: 493 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 398 KiB |
|
After Width: | Height: | Size: 412 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 342 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Jasmine Spec Runner</title>
|
||||
|
||||
<!-- jasmine source -->
|
||||
<link rel="shortcut icon" type="image/png" href="spec/lib/jasmine-1.2.0/jasmine_favicon.png">
|
||||
<link rel="stylesheet" type="text/css" href="spec/lib/jasmine-1.2.0/jasmine.css">
|
||||
<script type="text/javascript" src="spec/lib/jasmine-1.2.0/jasmine.js"></script>
|
||||
<script type="text/javascript" src="spec/lib/jasmine-1.2.0/jasmine-html.js"></script>
|
||||
|
||||
<!-- include source files here... -->
|
||||
<script type="text/javascript" src="js/index.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script type="text/javascript" src="spec/helper.js"></script>
|
||||
<script type="text/javascript" src="spec/index.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
var jasmineEnv = jasmine.getEnv();
|
||||
jasmineEnv.updateInterval = 1000;
|
||||
|
||||
var htmlReporter = new jasmine.HtmlReporter();
|
||||
|
||||
jasmineEnv.addReporter(htmlReporter);
|
||||
|
||||
jasmineEnv.specFilter = function(spec) {
|
||||
return htmlReporter.specFilter(spec);
|
||||
};
|
||||
|
||||
var currentWindowOnload = window.onload;
|
||||
|
||||
window.onload = function() {
|
||||
if (currentWindowOnload) {
|
||||
currentWindowOnload();
|
||||
}
|
||||
execJasmine();
|
||||
};
|
||||
|
||||
function execJasmine() {
|
||||
jasmineEnv.execute();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="stage" style="display:none;"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
afterEach(function() {
|
||||
document.getElementById('stage').innerHTML = '';
|
||||
});
|
||||
|
||||
var helper = {
|
||||
trigger: function(obj, name) {
|
||||
var e = document.createEvent('Event');
|
||||
e.initEvent(name, true, true);
|
||||
obj.dispatchEvent(e);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
describe('app', function() {
|
||||
describe('initialize', function() {
|
||||
it('should bind deviceready', function() {
|
||||
runs(function() {
|
||||
spyOn(app, 'deviceready');
|
||||
app.initialize();
|
||||
helper.trigger(window.document, 'deviceready');
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return (app.deviceready.calls.length > 0);
|
||||
}, 'deviceready should be called once', 500);
|
||||
|
||||
runs(function() {
|
||||
expect(app.deviceready).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('deviceready', function() {
|
||||
it('should report that it fired', function() {
|
||||
spyOn(app, 'report');
|
||||
app.deviceready();
|
||||
expect(app.report).toHaveBeenCalledWith('deviceready');
|
||||
});
|
||||
});
|
||||
|
||||
describe('report', function() {
|
||||
beforeEach(function() {
|
||||
var el = document.getElementById('stage');
|
||||
el.innerHTML = ['<div id="deviceready">',
|
||||
' <p class="status pending">Pending</p>',
|
||||
' <p class="status complete hide">Complete</p>',
|
||||
'</div>'].join('\n');
|
||||
});
|
||||
|
||||
it('should show the completion state', function() {
|
||||
app.report('deviceready');
|
||||
var el = document.querySelector('#deviceready .complete:not(.hide)');
|
||||
expect(el).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should hide the pending state', function() {
|
||||
app.report('deviceready');
|
||||
var el = document.querySelector('#deviceready .pending.hide');
|
||||
expect(el).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
|
||||
|
||||
bash $CORDOVA_PATH/cordova BOOM
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
|
||||
|
||||
bash $CORDOVA_PATH/cordova clean
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT_PATH=$( cd "$( dirname "$0" )/.." && pwd )
|
||||
|
||||
function check_devices {
|
||||
local devices=`adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}'`
|
||||
if [ -z "$devices" ] ; then
|
||||
echo "1"
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
}
|
||||
|
||||
function emulate {
|
||||
declare -a avd_list=($(android list avd | grep "Name:" | cut -f 2 -d ":" | xargs))
|
||||
# we need to start adb-server
|
||||
adb start-server 1>/dev/null
|
||||
|
||||
# Do not launch an emulator if there is already one running or if a device is attached
|
||||
if [ $(check_devices) == 0 ] ; then
|
||||
echo "Device attached or emulator already running"
|
||||
return
|
||||
fi
|
||||
|
||||
local avd_id="1000" #FIXME: hopefully user does not have 1000 AVDs
|
||||
# User has no AVDs
|
||||
if [ ${#avd_list[@]} == 0 ]
|
||||
then
|
||||
echo "You don't have any Android Virtual Devices. Please create at least one AVD."
|
||||
echo "android"
|
||||
fi
|
||||
# User has only one AVD
|
||||
if [ ${#avd_list[@]} == 1 ]
|
||||
then
|
||||
emulator -cpu-delay 0 -no-boot-anim -cache /tmp/cache -avd ${avd_list[0]} 1> /dev/null 2>&1 &
|
||||
# User has more than 1 AVD
|
||||
elif [ ${#avd_list[@]} -gt 1 ]
|
||||
then
|
||||
while [ -z ${avd_list[$avd_id]} ]
|
||||
do
|
||||
echo "Choose from one of the following Android Virtual Devices [0 to $((${#avd_list[@]}-1))]:"
|
||||
for(( i = 0 ; i < ${#avd_list[@]} ; i++ ))
|
||||
do
|
||||
echo "$i) ${avd_list[$i]}"
|
||||
done
|
||||
echo -n "> "
|
||||
read avd_id
|
||||
done
|
||||
emulator -cpu-delay 0 -no-boot-anim -cache /tmp/cache -avd ${avd_list[$avd_id]} 1> /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
function clean {
|
||||
ant clean
|
||||
}
|
||||
# has to be used independently and not in conjuction with other commands
|
||||
function log {
|
||||
adb logcat
|
||||
}
|
||||
|
||||
function debug {
|
||||
if [ $(check_devices) == 0 ] ; then
|
||||
ant debug install
|
||||
else
|
||||
ant debug
|
||||
echo "##################################################################"
|
||||
echo "# Plug in your device or launch an emulator with cordova/emulate #"
|
||||
echo "##################################################################"
|
||||
fi
|
||||
}
|
||||
|
||||
function launch {
|
||||
local launch_str=$(java -jar $PROJECT_PATH/cordova/appinfo.jar $PROJECT_PATH/AndroidManifest.xml)
|
||||
adb shell am start -n $launch_str
|
||||
}
|
||||
|
||||
function BOOM {
|
||||
clean && debug && launch
|
||||
}
|
||||
|
||||
# TODO parse arguments
|
||||
(cd $PROJECT_PATH && $1)
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
|
||||
|
||||
bash $CORDOVA_PATH/cordova debug
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
|
||||
|
||||
bash $CORDOVA_PATH/cordova emulate
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT_PATH=$( cd "$( dirname "$0" )/.." && pwd )
|
||||
|
||||
bash $PROJECT_PATH/cordova/cordova log
|
||||
@@ -0,0 +1,20 @@
|
||||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@@ -0,0 +1,14 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-15
|
||||
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:test="http://schemas.android.com/apk/res/com.wikitude.architect"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical" >
|
||||
<com.wikitude.architect.ArchitectView android:id="@+id/architectView" android:layout_width="fill_parent" android:layout_height="fill_parent">
|
||||
</com.wikitude.architect.ArchitectView>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="hello">Hello World, PhonegapSampleActivity!</string>
|
||||
<string name="app_name">Hello World</string>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<cordova>
|
||||
<!--
|
||||
access elements control the Android whitelist.
|
||||
Domains are assumed blocked unless set otherwise
|
||||
-->
|
||||
|
||||
<access origin="http://127.0.0.1*"/> <!-- allow local pages -->
|
||||
|
||||
<!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
|
||||
<!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
|
||||
<!-- <access origin=".*"/> Allow all domains, suggested development use only -->
|
||||
|
||||
<log level="DEBUG"/>
|
||||
<preference name="useBrowserHistory" value="false" />
|
||||
<plugins>
|
||||
<plugin name="App" value="org.apache.cordova.App"/>
|
||||
<plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
|
||||
<plugin name="Device" value="org.apache.cordova.Device"/>
|
||||
<plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
|
||||
<plugin name="Compass" value="org.apache.cordova.CompassListener"/>
|
||||
<plugin name="Media" value="org.apache.cordova.AudioHandler"/>
|
||||
<plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
|
||||
<plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
|
||||
<plugin name="File" value="org.apache.cordova.FileUtils"/>
|
||||
<plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
|
||||
<plugin name="Notification" value="org.apache.cordova.Notification"/>
|
||||
<plugin name="Storage" value="org.apache.cordova.Storage"/>
|
||||
<plugin name="Temperature" value="org.apache.cordova.TempListener"/>
|
||||
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
|
||||
<plugin name="Capture" value="org.apache.cordova.Capture"/>
|
||||
<plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
|
||||
<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
|
||||
|
||||
<!-- basic Wikitude plugin -->
|
||||
<plugin name="WikitudePlugin" value="com.wikitude.phonegap.WikitudePlugin"/>
|
||||
</plugins>
|
||||
</cordova>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.wikitude.phonegap;
|
||||
|
||||
import org.apache.cordova.DroidGap;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
|
||||
|
||||
public class PhonegapSampleActivity extends DroidGap {
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate( Bundle savedInstanceState ) {
|
||||
super.onCreate( savedInstanceState );
|
||||
super.loadUrl( "file:///android_asset/www/index.html" );
|
||||
// super.loadUrl( "file:///android_asset/www/demo.html" );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
package com.wikitude.phonegap;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewManager;
|
||||
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import com.wikitude.architect.ArchitectUrlListener;
|
||||
import com.wikitude.architect.ArchitectView;
|
||||
import com.wikitude.architect.ArchitectView.ArchitectConfig;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Basic PhoneGap Wikitude ARchitect Plugin
|
||||
*
|
||||
* @author Wikitude GmbH
|
||||
*/
|
||||
public class WikitudePlugin extends Plugin implements ArchitectUrlListener {
|
||||
|
||||
/** PhoneGap-root to Android-App-assets folder */
|
||||
private static final String LOCAL_ASSETS_PATH_ROOT = "assets/";
|
||||
|
||||
/* various JSON-Object keys*/
|
||||
private static final String JSON_KEY_APIKEY = "sdkKey";
|
||||
private static final String JSON_KEY_FILE_PATH = "filePath";
|
||||
|
||||
private static final String JSON_KEY_LOCATION_ALTITUDE = "alt";
|
||||
private static final String JSON_KEY_LOCATION_ACCURACY = "acc";
|
||||
private static final String JSON_KEY_LOCATION_LATITUDE = "lat";
|
||||
private static final String JSON_KEY_LOCATION_LONGITUDE = "lon";
|
||||
|
||||
/* static action strings */
|
||||
|
||||
/**
|
||||
* opens architect-view (add to view stack)
|
||||
*/
|
||||
private static final String ACTION_OPEN = "open";
|
||||
|
||||
/**
|
||||
* closes architect-view (remove view stack)
|
||||
*/
|
||||
private static final String ACTION_CLOSE = "close";
|
||||
|
||||
/**
|
||||
* set visibility of architectView to visible (of present)
|
||||
*/
|
||||
private static final String ACTION_SHOW = "show";
|
||||
|
||||
/**
|
||||
* set visibility of architectView to invisible (of present)
|
||||
*/
|
||||
private static final String ACTION_HIDE = "hide";
|
||||
|
||||
/**
|
||||
* inject location information
|
||||
*/
|
||||
private static final String ACTION_SET_LOCATION = "setLocation";
|
||||
|
||||
/**
|
||||
* callback for uri-invocations
|
||||
*/
|
||||
private static final String ACTION_ON_URLINVOKE = "onUrlInvoke";
|
||||
|
||||
/**
|
||||
* life-cycle notification for resume
|
||||
*/
|
||||
private static final String ACTION_ON_RESUME = "onResume";
|
||||
|
||||
/**
|
||||
* life-cycle notification for pause
|
||||
*/
|
||||
private static final String ACTION_ON_PAUSE = "onPause";
|
||||
|
||||
/**
|
||||
* check if view is on view-stack (no matter if visible or not)
|
||||
*/
|
||||
private static final String ACTION_STATE_ISOPEN = "isOpen";
|
||||
|
||||
/**
|
||||
* opens architect-view (add to view stack)
|
||||
*/
|
||||
private static final String ACTION_IS_DEVICE_SUPPORTED = "isDeviceSupported";
|
||||
|
||||
/**
|
||||
* check if view is on view-stack (no matter if visible or not)
|
||||
*/
|
||||
private static final String ACTION_CALL_JAVASCRIPT = "callJavascript";
|
||||
|
||||
/**
|
||||
* the Wikitude ARchitectview
|
||||
*/
|
||||
private ArchitectView architectView;
|
||||
|
||||
/**
|
||||
* callback-Id of url-invocation method
|
||||
*/
|
||||
private String urlInvokeCallbackId = null;
|
||||
|
||||
/**
|
||||
* callback-id of "open"-action method
|
||||
*/
|
||||
private String openCallbackId = null;
|
||||
|
||||
@Override
|
||||
public PluginResult execute( final String action, final JSONArray args, final String callbackId ) {
|
||||
|
||||
/* hide architect-view -> destroy and remove from activity */
|
||||
if ( WikitudePlugin.ACTION_CLOSE.equals( action ) ) {
|
||||
if ( this.architectView != null ) {
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
removeArchitectView();
|
||||
}
|
||||
} );
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
}
|
||||
else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
/* return success only if view is opened (no matter if visible or not) */
|
||||
if ( WikitudePlugin.ACTION_STATE_ISOPEN.equals( action ) ) {
|
||||
if ( this.architectView != null ) {
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
/* return success only if view is opened (no matter if visible or not) */
|
||||
if ( WikitudePlugin.ACTION_IS_DEVICE_SUPPORTED.equals( action ) ) {
|
||||
if ( ArchitectView.isDeviceSupported( this.cordova.getActivity() ) ) {
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": this device is ARchitect-ready" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": Sorry, this device is NOT ARchitect-ready" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* life-cycle's RESUME */
|
||||
if ( WikitudePlugin.ACTION_ON_RESUME.equals( action ) ) {
|
||||
|
||||
if ( this.architectView != null ) {
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
WikitudePlugin.this.architectView.onResume();
|
||||
}
|
||||
} );
|
||||
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
}
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
|
||||
/* life-cycle's PAUSE */
|
||||
if ( WikitudePlugin.ACTION_ON_PAUSE.equals( action ) ) {
|
||||
if ( architectView != null ) {
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
WikitudePlugin.this.architectView.onPause();
|
||||
}
|
||||
} );
|
||||
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
}
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
|
||||
/* set visibility to "visible", return error if view is null */
|
||||
if ( WikitudePlugin.ACTION_SHOW.equals( action ) ) {
|
||||
|
||||
if ( this.architectView != null ) {
|
||||
this.architectView.setVisibility( View.VISIBLE );
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
/* set visibility to "invisible", return error if view is null */
|
||||
if ( WikitudePlugin.ACTION_HIDE.equals( action ) ) {
|
||||
|
||||
if ( this.architectView != null ) {
|
||||
this.architectView.setVisibility( View.INVISIBLE );
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": architectView is present" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectView is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
/* define call-back for url-invocations */
|
||||
if ( WikitudePlugin.ACTION_ON_URLINVOKE.equals( action ) ) {
|
||||
this.urlInvokeCallbackId = callbackId;
|
||||
PluginResult result = new PluginResult( PluginResult.Status.NO_RESULT, action + ": registered callback" );
|
||||
result.setKeepCallback( true );
|
||||
return result;
|
||||
}
|
||||
|
||||
/* location update */
|
||||
if ( WikitudePlugin.ACTION_SET_LOCATION.equals( action ) ) {
|
||||
if ( this.architectView != null ) {
|
||||
try {
|
||||
String arrStr = args.getString( 0 );
|
||||
JSONObject arr = new JSONObject( arrStr );
|
||||
final double lat = arr.getDouble( WikitudePlugin.JSON_KEY_LOCATION_LATITUDE );
|
||||
final double lon = arr.getDouble( WikitudePlugin.JSON_KEY_LOCATION_LONGITUDE );
|
||||
Object altObj = arr.get( WikitudePlugin.JSON_KEY_LOCATION_ALTITUDE );
|
||||
float alt = Float.MIN_VALUE;
|
||||
|
||||
if ( altObj != null && altObj instanceof Double ) {
|
||||
alt = ((Double)altObj).floatValue();
|
||||
}
|
||||
|
||||
final float altitude = alt;
|
||||
|
||||
final Double acc = arr.getDouble( WikitudePlugin.JSON_KEY_LOCATION_ACCURACY );
|
||||
if ( this.cordova != null && this.cordova.getActivity() != null ) {
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if ( acc != null ) {
|
||||
WikitudePlugin.this.architectView.setLocation( lat, lon, altitude, acc.floatValue() );
|
||||
} else {
|
||||
WikitudePlugin.this.architectView.setLocation( lat, lon, altitude );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
} catch ( Exception e ) {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": exception thrown, " + e != null ? e.getMessage() : "(exception is NULL)" );
|
||||
}
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": updated location" );
|
||||
}
|
||||
|
||||
/* return error if there is no architect-view active*/
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectview is not active" );
|
||||
}
|
||||
|
||||
if ( WikitudePlugin.ACTION_CALL_JAVASCRIPT.equals( action ) ) {
|
||||
if ( this.architectView != null ) {
|
||||
String logMsg = null;
|
||||
try {
|
||||
final String callJS = args.getString( 0 );
|
||||
logMsg = callJS;
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
WikitudePlugin.this.architectView.callJavascript( callJS );
|
||||
}
|
||||
} );
|
||||
|
||||
} catch ( JSONException je ) {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": exception thrown, " + je != null ? je.getMessage() : "(exception is NULL)" );
|
||||
}
|
||||
return new PluginResult( PluginResult.Status.OK, action + ": called js, '" + logMsg + "'" );
|
||||
} else {
|
||||
return new PluginResult( PluginResult.Status.ERROR, action + ": architectview is not active" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* initial set-up, show ArchitectView full-screen in current screen/activity */
|
||||
if ( WikitudePlugin.ACTION_OPEN.equals( action ) ) {
|
||||
this.openCallbackId = callbackId;
|
||||
PluginResult result = null;
|
||||
String arrStr = null;
|
||||
|
||||
try {
|
||||
arrStr = args.getString( 0 );
|
||||
|
||||
// arrStr = arrStr.substring( 1, arrStr.length() - 1 );
|
||||
|
||||
JSONObject arr = new JSONObject( arrStr );
|
||||
|
||||
final String apiKey = arr.getString( WikitudePlugin.JSON_KEY_APIKEY );
|
||||
final String filePath = arr.getString( WikitudePlugin.JSON_KEY_FILE_PATH );
|
||||
|
||||
this.cordova.getActivity().runOnUiThread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
WikitudePlugin.this.addArchitectView( apiKey, filePath );
|
||||
|
||||
/* call success method once architectView was added successfully */
|
||||
if ( WikitudePlugin.this.openCallbackId != null ) {
|
||||
PluginResult result = new PluginResult( PluginResult.Status.OK );
|
||||
result.setKeepCallback( false );
|
||||
WikitudePlugin.this.success( result, WikitudePlugin.this.openCallbackId );
|
||||
}
|
||||
} catch ( Exception e ) {
|
||||
/* in case "addArchitectView" threw an exception -> notify callback method asynchronously */
|
||||
WikitudePlugin.this.error( e != null ? e.getMessage() : "Exception is 'null'", WikitudePlugin.this.openCallbackId );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
} catch ( Exception e ) {
|
||||
result = new PluginResult( PluginResult.Status.ERROR, action + ": exception thown, " + e != null ? e.getMessage() : "(exception is NULL)" );
|
||||
result.setKeepCallback( false );
|
||||
return result;
|
||||
}
|
||||
|
||||
/* adding architect-view is done in separate thread, ensure to setKeepCallback so one can call success-method properly later on */
|
||||
result = new PluginResult( PluginResult.Status.NO_RESULT, action + ": no result required, just registered callback-method" );
|
||||
result.setKeepCallback( true );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* fall-back return value */
|
||||
return new PluginResult( PluginResult.Status.ERROR, "no such action: " + action );
|
||||
}
|
||||
|
||||
/**
|
||||
* called when url was invoked in architectView (by e.g. calling document.location = "myprotocoll://foo";
|
||||
* @param url the invoked url (e.g. "myprotocoll://foo")
|
||||
* @return true if call was handled properly
|
||||
*/
|
||||
@Override
|
||||
public boolean urlWasInvoked( String url ) {
|
||||
|
||||
/* call callback-method if set*/
|
||||
if ( this.urlInvokeCallbackId != null ) {
|
||||
try {
|
||||
/* pass called url as String to callback-method */
|
||||
PluginResult res = new PluginResult( PluginResult.Status.OK, url );
|
||||
res.setKeepCallback( true );
|
||||
this.success( res, this.urlInvokeCallbackId );
|
||||
return true;
|
||||
} catch ( Exception e ) {
|
||||
this.error( "invalid url invoked: " + url, this.urlInvokeCallbackId );
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* hides/removes ARchitect-View completely
|
||||
* @return true if successful, false otherwise
|
||||
*/
|
||||
private boolean removeArchitectView() {
|
||||
if ( this.architectView != null ) {
|
||||
/* fake life-cycle calls, because activity is already up and running */
|
||||
this.architectView.onPause();
|
||||
this.architectView.onDestroy();
|
||||
this.architectView.setVisibility( View.INVISIBLE );
|
||||
((ViewManager)this.architectView.getParent()).removeView( this.architectView );
|
||||
this.architectView = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Architect-Configuration required for proper set-up
|
||||
* @param apiKey
|
||||
* @return
|
||||
*/
|
||||
protected ArchitectConfig getArchitectConfig( final String apiKey ) {
|
||||
/* no special set-up required in default Wikitude-Plugin, further things required in advanced usage (e.g. Vuforia Image Recognition) */
|
||||
return new ArchitectConfig( apiKey );
|
||||
}
|
||||
|
||||
/**
|
||||
* add architectView to current screen
|
||||
* @param apiKey developers's api key to use (hides watermarking/intro-animation if it matches your package-name)
|
||||
* @param filePath the url (starting with http:// for online use; starting with LOCAL_ASSETS_PATH_ROOT if oyu want to load assets within your app-assets folder)
|
||||
* @throws IOException might be thrown from ARchitect-SDK
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void addArchitectView( final String apiKey, String filePath ) throws IOException {
|
||||
if ( this.architectView == null ) {
|
||||
this.architectView = new ArchitectView( (Activity)this.ctx.getContext() );
|
||||
|
||||
/* add content view and fake initial life-cycle */
|
||||
((Activity)this.ctx.getContext()).addContentView( this.architectView, new ViewGroup.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT ) );
|
||||
|
||||
/* fake life-cycle calls, because activity is already up and running */
|
||||
this.architectView.onCreate( getArchitectConfig( apiKey ) );
|
||||
this.architectView.onPostCreate();
|
||||
|
||||
/* register self as url listener to fwd these native calls to PhoneGap */
|
||||
this.architectView.registerUrlListener( WikitudePlugin.this );
|
||||
|
||||
/* load asset from local directory if prefix is used */
|
||||
if ( filePath.startsWith( WikitudePlugin.LOCAL_ASSETS_PATH_ROOT ) ) {
|
||||
filePath = filePath.substring( WikitudePlugin.LOCAL_ASSETS_PATH_ROOT.length() );
|
||||
}
|
||||
this.architectView.load( filePath );
|
||||
|
||||
/* also a fake-life-cycle call (the last one before it is really shown in UI */
|
||||
this.architectView.onResume();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# Hello World
|
||||
This sample dispalys Hello world in the camera
|
||||
The project is a stand-alone Sample PhoneGap Android Project using the basic Wikitude PhoneGap plugin to display "Hello World" in the camera-view. Solely the wikitudesdk.jar needs to be pasted to the project and [added to build path](https://www.google.com/webhp?sourceid=chrome-instant&ie=UTF-8&ion=1#hl=de&sclient=psy-ab&q=how+to+add+library+to+build+path+in+eclipse&oq=how+to+add+library+to+build+path+in+eclipse&gs_l=serp.3...4768.4984.1.5346.3.3.0.0.0.1.116.271.2j1.3.0...0.0...1c.1.Nk4mv2tTjuA&pbx=1&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.&fp=a6ff543f77bf189e&ion=1&biw=1236&bih=661)
|
||||
to get rid of the compile-time errors
|
||||
|
||||
####Prerequisites:
|
||||
* You need to [register as developer at Wikitude](http://developer.wikitude.com) and downloaded the SDK
|
||||
# SETUP
|
||||
|
||||
|
||||
* [Import it in Eclipse as Android-Project](https://www.google.com/webhp?sourceid=chrome-instant&ie=UTF-8&ion=1#hl=de&output=search&sclient=psy-ab&q=import%20android%20project%20into%20eclipse&oq=&gs_l=&pbx=1&fp=531bf0abdc9ea0e7&ion=1&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.&biw=1030&bih=550)
|
||||
* Copy `wikitudesdk.jar` from the Android [WikitudeSDK](http://developer.wikitude.com) to project's `libs`-folder
|
||||
* Run the application on your device / emulator
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="lib" path="libs/wikitudesdk.jar"/>
|
||||
<classpathentry kind="lib" path="libs/cordova-2.0.0.jar"/>
|
||||
<classpathentry kind="lib" path="libs/QCAR.jar"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>HelloImageRecognition</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.wikitude.phonegapsamplehelloimagerecognition"
|
||||
android:versionCode="1"
|
||||
android:versionName="0.9" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="8"/>
|
||||
|
||||
<supports-screens
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:smallScreens="true"
|
||||
android:resizeable="true"
|
||||
android:anyDensity="true" />
|
||||
|
||||
<!--
|
||||
|
||||
Please check: Wikitude's AR does not need these permissions, maybe you need them anyway
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
||||
|
||||
-->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_GPS" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
|
||||
<!-- AHAU: required hardware components -->
|
||||
<uses-feature android:name="android.hardware.camera" android:required="true" />
|
||||
|
||||
<!-- you need to have a way to find users location -->
|
||||
<uses-feature android:name="android.hardware.location" android:required="true" />
|
||||
|
||||
<!-- you need to have a accelerometer -->
|
||||
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
|
||||
|
||||
<!-- you need to have a compass -->
|
||||
<uses-feature android:name="android.hardware.sensor.compass" android:required="true" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name" android:debuggable="true">
|
||||
<activity
|
||||
android:name="com.wikitude.phonegap.PhonegapSampleActivity"
|
||||
android:label="@string/app_name" android:configChanges="orientation|keyboardHidden|screenSize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
After Width: | Height: | Size: 7.3 KiB |
@@ -0,0 +1,117 @@
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="target-densitydpi=device-dpi, width = 540, user-scalable = 0" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Simple IR World</title>
|
||||
|
||||
<style type="text/css">
|
||||
.info {
|
||||
color: #9F6000;
|
||||
background-color: #FEEFB3;
|
||||
margin: -8px 1%;
|
||||
padding: 10px;
|
||||
font-size: 14pt;
|
||||
border-radius: 0 0 10px 10px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Include the ARchitect library -->
|
||||
<script src="architect://architect.js"></script>
|
||||
|
||||
<!--
|
||||
<script src="../ade.js"></script>
|
||||
-->
|
||||
<script>
|
||||
|
||||
/* Global variables */
|
||||
var logoTracker = null;
|
||||
var overlay = null;
|
||||
var trackable2DObject = null;
|
||||
var errorOccured = false;
|
||||
var masterAnimationGroup = null;
|
||||
|
||||
function error() {
|
||||
errorOccured = true;
|
||||
document.getElementById("messageElement").innerHTML = "Unable to load image or tracker!";
|
||||
}
|
||||
|
||||
function createTracker(){
|
||||
var image = new AR.ImageResource("overlay.png", {onError: error});
|
||||
overlay = new AR.ImageDrawable(image, 1.0, {zOrder: 0});
|
||||
|
||||
// create tracker
|
||||
trackerDataSetPath = "WikitudeLogo.zip";
|
||||
logoTracker = new AR.Tracker(trackerDataSetPath, { onLoaded : trackerLoaded, onError: error });
|
||||
|
||||
|
||||
// relative position from teh arrows
|
||||
arrowXOffset = 2.0;
|
||||
arrowYOffset = 0.1;
|
||||
|
||||
var arrow1 = arrowWithDirectionality(-arrowXOffset, -arrowYOffset, -45);
|
||||
var arrow2 = arrowWithDirectionality(-arrowXOffset, arrowYOffset, 45);
|
||||
var arrow3 = arrowWithDirectionality(-arrowXOffset, -arrowYOffset, 135);
|
||||
var arrow4 = arrowWithDirectionality(-arrowXOffset, arrowYOffset, 225);
|
||||
|
||||
trackable2DObject = new AR.Trackable2DObject(logoTracker, "WikitudeLogo", { drawables: { cam: [overlay, arrow1[0], arrow2[0], arrow3[0], arrow4[0] ] }});
|
||||
|
||||
// we need to pack the arrow animations into a parallel animation group to play them synchronisly
|
||||
masterAnimationGroup = new AR.AnimationGroup(AR.CONST.ANIMATION_GROUP_TYPE.PARALLEL, [ arrow1[1], arrow2[1], arrow3[1], arrow4[1] ]);
|
||||
}
|
||||
|
||||
function trackerLoaded()
|
||||
{
|
||||
if (errorOccured) return;
|
||||
|
||||
document.getElementById("messageElement").style.display = "none";
|
||||
|
||||
// start with the parameter -1 indicates, that the group will play the animation in an infinite loop
|
||||
masterAnimationGroup.start(-1);
|
||||
}
|
||||
|
||||
function arrowWithDirectionality(offsetX, offsetY, roll)
|
||||
{
|
||||
|
||||
var animationOffset = 0.9; // distance in sdu's
|
||||
var animationTime = 700; // ms
|
||||
|
||||
// load the arrow image
|
||||
var arrowImage = new AR.ImageResource("DirectionArrow.png");
|
||||
|
||||
// attach the image resource to a drawable, so that its visible on the screen
|
||||
var arrowImageDrawable = new AR.ImageDrawable(arrowImage, 0.6, {offsetX: offsetX, offsetY: offsetY, zOrder: 1, roll: roll} );
|
||||
|
||||
|
||||
// we want to animte the arrow, to lets add two animation
|
||||
var arrowSpinAnimation = new AR.PropertyAnimation(arrowImageDrawable, "tilt", 0, 360, animationTime, {type: AR.CONST.EASING_CURVE_TYPE.LINEAR});
|
||||
|
||||
// the first one moves the arrow to the trackableObject
|
||||
var arrowAnimationMoveDown = new AR.PropertyAnimation(arrowImageDrawable, "offsetX", offsetX, offsetX+animationOffset, animationTime, {type: AR.CONST.EASING_CURVE_TYPE.EASE_IN_CUBIC});
|
||||
|
||||
// the second one moves it back to the original position
|
||||
var arrowAnimationMoveUp = new AR.PropertyAnimation(arrowImageDrawable, "offsetX", offsetX+animationOffset, offsetX, animationTime, {type: AR.CONST.EASING_CURVE_TYPE.EASE_OUT_CUBIC});
|
||||
|
||||
// because these two animations should be played one after another, we gonna pack them into a sequential animation group.
|
||||
var animationGroup = new AR.AnimationGroup(AR.CONST.ANIMATION_GROUP_TYPE.SEQUENTIAL, [arrowAnimationMoveDown, arrowAnimationMoveUp]);
|
||||
|
||||
var arrow = new Array(arrowImageDrawable, animationGroup);
|
||||
|
||||
return arrow;
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="info" id="messageElement">Loading ...</div>
|
||||
|
||||
<script>
|
||||
createTracker();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 427 KiB |
|
After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,100 @@
|
||||
html,
|
||||
body {
|
||||
height:100%;
|
||||
font-size:12px;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
html {
|
||||
display:table;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color:#A7A7A7;
|
||||
background-image:linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
|
||||
background-image:-webkit-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
|
||||
background-image:-ms-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
|
||||
background-image:-webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
left bottom,
|
||||
color-stop(0, #A7A7A7),
|
||||
color-stop(0.51, #E4E4E4)
|
||||
);
|
||||
display:table-cell;
|
||||
font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif;
|
||||
text-transform:uppercase;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
.app {
|
||||
background-image:url(../img/cordova.png);
|
||||
background-repeat:no-repeat;
|
||||
margin:0px auto;
|
||||
width:275px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size:2em;
|
||||
font-weight:300;
|
||||
margin:0px;
|
||||
overflow:visible;
|
||||
padding:0px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.status {
|
||||
background-color:#333333;
|
||||
border-radius:4px;
|
||||
-webkit-border-radius:4px;
|
||||
color:#FFFFFF;
|
||||
font-size:1em;
|
||||
margin:0px auto;
|
||||
padding:2px 10px;
|
||||
text-align:center;
|
||||
width:100%;
|
||||
max-width:175px;
|
||||
}
|
||||
|
||||
.status.complete {
|
||||
background-color:#4B946A;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display:none;
|
||||
}
|
||||
|
||||
@keyframes fade {
|
||||
from { opacity: 1.0; }
|
||||
50% { opacity: 0.4; }
|
||||
to { opacity: 1.0; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes fade {
|
||||
from { opacity: 1.0; }
|
||||
50% { opacity: 0.4; }
|
||||
to { opacity: 1.0; }
|
||||
}
|
||||
|
||||
.blink {
|
||||
animation:fade 3000ms infinite;
|
||||
-webkit-animation:fade 3000ms infinite;
|
||||
}
|
||||
|
||||
/* portrait */
|
||||
/* @media screen and (max-aspect-ratio: 1/1) */
|
||||
.app {
|
||||
background-position:center top;
|
||||
height:100px; /* adds enough room for text */
|
||||
padding:180px 0px 0px 0px; /* background height - shadow offset */
|
||||
}
|
||||
|
||||
/* lanscape (when wide enough) */
|
||||
@media screen and (min-aspect-ratio: 1/1) and (min-width:445px) {
|
||||
.app {
|
||||
background-position:left center;
|
||||
height:140px; /* height + padding = background image size */
|
||||
padding-left:170px; /* background width */
|
||||
padding-top:60px; /* center the text */
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta name="viewport" content="width=320; user-scalable=no" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
|
||||
<title>PhoneGap and Wikitude</title>
|
||||
|
||||
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title">
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="cordova-2.0.0.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="js/WikitudePlugin.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="css/index.css" />
|
||||
<title>Hello Cordova</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<h1>Apache Cordova™</h1>
|
||||
<div id="deviceready">
|
||||
<p class="status pending blink">Connecting to Device</p>
|
||||
<p class="status complete blink hide">Device is Ready</p>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="cordova-2.0.0.js"></script>
|
||||
<script type="text/javascript" src="js/index.js"></script>
|
||||
<script type="text/javascript" src="js/WikitudePlugin.js"></script>
|
||||
<script type="text/javascript">
|
||||
app.initialize();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,383 @@
|
||||
var WikitudePlugin = {
|
||||
|
||||
/**
|
||||
*
|
||||
* This is the SDK Key, provided to you after you purchased the Wikitude SDK from http://www.wikitude.com/developer/sdk
|
||||
* If you're having a trial version, leave this string empty
|
||||
*
|
||||
*/
|
||||
mySDKKey : "ENTER-YOUR-KEY-HERE",
|
||||
|
||||
/** true if architectview is open */
|
||||
isOpened : false,
|
||||
|
||||
/**
|
||||
*
|
||||
* called when user pressed back-button on Android device
|
||||
*
|
||||
*/
|
||||
backButtonCallback : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* Change the value of this variable to modify the location update rate
|
||||
*
|
||||
*/
|
||||
locationUpdateRate : 3000,
|
||||
|
||||
/**
|
||||
*
|
||||
* This variable represents if the current device is capable of running the Wikitude SDK
|
||||
*
|
||||
*/
|
||||
isDeviceSupported : false,
|
||||
|
||||
/**
|
||||
*
|
||||
* This watchID is used to shedule location updates
|
||||
*
|
||||
*/
|
||||
watchID : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* Callbacks to get device information if ARchitect Worlds can be launched
|
||||
*
|
||||
*/
|
||||
onDeviceSupportedCallback : null,
|
||||
onDeviceNotSupportedCallback : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* Callbacks to get notified if the ARchitect World finished launching or if something went wrong during the World launch
|
||||
*
|
||||
*/
|
||||
onARchitectWorldLaunchedCallback : null,
|
||||
onARchitectWorldFailedLaunchingCallback : null,
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if PhoneGap reports that it has finished loading successfully.
|
||||
*
|
||||
*/
|
||||
isDeviceSupported: function(successCallback, errorCallback)
|
||||
{
|
||||
|
||||
WikitudePlugin.onDeviceSupportedCallback = successCallback;
|
||||
WikitudePlugin.onDeviceNotSupportedCallback = errorCallback;
|
||||
|
||||
|
||||
// PhoneGap is running, so the first thing we do is to check if the current device is capable of running the Wikitude Plugin
|
||||
cordova.exec(WikitudePlugin.deviceIsARchitectReady, WikitudePlugin.deviceIsNotARchitectReady, "WikitudePlugin", "isDeviceSupported", [""]);
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Declare what should happen when user pressed back-button while architect-view is opened.
|
||||
* If not declared/called or null: ARchitect-View is closed
|
||||
*
|
||||
*/
|
||||
onPressedBackButton : function(callback)
|
||||
{
|
||||
WikitudePlugin.backButtonCallback = callback;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if the Wikitude Plugin reports that the device is able to start the Wikitude SDK
|
||||
*
|
||||
*/
|
||||
deviceIsARchitectReady : function()
|
||||
{
|
||||
// We keep track of the device status
|
||||
WikitudePlugin.isDeviceSupported = true;
|
||||
|
||||
|
||||
if(WikitudePlugin.onDeviceSupportedCallback)
|
||||
{
|
||||
WikitudePlugin.onDeviceSupportedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called if the Wikitude Plugin reports that the device is not able of starting the Wikitude SDK.
|
||||
*
|
||||
*/
|
||||
deviceIsNotARchitectReady : function()
|
||||
{
|
||||
WikitudePlugin.isDeviceSupported = false;
|
||||
|
||||
// In this case we notify the user that his device is not supported by the Wikitude SDK
|
||||
if(WikitudePlugin.onDeviceNotSupportedCallback)
|
||||
{
|
||||
WikitudePlugin.onDeviceNotSupportedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* =============================================================================================================================
|
||||
*
|
||||
* PUBLIC API
|
||||
*
|
||||
* =============================================================================================================================
|
||||
*/
|
||||
|
||||
/* Managing ARchitect world loading */
|
||||
|
||||
/**
|
||||
*
|
||||
* Call this function if you want to load an ARchitect World
|
||||
*
|
||||
* @param {String} worldPath The path to an ARchitect world ether on the device or on e.g. your dropbox
|
||||
*
|
||||
*/
|
||||
loadARchitectWorld : function(worldPath)
|
||||
{
|
||||
|
||||
// before we actually call load, we check again if the device is able to open the world
|
||||
if(WikitudePlugin.isDeviceSupported)
|
||||
{
|
||||
|
||||
// the 'open' function of the Wikitude Plugin requires a option dictionary with two keys:
|
||||
// @param {Object} options (required)
|
||||
// @param {String} options.sdkKey License key for the Wikitude SDK
|
||||
// @param {String} options.filePath The path to a local ARchitect world or to a ARchitect world on a server or your dropbox
|
||||
|
||||
cordova.exec(WikitudePlugin.worldLaunched, WikitudePlugin.worldFailedLaunching, "WikitudePlugin", "open", [{ sdkKey: WikitudePlugin.mySDKKey, filePath: worldPath}]);
|
||||
|
||||
|
||||
// We add an event listener on the resume and pause event of the application lifecycle
|
||||
document.addEventListener("resume", WikitudePlugin.onResume, false);
|
||||
document.addEventListener("pause", WikitudePlugin.onPause, false);
|
||||
|
||||
WikitudePlugin.isOpened = true;
|
||||
document.addEventListener("backbutton", WikitudePlugin.onBackButton, false);
|
||||
|
||||
// After we started loading the world, we start location updates
|
||||
WikitudePlugin.startLocationUpdates();
|
||||
|
||||
}else
|
||||
{
|
||||
// if the device is not able to start the Wikitude SDK, we notify the user again
|
||||
WikitudePlugin.deviceNotARchitectReady();
|
||||
}
|
||||
},
|
||||
|
||||
/* Managing the Wikitude SDK Lifecycle */
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to stop the Wikitude SDK and to remove the ARchitectView from the screen
|
||||
*
|
||||
*/
|
||||
close : function()
|
||||
{
|
||||
document.removeEventListener("pause", WikitudePlugin.onPause, false);
|
||||
document.removeEventListener("resume", WikitudePlugin.onResume, false);
|
||||
|
||||
WikitudePlugin.stopLocationUpdates();
|
||||
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "close", [""]);
|
||||
WikitudePlugin.isOpened = false;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to only hide the Wikitude SDK. All location and rendering updates are still active
|
||||
*
|
||||
*/
|
||||
hide : function()
|
||||
{
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "hide", [""]);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to show the Wikitude SDK if it was hidden before
|
||||
*
|
||||
*/
|
||||
show : function()
|
||||
{
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "show", [""]);
|
||||
},
|
||||
|
||||
/* Interacting with the Wikitude SDK */
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to call javascript which will be executed in the context of your ARchitect World
|
||||
*
|
||||
*
|
||||
* @param js The JavaScript that gets evaluated in context of the ARchitect World
|
||||
*
|
||||
*/
|
||||
callJavaScript : function(js)
|
||||
{
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "callJavascript", [js]);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to set a callback which will be invoked when the ARchitect World calls for example
|
||||
* document.location = "architectsdk://opendetailpage?id=9";
|
||||
*
|
||||
*
|
||||
* @param onUrlInvokeCallback A function which gets called when the ARchitect World invokes a call to "document.location = architectsdk://"
|
||||
*/
|
||||
setOnUrlInvokeCallback : function(onUrlInvokeCallback)
|
||||
{
|
||||
cordova.exec(onUrlInvokeCallback, WikitudePlugin.onWikitudeError, "WikitudePlugin", "onUrlInvoke", [""]);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* =============================================================================================================================
|
||||
*
|
||||
* Callbacks of public functions
|
||||
*
|
||||
* =============================================================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this callback to get notified if the world loaded successfully
|
||||
*
|
||||
*/
|
||||
worldLaunched : function()
|
||||
{
|
||||
if(WikitudePlugin.onARchitectWorldLaunchedCallback)
|
||||
{
|
||||
WikitudePlugin.onARchitectWorldLaunchedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this callback to get notified if the Wikitude SDK wasn't able to load the ARchitect World
|
||||
*
|
||||
*/
|
||||
worldFailedLaunching : function(err)
|
||||
{
|
||||
if(WikitudePlugin.onARchitectWorldFailedLaunchingCallback)
|
||||
{
|
||||
WikitudePlugin.onARchitectWorldFailedLaunchingCallback(err);
|
||||
}
|
||||
},
|
||||
|
||||
/* Lifecycle updates */
|
||||
|
||||
/**
|
||||
*
|
||||
* This function actually starts the PhoneGap location updates
|
||||
*
|
||||
*/
|
||||
startLocationUpdates : function()
|
||||
{
|
||||
|
||||
WikitudePlugin.watchID = navigator.geolocation.watchPosition(WikitudePlugin.onReceivedLocation, WikitudePlugin.onWikitudeError, { frequency: WikitudePlugin.locationUpdateRate });
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This callback gets called everytime the location did update
|
||||
*
|
||||
*/
|
||||
onReceivedLocation : function(position)
|
||||
{
|
||||
|
||||
// Every time that PhoneGap did received a location update, we pass the location into the Wikitude SDK
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "setLocation", [{ lat: position.coords.latitude, lon: position.coords.longitude, alt: position.coords.altitude, acc: position.coords.accuracy}]);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Use this function to stop location updates
|
||||
*
|
||||
*/
|
||||
stopLocationUpdates : function()
|
||||
{
|
||||
|
||||
// We clear the location update watch which was responsible for updating the location in a specific time interval
|
||||
navigator.geolocation.clearWatch(WikitudePlugin.watchID);
|
||||
WikitudePlugin.watchID = null;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application did become active.
|
||||
*
|
||||
*/
|
||||
onResume : function()
|
||||
{
|
||||
|
||||
// Call the Wikitude SDK that the application did become active again
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "onResume", [""]);
|
||||
|
||||
// And start continuing updating the user location
|
||||
WikitudePlugin.startLocationUpdates();
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
onPause : function()
|
||||
{
|
||||
|
||||
// Call the Wikitude SDK that the application did resign active
|
||||
cordova.exec(WikitudePlugin.onWikitudeOK, WikitudePlugin.onWikitudeError, "WikitudePlugin", "onPause", [""]);
|
||||
|
||||
// And stop all ongoing location updates
|
||||
WikitudePlugin.stopLocationUpdates();
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Android specific!
|
||||
* This function gets called if the user presses the back button.
|
||||
* You may define your own implementation by using WikitudePlugin.onPressedBackButton(method)
|
||||
*
|
||||
*/
|
||||
onBackButton : function()
|
||||
{
|
||||
if (WikitudePlugin.isOpened) {
|
||||
if (WikitudePlugin.backButtonCallback==null) {
|
||||
WikitudePlugin.close();
|
||||
document.removeEventListener("backbutton", WikitudePlugin.onBackButton, false);
|
||||
} else {
|
||||
WikitudePlugin.backButtonCallback();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
onWikitudeOK : function()
|
||||
{
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
onWikitudeError : function()
|
||||
{
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* This function gets called every time the application is about to become inactive
|
||||
*
|
||||
*/
|
||||
report: function(id)
|
||||
{
|
||||
console.log("app report: " + id);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
var app = {
|
||||
initialize: function() {
|
||||
this.bind();
|
||||
},
|
||||
bind: function() {
|
||||
document.addEventListener('deviceready', this.deviceready, false);
|
||||
},
|
||||
|
||||
// A callback which gets called if the device is able to launch ARchitect Worlds
|
||||
onDeviceSupportedCallback : function()
|
||||
{
|
||||
// The device is able to launch ARchitect World, so lets do so :)
|
||||
WikitudePlugin.loadARchitectWorld("assets/world/SimpleImageRecognition/SimpleIRWorld.html");
|
||||
},
|
||||
|
||||
// A callback which gets called if the device is not able to start ARchitect Worlds
|
||||
onDeviceNotSupportedCallback : function()
|
||||
{
|
||||
app.report("Unable to launch ARchitect Worlds on this device");
|
||||
},
|
||||
|
||||
deviceready: function() {
|
||||
// note that this is an event handler so the scope is that of the event
|
||||
// so we need to call app.report(), and not this.report()
|
||||
app.report('deviceready');
|
||||
|
||||
// check if the current device is able to launch ARchitect Worlds
|
||||
WikitudePlugin.isDeviceSupported(app.onDeviceSupportedCallback, app.onDeviceNotSupportedCallback);
|
||||
},
|
||||
report: function(id) {
|
||||
console.log("report:" + id);
|
||||
// hide the .pending <p> and show the .complete <p>
|
||||
document.querySelector('#' + id + ' .pending').className += ' hide';
|
||||
var completeElem = document.querySelector('#' + id + ' .complete');
|
||||
completeElem.className = completeElem.className.split('hide').join('');
|
||||
}
|
||||
};
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 7.5 KiB |