Looking for a way to add a progress bar for asynchronic task (Unity, C#) - unity3d

I'm pretty new to writing asynchronous stuff in Unity. It is pretty easy to create a progress bar for asynchronous operation, but when it comes to doing it for the asynchronous task I'm not even sure when to start :(
public async void GetPhotoFromAndroidAndAddTexture(RawImage mainImage, string path)
{
await AddTextureToImage(mainImage, path);
}
public async Task<Texture2D> GetTextureFromAndroid(string path)
{
if(path != "" && path != " ")
{
#if UNITY_ANDROID
path = "file://" + path;
#endif
UnityWebRequest www = UnityWebRequestTexture.GetTexture(path);
var asyncOperation = www.SendWebRequest();
while(!asyncOperation.isDone)
{
await Task.Delay( 1000/30 );
}
return DownloadHandlerTexture.GetContent(www);
}
else
{
Debug.Log("The path is not correct!");
return null;
}
}
public async Task AddTextureToImage(RawImage mainImage, string path)
{
IProgress<int> progress;
Texture2D photoFromDevice = await GetTextureFromAndroid(path);
float textureH = photoFromDevice.height;
float textureW = photoFromDevice.width;
float aspectRat = textureH > textureW ? textureH/textureW : textureW/textureH;
mainImage.GetComponent<AspectRatioFitter>().aspectRatio = aspectRat;
mainImage.texture = photoFromDevice;
}
While the photo from android is being add as a texture I want to create a progress bar.
Thank you in advance for any suggestions

I can see no reason in your code why you should be using async at all. The only thing you actually are waiting for is the UnityWebRequest. async hasn't really any advantage over a simple Coroutine(IEnumerator) here.
In addition async stuff always also brings the problem of multi-threading ... Unity isn't thread safe so most of the API can only be used in the Unity mainthread.
You should rather stick to a Coroutine like e.g.
// wherever you want to show/use the progress
public float progress;
public void GetPhotoFromAndroidAndAddTexture(RawImage mainImage, string path)
{
StartCoroutine(AddTextureToImage(mainImage, path));
}
public IEnumerator AddTextureToImage(RawImage mainImage, string path)
{
Texture2D photoFromDevice;
if (path != "" && path != " ")
{
#if UNITY_ANDROID
path = "file://" + path;
#endif
UnityWebRequest www = UnityWebRequestTexture.GetTexture(path);
var asyncOperation = www.SendWebRequest();
while (!asyncOperation.isDone)
{
// wherever you want to show the progress:
progress = www.downloadProgress;
yield return null;
// or if you want to stick doing it in certain intervals
//yield return new WaitForSeconds(0.5f);
}
// you should also check for errors
if(www.error != null)
{
Debug.LogError("Something went wrong loading!", this);
yield break;
}
photoFromDevice = DownloadHandlerTexture.GetContent(www);
}
else
{
Debug.LogError("The path is not correct!", this);
yield break;
}
float textureH = photoFromDevice.height;
float textureW = photoFromDevice.width;
float aspectRat = textureH > textureW ? textureH / textureW : textureW / textureH;
mainImage.GetComponent<AspectRatioFitter>().aspectRatio = aspectRat;
mainImage.texture = photoFromDevice;
}
Alternatively often recommended is a kind of "dispatcher" or I prefer to call it a main thread worker where you can pass actions from other threads back to the main thread like e.g.
private ConcurrentQueue<Action> callbacks = new ConcurrentQueue<Action>();
private void Update()
{
while(callbacks.TryDequeue(var out a))
{
// Invokes the action in the main thread
a?.Invoke();
}
}
// example method to call
private void UpdateProgressBar(float progress)
{
// use progress
}
public async Task<Texture2D> GetTextureFromAndroid(string path)
{
if(path != "" && path != " ")
{
#if UNITY_ANDROID
path = "file://" + path;
#endif
UnityWebRequest www = UnityWebRequestTexture.GetTexture(path);
var asyncOperation = www.SendWebRequest();
while(!asyncOperation.isDone)
{
// add a callback for the main thread using a lambda expression
callbacks.Add(()=> { UpdateProgressBar(www.downloadProgress); });
await Task.Delay( 1000/30 );
}
return DownloadHandlerTexture.GetContent(www);
}
else
{
Debug.Log("The path is not correct!");
return null;
}
}
A cool way to have a simple progress bar for example can be achieved by using an UI.Image with
Image Type = Filled
Fill Method = Horizontal
Fill Origin = Left
now all you have to do is update the image.fillAmount

Related

GameObject.Find not working with string var

I cannot get GameObject.Find to work by passing a string variable as an agrument.
Here is the code:
public IEnumerator GetControls(string uri)
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
{
yield return webRequest.SendWebRequest();
controls = new JSONObject(webRequest.downloadHandler.text);
GameObject controlGO;
string keyName;
foreach (JSONObject control in controls)
{
keyName = control["keyName"].ToString();
controlGO = GameObject.Find(keyName); //WONT FIND IT
controlGO = GameObject.Find("growLight3"); //WILL FIND IT
}
}
}

Unity coroutine (MEC) not calling

I'm attempting to load an image from a Firestore storage url, by calling a coroutine (using more efficient coroutines asset).
However, the coroutine isn't calling and I can't figure out why...
public void displayImage(string url)
{
Debug.Log("called display image: "+ url);
Timing.RunCoroutine(_loadImageSingle(url));
}
public IEnumerator<float> _loadImageSingle(string url)
{
Debug.Log("Loading ....");
WWW wwwLoader = new WWW(url);
yield return Timing.WaitUntilDone(wwwLoader);
singleimg.texture = wwwLoader.texture;
}
Any pointers really appreciated!
Coroutines in Unity are only IEnumerator withouth any return value!
And then you have to run it using StartCoroutine ... I guess this happens in the code you didn't show?
public void displayImage(string url)
{
Debug.Log("called display image: "+ url);
Timing.RunCoroutine(_loadImageSingle(url));
}
private IEnumerator _loadImageSingle(string url)
{
Debug.Log("Loading ....");
WWW wwwLoader = new WWW(url);
yield return Timing.WaitUntilDone(wwwLoader);
singleimg.texture = wwwLoader.texture;
}
In general note that WWW is obsolete. You should rather use UnityWebRequestTexture.GetTexture:
private IEnumerator _loadImageSingle(string url)
{
Debug.Log("Loading ....");
using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url))
{
yield return uwr.SendWebRequest();
if (uwr.isNetworkError || uwr.isHttpError)
{
Debug.Log(uwr.error);
}
else
{
// Get downloaded texture
singleimg.texture = DownloadHandlerTexture.GetContent(uwr);
}
}
}

