IncompatibleClassChangeError on Android Things - android-things

After updating to the latest Android Things preview, my app is crashing when
setting a callback on by button GPIO. I have the following button callback defined:
private class ButtonCallback extends GpioCallback {
#Override
public boolean onGpioEdge(Gpio gpio) {
boolean isPressed = false;
try {
isPressed = gpio.getValue();
} catch (IOException e) {
Log.w(TAG, "Error", e);
}
if (isPressed) {
...
}
return true;
}
}
I am registering it with the GPIO in the application as follows:
Gpio button = ...;
try {
button.registerGpioCallback(new ButtonCallback());
} catch (IOException e) {
Log.w(TAG, "Error configuring GPIO pins", e);
}
When I run my app, I get an IncompatibleClassChangeError and the app crashes:
java.lang.IncompatibleClassChangeError: Superclass com.google.android.things.pio.GpioCallback of com.google.android.things.example.MainActivity$ButtonCallback is an interface (...)
This code was working before, why has this started happening after the update?

Starting in Preview 7, many of the Peripheral I/O interfaces were converted from
abstract classes to interfaces. This was done to better facilitate testability
in apps, as interfaces are easier to mock.
Be sure to update your app to use the Preview 7 SDK:
dependencies {
compileOnly 'com.google.android.things:androidthings:0.7-devpreview'
}
Then modify your callback to implement the interface instead:
private class ButtonCallback implements GpioCallback {
#Override
public boolean onGpioEdge(Gpio gpio) {
boolean isPressed = false;
try {
isPressed = gpio.getValue();
} catch (IOException e) {
Log.w(TAG, "Error", e);
}
if (isPressed) {
...
}
return true;
}
}
Review the Android Things API reference
to verify if any of the other APIs you are calling have changed.

Related

Stopping Fitnesse (Slim) on any exception

We've found the "Fail Fast" principle crucial for improving maintainability of our large Fitnesse-based battery of tests. Slim's StopTestException is our saviour.
However, it's very cumbersome and counterproductive to catch and convert any possible exception to those custom StopExceptions. And this approach doesn't work outside of fixtures. Is there a way to tell fitnesse (preferably using Slim test system) to stop test on any error / exception?
Update: corresponding feature request https://github.com/unclebob/fitnesse/issues/935
Most of the exceptions coming from fixtures are possible to conveniently convert to the StopTestException by implementing the FixtureInteraction interface, e.g.:
public class StopOnException extends DefaultInteraction {
#Override
public Object newInstance(Constructor<?> constructor, Object... initargs) throws InvocationTargetException, InstantiationException, IllegalAccessException {
try {
return super.newInstance(constructor, initargs);
} catch (Throwable e) {
throw new StopTestException("Instantiation failed", e);
}
}
#Override
public Object methodInvoke(Method method, Object instance, Object... convertedArgs) throws InvocationTargetException, IllegalAccessException {
try {
return super.methodInvoke(method, instance, convertedArgs);
} catch (Throwable e) {
throw new StopTestException(e.getMessage(), e);
}
}
public static class StopTestException extends RuntimeException {
public StopTestException(String s, Throwable e) {
super(s, e);
}
}
}

About good practice for GLib.Application and Soup.Server

I'm trying to create a simple server in vala using libsoup.
I am wondering if it is a good way to start a Soup.Server from a GLib.Application. Since using it synchronously (run is deprecated) is not recommended, the only way I found to keep it alive is to hold the default application.
public class Simple.Server : Soup.Server
{
public Server () {
Application.get_default ().hold ();
add_handler(null, null_handler);
}
private void null_handler (Soup.Server server, Soup.Message message,
string path, HashTable<string,string>? query,
Soup.ClientContext client) {
GLib.message ("path: %s", path);
message.status_code = 404;
message.set_response ("text/plain", Soup.MemoryUse.COPY, "".data);
}
}
public class Simple.App : Application
{
private Simple.Server server;
App () {
Object (application_id: "org.dev.simple-server",
flags: ApplicationFlags.FLAGS_NONE);
}
protected override void activate () {
base.activate ();
server = new Simple.Server();
try {
server.listen_all(8080, 0);
}
catch (Error e) {
GLib.message ("Error n°%u: %s", e.code, e.message);
}
}
protected override void shutdown () {
base.shutdown ();
server.disconnect ();
}
static int main (string[] args) {
App app = new Simple.App();
return app.run (args);
}
}
This is mimic of my code.
So here is the question, is it a good practice for starting the server, still using GLib.Application, or should I use (like examples say) only the server, starting/stopping manually the MainLoop ?
thanks.

QR Code Live Scanning in BlackBerry OS 6.0

