Richard Haven

Either a REST interface or some documentation for the AS3 library?

9 posts in this topic

I apologize if I have simply missed the documentation for the ActionScript library (SWC), but I have no idea how to use it. It does not seem to have either examples or class descriptions, and the source code is unlike any standard Flex or ActionScript style that I have seen.

Please point me in the direction of some specific source code examples or point me in the direction of a REST interface: either one is fine.

Thank you for your attention

-R

1 person likes this

Share this post


Link to post

So... I'm VERY frustrated with the lack of documentation or examples for the actionscript sdk. Here's the crux of the code I have so far:


protected function evernoteLoginButton_clickHandler(event:MouseEvent):void
{
//Try to authenticate the user
var usrAgent:String = "my-app/1.0";
var usrStoreUrlRequest:URLRequest = new URLRequest("https://sandbox.evernote.com/");
var usrStoreTransport:THttpClient = new THttpClient(usrStoreUrlRequest);
var usrStoreProtocol:TBinaryProtocol = new TBinaryProtocol(usrStoreTransport);
var usrStoreClient:UserStore = new UserStore(usrStoreProtocol, usrStoreProtocol);

//Version Check
usrStoreClient.checkVersion(usrAgent,
com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR,
com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR,
handleError,
handleSuccess);
}

private function handleError(err:TTransportError):void
{
trace(TAG + ".handleError:obj = " + err.getStackTrace().toString());
}

private function handleSuccess(obj:Object=null):void
{
if(obj){
trace(TAG + ".handleSuccess:obj = " + obj.toString());
}else{
trace(TAG + ".handleSuccess:obj = null");
}
}

When this code gets executed, I get the following console output:

RESPONSE_BUFFER BUFFER length: 5935, [a][a][a][a]...whole bunch more ...[6c][3e][a]

READ BUFFER length: 4, [a][a][a][a]

FAILED-RESPONSE-REQUEST BUFFER length: 86, [80][1][0][1]...whole bunch more ...[0][13][0]

FAILED-RESPONSE BUFFER length: 5935, [a][a][a]...whole bunch more ...[68][74][6d][6c][3e][a]

EvernoteLoginViewLogic.handleError:obj = Error: No more data available.

at org.apache.thrift.transport::THttpClient/read()[/users/bhall/Documents/Work/Clients/Current/Evernote/dev/gen/org/apache/thrift/transport/THttpClient.as:83]

at org.apache.thrift.transport::TTransport/readAll()[/users/bhall/Documents/Work/Clients/Current/Evernote/dev/gen/org/apache/thrift/transport/TTransport.as:87]

at org.apache.thrift.protocol::TBinaryProtocol/readAll()[/users/bhall/Documents/Work/Clients/Current/Evernote/dev/gen/org/apache/thrift/protocol/TBinaryProtocol.as:296]

at org.apache.thrift.protocol::TBinaryProtocol/readStringBody()[/users/bhall/Documents/Work/Clients/Current/Evernote/dev/gen/org/apache/thrift/protocol/TBinaryProtocol.as:280]

at org.apache.thrift.protocol::TBinaryProtocol/readMessageBegin()[/users/bhall/Documents/Work/Clients/Current/Evernote/dev/gen/org/apache/thrift/protocol/TBinaryProtocol.as:202]

at Function/<anonymous>()[/users/bhall/Documents/Work/Clients/Current/Evernote/dev/gen/com/evernote/edam/userstore/UserStore.as:64]

at Function/<anonymous>()[/users/bhall/Documents/Work/Clients/Current/Evernote/dev/gen/org/apache/thrift/transport/THttpClient.as:100]

at flash.events::EventDispatcher/dispatchEventFunction()

at flash.events::EventDispatcher/dispatchEvent()

at flash.net::URLLoader/onComplete()

What am I doing wrong?

Thanks!

Share this post


Link to post

I am attempting to use StageWebView in AS3 to implement oAuth as described here.