Cloud load failed with error code 7 using Unity GoolePlayGames plugin

I get the following log during on-device debugging
Error:
*** [Play Games Plugin DLL] ERROR: Cloud load failed with status code 7
Basically the OnStateLoaded() callback function always returns the boolean success = false and I can't figure out the reason why.
All that the plugin debugging logs mention is "Cloud load failed with status code 7".
According to the android doc, 7 is a generic "developer error", see https://developer.android.com/reference/com/google/android/gms/appstate/AppStateStatusCodes.html#STATUS_DEVELOPER_ERROR
I tried a quick sample and everything worked ok. Here are my steps:
Created a new game in the play console
(https://play.google.com/apps/publish)
Made sure Saved Games is set
to ON
Linked an Android Application Remembering the application ID
(the number after the title) and the package ID
Created a new project in Unity
Added the play games plugin (Assets/Import Package.../Custom
Package)
Set the application ID (Google Play Games/Android Setup...)
Switched the platform to Android (File/Build Settings...)
Set the player settings (bundle identifier and the keystore info)
Added a new script component to the camera
Saved everything and hit build and run.
Here are the contents:
using UnityEngine;
using System.Collections;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using System;
public class SaveSample : MonoBehaviour {
System.Action<bool> mAuthCallback;
GameData slot0;
void Start () {
slot0 = new GameData(0,"waiting for login....");
mAuthCallback = (bool success) => {
if (success) {
Debug.Log("Authentication was successful!");
slot0.Data =" loading....";
slot0.LoadState();
}
else {
Debug.LogWarning("Authentication failed!");
}
};
// make Play Games the default social implementation
PlayGamesPlatform.Activate();
// enable debug logs
PlayGamesPlatform.DebugLogEnabled = true;
//Login explicitly for this sample, usually this would be silent
PlayGamesPlatform.Instance.Authenticate(mAuthCallback, false);
}
protected void OnGUI() {
Screen.fullScreen = true;
int buttonHeight = Screen.height / 20;
int buttonWidth = Screen.width / 5;
GUI.skin.label.fontSize = 60;
GUI.skin.button.fontSize = 60;
Rect statusRect = new Rect(10,20,Screen.width,100);
Rect dataRect = new Rect( 10, 150, Screen.width,100);
Rect b1Rect = new Rect(10, 400, buttonWidth, buttonHeight);
Rect b2Rect = new Rect(b1Rect.x + 20 + buttonWidth,
b1Rect.y, buttonWidth, buttonHeight);
if(!Social.localUser.authenticated) {
if(GUI.Button(b1Rect, "Signin")) {
Social.localUser.Authenticate(mAuthCallback);
}
}
else {
// logged in, so show the load button and the contents of the saved data.
if(GUI.Button(b1Rect, "Load")) {
slot0.LoadState();
}
GUI.Label(dataRect, slot0.Data);
}
if(GUI.Button(b2Rect, "Save")) {
// just save a string, incrementing the number on the end.
int idx = slot0.Data.IndexOf("_");
if (idx > 0) {
int val = Convert.ToInt32(slot0.Data.Substring(idx+1));
val++;
slot0.Data = "Save_" + val;
}
else {
slot0.Data = "Save_0";
}
slot0.SaveState();
}
GUI.Label(statusRect, slot0.State);
}
// Class to handle save/load callbacks.
public class GameData : OnStateLoadedListener {
int slot;
string data;
string state;
public GameData(int slot, string data) {
this.slot = slot;
this.data = data;
this.state = "Initialized, modified";
}
public void LoadState() {
this.state += ", loading";
((PlayGamesPlatform)Social.Active).LoadState(0, this);
}
public void SaveState() {
byte[] bytes = new byte[data.Length * sizeof(char)];
System.Buffer.BlockCopy(data.ToCharArray(), 0, bytes, 0, bytes.Length);
this.state += ", saving";
((PlayGamesPlatform) Social.Active).UpdateState(slot, bytes, this);
}
public void OnStateLoaded(bool success, int slot, byte[] data) {
if (success) {
Debug.Log ("Save game slot : " + slot + " loaded: " + data);
if (data != null) {
char[] chars = new char[data.Length / sizeof(char)];
System.Buffer.BlockCopy(data, 0, chars, 0, data.Length);
this.data = new string(chars);
this.state = "loaded";
} else {
Debug.Log ("Saved data is null");
this.data = "";
this.state = "loaded, but empty";
}
} else {
// handle failure
Debug.LogWarning ("Save game slot : " + slot + " failed!: ");
this.data = "";
this.state = "loading failed!";
}
}
public byte[] OnStateConflict(int slot, byte[] local, byte[] server) {
// resolve conflict and return a byte[] representing the
// resolved state.
Debug.LogWarning("Conflict in saved data!");
state = "conflicted";
// merge or resolve using app specific logic, here
byte[] resolved = local.Length > server.Length ? local : server;
char[] chars = new char[resolved.Length / sizeof(char)];
System.Buffer.BlockCopy(resolved, 0, chars, 0, resolved.Length);
this.data = new string(chars);
return resolved;
}
public void OnStateSaved(bool success, int slot) {
Debug.Log ("Save game slot : " + slot + " success: " + success);
state = "saved";
}
public string Data {
get {
return data;
}
set {
data = value;
state += ", modified";
}
}
public int Slot {
get {
return slot;
}
}
public string State {
get {
return state;
}
}
}
}
The error code 7 is because the Cloud Save API has been deprecated and is only currently accessible to existing games that have used the API. The Unity plugin version 0.9.11 has been updated to use the SavedGames API.
I tried a quick sample and everything worked ok. Here are my steps:
Created a new game in the play console
(https://play.google.com/apps/publish)
Made sure Saved Games is set to ON
Linked an Android Application Remembering the application ID
(the number after the title) and the package ID Created a new
project in Unity
Added the play games plugin (Assets/Import
Package.../Custom Package)
Set the application ID (Google Play
Games/Android Setup...)
Switched the platform to Android (File/Build
Settings...)
Set the player settings (bundle identifier and the
keystore info)
Added a new script component to the camera Saved
everything and hit build and run.
Here is my script:
using UnityEngine;
using System.Collections;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using System;
using GooglePlayGames.BasicApi.SavedGame;
public class SaveSample : MonoBehaviour {
System.Action<bool> mAuthCallback;
GameData slot0;
bool mSaving;
private Texture2D mScreenImage;
// Use this for initialization
void Start () {
slot0 = new GameData("New game");
mAuthCallback = (bool success) => {
if (success) {
Debug.Log("Authentication was successful!");
slot0.State = "Click load or save";
}
else {
Debug.LogWarning("Authentication failed!");
}
};
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder()
.EnableSavedGames()
.Build();
PlayGamesPlatform.InitializeInstance(config);
// Activate the Play Games platform. This will make it the default
// implementation of Social.Active
PlayGamesPlatform.Activate();
// enable debug logs (note: we do this because this is a sample; on your production
// app, you probably don't want this turned on by default, as it will fill the user's
// logs with debug info).
PlayGamesPlatform.DebugLogEnabled = true;
//Login explicitly for this sample, usually this would be silent
PlayGamesPlatform.Instance.Authenticate(mAuthCallback, false);
}
public void CaptureScreenshot() {
mScreenImage = new Texture2D(Screen.width, Screen.height);
mScreenImage.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
mScreenImage.Apply();
}
protected virtual void OnGUI() {
Screen.fullScreen = true;
int buttonHeight = Screen.height / 20;
int buttonWidth = Screen.width / 5;
GUI.skin.label.fontSize = 60;
GUI.skin.button.fontSize = 60;
Rect statusRect = new Rect(10,20,Screen.width,200);
Rect dataRect = new Rect( 10, 250, Screen.width,100);
Rect b1Rect = new Rect(10, 800, buttonWidth, buttonHeight);
Rect b2Rect = new Rect(b1Rect.x + 20 + buttonWidth, b1Rect.y, buttonWidth, buttonHeight);
if(!Social.localUser.authenticated) {
if(GUI.Button(b1Rect, "Signin")) {
Social.localUser.Authenticate(mAuthCallback);
}
}
else {
if(GUI.Button(b1Rect, "Load")) {
mSaving = false;
((PlayGamesPlatform)Social.Active).SavedGame.ShowSelectSavedGameUI("Select game to load",
4,false,false,SavedGameSelected);
}
GUI.Label(dataRect, slot0.Data);
}
if(GUI.Button(b2Rect, "Save")) {
int idx = slot0.Data.IndexOf("_");
if (idx > 0) {
int val = Convert.ToInt32(slot0.Data.Substring(idx+1));
val++;
slot0.Data = "Save_" + val;
}
else {
slot0.Data = "Save_0";
}
mSaving = true;
CaptureScreenshot();
((PlayGamesPlatform)Social.Active).SavedGame.ShowSelectSavedGameUI("Save game progress",
4,true,true,SavedGameSelected);
}
GUI.Label(statusRect, slot0.State);
}
public void SavedGameSelected(SelectUIStatus status, ISavedGameMetadata game) {
if (status == SelectUIStatus.SavedGameSelected) {
string filename = game.Filename;
Debug.Log("opening saved game: " + game);
if(mSaving && (filename == null || filename.Length == 0)) {
filename = "save" + DateTime.Now.ToBinary();
}
if (mSaving) {
slot0.State = "Saving to " + filename;
}
else {
slot0.State = "Loading from " + filename;
}
//open the data.
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithAutomaticConflictResolution(filename,
DataSource.ReadCacheOrNetwork,
ConflictResolutionStrategy.UseLongestPlaytime,
SavedGameOpened);
} else {
Debug.LogWarning("Error selecting save game: " + status);
}
}
public void SavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game) {
if(status == SavedGameRequestStatus.Success) {
if( mSaving) {
slot0.State = "Opened, now writing";
byte[] pngData = (mScreenImage!=null) ?mScreenImage.EncodeToPNG():null;
Debug.Log("Saving to " + game);
byte[] data = slot0.ToBytes();
TimeSpan playedTime = slot0.TotalPlayingTime;
SavedGameMetadataUpdate.Builder builder = new
SavedGameMetadataUpdate.Builder()
.WithUpdatedPlayedTime(playedTime)
.WithUpdatedDescription("Saved Game at " + DateTime.Now);
if (pngData != null) {
Debug.Log("Save image of len " + pngData.Length);
builder = builder.WithUpdatedPngCoverImage(pngData);
}
else {
Debug.Log ("No image avail");
}
SavedGameMetadataUpdate updatedMetadata = builder.Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(game,updatedMetadata,data,SavedGameWritten);
} else {
slot0.State = "Opened, reading...";
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(game,SavedGameLoaded);
}
} else {
Debug.LogWarning("Error opening game: " + status);
}
}
public void SavedGameLoaded(SavedGameRequestStatus status, byte[] data) {
if (status == SavedGameRequestStatus.Success) {
Debug.Log("SaveGameLoaded, success=" + status);
slot0 = GameData.FromBytes(data);
} else {
Debug.LogWarning("Error reading game: " + status);
}
}
public void SavedGameWritten(SavedGameRequestStatus status, ISavedGameMetadata game) {
if(status == SavedGameRequestStatus.Success) {
Debug.Log ("Game " + game.Description + " written");
slot0.State = "Saved!";
} else {
Debug.LogWarning("Error saving game: " + status);
}
}
public class GameData {
private TimeSpan mPlayingTime;
private DateTime mLoadedTime;
string mData;
string mState;
static readonly string HEADER = "GDv1";
public GameData(string data) {
mData = data;
mState = "Initialized, modified";
mPlayingTime = new TimeSpan();
mLoadedTime = DateTime.Now;
}
public TimeSpan TotalPlayingTime {
get {
TimeSpan delta = DateTime.Now.Subtract(mLoadedTime);
return mPlayingTime.Add(delta);
}
}
public override string ToString () {
string s = HEADER + ":" + mData;
s += ":" + TotalPlayingTime.TotalMilliseconds;
return s;
}
public byte[] ToBytes() {
return System.Text.ASCIIEncoding.Default.GetBytes(ToString());
}
public static GameData FromBytes (byte[] bytes) {
return FromString(System.Text.ASCIIEncoding.Default.GetString(bytes));
}
public static GameData FromString (string s) {
GameData gd = new GameData("initializing from string");
string[] p = s.Split(new char[] { ':' });
if (!p[0].StartsWith(HEADER)) {
Debug.LogError("Failed to parse game data from: " + s);
return gd;
}
gd.mData = p[1];
double val = Double.Parse(p[2]);
gd.mPlayingTime = TimeSpan.FromMilliseconds(val>0f?val:0f);
gd.mLoadedTime = DateTime.Now;
gd.mState = "Loaded successfully";
return gd;
}
public string Data {
get {
return mData;
}
set {
mData = value;
mState += ", modified";
}
}
public string State {
get {
return mState;
}
set {
mState = value;
}
}
}
}

Parse.com - iOS push notifications and Unity integration

I notice that Parse Unity support still doesn't provide push notification for iOS.
Has anyone implemented a Unity plugin or another solution to support iOS Push Notifications via Parse?
(Cross posted on Unity Answers.)
It's actually possible now, using a ParseObject to mock up the ParseInstallation object.
Gist here: https://gist.github.com/gfosco/a3d092651c32ba3385e6
Explanation in the Parse Google Group: https://groups.google.com/d/msg/parse-developers/ku8-r91_o6s/6ioQ9T2TP7wJ
Attach this script to a GameObject, replace the important parts with your own:
using UnityEngine;
using System.Collections;
using Parse;
public class PushBehaviorScript : MonoBehaviour {
bool tokenSent = false;
public ParseObject currentInstallation = null;
void Start () {
if (PlayerPrefs.HasKey ("currentInstallation")) {
string objId = PlayerPrefs.GetString ("currentInstallation");
currentInstallation = ParseObject.CreateWithoutData ("_Installation", objId);
}
if (currentInstallation == null) {
#if UNITY_IPHONE && !UNITY_EDITOR
NotificationServices.RegisterForRemoteNotificationTypes (RemoteNotificationType.Alert | RemoteNotificationType.Badge | RemoteNotificationType.Sound);
#endif
}
}
void FixedUpdate () {
if (!tokenSent && currentInstallation == null) {
#if UNITY_IPHONE && !UNITY_EDITOR
byte[] token = NotificationServices.deviceToken;
if(token != null) {
tokenSent = true;
string tokenString = System.BitConverter.ToString(token).Replace("-", "").ToLower();
Debug.Log ("OnTokenReived");
Debug.Log (tokenString);
ParseObject obj = new ParseObject("_Installation");
obj["deviceToken"] = tokenString;
obj["appIdentifier"] = "com.parse.unitypush";
obj["deviceType"] = "ios";
obj["timeZone"] = "UTC";
obj["appName"] = "UnityPushTest";
obj["appVersion"] = "1.0.0";
obj["parseVersion"] = "1.3.0";
obj.SaveAsync().ContinueWith(t =>
{
if (obj.ObjectId != null) {
PlayerPrefs.SetString ("currentInstallation", obj.ObjectId);
}
});
}
#endif
}
}
}
To implement iOS push with parse.com You need to get the token from apple first. Then save Current instalation
Unity does have this functionality build in now.
//push notification
bool tokenSent = false;
void RegisterForPush()
{
Debug.Log("Register for push");
tokenSent = false;
#if UNITY_IOS
UnityEngine.iOS.NotificationServices.RegisterForNotifications(NotificationType.Alert |
NotificationType.Badge |
NotificationType.Sound, true);
#endif
}
void Update () {
if (!tokenSent) {
byte[] token = UnityEngine.iOS.NotificationServices.deviceToken;
if (token != null) {
// send token to a provider
tokenSent = true;
string hexToken = "%" + System.BitConverter.ToString(token).Replace('-', '%');
#if UNITY_IOS
ParseManager.instance.RegisterForPush(hexToken);
#endif
}
}
}
And inside ParseManager (or whatever class you use to manage parse>client communication)
public void RegisterForPush(string token) {
Debug.Log("Parse updating instalation");
ParseInstallation instalation = ParseInstallation.CurrentInstallation;
instalation["deviceToken"] = token;
instalation["user"] = ParseUser.CurrentUser.ObjectId;
instalation["timeZoneOffset"] = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
instalation.SaveAsync();
}
Tested on Unity 5.1.2 and iOS 8.4

WP - How to constantly update my location

Currently my location not updating when I change it to different location via emulator. But it will change after I restart my application. This is what I write when the app launch
private void Application_Launching(object sender, LaunchingEventArgs e)
{
IsolatedStorageSettings Settings = IsolatedStorageSettings.ApplicationSettings;
GeoCoordinate DefaultLocation = new GeoCoordinate(-6.595139, 106.793801);
Library.GPSServices MyGPS;
if (!Settings.Contains("FirstLaunch") || (bool)Settings["FirstLaunch"] == true)
{
Settings["FirstLaunch"] = false;
Settings["LastLocation"] = DefaultLocation;
Settings["SearchRadius"] = 1;
}
//If key not exist OR key value was set to false, ask for permission to use location
if (!Settings.Contains("LocationService") || (bool)Settings["LocationService"] == false)
{
var result = MessageBox.Show(
"Jendela Bogor need to know your location to work correctly, do you want to allow it?",
"Allow access to your location?",
MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
Settings["LocationService"] = true;
MyGPS = new Library.GPSServices();
}
else
{
Settings["LocationService"] = false;
}
Settings.Save();
}
else if ((bool)Settings["LocationService"] == true)
{
MyGPS = new Library.GPSServices();
}
}
I store my location in my application setting IsolatedStorage with name Settings["LastLocation"]
How should I do to constantly update my location in the Background using MVVM Pattern (MVVM-Light) so my PushPin on map in the ThirdPageView always updated?
EDIT
public GPSServices()
{
if ((bool)Settings["LocationService"] == true)
{
if (_watcher == null)
{
_watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
_watcher.MovementThreshold = 20;
}
StartWatcher();
_watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
_watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
}
else if ((bool)Settings["LocationService"] == false)
{
StopWatcher();
}
}
private void StartWatcher()
{
_watcher.Start();
}
private void StopWatcher()
{
if (_watcher != null)
_watcher.Stop();
}
private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
if (e.Position.Location.IsUnknown)
{
MessageBox.Show("Please wait while your position is determined....");
return;
}
Settings["LastLocation"] = e.Position.Location;
Settings.Save();
}
System.Device.Location.GeoCoordinateWatcher provides what you need.
var geoWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
// This event fires every time the device location changes
geoWatcher.PositionChanged += (s, e) => {
//e.Position.Location will contain the current GeoCoordinate
};
geoWatcher.TryStart(false, TimeSpan.FromMilliseconds(2000));
is this helpful for you ? using GeocoordinateWatcher.PositionChanged event?
public Location()
{
GeoCoordinateWatcher location == new GeoCoordinateWatcher();
location.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(location_PositionChanged);
location.Start();
}
//event to track the location change
public void location_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
}