How to access a variable from another class? android java - java

Have spent hours trying to figure out why the "finalURL" variable in the "fetch" method cannot be read by the "Downloader" class? Would really appreciate any pointers..
It's a vocabulary improvement application, so it fetches XML data from a dictionary api.
public class DefineWord extends Activity {
static final String head = new String("http://www.dictionaryapi.com/api/v1/references/collegiate/xml/");
static final String apikey = new String("?key=xxxxxx-xxx-xxx-xxxx-xxxxx");
TextView src;
EditText searchBar;
OnCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.defineword);
src=(TextView)findViewById(R.id.textFromWeb);
searchBar = (EditText)findViewById(R.id.searchBar);
}
fetch method:
public void fetch(View v){ //onClick in xml starts this "fetch" method
String w = searchBar.getText().toString(); // get the text the user enters into searchbar
String finalURL = head.trim() + w.trim() + apikey.trim(); //concatenate api url
Downloader d = new Downloader();
d.execute(finalURL); // Calls AsyncTask to connect in the background.
}
AsyncTask:
class Downloader extends AsyncTask<String,Void,String>{
ArrayList<String> information = new ArrayList<String>(); // Store fetched XML data in ArrayList
public String doInBackground(String... urls) {
String result = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
The problem is here. "finalURL" cannot be resolved to a variable.
Document doc = builder.parse(finalURL); //finalURL cannot be resolved to a variable ???
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("entry"); // Make a list of all elements in XML file with tag name "entry"
for (int temp = 0; temp < nList.getLength(); temp++) { //Iterate over elements and get their attributes (Definition, etymology...)
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE){
Element eElement = (Element) nNode;
String element = ("\nCurrent Element : " + eElement.getAttribute("id"));
information.add(element); //
String definitions = ("\nDefinition : \n" + eElement.getElementsByTagName("dt").item(0).getTextContent());
information.add(definitions);
}
}
}catch (ParserConfigurationException e){
e.printStackTrace();
}catch(SAXException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
return result;
}
protected void onPostExecute (String result){
String finalresult = information.toString();
src.setText(finalresult);
}
}
}
Thanks for your time.

This is called a parameter. By using asyncTask.execute(parameter) you pass in the objects to doInBackground(String... arrayOfParameters).
So to access the value again, you should use builder.parse(urls[0]);

finalURL is declared inside the fetch method and therefore can only be accessed within this function.
If you want it to be accessible throughout the program declare it outside of the function like so.
class MyClass{
public static String finalURL; // variable declaration
public void fetch(View v){
finalURL = head.trim() + w.trim() + apikey.trim(); // variable assignment
}
public void otherFunction(){
Document doc = builder.parse(finalURL); // retrieves static class variable
}
}
I hope this answers your question. If not, let me know what the confusion is.

Related

How do I transfer my parsed array data from one class to another?

My program uses Picocli to parse XML data and store it in an ArrayList. For some reason, the information gets removed when I try to access it from another class.
I run the code below, and it shows the elements just fine:
public class SourceSentences {
static String source;
static ArrayList<String> sourceArray = new ArrayList<>();
public static void translate() throws ParserConfigurationException, IOException, SAXException {
String xmlFileLocation = "C:\\Users\\user\\Desktop\\exercise\\source.txml";
System.out.println("---------------");
System.out.println("Get Text From Source File: ");
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
//parse '.txml' file
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.parse(new File(xmlFileLocation));
//...
document.getDocumentElement().normalize();
//specify tag in the '.txml' file and iterate
NodeList nodeList = document.getElementsByTagName("segment");
for (int i = 0; i < nodeList.getLength(); i++) {
//this is tag index of where line of el are
Node node = nodeList.item(i);
//check if actually a node
if (node.getNodeType() == Node.ELEMENT_NODE) {
//create a node object that will retrieve the element in the XML file
Element element = (Element) node;
//get the element from the specified node in nodeList
source = element.getElementsByTagName("source").item(0).getTextContent();
//check what it looks like
System.out.println(source);
//add to arraylist
sourceArray.add(source);
}
/*String[] arr = source.split("\\s");
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(arr));*/
}
//get its data type to make sure
System.out.println("data type: " + source.getClass().getSimpleName());
System.out.println(sourceArray);
}
}
So I try to access sourceArray from another class:
class getArrayElements extends SourceSentences{
public static void main(String[] args) {
System.out.println(SourceSentences.sourceArray);
}
}
and results in variables being [], thus not able to transfer data to another class.
Picocli setup snippet:
public class TranslateTXML implements Callable<String> {
#Option(names = "-f", description = " path to source txml file")
private String file;
#Option(names = "-o", description = "output path")
private String output;
public static void main(String... args) throws Exception {
int exitCode = new picocli.CommandLine(new TranslateTXML()).execute(args);
System.exit(exitCode);
}
public String call() throws Exception {
if (file != null) {
if (file.equals("C:\\Users\\gnier\\Desktop\\exercise\\source.txml")) {
sourceSent("C:\\Users\\gnier\\Desktop\\exercise\\source.txml");
System.out.println("source.txml data retrieved\n");
} else {
System.out.println("File \"source.txml\" not found. Check FileName and Directory.");
System.exit(2);
}
}
WriteSourceTranslatedToTXML.makeTranslated(System.out);
System.out.println("translated made");
System.out.println("------");
System.out.println("File \"translated.txml\" has been outputted to designated path");
}
}
The static context of the SourceSentences.main() is lost once you run the getArrayElements.main() method. The parsing of your XML data never happened as far as getArrayElements.main() was concerned.
You need to call the translate method from inside the getArrayElements' main function.
class getArrayElements extends SourceSentences {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
SourceSentences.translate();
System.out.println(SourceSentences.sourceArray);
}
}

