Unity: Google Play Games crashes on login - unity3d

I'm trying to save a variable using google play games cloud save. However it crashes when it signs in. I've definitely enabled it on the developer console. I never had this problem before I added the cloud save feature and it was just doing achievements and scoreboards. Also, when I'm not connected to the internet, it doesn't crash and locally saving the data works fine. Can any one help?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using System.Text;
public class playgamesscript : MonoBehaviour {
public static playgamesscript Instance { get; private set; }
const string SAVE_NAME = "Test";
bool isSaving;
textEdit textEditScript;
control controlScript;
bool isCloudDataLoaded;
// Use this for initialization
void Start () {
Instance = this;
textEditScript = GameObject.FindGameObjectWithTag("UIControl").GetComponent<textEdit>();
controlScript = GameObject.FindGameObjectWithTag("Control").GetComponent<control>();
if (!PlayerPrefs.HasKey(SAVE_NAME))
PlayerPrefs.SetString(SAVE_NAME, "0");
if (!PlayerPrefs.HasKey("IsFirstTime"))
PlayerPrefs.SetInt("IsFirstTime", 1);
LoadLocal();
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().EnableSavedGames().Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
if (control.signInAttempt == false)
{
SignIn();
}
}
void SignIn()
{
control.signInAttempt = true;
Social.localUser.Authenticate(success => { LoadData(); });
}
#region Saved Games
string GameDataToString()
{
return control.Highscore.ToString();
}
void StringToGameData(string cloudData, string localData)
{
if (PlayerPrefs.GetInt("IsFirstTime") == 1){
PlayerPrefs.SetInt("IsFirstTime", 0);
if (int.Parse(cloudData) > int.Parse(localData)){
PlayerPrefs.SetString(SAVE_NAME, cloudData);
}
}
else if (int.Parse(localData) > int.Parse(cloudData))
{
control.Highscore = int.Parse(localData);
AddScoreToLoeaderBoard(textEdit.leaderboardStat, control.Highscore);
isCloudDataLoaded = true;
SaveData();
return;
}
control.Highscore = int.Parse(cloudData);
isCloudDataLoaded = true;
}
void StringToGameData (string localData)
{
control.Highscore = int.Parse(localData);
}
void LoadData()
{
if (Social.localUser.authenticated)
{
isSaving = false;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(SAVE_NAME, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else {
LoadLocal();
}
}
private void LoadLocal()
{
StringToGameData(PlayerPrefs.GetString(SAVE_NAME));
}
public void SaveData()
{
if (!isCloudDataLoaded)
{
SaveLocal();
return;
}
if (Social.localUser.authenticated)
{
isSaving = true;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(SAVE_NAME, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else
{
SaveLocal();
}
}
private void SaveLocal()
{
PlayerPrefs.SetString(SAVE_NAME, GameDataToString());
}
private void ResolveConflict(IConflictResolver resolver, ISavedGameMetadata original, byte[] originalData, ISavedGameMetadata unmerged, byte[] unmergedData)
{
if (originalData == null)
{
resolver.ChooseMetadata(unmerged);
} else if (unmergedData == null)
{
resolver.ChooseMetadata(original);
} else
{
string originalStr = Encoding.ASCII.GetString(originalData);
string unmergedStr = Encoding.ASCII.GetString(unmergedData);
int originalNum = int.Parse(originalStr);
int unmergedNum = int.Parse(unmergedStr);
if (originalNum > unmergedNum)
{
resolver.ChooseMetadata(original);
return;
} else if (unmergedNum> originalNum)
{
resolver.ChooseMetadata(unmerged);
}
resolver.ChooseMetadata(original);
}
}
private void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game)
{
if (status == SavedGameRequestStatus.Success)
{
if (!isSaving)
{
LoadGame(game);
} else
{
SaveGame(game);
}
}
else
{
if (!isSaving)
{
LoadLocal();
}else
{
SaveLocal();
}
}
}
private void LoadGame(ISavedGameMetadata game)
{
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(game, OnSavedGameDataRead);
}
private void SaveGame(ISavedGameMetadata game)
{
string stringToSave = GameDataToString();
PlayerPrefs.SetString(SAVE_NAME, stringToSave);
byte[] dataToSave = Encoding.ASCII.GetBytes(stringToSave);
SavedGameMetadataUpdate update = new SavedGameMetadataUpdate.Builder().Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(game, update, dataToSave, OnSavedGameDataWritten);
}
private void OnSavedGameDataRead(SavedGameRequestStatus status, byte[] savedData)
{
if (status == SavedGameRequestStatus.Success)
{
string cloudDataString;
if (savedData.Length == 0)
{
cloudDataString = "0";
} else
cloudDataString = Encoding.ASCII.GetString(savedData);
string localDataString = PlayerPrefs.GetString(SAVE_NAME);
StringToGameData(cloudDataString, localDataString);
}
}
private void OnSavedGameDataWritten(SavedGameRequestStatus status, ISavedGameMetadata game)
{
}
#endregion /Saved Games
///
JNI DETECTED ERROR IN APPLICATION: can't call void com.google.android.gms.common.api.PendingResult.setResultCallback(com.google.android.gms.common.api.ResultCallback) on null object'

Related

MVVM AsyncExecute causing lag

AsyncExecute method causing lag in my treeview application when I am expanding a branch.
Important parts of my TreeView
public DirectoryItemViewModel(string fullPath, DirectoryItemType type, long size)
{
this.ExpandCommand = new AsyncCommand(Expand, CanExecute);
this.FullPath = fullPath;
this.Type = type;
this.Size = size;
this.ClearChildren();
}
public bool CanExecute()
{
return !isBusy;
}
public IAsyncCommand ExpandCommand { get; set; }
private async Task Expand()
{
isBusy = true;
if (this.Type == DirectoryItemType.File)
{
return;
}
List<Task<long>> tasks = new();
var children = DirectoryStructure.GetDirectoryContents(this.FullPath);
this.Children = new ObservableCollection<DirectoryItemViewModel>(
children.Select(content => new DirectoryItemViewModel(content.FullPath, content.Type, 0)));
//If I delete the remaining part of code in this method everything works fine,
in my idea it should output the folders without lag, and then start calculating their size in other threads, but it first lags for 1-2 sec, then output the content of the folder, and then start calculating.
foreach (var item in children)
{
if (item.Type == DirectoryItemType.Folder)
{
tasks.Add(Task.Run(() => GetDirectorySize(new DirectoryInfo(item.FullPath))));
}
}
var results = await Task.WhenAll(tasks);
for (int i = 0; i < results.Length; i++)
{
Children[i].Size = results[i];
}
isBusy = false;
}
My command Interface and class
public interface IAsyncCommand : ICommand
{
Task ExecuteAsync();
bool CanExecute();
}
public class AsyncCommand : IAsyncCommand
{
public event EventHandler CanExecuteChanged;
private bool _isExecuting;
private readonly Func<Task> _execute;
private readonly Func<bool> _canExecute;
public AsyncCommand(
Func<Task> execute,
Func<bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute()
{
return !_isExecuting && (_canExecute?.Invoke() ?? true);
}
public async Task ExecuteAsync()
{
if (CanExecute())
{
try
{
_isExecuting = true;
await _execute();
}
finally
{
_isExecuting = false;
}
}
RaiseCanExecuteChanged();
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
bool ICommand.CanExecute(object parameter)
{
return CanExecute();
}
void ICommand.Execute(object parameter)
{
//I suppose that here is the problem cause IDE is hinting me that I am not awaiting here, but I don't know how to change it if it is.
ExecuteAsync();
}
}

DeveloperError Exception of type 'Google.GoogleSignIn+SignInException', googleplaystore, unity, google login?

I have weird behaviour for my SignInWithGoogle.
I have everything set up for QAuth, SSH, WebClieng etc.
And when I sent a build to my phone directly. All work fine. I can SignIn, LogIn etc.
But when I made an aab build and uploaded it to google console and downloaded it from GooglePlay, as a tester, I received DeveloperError Exception of type 'Google.GoogleSignIn+SignInException.
Is there maybe something I need to change on QAuth to fix that?
public class SignInWithGoogle : MonoBehaviour
{
public static string slaveUserEmail;
public static string slaveUserPassword;
string webClientId = "536446807232-vh3olku8c637olltqlge92p17qmsqmtl.apps.googleusercontent.com";
private GoogleSignInConfiguration configuration;
FirebaseAuth _auth;
bool _initialized = false;
void Awake()
{
FireBaseInit.OnInitialized += OnFirebaseInit;
configuration = new GoogleSignInConfiguration
{
WebClientId = webClientId,
RequestIdToken = true
};
}
public void OnFirebaseInit()
{
if (_initialized) return;
_auth = FirebaseAuth.DefaultInstance;
_initialized = true;
Debug.Log("GoogleAuth Initialized");
}
public void OnSignIn()
{
Debug.Log("Calling SignIn");
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
var signInCompleted = new TaskCompletionSource<FirebaseUser>();
Debug.Log("SignInInit");
try
{
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(task =>
{
if (task.IsFaulted)
{
using (IEnumerator<Exception> enumerator =
task.Exception.InnerExceptions.GetEnumerator())
{
if (enumerator.MoveNext())
{
GoogleSignIn.SignInException error =
(GoogleSignIn.SignInException)enumerator.Current;
Debug.Log("Got Error: " + error.Status + " " + error.Message);
}
else
{
Debug.Log("Got Unexpected Exception?!?" + task.Exception);
}
}
}
else if (task.IsCanceled)
{
Debug.Log("Canceled");
}
else
{
Debug.Log("Welcome in Google: " + task.Result.DisplayName + "!");
Debug.Log("GEt Ceds");
Credential credential = GoogleAuthProvider.GetCredential(task.Result.IdToken, null);
Debug.Log("Creds added");
Debug.Log("Firebase Log In try!");
FirebaseAuth.DefaultInstance.SignInWithCredentialAsync(credential).ContinueWith(authTask =>
{
if (authTask.IsCanceled)
{
Debug.Log("Auth Canceld");
signInCompleted.SetCanceled();
}
else if (authTask.IsFaulted)
{
Debug.Log("Auth Faulted");
signInCompleted.SetException(authTask.Exception);
}
else
{
Debug.Log("Auth Coplited");
signInCompleted.SetResult(((Task<FirebaseUser>)authTask).Result);
}
});
}
});
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
The full error:
Got Error: DeveloperError Exception of type 'Google.GoogleSignIn+SignInException' was thrown. <>c__DisplayClass8_0:b__0(Task`1) System.Threading.ThreadPoolWorkQueue:Dispatch()

How to make HybridWebView go back when device back button is pressed

I have a Xamarin.Forms app with a HybridWebView and a HybridWebViewRenderer in the Droid project.
I am trying to make the web view navigate back when the device's back button is pressed.
It looks pretty simple if I was just using a Xamarin.Forms WebView within my page. I would just do it like this...
protected override bool OnBackButtonPressed()
{
_webView.GoBack();
return true;
}
But the HybridWebView does not have a GoBack() method.
In my Droid project, the only place where I have access to the WebView is in the HybridWebViewRenderer but I cannot listen for the OnBackButtonPressed event here.
Anyone know how I can make a HybridWebView navigate back when the device's back button is pressed?
Calling window.history.back(); from Javascript might be a dirty solution.
Also, calling the renderer's method from a PCL class should not be a problem.
The PCL class:
public class MyHybridWebView : HybridWebView
{
public event EventHandler<EventArgs> DoSomeNative;
public void CallNative()
{
DoSomeNative(this, EventArgs.Empty);
}
}
The renderer:
public class MyHybridWebViewRenderer : HybridWebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
(e.NewElement as MyHybridWebView).DoSomeNative += (sender, args) =>
{
//Do something
//Don't forget to unsubscribe in Dispose
};
}
}
My solution that is working are as follows:
HybridWebView that extends the View:
I created 2 event listeners and 1 bool property.
public event EventHandler<EventArgs> GoBackOnNativeEventListener;
public event EventHandler<EventArgs> CanGoBackOnNativeEventListener;
public bool _CanGoBack { get; set; }
Methods:
public bool GoBack()
{
GoBackOnNative();
return true;
}
private void GoBackOnNative()
{
GoBackOnNativeEventListener(this, EventArgs.Empty);
}
public bool CanGoBack()
{
CanGoBackOnNative();
return _CanGoBack;
}
private void CanGoBackOnNative()
{
CanGoBackOnNativeEventListener(this, EventArgs.Empty);
}
In iOS render
public class WebViewRender : HybridWebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (Control != null && e.NewElement != null)
{
InitializeCommands((ClickableWebView)e.NewElement);
}
}
private void InitializeCommands(ClickableWebView element)
{
element.RefreshCommand = () =>
{
Control?.Reload();
};
element.GoBackCommand = () =>
{
var ctrl = Control;
if (ctrl == null)
return;
if (ctrl.CanGoBack)
ctrl.GoBack();
};
element.CanGoBackFunction = () =>
{
var ctrl = Control;
if (ctrl == null)
return false;
return ctrl.CanGoBack;
};
element.CanGoForwardFunction = () =>
{
var ctrl = Control;
if (ctrl == null)
return false;
return ctrl.CanGoForward;
};
element.GoFrowardCommand = () =>
{
var ctrl = Control;
if (ctrl == null)
return;
if (ctrl.CanGoForward)
ctrl.GoForward();
};
}
}
On renderer I bind the listener:
e.NewElement.GoBackOnNativeEventListener += (sender, args) =>
{
Control.GoBack();
};
e.NewElement.CanGoBackOnNativeEventListener += (sender, args) =>
{
_cangoback = Control.CanGoBack();
var hybridWebView = Element as HybridWebView;
hybridWebView._CanGoBack = _cangoback;
};
Finally on xaml.cs, on method OnBackButtonPressed(), I do like:
if (hybridWebView.CanGoBack())
{
hybridWebView.GoBack();
return true;
}
else
return base.OnBackButtonPressed();

Service-Unavailable(503) Error in Smack XEP-0198: Stream Management

I am using below class to enable stream management("urn:xmpp:sm:3") in our ejabberd server(we have latest version of ejabberd). But when I send the Enable packet to server it says Service Unavailable(503). But when I use "yaxim" it works perfectly. Please help me to solve this problem. Thanks.
public class XmppStreamHandler {
public static final String URN_SM_3 = "urn:xmpp:sm:3";
private static final int MAX_OUTGOING_QUEUE_SIZE = 20;
private static final int OUTGOING_FILL_RATIO = 4;
private XMPPConnection mConnection;
private boolean isSmAvailable = false;
private boolean isSmEnabled = false;
private boolean isOutgoingSmEnabled = false;
private long previousIncomingStanzaCount = -1;
private String sessionId;
private long incomingStanzaCount = 0;
private long outgoingStanzaCount = 0;
private Queue<Packet> outgoingQueue;
private int maxOutgoingQueueSize = MAX_OUTGOING_QUEUE_SIZE;
private ConnectionListener mConnectionListener;
public XmppStreamHandler(XMPPConnection connection, ConnectionListener connectionListener) {
mConnection = connection;
mConnectionListener = connectionListener;
startListening();
}
/** Perform a quick shutdown of the XMPPConnection if a resume is possible */
public void quickShutdown() {
if (isResumePossible()) {
mConnection.quickShutdown();
// We will not necessarily get any notification from a quickShutdown, so adjust our state here.
closeOnError();
} else {
mConnection.shutdown();
}
}
public void setMaxOutgoingQueueSize(int maxOutgoingQueueSize) {
this.maxOutgoingQueueSize = maxOutgoingQueueSize;
}
public boolean isResumePossible() {
return sessionId != null;
}
public boolean isResumePending() {
return isResumePossible() && !isSmEnabled;
}
public static void addExtensionProviders() {
addSimplePacketExtension("sm", URN_SM_3);
addSimplePacketExtension("r", URN_SM_3);
addSimplePacketExtension("a", URN_SM_3);
addSimplePacketExtension("enabled", URN_SM_3);
addSimplePacketExtension("resumed", URN_SM_3);
addSimplePacketExtension("failed", URN_SM_3);
}
public void notifyInitialLogin() {
if (sessionId == null && isSmAvailable)
sendEnablePacket();
}
private void sendEnablePacket() {
debug("sm send enable " + sessionId);
if (sessionId != null) {
isOutgoingSmEnabled = true;
// TODO binding
StreamHandlingPacket resumePacket = new StreamHandlingPacket("resume", URN_SM_3);
resumePacket.addAttribute("h", String.valueOf(previousIncomingStanzaCount));
resumePacket.addAttribute("previd", sessionId);
mConnection.sendPacket(resumePacket);
} else {
outgoingStanzaCount = 0;
outgoingQueue = new ConcurrentLinkedQueue<Packet>();
isOutgoingSmEnabled = true;
StreamHandlingPacket enablePacket = new StreamHandlingPacket("enable", URN_SM_3);
enablePacket.addAttribute("resume", "true");
mConnection.sendPacket(enablePacket);
}
}
private void closeOnError() {
if (isSmEnabled && sessionId != null) {
previousIncomingStanzaCount = incomingStanzaCount;
}
isSmEnabled = false;
isOutgoingSmEnabled = false;
isSmAvailable = false;
}
private void startListening() {
mConnection.forceAddConnectionListener(new ConnectionListener() {
public void reconnectionSuccessful() {
}
public void reconnectionFailed(Exception e) {
}
public void reconnectingIn(int seconds) {
}
public void connectionClosedOnError(Exception e) {
if (e instanceof XMPPException &&
((XMPPException)e).getStreamError() != null) {
// Non-resumable stream error
close();
} else {
// Resumable
closeOnError();
}
}
public void connectionClosed() {
previousIncomingStanzaCount = -1;
}
});
mConnection.addPacketSendingListener(new PacketListener() {
public void processPacket(Packet packet) {
// Ignore our own request for acks - they are not counted
if (!isStanza(packet)) {
trace("send " + packet.toXML());
return;
}
if (isOutgoingSmEnabled && !outgoingQueue.contains(packet)) {
outgoingStanzaCount++;
outgoingQueue.add(packet);
trace("send " + outgoingStanzaCount + " : " + packet.toXML());
// Don't let the queue grow beyond max size. Request acks and drop old packets
// if acks are not coming.
if (outgoingQueue.size() >= maxOutgoingQueueSize / OUTGOING_FILL_RATIO) {
mConnection.sendPacket(new StreamHandlingPacket("r", URN_SM_3));
}
if (outgoingQueue.size() > maxOutgoingQueueSize) {
// Log.e(XmppConnection.TAG, "not receiving acks? outgoing queue full");
outgoingQueue.remove();
}
} else if (isOutgoingSmEnabled && outgoingQueue.contains(packet)) {
outgoingStanzaCount++;
trace("send DUPLICATE " + outgoingStanzaCount + " : " + packet.toXML());
} else {
trace("send " + packet.toXML());
}
}
}, new PacketFilter() {
public boolean accept(Packet packet) {
return true;
}
});
mConnection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
if (isSmEnabled && isStanza(packet)) {
incomingStanzaCount++;
trace("recv " + incomingStanzaCount + " : " + packet.toXML());
} else {
trace("recv " + packet.toXML());
}
if (packet instanceof StreamHandlingPacket) {
StreamHandlingPacket shPacket = (StreamHandlingPacket) packet;
String name = shPacket.getElementName();
if ("sm".equals(name)) {
debug("sm avail");
isSmAvailable = true;
if (sessionId != null)
sendEnablePacket();
} else if ("r".equals(name)) {
StreamHandlingPacket ackPacket = new StreamHandlingPacket("a", URN_SM_3);
ackPacket.addAttribute("h", String.valueOf(incomingStanzaCount));
mConnection.sendPacket(ackPacket);
} else if ("a".equals(name)) {
long ackCount = Long.valueOf(shPacket.getAttribute("h"));
removeOutgoingAcked(ackCount);
trace(outgoingQueue.size() + " in outgoing queue after ack");
} else if ("enabled".equals(name)) {
incomingStanzaCount = 0;
isSmEnabled = true;
mConnection.getRoster().setOfflineOnError(false);
String resume = shPacket.getAttribute("resume");
if ("true".equals(resume) || "1".equals(resume)) {
sessionId = shPacket.getAttribute("id");
}
debug("sm enabled " + sessionId);
} else if ("resumed".equals(name)) {
debug("sm resumed");
incomingStanzaCount = previousIncomingStanzaCount;
long resumeStanzaCount = Long.valueOf(shPacket.getAttribute("h"));
// Removed acked packets
removeOutgoingAcked(resumeStanzaCount);
trace(outgoingQueue.size() + " in outgoing queue after resume");
// Resend any unacked packets
for (Packet resendPacket : outgoingQueue) {
mConnection.sendPacket(resendPacket);
}
// Enable only after resend, so that the interceptor does not
// queue these again or increment outgoingStanzaCount.
isSmEnabled = true;
// Re-notify the listener - we are really ready for packets now
// Before this point, isSuspendPending() was true, and the listener should have
// ignored reconnectionSuccessful() from XMPPConnection.
mConnectionListener.reconnectionSuccessful();
} else if ("failed".equals(name)) {
// Failed, shutdown and the parent will retry
debug("sm failed");
mConnection.getRoster().setOfflineOnError(true);
mConnection.getRoster().setOfflinePresences();
sessionId = null;
mConnection.shutdown();
// isSmEnabled / isOutgoingSmEnabled are already false
}
}
}
}, new PacketFilter() {
public boolean accept(Packet packet) {
return true;
}
});
}
private void removeOutgoingAcked(long ackCount) {
if (ackCount > outgoingStanzaCount) {
// Log.e(XmppConnection.TAG,
// "got ack of " + ackCount + " but only sent " + outgoingStanzaCount);
// Reset the outgoing count here in a feeble attempt to re-sync. All bets
// are off.
outgoingStanzaCount = ackCount;
}
int size = outgoingQueue.size();
while (size > outgoingStanzaCount - ackCount) {
outgoingQueue.remove();
size--;
}
}
private static void addSimplePacketExtension(final String name, final String namespace) {
ProviderManager.getInstance().addExtensionProvider(name, namespace,
new PacketExtensionProvider() {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
StreamHandlingPacket packet = new StreamHandlingPacket(name, namespace);
int attributeCount = parser.getAttributeCount();
for (int i = 0; i < attributeCount; i++) {
packet.addAttribute(parser.getAttributeName(i),
parser.getAttributeValue(i));
}
return packet;
}
});
}
private void debug(String message) {
System.out.println(message);
}
private void trace(String message) {
System.out.println(message);
}
public static class StreamHandlingPacket extends UnknownPacket {
private String name;
private String namespace;
Map<String, String> attributes;
StreamHandlingPacket(String name, String namespace) {
this.name = name;
this.namespace = namespace;
attributes = Collections.emptyMap();
}
public void addAttribute(String name, String value) {
if (attributes == Collections.EMPTY_MAP)
attributes = new HashMap<String, String>();
attributes.put(name, value);
}
public String getAttribute(String name) {
return attributes.get(name);
}
public String getNamespace() {
return namespace;
}
public String getElementName() {
return name;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(getElementName());
// TODO Xmlns??
if (getNamespace() != null) {
buf.append(" xmlns=\"").append(getNamespace()).append("\"");
}
for (String key : attributes.keySet()) {
buf.append(" ").append(key).append("=\"")
.append(StringUtils.escapeForXML(attributes.get(key))).append("\"");
}
buf.append("/>");
return buf.toString();
}
}
/** Returns true if the packet is a Stanza as defined in RFC-6121 - a Message, IQ or Presence packet. */
public static boolean isStanza(Packet packet) {
if (packet instanceof Message)
return true;
if (packet instanceof IQ)
return true;
if (packet instanceof Presence)
return true;
return false;
}
public void queue(Packet packet) {
if (outgoingQueue.size() >= maxOutgoingQueueSize) {
System.out.println("outgoing queue full");
return;
}
outgoingStanzaCount++;
outgoingQueue.add(packet);
}
private void close() {
isSmEnabled = false;
isOutgoingSmEnabled = false;
sessionId = null;
}
}
when I send the Enable packet to server it says Service
Unavailable(503)
Service Unavailable means that the service is unavailable on the server. Does ejabberd support XEP-198? Did you enable it?
You should also consider switching to Smack 4.1.0-alpha, which also runs on Android and comes with Stream Management support. yaxim will soon switch to from it's custom XmppStreamHandler implementation to Smack 4.1.

Condition in Pick/PickBranch activities

I have a following scenario that I am trying to define in workflow foundation:
My workflow gets to a stage from which it can continue in 3 paths, each path has some conditions that must be satisfied before the path is taken. After each path is finished, a termination condition is checked, and if not terminated, the workflow gets back to the decision stage where the 3 paths are allowed.
I wanted to solve this with Pick activity, set up a branch with a trigger for each one (triggered by Receive), but I don't know how to add the conditions there (PickBranches have no conditions on them, just triggers).
You can implement your Custom Pick Activity to add new conditions.
namespace System.Activities.Statements
{
using System.Activities.DynamicUpdate;
using System.Activities.Validation;
using System.Collections.ObjectModel;
using System.Runtime;
using System.Runtime.Collections;
using System.Runtime.Serialization;
using System.Windows.Markup;
[ContentProperty("Branches")]
public sealed class Pick : NativeActivity
{
const string pickStateProperty = "System.Activities.Statements.Pick.PickState";
Collection<PickBranch> branches;
Variable<PickState> pickStateVariable;
Collection<Activity> branchBodies;
public Pick()
{
this.pickStateVariable = new Variable<PickState>();
}
protected override bool CanInduceIdle
{
get
{
return true;
}
}
public Collection<PickBranch> Branches
{
get
{
if (this.branches == null)
{
this.branches = new ValidatingCollection<PickBranch>
{
// disallow null values
OnAddValidationCallback = item =>
{
if (item == null)
{
throw FxTrace.Exception.ArgumentNull("item");
}
}
};
}
return this.branches;
}
}
protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
{
metadata.AllowUpdateInsideThisActivity();
}
protected override void UpdateInstance(NativeActivityUpdateContext updateContext)
{
PickState pickState = updateContext.GetValue(this.pickStateVariable);
Fx.Assert(pickState != null, "Pick's Execute must have run by now.");
if (updateContext.IsCancellationRequested || pickState.TriggerCompletionBookmark == null)
{
// do not schedule newly added Branches once a Trigger has successfully completed.
return;
}
CompletionCallback onBranchCompleteCallback = new CompletionCallback(OnBranchComplete);
foreach (PickBranchBody body in this.branchBodies)
{
if (updateContext.IsNewlyAdded(body))
{
updateContext.ScheduleActivity(body, onBranchCompleteCallback, null);
}
}
}
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
if (this.branchBodies == null)
{
this.branchBodies = new Collection<Activity>();
}
else
{
this.branchBodies.Clear();
}
foreach (PickBranch branch in this.Branches)
{
if (branch.Trigger == null)
{
metadata.AddValidationError(new ValidationError(SR.PickBranchRequiresTrigger(branch.DisplayName), false, null, branch));
}
PickBranchBody pickBranchBody = new PickBranchBody
{
Action = branch.Action,
DisplayName = branch.DisplayName,
Trigger = branch.Trigger,
Variables = branch.Variables,
};
this.branchBodies.Add(pickBranchBody);
metadata.AddChild(pickBranchBody, origin: branch);
}
metadata.AddImplementationVariable(this.pickStateVariable);
}
protected override void Execute(NativeActivityContext context)
{
if (this.branchBodies.Count == 0)
{
return;
}
PickState pickState = new PickState();
this.pickStateVariable.Set(context, pickState);
pickState.TriggerCompletionBookmark = context.CreateBookmark(new BookmarkCallback(OnTriggerComplete));
context.Properties.Add(pickStateProperty, pickState);
CompletionCallback onBranchCompleteCallback = new CompletionCallback(OnBranchComplete);
//schedule every branch to only run trigger
for (int i = this.branchBodies.Count - 1; i >= 0; i--)
{
context.ScheduleActivity(this.branchBodies[i], onBranchCompleteCallback);
}
}
protected override void Cancel(NativeActivityContext context)
{
context.CancelChildren();
}
void OnBranchComplete(NativeActivityContext context, ActivityInstance completedInstance)
{
PickState pickState = this.pickStateVariable.Get(context);
ReadOnlyCollection<ActivityInstance> executingChildren = context.GetChildren();
switch (completedInstance.State)
{
case ActivityInstanceState.Closed:
pickState.HasBranchCompletedSuccessfully = true;
break;
case ActivityInstanceState.Canceled:
case ActivityInstanceState.Faulted:
if (context.IsCancellationRequested)
{
if (executingChildren.Count == 0 && !pickState.HasBranchCompletedSuccessfully)
{
// All of the branches are complete and we haven't had a single
// one complete successfully and we've been asked to cancel.
context.MarkCanceled();
context.RemoveAllBookmarks();
}
}
break;
}
//the last branch should always resume action bookmark if it's still there
if (executingChildren.Count == 1 && pickState.ExecuteActionBookmark != null)
{
ResumeExecutionActionBookmark(pickState, context);
}
}
void OnTriggerComplete(NativeActivityContext context, Bookmark bookmark, object state)
{
PickState pickState = this.pickStateVariable.Get(context);
string winningBranch = (string)state;
ReadOnlyCollection<ActivityInstance> children = context.GetChildren();
bool resumeAction = true;
for (int i = 0; i < children.Count; i++)
{
ActivityInstance child = children[i];
if (child.Id != winningBranch)
{
context.CancelChild(child);
resumeAction = false;
}
}
if (resumeAction)
{
ResumeExecutionActionBookmark(pickState, context);
}
}
void ResumeExecutionActionBookmark(PickState pickState, NativeActivityContext context)
{
Fx.Assert(pickState.ExecuteActionBookmark != null, "This should have been set by the branch.");
context.ResumeBookmark(pickState.ExecuteActionBookmark, null);
pickState.ExecuteActionBookmark = null;
}
[DataContract]
internal class PickState
{
[DataMember(EmitDefaultValue = false)]
public bool HasBranchCompletedSuccessfully
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public Bookmark TriggerCompletionBookmark
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public Bookmark ExecuteActionBookmark
{
get;
set;
}
}
class PickBranchBody : NativeActivity
{
public PickBranchBody()
{
}
protected override bool CanInduceIdle
{
get
{
return true;
}
}
public Collection<Variable> Variables
{
get;
set;
}
public Activity Trigger
{
get;
set;
}
public Activity Action
{
get;
set;
}
protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
{
PickBranchBody originalBranchBody = (PickBranchBody)originalActivity;
if ((originalBranchBody.Action != null && metadata.GetMatch(this.Trigger) == originalBranchBody.Action) || (this.Action != null && metadata.GetMatch(this.Action) == originalBranchBody.Trigger))
{
metadata.DisallowUpdateInsideThisActivity(SR.PickBranchTriggerActionSwapped);
return;
}
metadata.AllowUpdateInsideThisActivity();
}
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
Collection<Activity> children = null;
if (this.Trigger != null)
{
ActivityUtilities.Add(ref children, this.Trigger);
}
if (this.Action != null)
{
ActivityUtilities.Add(ref children, this.Action);
}
metadata.SetChildrenCollection(children);
metadata.SetVariablesCollection(this.Variables);
}
protected override void Execute(NativeActivityContext context)
{
Fx.Assert(this.Trigger != null, "We validate that the trigger is not null in Pick.CacheMetadata");
context.ScheduleActivity(this.Trigger, new CompletionCallback(OnTriggerCompleted));
}
void OnTriggerCompleted(NativeActivityContext context, ActivityInstance completedInstance)
{
PickState pickState = (PickState)context.Properties.Find(pickStateProperty);
if (completedInstance.State == ActivityInstanceState.Closed && pickState.TriggerCompletionBookmark != null)
{
// We're the first trigger! We win!
context.ResumeBookmark(pickState.TriggerCompletionBookmark, context.ActivityInstanceId);
pickState.TriggerCompletionBookmark = null;
pickState.ExecuteActionBookmark = context.CreateBookmark(new BookmarkCallback(OnExecuteAction));
}
else if (!context.IsCancellationRequested)
{
// We didn't win, but we haven't been requested to cancel yet.
// We'll just create a bookmark to keep ourselves from completing.
context.CreateBookmark();
}
// else
// {
// No need for an else since default cancelation will cover it!
// }
}
void OnExecuteAction(NativeActivityContext context, Bookmark bookmark, object state)
{
if (this.Action != null)
{
context.ScheduleActivity(this.Action);
}
}
}
}
}