Windows phone 8 and phonegap 2.7.0, Navigation between HTML pages and Xaml and back - c#

I am developing an app, that will have a separate camera functionality. The reason is I do not like phonegap's builit in getPicture for windows phone as it automatically saves the image on the user's device, which will chew up alot of memory.
How my app currently works,
user opens app, app directs them to login.html page (where they enter username/pass) then to menu.html where they have a number of different options/features one of them is a take picture button, which opens camera.html in camera.html page i have this, code which calls my seperate Echo.cs class/plugin tool
cordova.exec(function (imageData) { onPhotoDataSuccess(imageData); }, function (err) {
alert("Intent Error. Unable to call update routines");
}, "Echo", "takePicture", ["takepicture"]);
my takePicture method looks like this:
public void takePicture(string options)
{
string takePic = null;
Debug.WriteLine("Reached imageconvert method");
try
{
string[] data = JsonHelper.Deserialize<string[]>(options);
takePic = data[0];
}
catch (Exception)
{
Debug.WriteLine("ERROR OCCURED!");
DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
return;
}
if ((takePic != null) && (takePic.Length > 0))
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
(Application.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri("/Camera.xaml", UriKind.Relative));
//logic here some way to get the image back from camera.xaml and resume my currant page.
});
//DispatchCommandResult(new PluginResult(PluginResult.Status.OK, "imaged passed back from camera.xaml should go here"));
}
else
{
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Expected one non-empty string argument."));
return;
}
}
this code above, redirects the user to a seperate camera.xaml page I built where my custom camera processes an image without saving it to the user library and converts it to encoded 64basestring to send back as ImageData, My question now is, is there a way to send that ImageData information back some how and resume my app from Camera.html page? is this even possible with phonegap?

i have used to back:
DispatchCommandResult(new PluginResult(PluginResult.Status.OK, "imaged passed back from camera.xaml should go here"));
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
root = Application.Current.RootVisual as PhoneApplicationFrame;
root.GoBack();
});
if you use root.Navigate(new Uri("/MainPage.xaml", UriKind.Relative)); will lost the actual page and return to index
sorry my english

Related

How to load a scene when it completes getting data from firebase?

there are two scenes in my game.
first one is "main Scene" and second one is "user Data Scene".
in "user data scene" I am retrieving current user data from firebase.
The problem is when I switch to "user data scene" from "main scene" there are no data for few seconds until its retrieved from firebase. it looks very bad to me.
All I want is when user is on "main scene" and try to open "user data scene" it should be not active until retrieving data from firebase is done.
I attached the script that gets data from firebase to the main scene's empty object which does not destroy on load. and calling it in start function of the "user data scene".
I am calling below function in start function of "user data scene".
I want to wait until data is loaded from firebase and value is attached to text objects before activating the "user data scene" ?
public IEnumerator getUserDataFromDb(Text userNameTxt, Text totalDiamondTxt, Text totalGoldText) //get data from database of diamond and how much diamond has been sold
{
userNameTxt.text = FirebaseAuth.DefaultInstance.CurrentUser.DisplayName;
var getDbTask = FirebaseDatabase.DefaultInstance.GetReference("Users").Child(FirebaseAuth.DefaultInstance.CurrentUser.UserId).GetValueAsync();
yield return new WaitUntil(predicate: () => getDbTask.IsCompleted);
if (getDbTask.Exception != null)
{
Debug.LogWarning(getDbTask.Exception.InnerExceptions[0].InnerException.Message);
}
else
{
DataSnapshot snapshot = getDbTask.Result;
totalDiamondTxt.text = snapshot.Child("Sell").Child("Total").Child("TotalDiamond").Value.ToString();
int dbDiamondValue = int.Parse(snapshot.Child("Sell").Child("Total").Child("TotalDiamond").Value.ToString());
totalGoldText.text = snapshot.Child("Sell").Child("Total").Child("TotalGold").Value.ToString();
int dbGoldValue = int.Parse(snapshot.Child("Sell").Child("Total").Child("TotalGold").Value.ToString());
}
}
Maybe something like this:
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
var dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available) {
db = Firebase.Firestore.FirebaseFirestore.DefaultInstance;
//use your data and load your secene after
DocumentReference docRef =
db.Collection("yourCollection").Document("yourDocumentCode");
docRef.GetSnapshotAsync().ContinueWithOnMainThread(task => {
DocumentSnapshot snapshot = task.Result;
if (snapshot.Exists) {
//do you stuff here after retrieving the info
} else {
Debug.Log(String.Format("Document {0} does not exist!", snapshot.Id));
}
});
} else {
UnityEngine.Debug.LogError(System.String.Format("Could not resolve all Firebase dependencies: {0}", dependencyStatus));
// Firebase Unity SDK is not safe to use here.
}
});
Need that for the specific use of firestore, but you got a similar snippet in the documentation so that right after you do whatever you need with the firebase services you move on executing your app.