However, since I am running an air app (mobile and desktop), what can I use as the callback parameter?

I have tried "oob" and other variants (how I have used OAuth from mobile for Google for example) but that doesn't seem to work.

I am able to get the temporary credentials response token and then the resource owner auth screen, but then simply receive a "load error" when the user clicks "Allow" (or Decline) which I am assuming is due to my callback being invalid?

Any suggestions?

Share this post


Link to post

Here's the code I used to connect to Evernote and to get fully authenticated. I used the StageWebViewUIComponent that Sonke Rohde posted at http://soenkerohde.com/2010/11/air-mobile-stagewebview-uicomponent/. The rest of my code is as follows:


package
{
import com.evernote.edam.limits.Constants;
import com.evernote.edam.type.User;
import com.evernote.edam.userstore.AuthenticationResult;
import com.evernote.edam.userstore.Constants;
import com.evernote.edam.userstore.UserStore;
import com.evernote.edam.userstore.UserStoreProcessor;

import flash.desktop.NativeApplication;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.events.HTTPStatusEvent;
import flash.events.IEventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.LocationChangeEvent;
import flash.events.MouseEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.events.TextEvent;
import flash.geom.Rectangle;
import flash.media.StageWebView;
import flash.net.URLLoader;
import flash.net.URLRequest;

import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.protocol.TProtocolUtil;
import org.apache.thrift.transport.THttpClient;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportError;

import spark.components.Button;
import spark.components.Group;
import spark.components.TextArea;
import spark.components.TextInput;
import spark.components.View;



public class EvernoteLoginViewLogic extends View
{
private const TAG:String = "EvernoteLoginViewLogic";
[Bindable] public var evernoteUsernameTextBox:TextInput;
[Bindable] public var evernotePasswordTextBox:TextInput;
[Bindable] public var evernoteLoginButton:Button;
[Bindable] public var accessToken:TextArea;
[Bindable] public var tokenType:TextInput;
[Bindable] public var expiresIn:TextInput;
[Bindable] public var viewPort:Group;
[Bindable] public var stageWebView:StageWebViewUIComponent;
[Bindable] public var okButton:Button;

private var usrStoreClient:UserStore;
private var user:User;
private var tempToken:String;
private var authToken:String;
private var userStoreUrl:String;
private var loader:URLLoader;


public function EvernoteLoginViewLogic()
{
super();
}

protected function getTempTokenButton_clickHandler(event:MouseEvent):void
{
//Try to get access to the UserStore
var usrAgent:String = "My-App/1.0";
var usrStoreUrlRequest:URLRequest = new URLRequest(EvernoteImplementationConstants.EvernoteStoreUrl);

var usrStoreTransport:THttpClient = new THttpClient(usrStoreUrlRequest);
var usrStoreProtocol:TBinaryProtocol = new TBinaryProtocol(usrStoreTransport);
usrStoreClient = new UserStore(usrStoreProtocol, usrStoreProtocol);

//DO a quick Version Check to make sure we are still compliant!
usrStoreClient.checkVersion(usrAgent,
com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR,
com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR,
handleError,
handleSuccess);
}

private function handleError(err:TTransportError):void
{
trace(TAG + ".handleError:obj = " + err.getStackTrace().toString());
}

private function handleSuccess(obj:Object=null):void
{
if(obj){
trace(TAG + ".handleSuccess:obj = " + obj.toString());
//The version is good, so now we can get the OAuth authorization token
getOAuthToken();
}else{
trace(TAG + ".handleSuccess:obj = null");
}
}

private function getOAuthToken():void
{
/**
*
* So... there is blessed little info on how to make this happen, except the following:
*
* The order of needed operations to get the application token is:
* 1) User requests to login to Evernote (in my app) (is this a given in our app???)
* 2) My App Requests temporary credentials from Evernote (Request Token)
* 3) Evernote Sends temporary credentials to my app (Request Token)
* 4) My App loads the Evernote login Page for the user to use
* 5) <already done>
* 6) Evernote returns the login the authorization pages
* 7) User grants access to your application via the webpage
* 8) Evernote redirects the webpage to the callback URL
* 9) My app recognizes the callback URL and closes the login window
* 10) My App requests an exchange of temporary credentials for application credentials from Evernote
* 11) Evernote grants the application token credentials to my app
* 12) We are off and running!
*
* It turns out that the best way to accomplish this is using a combination of URLLoader and the
* StageWebView. I use the URLLoader for interracting with the Evernote servers when I don't need
* the user to interact (i.e login or grant permissions). I use the StageWebView when user interaction
* is needed.
**/
// currentState = "WebsiteState";

// Build up the URL
var now:Date = new Date();

var oAuthUrl:String = EvernoteImplementationConstants.EvernoteOAuthTempCredentialRequestUrl
+ "?oauth_consumer_key="
+ EvernoteImplementationConstants.MyConsumerKey
+ "&oauth_signature="
+ EvernoteImplementationConstants.MyConsumerSecret
+ "&oauth_signature_method="
+ EvernoteImplementationConstants.EvernoteOAuthSignatureMethod
+ "&oauth_timestamp="
+ now.getTime()
+ "&oauth_nonce="
+ Math.random()
+ "&oauth_callback="
+ EvernoteImplementationConstants.EvernoteOAuthResourceOwnerAuthUrl;

// set up the URLLoader
loader = new URLLoader();

// set up the listeners for the URLLoader
loader.addEventListener(Event.COMPLETE, getTempTokenCompleteHandler);
loader.addEventListener(Event.OPEN, openHandler);
loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);

// set up the URL that we want to go to
var urlRequest:URLRequest = new URLRequest(oAuthUrl);

try {
// Let's try loading the URL using the loader
loader.load(urlRequest);
} catch (error:Error) {
trace(TAG + ".getOAuthToken: Unable to load requested document.");
}
}

private function getTempTokenCompleteHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
trace(TAG + ":getTempTokenCompleteHandler: " + loader.data);

//We should have a valid token
var rawData:String = loader.data;


//If we have a temp token
if(rawData.search("oauth_callback_confirmed=true") >= 0){
//We have received the temp token
//Let's pull out the token data

var tokenStart:Number = rawData.search("aaronpatty.");
var tokenEnd:Number = rawData.search("&oauth_token_secret");
tempToken = rawData.substring(tokenStart, tokenEnd);

currentState = "ResultsState";
accessToken.text = tempToken;
tokenType.text = "Temporary Authorization Token";
expiresIn.text = "???";

trace(TAG + ".completeHandler: TempToken=" + tempToken);

// Now we wait for the user to click the OK button!

}else if(rawData.search("&edam_noteStoreUrl") >= 0){

// We have successfully received access to the user's account! YEAH!
// Let's pull out the token and other data

var tokenStart:Number = "oauth_token=".length;
var tokenEnd:Number = rawData.search("&oauth_token_secret=");
authToken = rawData.substring(tokenStart, tokenEnd);
trace(TAG + "getTempTokenCompleteHandler: AuthToken=" + authToken);

var userNoteStoreUrlStart:Number = rawData.search("&edam_noteStoreUrl=") + "&edam_noteStoreUrl=".length;
userStoreUrl = rawData.substring(userNoteStoreUrlStart); // Grab the rest of the string including the edam_userId
trace(TAG + "getTempTokenCompleteHandler: UserStoreUrl=" + userStoreUrl);
stageWebView.hide();
stageWebView.removeEventListener(Event.COMPLETE, userAccessCompleteHandler);
stageWebView.removeEventListener(ErrorEvent.ERROR, userAccessErrorHandler);
stageWebView.removeEventListener(LocationChangeEvent.LOCATION_CHANGING, userAccessLocationChangingHandler);
stageWebView.removeEventListener(LocationChangeEvent.LOCATION_CHANGE, userAccessLocationChangeHandler);
stageWebView.dispose();

currentState = "ResultsState";
accessToken.text = authToken;
tokenType.text = "UserStore Authorization Token";
expiresIn.text = "365 Days!";

// We are done! We can now access the UserStore all we want!
}
}

