Going to next activity once the list is complete - java

So I am working on a project and I don't know much about the android studio. So what I am doing is, I am using jsoup as my web parser and I am creating a list of products from e-commerce websites. So I want that once I get all the details from the parser, then my next activity starts. Till now I am using handler and setting some delay time in it. But that is not helping because sometimes it takes more than 3-4 seconds.
Below is the code by which I am sending the allproduct ArrayList and producturl ArrayList
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
Bundle args = new Bundle();
args.putSerializable("ARRAYLIST", (Serializable) allproducts);
args.putSerializable("URLLINKS", (Serializable) producturl);
intent.putExtra("BUNDLE", args);
intent.putExtra(EXTRA_TEXT, searchtext);
startActivity(intent);
}
}, 6500);
Sometimes the listview shows only 2 websites result and sometimes it shows every website.
private class Snapdeal extends AsyncTask<String, Void, ArrayList<String>> {
ArrayList<String> tempurlstore = new ArrayList<>();
String link;
#Override
protected void onPostExecute(ArrayList<String> s) {
String product;
String urlstore;
super.onPostExecute(s);
for (int j = 0; j < 6; j++) {
product = s.get(j);
urlstore = tempurlstore.get(j);
allproducts.add(product);
producturl.add(urlstore);
}
String seemore = "See more products on website....";
allproducts.add(seemore);
producturl.add(link);
}
#Override
protected ArrayList<String> doInBackground(String... strings) {
try {
Document doc = Jsoup.connect(strings[0]).get();
Elements links = doc.getElementsByClass("col-xs-6 favDp product-tuple-listing js-tuple ");
ArrayList<String> mainlist = new ArrayList<String>();
mainlist.add("SNAPDEAL");
link = strings[0];
tempurlstore.add("https://www.snapdeal.com");
for (Element link : links) {
String temp1 = null, temp2 = null, temp3 = null, temp4 = null, temp5 = null;
String permanent1 = null;
Elements elLink = link.getElementsByTag("a");
Elements eltitle = link.getElementsByClass("product-title"); //for product title
Elements elpricebefore = link.getElementsByClass("lfloat product-desc-price strike ");
Elements elpriceafter = link.getElementsByClass("lfloat product-price");
Elements discount = link.getElementsByClass("product-discount");
//product title loop
for (Element titleOfProduct : eltitle) {
temp1 = "Title: " + titleOfProduct.text();
}
//product original price loop
for (Element priceOfProductBefore : elpricebefore) {
temp2 = "Price before: " + priceOfProductBefore.text();
}
//product discounted price loop
for (Element priceOfProductAfter : elpriceafter) {
temp3 = "Discounted price: " + priceOfProductAfter.text();
}
//discount in number loop
for (Element productdiscount : discount) {
temp4 = "Discount: " + productdiscount.text();
}
ArrayList<String> linkArray = new ArrayList<String>();
for (Element elementLink : elLink) {
String MainLink = elementLink.attr("href");
linkArray.add(MainLink);
}
for (int j = 0; j < 1; j++) {
temp5 = linkArray.get(0);
}
if (elpricebefore.text()==null)
{
permanent1 = "\n" + temp1 + "\n" + "Price :" + elpriceafter.text() + "\n" + temp4 + "\n";
}
else
{
permanent1 ="\n" + temp1 + "\n" + temp2 + "\n" + temp3 + "\n" + temp4 + "\n";
}
mainlist.add(permanent1);
tempurlstore.add(temp5);
}
return mainlist;
} catch (Exception e) {
ArrayList<String> exception = new ArrayList<String>();
String ex = e.toString();
exception.add(ex);
return exception;
}
}
}
Above is some part of my project. So this is how I am taking all the products and all from the parser.
So how can I do this that once all the products are ready in the Arraylist then only intent gets started?
Please help. Thank you.

Why are you using a timer instead of a callback from your parser? This is creating a race condition which is at the heart of your issue. The only way around it is to fire your intent only after your parser is complete.
Without seeing the parser code it is tough to know the exact place to add your hook.

