Windows Phone: how to manage shake events? - event-handling

The accelerometer is activated (if I set ReadingChanged it works).
Why the shaking event isn't handled?
namespace AppExample
{
public sealed partial class MainPage : Page
{
private Accelerometer accel;
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
accel = Accelerometer.GetDefault();
//accel.ReadingChanged += accel_ReadingChanged;
accel.Shaken += accel_Shaken;
}
void accel_Shaken(Accelerometer sender, AccelerometerShakenEventArgs args)
{
Debug.WriteLine("shaken");
}
}
}

If you mind, there is helper librairy called ShakeGestures to handle shake gestures for windows phone 8. check this question

If you're running Windows Phone 8 , Shaken event won't trigger and does not raise any errors according to MSDN page.
Otherwise it seems like a weird bug to me , I couldn't find any information about it.

You can call the Dispatcher in order to show the result on the main thread.
namespace AppExample
{
public sealed partial class MainPage : Page
{
Accelerometer accel;
public MainPage()
{
this.InitializeComponent();
accel = Accelerometer.GetDefault();
accel.ReadingChanged += accel_ReadingChanged;
accel.Shaken += accel_Shaken;
}
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
LabelTest.Text = "Shaken!! " + args.Reading.AccelerationX.ToString();
});
async private void accel_Shaken(object sender, AccelerometerShakenEventArgs e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
_shakeCount++;
ScenarioOutputText.Text = _shakeCount.ToString();
});
}
}
}

Related

Unity & PhotonEngine. After scene reaload Joining to Lobby, CreateRoom and JoinRandom functions called repeatedly

I ran into a problem in the last step of a test project using Photon Network. When you first connect and join the room, everything goes without errors. However, after completing the match, exiting the room, and using LoadScene(), errors appear:
JoinLobby operation (229) not called because client is not connected or not yet ready, client state: JoiningLob <- in OnConnectedToMaster()
Through experience, I realized that the ConnectUsingSettings() methods and other Photon methods are called multiple times. But the connection to the lobby happens and I can create a room, but I immediately encounter MissingReferenceException errors.
I've seen a solution from guys who ran into this very same problem. The problems arose because of the events. Wherever this could happen, I unsubscribed from the events, but that doesn't help. What else can cause such problems, because I obviously missed something that prevents me from completely closing the scene during the transition?
Sorry for my language, used Google Translate
Code:
LobbyManager.cs
private void StartConnect()
{
PhotonNetwork.NickName = master.GameSettings.NickName;
PhotonNetwork.GameVersion = master.GameSettings.NickName;
PhotonNetwork.ConnectUsingSettings();
PhotonNetwork.AutomaticallySyncScene = true;
}
public override void OnConnectedToMaster()
{
Debug.Log("Connected to server");
if(!PhotonNetwork.InLobby) PhotonNetwork.JoinLobby();
}
public override void OnJoinedLobby()
{
onConnected.Invoke();//This use for show UIElements on Canvas
}
JoinRandomRoom class
public void OnClick_JoinRandomRoom()
{
if (!PhotonNetwork.IsConnected) return;
if (GameModeGlobalData.SelectedGameMode != null)
{
SetRoomOptions();
PhotonNetwork.JoinRandomRoom(expectedRoomProperties, GameModeGlobalData.SelectedGameMode.MaxPlayers);
}
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
Debug.Log("Join random failed: " + message + ". Room will be created...");
_createRoomMenu.CreateAndJoinRoom();
}
public void SetRoomOptions()
{
expectedRoomProperties[RoomData.GAME_MODE] = GameModeGlobalData.SelectedGameMode.GameModeName;
}
private void OnDisable()
{
ShowPanels.RemoveAllListeners();
}
And CreateRoom.cs
private ExitGames.Client.Photon.Hashtable _roomCustomProperties = new ExitGames.Client.Photon.Hashtable();
public void CreateAndJoinRoom()
{
if (!PhotonNetwork.IsConnected) return;
if (GameModeGlobalData.SelectedGameMode != null)
{
RoomOptions roomOptions = GetCustomRoomOptions();
roomOptions.CleanupCacheOnLeave = true;
PhotonNetwork.CreateRoom(randomRoomName, roomOptions);
}
}
public RoomOptions GetCustomRoomOptions()
{
RoomOptions options = new RoomOptions();
options.MaxPlayers = _maxPlayer;
options.IsOpen = true;
options.IsVisible = true;
string[] roomProperties = new string[]{ RoomData.GAME_MODE };
_roomCustomProperties[RoomData.GAME_MODE] = GameModeGlobalData.SelectedGameMode.GameModeName;
options.CustomRoomPropertiesForLobby = roomProperties;
options.CustomRoomProperties = _roomCustomProperties;
return options;
}
The project has grown, and I blame myself for not testing it at the very beginning. Didn't think there would be problems at this stage
Sorry for this post. Its resolved. For those who may encounter this in the future, in addition to unsubscribing from events, check all classes that inherit from MonoBehaviourPunCallbacks for overridden OnDisable() methods.
Like this:
public override void OnDisable()
{
base.OnDisable();
}
This in turn will call the
PhotonNetwork.RemoveCallbackTarget(this);
Also, from the documentation:
Do not add new MonoBehaviour.OnEnable or MonoBehaviour.OnDisable. Instead, you should override those and call base.OnEnable and base.OnDisable.
I forgot about it and used MonoBehaviour.OnDisable.

