Xamarin ZXing Qr to List - c#

In my project i need contunistly read barcode and put them in a list. But while i trying it its always giving me NullReferenceException but i didn't get it. When i check it in debug i can see it have a string value but while trying put it to list its always giving me that error. Its my code for Scan and take data :
List<HoldMyString> mylist;
HoldMyString hold;
private void ZXingScannerView_OnScanResult(ZXing.Result result)
{
Device.BeginInvokeOnMainThread(() =>
{
hold.HoldString = result.Text; // HoldString is taking string value
mylist.Add(hold);
});
}
How i can put my datas in to my list contunistly. Thanks for help!

I was able to reproduce the same error with yours.
You could use the code below.
HoldMyString:
public class HoldMyString
{
public string HoldString { get; set; }
}
Code for Scan and take data:
List<HoldMyString> mylist=new List<HoldMyString>();
HoldMyString hold = new HoldMyString();
private void Handle_OnScanResult(ZXing.Result result)
{
Device.BeginInvokeOnMainThread(() =>
{
hold.HoldString = result.Text; // HoldString is taking string value
mylist.Add(hold);
});
}
For more details about how to get the barcodes, you could check the thread i done before.
How to embed ZXing scanner in PageRenderer/Fragment/View into Xamarin.Forms ContentPage?

Related

Why is the navigation page black after populating an object from a Json scan?

Good afternoon,
My first time posting after using this website for years, so I apologize for formatting and probably a dumb question I can't find the answer for... I am scanning a QR Code that contains the JSON format below and am trying to populate a "device details page" with the full object's data from the ZtdId value from the JSON received from the scanned code. The parameter passes along fine to the new page, but the screen will be black.
JSON Format:
{"Version":"1.0.0","Id":"5ca169f7-9e7b-4861-abf5-859cdb468f6e","ZtdId":"dfb0527f-64d1-4f78-85ff-50cd6fab7e6c","PKID":"","SerialNumber":"","SequenceBlockNumber":1,"TotalBlocks":1}
Black navigated page example
I have a separate collectionview page that navigates to the same "device details page" and works fine. I've tried quite a number of combinations from the code referenced below in the hyperlink and across the internet, though, I can't get the page to load at all. I realized later in my fumbling that it wasn't loading the object and placed an "if the serialnumber is blank.." operator to connect it to the data.
I've even tried passing it to a blank or about page and it loads the page fine...What am I doing wrong here? (I can confirm if I write in a bunch of Console.WriteLine entries I can expose all the fields of the device I'm trying to load from the scanned code.) I've tried going through the "Xanimals" and many other sample solutions, from the sample github repositories, but can't seem to identify why the page comes up black.
https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/shell/navigation?view=net-maui-7.0#pass-data
Scan Page relevant code:
async void BarcodesDetected(object sender, BarcodeDetectionEventArgs e)
{
try
{
var first = e.Results?.FirstOrDefault();
if (first is not null)
{
Dispatcher.Dispatch(() =>
{
barcodeGenerator.ClearValue(BarcodeGeneratorView.ValueProperty);
barcodeGenerator.Format = first.Format;
barcodeGenerator.Value = first.Value;
});
}
string Json = JToken.Parse(e.Results[0].Value).ToString();
Models.Device device = JsonConvert.DeserializeObject<Models.Device>(Json);
var navigationParameters = new Dictionary<string, object>
{
{ "Device", device }
};
await Shell.Current.GoToAsync($"devicedetails", navigationParameters);
}
catch (Exception)
{
}
}
Device Detail Page relevant code:
public Models.Device Device { get; private set; }
public void ApplyQueryAttributes(IDictionary<string, object> query)
{
Device = query["Device"] as Models.Device;
if(String.IsNullOrEmpty(Device.SerialNumber))
{
Models.Device device = DeviceData.Devices.FirstOrDefault(a => a.ZtdId == Device.ZtdId);
Device = device;
}
OnPropertyChanged("Device");
}
Device Example:
public static IList<Models.Device> Devices { get; private set; }
static DeviceData()
{
Devices = new List<Models.Device>
{
new Models.Device
{
SerialNumber = "00-000001",
Manufacturer = "Dell, Inc.",
Model = "XPS 13 9360",
PurchaseOrderNumber = "",
GroupTag = "US-EST-001",
DeploymentProfile = "Hybrid AAD",
AddressableUserName = "Jane Doe",
UserPrincipalName = "janedoe#contoso.com",
ZtdId = "dfb0527f-64d1-4f78-85ff-50cd6fab7e6c",
AzureActiveDirectoryDeviceId = Guid.NewGuid().ToString(),
ManagedDeviceId = Guid.NewGuid().ToString()
}
};
}

