Adobe ANE works on iOS and Android devices, but not in AIR simulator - air

The vibration ane by Adobe works well in a Flex mobile app both on iOS and Android, but when I try to launch an AIR simulator from Flash Builder 4.7 on Windows 7 I get the error:
Here a copy of the error message from the latter screenshot:
Process terminated without establishing connection to debugger.
The content cannot be loaded because there was a problem loading an extension: Error: Requested extension com.adobe.Vibration is not supported for Windows-x86.
Launch command details: "C:\Program Files\Adobe\Adobe Flash Builder 4.7 (64 Bit)\sdks\4.6.0 (AIR 3.5)\bin\adl.exe" -runtime "C:\Program Files\Adobe\Adobe Flash Builder 4.7 (64 Bit)\sdks\4.6.0 (AIR 3.5)\runtimes\air\win" -profile extendedMobileDevice -screensize 640x920:640x960 -XscreenDPI 326 -XversionPlatform IOS -extdir "C:\Users\xxx\Adobe Flash Builder 4.7\.metadata\.plugins\com.adobe.flexbuilder.project.ui\ANEFiles\MyApp-Mobile\win32\" C:\Users\xxx\Documents\MyApp\mobile\bin-debug\MyApp-app.xml C:\Users\xxx\Documents\MyApp\mobile\bin-debug
At the same time:
Another ANE by Adobe - the GameCenter.ane included with Adobe Gaming SDK works flawlessly with the AIR Simulator
The com.adobe.extensions.Vibration.ane mentioned above doesn't fail when I select the BlackBerry AIR simulator (but the iOS and Android AIR Simulators do not work).
Is there a way to make this work more comfortable?
I'd like to use the com.adobe.extensions.Vibration.ane in my Flex mobile app, but I also want to use the AIR simulator - without commenting the source code and removing that ANE from project properties.
UPDATE 2016:
Adobe has updated their Vibration native extension (ANE) sample with 64-bit support.

The problem with the ANE is that it's not a complete implementation. Most importantly the ANE doesn't implement a default fallback implementation which is what the device would fallback to if there wasn't a particular implementation for the current platform.
This makes the ANE very hard to use in cross-platform development as it will fail in some cases. Any platform that isn't specifically included will fail with the message you received.
Basically without changing the ANE yourself you won't be able to use it as you are expecting. Your only way is to do some conditional style compilation and not call the ANE in the simulator.
If you do wish to change the ANE then the best option is to implement the default library. This is quite simple, but you will need: XCode, eclipse with Android dev tools, and adt from the AIR SDK.
Firstly you'll need to compile the existing projects, the Android lib, the iOS lib and the existing actionscript library, to generate VibrationAndroidLibrary.jar, libVibrationiOSLibrary.a and VibrationActionScriptLibrary.swc respectively.
You'll then need to make another actionscript library, and duplicate the com.adobe.nativeExtensions.Vibration class as below:
public class Vibration
{
public function Vibration()
{
}
public static function get isSupported():Boolean
{
return false;
}
public function vibrate(duration:Number):void
{
}
}
This class will replace the other class in cases where the extension isn't implemented instead of you getting the above message.
Then we'll need to add the default definition to the extension.xml file:
<extension xmlns="http://ns.adobe.com/air/extension/2.5">
<id>com.adobe.Vibration</id>
<versionNumber>1</versionNumber>
<platforms>
<platform name="Android-ARM">
<applicationDeployment>
<nativeLibrary>VibrationAndroidLibrary.jar</nativeLibrary>
<initializer>air.extensions.VibrationExtension</initializer>
<finalizer>air.extensions.VibrationExtension</finalizer>
</applicationDeployment>
</platform>
<platform name="iPhone-ARM">
<applicationDeployment>
<nativeLibrary>libVibrationiOSLibrary.a</nativeLibrary>
<initializer>ExtInitializer</initializer>
<finalizer>ExtFinalizer</finalizer>
</applicationDeployment>
</platform>
<platform name="default">
<applicationDeployment />
</platform>
</platforms>
</extension>
Then we'll need to recompile the ANE using the new default actionscript SWC. Lets say you're in the VibrationNEDeliverables directory from the mentioned ANE, you can enter this into a bash file and run it or put it all on one line from the command line). The first couple of lines just extract the library.swf file and move it to the locations needed by the package command. Be careful with the paths etc here, I've assumed you've put the default lib in VibrationActionScriptDefaultLibrary but you'll need to change this appropriately.
unzip -o -d VibrationActionScriptLibrary/bin VibrationActionScriptLibrary/bin/VibrationActionScriptLibrary.swc
unzip -o -d VibrationActionScriptDefaultLibrary/bin VibrationActionScriptDefaultLibrary/bin/VibrationActionScriptDefaultLibrary.swc
cp VibrationActionScriptLibrary/bin/library.swf VibrationiOSLibrary/build/Release-iphoneos/.
cp VibrationActionScriptLibrary/bin/library.swf VibrationAndroidLibrary/bin/.
adt -package \
-storetype pkcs12 -keystore YOUR_SIGNING_KEY.p12 -storepass KEY_PASSWORD \
-target ane com.adobe.extensions.Vibration.ane VibrationActionScriptLibrary/src/extension.xml \
-swc VibrationActionScriptLibrary/bin/VibrationActionScriptLibrary.swc \
-platform iPhone-ARM -C VibrationiOSLibrary/build/Release-iphoneos . \
-platform Android-ARM -C VibrationAndroidLibrary/bin . \
-platform default -C VibrationActionScriptDefaultLibrary/bin .
Once that's complete you should now have a new version of the ANE with a default lib which will make it much more useable! Personally I don't think an ANE should be released without it.
If you need a fully functional ANE, you can check out ours: http://distriqt.com/native-extensions

