Nearby Message API MessageLisenter не срабатывает

Я работаю над проектом IoT с NXP i.MX7D. В этом проекте я использовал Google Nearby API для публикации данных из сопутствующего приложения в приложение Things. Я следил за этим проектом nearby-kotlin. Я почти точно следовал этому репозиторию. но в моем случае оба моих приложения успешно публикуются и подписываются. Вот мой код для двух действий: первое — это приложение-компаньон MainActiviy.kt, а второе — действие, выполняемое на NXP i.MX7D.

class MainActivity : AppCompatActivity(), GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {


/**
 * The entry point to Google Play Services.
 */
private var mGoogleApiClient: GoogleApiClient? = null

/**
 * A [MessageListener] for processing messages from nearby devices.
 */
private var messageListener: MessageListener? = null



/**
 * One minutes.
 */
private val ttlInSeconds = 60 * 3
/**
 * Sets the time in seconds for a published message or a subscription to live. Set to three
 * minutes in this sample.
 */
private val publishSubscriptionStrategy = Strategy.Builder().setTtlSeconds(ttlInSeconds).build()


private val savedInstance = Calculate::class.java.simpleName

private val TAG = MainActivity::class.java.simpleName

private val keyUUID: String = "UUID_KEY"

private lateinit var calculation: Calculate

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    calculation = savedInstanceState?.get(savedInstance) as Calculate? ?:
            Calculate.builder(getUUID(getSharedPreferences(applicationContext.packageName, Context.MODE_PRIVATE)),
                    "0", "0", Operator.OPERATOR_PLUS)

    val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
    binding.calculate = calculation

    setOperatorDrawable(calculation.operator)


    messageListener = object : MessageListener() {
        override fun onFound(message: Message) {
            Calculate.fromMessage(message).toString()
            resultTv.text = calculation.result
        }

        override fun onLost(message: Message) {

        }
    }

    if (mGoogleApiClient != null && mGoogleApiClient!!.isConnected)
        subscriberForMessage()


    fab_plus.setOnClickListener {
        publishMessage()
        calculation.operator = "Plus"
        calculation.operandOne = operandOneET.text.toString()
        calculation.operandTwo = operandTwoET.text.toString()
        setOperatorDrawable(calculation.operator)
    }

    fab_minus.setOnClickListener {
        Log.i(TAG, "minus clicked")
        publishMessage()
        calculation.operator = "Minus"
        calculation.operandOne = operandOneET.text.toString()
        calculation.operandTwo = operandTwoET.text.toString()
        setOperatorDrawable(calculation.operator)
    }

    fab_multiply.setOnClickListener {
        publishMessage()
        calculation.operator = "Multiply"
        calculation.operandOne = operandOneET.text.toString()
        calculation.operandTwo = operandTwoET.text.toString()
        setOperatorDrawable(calculation.operator)
    }

    fab_divide.setOnClickListener {

        if (calculation.operandTwo.equals("0")) {
            Snackbar.make(resultTv, "Divide by zero exception", Snackbar.LENGTH_SHORT).show()

            return@setOnClickListener
        }
        publishMessage()
        calculation.operator = "Divide"
        calculation.operandOne = operandOneET.text.toString()
        calculation.operandTwo = operandTwoET.text.toString()
        setOperatorDrawable(calculation.operator)
    }

    buildGoogleApiClient()
}


private fun setOperatorDrawable(operator: String?) {

    when (operator) {
        "Plus" -> operatorIV.setImageResource(android.R.drawable.ic_input_add)
        "Minus" -> operatorIV.setImageResource(R.drawable.ic_minus_symbol)
        "Multiply" -> operatorIV.setImageResource(R.drawable.ic_multiply)
        else -> operatorIV.setImageResource(R.drawable.ic_divide)
    }
}


private fun getUUID(sharedPreferences: SharedPreferences): String {
    var uuid = sharedPreferences.getString(keyUUID, "")

    if (uuid.isEmpty()) {
        uuid.apply {
            uuid = UUID.randomUUID().toString()
            sharedPreferences.edit().putString(keyUUID, this).apply()
        }
    }

    return uuid
}