.net core: run big tasks in the background

I created a .net core web api project. It has gotten kinda big and I want to program a "delete" operation which deletes a lot of stuff from the database. Since there are a lot of things to delete, this will be a long running process. So I thought maybe I can run this in the background and just write status updates somewhere for the user to see whats happening.
I googled this and I found BackgroundWorkerQueue and thought this might be my solution.
So I registered the service and everything and here is my method that calls it:
public class DeleteController : ControllerBase {
private readonly BackgroundWorkerQueue _backgroundWorkerQueue;
public AdminController(BackgroundWorkerQueue backgroundWorkerQueue){
_backgroundWorkerQueue = backgroundWorkerQueue;
}
public async Task<ActionResult> HugeDeleteMethod(int id)
{
// some prechecks here...
// and here I thought I'd start the background task
_backgroundWorkerQueue.QueueBackgroundWorkItem(async token =>
{
var a = _context.StatusTable.Find(id);
a.Status += "Blablablabla\n";
_context.StatusTable.Update(a);
await _context.SaveChangesAsync();
//now start doing delete operations
});
}
}
And that class looks like this:
public class BackgroundWorkerQueue
{
private ConcurrentQueue<Func<CancellationToken, Task>> _workItems = new ConcurrentQueue<Func<CancellationToken, Task>>();
private SemaphoreSlim _signal = new SemaphoreSlim(0);
public async Task<Func<CancellationToken, Task>> DequeueAsync(CancellationToken cancellationToken)
{
await _signal.WaitAsync(cancellationToken);
_workItems.TryDequeue(out var workItem);
return workItem;
}
public void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem)
{
if (workItem == null)
{
throw new ArgumentNullException(nameof(workItem));
}
_workItems.Enqueue(workItem);
_signal.Release();
}
}
There is also a DeleteService, which is also called in my startup, but I am not sure what it does:
public class DeleteService : BackgroundService
{
private readonly BackgroundWorkerQueue queue;
public NukeService(BackgroundWorkerQueue queue)
{
this.queue = queue;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var workItem = await queue.DequeueAsync(stoppingToken);
await workItem(stoppingToken);
}
}
}
Both are added in my startup.cs:
services.AddHostedService<DeleteService>();
services.AddSingleton<BackgroundWorkerQueue>();
Well, maybe I'm going about this all wrong. This is never called it seems, the StatusTable field "Status" is always empty. So how do I do this?
You just need to subclass BackgroundService class or implement IHostedService and than register your service as hosted service.
This will run a service in the background. Than in your service you can leverage the BlockingQueue that will perform tasks only when they are added, e.g. like this:
public class MyService : BackgroundService {
private readonly BlockingCollection<long> queue;
public MyService(){
this.queue = new BlockingCollection<long>();
Task.Run(async () => await this.Execute());
}
public void AddId(long id) {
this.queue.Add(id);
}
private async Task Execute()
{
foreach (var id in this.queue.GetConsumingEnumerable())
{
... do your stuff ...
}
}
}
services.AddHostedService<MyService>();
Here is the docu: Background services in .net core

MoPub initialization with SdkInitializationListener