A solution that I've used in the past was something like this:
Create a utility class that returns whether you're running on a device that supports the ANE. In my case, the class contained a static method that checked the value of Capabilities.os. See the list of values it can return here.
Put the code that calls the ANE method(s) into their own function, and call this function if the ANE is supported. If I recall correctly, it was necessary to put the code that used the ANE in a separate function, not just inside an if block, otherwise the same error would occur in the simulator:
Do this:
public function doSomethingThatWillUseANE():void
{
if (DeviceCapabilities.supportsANE) // static utility class
{
methodThatUsesANE();
}
}
private function methodThatUsesANE()
{
// execute actual ANE method here
}
Instead of doing it all in one function like this:
public function doSomethingThatWillUseANE():void
{
if (DeviceCapabilities.supportsANE) // static utility class
{
// execute actual ANE method here
}
}

same problem exists with the newest vibration ane built for ios 64bit compatibility. My workaround was to place the ane import statement inside the function that actually called the vibrate method, and uncheck the include box for the ane in the project build path settings for android and ios.
I have a flag variable (set by a separate function) in my application that flags whether the app is being run within the ide. The view that uses vibration will only call the above vibration function if the flag is set to non-IDE mode. I still get an initial warning when I run the ide simulator, but not the critical error. When I do a release build, FlashBuilder forces me to checkmark the include box for the ane in the applicable project build path settings (I have to uncheck it again next time I want to run the simulator).
It's clunky, but it makes working with the ane liveable. Peeves me to no end that adobe hasn't addressed this.

Related

How to whitelist a vendor-specific API in AOSP for Android 10

I'm trying to add a vendor-specific API to my AOSP code base. I was able to get this working on Android 5 through 9, but cannot figure this out on Android 10.
I read the documentation on the AOSP docs for Implementing Java SDK Library
I have the following blueprint file:
java_sdk_library {
name: "com.mycompany.sdk.myclass",
srcs: ["java/**/*.java"],
api_packages: ["com.mycompany.sdk.myclass"],
}
I generated the api subdirectory using:
build/soong/scripts/gen-java-current-api-files.sh "vendor/mycompany/sdk/myclass" && m update-api
This put all my public method signatures into the current.txt file.
I added this as a boot jar to my top level board.mk file with:
PRODUCT_BOOT_JARS += com.mycompany.sdk.myclass
Building this creates the corresponding com.mycompany.sdk.myclass.xml permissions file:
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<library name="com.mycompany.sdk.myclass"
file="/system/framework/com.mycompany.sdk.myclass.jar"/>
</permissions>
Everything builds and installs fine. I verified the permissions file is in /system/etc/permissions/ and points to the correct jar filename. But I get "Accessing hidden method (blacklist, linking, denied)" exceptions when I run a test app built against my private SDK:
W/test_app: Accessing hidden method Lcom/mycompany/sdk/myclass;->myMethod(Landroid/content/Context;Z)V (blacklist, linking, denied)
I can eliminate this blacklist error by issuing the command:
adb shell settings put global hidden_api_policy 1
So I know my jar is being built and installed correctly. But is just blacklisted for 3rd parties.
I eventually added my package name to frameworks/base/config/hiddenapi-greylist-packages.txt, and suddenly my test app runs, and properly finds the private API. Unfortunately, the blacklist errors are replaced by greylist warnings on every method call. I don't want the log cluttered with these warnings, so it must be whitelisted, not greylisted.
I tried adding it to /build/make/core/tasks/check_boot_jars/package_whitelist.txt, but this made no difference.
How do I whitelist my private API instead of greylist?
There is no white list.
The white list (allow list) is the methods listed in Android SDK.
Private API are not in Android SDK.

PhoneGap / iOS7 / XCode 5 / Mavericks: compiles but doesn't really work

