Android Wear Message API unknown error code 4004 - android

I have the following block of code to sent a message to my device, but the message is not getting sent... I do not have any idea why...
Here is the code in which I build my GoogleApiClient:
mClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(new ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.d("dirk", "Google API Client connected");
sendMessage();
}
#Override
public void onConnectionSuspended(int cause) {
Log.d("dirk", "Google API Client disconnected, cause: " + cause);
mConnected = false;
mConnecting = false;
// TODO handle disconnect
}
})
.addOnConnectionFailedListener(new OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.d("dirk", "Google API Client connection failed, reason: " + result);
mConnected = false;
mConnecting = false;
// TODO handle connection failure
}
})
.addApi(Wearable.API)
.build();
And here is my code that is getting called from the sendMessage method:
Wearable.MessageApi.sendMessage(getClient(), nodeId, PATH, null).setResultCallback(new ResultCallback<SendMessageResult>() {
#Override
public void onResult(SendMessageResult sendMessageResult) {
if (!sendMessageResult.getStatus().isSuccess()) {
Log.d("dirk", "message could not be sent: " + sendMessageResult.getStatus().toString());
Log.d("dirk", "Client connected: " + getClient().isConnected());
// TODO show communication error
}
}
});
The logging is here:
Google API Client connected
message could not be sent: Status{statusCode=unknown status code: 4004, resolution=null}
Client connected: true
So all conditions seem to be fine, but the unknown error code 4004 cannot be resolved (at least I did not find anything wrong so far).
Anyone an idea what could be the reason of this?
Dirk

I've found a documentation that supports my previous assumptions from comment above. Please take a look at WearableStatusCodes class - it contains status codes used in WearableApi method results.
https://developer.android.com/reference/com/google/android/gms/wearable/WearableStatusCodes.html#INVALID_TARGET_NODE
So this error is no longer "unknown":) - 4004 is a code for INVALID_TARGET_NODE.
Please check what value you pass in nodeId variable.

Related

How to resolve STATUS_OUT_OF_ORDER_API_CALL error?

I am trying to create a Nearby app. I am trying to connect two devices. I found a device an endpoint and then I send a connection request with requestConnection method of Nearby API. In failure listener of this API I am getting "STATUS_OUT_OF_ORDER_API_CALL" in error message. What can be the possible reasons for this error, and how to handle it.
Nearby.getConnectionsClient(context)
.requestConnection(myEndPointName, endPointID,
discoverConnectionLifecycleCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "start connection onSuccess");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG, "start connection onFailure " + e.getLocalizedMessage());
// here I am getting STATUS_OUT_OF_ORDER_API_CALL in error message
}
});
POINT_TO_POINT only allows one connection at a time (either incoming or outgoing, not both). OUT_OF_ORDER is given if you try to connect to someone else without first disconnecting from the existing connection.

GoogleApiClient Node is null

I'm writing an Android Wear app and I want to make the wear device start an intent on the phone when a button is clicked.
To do this, I've first set up the connection to the GoogleApiClient like this
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
googleApiClient.connect();
Then on button click the function sendMessage is run. This is the function
private void sendMessage(){
if(mNode != null && googleApiClient != null && googleApiClient.isConnected()){
Wearable.MessageApi.sendMessage(
googleApiClient, mNode.getId(),HELLO_WORLD_WEAR_PATH, null).setResultCallback(
new ResultCallback<MessageApi.SendMessageResult>() {
#Override
public void onResult(MessageApi.SendMessageResult sendMessageResult) {
if(!sendMessageResult.getStatus().isSuccess()){
Log.e("TAG", "Failed to send message with status code: " + sendMessageResult.getStatus().getStatusCode());
}
else{
Log.e("TAG", "Success");
}
}
}
);
}
else {
Log.e("TAG","No nodes" + mNode);
}
}
The problem is that the function goes into the else statement of sendMessage which means mNode is null. mNode is a variable of type Node.
To get the node, I have this function
private void resolveNode() {
Wearable.NodeApi.getConnectedNodes(googleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
#Override
public void onResult(NodeApi.GetConnectedNodesResult nodes) {
for (Node node : nodes.getNodes()) {
mNode = node;
}
}
});
}
I've connected my phone with the Android Wear Virtual Device in Android Studio.
What am I doing wrong here?
When you call googleApiClient.connect(), the connection takes a short amount of time and this call does not block. So you need to wait until the connection succeeds with a call to onConnected() before you do any further calls.
Next, when you call resolveNode(), the mNode variable is not set instantly. The setResultCallback is executed a short time later, and so you should not call sendMessage() until the result is processed.
So you need to ensure proper ordering for everything here.
(Edit)
After going through the comments, it turns out the problem was caused by the connection to Google Play Services failing. This was because the emulator used was an old API 20 device, which has an old version of Google Play Services. Using the latest API 22 emulator will resolve the issue.
try with this to get Node
new Thread(new Runnable() {
#Override
public void run() {
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
for (Node node : nodes.getNodes()){
MessageApi.SendMessageResult resultMessage = Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), ID_PATH, BYTES HERE).await();
if (resultMessage.getRequestId() == MessageApi.UNKNOWN_REQUEST_ID) {
Log.e("Message failed", ".......");
}
}
}
}).start();

