Can somebody explain the error messages that can be passed into the callbacks i.e.
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode)
I've seen error code 3 before but have no idea what it means. The documentation seems flakey at best...
Cheers,
I worked around this by calling resolveService again. It may fail a couple of times in a row, but eventually resolves.
#Override
public void onServiceFound(NsdServiceInfo serviceInfo) {
Log.d(TAG, "Service found: "+ serviceInfo);
if (!serviceInfo.getServiceType().equals(SERVICE_TYPE)){
Log.d(TAG, "Unknown service type: " + serviceInfo.getServiceType());
} else if (serviceInfo.getServiceName().equals(mServiceName)){
Log.d(TAG, "Same machine");
} else {
startResolveService(serviceInfo);
}
}
Rather than call resolveService from within onServiceFound, I call a separate declaration of it:
private void startResolveService(NsdServiceInfo serviceInfo){
NsdManager.ResolveListener newResolveListener = new NsdManager.ResolveListener() {
#Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.e(TAG, "Resolve Failed: " + serviceInfo + "\tError Code: " + errorCode);
switch (errorCode) {
case NsdManager.FAILURE_ALREADY_ACTIVE:
Log.e(TAG, "FAILURE_ALREADY_ACTIVE");
// Just try again...
startResolveService(serviceInfo);
break;
case NsdManager.FAILURE_INTERNAL_ERROR:
Log.e(TAG, "FAILURE_INTERNAL_ERROR");
break;
case NsdManager.FAILURE_MAX_LIMIT:
Log.e(TAG, "FAILURE_MAX_LIMIT");
break;
}
}
#Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
Log.i(TAG, "Service Resolved: " + serviceInfo);
mLocatedServices.add(serviceInfo);
reportNewService();
}
};
mNsdManager.resolveService(serviceInfo, newResolveListener);
}
When multiple services are discovered nearly-instantaneously, the first one gets resolved, then you get FAILURE_ALREADY_ACTIVE once or twice more, then the next service gets resolved, and so on.
Had the same question and got the answer from NsdManager sources:
/**
* Failures are passed with {#link RegistrationListener#onRegistrationFailed},
* {#link RegistrationListener#onUnregistrationFailed},
* {#link DiscoveryListener#onStartDiscoveryFailed},
* {#link DiscoveryListener#onStopDiscoveryFailed} or {#link ResolveListener#onResolveFailed}.
*
* Indicates that the operation failed due to an internal error.
*/
public static final int FAILURE_INTERNAL_ERROR = 0;
/**
* Indicates that the operation failed because it is already active.
*/
public static final int FAILURE_ALREADY_ACTIVE = 3;
/**
* Indicates that the operation failed because the maximum outstanding
* requests from the applications have reached.
*/
public static final int FAILURE_MAX_LIMIT = 4;
edited:
Actually it is mentioned in developer documentation:
http://developer.android.com/reference/android/net/nsd/NsdManager.html
I was a bit confused by this also...
Here's what's happening. When you are discovering services, you will often get the exact same service a few times in the same millisecond.
if you log the output from NsdManager.DiscoveryListener.onServiceFound(NsdServiceInfo service) you'll see this.
Now, you probably resolve the service using mNsdManager.resolveService(service, mResolveListener). Only the first attempt is going to start resolving, the others will give FAILURE_ALREADY_ACTIVE. (At least until the first is completed)
I met this problem two days....and i solve it...
first time i do resolveService(service, mResolveListener);
no callback
and i do again same service, resolveService(service, mResolveListener);
the callback is error code 3
At least I found ,because my server name is "III...."
I take out double quotes and it's work
hope it's can help you.
I found that reusing the same listener with a semaphore gave the best result.
if (semaphore.tryAcquire()) {
mNsdManager.resolveService(service, resolveListener);
}
Using tryAcquire as we do not wan't to block onServiceFound which will lock it completely. With this approach we eventually get all services on the network to show up.
Related
I know similar questions are asked but the answers didn't work for me. I tried this answer but it throws null pointer exception. I also saw this answer but WifiP2pManager does not have any property or method that returns device name.
Can anyone please help?
I basically want to show user their device name and let them change it if they want to set custom name.
Thanks.
If you're still looking for the answer, here's how:
Identify own device name
This becomes available upon receiving the WIFI_P2P_THIS_DEVICE_CHANGED_ACTION intent in your broadcast receiver. Simply use the deviceName member variable like so:
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
WifiP2pDevice self = (WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
// Now self.deviceName gives you own device name
} else if(WifiP2pManager.WIFI_P2P...) {
...
2. Change own device name
There's no method to change the device name using the WifiP2pManager as per the develper docs, and although a public setDeviceName() method exists in the source code, you can't call it on your object (probably to keep devs from calling it on an object representing a nearby peer device). What worked for me was to obtain a Method object representing said method and invoking it on my WifiP2pManager instance:
private WifiP2pManager manager;
private WifiP2pManager.Channel channel;
...
public void changeDeviceName(String deviceNewName) {
try {
Method method = manager.getClass().getMethod("setDeviceName", WifiP2pManager.Channel.class, String.class, WifiP2pManager.ActionListener.class);
method.invoke(manager, channel, deviceNewName, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(MainActivity.this, "Name successfully changed", Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(int reason) {
Toast.makeText(MainActivity.this, "Request failed: " + reason, Toast.LENGTH_SHORT).show();
Log.d(TAG, "Name change failed: " + reason);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
Alternatively, users can rename their device manually from the advanced WiFi settings (Preferences > Advanced > WiFi Direct > Configure Device),
EDIT: Starting with Pie, use of non-SDK interfaces (essentially classes, variables or methods marked with #hide, which you access using reflection) is being restricted and will eventually be disallowed. The above method is currently greylisted (which means support for reflecting it might be removed in the future). Read up more here: https://developer.android.com/distribute/best-practices/develop/restrictions-non-sdk-interfaces
Well, my RouteListener sometimes return ROUTING_CANCELLED. I look in documentation and it's says: "An application user cancelled the calculation."
RouteListener
private class RouteListener implements RouteManager.Listener {
// Method defined in Listener
public void onProgress(int percentage) {
// Display a message indicating calculation progress
}
// Method defined in Listener
public void onCalculateRouteFinished(RouteManager.Error error, List<RouteResult> routeResult) {
if (error == RouteManager.Error.NONE) {
// Logic here
} else {
Toast.makeText(context, "Calc error: " + error.name(), Toast.LENGTH_LONG).show();
}
}
}
How to avoid this error? I'm lost x_x ~. Are something in my phone irregular?
Obs: Internet, GPS, battery and cpu are fine.
Aggregating answer from the comments.
Reverse Geocoding in here maps only work after MapEngine initialization. Calling the Reverse Geocoding before the MapEngine initialization will trigger a ROUTE_CANCELLED error.
I am using Android SIP API to create my sip client and FREE PBX for sip server. But I am facing this issue, while calling to some extension, if this user is not registered to server, it gives me the error response in 8 seconds. Here is my code.
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is
// established.
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
if (call.isMuted())
call.toggleMute();
updateStatus("call established.");
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("call ended.");
}
#Override
public void onError(SipAudioCall call, int errorCode,
String errorMessage) {
delay = System.currentTimeMillis() - delay;
delay = delay / 1000;
Log.v("", "call failed: time taken in decision is " + delay
+ " seconds.");
endCall(call);
makeGsmCall(numberString);
super.onError(call, errorCode, errorMessage);
}
};
delay=System.currentTimeMillies();
SipState.sipAudioCall = SipState.sipManager.makeAudioCall(SipState.localSipProfile.getUriString(), sipAddress,
listener, 0);
In this code, the onError(), method is called after 8 seconds. Can we minimize that? Or if there is some other method we could achieve that?
Also I have seen other applications like sipdroid and linephone, they seem to take no time to tell that specified username is unavailable.
Please help me. Thanks.
When your SIP registers it sends acknowledgement. If it is fine. the response you will get will be "Ready" otherwise it will give you an errorCode which can be seen at this page
https://stuff.mit.edu/afs/sipb/project/android/OldFiles/docs/reference/android/net/sip/SipErrorCode.html
By refering to this you can see what error you are getting. Also there is a string for Error Message. you can save that in string and then show on UI.
Hope this helps
With Google Play Game Services, I'm trying to implement a CallBack such that, if there is an issue with sending a message, then I need to resolve it (as each player "passes" their bid to the next player, and all other players need to see what the player that passed bid)
I thought I would try and use the following to instantiate a RealTimeReliableMessageSentListener for that round of messages, so that I can tell if the message was sent and received by everyone:
(I add the tokenID returned by the call to an ArrayList, and then check off remove each tokenID as it comes back in to track when all messages from this round are received)
#Override
public void sendReadyToPlay() {
dLog("Sending ReadyToPlay");
// Broadcast that I'm ready, and see that they are ready
if (!mMultiplayer){
return; // playing against computer
}
// First byte in message indicates whether it's a final score or not
mMsgBuf[0] = (byte) ('R');
readyToPlayTokens.clear();
// Send to every other participant.
for (Participant p : mParticipants) {
dLog("Participant:" + p.getParticipantId());
if (p.getParticipantId().equals(mMyId)) {
continue;}
if (p.getStatus() != Participant.STATUS_JOINED){
continue;
}
readyToPlayTokens.add(mHelper.getGamesClient().sendReliableRealTimeMessage(new RealTimeReliableMessageSentListener() {
#Override
public void onRealTimeMessageSent(int statusCode, int tokenId, String recipientParticipantId){
dLog("onRealTimeMessageSent number two and size is: " + readyToPlayTokens.size());
if(readyToPlayTokens.contains(tokenId)){
readyToPlayTokens.remove(tokenId);
}
dLog("onRealTimeMessageSent number two and size is: " + readyToPlayTokens.size());
if (statusCode != GamesClient.STATUS_OK) {
mGHInterface.onRealTimeMessageReceived("RTPProblem:" + recipientParticipantId);
} else if (readyToPlayTokens.size() == 0) {
mGHInterface.beginRound();
}
}
}, mMsgBuf, mRoomId, p.getParticipantId()));
dLog("sent to:" + p.getParticipantId());
}
}
I can see the messages coming in almost every time from one device to another, so I can see that the messages are going through, BUT, the RealTimeReliableMessageSent listener is only being fired about 50-60 percent of the time, which isn't very reliable! :)
Can anyone see what I might be doing wrong to keep the listener from firing reliably?
may be it happens because you are using anonymous inner class, try to use in different way like implementing your activity RealTimeReliableMessageSentListener
I'm very new to OpenFeint, actually started integrating it into my game today. I can't understand one simple thing that every OpenFeint using developer should probably know. Here's the example of unlocking an achievement from OpenFeint official tutorial:
new Achievement("achievementID").unlock(new Achievement.UnlockCB () {
#Override public void onSuccess() {
MyClass.this.setResult(Activity.RESULT_OK);
MyClass.this.finish();
}
#Override public void onFailure(String exceptionMessage) {
Toast.makeText( MyClass.this,
"Error (" + exceptionMessage + ") unlocking achievement.",
Toast.LENGTH_SHORT).show();
MyClass.this.setResult(Activity.RESULT_CANCELED);
MyClass.this.finish();
}
});
Problem is that I don't want to finish my activity in onSuccess or onFailure, I just don't need to do anything here. If I just leave these two methods codeless, my game freezes an becomes totally unresponsive. What should I do? Thanks in advance.
P.S. How do you create Test Users? I've tryed every email-password combination possible and could not get it to go..
Its generally a good idea to put all your communication with the internet in a AsyncTask. Not everyone has fast internet, so this will make sure the main thread doesn't lock up because of that.
That being said, I think that the setResult function is used in a startActivityForResult construction. The intent that is created in this way is only sent back to the original class if the activity is finished. So to fix this you would need to put the code in a separate activity.
I simply wrote this method in my Utility class
public static void unlockAchievement(final String achievementId, final Activity context){
final Achievement achievement = new Achievement(achievementId);
achievement.unlock(new Achievement.UnlockCB() {
#Override
public void onSuccess(boolean newUnlock) {
context.setResult(Activity.RESULT_OK);
}
#Override
public void onFailure(String exceptionMessage) {
context.setResult(Activity.RESULT_CANCELED);
Toast.makeText(context, "Error (" + exceptionMessage + ") unlocking achievement.", Toast.LENGTH_SHORT).show();
FlurryAgent.onError("unlockingAchievement", exceptionMessage, this.getClass().getSimpleName());
}
});
}