I have used Phonegap several times but since the upgrade to Mavericks / Xcode5 everything has changed.
If I try to create a helloworld project, everything looks good: it compiles and launches the simulator or installs the app on my phone. The problem is if I try to add any Phonegap functionality, the it just won't work.
UPDATE: this is how I'm creating the project:
cordova create helloworld
cordova platform add ios
I have tried directly opening helloworld.xcodeproj in Xcode, using the "cordova run ios", "cordova prepare", "cordova build" commands but none of them seems to make any difference (some of these create and copy a lot of files, but there is no difference regarding the access to "device" variable)
The only way of debugging I have managed to use is to show alerts and try/catch blocks like this:
try {
alert(device);
// var text = '';
// var i = 0;
// for (var attribute in window) {
// text = text + '\n' + attribute;
// i++;
// }
// alert("total " + i + " keys: " + text);
} catch (err) {
alert(err);
}
Trying to read from "device" variable results in the following:
The text on this error suggests that one should use the following command
phonegap plugin add thePlugin
That indeed works: it adds the desired feature on the config.xml file, but the problem persits, so it does not look like an issue related to permissions. The same thing occurs when installing and trying to use other plugins, such as accelerometer or notifications.
I really liked Phonegap because it made things easier, but now it seems the opposite. One optoin is to use an older version of Phonegap and/or Xcode, but that's not what I'm looking for.
So, what is my configuration?
Mavericks 10.9.1
Xcode 5.0.2 (5A3005)
Phonegap / cordova 3.3.0
iOS 7.0.4 (iPhone 5) --> or the emulator
Any clues?
Thanks
I finally managed to solve this issue.
The solution is simple, yet it was difficult to detect.
Every time you add a plugin using the following command: cordova plugin add thePlugin you then need to run the cordova prepare command again. This is tricky, because if you take a look at the code after adding the plugin there is some setup/changes made. But these changes aren't enough, so cordova prepare might first seem redundant, but solves the issue.
So:
create the project
add as many plugins as you might use
start developing either:
(a) directly on the generated YOURAPP.xcodeproj file, and NEVER run
the cordova prepare commmand again, otherwise you will delete all your
changes
(b) work on the "general" www folder of your project and then run cordova prepare everytime you need to create a new version. Note:
you'll need to close the xcodeproj file in order to see any changes
I tend to think that alternative "(a)" should be the optimal, just make sure you don't overwrite your files or keep your files properly versioned

XCode 5 unit testing: starts my app