XMPP “stream:error (conflict)” when try to reconnect or login

I am using Smack and Openfire server for a chat client, all things working well like chat, sending an invitation for a new addition of user, getting list of available users etc. I don't have a clue what to do if the connection is in a Sticky Service and I added a connection listener to the connection and connection disconnected, let's say for "Internet Connection"
I am using the below code for the connectionlistener.
connection.addConnectionListener(new ConnectionListener() {
#Override
public void reconnectionSuccessful() {
Log.i("","Successfully reconnected to the XMPP server.");
}
#Override
public void reconnectionFailed(Exception arg0) {
Log.i("","Failed to reconnect to the XMPP server.");
}
#Override
public void reconnectingIn(int seconds) {
Log.i("","Reconnecting in " + seconds + " seconds.");
}
#Override
public void connectionClosedOnError(Exception arg0) {
Log.i("","Connection to XMPP server was lost.");
Log.v("ONMESSAGE", "Error was " + arg0.toString() + "and Now connecting");
}
#Override
public void connectionClosed() {
Log.i("","XMPP connection was closed.");
}
});
So I thought of adding two lines of code to connectionClosedOnError() i.e
connection.disconnect(new Presence(Presence.Type.unavailable));
//code for connection(new one)
Which gives me some time following error
No Response from Server.
Not connected to server.
conflict error
Now I researched on the issue and found there is still connection when I try to reconnect using the same resource so I got the errors. My question is how to do reconnection and what is the correct procedure for that?
I know how to resolve the issue "XMPP “stream:error (conflict)” as I can provide a String to login() method as a third parameter and it resolves the issue.
That is not my main concern, what I want to know the procedure of reconnection. I tried logging in all methods and it's quite amazing that there are no order of methods being called.

What happened to Packet.setProperty() in (a)Smack 4.0?

Hi i am recently converting from aSmack 3.X to aSmack 4.0. In aSmack 4.0 it seems that the Packet.setProperty() method has been removed. Is there any documentation or examples of how to get this setting to the packet back in aSmack 4.0 as my system relies heavily on aSmack properties.
Thank you in advance.
Those methods where moved out of smack-core into smack-extensions with Smack 4. You now need to use JivePropertiesManager.getProperty(Packet, String) and JivePropertiesManager.addProperty(Packet, String) to add and get those.
More info about the API changes from Smack 3 to Smack 4 can be found at the official "Smack 4.0 Readme and Upgrade Guide".
This is an upgrade of my last FCM XMPP Connection Server application. Now, this project uses the latest version at this time of the Smack library (4.1.8).
https://github.com/carlosCharz/fcmxmppserverv2
This is my sample java project to showcase the Firebase Cloud Messaging (FCM) XMPP Connection Server. This server sends data to a client app via the FCM CCS Server using the XMPP protocol.
https://github.com/carlosCharz/fcmxmppserver
And also I've created a video in youtube where I explain what the changes are.
https://www.youtube.com/watch?v=KVKEj6PeLTc
Hope you find it useful.
Here is a code snippet for the implementation:
public class CcsClient implements StanzaListener {
//Other code
public void connect() throws XMPPException, SmackException, IOException {
XMPPTCPConnection.setUseStreamManagementResumptionDefault(true);
XMPPTCPConnection.setUseStreamManagementDefault(true);
XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration.builder();
config.setServiceName("FCM XMPP Client Connection Server");
config.setHost(Util.FCM_SERVER);
config.setPort(Util.FCM_PORT);
config.setSecurityMode(SecurityMode.ifpossible);
config.setSendPresence(false);
config.setSocketFactory(SSLSocketFactory.getDefault());
// Launch a window with info about packets sent and received
config.setDebuggerEnabled(mDebuggable);
// Create the connection
connection = new XMPPTCPConnection(config.build());
// Connect
connection.connect();
// Enable automatic reconnection
ReconnectionManager.getInstanceFor(connection).enableAutomaticReconnection();
// Handle reconnection and connection errors
connection.addConnectionListener(new ConnectionListener() {
#Override
public void reconnectionSuccessful() {
logger.log(Level.INFO, "Reconnection successful ...");
// TODO: handle the reconnecting successful
}
#Override
public void reconnectionFailed(Exception e) {
logger.log(Level.INFO, "Reconnection failed: ", e.getMessage());
// TODO: handle the reconnection failed
}
#Override
public void reconnectingIn(int seconds) {
logger.log(Level.INFO, "Reconnecting in %d secs", seconds);
// TODO: handle the reconnecting in
}
#Override
public void connectionClosedOnError(Exception e) {
logger.log(Level.INFO, "Connection closed on error");
// TODO: handle the connection closed on error
}
#Override
public void connectionClosed() {
logger.log(Level.INFO, "Connection closed");
// TODO: handle the connection closed
}
#Override
public void authenticated(XMPPConnection arg0, boolean arg1) {
logger.log(Level.INFO, "User authenticated");
// TODO: handle the authentication
}
#Override
public void connected(XMPPConnection arg0) {
logger.log(Level.INFO, "Connection established");
// TODO: handle the connection
}
});
// Handle incoming packets (the class implements the StanzaListener)
connection.addAsyncStanzaListener(this,
stanza -> stanza.hasExtension(Util.FCM_ELEMENT_NAME, Util.FCM_NAMESPACE));
// Log all outgoing packets
connection.addPacketInterceptor(stanza -> logger.log(Level.INFO, "Sent: {}", stanza.toXML()), stanza -> true);
connection.login(fcmServerUsername, mApiKey);
logger.log(Level.INFO, "Logged in: " + fcmServerUsername);
}\
}

