上下文dispatchStatusEventAsync抛出IllegalArgumentException

时间:2014-07-17 15:02:44

标签: android bluetooth air bluetooth-lowenergy ane

我正在创建一个与专有蓝牙LE设备的Android SDK连接的ANE。 SDK已经在纯Android项目上进行了测试,并且工作正常。我正在使用FREContext.dispatchStatusEventAsync返回有关检测到的每个信标的信息。但是,在AIR应用程序运行时观察从LogCat返回的日志时,我发现每次找到信标时都会抛出IllegalArgumentException。有趣的是,我可以在其他任何地方使用dispatchStatusEventAsync,它似乎工作正常。

以下是ANE的所有相关代码。 (我通过执行查找/替换来掩盖SDK的名称,但代码编译,所以如果对类或函数的命名有些疯狂,请不要认为它是一个可能的问题。)

" DUMMY"语句只是表明它们是用于调试的。

BecsterExtension.java

public class BecsterExtension implements FREExtension 
{
    public static final String TAG = "BecsterExtension";

    @Override
    public FREContext createContext(String arg0) 
    {
        return new BecsterContext();
    }

    @Override
    public void dispose() 
    {
        // TODO Auto-generated method stub

    }

    @Override
    public void initialize() 
    {
        // TODO Auto-generated method stub

    }

}

BecContext.java

public class BecContext extends FREContext {

@Override
public void dispose() 
{
    // TODO Auto-generated method stub

}

@Override
public Map<String, FREFunction> getFunctions() 
{
    Map<String, FREFunction> functionMap = new HashMap<String, FREFunction>();
    functionMap.put("startScanning", new StartScanFunction());
    return functionMap;
}

}

StartScanFunction.java

private final static String TAG = StartScanFunction.class.getSimpleName();

byte[] advPacket;

public BecsterBeacon becBecMgr; 

@Override
public FREObject call(FREContext context, FREObject[] args) 
{

    //****-----BECSTER SDK START-----****//

    Log.i(TAG, "**Initializing Becster SDK**");

    //this call works
    context.dispatchStatusEventAsync("BECSTER_DUMMY", "Becster SDK has started initalizing");

    if (!context.getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) 
    {
        Log.e(TAG, "Bluetooth LE not supported or disabled");
        return null;
    }

    // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
    // BluetoothAdapter through BluetoothManager.
    final BluetoothManager bluetoothManager =
            (BluetoothManager) context.getActivity().getSystemService(Context.BLUETOOTH_SERVICE);

    Log.i(TAG, "Starting Becster Beacon Manager");

    becBecMgr = new BecsterBeacon(bluetoothManager, new BecNotifyHandler(context));

    Log.i(TAG, "**Becster SDK Initialized**");

    //this call works
    context.dispatchStatusEventAsync("BECSTER_DUMMY", "Becster SDK has finished initalizing");

    BecBecMgr.startLEScan();

    return null;
}

