I have just created a two page MVVM solution using Prism. The MainPage has a single button that navigates to a BarcodePage. The BarcodePage only contains the Barcode, but the back navigation is available in the status bar. The BarCodeValue is bound to a string on the view model.
When I navigate back from the BarcodePage to the MainPage in Android I get a SystemArgumentException: Found Empty Contents. When I hard code a value for BarCodeValue within the xaml everything works, and there is no problem in iOS.
I have the following NuGets installed:
Xamarin.Forms v3.1.0.637273
ZXing.Net.Mobile v2.4.1
ZXing.Net.Mobile.Forms v2.4.1
Xamarin.Android.Support packages all v25.4.0.2
Prism.Dryloc.Forms v7.0.0.396
I believe the call stack for the error looks like this:
QRCodeWriter.encode (System.String contents, ZXing.BarcodeFormat format, System.Int32 width, System.Int32 height, System.Collections.Generic.IDictionary`2[TKey,TValue] hints)
MultiFormatWriter.encode (System.String contents, ZXing.BarcodeFormat format, System.Int32 width, System.Int32 height, System.Collections.Generic.IDictionary`2[TKey,TValue] hints)
BarcodeWriterGeneric.Encode (System.String contents)
BarcodeWriter`1[TOutput].Write (System.String contents)
ZXingBarcodeImageViewRenderer+<>c__DisplayClass5_0.
Thread+RunnableImplementor.Run ()
Any help would be greatly appreciated.
Thanks,
Andrew
I faced the same exact issue, with a quick help from my colleague @ak47akshaykulkarni directed me to a solution here: https://stackoverflow.com/questions/37673628/exception-in-zxingbarcodeimageview-when-removing-from-observablecollection
Check out the reply from 'Julian Radowsky' in there, I tried it myself and got it to work.
Such a simple solution, looking at the ZXing.Net.Mobile.Forms Android Renderer implementation, the code itself is not very well done.
Just get the ZXingBarcodeImageViewRenderer's code and override that with your own Renderer in your Android project, by replacing the following code.
if (formsView != null && formsView.BarcodeValue != null)
to this,
if (formsView != null && !string.IsNullOrWhiteSpace(formsView.BarcodeValue))
As you can see what they have missed is a simple null or white space check at run time.
Hope you figured it out.
Cheers! :)
Thanks for your reply,
I did stumble across that solution, but I came up with a different workaround as I wasn't too confident about going into the renderers.
I added a hidden Entry onto the view and bound its Text property to the Barcode property in the view model.I then added a TextChanged handler for the Entry in the code behind, which updates the BarCodeValue property of the ZXingBarCodeImageView to the value of the Entry.Text.
I was happy enough with this solution. It doesn't really break the MVVM pattern because the code behind is only accessing properties within the view, and the update of the view is still done through the binding.
Thanks again,
Andrew
The same error with prism navigation...
`System.ArgumentException: Found empty contents
11-01 23:34:49.262 D/Mono (19005): DllImport attempting to load: '/system/lib64/liblog.so'.
11-01 23:34:49.264 D/Mono (19005): DllImport loaded library '/system/lib64/liblog.so'.
11-01 23:34:49.265 D/Mono (19005): DllImport searching in: '/system/lib64/liblog.so' ('/system/lib64/liblog.so').
11-01 23:34:49.265 D/Mono (19005): Searching for '__android_log_print'.
11-01 23:34:49.265 D/Mono (19005): Probing '__android_log_print'.
11-01 23:34:49.265 D/Mono (19005): Found as '__android_log_print'.
11-01 23:34:49.276 I/MonoDroid(19005): UNHANDLED EXCEPTION:
11-01 23:34:49.320 I/MonoDroid(19005): System.ArgumentException: Found empty contents
11-01 23:34:49.320 I/MonoDroid(19005): at ZXing.QrCode.QRCodeWriter.encode (System.String contents, ZXing.BarcodeFormat format, System.Int32 width, System.Int32 height, System.Collections.Generic.IDictionary2[TKey,TValue] hints) [0x00008] in <ccd33a3710ff407d90a31fb75c8c27de>:0
11-01 23:34:49.320 I/MonoDroid(19005): at ZXing.MultiFormatWriter.encode (System.String contents, ZXing.BarcodeFormat format, System.Int32 width, System.Int32 height, System.Collections.Generic.IDictionary2[TKey,TValue] hints) [0x00033] in
11-01 23:34:49.320 I/MonoDroid(19005): at ZXing.BarcodeWriterGeneric.Encode (System.String contents) [0x0002f] in
11-01 23:34:49.320 I/MonoDroid(19005): at ZXing.BarcodeWriter`1[TOutput].Write (System.String contents) [0x00013] in
11-01 23:34:49.320 I/MonoDroid(19005): at ZXing.Net.Mobile.Forms.Android.ZXingBarcodeImageViewRenderer+<>c__DisplayClass5_0.
11-01 23:34:49.320 I/MonoDroid(19005): at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in
11-01 23:34:49.320 I/MonoDroid(19005): at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00009] in
11-01 23:34:49.320 I/MonoDroid(19005): at (wrapper dynamic-method) System.Object.52(intptr,intptr)
11-01 23:34:49.335 W/zygote64(19005): JNI RegisterNativeMethods: attempt to register 0 native methods for android.runtime.JavaProxyThrowable
11-01 23:34:49.340 D/Mono (19005): DllImport searching in: '__Internal' ('(null)').
11-01 23:34:49.340 D/Mono (19005): Searching for 'java_interop_jnienv_throw'.
11-01 23:34:49.340 D/Mono (19005): Probing 'java_interop_jnienv_throw'.
11-01 23:34:49.340 D/Mono (19005): Found as 'java_interop_jnienv_throw'.
An unhandled exception occured.
11-01 23:34:51.709 E/mono (19005):
11-01 23:34:51.709 E/mono (19005): Unhandled Exception:
11-01 23:34:51.709 E/mono (19005): System.ArgumentException: Found empty contents
11-01 23:34:51.709 E/mono (19005): at (wrapper dynamic-method) System.Object.52(intptr,intptr)
11-01 23:34:51.710 E/mono-rt (19005): [ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: Found empty contents
11-01 23:34:51.710 E/mono-rt (19005): at (wrapper dynamic-method) System.Object.52(intptr,intptr)`
This error only shows with navigation prism, it is a framework error????
How to fix it?
Thanks for your reply,
I did stumble across that solution, but I came up with a different workaround as I wasn't too confident about going into the renderers.
I added a hidden Entry onto the view and bound its Text property to the Barcode property in the view model.I then added a TextChanged handler for the Entry in the code behind, which updates the BarCodeValue property of the ZXingBarCodeImageView to the value of the Entry.Text.
I was happy enough with this solution. It doesn't really break the MVVM pattern because the code behind is only accessing properties within the view, and the update of the view is still done through the binding.
Thanks again,
Andrew
Please, can you put the example?
@angelru
Following is my implementation with a hidden entry field. I didn't use the TextChange event as it was suggested by @abailie
I just bound the 'Text' field of the entry (source) to the 'BarcodeValue' of the zxing (target)
<!-- Not Visible Entry -->
<Entry x:Name="EntryPhoneNumber" Text="{Binding MyBarCodeValue}" IsVisible="False"/>
<zx:ZXingBarcodeImageView BarcodeFormat="CODE_128"
BindingContext="{x:Reference Name=EntryPhoneNumber}"
BarcodeValue="{Binding Path=Text}">
<zx:ZXingBarcodeImageView.BarcodeOptions>
<zxcm:EncodingOptions Height="120" Width="1000" />
</zx:ZXingBarcodeImageView.BarcodeOptions>
</zx:ZXingBarcodeImageView>
Thanks
Dimitris
@angelru
Following is my implementation with a hidden entry field. I didn't use the TextChange event as it was suggested by @abailie
I just bound the 'Text' field of the entry (source) to the 'BarcodeValue' of the zxing (target)<!-- Not Visible Entry --> <Entry x:Name="EntryPhoneNumber" Text="{Binding MyBarCodeValue}" IsVisible="False"/> <zx:ZXingBarcodeImageView BarcodeFormat="CODE_128" BindingContext="{x:Reference Name=EntryPhoneNumber}" BarcodeValue="{Binding Path=Text}"> <zx:ZXingBarcodeImageView.BarcodeOptions> <zxcm:EncodingOptions Height="120" Width="1000" /> </zx:ZXingBarcodeImageView.BarcodeOptions> </zx:ZXingBarcodeImageView>Thanks
Dimitris
Many thanks!!!!!!!
Sorry @angelru,
Only just seeing this now. I think @gnout came up with a better solution than mine.
Andrew
I've been using the suggested solution from @gnout for the last 3 months on iOS without an issue, but today I started working with Android and things went wrong.
I think the problem is that my QR code needs to update every 2 minutes, so I'd set the binding mode on the Entry to TwoWay to achieve this. Like I say, this worked well in iOS, but it's giving the 'Found Empty Contents' exception in Android. I tried setting the ZXingBarcodeImageView's binding mode to OneWay and leaving the Entry's binding as default, but that earned me an ObjectDisposedException.
I've run out of time to play with the different combinations of binding settings to get this working properly, so I've gone back to my previous way of doing it and it's working for both Android and iOS.
For the .xaml file:
<zx:ZXingBarcodeImageView x:Name="QrCodeView"
BarcodeFormat="QR_CODE"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" >
<zx:ZXingBarcodeImageView.BarcodeOptions>
<zxcm:EncodingOptions Width="210" Height="210" />
</zx:ZXingBarcodeImageView.BarcodeOptions>
</zx:ZXingBarcodeImageView>
<Entry IsVisible="False" TextChanged="QREntry_TextChanged" Text="{Binding QrCode}"/>
Then for the .xaml.cs file:
private void QREntry_TextChanged(object sender, TextChangedEventArgs e)
{
QrCodeView.BarcodeValue = (sender as Entry)?.Text;
}
Hope this helps someone
Ok, the fix works perfectly. But... is this gonna get fixed at any point?
Are PRs accepted? I might be able to put some time aside and apply the fix that has been talked about in this thread by @UdaraAlwis to see if that fixes it.
EDIT: I mean I see that a fix has been merged but wondering why it didn't work. Or is it that it never got released?
This is fixed in the 3.0 series.
Most helpful comment
@angelru
Following is my implementation with a hidden entry field. I didn't use the TextChange event as it was suggested by @abailie
I just bound the 'Text' field of the entry (source) to the 'BarcodeValue' of the zxing (target)
Thanks
Dimitris