override fun onSaveInstanceState(outState: Bundle?) {
    super.onSaveInstanceState(outState)

    outState?.putSerializable(savedInstance, calculation)
}

private fun buildGoogleApiClient() {

    if (mGoogleApiClient != null)
        return


    mGoogleApiClient = GoogleApiClient.Builder(this@MainActivity)
            .addApi(Nearby.MESSAGES_API)
            .addConnectionCallbacks(this@MainActivity)
            .enableAutoManage(this@MainActivity, this@MainActivity)
            .build()
}


/**
 * Publishes a message to nearby devices and updates the UI if the publication either fails or
 * TTLs.
 */
private fun publishMessage() {
    Log.i(TAG, "publishing msg")


    val option: PublishOptions = PublishOptions.Builder().setStrategy(publishSubscriptionStrategy)
            .setCallback(object : PublishCallback() {
                override fun onExpired() {
                    super.onExpired()

                    Log.i(TAG, "Message Publish expired")
                    runOnUiThread { Snackbar.make(resultTv, "Publish expired", Snackbar.LENGTH_SHORT).show() }
                }
            }).build()

    Nearby.Messages.publish(mGoogleApiClient, calculation.toMessage(), option)
            .setResultCallback { status ->
                if (status.isSuccess) {
                    Log.i(TAG, "publishing was successful")
                    Snackbar.make(resultTv, "publishing successful", Snackbar.LENGTH_SHORT).show()
                } else {
                    Snackbar.make(resultTv, "Couldn't publish " + status, Snackbar.LENGTH_SHORT).show()
                }

            }

}

/**
 * Subscribes to messages from nearby devices and updates the UI if the subscription either
 * fails or TTLs.
 */
private fun subscriberForMessage() {
    Log.i(TAG, "Subscribing")

    val option: SubscribeOptions = SubscribeOptions.Builder().setStrategy(publishSubscriptionStrategy)
            .setCallback(object : SubscribeCallback() {
                override fun onExpired() {
                    super.onExpired()

                    Log.i(TAG, "Subscription expired")
                    runOnUiThread { Snackbar.make(resultTv, "Subscription expired", Snackbar.LENGTH_SHORT).show() }
                }
            }).build()

    Nearby.Messages.subscribe(mGoogleApiClient, messageListener, option)
            .setResultCallback { status ->
                if (status.isSuccess) {
                    Log.i(TAG, "subscription was successful")
                    Snackbar.make(resultTv, "Subscription successful", Snackbar.LENGTH_SHORT).show()
                } else {
                    Snackbar.make(resultTv, "Couldn't subscribe " + status, Snackbar.LENGTH_SHORT).show()
                }

            }

}

/**
 * Stops publishing message to nearby devices.
 */
private fun unpublish() {
    Log.i(TAG, "Unpublishing.")
    Nearby.Messages.unpublish(mGoogleApiClient, calculation.toMessage())
}


override fun onConnected(bundle: Bundle?) {
    Log.i(TAG, "GoogleApiClient connected")
    Snackbar.make(resultTv, "GoogleApiClient connected", Snackbar.LENGTH_SHORT).show()

    publishMessage()
    subscriberForMessage()
}

override fun onConnectionSuspended(i: Int) {
    Snackbar.make(resultTv, "Google Api connection Suspended", Snackbar.LENGTH_SHORT).show()
 }

override fun onConnectionFailed(connectionResult: ConnectionResult) {
    Snackbar.make(resultTv, "connection Failed" + connectionResult.errorMessage, Snackbar.LENGTH_SHORT).show()
 } }

активность для приложения, работающего на вещах