How I set an ui text value to a register from Firebase in Unity?

I'm working in a school project using Unity and Firebase where I need to display the username of the current user in a Text box.
I´m already get the data from Firebase but when
I try to set the userNameText's text to it, nothing happens.
This is my code:
Variables:
private DatabaseReference reference;
private string userName;
public Text userNameText;
Initialization:
void Start()
{
//database reference (I'm hiding the project id)
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://projectID.firebaseio.com/");
// Get the root reference location of the database.
reference = FirebaseDatabase.DefaultInstance.RootReference;
GetUserData();
}
GetUserData():
public void GetUserData()
{
reference.Child("users").Child(PlayerPrefs.GetString("userUID")).GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
Debug.Log("something was wrong");
}
else if (task.IsCompleted)
{
Dictionary<string, object> results = (Dictionary<string, object>)task.Result.Value;
userName= (string)results["userName"];
Debug.Log(userName);
userNameText.text = userName;
}
});
}
When I run the project, it just display the userName in the console but the text box has not yet been updated.
You're going to want to move your void method into an IEnumerator and set your reference to a variable.
IEnumerator GetUserData(){
var getTask = reference.Child("users").Child(PlayerPrefs.GetString("userUID")).GetValueAsync();
yield return new WaitUntil(() => getTask.IsCompleted || getTask.IsFaulted);
if (getTask.IsCompleted)
{
Dictionary<string, object> results = (Dictionary<string, object>)task.Result.Value;
userName= (string)results["userName"];
Debug.Log(userName);
userNameText.text = userName;
}
}
And then in your start method, you can start the coroutine. I also had the same issue with my text box disappearing. If you put up some log statements, you can see the first pass through your function reads before the call to firebase is made, and sets the text to an empty string.
void Start()
{
//database reference (I'm hiding the project id)
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://projectID.firebaseio.com/");
// Get the root reference location of the database.
reference = FirebaseDatabase.DefaultInstance.RootReference;
StartCoroutine(GetUserData());
}

Ban a variable from a list with a "ban" list

