Flex Mobile AIR Native Extension errors - actionscript-3

I'm currently working on creating an Android ANE for native alert popups. I'm now at the point where I think my both my Java and AS3 code is good to go but I'm getting an error when I try to use it.
Main Thread (Suspended: TypeError: Error #1009: Cannot access a property or method of a null object reference.)
My problem is I'm really not sure where this error is coming from. My thinking is that I'm not building the ANE file correctly or something is wrong in my extension.xml file but I'm really not too sure.
I'm going to try to provide as much information as I can about how this project is set up. Right now I'm trying to use this ANE in a small, testing application.
First, the folder setup:
ANEextensions-
Alert_Java (holding my Java project)
(Android/Java created assets. Not sure if these are important or now. If so I will list them)
src
com
fa
ne
android
AlertContext.java
AlertExtension.java
ShowAlert.java
Alert_AS
bin
AlertAndroidAS.swc
src
Alert.as
extension.xml
I'm not going to bother posting my java code as I think it's correct. but if anyone who is willing to invest some time in helping me with this issue wants to take a look please let me know.
This is my extensions.xml file
<extension xmlns="http://ns.adobe.com/air/extension/2.5">
<id>com.fa.alerts</id>
<versionNumber>1.0</versionNumber>
<platforms>
<platform name="Android-ARM">
<applicationDeployment>
<nativeLibrary>AndroidAlert.jar</nativeLibrary>
<initializer>com.fa.ne.android.AlertExtension</initializer>
<finalizer>com.fa.ne.android.AlertExtension</finalizer>
</applicationDeployment>
</platform>
</platforms>
</extension>
And this is my Alert.as file:
package {
import flash.events.EventDispatcher;
import flash.external.ExtensionContext;
public class Alert extends EventDispatcher{
public static var extContext:ExtensionContext = null
public function Alert(){
super();
extContext = ExtensionContext.createExtensionContext("com.fa.alerts", null);
}
public static function androidAlert(aTitle:String, aMsg:String, aNeg:String = "Cancel", aPos:String = "Ok"):void{
extContext.call("showAlert", aTitle, aMsg, aNeg, aPos);
}
}
}
And this is my stub app I'm using to test
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">
<fx:Script>
<![CDATA[
protected function spawnAne(event:MouseEvent):void{
var a:Alert = new Alert();
Alert.androidAlert("test","testing");
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button click="spawnAne(event)" />
</s:View>
Now clicking on that button is what causes the error.
I don't have any kind of swc or link between my testing app and the AS3 Alert_AS project. I'm using Flash Builder 4.6 to import the ANE file using the IDE tools.
To build my ANE I'm using a lightly modified bash script from this post: http://gotoandlearn.com/play.php?id=149 by Lee Brimelow
# path to YOUR Android SDK
export AIR_ANDROID_SDK_HOME="my sdk"
# path to the ADT tool in Flash Builder sdks
ADT="my adt"
# native project folder
NATIVE_FOLDER=Alert_Java
# AS lib folder
LIB_FOLDER=Alert_AS
# name of ANE file
ANE_NAME=AndroidAlert.ane
# JAR filename
JAR_NAME=AndroidAlert.jar
# cert path
CERT_NAME=cert.p12
# cert password
CERT_PASS=password
#===================================================================
echo "****** preparing ANE package sources *******"
rm ${ANE_NAME}
rm -rf ./build/ane
mkdir -p ./build/ane
mkdir -p ./build/ane/Android-ARM
mkdir -p ./build/ane/Android-ARM/res
# copy resources
cp -R ./${NATIVE_FOLDER}/res/* ./build/ane/Android-ARM/res
# create the JAR file
jar cf ./build/ane/Android-ARM/${JAR_NAME} -C ./${NATIVE_FOLDER}/bin .
# grab the extension descriptor and SWC library
cp ./${LIB_FOLDER}/src/extension.xml ./build/ane/
cp ./${LIB_FOLDER}/bin/*.swc ./build/ane/
unzip ./build/ane/*.swc -d ./build/ane
mv ./build/ane/library.swf ./build/ane/Android-ARM
echo "****** creating ANE package *******"
"$ADT" -package -storetype PKCS12 -keystore ./cert.p12 -storepass password -tsa none \
-target ane \
${ANE_NAME} \
./build/ane/extension.xml \
-swc ./build/ane/*.swc \
-platform Android-ARM \
-C ./build/ane/Android-ARM/ .
echo "****** ANE package created *******"
I know this is a bit long but any help would be greatly appreciated! And feel free to let me know if you need some more elaboration
Added Java code
I modified the original code a bit. I removed AlertExtension.java and moved the get context function to AlertContext.java. I was thinking this would solve my issue but I'm still getting the same result. Here is my code:
AlertContext.java, I'm assuming the createContext method is fired after var a:Alert = new Alert();
package com.fa.ne.android;
import java.util.Map;
import java.util.HashMap;
import com.adobe.fre.FREContext;
import com.adobe.fre.FREExtension;
import com.adobe.fre.FREFunction;
public class AlertContext extends FREContext implements FREExtension {
#Override
public FREContext createContext(String type){
return new AlertContext();
}
#Override
public void initialize(){
}
#Override
public void dispose() {
}
#Override
public Map<String, FREFunction> getFunctions() {
HashMap<String, FREFunction> functionMap = new HashMap<String, FREFunction>();
functionMap.put("showAlert", new ShowAlert());
return functionMap;
}
}
Here is my ShowAlert class
package com.fa.ne.android;
import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;
import com.adobe.fre.FREInvalidObjectException;
import com.adobe.fre.FREObject;
import com.adobe.fre.FRETypeMismatchException;
import com.adobe.fre.FREWrongThreadException;
public class ShowAlert implements FREFunction {
#Override
public FREObject call(FREContext aContext, FREObject[] aPassedArgs) {
//get activity
Activity a = aContext.getActivity();
//grabbing context
final FREContext context = aContext;
try{
//getting the title and msg for alert as string
String title = aPassedArgs[0].getAsString();
String message = aPassedArgs[1].getAsString();
String negitive = aPassedArgs[3].getAsString();
String positive = aPassedArgs[4].getAsString();
//creating the alert builder with the activity
Builder builder = new Builder(a);
//setting the title and msg
builder.setTitle(title);
builder.setMessage(message);
//setting up buttons, negative and positive, each with an event so we can listen in AS3
//doing listeners inline
builder.setNegativeButton(negitive, new OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int dig){
context.dispatchStatusEventAsync("nativeAlert", "negitive");
}
}).setNeutralButton(positive, new OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int dig){
context.dispatchStatusEventAsync("positiveAlert", "positive");
}
});
//done building, time to alert and return
builder.create().show();
return FREObject.newObject(true);
//error handeling
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (FRETypeMismatchException e) {
e.printStackTrace();
} catch (FREInvalidObjectException e) {
e.printStackTrace();
} catch (FREWrongThreadException e) {
e.printStackTrace();
}
return null;
}
}

Quick tip, create a function,
which tells you whether the extension is available.
public static function isSupported():Boolean
{
return extContext != null;
}
Hope this helps.
Also it's good to add a default implementation of the native extension, which can bee ritten entierly in actions script and will be used when you run the app in emulator.
For more information look here:
http://www.adobe.com/devnet/air/articles/extending-air.html

I can't really answer your question. I don't know Java (it reads like pseudo ActionScript for me heehhehee). However, this might offer you some help & someone you could refer back here who might spot the problem easily.
Piotr Walczyszyn created an Android native alert / push extension here:
http://www.riaspace.com/2011/09/as3c2dm-air-native-extension-to-push-notifications-with-c2dm/
In the comments I also found another person with an extensive tutorial for native alerts in iOS here: http://www.liquid-photo.com/2011/10/28/native-extension-for-adobe-air-and-ios-101/
I was reading the comments on Piotr's post and some things he said leads me to wonder if this line
extContext = ExtensionContext.createExtensionContext("com.fa.alerts", null);
might be causing/related to the problem
Hope this can help you and/or others.
Best of luck everyone!
Todd
...back to researching push notification options/viability
=D

I kept running into your problem too.
The ONLY tutorial I have been able to get to work (with some changes) has been the one found here.
http://www.adobe.com/devnet/air/articles/developing-native-extensions-air.html
I had to add -swf-version 13 to the flex library compiler.
And I had to add -tsa none to the adt command to build the ANE file.

Did You link the extension to the Android platform in FlashBuilder? Just adding it to the NativeExtension tab in "Flex Build Path" is not enough You also have to check the checkbox in
"Flex Build Packaging" >> "Google Andorid">> "Native Extension"
Also You can try to look at the diference and maby somthing will help from my porject:
NativeAlert

Related

how can i determine the working directory a fatjar was invoked from

I have a project which i have made into a fatjar. Gradle pus this into the /build/libs
I have gone to this directory and invoked the fatjar with a file as a param.
steps
cd /build/libs
java -jar .jar --execute script.groovy
this launches the Main-Class - a launcher class that reads the args from command line.
however what you get as the file name is 'script.groovy' and thats intended to be from the same directory as i have the jar file
Inside the class /fatjar however if you look at
System.getProperty("user.dir")
or
Path path = FileSystems.getDefault().getPath(".").toAbsolutePath()
they all report the path as the projectRoot directory - and not where the jar itself was run from (/build/libs)
inside your class, inside the fatjar, how do you determine the directory where the fatjar actually is when invoked from the command line?
I struggled a bit on this as well. You can find some hints in StartupInfoLogger.java from spring. I am using 2.1.5 spring boot version.
Here is some sample code.
public class MyTestFatJarMainClass {
public static void main(String[] args) {
SpringApplication.run(MyTestFatJarMainClass.class, args);
// The needed code start below
// The class is MyTestFatJarMainClass.class, but it can be any class in your app
ApplicationHome home = new ApplicationHome(MyTestFatJarMainClass.class);
String path = (home.getSource() != null) ? home.getSource().getAbsolutePath() : "";
// Now you got the path, it contains the jar file itself.
System.out.println("DINDA " + s + " path " + path);
}
}
You could also read String property = System.getProperty("user.dir");
Check which one of them can be useful for you.

GCP Dataflow pipeline no json rows being read/processed

Based on the WordCount Example, I am trying to read my own json data (instead of the shakespear txts).
I am running the pipeline with:
mvn compile exec:java -Dexec.mainClass=myPkg.myClass -Dexec.args=" \
--project=myProj \
--stagingLocation=gs://myBkt/stage \
--runner=BlockingDataflowPipelineRunner \
--output=gs://myBkt/output/out \
--defaultWorkerLogLevel=DEBUG"
the output from the console is as follows:
<date> com.google.cloud.dataflow.sdk.runners.DataflowPipelineRunner fromOptions
INFO: PipelineOptions.filesToStage was not specified. Defaulting to files from the classpath: will stage 68 files. Enable logging at DEBUG level to see which files will be staged.
<date> myPkg$GroupPublished apply
<date> myPkg$GroupPublished apply
INFO: GroupPublished/JsonToDatePosPlatKeyFn.out [PCollection]
<date> myPkg main
main
static void main(String[] args) {
...
Pipeline p = Pipeline.create(options);
p.apply(TextIO.Read.named("ReadJson").from(options.getInputFile()))
.apply(new GroupPublished())
.apply(ParDo.of(new FormatAsStringFn()))
.apply(TextIO.Write.named("WriteCounts").to(options.getOutput()));
}
GroupPublished transformation
static class GroupPublished extends PTransform<PCollection<String>,
PCollection<KV<DatePosPlatKey, Long>>> {
#Override
public PCollection<KV<DatePosPlatKey, Long>> apply(PCollection<String> lines) {
PCollection<DatePosPlatKey> keyList
= lines.apply(ParDo.of(new JsonToDatePosPlatKeyFn()));
PCollection<KV<DatePosPlatKey, Long>> keysCounted =
keyList.apply(Count.<DatePosPlatKey>perElement());
return keysCounted;
}
}
json row processing
static class JsonToDatePosPlatKeyFn extends DoFn<String, DatePosPlatKey>{
#Override
public void processElement(ProcessContext c) throws Exception {
JsonNode root = mapper.readTree(c.element());
for (JsonNode jsonFact : root) {
DatePosPlatKey key = new DatePosPlatKey(...construct...);
...manipulate...
c.output(key);
}
}
}
data class
#DefaultCoder(AvroCoder.class)
public static class DatePosPlatKey { ... }
stuff I've checked so far:
adding defaultWorkerLogLevel doesn't seem to make any difference to the console output
renaming the json file throws an error, so I know its been seen by TextIO
the json files have data in the format: {...}\n{...}\n...
no logging or dataflow job appears in the google cloud console
how can I better debug a complete lack of data?
can you see what I've done wrong?
Upon offline discussion it turned out the code was missing a call to p.run(), so the pipeline was only constructed but not executed.

Assert element color in Selenium IDE

I'm trying to setup a test automation that will assert an element color when clicked. However, I couldn't find the right way to do it. I'm a selenium newbie, I have tried every possible way to do it but failed.
HTML:
<a class="mg-friend-12345 friend selected" title="test" data-cid="12345" style="">
CSS:
.imweb #mgifting-dialog .mg-friends .friend.selected, .imweb #mgifting-dialog .mg-friends .non-friend.selected {
background-color: #9DD4FD;
}
IMHO the idea be the following:
we simply need to get css property(color, in particulat) of element before click. and get css property(color ) of the element after click on it.
so it be like (I work on java and we will execute a piece of javascript using jsExecutor to implement getColor function. It will take css selector of the element. And get return its color):
public String jsGetColor(String css){
JavascriptExecutor js = (JavascriptExecutor) driver;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("var x=$(\'"+css+"\');");
stringBuilder.append("return x.css('color')");
//stringBuilder.append("return x.css('background-color')");
String res= (String) js.executeScript(stringBuilder.toString());
return res;
}
String cssSelectorLink="a[class='mg-friend-12345 friend selected']";
WebElement linkToClick = driver.findElemebt(By.cssSelector(cssSelectorLink));
String colorBeforeClick = jsGetColor(cssSelectorLink);
linkToClick.click();
String colorAfterClick = jsGetColor(cssSelectorLink);
Assert.assertFalse(colorBeforeClick.equals(colorAfterClick));
Hope it be helpful for you.
well I work in intelij IDEA. So setUp to write selenium tests e.g. be the following:
1) install maven
Unzip the distribution archive, i.e. apache-maven-3.0.4-bin.zip to
the directory you wish to install Maven 3.0.4. These instructions
assume you chose C:\Program Files\Apache Software Foundation. The
subdirectory apache-maven-3.0.4 will be created from the archive.
Add the M2_HOME environment variable by opening up the system
properties (WinKey + Pause), selecting the "Advanced" tab, and the
"Environment Variables" button, then adding the M2_HOME variable
in the user variables with the value C:\Program Files\Apache
Software Foundation\apache-maven-3.0.4. Be sure to omit any
quotation marks around the path even if it contains spaces. 
In the same dialog, add the M2 environment variable in the user
variables with the value %M2_HOME%\bin.
2) install jdk
3)
4) verify that all environment variables you've set properly
5) run intelij IDEA
select Project structure to set up installed JDK
6)
press New.select jsdk. write path where we installed java, e.g C:\Program Files\Java\jdk1.6.0_29
7)create new project from scratch
8) maven module
9)
10)
11) add to POM appropriate dependencies:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.24.1</version>
</dependency>
12) if still someting underline with red line , press alt+enter on it >> idea should automatically suggest autoimport.
13)test structure in the project
14)common structure of selenium test
import com.thoughtworks.selenium.SeleneseTestBase;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import java.util.concurrent.TimeUnit;
public class HomePageTest extends SeleneseTestBase{
static WebDriver driver;
#Before
public void openFirefox(){
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
}
#Test
public void testHomePage(){
driver.get("https://www.google.by/");
WebElement search = driver.findElement(By.xpath("//*[#id=\"gbqfq\"]"));
search.sendKeys("laptop");
search.submit();
}
#After
public void closeFirefox(){
// driver.quit();
}
}
15) also don't forget that you can export your created test in selenium IDE as JUNIT4- selenium and open them in IDEA
Regards

How to connect Gaia Framework with Facebook Graph API?

I'm trying to include a Facebook app in a section of a Flash website developed in GAIA Framework. I've followed many examples and tutorials and I've tried to do a simple login on the Nav Page.
My imported classes (ALL of the facebook api?):
import com.adobe.serialization.json.JSON;
import com.facebook.graph.Facebook;
import com.facebook.graph.controls.*;
import com.facebook.graph.core.*;
import com.facebook.graph.data.*;
import com.facebook.graph.net.*;
import com.facebook.graph.utils.*;
My var with facebook id:
private var FB_app_id:String = 'my app id goes here :)';
My constructor:
public function NavPage()
{
super();
alpha = 0;
init();
Facebook.init(FB_app_id);
}
So, every time I try to publish, the following error appears:
C:\PROJECT ZERO\1 - Proyectos\2p -
WEB\src\com\facebook\graph\data\FQLMultiQuery.as, Line 80 1061: Call
to a possibly undefined method encode through a reference with static
type Class.
Line 80 of FQLMultiQuery.as refers to the following code:
public function toString():String {
return JSON.encode(queries);
}
What could be wrong? What am I doing wrong? I'm starting to think it might be an incompatibility issue between GAIA and the Facebook API.
It seems like you have a conflict with native JSON (since flash player 11) and the JSON from com.adobe.serialization.json package.
My solution for this is to rename the second one. Or start using the new JSON instead and exclude com.adobe.serialization.* from project.
reference:
http://www.pippoflash.com/index.php/2012/06/20/flash-player-10-and-flash-player-11-json-json-conflict-solved/

Getting started with rhino service bus

I've read a lot of examples/tutorials (incl. Ayende's Alexandria on MSDN).
But just getting somewhat updated assemblies have proven to be an obstacle in itself. After getting the correct version of Castle.Windsor - it cannot find the correct section in the app.config file. The syntax in both Rhino Service Bus and the CastleBootstrapper has been changed as well - and I'm now totally confused. The 'documentation' on Hibernating Rhinos is really not helping me get started.
Could anyone please help me a working sample with Rhino Service Bus with either Castle Windsor v. 3.0 (beta) or 2.5.3, point me at something already online or just giving me a step-by-step pointers on what I need to get up and running?
after downloading the latest Rhino-ESB bits from github (https://github.com/hibernating-rhinos/rhino-esb) and building it, it's pretty straightforward to get started.
I have a asp.net MVC application which communicates with a backend through Rhino-ESB.
On the asp.net MVC side:
On global.asax.cs:
private IWindsorContainer _container;
protected void Application_Start()
{
_container = new WindsorContainer();
new RhinoServiceBusConfiguration().UseCastleWindsor(_container).Configure();
_container.Install(new YourCustomInstaller());
//Don't forget to start the bus
_container.Resolve<IStartableServiceBus>().Start();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));
}
Note that YourCustomInstaller must implement IWindsorInstaller and you register your controllers with the container in the Installmethod:
public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(Component
.For<HomeController>().LifeStyle.PerWebRequest.ImplementedBy<HomeController>());
Also note that the WindsorControllerFactory internally delegates controller creation to the container:
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)this.container.Resolve(controllerType);
}
Last but not least, provide the configuration on your web.config
<configSections>
<section name="rhino.esb" type="Rhino.ServiceBus.Config.BusConfigurationSection, Rhino.ServiceBus"/>
</configSections>
<rhino.esb>
<bus threadCount="1"
numberOfRetries="5"
endpoint="rhino.queues://localhost:31316/Client"
queueIsolationLevel="ReadCommitted"
name="Client"/>
<messages>
<add name="YourMessagesNamespace"endpoint="rhino.queues://localhost:31315/Backend"/>
</messages>
</rhino.esb>
This configuration assumes that the backend runs a queue in localhost:31315 and the client runs its queue on localhost:31316.
On the backend side:
assuming we're running it as a console application,
static void Main(string[] args)
{
IWindsorContainer container;
container = new WindsorContainer();
new RhinoServiceBusConfiguration()
.UseCastleWindsor(container)
.Configure();
var host = new RemoteAppDomainHost(typeof(YourBootstrapper));
host.Start();
Console.WriteLine("Starting to process messages");
Console.ReadLine();
Notice that YourBootstrapperclass implements CastleBootstrapper
public class YourBootstrapper: Rhino.ServiceBus.Castle.CastleBootStrapper
{
protected override void ConfigureContainer()
{
Container.Register(Component.For<OneOfYourMessages>());
}
}
in which we're registering a consumer for OneOfYourMessages