How to clear the WorkStatus create by WorkManager in Android? - android-architecture-components

I create some OneTimeWorkRequest When I use the android-arch work WorkManager.
I can watch WorkStatus by observer like this
final WorkManager workManager = WorkManager.getInstance();
final LiveData<List<WorkStatus>> workStatus =
workManager.getStatusesByTag(DailyWorker.DAILY_WORK);
observer = new Observer<List<WorkStatus>>() {
#Override public void onChanged(#Nullable List<WorkStatus> workStatuses) {
Log.d("WorkManager", "onChanged = workStatuses = " + workStatuses);
if (workStatuses == null || workStatuses.size() == 0) {
//DailyWorker.createNewPeriodWork();
} else {
Log.d("WorkManager ", "onChanged = workStatuses.size() = " + workStatuses.size());
for (int i = 0; i < workStatuses.size(); i++) {
Log.d("WorkManager ", "onChanged Work Status Id: " + workStatuses.get(i).getId());
Log.d("WorkManager ", "onChanged Work Status State: " + workStatuses.get(i).getState());
}
}
workStatus.removeObserver(observer);
}
};
workStatus.observe(this, observer);
My Android arch version is android.arch.work:work-runtime:1.0.0-alpha02
But there are a lot of WorkStatus in the list,some SUCCEEDED ,some ENQUEUED , some CANCELLED, and the number of the list continue increase.
how can I clear the WorkStatus List?

You can call the method pruneWork() on your WorkManager to clear the List<WorkStatus>.
myWorkManager.pruneWork();
Hope it helps!

You can call WorkRequest#keepResultsForAtLeast when you make the work

Related

ESP32 WifiClientSecure no response

