Nearby Message API MessageLisenter is not triggerd

2019-04-16 06:51发布

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

1条回答
Ridiculous、
2楼-- · 2019-04-16 07:46

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!

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;
    }

}

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.

查看更多
登录 后发表回答