When I run my tests in XCode 5, the main window of my OS X app appears on the screen for a couple of seconds while running the tests. Why? Even if I uncomment all my tests it still opens my main window.
You are running application test, not logic test. This means an instance of your app will be started and then run the unit tests. This allow you to perform some integration test that require your app is running.
Here is the guide to setup application test and logic test.
If you want to change it to logic test (so it run faster and don't need to start your app first):
go to build settings for your unit test target
search Bundle
remove Bundle Loader and Test Host
Thats right, you have to delete the "Bundle Loader" and "Test Host" from your build settings.
But you have to add the necessary implementation files to your unit test target. The necessary files are what you want to use in your unit test cases. You need to do this because in logic tests XCode wont compile the whole application. So some of your files will be missing.
This is en error message if you have left out a file:
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_Module", referenced from:
objc-class-ref in Lobic Network.o
objc-class-ref in Logic_Unit.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
You can add the missing files by selecting the implementation file and bringing up the file inspector. There will be a section named "Target Membership" and there you can set the files target membership to your unit test also.
With XCTest, application files DO NOT need to be included within XCTest targets. The XCTest bundle is linked against the application which makes those files available during runtime.
To make this work, ensure the compiler option "Symbols hidden by default" is set to NO Within the Application target.
Here is a blog post with screenshots for clarity:
http://zmcartor.github.io/code/2014/02/24/slim-xctest-targets
The advantage of this approach is test target builds much much faster.
In XCode 7, removing Host Application does not work for me. Indeed I use the following to avoid app runs.
Setup Test Scheme Arguments
in main.m
static bool isRunningTests()
{
NSDictionary* environment = [[NSProcessInfo processInfo] environment];
NSString* testEnabled = environment[#"TEST_ENABLED"];
return [testEnabled isEqualToString:#"YES"];
}
modify main()
int main(int argc, char * argv[]) {
#autoreleasepool {
if (isRunningTests()) {
return UIApplicationMain(argc, argv, nil, nil);
} else {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
}
If the tests are for code that can run on desktop and mobile, you can run them without a simulator or hosting them within your app.
The trouble is that you cannot use the scheme chooser for your normal target (desktop or iOS) to run the test.
The following worked for me in Xcode6.
File > New Target...
Select Cocoa Testing Bundle from the OS X category.
Take care to select None from the target drop-down.
Click Finish. Add the relevant files to the new target as described above.
Now create a scheme to run the test.
Click the schemes chooser top-right and choose New Scheme..., click the drop-down and navigate down the list to the new target. Now you can choose the scheme from the schemes chooser, and use ⌘U to run the tests.
I just wasted a morning on this.
Project was created in XCode 4 and used SenTesting.
Tried migrating tests on XCode 5/XCTTest
Had same issue - app ran in simulator and test never started
after trying everything (change from app to logic tests, change to XCTest, remove SenTesting)
gave up created a clean XCode 5 project.
Added all my files in and tests ran ok.
May still have issues with Storyboard as these were built with XCode 4.
Drastic but it works so keep it as last resort.
On XCode5, the app does start. This answer shows how to change its delegate when running unit tests so that it exits right away: https://stackoverflow.com/a/20588035/239408

JNI UnsatisfiedLinkError- how do I load libraries correctly?

I'm trying to work with the Java sample Database program from the CardScan SDK.
I am working with files located in Java/JNI and Java/Database. The program must be run with a 32 bit JRE. I was able to do so on a 64 bit machine by uninstalling Java and installing the 32 bit version, then re-adding the system path for Java. I can run the program and interface with a CardScan database file (.cdb) successfully by double clicking the SDKData.bat file, but when I open the source files for editing and edit the Java.library.path to include the required library (CRTK_JNI.dll), I get UnsatisfiedLinkErrors everywhere:
Exception in thread "main" java.lang.UnsatisfiedLinkError: sdkdata.CRTK.CRTK_Init([I)I
at sdkdata.CRTK.CRTK_Init(Native Method)
at sdkdata.CRTK.(CRTK.java:239)
at sdkdata.SDKData.(SDKData.java:97)
at sdkdata.SDKData.main(SDKData.java:643)
Java Result: 1
Presumably this is happening because the library is not loading properly.
What do I need to do to run and edit the program at full capacity (with all the native functions from CRTK_JNI in working order)?
Presumably this is happening because the library is not loading properly.
On the contrary. The library load is complete. You aren't getting that from a System.load()/loadLibrary() call, you are getting the error when calling your native method, the one that should have the signature:
package sdkdata;
public class CRTK
{
public native int CRTK_Init(int[]);
}
So it isn't there, or you have changed the signature without regenerating the .h and .c files, or you have manually mangled the declaration some other way.
Post your code.
To clarify, this Java sample program is officially unsupported by the CardScan API - it was a bad idea to try to use the API with an unsupported language relying solely on an experimental implementation. I ended up using one of the supported languages (Visual Basic) to work with the SDK; if anyone looking at this question happens to be struggling with using the CardScan API, here is my VB implementation on Github.

ClassNotFoundException on app startup (on device)

I have been able to run my app exactly ONCE on the device (N8). Since then I always get a ClassNotFoundException when I launch it. It goes like this:
ClassNotFoundException:
com.greencod.pinball.nokia.PinballMIDLet
at java.lang.Class.forName at
...rtCldc.loadApplicationClass at
...rt.jvm.loadApplicationClass at ...
Invoker.handleStarRequest at
...l.rt.midp.MidleInvoker.run at
java.lang.Thread.run
Note that the app runs fine on the emulator. Also, the first time that it ran was througth the debugger in eclipse. Now the debugger or a plain install doesn't produce an app that can run. I am new to Nokia development, so I must be doing something stupid, I just don't know what :) I am using the Symbian^3 SDK 0.9.
To get the application on the phone, I click 'create package' from the manifest view, which build the jar/jad files for 2 targets: SymbianEmulator and SymbianDevice, which I installed by scanning the SDK folder. After I have tried uploading the file to the device by dropping it in the Install folder, by using the debuger in eclipse and with the Ovi program on my computer. The phone itself is configured to accept unsigned application.
I am quite lost and any help is welcome.
Additional Info
Eclipse is building the jad for me, so I'm not sure that is the problem. Here is the jad file:
MIDlet-1: Pinball Deluxe,,com.greencod.pinball.nokia.PinballMIDLet
MIDlet-Jar-Size: 1882
MIDlet-Jar-URL: Pinball-MIDLet.jar
MIDlet-Name: Pinball Deluxe MIDLet
MIDlet-Vendor: GreenCod
MIDlet-Version: 0.1.0
MicroEdition-Configuration: CLDC-1.1
MicroEdition-Profile: MIDP-2.1
Navi-Key-Hidden: true
Nokia-MIDlet-App-Orientation: portrait
Nokia-MIDlet-On-Screen-Keypad: no
And here is my class declaration:
package com.greencod.pinball.nokia;
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
public class PinballMIDLet extends MIDlet { ... }
It has been solved: nokia forums. Basically the problem was that the build.properties of the project were messed up.