I'm working on a project using a google script to publish images from an ESP32-CAM to google drive.
I keep getting the error "no response", no matter how long I set the wait peroid to. I tried using http and https(wificlient and wificlientsecure) but it doesn't work no matter what.
What could be the issue?
WiFiClientSecure clienthttps;
Serial.println("Connect to " + String(myDomain));
if (clienthttps.connect(myDomain, 443)) {
Serial.println("Connection successful");
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
delay(1000);
ESP.restart();
return;
}
char *input = (char *)fb->buf;
char output[base64_enc_len(3)];
String imageFile = "";
for (int i = 0; i < fb->len; i++) {
base64_encode(output, (input++), 3);
if (i % 3 == 0) imageFile += urlencode(String(output));
}
String Data = myFilename + mimeType + myImage;
esp_camera_fb_return(fb);
Serial.println("Send a captured image to Google Drive.");
Serial.println("POST " + myScript + " HTTP/1.1");
Serial.println("Host: " + String(myDomain));
Serial.println("Content-Length: " + String(Data.length() + imageFile.length()));
Serial.println("Content-Type: application/x-www-form-urlencoded");
Serial.println(Data);
Serial.println();
clienthttps.println("POST " + myScript + " HTTP/1.1");
clienthttps.println("Host: " + String(myDomain));
clienthttps.println("Content-Length: " + String(Data.length() + imageFile.length()));
clienthttps.println("Content-Type: application/x-www-form-urlencoded");
clienthttps.println();
clienthttps.print(Data);
int Index;
for (Index = 0; Index < imageFile.length(); Index = Index + 1000) {
clienthttps.print(imageFile.substring(Index, Index + 1000));
}
Serial.println("Waiting for response.");
long int StartTime = millis();
while (!clienthttps.available()) {
Serial.print(".");
delay(100);
if ((StartTime + waitingTime) < millis()) {
Serial.println();
Serial.println("No response.");
//If you have no response, maybe need a greater value of waitingTime
break;
}
}
Serial.println();
while (clienthttps.available()) {
Serial.print(char(clienthttps.read()));
}
} else {
Serial.println("Connected to " + String(myDomain) + " failed.");
}
clienthttps.stop();
Note that in the latest "github.com/espressif/arduino-esp32" (as at 17Jan23) the command
"WiFiClientSecure.println();" (your "clienthttps.println()") seems to corrupt the SSL-buffer somehow, and although the command returns after a bit, the SSL-connection fails at that point (this didn't happen in earlier versions of the software).
The solution which worked for me was to ensure I at very least sent "WiFiClientSecure.println(" ");" (ie. " \r\n") as this seems to work.
(This solution appears also often necessary if sending data over a GPRS connection because in that instance a ".println()" seems to be ingored!)

JavaFX App: creating a user-feedback, that the program is still working

I'm working on a Tool to read XML-files from a collection and write the information into a text-file. This process can take a few seconds and my program gets the "no response" in the title ...
Is there a simple way to inform the user, that the program is still working? like implementing a loading image or a 3-dot animation with a Label?
I have no experience with this topic
This is the current method to read the files and write the txt:
#FXML
public void FullFilterAndExport() throws JAXBException, IOException {
totalFilesCount = 0;
totalFilesCountPositive = 0;
PrintWriter pWriter = new PrintWriter(new BufferedWriter(new FileWriter(DB_Path.toString() + "\\export_full.txt")));
for(String file: FileList) {
if (file.endsWith(".xml") && !file.contains("databaseinfo.xml")) {
totalFilesCount = totalFilesCount +1;
ItemList.clear();
JAXBContext context = JAXBContext.newInstance(NotesDocumentMetaFile.class);
Unmarshaller um = context.createUnmarshaller();
NotesDocumentMetaFile docMetaFile = (NotesDocumentMetaFile) um.unmarshal(new FileReader(file));
for(int i = 0; i < docMetaFile.getItems().size(); i++) {
if(docMetaFile.getItems().get(i).getValueIsSpecial() == true) {
ItemList.add("Itemname:" + docMetaFile.getItems().get(i).getName());
}
}
if(!ItemList.isEmpty()) {
totalFilesCountPositive = totalFilesCountPositive + 1;
pWriter.println(file);
pWriter.println();
for(String item : ItemList) {
pWriter.println(item);
}
pWriter.println();
}
}
}
pWriter.println();
pWriter.println("------------------");
pWriter.println("Anzahl der geprüften Dateien: " + totalFilesCount);
pWriter.println("Anzahl der geprüften positiven Dateien: " + totalFilesCountPositive);
if (pWriter != null){
pWriter.flush();
pWriter.close();
}
}

Catch incoming emails and send them to a web service (rather than just to a mail server)

I would like to catch incoming emails and send them a web service (rather than just to a mail server).
--
After some searching I found a way of getting new emails via polling - see below: This may be of some help to others. Is there a way to receive messages by SMTP? Perhaps by ISAPI ???
using Limilabs.Mail;
using Limilabs.Client.IMAP;
public ActionResult checkIMAPmail()
{
string rval = "not a sausage";
using (Imap imap = new Imap())
{
imap.Connect(<mail server>);
imap.Login(<username>, <password>);
imap.SelectInbox();
List<long> uids = imap.Search(Flag.Unseen);
foreach (long uid in uids)
{
byte[] ourBytes = imap.GetMessageByUID(uid);
IMail email = new MailBuilder().CreateFromEml(ourBytes);
rval = email.Subject + " [" + email.From + "][" + email.Text + "]";
}
imap.Close();
}
return Content(rval, "text/html");
}
See also http://stackoverflow.com/questions/670183/accessing-imap-in-c-sharp
for other IMAP packages, although note the change to using byte[], above.
Given that Limilabs.Mail is a paid service, I finally used MailKit:
using MailKit;
public int checkIMAPmail()
{
int numEmails = 0;
try {
using (var client = new MailKit.Net.Imap.ImapClient())
{
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(ourSmtpClient);
// disable the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
client.Authenticate(ourSmtpAdminUser, ourSmtpAdminUserPwd);
// The Inbox folder is always available on all IMAP servers...
var inboxFolder = client.Inbox;
var savedFolder = client.GetFolder("saved");
inboxFolder.Open(FolderAccess.ReadWrite);
for (int ii = 0; ii < inboxFolder.Count; ii++)
{
var query = MailKit.Search.SearchQuery.NotSeen;
foreach (var uid in inboxFolder.Search(query))
{
var thisMsg = inboxFolder.GetMessage(uid);
string thisDate = notNullString(thisMsg.Date);
string thisSubject = notNullString( thisMsg.Subject);
string thisBody = notNullString(thisMsg.GetTextBody(0)); // plain text
string thisFromName = "";
string thisFromEmail = "";
if ( thisMsg.From != null)
{
// just get the first
foreach( var mb in thisMsg.From.Mailboxes)
{
thisFromName = notNullString( mb.Name);
thisFromEmail = notNullString( mb.Address);
break;
}
}
numEmails += 1;
// move email to saved
inboxFolder.MoveTo(uid, savedFolder);
}
}
client.Disconnect(true);
}
}
catch (Exception exc)
{
log2file("checkIMAPmail Error: " + exc.ToString());
}
return numEmails;
}

replacing a submitlink with indicatingAjaxButton

I have a form with a submitbutton which will get results from a database and updates a listview based on these results. If there is no result, a feedback message is shown. This all works fine.
Now I want to replace the submitlink with an IndicatingAjaxButton, so the user can see something happening when getting the result takes a long time.
The basic idea is this:
IndicatingAjaxButton submitLink = new IndicatingAjaxButton("submit", form) {
private static final long serialVersionUID = -4306011625084297054L;
#Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
Integer hourFrom = 0;
Integer hourTo = 0;
Integer minuteFrom = 0;
Integer minuteTo = 0;
hourFrom = Integer.parseInt(hour_from.getModelObject());
hourTo = Integer.parseInt(hour_to.getModelObject());
minuteFrom = Integer.parseInt(minute_from.getModelObject());
minuteTo = Integer.parseInt(minute_to.getModelObject());
Calendar from = Calendar.getInstance();
Calendar to = Calendar.getInstance();
Date dateFrom = date_from.getModelObject();
Date dateTo = date_to.getModelObject();
from.setTime(dateFrom);
to.setTime(dateTo);
from.set(Calendar.HOUR, hourFrom);
from.set(Calendar.MINUTE, minuteFrom);
to.set(Calendar.HOUR, hourTo);
to.set(Calendar.MINUTE, minuteTo);
if (topicQueueSelect.getModelObject() == null) {
error("Please select a message name.");
getSession().setAttribute("error", "");
}
if (to.before(from)) {
error("Date to must be after date from.");
getSession().setAttribute("error", "");
}
cal.setTimeInMillis(System.currentTimeMillis());
if (from.after(cal)) {
error("Date from must be in the past.");
getSession().setAttribute("error", "");
}
if (getSession().getAttribute("error") != null) {
getSession().removeAttribute("error");
return;
}
page.setModelObject(1);
List<Search> searchFields = (List<Search>) searchFieldsField
.getModelObject();
messageKeyDataList = messageController.search(
topicQueueSelect.getModelObject(), searchFields,
from.getTime(), to.getTime(),
maxResults.getModelObject(), page.getModelObject(),
sortorder);
if (messageKeyDataList.size() == 0) {
info("Search criteria didn't produce any results.");
result.setList(messageKeyDataList);
resultContainer.setVisible(false);
return;
}
resultContainer.setVisible(true);
resultSize = messageController.getResultSize();
int pages = (int) Math.ceil((float) resultSize
/ maxResults.getModelObject());
ArrayList<Integer> pageNumbers = new ArrayList<Integer>();
for (int n = 1; n <= pages; n++) {
pageNumbers.add(n);
}
page.setChoices(pageNumbers);
pageunder.setChoices(pageNumbers);
showing.setDefaultModelObject("Showing 1 to "
+ messageKeyDataList.size() + " out of " + resultSize
+ " messages");
lastSearch.put("topicQueue", topicQueueSelect.getModelObject());
lastSearch.put("searchFields", searchFields);
lastSearch.put("from", from.getTime());
lastSearch.put("to", to.getTime());
lastSearch.put("maxResults", maxResults.getModelObject());
result.setList(messageKeyDataList);
target.add(feedback);
}
};
The SubmitLink does show me either the ResultView with the new list, or the info message, the IndicatingAjaxButton doesn't. I know the form submit is called, because the system.out is being printed.
Any suggestions on this?
SubmitLink is non-Ajax component. Using it will repaint the whole page!
IndicatingAjaxButton is an Ajax component. You need to use the passed AjaxRequestTarget to add components which should be repainted with the Ajax response. For example the FeedbackPanel should be added to the AjaxRequestTarget.
I found that I had to do setOutputMarkupPlaceholderTag(true) on both the resultContainer and the feedback. After that adding them to the requesttarget works as expected.