I like to initialize MoPub SDK in Android and continue loading banners and interstitials only if SDK init is complete and successful.
What can be a good way to accomplish this?
create a variable listner :
private SdkInitializationListener Listner2;
then put this code inside your oncreate :
final SdkConfiguration.Builder configBuilder = new SdkConfiguration.Builder("24534e1901884e398f1253216226017e");
configBuilder.withLogLevel(DEBUG);
Listner2 = new SdkInitializationListener() {
#Override
public void onInitializationFinished() {
Log.d("MoPub", "SDK initialized");
mInterstitial.load();
}
};
MoPub.initializeSdk(this, configBuilder.build(), Listner2);
The code above load test interstitial if SDK init is complete and successful.
Very easy to accomplish with Android's new Livedata objects. There objects are observable and you can receive their changes wherever you want in your app.
Technology and patterns used:
Livedata
Singleton pattern
MoPub SDK 5.11.1
I will show you how by code snippets
Singleton pattern
public class MoPubSdk {
private static MoPubSdk INSTANCE;
public static MoPubSdk getInstance(Activity activity) {
if(MoPubSdk.INSTANCE == null) {
MoPubSdk.INSTANCE = new MoPubSdk(activity);
}
return MoPubSdk.INSTANCE;
}
}
Constructor with SdkInitializationListener function
Note the MutableLiveData object that changes it's value to true (isInitialized) when the listener is called and the MoPub SDK is ready to call ads. Also see the showConsentIfNeeded function which you can see in the next code block. Just comment the function if not needed.
public class MoPubSdk {
private final MutableLiveData<Boolean> isMoPubSdkInitialized = new MutableLiveData<>();
private Activity mActivity;
private MoPubSdk(Activity activity) {
this.mActivity = activity;
SdkConfiguration sdkConfiguration = new SdkConfiguration.Builder("ANYadunitID")
.withLogLevel(BuildConfig.DEBUG ? MoPubLog.LogLevel.DEBUG : MoPubLog.LogLevel.NONE)
.build();
MoPub.initializeSdk(activity, sdkConfiguration, initSdkListener());
}
private SdkInitializationListener initSdkListener() {
return new SdkInitializationListener() {
#Override
public void onInitializationFinished() {
/* MoPub SDK initialized.
Check if you should show the consent dialog here, and make your ad requests. */
Log.d("MoPub", "SDK initialized");
isMoPubSdkInitialized.setValue(true);
showConsentIfNeeded();
}
};
}
public LiveData<Boolean> isMoPubSdkInitialized() {
return isMoPubSdkInitialized;
}
}
Optional consent Dialog
private void showConsentIfNeeded() {
PersonalInfoManager mPersonalInfoManager = MoPub.getPersonalInformationManager();
Log.d("customeee", "Can collect pers information? "+MoPub.canCollectPersonalInformation()
+ ".\nShould show consent dialog? "+mPersonalInfoManager.shouldShowConsentDialog());
if(!MoPub.canCollectPersonalInformation()) {
if(mPersonalInfoManager.shouldShowConsentDialog()) {
mPersonalInfoManager.loadConsentDialog(new ConsentDialogListener() {
#Override
public void onConsentDialogLoaded() {
mPersonalInfoManager.showConsentDialog();
}
#Override
public void onConsentDialogLoadFailed(#NonNull MoPubErrorCode moPubErrorCode) {
MoPubLog.i("Consent dialog failed to load.");
}
});
}
}
}
So much for initialization. Now let's call the MoPub SDK from an activity and continue with banner loading.
public class MyActivity extends Activity {
private MoPubSdk moPubSdk;
protected void onCreate(final Bundle savedInstanceState) {
moPubSdk = MoPubSdk.getInstance(this);
moPubSdk.isMoPubSdkInitialized().observe(this, new Observer<Boolean>() {
#Override
public void onChanged(Boolean aBoolean) {
if (aBoolean)
//Init your banner here.
}
});
}
}
The LiveData is easy to explain. First time the MoPub SDK initialization begins the Livedata object is false. It takes some time to init, on success the value switches to true and the observer gets called, you can begin banner loading.
On switching activities during init or call MoPubSdk#getInstance another time, the value is already true and gets passed directly on #observe call and you init your banner straight away.

Postsharp Aspect with Async methods

