Hallo,
Ich habe ein Xamarin Forms (4.2.0.709249) Projekt.
Ich nutzte das Plugin Xam.Plugin.Media (4.0.1.5) um Fotos zu machen.
Ich nutze das Plugin ZXing.Net.Mobile.Forms (2.4.1) um Barcodes zu scannen.
Für ZXing habe ich im MainPage
Konstruktor nach Anleitung folgendes hinzugefügt:
ZXing.Net.Mobile.Forms.WindowsUniversal.ZXingScannerViewRenderer.Init();
Und für das Xam.Plugin.Media habe ich nach Anleitung die Webcam Capability aktiviert.
Das folgende Problem tritt nur bei UWP auf. Bei Android und iOS Geräten habe ich kein Problem.
Testgerät: Microsoft Surface, Windows 10 Pro, mit zwei Kameras.
Nennen wir die Kameras mal Frontkamera und Webcam.
Zum Scannen von Barcodes wird die Frontkamera verwendet und es gibt keine Möglichkeit die Kamera zu wechseln.
Nach der Installation kann ich problemlos beliebig Barcodes scannen.
Öffne ich dann einmal die Kamera über meine App um ein Foto zu machen und stelle auch hier die Frontkamera ein kann ich danach keine Barcodes mehr scannen.
Der Bildschirm bleibt einfach weiß.
Um wieder Barcodes scannen zu können muss ich entweder
Sowohl die Windows App "Kamera" als auch die von mir aufgerufenen Kamera scheinen beide die Windows App "Kamera" aufzurufen.
Das Problem wird durch einen Neustart meiner App auch nicht behoben.
Ich habe mir zu dem Problem ein Testprojekt gebaut. Dazu habe ich ein Xamarin.Forms Projekt mit der Vorlage Master-Detail in Visual Studio angelegt.
In der About.xaml habe ich zwei Buttons unter dem "Learn more" Button hinzugefügt:
<Button
Margin="0,10,0,0"
BackgroundColor="{StaticResource Primary}"
Command="{Binding ScanCommand}"
Text="Scan"
TextColor="White" />
<Button
Margin="0,10,0,0"
BackgroundColor="{StaticResource Primary}"
Command="{Binding TakePhotoCommand}"
Text="TakePhoto"
TextColor="White" />
Mein AboutViewModel sieht so aus:
public class AboutViewModel : BaseViewModel
{
public ICommand OpenWebCommand { get; }
public ICommand ScanCommand { get; }
public ICommand TakePhotoCommand { get; }
public AboutViewModel()
{
Title = "About";
OpenWebCommand = new Command(() => Device.OpenUri(new Uri("https://xamarin.com/platform")));
ScanCommand = new Command(async () => await ScanAsync());
TakePhotoCommand = new Command(async () => await TakePhotoAsync());
}
private async Task ScanAsync()
{
var camera = new Camera();
await camera.ScanBarcode(p => Application.Current?.MainPage?.DisplayAlert("Barcode", p, "ok"));
}
private async Task TakePhotoAsync()
{
var camera = new Camera();
await camera.TakePhoto(p => { });
}
}
Und meine Klasse Camera sieht so aus:
public class Camera
{
public Task TakePhoto(Action<MediaFile> onPhotoTakenAction, Action noCameraAction = null)
{
return TakePhoto(null, onPhotoTakenAction, noCameraAction);
}
public async Task TakePhoto(string directory, Action<MediaFile> onPhotoTakenAction, Action noCameraAction = null)
{
if (!await IsCameraAvailable())
{
noCameraAction?.Invoke();
return;
}
var mediaOptions = new StoreCameraMediaOptions();
mediaOptions.MaxWidthHeight = 1024;
mediaOptions.PhotoSize = PhotoSize.MaxWidthHeight;
mediaOptions.Name = Guid.NewGuid().ToString("N") + ".jpg";
mediaOptions.CompressionQuality = 50;
if (!string.IsNullOrEmpty(directory))
mediaOptions.Directory = directory;
var photo = await CrossMedia.Current.TakePhotoAsync(mediaOptions);
if (photo != null)
onPhotoTakenAction(photo);
}
public async Task ScanBarcode(Action<string> onScannedAction)
{
if (!await IsCameraAvailable())
return;
ZXingScannerPage scanPage;
var stackLayout = new StackLayout();
stackLayout.HorizontalOptions = LayoutOptions.FillAndExpand;
stackLayout.VerticalOptions = LayoutOptions.FillAndExpand;
var cancelButton = new Button();
cancelButton.VerticalOptions = LayoutOptions.EndAndExpand;
cancelButton.HorizontalOptions = LayoutOptions.EndAndExpand;
cancelButton.Text = "Cancel";
stackLayout.Children.Add(cancelButton);
scanPage = new ZXingScannerPage(MobileBarcodeScanningOptions.Default, stackLayout);
cancelButton.Clicked += async (sender, args) =>
{
await scanPage.Navigation.PopModalAsync();
};
scanPage.OnScanResult += result =>
{
scanPage.IsScanning = false;
Device.BeginInvokeOnMainThread(async () =>
{
await scanPage.Navigation.PopModalAsync();
if (!string.IsNullOrEmpty(result.Text))
onScannedAction(result.Text);
});
};
await Application.Current.MainPage.Navigation.PushModalAsync(scanPage);
}
private async Task<bool> IsCameraAvailable()
{
var isInitialized = await CrossMedia.Current.Initialize();
var isCameraAvailable = false;
if (isInitialized)
isCameraAvailable = CrossMedia.Current.IsCameraAvailable;
return isCameraAvailable;
}
}
Alternativ habe ich den Zugriff auf die Kamera ohne das Plugin.Media mit Hilfe des DependencyServices realisiert. Gleiches Ergebnis...
[assembly: Dependency(typeof(Camera_UWP))]
namespace CameraScanTest.UWP
{
public class Camera_UWP : ICamera
{
public async Task TakePhoto()
{
CameraCaptureUI captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.CroppedSizeInPixels = new Windows.Foundation.Size(200, 200);
StorageFile photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (photo == null)
{
// User cancelled photo capture
return;
}
}
}
}
Habt ihr nützliche Tips für mich?
Viele Grüße
Urza
“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”
Ich hab ZXing schon länger nicht mehr benutzt (und für UWP noch nie), aber solche Probleme hingen bei meinen iOS/Android-Projekten fast immer mit Rechten zusammen. Sprich aus irgend einem Grund möchte das Smartphone gerade nicht, dass du auf die Kamera zugreifen kannst.
So wie ich dein Problem lese fehlt irgend eine weitere Berechtigung im Manifest (Kamera wechseln o.ä. wie gesagt, ich weiß nicht welche Rechte bei UWP speziell festgelegt werden können).
Ich erinnere mich dunkel daran, dass es bei ZXing mal ein Problem mit dem Flashlight gab. Also Fehler auftraten, wenn du keine Rechte zum Nutzen des Flashlights angefordert hast (obwohl es nicht verwendet wird). Ist aber schon 2-3 Jahre her, dass ich damit zu tun hatte.
Beste Grüße
emuuu
2+2=5( (für extrem große Werte von 2)
Hallo emuuu,
danke für die Antwort.
Ich habe gerade mal einfach alle Capabilities aktiviert. Keine Änderung.
Grundsätzlich klappt ja sowohl das wechseln der Kamera als auch das Scannen von Barcodes.
Es ist nur die Kombination von beidem...
Viele Grüße
Urza
“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”
Was liefert denn IsCameraAvailable
zurück?
Ohne dir eine genaue Lösung zu liefern, liest es sich so, als wenn die Camera im Gerät einfach "blockiert" ist, evtl. muss sie explizit wieder freigegeben werden.
Was passiert, wenn du deine Kamera-App, die augenscheinlich für die Blockade zuständig ist, schließt - kannst du dann wieder Barcodes scannen?
Hallo Urza,
da ich selbiges Szenario habe aber die Kombination unter UWP so noch nicht getestet habe, hier meine Ergebnisse:*Barcodescan mit der Webcam: OK *Kamera Aufnahme mit der Webcam: OK *Barcodescan mit der Webcam: OK *Kamera Aufnahme mit der Haupt-Kamera: OK *Barcodescan mit der Webcam: OK
Über eine Einrichtung in einer Datenbank kann ich den Barcodescan ebenfalls mit der Hauptkamera tätigen. Das hat aber unter UWP nach wie vor die Webcam geöffnet. Ohne erst die Hauptkamera zu starten.
Unter Android wechselt die Webcam und Hauptkamera freudig hin und her, je nach dem wie ich den Haken setze.
Surfacebook 1
Xamarin Forms 3.6.0.539721
ZXing: 2.4.1
Xam.Plugin.Media: 4.0.1.5
Und ja, ich weiß: Die Forms Version ist veraltet. Sobald ich diese hochziehe, läuft die Anwendung aber nicht mehr unter Android 4.0.3. Bzw. sie startet, man kann sie aber nicht mehr bedienen, da Pop & Push nix mehr machen.
Hallo p!lle,
IsCameraAvailable
liefert true zurück.
Sonst würde sich der Scanner/die Foto-App gar nicht erst öffnen. In der ursprünglichen Anwendung bekommt der Nutzer dann einen entsprechenden Hinweis.
Die Methode prüft aber nicht ob die Kamera blockiert ist o.ä. sondern fragt nur ab, ob das Gerät eine Kamera verbaut hat.
Das Initialize()
wird auch im Beispiel des Plugin-Erstellers vor jedem Aufruf der Kamera aufgerufen...
Was passiert, wenn du deine Kamera-App, die augenscheinlich für die Blockade zuständig ist, schließt - kannst du dann wieder Barcodes scannen?
Das mache ich immer. Ohne meine Kamera-App zu schließen kann ich die App nicht weiter bedienen. Die Kamera-App ist quasi ein modales Fenster.
...liest es sich so, als wenn die Camera im Gerät einfach "blockiert" ist
Ja das sehe ich auch so, wie ich ich auch im Titel des Beitrags angedeutet habe. Aber ich habe bisher noch keine Möglichkeit gefunden die "Blockade" aufzuheben. Für die Windows eigene Kamera-App ist die Kamera ja auch wiederum nicht blockiert.
Btw.: Der Code wie er im Dependency-Service steht ist ein 1:1 Kopie aus den Microsoft docs...
Viele Grüße
Urza
“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”
Hallo trib,
danke, dass du dir die Mühe gemacht hast das Problem nachzuvollziehen.
Ich habe beim Nachvollziehen deiner Schritte noch folgendes festgestellt.
Öffne ich die Kamera und mache tatsächlich ein Foto läuft alles super.
Öffne ich die Kamera und schließe sie ohne ein Foto zu machen oder verwerfe ich das gemachte Foto dann habe ich das besagte Problem, dass ich keine Barcodes mehr scannen kann.
Viele Grüße
Urza
“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”
Auch für mich liest sich das so, dass die Camera blockiert it.
Ich würde hier zwei Dinge mal prüfen:
Soweit ich ZXing noch in Erinnerung hatte, muss man bei einem Page Wechsel zB das Scannen von Barcodes deaktivieren und bei einer anderen Page entsprechend wieder aktivieren.
Bei Dir wird das Scannen nur deaktiviert, wenn etwas gefunden wurde
scanPage.OnScanResult += result =>
{
scanPage.IsScanning = false;
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hallo Abt,
danke für die Hilfe.
Ich habe alle relevanten Typen überprüft. Ich kann nirgendwo ein Dispose, Close o.ä. aufrufen.
Den Tip mit dem IsScanning = false
habe ich gerade mal getestet.
cancelButton.Clicked += async (sender, args) =>
{
scanPage.IsScanning = false;
await scanPage.Navigation.PopModalAsync();
};
Leider ohne Erfolg.
“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”
Hallo zusammen,
hier ein kleines Update.
Die Kamera wird tatsächlich von der Windows-Kamera App blockiert.
Schließe ich die Kamera in meiner App, ohne ein Foto zu machen, taucht im Task-Manager ein "Kamera" Prozess auf.
Solange dieser Prozess nicht beendet wird kann keine andere App mehr auf die Kamera zugreifen.
Es liegt wohl auch nicht an meiner App. Ich habe testweise die App "Ultimate Photo Editor" installiert. Dort kann ich das Verhalten auch reproduzieren.
Leider kann ich den Prozess in UWP nicht einfach beenden...
Viele Grüße
Urza
“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”