Visual Studio If statement always going through

For some reason the If statements are always going through no matter what I put. Even if i did things like True == False or 0 == 1 it still goes through. What I am trying to do is detect if the text is null and set it to - so it doesn't error.
This is my code inside the button
private void SearchButton_Click(object sender, EventArgs e)
{
reg = String.IsNullOrWhiteSpace(RegText.Text);
if (reg == true);
{
RegText.ResetText();
RegText.AppendText("-");
}
model = String.IsNullOrWhiteSpace(ModelText.Text);
if (model == true) ;
{
ModelText.ResetText();
ModelText.AppendText("-");
}
for (int i = 0; i < MaxCars; i++)
{
if (regos[i].Equals(Convert.ToString(RegText.Text)) || models[i].Equals(Convert.ToString(ModelText.Text)) || price[i] == Convert.ToInt32(PriceText.Text))
{
Console.WriteLine(regos[i] + " " + models[i] + " " + price[i]);
}
}
}
You have put ; at the end of every if that is causing an error.
This is the code with fix:
private void SearchButton_Click(object sender, EventArgs e)
{
reg = String.IsNullOrWhiteSpace(RegText.Text);
if (reg == true)
{
RegText.ResetText();
RegText.AppendText("-");
}
model = String.IsNullOrWhiteSpace(ModelText.Text);
if (model == true)
{
ModelText.ResetText();
ModelText.AppendText("-");
}
for (int i = 0; i < MaxCars; i++)
{
if (regos[i].Equals(Convert.ToString(RegText.Text)) || models[i].Equals(Convert.ToString(ModelText.Text)) || price[i] == Convert.ToInt32(PriceText.Text))
{
Console.WriteLine(regos[i] + " " + models[i] + " " + price[i]);
}
}
}

Resources