2

我正在为专有蓝牙 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();
    }

}

日志猫:

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)

任何见解都非常感谢!

4

1 回答 1

1

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

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

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 端管理排队。

谢谢大家!

于 2014-07-25T20:32:56.723 回答