How can I ban a variable from a list without removing it from that list by adding the variable to a list of "banned" variable?
I wish to be able to type in a string. That string is compared to the file names in a folder. If there is a match, the file is read. If I type this same string again, the file should not be read again. There for I want to have a list of "banned" string that is checked whilst typing to avoid the file to be read again.
I have tried a few ways but not getting there. Below is an example of my last attempt.
What would be the best way?
public class test
{
string scl= "test3";
List <string> lsf,lso;
void Start ()
{
lsf=//file names
new List<string>();
lso=//files open
new List<string>();
lsf.Add("test0");
lsf.Add("test1");
lsf.Add("test2");
lsf.Add("test3");
lsf.Add("test4");
lso.Add("idhtk49fngo");//random string
}
void Update ()
{
if
(
Input.GetKeyDown("a")
)
{
for
(
int i=0;
i<lsf.Count;
i++
)
{
if(lsf[i]==scl)
{
Debug.Log
(i+" is read");
for
(
int j=0;
j<lso.Count;
j++
)
{
//how can i avoid reading
//lsf[3] here the second time
//"a" is pressed (by having "test3"
//added to a "ban" list (lso) )
if(scl!=lso[j])
{
lso.Add(lsf[i]);
}
}
}
}
}
}
Michael’s answer is the way to go here but it can be improved using the more appropriate collection available to keep track of opened files; if you want uniqueness use a set, not a list:
HashSet<string> openedFiles = new HashSet<string>();
public static bool TryFirstRead(
string path,
out string result)
{
if (openedFiles.Add(path))
{
result = File.ReadAllText(path);
return true;
}
result = null;
return false;
}
Also, I’d avoid throwing vexing exceptions. Give the consumer a friendly way to know if the file was read or not, don’t make them end up having to use exceptions as a flow control mechanism.
I didn't understand although if you want to replace a value from another list.
You can use the list index to create a new list with the values which you removed.
String list1 = {"hi", "hello", "World"};
String list2 = {"bye", "goodbye", "World"};
List1[1] = list2[1];
I would suggest such way:
public static List<string> openedFiles = new List<string>();
public static string ReadFileAndAddToOpenedList(string path)
{
if (openedFiles.Contains(path))
throw new Exception("File already opened");
// Instead of throwing exception you could for example just log this or do something else, like:
// Consolle.WriteLine("File already opened");
else
{
openedFiles.Add(path);
return File.ReadAllText(path);
}
}
The idea is - on every file read, add file to list, so you can check every time you try read file, if it was already read (or opened). If it is, throw exception (or do something else). Else read a file.
You could instead of making it a string list use your own class
public class MyFile
{
public string Name;
public bool isOpen;
public MyFile(string name)
{
Name = name;
isOpen = false;
}
}
List<MyFile> lsf = new List<MyFile>()
{
new MyFile("test0"),
new MyFile("test1"),
new MyFile("test2"),
new MyFile("test3"),
new MyFile("test4")
};
Than when you read the file set isOpen to true
MyFile[someIndex].isOpen = true;
and later you can check this
// E.g. skip in a loop
if(MyFile[someIndex]) continue;
You could than also use Linq in order to get a list of only unread files:
var unreadFiles = lsf.Select(f => f.Name).Where(file => !file.isOpen);

gsapi_init_with_args is made: -100

I'm trying to build a PostScript to PDF Converter using Ghostscript.Net.
The Args that GetArgs return, are the ones I usually use to call gswin32c.exe and they work fine.
But every time i call Process, i get an error Saying "An error occured when call to 'gsapi_init_with_args' is made: -100". Googling that error didn't bring anything up so I thought I might ask here.
Are there differnet arguments to consider when calling the .dll directly with Ghostscript.net? Or did I made a mistake somewhere else?
Here's my class:
public class PdfConverter
{
#region Private Fields
private List<GhostscriptVersionInfo> _Versions = GhostscriptVersionInfo.GetInstalledVersions(GhostscriptLicense.GPL | GhostscriptLicense.AFPL | GhostscriptLicense.Artifex);
#endregion
#region Private Properties
private GhostscriptVersionInfo Version { get; set; }
#endregion
#region Construction
public PdfConverter()
{
Version = GhostscriptVersionInfo.GetLastInstalledVersion();
}
#endregion
#region Public Members
public bool ConvertToPdf(DirectoryInfo dir)
{
var d = dir;
if(!d.Exists)
return false;
var postScriptFiles = d.GetFiles("*.ps");
var pdfFiles = postScriptFiles.Select(psf => new FileInfo(Path.ChangeExtension(psf.FullName, ".pdf")));
foreach(var file in postScriptFiles) {
//ThreadPool.QueueUserWorkItem(new WaitCallback((o) => {
Process(file, new FileInfo(Path.ChangeExtension(file.FullName, ".pdf")));
//}));
}
pdfFiles.ForEach(pdf => pdf?.Refresh());
return pdfFiles.All(pdf => pdf.Exists);
}
#endregion
#region Private Helpers
private void Process(FileInfo inputFile, FileInfo outputFile)
{
Console.WriteLine($"Converting {inputFile} to {outputFile}");
var proc = new GhostscriptProcessor(Version, true);
proc.Process(GetArgs(inputFile, outputFile).ToArray(), new ConsoleStdIO(true, true, true));
}
private IEnumerable<string> GetArgs(FileInfo inputFile, FileInfo outputFile)
{
return new [] {
$"-q ",
$"-sDEVICE=pdfwrite",
$"-dSAFER",
$"-dNOPAUSE",
$"-dBATCH",
$"-sPAPERSIZE=a4",
$"-dEmbedAllFonts=true",
$"-dAutoRotatePages=/None",
$"-sOutputFile=\"{outputFile.FullName}\"",
$"-dCompatibilityLevel#1.4",
$"-c .setpdfwrite",
$"-f \"{inputFile.FullName}\""
};
}
#endregion
}
Edit:
I forgot to mention: To implement it i had to make my own GhostsdcriptStdIO class. I admit that I'm not entirely sure if I did this right. Although it does get instanciated without exceptions, and override StdOut(...) get's called, and the output is written to the console as expected. override void StdError(...) get's called as well. And also written to the console as expeted.
The Output of the error btw is:
"**** Could not open the file "c:\temp\test.pdf""
"**** Unable to open the initial device, quitting."
Here's my ConsoleStdIO class:
public class ConsoleStdIO : Ghostscript.NET.GhostscriptStdIO
{
#region Construction
public ConsoleStdIO(bool handleStdIn, bool handleStdOut, bool handleStdError) : base(handleStdIn, handleStdOut, handleStdError) { }
#endregion
#region Overrides
public override void StdError(string error)
{
var foo = Encoding.Default.GetBytes(error);
var lenght = foo.Length;
using (var err = Console.OpenStandardError()) {
if(err.CanWrite)
err.Write(foo, 0, lenght);
}
}
public override void StdIn(out string input, int count)
{
byte[] bytes = new byte[0];
using(var stdInput = Console.OpenStandardInput()) {
stdInput.Read(bytes, 0, count);
}
input = Encoding.Default.GetString(bytes);
}
public override void StdOut(string output)
{
var foo = Encoding.Default.GetBytes(output);
var lenght = foo.Length;
using (var err = Console.OpenStandardError()) {
if(err.CanWrite)
err.Write(foo, 0, lenght);
}
}
#endregion
}
Again: doing the same operation with the exact same files and arguments using gswin32c.exe works fine.
Happy Hacking
Error -100 is gs_error_Fatal, which means 'something catastrophic went wrong'. Its an indication that the program failed to start up properly and we can't tell why. The back channel may contain more information.
And indeed, the back channel tells you what's wrong:
**** Could not open the file "c:\temp\test.pdf
**** Unable to open the initial device, quitting.
Ghostscript is unable to open the output file, which means it can't open the pdfwrite device (because that requires an output file) so it aborts the operation.
There could be a number of reasons why Ghostscript can't open the output file. The first thing I'd do is trim down the number of arguments;
You don't want -q (quiet) when you are trying to debug a problem, you want all the information you can get.
I'd remove -dSAFER at least to start with, because that prevents Ghostscript accessing directories outside the current working directory and certain 'special' ones. It may well prevent you accessing the temp directory.
You don't need to set EmbedAllFonts when its the same value as the default.
You could drop the CompatibilityLevel (and note that you've used a # there instead of an =) switch, and the AutoRotatePages while getting this to work.
The "-c .setpdfwrite -f" string has been pointless for years but people still keep using it. All that does these days is slow down the start of processing, ditch it.
Finally you can try changing the backslash ('\') characters to forward slash ('/') in case your string handling is messing that up, or use double backslashes (I'd use the forward slash myself).
You should also check that c:\test\temp.pdf doesn't exist, or if it does exist is not read-only or already open in a different application.
So I solved the problem...
After taking KenS' advice I could run the application without Ghostscript (not Ghostscript.NET) giving me any errors. But it did not produce an actual PDF File.
So KenS's answer did not quite solve the problem, but since 'less is more' and since he took the time to talk to me on IRC to verify that my args in itself were correct, I'll give the answer points nonetheless.
What actually solved my was the following:
Here my original GetArgs(...)
private IEnumerable<string> GetArgs(FileInfo inputFile, FileInfo outputFile)
{
return new [] {
$"-sDEVICE=pdfwrite",
$"-dNOPAUSE",
$"-dBATCH",
$"-sPAPERSIZE=a4",
#"-sFONTPATH=" + System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts),
$"-sOutputFile={outputFile.FullName}",
$"{inputFile.FullName}",
};
}
Someone in #csharp pointed out to me, that in c, the first argument is always the name of the command. So he suggested to just put "gs" as the first argument (as a dummy) and try... And that's what actually solved my problem.
So this is how the working GetArgs(...) looks:
private IEnumerable<string> GetArgs(FileInfo inputFile, FileInfo outputFile)
{
return new [] {
$"gs",
$"-sDEVICE=pdfwrite",
$"-dNOPAUSE",
$"-dBATCH",
$"-sPAPERSIZE=a4",
#"-sFONTPATH=" + System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts),
$"-sOutputFile={outputFile.FullName}",
$"{inputFile.FullName}",
};
}

JsonConvert - Can not assign string value to a string variable

public void FindCityName()
{
string url = "http://maps.google.com/maps/geo?q=39.920794,32.853902&output=json&oe=utf8&sensor=true&key=MYKEY";
var w = new WebClient();
Observable.FromEvent<DownloadStringCompletedEventArgs>(w, "DownloadStringCompleted").Subscribe(r =>
{
var deserialized = JsonConvert.DeserializeObject<RootObject>(r.EventArgs.Result);
string s = deserialized.Placemark[0].AddressDetails.Country.SubAdministrativeArea.Locality.LocalityName;
/// setCity() and City=s produce the same thing
setCity(s);
City = s;
//foreach (var item in deserialized.Placemark)
//{
// //MessageBox.Show(item.AddressDetails.Country.SubAdministrativeArea.Locality.LocalityName);
// City = (string)item.AddressDetails.Country.SubAdministrativeArea.Locality.LocalityName;
//}
//Problem here >>>>>
////MessageBox.Show(City);
});
w.DownloadStringAsync(new Uri(url));
}
Problem:
I am working on a windows phone 7 application and I need to find the "City Name" from GPS coordinates in order to move forward...
I found the code above on the internet and tried it. I can see the city name by using these codes(Message.Box(City) show exactly what I want, the city name). However, this line of code
deserialized.Placemark[0].AddressDetails.Country.SubAdministrativeArea.Locality.LocalityName;
which gives me the city name seems to give a volatile string value.
For example, I created a method which assigns the value of string variable "s" to the string field of my class, name City. If I try to get the City's content after calling FindCityName() method, I see that City's content is not updated.
Again, same thing happens then I call the code line under the comment "Problem here >>>>>" that MessageBox.Show(City) shows nothing new...
Can someone explain me the reason of my problem?
you put this question on my blog as well, but I will answer it here. I feel a bit responsible for putting up the sample code in the first place ;-)
I am going to assume the class containing your code looks like this:
public class MyClass
{
private void MyMethod()
{
FindCityName();
MessageBox.Show(City);
}
private void FindCityName()
{
// Code omitted - see your question
}
private string City;
}
There is nothing volatile about the string. Your problem is asynchronicity. If you look carefully you will see that I use an observable that fires when the DownloadStringCompleted is fired. The code inside Observable.Event is only called when the download is finished but that happens asynchronously. But what I assume you do is call the FindCityName method and then directly trying to access results like I show in the MyMethod method. That's like directly wanting the result after firing the request. The results are not in yet! It's like a web page downloading - it takes a while. You can fix that with a callback, something like this:
public class MyClass
{
private void MyMethod()
{
FindName();
}
public void FindCityName()
{
string url = "http://maps.google.com/maps/geo?q=39.920794,32.853902&output=json&oe=utf8&sensor=true&key=MYKEY";
var w = new WebClient();
Observable.FromEvent<DownloadStringCompletedEventArgs>(w, "DownloadStringCompleted").Subscribe(r =>
{
var deserialized = JsonConvert.DeserializeObject<RootObject>(r.EventArgs.Result);
City = deserialized.Placemark[0].AddressDetails.Country.SubAdministrativeArea.Locality.LocalityName;
DoneDownloading();
});
w.DownloadStringAsync(new Uri(url));
}
private string City;
private void DoneDownloading
{
MessageBox.Show(City);
}
}
Does that help?
I would recommend you to use this Google Map API
http://maps.googleapis.com/maps/api/geocode/json?latlng=39.920794,32.853902&sensor=true
And once you get JSON response in your request. You can parse easily with NEWTONSOFT for wp7
WebClient wc = new WebClient();
var json = (JObject)JsonConvert.DeserializeObject(wc.DownloadString(url));
var locality= json["results"]
.SelectMany(x => x["address_components"])
.FirstOrDefault(t => t["types"].First().ToString() == "locality");
var name = locality!=null ? locality["long_name"].ToString() : "";

Categories

Resources