Pagination with Web Driver Selenium and JSoup

I'm developing an app that takes data from a website with JSoup. I was able to get the normal data.
But now I need to implement a pagination on it. I was told it would have to be with Web Driver, Selenium. But I do not know how to work with him, could someone tell me how I can do it?
public class MainActivity extends AppCompatActivity {
private String url = "http://www.yudiz.com/blog/";
private ArrayList<String> mAuthorNameList = new ArrayList<>();
private ArrayList<String> mBlogUploadDateList = new ArrayList<>();
private ArrayList<String> mBlogTitleList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Description().execute();
}
private class Description extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
// Connect to the web site
Document mBlogDocument = Jsoup.connect(url).get();
// Using Elements to get the Meta data
Elements mElementDataSize = mBlogDocument.select("div[class=author-date]");
// Locate the content attribute
int mElementSize = mElementDataSize.size();
for (int i = 0; i < mElementSize; i++) {
Elements mElementAuthorName = mBlogDocument.select("span[class=vcard author post-author test]").select("a").eq(i);
String mAuthorName = mElementAuthorName.text();
Elements mElementBlogUploadDate = mBlogDocument.select("span[class=post-date updated]").eq(i);
String mBlogUploadDate = mElementBlogUploadDate.text();
Elements mElementBlogTitle = mBlogDocument.select("h2[class=entry-title]").select("a").eq(i);
String mBlogTitle = mElementBlogTitle.text();
mAuthorNameList.add(mAuthorName);
mBlogUploadDateList.add(mBlogUploadDate);
mBlogTitleList.add(mBlogTitle);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Set description into TextView
RecyclerView mRecyclerView = (RecyclerView)findViewById(R.id.act_recyclerview);
DataAdapter mDataAdapter = new DataAdapter(MainActivity.this, mBlogTitleList, mAuthorNameList, mBlogUploadDateList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mDataAdapter);
}
}
}
Problem statement (as per my understanding): Scraper should be able to go to the next page until all pages are done using the pagination options available at the end of the blog page.
Now if we inspect the next button in the pagination, we can see the following html.
a class="next_page" href="http://www.yudiz.com/blog/page/2/"
Now we need to instruct Jsoup to pick up this dynamic url in the next iteration of the loop to scrap data. This can be done using the following approach:
String url = "http://www.yudiz.com/blog/";
while (url!=null){
try {
Document doc = Jsoup.connect(url).get();
url = null;
System.out.println(doc.getElementsByTag("title").text());
for (Element urls : doc.getElementsByClass("next_page")){
//perform your data extractions here.
url = urls != null ? urls.absUrl("href") : null;
}
} catch (IOException e) {
e.printStackTrace();
}
}

Fetching data from an API with JSON and storing two objects in a single row of an Array Adapter