What Payload to send to the Chromecast Default Media Receiver via Cast.CastApi.sendMessage

I have been trying to build a little test application that sends data from an android app (sender) to my chromecast. I am using the Default Media Receiver to avoid paying for registration while I learn.
All the code is implemented in an service, the receiver is found and ready but i don't know how to format the payload to actually get the Media Receiver to do anything (display images for example)
Here is a bit of code (if more is needed I gladly post it). The onConnected() method is called and runs without errors, the receiver is connected and ready, showing the chromecast symbol but the picture of which I send the URL is not shown.
private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks
{
#Override
public void onConnected(Bundle bundle)
{
Log.d(TAG, "on connected for callback");
Cast.CastApi.launchApplication(mApiClient,
CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID, false)
.setResultCallback(new ResultCallback<Cast.ApplicationConnectionResult>()
{
#Override
public void onResult(Cast.ApplicationConnectionResult result)
{
Log.d(TAG, "OnResultCallback... ");
Status status = result.getStatus();
Log.d(TAG, "ApplicationConnectionResultCallback.onResult: statusCode" + status.getStatusCode());
if (status.isSuccess())
{
mApplicationStarted=true;
ApplicationMetadata applicationMetadata = result.getApplicationMetadata();
mSessionId = result.getSessionId();
String applicationStatus = result.getApplicationStatus();
boolean wasLaunched = result.getWasLaunched();
Log.d(TAG, mSessionId+" "+applicationStatus);
try
{
Cast.CastApi.sendMessage(mApiClient, "urn:x-cast:com.google.cast.media",
"http://www.randomwebsite.com/images/head.jpg")
.setResultCallback(new ResultCallback<Status>()
{
#Override
public void onResult(Status result)
{
if (!result.isSuccess())
{
Log.e(TAG, "Sending message failed");
}
}
});
}
catch(Exception e)
{
Log.e(TAG, "Sending message to chromecast failed... hard.");
}
}
}
});
}
#Override
public void onConnectionSuspended(int i)
{
Log.d(TAG, "on connection suspended for callback");
}
}
This and most of the code is similar to the https://github.com/googlecast/CastHelloText-android example from google.
My problem, I think is the line Cast.CastApi.sendMessage(mApiClient, "urn:x-cast:com.google.cast.media", "http://www.randomwebsite.com/images/head.jpg") especially the third parameter which i suspect just isn't formatted the way the Default Media Receiver expects data. However I could not find any working examples on this.
So, how does one get a working example using the Default Media Receiver to run?
If you want to send you own messages (non-media), you should create a custom receiver with your own namespace. The Default Receiver/Styled Receiver only understands media namespace and to use that namespace, do not use sendMessage; use RemoteMediaPlayer to send common actions like play/pause/stop/seek/... There are some samples on our GitHub repo.

Categories

Resources