I am firing the following event in my Xamarin application:
AppEvents.Instance.UI.RiseSearchStringTypingEvent(this, new EventArgs());
The HomePage.xaml.cs codebehind subscriber-event performs an auto scroll to top every time the event is being fired (on every input on the search field)
void OnSearchStringTyping(object sender, EventArgs e)
{
scrollView.ScrollToAsync(0.0, 0.0, true);
}
when the searchstring is complete and the user hits the submit-button, the Oncompleted() method invokes on the SearchHeaderView.xaml.cs which navigates to the SearchPage
void OnCompleted(object sender, EventArgs e)
{
var tag = this + ".OnCompleted";
try
{
if (string.Compare(LastSearchText, SearchEntry.Text) == 0) return
if (Device.RuntimePlatform == Device.Android)
{
SearchRequest();
}
else if (Device.RuntimePlatform == Device.iOS)
{
var task = new Task(SearchRequest);
task.Start();
}
LastSearchText = SearchEntry.Text;
}
catch (Exception ex)
{
Track.Exception(tag, ex);
}
}
This procedure works perfect on iOS platforms...But in android, when i submit my search string, the app crashes with an ObjectDisposedException on the ScrollView
I think the problem is that the application tries to scroll up the view again after it navigates away from the homepage. The SearchRequest() method on Android is not invoked in a new Thread, but iOS is. How can i fix this? I can not just make the method being invoked asynchronously, because the Search doesn't work then.
Related
Am I opening the camera for taking a picture, but the user has the possibility to stop the camera if he no longer wants to capture something, so I have a close button which is intended to close the camera, so that the camera preview should be stopped.
If I open the camera, close, open again, I will get the following exception once the close button is clicked for the second time:
System.Runtime.InteropServices.COMException: 'The video recording device is preempted by another immersive application.
I do not know, how the preview camera should be stopped, more than UWP docs say here: https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/simple-camera-preview-access
The code for stopping the camera preview:
private async Task CleanupCameraAsync()
{
if (_mediaCapture != null)
{
if (_isPreviewing)
{
await _mediaCapture.StopPreviewAsync();
}
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
CameraPreviewControl.Source = null;
if (_displayRequest != null)
{
_displayRequest.RequestRelease();
}
_mediaCapture.Dispose();
});
}
}
I tried to test your code snippet on my side and it can work well. I didn't get the above exception. I tested on the emulator build 15063 and build 14393. Since your code snippet is not the completed code, so I created a minimal project for testing as follows which can work well on my side. You may test it on your side and compare with your code if something wrong with your project.
XAML
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Padding="30">
<CaptureElement Name="PreviewControl" Stretch="Uniform"/>
<Button x:Name="btnpreview" Click="btnpreview_Click" Content="preview test"></Button>
<Button x:Name="btnstop" Click="btnstop_Click" Content="stop"></Button>
</StackPanel>
Code behind
private DeviceInformation _cameraDevice;
private MediaCapture _mediaCapture;
private InMemoryRandomAccessStream _ras;
private LowLagMediaRecording _recording;
private CameraRotationHelper _rotationHelper;
private readonly DisplayRequest _displayRequest = new DisplayRequest();
private bool _isPreviewing;
public MainPage()
{
this.InitializeComponent();
}
private async void btnstop_Click(object sender, RoutedEventArgs e)
{
if (_mediaCapture != null)
{
if (_isPreviewing)
{
await _mediaCapture.StopPreviewAsync();
_isPreviewing = false;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
PreviewControl.Source = null;
if (_displayRequest != null)
{
_displayRequest.RequestRelease();
}
_mediaCapture.Dispose();
});
}
}
}
private async void btnpreview_Click(object sender, RoutedEventArgs e)
{
try
{
_mediaCapture = new MediaCapture();
var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back);
_cameraDevice = desiredDevice ?? allVideoDevices.FirstOrDefault();
_rotationHelper = new CameraRotationHelper(_cameraDevice.EnclosureLocation);
_mediaCapture.Failed += MediaCapture_Failed;
var settings = new MediaCaptureInitializationSettings { VideoDeviceId = _cameraDevice.Id };
await _mediaCapture.InitializeAsync(settings);
PreviewControl.Source = _mediaCapture;
_displayRequest.RequestActive();
await _mediaCapture.StartPreviewAsync();
_isPreviewing = true;
}
catch (UnauthorizedAccessException)
{
// This will be thrown if the user denied access to the camera in privacy settings
System.Diagnostics.Debug.WriteLine("The app was denied access to the camera");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("MediaCapture initialization failed. {0}", ex.Message);
}
}
If you still have issues, please provide a minimal reproduced project and the testing environment information. More details please reference the official sample.
I am new to developing plugins, and was wondering what causes a test plugin to hang when started i.e. Eclipse is unresponsive.
I know that my code is working as I developed a voice recognition plugin to write to the screen what is said and when I open notepad everything I say is printed to notepad.
So I was wondering, am I missing something in the plugin life-cycle that causes the IDE to hang when my plugin is started?
package recognise.handlers;
public class SampleHandler extends AbstractHandler {
public SampleHandler() {
}
/**
* the command has been executed, so extract extract the needed information
* from the application context.
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
boolean finish = false;
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
MessageDialog.openInformation(
window.getShell(),
"Recognise",
"Starting Recognition");
TakeInput start = new TakeInput();
//Stage a = new Stage();
//SceneManager scene = new SceneManager();
try {
start.startVoiceRecognition(finish);
//scene.start(a);
} catch (IOException | AWTException e) {
e.printStackTrace();
}
return null;
}
}
Does the start.startVoiceRecognition() need to be threaded?
Thanks in advance and let me know if you would like to see my manifest/activator etc.
Conclusion
Added a job separate to the UI thread
/*
* Start a new job separate to the main thread so the UI will not
* become unresponsive when the plugin has started
*/
public void runVoiceRecognitionJob() {
Job job = new Job("Voice Recognition Job") {
#Override
protected IStatus run(IProgressMonitor monitor) {
TakeInput start = new TakeInput();
try {
start.startVoiceRecognition(true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// use this to open a Shell in the UI thread
return Status.OK_STATUS;
}
};
job.setUser(true);
job.schedule();
}
As shown start.startVoiceRecognition() is running in the UI thread, and it will block the UI thread until it is finished and the app will be unresponsive during that time. So if it is doing a significant amount of work either use a Thread or use an Eclipse Job (which runs work in a background thread managed by Eclipse).
To unblock your UI you have to use Display thread.
/**
* the command has been executed, so extract extract the needed information
* from the application context.
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
boolean finish = false;
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
MessageDialog.openInformation(
window.getShell(),
"Recognise",
"Starting Recognition");
TakeInput start = new TakeInput();
//Stage a = new Stage();
//SceneManager scene = new SceneManager();
try {
start.startVoiceRecognition(finish);
//scene.start(a);
} catch (IOException | AWTException e) {
e.printStackTrace();
}
MessageDialog.openInformation(shell, "Your Popup ",
"Your job has finished.");
}
});
return null;
}
You can use Display.getDefault().asyncExec() as mentioned above, so your UI will be unblocked, while your non UI code will be executing.
// Get the camera
private void getCamera() {
if (camera == null) {
try {
camera = Camera.open();
params = camera.getParameters();
} catch (RuntimeException e) {
Log.e("Camera Error. Failed to Open. Error: ", e.getMessage());
}
}
}
// Turning On flash
private void turnOnFlash() {
if (!isFlashOn) {
if (camera == null || params == null) {
return;
}
// play sound
playSound();
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
isFlashOn = true;
// changing button/switch image
toggleButtonImage();
}
}
My code that gets involved with flash on is above, any suggestions,how to make the flash not open the moment my app opens but only when i press the button
I would guess you are calling turnFlashOn() in onCreate() and don't have a button ClickListener. But it is possible you could be calling turnFlashOn() in onStart() or onResume().
To have it turn on with a button press you should do something like
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_view);
flashlight_button = (Button) findViewById(R.id.your_button);
flashlight_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getCamera();
turnOnFlash();
}
});
}
I built an open source flashlight for Android that you can check out at Flashlight by Joe github.
I'm trying to call a MessageDialog out of a PropertyChanged Handler. The first call is always successful, but when the Dialog gets called a second time, I get an UnauthorizedAccessException.
I've tried to wrap the call in a Dispatcher, but I got the same behavior.
Here's the code (snippet of MainPage.xaml.cs):
void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
showMessage("Message", "Title");
});
}
async void showMessage(String message, String title)
{
MessageDialog dialog = new MessageDialog(message, title);
await dialog.ShowAsync();
}
Could anybody please help me with this issue?
I think your problem is that multiple property changes will cause multiple calls to display the dialog. You should only ever display one dialog at a time:
bool _isShown = false;
async void showMessage(String message, String title)
{
if (_isShown == false)
{
_isShown = true;
MessageDialog dialog = new MessageDialog(message, title);
await dialog.ShowAsync();
_isShown = false;
}
}
I have following two methods. When user clicks on start button from ui, the step geoLocator_PositionChanged in geoLocator_PositionChanged method is fired and calls the other method geoLocator_PositionChanged.But when it comes to try block while executing the first statement it throws the following error:
"The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))"
private async void btnStartStop_Click_1(object sender, RoutedEventArgs e)
{
geoLocator.PositionChanged += geoLocator_PositionChanged;
}
async void geoLocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
MessageDialog msgdlg = null;
bool bDisplayDialog = false;
try
{
lblAltValue.Text = args.Position.Coordinate.Altitude.ToString();
}
catch
{
}
}
Any help how can I fix this issue ?
You try to access the UI-Thread from another one.
Try something like ths
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync
(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
//HERE GOES THE UI ACCESS LIKE this.textbox.text = "MY AWESOME TEXT";
});