class MainActivity : AppCompatActivity(), GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {


/**
 * The entry point to Google Play Services.
 */
private var mGoogleApiClient: GoogleApiClient? = null

/**
 * A [MessageListener] for processing messages from nearby devices.
 */
private var messageListener: MessageListener? = null


/**
 * One minutes.
 */
private val ttlInSeconds = 60 * 3
/**
 * Sets the time in seconds for a published message or a subscription to live. Set to three
 * minutes in this sample.
 */
private val publishSubscriptionStrategy = Strategy.Builder().setTtlSeconds(ttlInSeconds).build()


private val savedInstance = Calculation::class.java.simpleName

private val TAG = MainActivity::class.java.simpleName

private val keyUUID: String = "UUID_KEY"

private lateinit var calculation: Calculation


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    calculation = savedInstanceState?.get(savedInstance) as Calculation? ?:
            Calculation.builder(getUUID(getSharedPreferences(applicationContext.packageName, Context.MODE_PRIVATE)),
                    "0", "0", Operator.OPERATOR_PLUS)

    setOperatorName(calculation.operator)



    messageListener = object : MessageListener() {
        override fun onFound(message: Message) {
            Calculation.fromMessage(message).toString()
            Log.i(TAG , "message found "+calculation.operandOne)
        }

        override fun onLost(message: Message) {
            Log.i(TAG, "message lost " + message)
        }
    }

    checkBox.setOnCheckedChangeListener({ _, isChecked ->
        if (mGoogleApiClient != null && mGoogleApiClient!!.isConnected)
            if (isChecked)
                subscriberForMessage()
            else
                unsubscribe()
    })

    buildGoogleApiClient()

}


private fun setOperatorName(operator: String?) {

    when (operator) {
        "Plus" -> operatorTv.text = "plus"
        "Minus" -> operatorTv.text = "minus"
        "Multiply" -> operatorTv.text = "times"
        else -> operatorTv.text = "divided"
    }
}


private fun getUUID(sharedPreferences: SharedPreferences): String {
    var uuid = sharedPreferences.getString(keyUUID, "")

    if (uuid.isEmpty()) {
        uuid.apply {
            uuid = UUID.randomUUID().toString()
            sharedPreferences.edit().putString(keyUUID, this).apply()
        }
    }

    return uuid
}

override fun onSaveInstanceState(outState: Bundle?) {
    super.onSaveInstanceState(outState)

    outState?.putSerializable(savedInstance, calculation)
}


private fun buildGoogleApiClient() {

    if (mGoogleApiClient != null)
        return


    mGoogleApiClient = GoogleApiClient.Builder(this@MainActivity)
            .addApi(Nearby.MESSAGES_API)
            .addConnectionCallbacks(this@MainActivity)
            .enableAutoManage(this@MainActivity, this@MainActivity)
            .build()


}

/**
 * Publishes a message to nearby devices and updates the UI if the publication either fails or
 * TTLs.
 */
private fun publishMessage() {
    Log.i(TAG, "publishing msg")


    val option: PublishOptions = PublishOptions.Builder().setStrategy(publishSubscriptionStrategy)
            .setCallback(object : PublishCallback() {
                override fun onExpired() {
                    super.onExpired()

                    Log.i(TAG, "Message Publish expired")
                    runOnUiThread { Snackbar.make(resultTv, "Publish expired", Snackbar.LENGTH_SHORT).show() }
                }
            }).build()

    Nearby.Messages.publish(mGoogleApiClient, calculation.toMessage(), option)
            .setResultCallback { status ->
                if (status.isSuccess) {
                    Log.i(TAG, "publishing was successful")
                    Snackbar.make(resultTv, "publishing successful", Snackbar.LENGTH_SHORT).show()
                } else {
                    Snackbar.make(resultTv, "Couldn't publish " + status, Snackbar.LENGTH_SHORT).show()
                }

            }

}

/**
 * Subscribes to messages from nearby devices and updates the UI if the subscription either
 * fails or TTLs.
 */