I've got this code with fetches the "rate" data from an API, along with "rate", I need to get the "name". If I get "name" it often binds it below the "rate".
I need it to join on the same row of the List View, so it is like [Rate Name].
I need to get two objects of a JSON Array and bind it to the array adapter so I can display two objects in the same row of a List View so it is more user friendly.
The code below is of the AsyncTask, the code works fine but I need to add one more object and make sure it is displayed as one rate - one name and then iterating through the loop and adding more as needed in the same order.
public class AsyncTaskParseJson extends AsyncTask<String, String, String> {
// the url of the web service to call
String yourServiceUrl = "eg: URL";
#Override
protected void onPreExecute() {
}
String filename = "bitData";
#Override
protected String doInBackground(String... arg0) {
try {
// create new instance of the httpConnect class
httpConnect jParser = new httpConnect();
// get json string from service url
String json = jParser.getJSONFromUrl(yourServiceUrl);
// parse returned json string into json array
JSONArray jsonArray = new JSONArray(json);
// loop through json array and add each currency to item in arrayList
//Custom Loop Initialise
for (int i = 1; i < 8; i++) {
JSONObject json_message = jsonArray.getJSONObject(i);
// The second JSONObject which needs to be added
JSONObject json_name = jsonArray.getJSONObject(i);
if (json_message != null) {
//add each currency to ArrayList as an item
items.add(json_message.getString("rate"));
String bitData = json_message.getString("rate");
String writeData = bitData + ',' +'\n';
FileOutputStream outputStream;
File file = getFileStreamPath(filename);
// first check if file exists, if not create it
if (file == null || !file.exists()) {
try {
outputStream = openFileOutput(filename, MODE_PRIVATE);
outputStream.write(writeData.getBytes());
outputStream.write("\r\n".getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// if file already exists then append bit data to it
else if (file.exists()) {
try {
outputStream = openFileOutput(filename, Context.MODE_APPEND);
outputStream.write(writeData.getBytes());
outputStream.write("\r\n".getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
// below method will run when service HTTP request is complete, will then bind text in arrayList to ListView
#Override
protected void onPostExecute(String strFromDoInBg) {
ListView list = (ListView) findViewById(R.id.rateView);
ArrayAdapter<String> rateArrayAdapter = new ArrayAdapter<String>(BitRates.this, android.R.layout.simple_expandable_list_item_1, items);
list.setAdapter(rateArrayAdapter);
}
}
Just Create Custom Class Messsage:
public class Item{
private String name;
private String rate;
public void Message(String n, String r){
this.name=n;
this.rate=r;
}
// create here getter and setter
}
Now in your background, you have to add name and rate in Message class
Public class MainAcitity extends Activity{
public static List<Item> items= new ArrayList<>();// define in inside the class
// this has to be down on background
Item i=new Item(json_message.getString("name"),json_message.getString("rate"));
items.add(i);
Now pass this listmessge onPostExecute :
ListView list = (ListView) findViewById(R.id.rateView);
ArrayAdapter<String> rateArrayAdapter = new ArrayAdapter<String>(BitRates.this, android.R.layout.simple_expandable_list_item_1, items);
list.setAdapter(rateArrayAdapter);
Is that any helpful for you.
Follow this link.You will get my point.
https://devtut.wordpress.com/2011/06/09/custom-arrayadapter-for-a-listview-android/

How to store values as variables in iterator, for loop?

I'm developing an Android app. I'm using Jsoup to retreive elements from a page. Then, I'm iterating over the collection to get each individual part of it. I'm not sure how to save each instance of an element as a different variable. I think that I can use a for loop for this, but I don't quite understand it. How would I determine the length of how long to select from? How would I use it? I'm retreiving elements from here: http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=201412abc85d49b2b83f907f9e329eaa&mapid=40380. My code is below:
public class TestStation extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_station);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Intent intent = getIntent();
String value = intent.getExtras().getString("value");
Uri my = Uri.parse("http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=201412abc85d49b2b83f907f9e329eaa&mapid="+value);
String myUrl = my.toString();
Document doc = null;
TextView tv1 = (TextView) findViewById(R.id.tv1);
try {
doc = Jsoup.connect(myUrl).userAgent("Mozilla/5.0 (Macintosh; U; Intel Mac OS X; de-de) AppleWebKit/523.10.3 (KHTML, like Gecko) Version/3.0.4 Safari/523.10").get();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Elements elem = doc.select("eta");
Iterator<Element> iterator = elem.iterator();
while(iterator.hasNext())
{ Element div = iterator.next();
Elements arrT = div.select("arrT");
Elements prdt = div.select("prdt");
Elements destNm = div.select("destNm");
Elements rt = div.select("rt");
String DestNm = destNm.text();
String Rt = rt.text();
tv1.setText(String.valueOf (Rt));
I would like to store each instance (there is many) of arrT, pdrt, and destNm as a different variable. How would I go across doing this? Thank you for your help.
You could use a generic type list
ArrayList<Elements> xx = new ArrayList<Elements>();
then in your while loop
xx.add(arrT);
`Could you make an class with getters and setters for the properties you're interested in, and create an array of that?
EDIT:
To create your class:
public class YourClass {
private Element arrt;
...
public void setArrT (String input) {
arrt = input;
}
public Element getArrt() {
return arrt;
}
....
}
Give it a go.
Transfer between Unicode and UTF-8
try {
String string = "\u201cGoodbye Athens thanks";
byte[] utf8 = string.getBytes("UTF-8");
string = new String(utf8, "UTF-8");
} catch (UnsupportedEncodingException e) {
}

Blackberry XML Parsing Application not working

I found one sample application from the Blackberry knowledgebase.
From that application I have put that sample application on my eclipse plugin, and the code is as follows :
import javax.microedition.io.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import net.rim.device.api.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
class XML_Parsing_Sample extends UiApplication {
// creating a member variable for the MainScreen
MainScreen _screen = new MainScreen();
// string variables to store the values of the XML document
String _node, _element;
Connection _connectionthread;
public static void main(String arg[]) {
XML_Parsing_Sample application = new XML_Parsing_Sample();
// create a new instance of the application
// and start the application on the event thread
application.enterEventDispatcher();
}
public XML_Parsing_Sample() {
_screen.setTitle("XML Parsing");// setting title
_screen.add(new RichTextField("Requesting....."));
_screen.add(new SeparatorField());
pushScreen(_screen); // creating a screen
// creating a connection thread to run in the background
_connectionthread = new Connection();
_connectionthread.start();// starting the thread operation
}
public void updateField(String node, String element) {
// receiving the parsed node and its value from the thread
// and updating it here
// so it can be displayed on the screen
String title = "My App";
_screen.add(new RichTextField(node + " : " + element));
if (node.equals(title)) {
_screen.add(new SeparatorField());
}
}
private class Connection extends Thread {
public Connection() {
super();
}
public void run() {
// define variables later used for parsing
Document doc;
StreamConnection conn;
try {
// providing the location of the XML file,
// your address might be different
conn = (StreamConnection) Connector
.open("http://www.sufalamtech.com/demo/moviewebservice/Test.xml");
// next few lines creates variables to open a
// stream, parse it, collect XML data and
// extract the data which is required.
// In this case they are elements,
// node and the values of an element
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docBuilderFactory
.newDocumentBuilder();
docBuilder.isValidating();
doc = docBuilder.parse(conn.openInputStream());
doc.getDocumentElement().normalize();
NodeList list = doc.getElementsByTagName("*");
_node = new String();
_element = new String();
// this "for" loop is used to parse through the
// XML document and extract all elements and their
// value, so they can be displayed on the device
for (int i = 0; i < list.getLength(); i++) {
Node value = list.item(i).getChildNodes().item(0);
_node = list.item(i).getNodeName();
_element = value.getNodeValue();
updateField(_node, _element);
}// end for
}// end try
// will catch any exception thrown by the XML parser
catch (Exception e) {
Dialog.alert("exception = " + e);
}
}// end connection function
}// end connection class
}// end XML_Parsing_Sample
But when I am running this application, the simulator just showing me a Blank screen with label Requesting...
Anybody help me out for this ?
Thanks in advance...
Try this
public void updateField(String node, String element) {
// receiving the parsed node and its value from the thread
// and updating it here
// so it can be displayed on the screen
//Don't forget to add this next line when called from a thread
synchronized (UiApplication.getEventLock()) {
String title = "My App";
_screen.add(new RichTextField(node + " : " + element));
if (node.equals(title)) {
_screen.add(new SeparatorField());
}
}
}
This synchronized (UiApplication.getEventLock()) is really important, you need this every time thread try to access the UI.
More solutions exist, see the documentation

Categories

Resources