How to know App navigating to HomeActivity or LoginActivity - Appium

I am testing my mobile app using Appium. When app starting it directly navigation to HomeActivity sometimes(if user already logged in). If user not logged in then opening LoginActivity.
So, how can I know which activity starting? so that I can execute logout code accordingly.
This code not executing at all because app navigation to HomeActivity directly instead of LoginActivity.
public void DemoTest()
{
AndroidElement editElement1 = driver.FindElementById("input_name");
editElement1.Clear();
editElement1.SendKeys("ak#ct");
AndroidElement editElement2 = driver.FindElementById("input_password");
editElement2.Click();
editElement2.SendKeys("qa");
driver.HideKeyboard();
driver.Manage().Timeouts().ImplicitWait =TimeSpan.FromSeconds(4);
AndroidElement editElement3 = driver.FindElementById("btnLogin");
editElement3.Click();
}
If you always want to test in fresh app, you can add noReset = false capability in your DesiredCapabilities.
If you want to check which screen is visible, there must be unique element or id in the homeActivityScreen and LoginActivityScreen. Then you can use isDisplayed() function.
If you use Page Object Model it will be very easy for you to check which screen is Display.
I am going to show sample of page object model in java code. Hope you can convert it into C# code
public class HomeActivityScreen {
//you can use accessibility, id or xpath
#AndroidFindBy(id = " your element id")
private MobileElement element1;
#AndroidFindBy(id = "element id")
private MobileElement element2;
public HomeActivityScreen(AppiumDriver<MobileElement> driver) {
PageFactory.initElements(new AppiumFieldDecorator(driver), this);
}
public boolean isScreenDisplayed() {
try {
return element1.isDisplayed();
} catch (Exception e) {
return false;
}
}
}
Similarly you can add page object model for other screen. Then in your test class you can check which screen is visible like
HomeActivityScreen homeScreen = new HomeActivityScreen(driver);
LoginActivityScreen loginScreen = new LoginActivityScreen(driver);
if(homeScreen.isScreenDisplayed){
//write your code
}else if(loginScreen.isScreenDisplayed){
//write logout code
}else{
//none of above screen is visible
}
You'll need a way to identify the page as being the home page or login page.
If you have access to the mobile app source code, you could give your home page a "homePage" AutomationId and your login page a "loginPage" AutomationId. If that is not possible, ask the developer to add them for you. Use these Id's in your appium code to uniquely identify the page that got loaded.
In your appium code, these are the steps you need to take:
Start your app: driver = new AndroidDriver<AndroidElement>(url, cap);
Give the app some time to get loaded.
Check what page you are on, e.g. by checking the AutomationId or a other unique value for those pages.
In your test script, you can do it like this:
try
{
control = driver.FindElementByAccessibilityId("loginPage");
}
catch (Exception ex)
{
// No login page found, your in the home page.
// Code for logging out here.
}
As Suban Dhyako already suggested, a page object design pattern is a very good practice. It keeps your code clean and clear to read. You can read more about it here.

How to download data from Firebase?

I'm attempting to retrieve some data from a Firebase database. I've been able to do it fine in the past, but there's something wrong with my GetValueAsync() code below. When debugging it gets stuck at the "await reference.Database" line, but I'm not sure what I'm doing wrong. When running without debugging, none of the information is ever retrieved.
I'm uncertain if the problem is with the path, or the await/async function. Debugging shows that loggedUserId is storing the value before referencing it in the next line, but the rest of the function never completes or faults. The application compiles but I'm never able to capture any info from the snapshot.
The format of my database is "users" -> 78cVqzA8qNTNigsao3VvdnM0Qol2 (Which is correct) -> (several data pairs such as level : 1, lives : 3, etc)
public static async void GetUserData()
{
FirebaseApp app = FirebaseApp.DefaultInstance;
app.SetEditorDatabaseUrl("https://narwhaltrivia.firebaseio.com/");
if (app.Options.DatabaseUrl != null) app.SetEditorDatabaseUrl(app.Options.DatabaseUrl);
DatabaseReference reference = Firebase.Database.FirebaseDatabase.DefaultInstance.RootReference;
loggedUserId = FirebaseAuth.DefaultInstance.CurrentUser.UserId;
await reference.Database.GetReference("users").Child(loggedUserId).GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
Debug.LogError("Error retrieving user data");
return;
}
if (task.IsCompleted)
{
DataSnapshot userSnapshot = task.Result;
loggedEmail = userSnapshot.Child("email").GetRawJsonValue();
loggedCurrentScore = userSnapshot.Child("currentScore").GetRawJsonValue();
loggedLevel = userSnapshot.Child("level").GetRawJsonValue();
loggedLives = userSnapshot.Child("lives").GetRawJsonValue();
loggedRound = userSnapshot.Child("round").GetRawJsonValue();
loggedTotalScore = userSnapshot.Child("totalScore").GetRawJsonValue();
return;
}
});
}