private function openHandler(event:Event):void {
trace(TAG + ":openHandler: " + event);
}

private function progressHandler(event:ProgressEvent):void {
trace(TAG + ":progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
}

private function securityErrorHandler(event:SecurityErrorEvent):void {
trace(TAG + ":securityErrorHandler: " + event);
}

private function httpStatusHandler(event:HTTPStatusEvent):void {
trace(TAG + ":httpStatusHandler: " + event);
}

private function ioErrorHandler(event:IOErrorEvent):void {
trace(TAG + ":ioErrorHandler: " + event);
}

protected function okButton_clickHandler(event:MouseEvent):void
{
if(authToken){
NativeApplication.nativeApplication.exit();
}
// Switch to the WebsiteState
currentState = "WebsiteState";

}

protected function userLoginButton_clickHandler(event:MouseEvent):void
{
// We have the temp token... now it's time to have the user
// give us authorization to use their account in our app!


// Build up the URL
var now:Date = new Date();
var oAuthUrl:String = EvernoteImplementationConstants.EvernoteOAuthResourceOwnerAuthUrl
+ "?oauth_token="
+ tempToken;

// Add the listeners to the StageWebView
stageWebView.addEventListener(Event.COMPLETE, userAccessCompleteHandler);
stageWebView.addEventListener(ErrorEvent.ERROR, userAccessErrorHandler);
stageWebView.addEventListener(LocationChangeEvent.LOCATION_CHANGING, userAccessLocationChangingHandler);
stageWebView.addEventListener(LocationChangeEvent.LOCATION_CHANGE, userAccessLocationChangeHandler);

// Go to the URL
stageWebView.url = oAuthUrl;
okButton.label = "Exit";
}

protected function userAccessCompleteHandler(event:Event):void
{
trace(TAG + ".userAccessCompleteHandler: " + event.toString());
}

protected function userAccessLocationChangingHandler(event:LocationChangeEvent):void
{
trace(TAG + ".userAccessLocationChangingHandler: " + event.toString());
}

protected function userAccessLocationChangeHandler(event:LocationChangeEvent ):void
{
trace(TAG + ".userAccessLocationChangeHandler: " + event.toString());
// Watch for the oauth_verifier


var verifierStart:Number = event.location.search("&oauth_verifier=")+ "&oauth_verifier=".length;
if(verifierStart > 0){
// We have been allowed access!
// Now get the verifier string
var verifier:String = event.location.substring(verifierStart);

// Now that we have the verifier, we can request the official Authorization Token
// Build up the URL
var now:Date = new Date();

var oAuthUrl:String = EvernoteImplementationConstants.EvernoteOAuthTempCredentialRequestUrl
+ "?oauth_consumer_key="
+ EvernoteImplementationConstants.MyConsumerKey
+ "&oauth_signature="
+ EvernoteImplementationConstants.MyConsumerSecret
+ "&oauth_signature_method="
+ EvernoteImplementationConstants.EvernoteOAuthSignatureMethod
+ "&oauth_timestamp="
+ now.getTime()
+ "&oauth_nonce="
+ Math.random()
+ "&oauth_token="
+ tempToken
+ "&oauth_verifier="
+ verifier;

stageWebView.enabled = false;

// set up the URL that we want to go to
var urlRequest:URLRequest = new URLRequest(oAuthUrl);

try {
// Let's try loading the URL using the loader
loader.load(urlRequest);
} catch (error:Error) {
trace(TAG + ".getOAuthToken: Unable to load requested document.");
}
}
}

protected function userAccessErrorHandler(event:Event):void
{
trace(TAG + ".userAccessErrorHandler: " + event.toString());
}
}
}