BecNotifyHandler.java(这实现了BecEvent的功能becsterEventNotify,它是从内部调用的

public static final String TAG = "BecNotifyHandler"; 

private FREContext context;

public BecNotifyHandler(FREContext context)
{
    context.dispatchStatusEventAsync("BECSTER_DUMMY", "BecNotifyHandler has been initialized");
    this.context = context;
}

@Override
public void becsterEventNotify(BecPkt event) 
{
    try
    {
        Log.i(TAG, "Notifying of Becster event. Context: " + context);

        //this call ALWAYS throws the IllegalArgumentException
        context.dispatchStatusEventAsync("BECSTER_NOTIFY", "Becster notify");
        Log.i(TAG, "Notified");
    }
    catch (IllegalArgumentException e)
    {
        e.printStackTrace();
    }

}

logcat的:

07-17 10:50:33.949: I/BecNotifyHandler(17467): Notifying of Becster event. Context: com.company.sdk.BecsterContext@41e2df30
07-17 10:50:33.949: W/System.err(17467): java.lang.IllegalArgumentException
07-17 10:50:33.949: W/System.err(17467):    at com.adobe.fre.FREContext.dispatchStatusEventAsync(Native Method)
07-17 10:50:33.949: W/System.err(17467):    at com.company.sdk.BecNotifyHandler.becsterEventNotify(BecNotifyHandler.java:27)
07-17 10:50:33.949: W/System.err(17467):    at com.becster.becsterSDK.BecsterBeacon$1$1.run(BecsterBeacon.java:280)
07-17 10:50:33.949: W/System.err(17467):    at android.os.Handler.handleCallback(Handler.java:733)
07-17 10:50:33.949: W/System.err(17467):    at android.os.Handler.dispatchMessage(Handler.java:95)
07-17 10:50:33.949: W/System.err(17467):    at android.os.Looper.loop(Looper.java:136)
07-17 10:50:33.949: W/System.err(17467):    at android.app.ActivityThread.main(ActivityThread.java:5141)
07-17 10:50:33.949: W/System.err(17467):    at java.lang.reflect.Method.invokeNative(Native Method)
07-17 10:50:33.957: W/System.err(17467):    at java.lang.reflect.Method.invoke(Method.java:515)
07-17 10:50:33.957: W/System.err(17467):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
07-17 10:50:33.957: W/System.err(17467):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:611)
07-17 10:50:33.957: W/System.err(17467):    at dalvik.system.NativeStart.main(Native Method)

非常感谢任何见解!

1 个答案:

答案 0 :(得分:1)

context.dispatchStatusEventAsync继续产生一些非常奇怪的结果。当我调用becsterEventNotify一次时,我会收到正确的消息。两次背靠背调用becsterEventNotify没有发送任何消息。因此,我仍然不确定导致问题的原因。我怀疑线程可能存在问题,因为我一度使用Thread.sleep(1000)来查看在消息之间放一些时间是否有帮助,但这并没有导致任何消息被发送。

如果有人好奇,我确实想出了一个解决方法。我创建了一个静态的字符串Vector来保存来自信标的数据(id,电池寿命和rssi),而不是使用dispatchStatusEventAsync。

public static Vector<String> packets = new Vector<String>();

然后将此gem添加为函数:

public class GetNextPacketFunction implements FREFunction 
{
private static final String TAG = GetNextPacketFunction.class.getSimpleName();

@Override
public FREObject call(FREContext context, FREObject[] args) 
{
    Vector<String> packets = BecsterExtension.packets;

    if (packets != null && packets.size() > 0)
    {
        String nextPacket = packets.remove(packets.size() - 1);
        Log.i(TAG, "Found packet: " + nextPacket);
        try 
        {
            return FREObject.newObject(nextPacket);
        } 
        catch (FREWrongThreadException e) 
        {
            Log.e(TAG, "WRONG THREAD!");
            e.printStackTrace();
        }
    }

    return null;
}

}

然后我实现了这样的通知程序,以便在数据包进入时保存:

@Override
public void becsterEventNotify(BecPkt event) 
{

    String newPacket = btIDStr + ";" + event.getBattVal() + ";" + event.getRssiVal();
    BecsterExtension.packets.add(newPacket);

    Log.i(TAG, "Number of packets in queue: " + BecsterExtension.packets.size());

}

然后在AS端,我使用Timer每秒轮询一次新的数据包(尚未确定这是否是最佳间隔):

            var packetTimer:Timer = new Timer(1000);
            packetTimer.addEventListener(TimerEvent.TIMER, function (e:TimerEvent):void
            {
                var newPacket:String = getNextPacket();

                if (newPacket != null)
                {
                    var data:Array = newPacket.split(";");

                    var becEvent:BecEvent = new BecEvent(BecEvent.NOTIFY);
                    becEvent.id = data[0];
                    becEvent.battLife = data[1];
                    becEvent.rssi = data[2];
                    dispatchEvent(becEvent);
                }
            });

            packetTimer.start();

这种方法目前运作良好,我更喜欢它,因为我可以管理AS端的排队。

全部谢谢!