【问题标题】:Nearby Message API MessageLisenter is not triggerd附近消息 API 消息侦听器未触发
【发布时间】:2017-12-14 18:22:37
【问题描述】:

我正在使用 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 序列化和反序列化的类以作为有效负载发送到我附近的消息,则此 calsses 是 Calculate 和 Calculation

这是我的物联网 Hello world 类型项目。感谢您的帮助和建议。

谢谢提前

【问题讨论】:

  • 你好像从来没有打电话给mGoogleApiClient.connect()。您可以添加该调用并查看是否收到 onConnected 回调吗?
  • @NickFelker 基本上我遵循了来自谷歌代码示例(github.com/googlesamples/android-nearby/blob/master/messages/…)的代码,那里的代码正在运行。代码中没有 mGoogleApiClient.connect() 。我应该在哪里调用这个函数

标签: android iot android-things google-nearby


【解决方案1】:

事实证明,Google Nearby API 的使用非常棘手。在我的 JAVA 代码中,我遇到了同样的问题,该代码在 今天 之前一直运行良好。我创建了我的 NearbyManager 类来帮助自动化和清理主线代码。突然发不出去。 我的发布成功回调从未被触发。 我也没有收到任何消息。

查看您的 日志,我发现不知何故我的 API 密钥未被 Google 接受(我清除了我的日志,所以没有快照!),因为我的 SHA1(Android Debug Key) 指纹已更改(再次说明,为什么对我来说毫无意义,如果有人能解释,我将不胜感激),所以我去了我的 Console 并更新了我的指纹。这可能行得通,虽然我做出这个改变不久之后,我还没有看到结果或测试。

我的代码不是解决问题的方法,而是我为让人们开始使用 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 以编程方式检查发布和订阅是否成功。

【讨论】:

  • 终于又开始工作了。我尝试了很多东西,直到删除 .setStrategy(Strategy.BLE_ONLY) 让它再次工作。
猜你喜欢
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 2010-12-04
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
相关资源
最近更新 更多