I'm using Trial Ultimate version of PostSharp 4.0 but this doesn't work for me. Can you please check my code and advise. The error doesn't gets logged. And if i put the breakpoint doesn't hit onException method
This is code that I've written for Error handling Aspect
[Serializable]
public class MyMethodAspectAttribute : OnMethodBoundaryAspect
{
public MyMethodAspectAttribute()
{
this.ApplyToStateMachine = true;
}
public override void OnEntry(MethodExecutionArgs args)
{
Console.Write("Method Entry");
}
public override void OnException(MethodExecutionArgs args)
{
Console.Write(args.Exception.Message);
args.ReturnValue = null;
args.FlowBehavior = FlowBehavior.Return;
}
}
This is class where I've implemented this aspect
public class ErrorMethods
{
[MyMethodAspect]
public Task<int> Calculate(int i, int j)
{
var task = Task.Factory.StartNew(
() => i / j);
return task;
}
}
This is how I've used this method
private async void Button_Click(object sender, RoutedEventArgs e)
{
var obj = new ErrorMethods();
var result = await obj.Calculate(1, 0);
if (null == result)
{
MessageBox.Show("error");
}
}
The Calculate method in your example is not an async method, so setting ApplyToStateMachine aspect's property doesn't have effect on this method. The exception is thrown when a newly created task executes in the background and the aspect has no chance of catching it.
If you change your Calculate method to async method, then the async state machine execution can be intercepted by the aspect and OnException handler is invoked upon exception.
Note, however that setting the ReturnValue and FlowBehavior does not alter the flow of the state machine, so the exception will not be swallowed.
public class ErrorMethods
{
[MyMethodAspect]
public async Task<int> Calculate( int i, int j )
{
return await Task.Factory.StartNew( () => i / j );
}
}

Building unit tests for MVC2 AsyncControllers

I'm considering re-rewriting some of my MVC controllers to be async controllers. I have working unit tests for these controllers, but I'm trying to understand how to maintain them in an async controller environment.
For example, currently I have an action like this:
public ContentResult Transaction()
{
do stuff...
return Content("result");
}
and my unit test basically looks like:
var result = controller.Transaction();
Assert.AreEqual("result", result.Content);
Ok, that's easy enough.
But when your controller changes to look like this:
public void TransactionAsync()
{
do stuff...
AsyncManager.Parameters["result"] = "result";
}
public ContentResult TransactionCompleted(string result)
{
return Content(result);
}
How do you suppose your unit tests should be built? You can of course invoke the async initiator method in your test method, but how do you get at the return value?
I haven't seen anything about this on Google...
Thanks for any ideas.
As with any async code, unit testing needs to be aware of thread signalling. .NET includes a type called AutoResetEvent which can block the test thread until an async operation has been completed:
public class MyAsyncController : Controller
{
public void TransactionAsync()
{
AsyncManager.Parameters["result"] = "result";
}
public ContentResult TransactionCompleted(string result)
{
return Content(result);
}
}
[TestFixture]
public class MyAsyncControllerTests
{
#region Fields
private AutoResetEvent trigger;
private MyAsyncController controller;
#endregion
#region Tests
[Test]
public void TestTransactionAsync()
{
controller = new MyAsyncController();
trigger = new AutoResetEvent(false);
// When the async manager has finished processing an async operation, trigger our AutoResetEvent to proceed.
controller.AsyncManager.Finished += (sender, ev) => trigger.Set();
controller.TransactionAsync();
trigger.WaitOne()
// Continue with asserts
}
#endregion
}
Hope that helps :)
I've written short AsyncController extension method that simplifies unit testing a bit.
static class AsyncControllerExtensions
{
public static void ExecuteAsync(this AsyncController asyncController, Action actionAsync, Action actionCompleted)
{
var trigger = new AutoResetEvent(false);
asyncController.AsyncManager.Finished += (sender, ev) =>
{
actionCompleted();
trigger.Set();
};
actionAsync();
trigger.WaitOne();
}
}
That way we can simply hide threading 'noise':
public class SampleAsyncController : AsyncController
{
public void SquareOfAsync(int number)
{
AsyncManager.OutstandingOperations.Increment();
// here goes asynchronous operation
new Thread(() =>
{
Thread.Sleep(100);
// do some async long operation like ...
// calculate square number
AsyncManager.Parameters["result"] = number * number;
// decrementing OutstandingOperations to value 0
// will execute Finished EventHandler on AsyncManager
AsyncManager.OutstandingOperations.Decrement();
}).Start();
}
public JsonResult SquareOfCompleted(int result)
{
return Json(result);
}
}
[TestFixture]
public class SampleAsyncControllerTests
{
[Test]
public void When_calling_square_of_it_should_return_square_number_of_input()
{
var controller = new SampleAsyncController();
var result = new JsonResult();
const int number = 5;
controller.ExecuteAsync(() => controller.SquareOfAsync(number),
() => result = controller.SquareOfCompleted((int)controller.AsyncManager.Parameters["result"]));
Assert.AreEqual((int)(result.Data), number * number);
}
}
If you want to know more I've written a blog post about how to Unit test ASP.NET MVC 3 asynchronous controllers using Machine.Specifications
Or if you want to check this code it's on a github