And, here's the code for the user interface (view):


<?xml version="1.0" encoding="utf-8"?>
<local:EvernoteLoginViewLogic xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:local="*"
xmlns:s="library://ns.adobe.com/flex/spark"
currentState="LoginState" title="EvernoteLoginView">

<fx:Script>
</fx:Script>

<local:states>
<s:State name="LoginState"/>
<s:State name="ResultsState"/>
<s:State name="WebsiteState"/>
</local:states>
<fx:Declarations>
<!-- DO NOT PLACE ANYTHING HERE!
All scripting should be done in the EvernoteLoginViewLogic.as class! -->
</fx:Declarations>

<!--<s:Group id="viewPort" width="100%" height="100%"
left.ResultsState="0" top.ResultsState="0">
<s:Rect width="100%" height="100%"
left.LoginState="0" top.LoginState="0">
<s:fill>
<s:SolidColor color="#cecece" />
</s:fill>
</s:Rect>
</s:Group>-->

<s:Label includeIn="LoginState" fontSize="50" horizontalCenter="0" text="Evernote Login"
verticalCenter="-300"/>
<s:Button id="getTempTokenButton" includeIn="LoginState" label="Get Temp Token"
click="getTempTokenButton_clickHandler(event)" fontSize="36" horizontalCenter="0"
verticalCenter="0"/>
<s:Label includeIn="ResultsState" top="10" fontWeight="bold" horizontalCenter="0"
text="Token Response"/>
<s:VGroup includeIn="ResultsState" top="40" horizontalCenter="0">
<s:Label x="10" text="Access Token"/>
<s:Scroller x="10" y="41" width="95%" height="256">
<s:VGroup width="100%" height="100%">
<s:TextArea id="accessToken" width="100%" height="100%"/>
</s:VGroup>
</s:Scroller>
<s:Label x="10" text="Token Type"/>
<s:TextInput id="tokenType" y="229" width="95%" horizontalCenter="0" />
<s:Label x="10" text="Expires In"/>
<s:TextInput id="expiresIn" y="323" width="95%" horizontalCenter="0" />
<s:Group width="100%">
<s:Button id="okButton" includeIn="ResultsState" label="OK"
click="okButton_clickHandler(event)" horizontalCenter="0"
verticalCenter="0"/>
</s:Group>
</s:VGroup>
<local:StageWebViewUIComponent id="stageWebView" includeIn="WebsiteState" top="100" width="100%"
height="500" horizontalCenter="0"/>
<s:Button id="userLoginButton" includeIn="WebsiteState" top="10"
label="Have User Login to Evernote" click="userLoginButton_clickHandler(event)"
horizontalCenter="0"/>

</local:EvernoteLoginViewLogic>

It's not a pretty UI, nor has the code been cleaned up at all, but it works.

Good luck!

Share this post


Link to post

Update: I have gotten the AS3 api to compile (one has to remove the naive directory names in the src/)

Now, off to access using the developers token and then the OAuth

Thanks for everyone's contributions

Share this post


Link to post

Here's the code I used to connect to Evernote and to get fully authenticated...

Where is EvernoteImplementationConstants ?

Share this post


Link to post

So what is the status here? I tried to use the as3 library but I failed. there is still no documentation and the only example I found is the one from Aron P.

 

It works so far but I am not sure if the AS Library will be supported in the future

 

Here are the missing constants:

 

 

    public const EvernoteStoreUrl:String = "https://sandbox.evernote.com/edam/user";
    public const EvernoteOAuthTempCredentialRequestUrl:String = "https://sandbox.evernote.com/oauth";
    public const MyConsumerKey:String = "xxxxxx";
    public const MyConsumerSecret:String = "xxxxxx";
    public const EvernoteOAuthSignatureMethod:String = "PLAINTEXT";
    public const EvernoteOAuthResourceOwnerAuthUrl:String = "https://sandbox.evernote.com/OAuth.action";

Share this post


Link to post