Has anyone heard of any issues with MessageDialog's not displaying on Windows 8 tablets? Or more specifically Samsung 700t? It uses a regular intel process and not ARM. I built the app on a laptop and the messagedialog shows when debugging from the laptop, shows on the tablet simulator but doesn't show on the actual tablet.
I'm using the Caliburn.Micro IResult interface to display the messagedialog in the view.
Heres snippits of code that I'm using:
public IEnumerable<IResult> NavExecute(String method)
{
Windows.UI.ViewManagement.ApplicationView.TryUnsnap();
var conn = NetworkInformation.GetInternetConnectionProfile();
if (conn.GetNetworkConnectivityLevel() != NetworkConnectivityLevel.InternetAccess)
{
yield return new MessageDialogResult("Internet Connection Not Detected", "Connection Error");
netOn = false;
}
}
the above is in my view model base class, and heres the implementation of the IResult class itself:
public class MessageDialogResult : ResultBase
{
private readonly string _content;
private readonly string _title;
public MessageDialogResult(string content, string title)
{
_content = content;
_title = title;
}
public async override void Execute(ActionExecutionContext context)
{
var dialog = new MessageDialog(_content, _title);
await dialog.ShowAsync();
OnCompleted();
}
}
I doub't it's an issue with the code since I'm debugging in x86 mode on both devices (before anyone asks why I'm not debugging for all devices it's because I'm using SQLite which requires a seperate package for each arhitecture.)
I'm not sure if theres a setting somewhere in Windows 8 that disables in app popups, but I couldn't find one.
Any ideas?
Are you handling the callback of Coroutine.Execute?
The callback on Execute might be calling back with an exception thrown by the coroutine - this would silently fail if you weren't explicitly looking for it in the callback
Coroutine.Execute(YourEnumerator(), new ActionExecutionContext { Blah }, (o, e) => {
if(e.Error != null) // Something went wrong
});
Maybe the async await is throwing or something like that (can't think why!)
Edit:
Ah additionally stuff in your enumerator could also throw:
Windows.UI.ViewManagement.ApplicationView.TryUnsnap();
var conn = NetworkInformation.GetInternetConnectionProfile();
Either one could throw making the outer enumerator swallow an exception if not handled in the callback - or could be a nullref on conn?
The reason why GetInternetConnectionProfile() was returning a null ref was due to the fact that when on a laptop, if you disconnect from a wireless connection the laptop's internet connection profile defaults to ethernet, whereas the tablet (at least the Samsung 700T) doesn't have an ethernet port so it's connection profile doesn't exist if a wireless connection isn't established.
Thanks to Charleh for pointing me in the right direction.
Related
Technologies, frameworks and devices I'm using:
Framework: Xamarin.Forms
IDE: Visual Studio 2022
Physical Device (smartphone): Zebra TC26 (Android 10)
Physical Device (smartwatch): Samsung Galaxy Watch4 (Android 11)
Problem definition
Currently I have a test Xamarin.Forms project that consists of two different UIs (XAML files):
User Interface 1: HomePage.XAML - This screen should be displayed on the smartphone
User Interface 2: WatchScreen.XAML - This screen should be displayed on the smartwatch
With code below I make sure HomePage.XAML is deployed to a smartphone and watchscreen is deployed to a smartwatch:
Page homePage = new NavigationPage(new HomePage());
// BuildVersionCodes.R is a reference to Android version 11 (mostly now used by Wear OS 3.x)
if (Build.VERSION.SdkInt == BuildVersionCodes.R)
{
// SM-R870 is a reference to the Samsung Galaxy Watch4
// Note: This is needed to ensure the UI is specific to the UI of a smartwatch
if (Build.Model == "SM-R870")
{
Page watchScreen = new NavigationPage(new WatchScreen());
MainPage = watchScreen;
}
}
else
{
MainPage = homePage;
}
Now I want to make these pages on different devices communicate with each other. HomePage.xaml exists within the main Xamarin.Forms project as well as WatchScreen.xaml.
The way I want them to communicate with each other is by sending a message or something. A Xamarin.Forms project also comes with a native project. In this native Xamarin.Android project I try to retrieve inside the MainActivity.cs the button that exists within the main project by using (in WatchScreen.xaml this button exists and in WatchScreen.xaml.cs I have a method that gives this button back).
Method in WatchScreen.xaml.cs that gives button back:
public Button GetSendButtonFromWearableUI() => btnSendMessage;
In MainActivity.cs I get this method by using:
Button button = (App.Current.MainPage.Navigation.NavigationStack.LastOrDefault() as WatchScreen)
.GetSendButtonFromWearableUI();
Whenever I click on the button by doing this:
button.Clicked += delegate
{
SendData();
};
Some data should be sent from MainActivity.cs and catched by HomePage.xaml and displayed on it. I tried several approaches but I didn't succeed in achieving what needs to happen.. Therefore, I'm wondering if you guys could help me out with this and would be much appreciated.
In the meantime I've been investigating this issue and came up with a solution. Follow steps below to get the same result. To make this solution work I've combined the Wearable Data Layer API from Google and MessagingCenter from Microsoft.
Also the example below shows only the communication from the smartwatch to the smartphone. In order to reverse processes you can put the send button on the HomePage instead of the smartwatch screen and make sure to subscribe to the correct messages.
One last note: keep in mind that code used below from Google is deprecated but it still works...
References used to make this work:
Syncing Data Between Wearable and Handheld Devices Using Xamarin in Android
Installed dependencies on the Xamarin.Android project within Xamarin.Forms project:
Xamarin.Android.Support.v4
Xamarin.GooglePlayServices.Base
Xamarin.GooglePlayServices.Wearable
MessageKeys.cs
This class is used to declare message keys that are being used to send and receive messages between devices.
public class MessageKeys
{
public const string Smartwatch = "Smartwatch";
public const string Smartphone = "Smartphone";
}
Xamarin.Forms (Base project) - App.xaml.cs
In the App.xaml.cs, as pointed out earlier, I'm making sure the wearable UI displays WatchScreen.xaml and any other devices display regular Android UI -> HomePage.xaml.
Xamarin.Forms (Base project) - WatchScreen.xaml.cs
Send message from Wearable device to Android smartphone.
private void btnSendMessage_Clicked(object sender, EventArgs e)
{
MessagingCenter.Send(Xamarin.Forms.Application.Current, MessageKeys.Smartwatch);
}
Xamarin.Forms (Base project) - HomePage.xaml.cs
public HomePage()
{
InitializeComponent();
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, MessageKeys.Smartphone, (sender) =>
{
DisplayAlert("Message", "Wearable message received!", "OK");
});
}
Xamarin.Forms (Native Android Project) - MainActivity.cs
Within MainActivity.cs I implement the following interfaces:
public class MainActivity : WearableActivity, DataClient.IOnDataChangedListener,
GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener
Variables:
private GoogleApiClient client;
const string syncPath = "/[project name]/[subdirectory for watch]";
Internal class 'MessageReceiver' for receiving broadcast messages:
[BroadcastReceiver]
public class MessageReciever : BroadcastReceiver
{
MainActivity main;
public MessageReciever() { }
public MessageReciever(MainActivity owner) { this.main = owner; }
public override void OnReceive(Context context, Intent intent)
{
main.ProcessMessage(intent);
}
}
Registering receiver (to receive through Wearable Data Layer API), creating Google Client and Subscribing to smartwatch message (to retrieve message through MessagingCenter)
protected override void OnCreate(Bundle bundle)
{
IntentFilter filter = new IntentFilter(Intent.ActionSend);
MessageReciever receiver = new MessageReciever(this);
LocalBroadcastManager.GetInstance(this).RegisterReceiver(receiver, filter);
client = new GoogleApiClient.Builder(this, this, this)
.AddApi(WearableClass.Api)
.Build();
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, MessageKeys.Smartwatch, (sender) =>
{
SendData();
});
}
ProcessMessage method: sends received message from wearable to smartphone
public void ProcessMessage(Intent intent)
{
// For now I'm not sending the payload...
string message = intent.GetStringExtra("WearMessage");
MessagingCenter.Send(Xamarin.Forms.Application.Current, MessageKeys.Smartphone);
}
SendData(), OnStart(), OnStop(), OnDataChanged (didn't do anything with this part, because this is to receive messages outside the project and I don't need it for now), OnConnected(), OnConnectionSuspended(), OnConnectionFailed():
See the reference to see what code has been used, since code is exactly the same... P.S.: one thing for SendData has been changed. If you want to keep sending data, remove 'client.Disconenct()' from finally after the try and catch block.
Xamarin.Forms (Native Android Project) - WearableService inherits from WearableListenerService:
WearableService is a new class and created within the native project. Also for this part see the reference, because it's the exact same code being used within my project.
To get an overall overview of what's happening, I've visualized this in the diagram below: (example shows how communication works from smartwatch to smartphone)
If you want to communicate from smartphone to smartwatch, you could do something like this:
That's it guys. Now you will receive messages within the same application using the Wearable Data Layer API and MessagingCenter. Instead of having separate projects, we just use separate UIs to make this happen...
I am currently trying to implement the Java web service(Rest API) where the endpoint creates the device in the IoTHub and updates the device twin.
There are two methods available in the azure-iot sdk. One is
addDevice(deviceId, authenticationtype)
and another is to
addDeviceAsync(deviceId, authenticationtype)
I just wanted to figure out which one should I use in the web service(as a best practice). I am not very strong in MultiThreading/Concurrency so was wondering to receive people's expertise on this. Any suggestion/Link related to this is much appreciated
Thanks.
The Async version of AddDevice is basically the same. If you use AddDeviceAsync then a thread is created to run the AddDevice call so you are not blocked on it.
Check the code#L269 of RegistryManager doing exactly that: https://github.com/Azure/azure-iot-sdk-java/blob/master/service/iot-service-client/src/main/java/com/microsoft/azure/sdk/iot/service/RegistryManager.java#L269
public CompletableFuture<Device> addDeviceAsync(Device device) throws IOException, IotHubException
{
if (device == null)
{
throw new IllegalArgumentException("device cannot be null");
}
final CompletableFuture<Device> future = new CompletableFuture<>();
executor.submit(() ->
{
try
{
Device responseDevice = addDevice(device);
future.complete(responseDevice);
}
catch (IOException | IotHubException e)
{
future.completeExceptionally(e);
}
});
return future;
}
You can as well build your own async wrapper and call AddDevice() from there.
I'm using usbmanager class to manage USB host on my android 4.1.1 machine.
all seems to work quite well for a few hundreds of transactions until (after ~ 900 transactions) opening the device fails, returning null without exception.
Using a profiler it doesn't seem to be a matter of memory leakage.
this is how I initialize the communication from my main activity (doing this once):
public class MainTestActivity extends Activity {
private BroadcastReceiver m_UsbReceiver = null;
private PendingIntent mPermissionIntent = null;
UsbManager m_manager=null;
DeviceFactory m_factory = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
m_UsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
// call your method that cleans up and closes communication with the device
Log.v("BroadcastReceiver", "Device Detached");
}
}
}
};
registerReceiver(m_UsbReceiver, filter);
m_manager = (UsbManager) getSystemService(Context.USB_SERVICE);
m_factory = new DeviceFactory(this,mPermissionIntent);
}
and this is the code of my test:
ArrayList<DeviceInterface> devList = m_factory.getDevicesList();
if ( devList.size() > 0){
DeviceInterface devIf = devList.get(0);
UsbDeviceConnection connection;
try
{
connection = m_manager.openDevice(m_device);
}
catch (Exception e)
{
return null;
}
The test will work OK for 900 to 1000 calls and after this the following call will return null (without exception):
UsbDeviceConnection connection;
try
{
connection = m_manager.openDevice(m_device);
}
You might just run out of file handles, a typical limit would be 1024 open files per process.
Try calling close() on the UsbDeviceConnection, see doc.
The UsbDeviceConnection object has allocated system ressources - e.g. a file descriptor - which will be released only on garbage collection in your code. But in this case you run out of ressources before you run out of memory - which means the garbage collector is not invoked yet.
I had opendevice fail on repeated runs on android 4.0 even though I open only once in my code. I had some exit paths that did not close the resources and I had assumed the OS would free it on process termination.
However there seems to be some issue with release of resources on process termination -I used to have issues even when I terminated and launched a fresh process.
I finally ensured release of resources on exit and made the problem go away.
I am currently developing a Windows Phone 7 App that calls a WCF web service which I also control. The service offers an operation that returns the current user's account information when given a user's login name and password:
[ServiceContract]
public interface IWindowsPhoneService
{
[OperationContract]
[FaultContract(typeof(AuthenticationFault))]
WsAccountInfo GetAccountInfo(string iamLogin, string password);
}
Of course, there is always the possibility of an authentication failure and I want to convey that information to the WP7 app. I could simply return null in that case, but I would like to convey the reason why the authentication failed (i.e. login unknown, wrong password, account blocked, ...).
This is my implementation of the above operation (for testing purposes, all it does is throwing an exception):
public WsAccountInfo GetAccountInfo(string iamLogin, string password)
{
AuthenticationFault fault = new AuthenticationFault();
throw new FaultException<AuthenticationFault>(fault);
}
Now, if I call this operation in my WP7 app, like this:
Global.Proxy.GetAccountInfoCompleted += new EventHandler<RemoteService.GetAccountInfoCompletedEventArgs>(Proxy_GetAccountInfoCompleted);
Global.Proxy.GetAccountInfoAsync(txbLogin.Text, txbPassword.Password);
void Proxy_GetAccountInfoCompleted(object sender, RemoteService.GetAccountInfoCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
return;
}
}
The debugger breaks in Reference.cs, saying that FaultException'1 was unhandled, here:
public PhoneApp.RemoteService.WsAccountInfo EndGetAccountInfo(System.IAsyncResult result) {
object[] _args = new object[0];
PhoneApp.RemoteService.WsAccountInfo _result = ((PhoneApp.RemoteService.WsAccountInfo)(base.EndInvoke("GetAccountInfo", _args, result)));
return _result;
}
BEGIN UPDATE 1
When pressing F5, the exception bubbles to:
public PhoneApp.RemoteService.WsAccountInfo Result {
get {
base.RaiseExceptionIfNecessary(); // <-- here
return ((PhoneApp.RemoteService.WsAccountInfo)(this.results[0]));
}
}
and then to:
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
// An unhandled exception has occurred; break into the debugger
System.Diagnostics.Debugger.Break();
}
}
After that, the app terminates (with or without the debugger).
END UPDATE 1
Now, I would love to catch the exception in my code, but I am never given the chance, since my Completed handler is never reached.
Based on similar questions on this site, I have already tried the following:
Re-add the service reference --> no change
Re-create a really simple WCF service from scratch --> same problem
Start the app without the debugger to keep the app from breaking into the debugger --> well, it doesn't break, but the exception is not caught either, the app simply exits
Tell VS 2010 not to break on FaultExceptions (Debug > Options) --> does not have any effect
wrap every line in my app in try { ... } catch (FaultException) {} or even catch (Exception) --> never called.
BEGIN UPDATE 2
What I actually would like to achieve is one of the following:
ideally, reach GetAccountInfoCompleted(...) and be able to retrieve the exception via the GetAccountInfoCompletedEventArgs.Error property, or
be able to catch the exception via a try/catch clause
END UPDATE 2
I would be grateful for any advice that would help me resolve this issue.
The framework seems to read your WsAccountInfo.Result property.
This rethrows the exception on client side.
But you should be the first to read this property.
I don't know your AuthenticationFault class, does it have a DataContractAttribute and is it a known type like the example in
http://msdn.microsoft.com/en-us/library/system.servicemodel.faultcontractattribute.aspx ?
I believe I had the same problem. I resolved it by extending the proxy class and calling the private Begin.../End... methods within the Client object rather than using the public auto-generated methods on the Client object.
For more details, please see:
http://cbailiss.wordpress.com/2014/02/09/wcf-on-windows-phone-unable-to-catch-faultexception/
I'm currently using WCF in monotouch to call an existing service and a custom UIAlertView.
The problem is that if I create an UIAlertView as class instance and the I do the following:
public override void ViewDidAppear()
{
_alertView.Message = "Loading...";
_alertView.Show();
_client.GetDataAsync("test");
_client.GetDataCompleted += GetDataCompletedDelegate;
base.ViewDidAppear();
}
void GetDataCompletedDelegate(object sender, GetDataEventArgs)
{
// do someting with data
_alertView.Hide();
}
it works but this advice is written in console : UIAlertView: wait_fences: failed to receive reply: 10004003
else, if I try to run this code:
public override void ViewDidAppear()
{
using(CustomAV _alertView = new CustomAV())
{
_alertView.Message = "Loading...";
_alertView.Show();
_client.GetDataAsync("test");
_client.GetDataCompleted += delegate{
InvokeOnMainThread(delegate{
// do someting with data
_alertView.Hide();
});
};
}
base.ViewDidAppear();
}
the first time the code run, but now alert is shown. The second time the simulator can't startup. Couldn't register "com.yourcompany.wcftest" with the bootstrap server. Error: unknown error code. This generally means that another instance of this process was already running or is hung in the debugger.StackTrace. In this case I have to reboot the machine.
Thank you in advance.
EDIT:
Thank you Geoff, I've checked my code and into GetDataCompletedDelegate I've inserted a function that runs inside the UI Thread.
InvokeOnMainThread(delegate{
doSomething();
});
private void doSomething()
{
// do stuff here
_alertView.Hide();
}
The fency error continues to appear. If I use your solution inside doSomething() method, it works
_alertView.InvokeOnMainThread(delegate{
_alertView.Hide();
});
Why? Maybe I didn't understand, but in the first snippet of code do something() works in the UI thread!! Isn't true?
You have 2 seperate problems here.
1: _alertView.Hide () is not running on the UI thread (this is what causes the fences error)
2: In your second example you're disposing the UIAlertVeiw immediately after creating it, but you have a instance delegate dangled off it. This crashes the runtime in a hard way, and then when you run it again since the old crashed process is still running the simulator wont let you start a second instance.
Use case #1 but do _alterView.InvokeOnMainThread (delegate { _alertView.Hide (); });