I want to Implement a QR Code Reader In BlackBerry Os 6. I try the following Code On the Basis of KB Article How to use the Barcode API.
public class ScanScreen extends MainScreen implements BarcodeDecoderListener
{
private LabelField match;
private BarcodeScanner scanner;
public ScanScreen()
{
match = new LabelField("Scanning...");
add(match);
Vector supported = new Vector();
supported.addElement(BarcodeFormat.QR_CODE);
Hashtable hints = new Hashtable();
hints.put(DecodeHintType.POSSIBLE_FORMATS, supported);
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
BarcodeDecoder decoder = new BarcodeDecoder(hints);
try
{
scanner = new BarcodeScanner(decoder, this);
add(scanner.getViewfinder());
scanner.startScan();
}
catch (Exception e)
{
e.printStackTrace();
match.setText("Exception");
invalidate();
}
}
public void barcodeDecoded(String rawText)
{
match.setText("Found: " + rawText);
invalidate();
}
public void close()
{
try
{
scanner.stopScan();
}
catch (Exception e)
{
e.printStackTrace();
}
super.close();
}
}
The Code not working. It do not recognize QR codes. I try to focus on different QR codes. But it not decode The qrcodes.Also It not Thrown Any exceptions. Please Help me....
I tried using these Devices: BB pearl 9105 and BB Storm 9530
See the sample from the following link.It will help you
http://aliirawan-wen.blogspot.com/2011/05/barcode-scanner-for-blackberry-os-50.html
I'm painfully new to BB development, but I notice you pass "this" as the decoderlistener parameter, perhaps that's causing a problem?
BarcodeDecoder decoder = new BarcodeDecoder(hints);
BarcodeDecoderListener decoderListener = new BarcodeDecoderListener()
{
public void barcodeDecoded(String rawText)
{
displayMessage(rawText);
}
};
try
{
scanner = new BarcodeScanner(decoder, decoderListener)
add(scanner.getViewfinder());
scanner.startScan();
}
catch (Exception e)
{
e.printStackTrace();
match.setText("Exception");
invalidate();
}
}

Blackberry check internet connection on device

How do I check if the Internet connection is ON or OFF on a device?
You better check using
CoverageInfo.isCoverageSufficient(CoverageInfo.COVERAGE_DIRECT);
The CoverageInfo class provides some more types of coverage to check for. See http://www.blackberry.com/developers/docs/6.0.0api/net/rim/device/api/system/CoverageInfo.html
I think there is no direct way.
You just request for a server,if there is there is no internet not avilable at that time an exception is thrown, you catch it display an alert to the user.
Some thing like below:
try {
// request http
}
catch(IOException e) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("No Internet Connectivity");
//System.exit(0);
}
});
System.out.println(e);
}
Call this method, if it returns true then you've got connection. It checks to ensure you have enough battery for internet connection, your 3G or wireless is turned on and then you have enough signal.
public synchronized static boolean checkConnection() {
boolean returnVal = true;
if (DeviceInfo.getBatteryLevel() < 6) {
returnVal = false;
}
else if (RadioInfo.getState() == RadioInfo.STATE_OFF) {
returnVal = false;
}
else if (RadioInfo.getSignalLevel() == RadioInfo.LEVEL_NO_COVERAGE) {
returnVal = false;
}
return returnVal;
}
Here's what I use in my application, and it works just fine:
protected static boolean isOutOfServiceRange() {
return !RadioInfo.isDataServiceOperational();
}

previous instance still active error in blackberry

I created app which user can start from menu and from icon. I do not use GlobalEventListener in my app, just register ApplicationMenuitem. And now I am getting error: previous instance still active when launch my app.
Steps to reproduce not so trivial:
launch app from icon
do not close it, just switch to another app
launch app from icon again
I founded article in blackberry's forum about it , but I can't find solution where I should remove my ApplicationMenuItem: it added on phone boot and should show all the time.
My code:
public class Jingu extends UiApplication {
public static void main(String[] args) {
ApplicationManager app = ApplicationManager.getApplicationManager();
boolean keepGoing = true;
while (keepGoing) {
if (app.inStartup()) {
try {
Thread.sleep(1000);
} catch (Exception e) {}
} else {
keepGoing = false;
}
}
Jingu theApp = new Jingu();
theApp.initMenuItem();
theApp.showMainScreen();
theApp.enterEventDispatcher();
}
public Jingu() {
}
public void showMainScreen() {
showScreen(new JinguMainScreen(this));
}
public void initMenuItem() {
// Create menu item
Object o = RuntimeStore.getRuntimeStore().get(JinguMenuItem.MY_MENU_ID);
// register only if not done already.
if (o == null) {
new JinguMenuItem(this).registerInstance();
}
}
public void showScreen(Screen aScreen) {
synchronized (Application.getEventLock()) {
try {
UiApplication.getUiApplication().popScreen(aScreen);
} catch (Exception e) {
}
UiApplication.getUiApplication().pushScreen(aScreen);
}
}
}
public class JinguMenuItem extends ApplicationMenuItem {
public static final long MY_MENU_ID = 0xb9739d5240d5943dL;
private final Jingu jingu;
public JinguMenuItem(Jingu jingu) {
super(0x350100);
this.jingu = jingu;
}
public void registerInstance() {
Object menuItem = RuntimeStore.getRuntimeStore().remove(MY_MENU_ID);
if (menuItem == null) {
ApplicationMenuItemRepository amir = ApplicationMenuItemRepository.getInstance();
amir.addMenuItem(ApplicationMenuItemRepository.MENUITEM_SYSTEM, this);
RuntimeStore.getRuntimeStore().put(MY_MENU_ID, this);
}
}
public Object run(Object context) {
jingu.setDefaultFont(Font.getDefault());
jingu.setMainApp(false);
jingu.setBbmEditField(null);
jingu.showMainScreen();
return context;
}
public String toString() {
return "My Menu";
}
}
plz advice where I should delete ApplicationMenuItem in my app?
my regards,
Vadim
If you are registering an ApplicationMenuItem from your application, as a user I would consider it bad style for your application to remove and exit, even if RIM provided a way to do this. You may want to separate your application into two parts. One provides the minimal support for responding to the ApplicationMenuItem selection, that starts automatically and runs in the background. The other has all the rest and can run and exit as needed.
My solution for this situation is:
create alternative entry point and run it on app load
register menu in it
do not use runtimeStore

Resources