I am working on IoT project with NXP i.MX7D . In this project I used Google Nearby API to publish data from companion app to the things app . I have followed this project nearby-kotlin . I have followed almost exactly as this repo . but in my case both of my app is publishing is subscribing successfully . Here are my code for two activity first one is companion app's MainActiviy.kt
and second one is for the activity running on the 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()
} }
activty for the app running on things
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()
} }
if you guys need to check the class which has been serialized and deserialized with Gson to send as payload nearmy message this calsses are Calculate & Calculation
this is my Hello world type project for IoT . Help and suggestion is appreciated .
Thanks is advance
The Google Nearby API is proving really tricky to work with. I am having the same problem with it, in my JAVA code, which was working perfectly until today. I created my NearbyManager Class to help automate and clear up the mainline code. Suddenly I'm not able to publish. My publish Success Callback is never fired. Nor do I receive any messages.
Look at your Log, I found out that somehow my API Key was not accepted by Google (I cleared my Log so no snap!), because my SHA1(Android Debug Key) fingerprint had changed (Again, makes no sense to me why, if anyone can explain, I'll be grateful), so I went to my Console and updated my fingerprint. This might have worked, though it's not been very long since I made that change, I'm yet to see results or test.
My code is not a solution to the problem, but is more of a prerequisite I put together to get people started with the Nearby API! We don't have a supporting class as such and I figured this would help anyone starting out! This should help you to find missing pieces in your puzzle! Good luck!
One recommendation I would give is to trace your function calls by placing Log or Toast statements in your function call body. Like inside mMessageListener, publish and subscribe.
plus I didn't read much of your code, but I hope you are programatically checking if publish and subscribe is a success using onSuccessListeners.