private fun subscriberForMessage() {
    Log.i(TAG, "Subscribing")


    val option: SubscribeOptions = SubscribeOptions.Builder().setStrategy(publishSubscriptionStrategy)
            .setCallback(object : SubscribeCallback() {
                override fun onExpired() {
                    super.onExpired()

                    Log.i(TAG, "Subscription expired")
                    runOnUiThread {
                        Snackbar.make(resultTv, "Subscription expired", Snackbar.LENGTH_SHORT).show()
                        checkBox.isChecked = false
                    }
                }
            }).build()

    Nearby.Messages.subscribe(mGoogleApiClient, messageListener, option)
            .setResultCallback { status ->
                if (status.isSuccess) {
                    Log.i(TAG, "subscription was successful" + status.statusMessage)
                    Snackbar.make(resultTv, "Subscription successful", Snackbar.LENGTH_SHORT).show()
                } else {
                    Snackbar.make(resultTv, "Couldn't subscribe " + status, Snackbar.LENGTH_SHORT).show()
                }

            }

}

/**
 * Stops publishing message to nearby devices.
 */
private fun unpublish() {
    Log.i(TAG, "Unpublishing.")
    Nearby.Messages.unpublish(mGoogleApiClient, calculation.toMessage())
}

/**
 * Stops subscribing to messages from nearby devices.
 */
private fun unsubscribe() {
    Log.i(TAG, "Unsubscribing.")
    Nearby.Messages.unsubscribe(mGoogleApiClient, messageListener)
}


override fun onConnected(bundle: Bundle?) {
    Log.i(TAG, "GoogleApiClient connected")

    if (checkBox.isChecked)
        subscriberForMessage()

    publishMessage()

    //Snackbar.make(operatorTv, "GoogleApiClient connected", Snackbar.LENGTH_SHORT).show()
}

override fun onConnectionSuspended(i: Int) {
    Log.i(TAG, "GoogleApiClient connection suspended")
    //Snackbar.make(operatorTv, "Google Api connection Suspended", Snackbar.LENGTH_SHORT).show()
}

override fun onConnectionFailed(connectionResult: ConnectionResult) {
    Log.i(TAG, "GoogleApiClient connection failed")
    checkBox.isChecked = false
    //Snackbar.make(operatorTv, "connection Failed" + connectionResult.errorMessage, Snackbar.LENGTH_SHORT).show()
} } 

если вам, ребята, нужно проверить класс, который был сериализован и десериализован с помощью Gson для отправки в качестве полезной нагрузки рядом с моим сообщением, эти классы Рассчитать & Расчет

это мой проект типа Hello world для IoT. Помощь и предложение приветствуются.

Спасибо заранее


person Wubbalubbadubdub    schedule 14.12.2017    source источник
comment
Похоже, вы никогда не звоните mGoogleApiClient.connect(). Можете ли вы добавить этот вызов и посмотреть, получите ли вы обратный вызов onConnected?   -  person Nick Felker    schedule 14.12.2017
comment
@NickFelker в основном я следовал этому коду из образцов кода Google (github.com/googlesamples/android-nearby/blob/master/messages/) там работает код. в коде не было mGoogleApiClient.connect(). где я должен вызвать эту функцию   -  person Wubbalubbadubdub    schedule 14.12.2017


Ответы (1)


С Google Nearby API действительно сложно работать. У меня та же проблема с этим, в моем коде JAVA, который отлично работал до сегодня. Я создал свой класс NearbyManager, чтобы помочь автоматизировать и очистить основной код. Вдруг не смогу опубликовать. Мой обратный вызов об успешном завершении публикации никогда не срабатывает. Я также не получаю никаких сообщений.

Посмотрите на свой Журнал. Я обнаружил, что Google почему-то не принял мой Ключ API (я очистил свой Журнал, так что нет привязки!), потому что мой SHA1( Ключ отладки Android) изменился отпечаток пальца (опять же, мне непонятно почему, если кто-нибудь объяснит, буду признателен), поэтому я зашел в свою Консоль и обновил свой отпечаток . Возможно, это сработало, хотя прошло не так много времени с тех пор, как я внес это изменение, я еще не видел результатов или тестов.