You shouldn't use a handler for that. What you could do is use an Observer or use Android's Live Data so the one you choose can let you know when the list is ready so you can start the activity.

Related

Scanning for Network Printers On Cordova-Android

I am trying to build a plugin on cordova that can find the Bluetooth, USB and Network printer and print text, images, QR code, bar-codes... I have an issue in the network printer scanning, need some help with that. I have this code below that can search for the network printer connected to wifi. It works well with android 7 and 6 but in case of android 5, it is unable to return callback.This probably might be cause of the thread limit or something on android 5
scanWifi(ips, new OnIPScanningCallback() {
#Override
public void onScanningComplete(List<String> results) {
Log.d("TAG", "onScanningComplete: " + results.size()+" : "+results.toString());
Printers printerList =null;
for(String printerIps:results) {
String mac = getHardwareAddress(printerIps);
printerList = new Printers(printerIps, mac);
printers.put(printerIps);
list.add(printerList);
}
Log.d(TAGS,"The List of all wifi Printers : "+list);
}
});
isStart = false;
}
private static void scanWifi(final List<String> ips, final
OnIPScanningCallback callback) {
final Vector<String> results = new Vector<String>();
final int totalSize = ips.size();
final int splitSize = 10;
final int[] index = {0};
final long start = System.currentTimeMillis();
for (int i = 0; i < totalSize; i += splitSize) {
final List<String> child = new ArrayList<String>(ips.subList(i, Math.min(totalSize, i + splitSize)));
new Thread() {
#Override
public void run() {
for (String ip : child) {
Log.d("TAG", " scanning : " + index[0] + ", ip: " + ip);
boolean isPrinter = connect(ip);
if (isPrinter) {
results.add(ip);
}
if (index[0] == ips.size() - 1) {
long end = System.currentTimeMillis();
Log.d("TAG", "scanning time: " + (end - start) / 1000);
callback.onScanningComplete(results);
} else {
index[0]++;
}
}
}
}.start();
}
}
public interface OnIPScanningCallback {
void onScanningComplete(List<String> results);
}
I have also tried the async task and it works on all the versions of android but the problem is the process takes 170 to 193 secs which is way too long as in the above code it was able to do the same in 20 secs
scanWifi(ips, new PrintingPlugin.OnIPScanningCallback() {
#Override
public void onScanningComplete(List<String> results) {
Log.d(TAGS, "onScanningComplete: " + results.size() + " : " + results.toString());
Printers printerList;
for (String printerIps : results) {
String mac = getHardwareAddress(printerIps);
printerList = new Printers(printerIps, mac);
printers.put(printerIps);
list.add(printerList);
}
Log.d(TAGS, "The List of all wifi Printers : " + list);
}
});
isStart = false;
} catch (Exception e) {
Log.e(TAGS, "Error while scanning for wifi"+e.getMessage());
}
return printers;
}
private Integer index = 0;
void resetIndex() {
index = 0;
}
private void scanWifi(final List<String> ips, final PrintingPlugin.OnIPScanningCallback callback) {
Log.d(TAGS, " scanWifi" );
final Vector<String> results = new Vector<String>();
final int totalSize = ips.size();
final int splitSize = 10;
resetIndex();
final long start = System.currentTimeMillis();
for (int i = 0; i < totalSize; i += splitSize) {
final List<String> child = new ArrayList<String>(ips.subList(i, Math.min(totalSize, i + splitSize)));
executeTask(new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
synchronized (index) {
for (String ip : child) {
Log.d(TAGS, " scanning : " + index + ", ip: " + ip);
boolean isPrinter = connect(ip);
if (isPrinter) {
results.add(ip);
}
if (index == ips.size() - 1) {
long end = System.currentTimeMillis();
Log.d(TAGS, "scanning time: " + (end - start) / 1000);
callback.onScanningComplete(results);
} else {
index++;
}
}
}
return null;
}
});
}
public void executeTask(AsyncTask asyncTask) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
asyncTask.execute();
}
}
This is the message that I get when I run on android 5.
D/ConnectivityManager.CallbackHandler: CM callback handler got msg 524290
Any help to make this thing work in any way (the first code to work on android 5 or the second code to work faster and in an efficient way ) will be deeply appreciated. I have looked on the issues related to this but I don't want to use print services.
As the index value was the reason why the callback was not sent, so to solve it just sending the callback as soon as you discover the Network Printer and storing it in a var(JSONArray in my case ) will give you the list of the printers and its effective.