store logged in user details in xamarin forms using SQLite

I am working on Xamarin forms applicaiton which will have three welcome pages while the user is logging into the applicaiton for the first time, if the user user is trying to start the application after logging in only dashboard has to be displayed. I have written the following code for that :
public LoginUserInfoDbModel SaveUserDetails(LoginUserInfoDbModel model)
{
if(model.LoggedInUser!=null)
{
return null;
}
else
{
connection.Insert(model);
return model;
}
}
and called the above method in LoginPage.xaml.cs in the following way :
if (model.ResultString == "Valid")
{
App.UserDatabase.SaveUserDetails(model);
await DisplayAlert("", "You have logged in succesfully ", "Ok");
await Navigation.PushAsync(new DashBoardPage());
}
So now I need to check whether the User is already a existing user or not in DB, so I have written the following code in App.xaml.cs :
var connection = DependencyService.Get<ISQLiteDb>().GetConnection();
var c=connection.CreateTableAsync<LoginUserInfoDbModel>().Result;
var UserData = connection.Table<LoginUserInfoDbModel().ToListAsync().Result?.FirstOrDefault();
if(UserData != null)
{
MainPage= new DashBoardPage();
}
else
{
MainPage=new WelcomePages();
}
But this code is not working I am getting null reference Exception and some other exceptions, So do we have any alternative for this scenario or else can you suggest any modifications for this code ?

Facebook SDK and threads (WebBrowser control)

This is probably more of a general c# and simple threading question than it is a Facebook SDK question, but I may be wrong. But I could really use some help. I am reusing the sample code that comes with the SDK which includes a FacebookLoginDialog class. I am currently using it like this. In my GetMessages, GetFriendRequests, and other Get* classes, I always try/catch calls like this:
try
{
var result = (IDictionary<string, object>)fb.Get("/me/inbox");
}
catch (FacebookOAuthException e)
{
FacebookSession.Login();
}
Here's my login method in my FacebookSession class
public static void Login()
{
var fbLoginDialog = new FacebookLoginDialog(APP_ID, EXTENDED_PERMISSIONS);
DialogResult dr = fbLoginDialog.ShowDialog();
DisplayAppropriateMessage(fbLoginDialog.FacebookOAuthResult);
}
And here is the constructor in my FacebookLoginDialog class (this is where I have the problem)
public FacebookLoginDialog(string appId, string[] extendedPermissions, bool logout)
{
try
{
var oauth = new FacebookOAuthClient { AppId = appId };
var loginParameters = new Dictionary<string, object>
{
{ "response_type", "token" },
{ "display", "popup" }
};
if (extendedPermissions != null && extendedPermissions.Length > 0)
{
var scope = new StringBuilder();
scope.Append(string.Join(",", extendedPermissions));
loginParameters["scope"] = scope.ToString();
}
var loginUrl = oauth.GetLoginUrl(loginParameters);
if (logout)
{
var logoutParameters = new Dictionary<string, object>
{
{ "next", loginUrl }
};
System.Uri uri =
new Uri("https://www.facebook.com/logout.php?next=" +
"https://www.facebook.com/connect/login_success.html&access_token=" +
FacebookSession._accessToken);
this.navigateUrl = uri;
}
else
{
this.navigateUrl = loginUrl;
}
InitializeComponent(); // crash here... sometimes
}
catch (Exception e)
{
//Log error message
}
}
Sorry for all the code, but now the problem. This code works fine the first time through. If I go to my facebook applications permissions page in Facebook and remove the app (that is, remove its permissions), while my desktop app here is NOT running, when I do start it up, it sees that it does not have permission and shows the login dialog. I can save the access_key and it will work just fine. But if I go to the facebook apps page and yank the permissions while my desktop app is running, then bad things happen. I get an error message about the activex control cannot be instantiated because the current thread is not in a single-threaded apartment. I have seen many posts here that say all you have to do is put [STAThread] above your main(), and my code has that. I have also tried creating a new thread to call the FacebookLoginDialog, but not only did that not work, but since my code is really not designed to run in multiple threads, that started causing more problems.
Is there a simple solution to all this, or do I need to redesign my code so that it properly runs in multiple threads? Or should I just live with the program crashing in those few instances when someone monkeys with the facebook permissions while my app is running?

Categories