Мой код не является решением проблемы, а скорее необходим для того, чтобы люди могли начать работу с Nearby API! У нас нет класса поддержки как такового, и я подумал, что это поможет всем начинающим! Это должно помочь вам найти недостающие части вашей головоломки! Удачи!

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.nearby.Nearby;
import com.google.android.gms.nearby.messages.Message;
import com.google.android.gms.nearby.messages.MessageListener;
import com.google.android.gms.nearby.messages.MessagesClient;
import com.google.android.gms.nearby.messages.PublishCallback;
import com.google.android.gms.nearby.messages.PublishOptions;
import com.google.android.gms.nearby.messages.Strategy;
import com.google.android.gms.nearby.messages.SubscribeCallback;
import com.google.android.gms.nearby.messages.SubscribeOptions;
import com.google.android.gms.tasks.OnSuccessListener;

public class NearbyManager {
    private boolean isSubscribing = false;
    private boolean isPublishing = false;
    private Activity current;
    private MessagesClient mMessageClient;
    private MessageListener mMessageListener;
    private static final Strategy PUB_STRATEGY = new Strategy.Builder()
            .setTtlSeconds(Strategy.TTL_SECONDS_DEFAULT).build();
    private static final Strategy SUB_STRATEGY = new Strategy.Builder()
            .setTtlSeconds(Strategy.TTL_SECONDS_MAX).build();
    private String mPubMessage;


    public boolean isSubscribing() {
        return isSubscribing;
    }

    public boolean isPublishing() {
        return isPublishing;
    }

    public NearbyManager(Activity activity){
        current = activity;
        PermissionManager.checkPerms(current);
        mMessageClient = Nearby.getMessagesClient(current);
        mMessageListener = new MessageListener(){
            @Override
            public void onFound(Message message) {
                if(message != null){
                    //DO SOMETHING
                    }
                }
            }
            @Override
            public void onLost(Message message) {
                Toast.makeText(current, "Device is lost", Toast.LENGTH_SHORT).show();
            }
        };

    }
    public void publish(final String message){
        mPubMessage = message;
        PublishOptions options = new PublishOptions
                .Builder()
                .setStrategy(PUB_STRATEGY)
                .setCallback(new PublishCallback(){
                    @Override
                    public void onExpired() {
                        super.onExpired();
                        current.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                isPublishing = false;
                            }
                        });
                    }
                })
                //.setStrategy(Strategy.BLE_ONLY) <-- removed this
                .build();
        mMessageClient.publish(new Message(message.getBytes()), options).addOnSuccessListener(current, new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Toast.makeText(current, "Publishing! Message:" + message, Toast.LENGTH_SHORT).show();
            }
        });
        isPublishing = true;
    }
    public void subscribe(){
        SubscribeOptions options = new SubscribeOptions.Builder()
                .setStrategy(SUB_STRATEGY)
                .setCallback(new SubscribeCallback(){
                    @Override
                    public void onExpired() {
                        super.onExpired();
                        Toast.makeText(current, "No longer Subscribing!", Toast.LENGTH_SHORT).show();
                        current.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                isSubscribing = false;
                            }
                        });
                    }
                })
                //.setStrategy(Strategy.BLE_ONLY) <-- removed this
                .build();
        mMessageClient.subscribe(mMessageListener, options).addOnSuccessListener(current, new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Toast.makeText(current, "Subscribing!", Toast.LENGTH_SHORT).show();
            }
        });
        isSubscribing = true;
    }
    public void unsubscribe(){
        if(isSubscribing && mMessageClient != null)
            mMessageClient.unsubscribe(mMessageListener);
        isSubscribing = false;
    }
    public void unpublish(){
        if(isPublishing && mMessageClient != null)
            mMessageClient.unpublish(new Message(mPubMessage.getBytes()));
        isPublishing = false;
    }

}

Одна рекомендация, которую я бы дал, — отслеживать вызовы функций, помещая операторы Log или Toast в тело вызова функции. Как и внутри mMessageListener, публикуйте и подписывайтесь.

плюс я не читал большую часть вашего кода, но я надеюсь, что вы программно проверяете, успешна ли публикация и подписка, используя onSuccessListeners.

person k007sam    schedule 19.10.2018
comment
Наконец-то снова начал работать. Я пробовал много вещей, пока удаление .setStrategy(Strategy.BLE_ONLY) не заставило его снова работать. - person k007sam; 19.10.2018