2

Pebble に大量のデータを送信していますが、一部がドロップされ続けています。これの一部は、バッファ サイズが送信するのに十分な大きさではないことが原因であることに気付いたPebbleDictionaryので、代わりに複数の小さなものに分割しました。ただし、これにより、APP_MSG_BUSYエラーが発生するという問題が発生します。

これは、小石からの ack/nack を待っているのではなく、データを連続して送信しているためである可能性があります。したがって、ack/nack ハンドラーとキューを追加しようとしましたがsendMessage()、ack/nack ハンドラーの待機中に関数がメイン UI スレッドをブロックしていたため、それを機能させることができませんでした。

したがって、私の質問は、この特定のインスタンスを処理する最良の方法は何かということAPP_MSG_BUSYです。送信するデータがドロップされることを望まないので、次のデータを送信する前に確認応答を待つか、応答を受信して​​から再送信する必要があります。できればスレッド化は避けたいのですが、スレッド化を伴わない合理的な解決策を思いつきませんでした。

編集: 私の知る限り、pebble コードにバグはありません。正しいキーを使用してデータを要求し、Android アプリから送信されたメッセージを (自動的に) 確認します。

必要に応じて、以下にコードを投稿しました。

現在のコード (Android アプリの関連部分):

public class MainActivity extends ActionBarActivity {

    private PebbleDataReceiver mReceiver;
    private PebbleAckReceiver ackReceiver;
    private PebbleNackReceiver nackReceiver;

    ConcurrentLinkedQueue<BoolDictionary> queue = new ConcurrentLinkedQueue<BoolDictionary>();

    final UUID PEBBLE_APP_UUID = UUID.fromString("2ef1h2ba-1a59-41f7-87da-797beca4d395");
    final static int CONTACTS_NEEDED = 0x0;
    final static int CONTACTS_SIZE = 0x1;
    final static int NEW_MESSAGE = 0x2;
    final static int NEW_CONVERSATION = 0x3;
    final static int RECORD_NEW_MESSAGE = 0x4;

    Thread sendMessages = new Thread(){
        public void run(){

            while (true){
                PebbleKit.sendDataToPebbleWithTransactionId(getApplicationContext(), PEBBLE_APP_UUID, queue.element().getDict(), queue.element().getTransId());

                try {
                    queue.element().wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                }

                if (queue.element().isAkced()){
                    break;
                }
            }

            queue.remove();
            if (queue.size() > 0){
                run();
            }
            else if (queue.size() == 0){
                queue.element().wait();
            }
        }
    };

    public BoolDictionary createBoolDictionary(int key, int data){
        PebbleDictionary dict = new PebbleDictionary();
        dict.addInt32(key, data);
        return new BoolDictionary(dict);
    }

    public BoolDictionary createBoolDictionary(int key, String data){
        PebbleDictionary dict = new PebbleDictionary();
        dict.addString(key, data);
        return new BoolDictionary(dict);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sendMessages.start();

        ackReceiver = new PebbleAckReceiver(PEBBLE_APP_UUID) {
            @Override
            public void receiveAck(Context context, int transactionId) {
                if (queue.element().getTransId() == transactionId){
                    queue.element().setAkced(true);
                    queue.element().notifyAll();
                }               
            }
        };

        nackReceiver = new PebbleNackReceiver(PEBBLE_APP_UUID){
            @Override
            public void receiveNack(Context context, int transactionId) {
                if (queue.element().getTransId() == transactionId){
                    queue.element().setAkced(false);
                    queue.element().notifyAll();
                }
            }           
        };

        mReceiver = new PebbleDataReceiver(PEBBLE_APP_UUID) {
            @Override
            public void receiveData(Context context, int transactionId, PebbleDictionary data) {

                PebbleKit.sendAckToPebble(context, transactionId);

                if (data.contains(CONTACTS_NEEDED)){                    

                    //test data
                    queue.add(createBoolDictionary(0x5, "Entry 1"));
                    queue.add(createBoolDictionary(0x6, "Entry 2"));
                    queue.add(createBoolDictionary(0x7, "Entry 3"));
                    queue.add(createBoolDictionary(0x8, "Entry 4"));
                    queue.add(createBoolDictionary(0x9, "Entry 5"));
                    queue.element().notifyAll();
                }
            }

        };

        PebbleKit.registerReceivedDataHandler(this, mReceiver);
        PebbleKit.registerReceivedAckHandler(this, ackReceiver);
        PebbleKit.registerReceivedNackHandler(this, nackReceiver);
    }

    @Override
    protected void onPause(){
        super.onPause();
        unregisterReceiver(mReceiver);
        unregisterReceiver(ackReceiver);
        unregisterReceiver(nackReceiver);
    }
}

ブール辞書:

public class BoolDictionary extends PebbleDictionary{
    private PebbleDictionary dict;
    private boolean akced = false;
    private int transId;

    BoolDictionary(PebbleDictionary data){
        this.setDict(data);
        setTransId(new Random().nextInt(Integer.MAX_VALUE));
    }

    [insert getters and setters here]
}

次のエラーが生成されます。

07-01 10:43:06.096: E/AndroidRuntime(21941): FATAL EXCEPTION: Thread-5310
07-01 10:43:06.096: E/AndroidRuntime(21941): Process: com.example.firstapp, PID: 21941
07-01 10:43:06.096: E/AndroidRuntime(21941): java.util.NoSuchElementException
07-01 10:43:06.096: E/AndroidRuntime(21941):    at java.util.AbstractQueue.element(AbstractQueue.java:107)
07-01 10:43:06.096: E/AndroidRuntime(21941):    at com.example.firstapp.MainActivity$1.run(MainActivity.java:366)
4

1 に答える 1

2

Pebble が新しいパケットを受信すると、エラーAPP_MSG_BUSYが返されますが、アプリがまだ読み取る時間がないというメッセージが Bluetooth バッファーに既に存在します。

これを理解するには、Pebble のメモリが不足していることを覚えておく必要があります。そのため、システムは着信メッセージをバッファリングできません。代わりに、メッセージを拒否します。

この問題を回避する最善の方法は、Pebble からの ACK/NACK を待ってから別のメッセージを送信することです。すでにそれを行っているようですが、別のヒントは、キーごとに1つのメッセージを送信するのではなく、複数のキーを1つのメッセージにグループ化することです(これにより、受信バッファーの使用が最大になりますが、もちろん制限はそのバッファーのサイズです) )。

于 2014-07-07T21:09:13.797 に答える