How to divide a sentence to words and compare with another string?

I have saved the units in .txt file. These I am getting in an array list. Now I want to check if any of the units present in the string.
List contains :
"units", "kg", "kilogms", "kilo", "literes",
"Liter", "packets", "packet", "gms", "grams", "half kg"
Like, if I have a string - 1kg rice, I want to get numbers from this string and I want to divide this sentence to words and want to compare with each item from array list of units. If it is present I want to save it. So I want to store 1kg and rice separately. string may contain any spaces I want to trim all those spaces and check compare.
Getting text file in an array list.
public class ReadTextFiles {
public static List<String> readItemNamesFile(Context context) {
String sText = null;
List<String> stringList;
try{
InputStream is = context.getResources().openRawResource(R.raw.item_names);
//Use one of the above as per your file existing folder
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
sText = new String(buffer, "UTF-8");
String[] sTextArray = sText.replace("\"", "").split(",");
stringList = new ArrayList<String>(Arrays.asList(sTextArray));
System.out.print(stringList);
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return stringList;
}
}
public void getUnits()
{
List<String> units = new ArrayList<>();
units = ReadTextFiles.readUnitsFile(getActivity());
System.out.print(units.size());
}
Now I want to compare string suppose its "1 kg potato".Then should find potato from the array list. Also it should be case insensitive.
This is the full solution of your requirement as I understood:
String measuring = "\"units\", \"kg\", \"kilogms\", \"kilo\", \"literes\", \"Liter\", \"packets\", \"packet\", \"gms\", \"grams\", \"half kg\"";
String items = "\"Potato\", \"rice\", \"Eggs\", \"Maggi\", \"Dryfruits\", \"Maza\", \"cold drink\", \"sauce\", \"catchup\", \"coconut oil\"";
String matching = "Kg500 Potato";//"Potato 1 kg";
String item = "", measuringUnit = "", quantity = "";
private void findOut() {
String[] sMeasuringArray = measuring.replace("\"", "").split(", ");
ArrayList<String> measuringList = new ArrayList<String>(Arrays.asList(sMeasuringArray));
String[] sItemsArray = items.replace("\"", "").split(", ");
ArrayList<String> itemsList = new ArrayList<String>(Arrays.asList(sItemsArray));
String[] sMatchingArray = matching.split(" ");
matching = matching.toUpperCase();
for (int i = 0; i < measuringList.size(); i++) {
if (matching.contains(measuringList.get(i).toUpperCase())) {
measuringUnit = measuringList.get(i).trim();
break;
}
}
for (int i = 0; i < itemsList.size(); i++) {
if (matching.contains(itemsList.get(i).toUpperCase())) {
item = itemsList.get(i).trim();
break;
}
}
if (matching!= null) {
String[] part = matching.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
for (int k = 0; k < part.length; k++) {
try {
Integer.parseInt(part[k]);
quantity = part[k];
break;
} catch (Exception ex) {
continue;
}
}
}
/*if (sMatchingArray != null) {
if (sMatchingArray.length == 3) {
for (int j = 0; j < sMatchingArray.length; j++) {
if (measuringUnit.trim().equals(sMatchingArray[j].trim())) {
quantity = sMatchingArray[j - 1].trim();
break;
}
}
} else if (sMatchingArray.length == 2) {
String[] part = matching.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
for (int k = 0; k < part.length; k++) {
try {
Integer.parseInt(part[k]);
quantity = part[k];
break;
} catch (Exception ex) {
continue;
}
}
}
}*/
Log.e("Solution: ", "item = " + item + ", measuringUnit = " + measuringUnit + ", quantity = " + quantity);
}
I'm gonna be using algorithmic approach for the answer. So here it goes:
strItem = "1kg rice";
//Run a loop through the list of units and for each unit check this
if (strItem.contains(list.get(index)))
//Do the needful and break

Scroll/Click Function - Processing 2 - Java

I am trying to add a scroll function to my code as currently it merely displays the first couple tweets, enough to fill the canvas but no more. How do I go about adding a scroll/click function so the canvas lists other tweets as well?
This is what I have so far with my Twitter API tokens omitted.
import java.util.Date;
import java.util.Arrays;
ArrayList<String> words = new ArrayList();
void setup() {
//Set the size of the stage, and the background to black.
size(750, 750);
background(0);
//Credentials
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setOAuthConsumerKey("x");
cb.setOAuthConsumerSecret("x");
cb.setOAuthAccessToken("x");
cb.setOAuthAccessTokenSecret("x");
TwitterFactory twitterFactory;
twitterFactory = new TwitterFactory(cb.build());
Twitter twitter = twitterFactory.getInstance();
Query query = new Query("StackOverFow");
query.count(100);
try {
QueryResult result = twitter.search(query);
ArrayList tweets = (ArrayList) result.getTweets();
for (int i = 0; i < tweets.size (); i++) {
Status t = (Status) tweets.get(i);
User u=(User) t.getUser();
String user=u.getName();
String msg = t.getText();
Date d = t.getCreatedAt();
text("User Name - " + user + " Time - " + d + " Message - " + msg,
20, 15+i*50, width-40, 50);
println("Tweet by " + user + " at " + d + ": " + msg);
//Break the tweet into words
String[] input = msg.split(" ");
println(input);
for (int j = 0; j < input.length; j++) {
//Put each word into the words ArrayList
words.add(input[j]);
}
};
}
catch (TwitterException te) {
println("Couldn't connect: " + te);
};
}
int j=0;
void mousePressed() {
saveData();
}
void saveData() {
String[] data = new String[words.size()];
words.toArray(data);
saveStrings("data/data.txt", data);
}
You already have a handler for mousePressed, adding click and scroll handling is the same concept: add mouseClicked for full click handling, and mouseWheel() for handling scroll events.

Android: Get the entire array the value/key is in ArrayList<HashMap<String, String>>

I am trying to get v8 from the third array inside following arraylist
String[][] test = {
{"v1","v2","v3","v4","v5","v6","v7"},
{"v1","v2","v3","v4","v5","v6","v7"},
{"v1","v2","v3","v4","v5","v6","v7", "v8"}
};
ArrayList<String[]> test2= new ArrayList<String[]>(Arrays.asList(test));
Log.e("v1: ", "" + test2.get(0));
for (int j = 0; j <= test2.size(); j++) {
for (String[] arrays: test2) {
for (String string2 : arrays) {
if (string2.equalsIgnoreCase("v8")) {
Log.e("LOOOOOOOOOG", "" + test2.indexOf("v8")); // 3
}else {
Log.e("LOOOOOOOOOG", "Cant find it!!");
}
}
}
}
How would i do this?
I currently just get either -1 or Cant find it!!
I am trying to solve the above problem to solve the following HashMap problem.
public static void updateJSONdata() {
mEmailList = new ArrayList<HashMap<String, String>>();
JSONParser jParser = new JSONParser();
JSONObject json = jParser.getJSONFromUrl(READ_EMAILS_URL);
try {
mEmails = json.getJSONArray("info");
// looping through all emails according to the json object returned
for (int i = 0; i < mEmails.length(); i++) {
JSONObject c = mEmails.getJSONObject(i);
// gets the content of each tag
String email = c.getString(TAG_EMAIL);
String firstName = c.getString(TAG_FNAME);
String lastName = c.getString(TAG_LNAME);
String address = c.getString(TAG_ADDRESS);
String phoneNumber = c.getString(TAG_PHONE);
String city = c.getString(TAG_CITY);
String state = c.getString(TAG_STATE);
String zip = c.getString(TAG_ZIP);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_EMAIL, email);
map.put(TAG_FNAME, firstName);
map.put(TAG_LNAME, lastName);
map.put(TAG_ADDRESS, address);
map.put(TAG_PHONE, phoneNumber);
map.put(TAG_CITY, city);
map.put(TAG_STATE, state);
map.put(TAG_ZIP, zip);
// adding HashList to ArrayList
mEmailList.add(map);
for (HashMap<String, String> maps : mEmailList){
for (Entry<String, String> mapEntry : maps.entrySet()){
String key = mapEntry.getKey();
String value = mapEntry.getValue();
if (value.equals(passedEmail)) {
Log.e("Is this email in the database?", value + " Is in the database!!!");
int index = map.get(key).indexOf(value);
Log.e("mEmailList: ", "" + mEmailList);
// String[] test = mEmailList.indexOf(value);
fullName = mEmailList.get(index).get(TAG_FNAME) +
" " +
mEmailList.get(index).get(TAG_LNAME);
mPhoneNumber = mEmailList.get(index).get(TAG_PHONE);
mAddress = mEmailList.get(index).get(TAG_ADDRESS) + " " +
mEmailList.get(index).get(TAG_CITY) + " " +
mEmailList.get(index).get(TAG_STATE) + " " +
mEmailList.get(index).get(TAG_ZIP);
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
It looks like you want the index within the list that contains a map that has a specific email address as one of the values. For that purpose you need to call indexOf on the list, and pass to it a Map.
Something like : mEmailList.indexOf(map).
What you are doing is searching for the index of the first occurrence of a sub-string within another String. That won't give you an index within the list.
In addition, it looks like you are mixing the code that creates the list of maps with the code that searches the list for a specific email.
You are getting -1 because of
test2.indexOf("v8")
The ArrayList test2 contains arrays String[], it doesn't containg "v8". test2, for example, contains { "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8" }, but not "v8".
Note: The methods String#indexOf() and ArrayList#indexOf() are different, so you should read their specification before using them.

How do you parse JSON with a colon in the name? Android/Java

For example: { "primary:title":"Little Red Riding Hood"}
My Parser in Java (Android) is always getting stuck because of the colon between primary and title. I can parse anything else with ease, I just need help in this.
public class MainActivity extends Activity {
/** Called when the activity is first created. */
TextView txtViewParsedValue;
private JSONObject jsonObject;
private JSONArray jsonArray;
String [] titles, links, mediaDescriptions, mediaCredits, descriptions, dcCreators, pubDates, categories;
String [] permalinks, texts; // guid
String [] rels, hrefs;
String [] urls, media, heights, widths; // media:content
String strParsedValue = "";
private String strJSONValue;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
strJSONValue = readRawTextFile(this, R.raw.jsonextract);
txtViewParsedValue = (TextView) findViewById(R.id.text_view_1);
try {
parseJSON();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void parseJSON() throws JSONException
{
txtViewParsedValue.setText("Parse 1");
jsonObject = new JSONObject(strJSONValue);
jsonArray = jsonObject.getJSONArray("item");
titles = new String[jsonArray.length()];
links = new String[jsonArray.length()];
permalinks = new String[jsonArray.length()];
texts = new String[jsonArray.length()];
mediaDescriptions = new String[jsonArray.length()];
mediaCredits = new String[jsonArray.length()];
descriptions = new String[jsonArray.length()];
dcCreators = new String[jsonArray.length()];
pubDates = new String[jsonArray.length()];
categories = new String[jsonArray.length()];
txtViewParsedValue.setText("Parse 2");
for (int i=0; i<jsonArray.length(); i++)
{
JSONObject object = jsonArray.getJSONObject(i);
titles[i] = object.getString("title");
links[i] = object.getString("link");
JSONObject guidObj = object.getJSONObject("guid");
permalinks[i] = guidObj.getString("isPermaLink");
texts[i] = guidObj.getString("text");
//mediaDescriptions[i] = object.getString("media:description");
//mediaCredits[i] = object.getString("media:credit");
// *** THE PARSER FAILS IF THE COMMENTED LINES ARE IMPLEMENTED BECAUSE
// OF THE : IN BETWEEN THE NAMES ***
descriptions[i] = object.getString("description");
//dcCreators[i] = object.getString("dc:creator");
pubDates[i] = object.getString("pubDate");
categories[i] = object.getString("category");
}
for (int i=0; i<jsonArray.length(); i++)
{
strParsedValue += "\nTitle: " + titles[i];
strParsedValue += "\nLink: " + links[i];
strParsedValue += "\nPermalink: " + permalinks[i];
strParsedValue += "\nText: " + texts[i];
strParsedValue += "\nMedia Description: " + mediaDescriptions[i];
strParsedValue += "\nMedia Credit: " + mediaCredits[i];
strParsedValue += "\nDescription: " + descriptions[i];
strParsedValue += "\nDC Creator: " + dcCreators[i];
strParsedValue += "\nPublication Date: " + pubDates[i];
strParsedValue += "\nCategory: " + categories[i];
strParsedValue += "\n";
}
txtViewParsedValue.setText(strParsedValue);
}
public static String readRawTextFile(Context ctx, int resId)
{
InputStream inputStream = ctx.getResources().openRawResource(resId);
InputStreamReader inputreader = new InputStreamReader(inputStream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line;
StringBuilder text = new StringBuilder();
try {
while (( line = buffreader.readLine()) != null) {
text.append(line);
//text.append('\n');
}
} catch (IOException e) {
return null;
}
return text.toString();
}
For one, and to answer your question, there is no issue with JSONObject and the org.json.* classes parsing keys with colons in them if they're properly formed. The following unit test passed which means it was able to parse your example scenario:
public void testParsingKeysWithColons() throws JSONException {
String raw = "{ \"primary:title\":\"Little Red Riding Hood\"}";
JSONObject obj = new JSONObject(raw);
String primaryTitle = obj.getString("primary:title");
assertEquals("Little Red Riding Hood", primaryTitle);
}
Another suggestion is that using arrays of Strings for your data is clumsy and you'd be much better organized using a data structure to represent your objects. Instead of string arrays for titles, links, descriptions; use an object that has these properties and make a list of the objects. For example:
public class MyDataStructure {
public String title;
public String primaryTitle;
public String link;
public String mediaDescription;
public static class Keys {
public static String title = "title";
public static String primaryTitle = "primary:title";
public static String link = "link";
public static String mediaDescription = "media:description";
}
}
And then you can make a "translator" class that does all the parsing for you and returns a list of your object. This is much easier to work with and keep track of. You never have to think about data misaligning or having more or less data in one of your arrays than you expected. You also have a much easier time testing where the problem is if your input data is missing anything or any of your json is malformed.
public class MyDataStructureTranslator {
public static List<MyDataStructure> parseJson(String rawJsonData) throws JSONException {
List<MyDataStructure> list = new ArrayList<MyDataStructure>();
JSONObject obj = new JSONObject(rawJsonData);
JSONArray arr = obj.getJSONArray("item");
for(int i = 0; i < arr.length(); i++) {
JSONObject current = arr.getJSONObject(i);
MyDataStructure item = new MyDataStructure();
item.title = current.getString(MyDataStructure.Keys.title);
item.primaryTitle = current.getString(MyDataStructure.Keys.primaryTitle);
item.link = current.getString(MyDataStructure.Keys.link);
item.mediaDescription = current.getString(MyDataStructure.Keys.mediaDescription);
list.add(item);
}
return list;
}
}
Since Java identifiers cannot have colons, just specify a json property name that maps to the exact json name like:
#JsonProperty("primary:title")
public String primaryTitle;

Categories

Resources