Getting same values in list while parsing xml using xmlpullparser - java

I am trying to parse an xml file present in asset folder.All seems good and there is no error but the problem is that it gives same values to the list for every node in xml.As i feel it overwrite previous value.I am stuck here.Even after a lot of googling could not find any solution. Any help would be appreciated.
Below is the code:-
Product.java
package com.example.webservicedemo;
public class product {
private static String productname="";
private static String productcolor="";
private static String productquantity="";
public static String getProductname() {
return productname;
}
public static void setProductname(String productname) {
product.productname = productname;
}
public static String getProductcolor() {
return productcolor;
}
public static void setProductcolor(String productcolor) {
product.productcolor = productcolor;
}
public static String getProductquantity() {
return productquantity;
}
public static void setProductquantity(String productquantity) {
product.productquantity = productquantity;
}
}
Below is the code of parser:-
productXmlPullParser.java
package com.example.webservicedemo;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.content.Context;
import android.content.res.AssetManager;
import android.widget.Toast;
import com.example.webservicedemo.*;
public class productXmlPullParser {
static final String KEY_PRODUCT = "product";
static final String KEY_NAME = "productname";
static final String KEY_COLOR = "productcolor";
static final String KEY_QUANTITY = "productquantity";
public static List<product> getproductsFromFile(Context ctx) {
String tagname;
List<product> Products;
Products = new ArrayList<product>();
product curproduct = null;
String curText = "";
InputStream is = null;
try {
is = ctx.getAssets().open("temp.xml");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xpp = factory.newPullParser();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
xpp.setInput(reader);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
tagname = xpp.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
if (tagname.equalsIgnoreCase(KEY_PRODUCT)) {
curproduct = new product();
}
break;
case XmlPullParser.TEXT:
//grab the current text so we can use it in END_TAG event
curText = xpp.getText();
break;
case XmlPullParser.END_TAG:
if (tagname.equalsIgnoreCase(KEY_PRODUCT)) {
// if </site> then we are done with current Site
// add it to the list.
Products.add(curproduct);
// Toast.makeText(ctx, curproduct+"",3000).show();
} else if (tagname.equalsIgnoreCase(KEY_NAME)) {
// if </name> use setName() on curSite
product.setProductname(curText);
Toast.makeText(ctx, curText+"",3000).show();
} else if (tagname.equalsIgnoreCase(KEY_COLOR)) {
// if </link> use setLink() on curSite
curproduct.setProductcolor(curText);
Toast.makeText(ctx, curText+"",3000).show();
} else if (tagname.equalsIgnoreCase(KEY_QUANTITY)) {
// if </about> use setAbout() on curSite
curproduct.setProductquantity(curText);
Toast.makeText(ctx, curText+"",3000).show();
}
break;
default:
break;
}
//move on to next iteration
eventType = xpp.next();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(ctx, "error", 6000).show();
}
// return the populated list.
return Products;
}
}
Below is the code of my custom arrayadapter:--
ProductAdapter
package com.example.webservicedemo;
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class UsersAdapter extends ArrayAdapter<product> {
public UsersAdapter(Context context, int resource, List<product> objects) {
super(context, resource, objects);
// TODO Auto-generated constructor stub
}
#Override
public View getView(int pos, View convertView, ViewGroup parent){
RelativeLayout row = (RelativeLayout)convertView;
Log.i("Users", "getView pos = " + pos);
if(null == row){
LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = (RelativeLayout)inflater.inflate(R.layout.listitem, null);
}
TextView Email = (TextView)row.findViewById(R.id.txtEmail);
TextView Password = (TextView)row.findViewById(R.id.txtPassword);
TextView Deviceid = (TextView)row.findViewById(R.id.txtDeviceid);
Email.setText(getItem(pos).getProductname());
Password.setText(getItem(pos).getProductcolor());
Deviceid.setText(getItem(pos).getProductquantity());
return row;
}
}
Below is the main activity where i am trying to get the result values in a list
MainActivity.java
package com.example.webservicedemo;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.Toast;
import com.example.webservicedemo.productXmlPullParser;;;
public class UserList extends Activity {
UsersAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_xmlparsingdemo);
ListView lvUser=(ListView)findViewById(R.id.lvUsers);
mAdapter=new UsersAdapter(getApplicationContext(),R.layout.listitem,productXmlPullParser.getproductsFromFile(getApplicationContext()));
lvUser.setAdapter(mAdapter);
Toast.makeText(getApplicationContext(), mAdapter.getCount()+"",3000).show();
}
}
Here is the xml which i am trying to parse:--
temp.xml
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product>
<productname>Jeans</productname>
<productcolor>red</productcolor>
<productquantity>5</productquantity>
</product>
<product>
<productname>Tshirt</productname>
<productcolor>blue</productcolor>
<productquantity>3</productquantity>
</product>
<product>
<productname>shorts</productname>
<productcolor>green</productcolor>
<productquantity>4</productquantity>
</product>
</products>
But the output is like something like below screenshot:-
After a lot of effort i could not find what went wrong.
Any help would be appreciated.

Problem in yours class "product". Fields are static, each field contains one last value for all instances. Remove "static" modificator, and all will work fine.

Related

Using list view and array adapter in android studio

I am a beginner in Android studio and I am trying to send an array list to a list view. I know that I am passing the correct info from my main activity to the second activity and that it is received properly in the second activity. My issue is coming in when I try to pass the array list "filteredlist" to the array adapter "arradapter" to then send to list view. It is giving me this error: java.lang.NullPointerException: "Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference."
I am sure I am missing something, but I am not sure what.
I am aware the code isn't perfect, and I plan on streamlining it later.
Second activity:
package com.example.charityfinder;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.ArrayList;
public class ResultsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_results);
ArrayList<NationalCharity> filteredlist = (ArrayList<NationalCharity>) getIntent().getSerializableExtra("Filtered List");
Log.d("DEBUG", "Second Activity: " + filteredlist);//prints out list here
ListView dataresults = (ListView) findViewById(R.id.dataresults);
ArrayAdapter<NationalCharity> arradapter = new ArrayAdapter<NationalCharity>(this, R.layout.item_view, R.id.itemTextView, filteredlist);
dataresults.setAdapter(arradapter);
}
}
Main Activity:
package com.example.charityfinder;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
//references to buttons and other controls
Button submitbtn;
RadioButton medicalRadio, envirRadio, hserviceRadio, educationRadio, publicaRadio,
cultureRadio, domesticvRadio, hrightsRadio, homelessRadio, religionRadio, youthRadio;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
readcharitydata();
medicalRadio = findViewById(R.id.medicalRadio);
envirRadio = findViewById(R.id.envirRadio);
hserviceRadio = findViewById(R.id.hserviceRadio);
educationRadio = findViewById(R.id.educationRadio);
publicaRadio = findViewById(R.id.publicaRadio);
cultureRadio = findViewById(R.id.cultureRadio);
domesticvRadio = findViewById(R.id.domesticvRadio);
hrightsRadio = findViewById(R.id.hrightsRadio);
homelessRadio = findViewById(R.id.homelessRadio);
religionRadio = findViewById(R.id.religionRadio);
youthRadio = findViewById(R.id.youthRadio);
submitbtn = findViewById(R.id.submitbtn);
submitbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openNewActivity();
}
});
}
String category;
public void onRadioButtonClicked(View view) {
if (medicalRadio.isChecked()) {
category = "Medical";
} else if (envirRadio.isChecked()) {
category = "Environmental_Animal";
} else if (hserviceRadio.isChecked()) {
category = "Human_Services";
} else if (educationRadio.isChecked()) {
category = "Education";
} else if (publicaRadio.isChecked()) {
category = "Public_Affairs";
} else if (cultureRadio.isChecked()) {
category = "Culture_Arts_Humanities";
} else if (domesticvRadio.isChecked()) {
category = "Domestic_Violence";
} else if (hrightsRadio.isChecked()) {
category = "Human_Rights";
} else if (homelessRadio.isChecked()) {
category = "Homelessness";
} else if (religionRadio.isChecked()) {
category = "Religious";
} else if (youthRadio.isChecked()) {
category = "Youth";
}
filterCharity(category);
}
private List<NationalCharity> charities = new ArrayList<>();
private void readcharitydata() {
InputStream is = getResources().openRawResource(R.raw.charities);
BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String line = "";
try {
//ignore headers
reader.readLine();
while ((line = reader.readLine()) != null) {
//split by comma
String[] token = line.split(",");
//Read data
NationalCharity charity = new NationalCharity();
charity.setCharity_name(token[0]);
charity.setCategory(token[1]);
charity.setWeb_address(token[2]);
charity.setAddress(token[3]);
charity.setCity(token[4]);
charity.setState(token[5]);
charity.setZipcode(token[6]);
charity.setMission_statement(token[7]);
charities.add(charity);
}
} catch (IOException e) {
Log.wtf("Error", "Error reading data file" + line, e);
e.printStackTrace();
}
}
private ArrayList<NationalCharity> filtered = new ArrayList<>();
//needing to filter here from the charities list
private void filterCharity(String type) {
for (NationalCharity charity : charities) {
if (charity.getCategory().equals(type)) {
filtered.add(charity);
Log.d("DEBUG", "Just created: " + filtered);
}
}
}
public void openNewActivity() {
Intent intent = new Intent(MainActivity.this, ResultsActivity.class);
intent.putExtra("Filtered List", filtered);
Log.d("DEBUG", "Passing: " + filtered);
startActivity(intent);
}
}

NullPointerExcepter Error when using List Adapter and Custom List View in Android Studio

Been trying to write an app in android studio. Part of the app has to parse a document in JSON and display two TextViews of data for each instance. One being Signal and the other being Noise. I am trying to make a custom list view in case I want to add more detail to each instance. I also would like to make it all contained in a ScrollView. I initially had no problems parsing the document but now that I am trying to implement the ListAdapter I am running into issues.
My code is giving me the error...
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.yesinc.tsi880, PID: 4919
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
at com.yesinc.tsi880.TelemetryActivity$JSONTask.onPostExecute(TelemetryActivity.java:136)
at com.yesinc.tsi880.TelemetryActivity$JSONTask.onPostExecute(TelemetryActivity.java:50)
Not sure if the problem is with the document that I am trying to parse or the java code itself. Any help would be much appreciated. Code is below.
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.yesinc.tsi880.models.SondeModel;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import android.widget.ArrayAdapter;
public class TelemetryActivity extends AppCompatActivity {
private TextView tvData;
private ListView lvSondes;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_telemetry);
ListView lvSondes = findViewById(R.id.lvSondes);
//new JSONTask().execute("http://172.16.5.70/plots/sigstr2.txt");
}
public class JSONTask extends AsyncTask<String, String, List<SondeModel> >{
#Override
protected List<SondeModel> doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line;
while((line=reader.readLine()) != null){
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONObject parentArray0 = parentObject.getJSONObject("0");
JSONObject parentArray1 = parentObject.getJSONObject("1");
List<SondeModel> sondeModelList = new ArrayList<>();
//StringBuffer finalBufferedData = new StringBuffer();
for(int i=0; i<8; i++){
String sonde = String.valueOf(i);
JSONObject finalObject = parentArray0.getJSONObject(sonde);
SondeModel sondeModel = new SondeModel();
sondeModel.setNoisedbm(finalObject.getString("noisedbm"));
sondeModel.setSigdbm(finalObject.getString("sigdbm"));
//String noiseDBM = finalObject.getString("noisedbm");
//String sigDBM = finalObject.getString("sigdbm");
sondeModelList.add(sondeModel);
}
for(int i=0; i<8; i++){
String sonde = String.valueOf(i);
JSONObject finalObject = parentArray1.getJSONObject(sonde);
SondeModel sondeModel = new SondeModel();
sondeModel.setNoisedbm(finalObject.getString("noisedbm"));
sondeModel.setSigdbm(finalObject.getString("sigdbm"));
//String noiseDBM = finalObject.getString("noisedbm");
//String sigDBM = finalObject.getString("sigdbm");
sondeModelList.add(sondeModel);
}
return sondeModelList;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if(connection != null) {
connection.disconnect();
}try {
if(reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(List<SondeModel> result) {
super.onPostExecute(result);
SondeAdapter adapter = new SondeAdapter(getApplicationContext(), R.layout.row, result);
lvSondes.setAdapter(adapter);
// TODO need to set a data to the List
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.navigation, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.navigation_telemetry) {
new JSONTask().execute("http://172.16.5.70/plots/sigstr2.txt");
return true;
}
return super.onOptionsItemSelected(item);
}
public class SondeAdapter extends ArrayAdapter{
public List<SondeModel> sondeModelList;
private int resource;
private LayoutInflater inflater;
public SondeAdapter(Context context, int resource, List<SondeModel> objects) {
super(context, resource, objects);
sondeModelList = objects;
this.resource = resource;
inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = inflater.inflate(resource, null);
}
TextView sig;
TextView noise;
sig = (TextView)convertView.findViewById(R.id.sig);
noise = (TextView)convertView.findViewById(R.id.noise);
sig.setText(sondeModelList.get(position).getSigdbm());
noise.setText(sondeModelList.get(position).getNoisedbm());
return convertView;
}
}
}
ListView lvSondes = findViewById(R.id.lvSondes);
You are re-declaring the lvSondes inside your onCreate method. The class member list view is never used and is never initialized. Instead a local lvSondes is initialized. This variable will not be in scope and won't be visible to the AsyncTask. The async task will use the member variable and that will be null.
Solution: remove the ListView from the stated line and just initialize the member variable

Controlling an AsynTaskLoader using a button click

I have created an app that displays a list of 10 books based on a query keyword entered by the user.
I have used an EditText View for the user to enter the query.
I have also used an ImageButton for the search button.
I have used a custom class that extents AsyncTaskLoader to load content to my ListView.
I have called the initloader() method from the MainActivity of the app and has called my custom loader from the OnCreateLoader override method.
I want the loader to fetch the data only on a button click and not automatically when the activity starts.
Main Activity
package com.example.shara.booklistapp;
import android.app.LoaderManager;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import static android.app.LoaderManager.*;
import static com.example.shara.booklistapp.BookQueryUtils.LOG_TAG;
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Blist>> {
private ListAdapter mAdapter;
private static final int BOOK_LOADER_ID = 1;
private String Book_list_request_url = "Michael Jackson";
private ProgressBar progressBar;
private NetworkInfo networkInfo;
private TextView emptytextview;
private EditText editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView booklistview = findViewById(R.id.list);
progressBar = findViewById(R.id.progressbar);
mAdapter = new ListAdapter(this, new ArrayList<Blist>());
booklistview.setAdapter(mAdapter);
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
networkInfo = connectivityManager.getActiveNetworkInfo();
emptytextview = (TextView) findViewById(R.id.emptytextview);
editText = findViewById(R.id.search_query_text_view);
booklistview.setEmptyView(emptytextview);
booklistview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Blist currentBook = mAdapter.getItem(position);
Uri currentbookk = Uri.parse(currentBook.getUrl());
startActivity(new Intent(Intent.ACTION_VIEW, currentbookk));
}
});
LoaderManager loaderManager = getLoaderManager();
loaderManager.initLoader(BOOK_LOADER_ID, null, this);
}
//Overriding the abstract methods of the Loadermanager
#Override
public Loader<List<Blist>> onCreateLoader(int id, Bundle bundle) {
Log.i(LOG_TAG, Book_list_request_url);
return new BlistLoader(this, Book_list_request_url);
}
#Override
public void onLoadFinished(Loader<List<Blist>> loader, List<Blist> blists) {
progressBar.setVisibility(View.GONE);
//Using the networkInfo variable declared earlier to check whether the system has internet connectivity and displays a message if there isn't one.
if (networkInfo == null) {
emptytextview.setText(R.string.no_network);
} else {
emptytextview.setVisibility(View.GONE);
}
mAdapter.clear();
if (blists != null && !blists.isEmpty()) {
mAdapter.addAll(blists);
}
}
#Override
public void onLoaderReset(Loader loader) {
Log.i(LOG_TAG, "Testing: onLoaderReset is successfully called");
mAdapter.clear();
}
}
Custom Loader class
package com.example.shara.booklistapp;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.util.Log;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import org.json.JSONException;
import java.io.IOException;
import java.util.List;
public class BlistLoader extends AsyncTaskLoader<List<Blist>> {
private static final String LOG_TAG = BaseAdapter.class.getName();
private String mUrl;
public BlistLoader(Context context, String url) {
super(context);
mUrl = url;
}
#Override
protected void onStartLoading() {
Log.i(LOG_TAG, "Testing: onStartLoading is successfully called");
forceLoad();
}
#Override
public List<Blist> loadInBackground() {
Log.i(LOG_TAG, "Testing: loadInBackground is successfully called");
if (mUrl == null) {
return null;
}
List<Blist> blists = null;
try {
blists = BookQueryUtils.fetchBookList(mUrl);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return blists;
}
}
XML that contains the ImageButton
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal">
<EditText
android:id="#+id/search_query_text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:hint="#string/hint" />
<ImageButton
android:id="#+id/search_button1"
android:layout_width="42dp"
android:layout_height="42dp"
android:src="#drawable/search" />
</LinearLayout>
<TextView
android:id="#+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:backgroundTint="#color/colorPrimaryDark"
android:backgroundTintMode="add"
android:text="Results" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:dividerHeight="1dp" />
<ProgressBar
android:id="#+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<TextView
android:id="#+id/emptytextview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="" />
</RelativeLayout>
</LinearLayout>
I want the oncreateloader method to only execute when the search button is clicked and not otherwise.
How can this be achieved? Does my code need heavy modification or is it just something that I missed altogether.
I have previously asked the same question here but I didn't get any answers.
Any help would be greatly appreciated.
Book query utils is for the HTTP request and JSON parsing.
package com.example.shara.booklistapp;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* Created by shara on 12/17/2017.
*/
public final class BookQueryUtils {
public static final String LOG_TAG = BookQueryUtils.class.getName();
private BookQueryUtils() {
}
private static URL createURL(String search_query) throws MalformedURLException {
URL url = null;
String q = "q";
try {
final String base_URL = "https://www.googleapis.com/books/v1/volumes?";
Uri final_Url = Uri.parse(base_URL).buildUpon()
.appendQueryParameter(q, search_query)
.build();
url = new URL(final_Url.toString());
Log.i(LOG_TAG, "The final Url is" + url);
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Url could not be formed", e);
}
return url;
}
private static String theHTTPRequest(URL url) throws IOException {
String jsonResponse = "";
if (url == null) {
return jsonResponse;
}
HttpURLConnection connectionUrl = null;
InputStream theInputStream = null;
try {
connectionUrl = (HttpURLConnection) url.openConnection();
connectionUrl.setReadTimeout(10000);
connectionUrl.setConnectTimeout(15000);
connectionUrl.setRequestMethod("GET");
connectionUrl.connect();
if (connectionUrl.getResponseCode() == 200) {
theInputStream = connectionUrl.getInputStream();
jsonResponse = readFromStream(theInputStream);
} else {
Log.e(LOG_TAG, "could not make the connection");
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem getting the requested data", e);
} finally {
if (connectionUrl != null) {
connectionUrl.disconnect();
}
if (theInputStream != null) {
theInputStream.close();
}
}
return jsonResponse;
}
private static String readFromStream(InputStream inputStream) throws IOException {
StringBuilder streamoutput = new StringBuilder();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String urlline = bufferedReader.readLine();
while (urlline != null) {
streamoutput.append(urlline);
urlline = bufferedReader.readLine();
}
return streamoutput.toString();
}
private static List<Blist> extractFeatureFromJSON(String BlistJSON) throws JSONException {
if (TextUtils.isEmpty(BlistJSON)) {
return null;
}
List<Blist> blists = new ArrayList<>();
try {
String a = "";
JSONObject baseJSON = new JSONObject(BlistJSON);
JSONArray items = baseJSON.getJSONArray("items");
for (int i = 0; i < items.length(); i++) {
Blist blistss = new Blist();
JSONObject j = items.getJSONObject(i);
JSONObject vInfo = j.getJSONObject("volumeInfo");
if (vInfo.has("authors")) {
JSONArray athrs = vInfo.getJSONArray("authors");
if (athrs.length() != 0) {
for (int k = 0; k < athrs.length(); k++) {
a = athrs.getString(k);
blistss.setAuthor(a);
}
}
}
if (vInfo.has("imageLinks")) {
JSONObject thumbnail = vInfo.getJSONObject("imageLinks");
blistss.setImage(thumbnail.getString("thumbnail"));
}
blistss.setUrl(vInfo.getString("previewLink"));
blistss.setTitle(vInfo.getString("title"));
blistss.setPublisher(vInfo.getString("publisher"));
blists.add(blistss);
}
} catch (JSONException e) {
Log.e(LOG_TAG, "Could not parse JSON", e);
}
return blists;
}
public static List<Blist> fetchBookList(String query_url) throws IOException, JSONException {
URL url = createURL(query_url);
String JSONResponse = null;
try {
JSONResponse = theHTTPRequest(url);
} catch (IOException e) {
Log.e(LOG_TAG, "Could not fetch data");
}
List<Blist> blists = extractFeatureFromJSON(JSONResponse);
return blists;
}
}
This is my adapter for the listview.
package com.example.shara.booklistapp;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.SearchView;
import android.widget.TextView;
import java.io.InputStream;
import java.util.ArrayList;
/**
* Created by shara on 12/17/2017.
*/
public class ListAdapter extends ArrayAdapter<Blist> {
private ProgressBar progressBar;
public ListAdapter(#NonNull Context context, ArrayList<Blist> blists) {
super(context, 0, blists);
}
public String rslt;
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listitemview = convertView;
if (listitemview == null) {
listitemview = LayoutInflater.from(getContext()).inflate(R.layout.list_layout, parent, false);
}
Blist blist = getItem(position);
ImageView thumbnail = listitemview.findViewById(R.id.thumbnail_imageview);
new imageLoader(thumbnail).execute(blist.getImage());
progressBar = listitemview.findViewById(R.id.Image_Progress_bar);
progressBar.setVisibility(View.GONE);
TextView title = listitemview.findViewById(R.id.title_textview);
title.setText(blist.gettitle());
TextView author = listitemview.findViewById(R.id.author_textview);
author.setText(blist.getauthor());
TextView publisher = listitemview.findViewById(R.id.publisher_texview);
publisher.setText(blist.getpublisher());
return listitemview;
}
private class imageLoader extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public imageLoader(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
}
Updated in Code
Initially set empty query
private String Book_list_request_url = "";
Create method for "Search Click(imagebutton)"
public void Search(View v)
{
Book_list_request_url = editText.getText().toString();
loaderManager.restartLoader(BOOK_LOADER_ID, null, this);
}
Add method to imagebutton
<ImageButton
android:id="#+id/search_button1"
android:layout_width="42dp"
android:layout_height="match_parent"
android:onClick="Search"
android:src="#drawable/ic_launcher_background" />

Waiting for multiple broadcast messages to be received before continuing

I have an app that uses a system of plugins. These "plugins" send out a broadcast message which my app then receives and uses the relevant data attached to register the app.
The issues is that I dont know how many plugin are installed on the device at any given time, so I dont know how many messages to wait for, and I don't know of any way to check to see if its the last message being sent.
Right now I'm kinding faking it by waiting for a three second timer to finish, allowing three seconds for the plugins to register, but as more plugins are developed, this isnt going to be enough time.
How can I refresh my UI only when all of the plugins have finished registering?
PanelReceiver.java
package com.t3hh4xx0r.haxlauncher.menu.livepanel;
import java.io.ByteArrayOutputStream;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import com.t3hh4xx0r.haxlauncher.DBAdapter;
public class PanelReceiver extends BroadcastReceiver {
private static final String PANEL_REQUEST = "com.t3hh4xx0r.haxlauncher.PANEL_REQUEST";
private static final String PANEL_REGISTER = "com.t3hh4xx0r.haxlauncher.PANEL_REGISTER";
private static final String PANEL_UPDATE = "com.t3hh4xx0r.haxlauncher.PANEL_UPDATE";
boolean shouldAdd = true;
#Override
public void onReceive(Context context, Intent intent) {
String a = intent.getAction();
if (a.equals(PANEL_REGISTER)) {
Bundle b = intent.getExtras();
String author = b.getString("author_name");
String plugin = b.getString("plugin_name");
String packageN = b.getString("package_name");
String desc = b.getString("description");
String version = b.getString("version");
DBAdapter db = new DBAdapter(context);
db.open();
Cursor c = db.getAllPanels();
if (c.getCount() != 0) {
while (c.moveToNext()) {
if (c.getString(c.getColumnIndex("author")).equals(author) &&
c.getString(c.getColumnIndex("package")).equals(packageN)){
shouldAdd = false;
if (!c.getString(c.getColumnIndex("version")).equals(version)) {
db.removePanel(packageN);
shouldAdd = true;
}
}
}
}
if (shouldAdd) {
db.insertPanel(version, author, plugin, packageN, desc, image("ic_launcher", context, packageN), image("screencap", context, packageN));
}
db.close();
} else if (a.equals(PANEL_UPDATE)) {
Log.d("UPDATE", "OMFG!");
}
}
public static void requestPanels(Context context) {
Intent i = new Intent();
i.setAction(PANEL_REQUEST);
context.sendBroadcast(i);
}
public byte[] image(String imageName, Context c, String packageN) {
try {
Context fC = c.getApplicationContext().createPackageContext(packageN, Context.CONTEXT_IGNORE_SECURITY);
Resources res = fC.getResources();
Bitmap photo = drawableToBitmap(res.getDrawable(res.getIdentifier(imageName, "drawable", packageN)));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, bos);
return bos.toByteArray();
} catch (NameNotFoundException e) {
return null;
}
};
public static Bitmap drawableToBitmap (Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable)drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}
PanelMenuActivity.java
package com.t3hh4xx0r.haxlauncher.menu.livepanel;
import java.util.ArrayList;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import com.t3hh4xx0r.haxlauncher.DBAdapter;
import com.t3hh4xx0r.haxlauncher.R;
public class PanelMenuActivity extends Activity {
ListView lv;
static ArrayAdapter<String> a;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.panel_menu);
lv = (ListView) findViewById(R.id.panel_list);
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int pos,
long id) {
Intent i = new Intent(v.getContext(), PanelDetails.class);
Bundle b = new Bundle();
b.putInt("pos", ((PanelDetailHolder)a.getItemAtPosition(pos)).id);
i.putExtras(b);
startActivity(i);
}
});
GetPanelsTask t = new GetPanelsTask();
t.execute();
}
private ListAdapter buildAdapter(Context c) {
return new PanelAdapter(this, getPanels(c));
}
public ArrayList<PanelDetailHolder> getPanels(Context ctx) {
ArrayList<PanelDetailHolder> panelArray = new ArrayList<PanelDetailHolder>();
DBAdapter db = new DBAdapter(ctx);
db.open();
Cursor c = db.getAllPanels();
while (c.moveToNext()) {
try{
getPackageManager().getApplicationInfo(c.getString(c.getColumnIndex("package")), 0 );
} catch (NameNotFoundException e){
db.removePanel(c.getString(c.getColumnIndex("package")));
continue;
}
PanelDetailHolder p = new PanelDetailHolder();
p.author = c.getString(c.getColumnIndex("author"));
p.title = c.getString(c.getColumnIndex("name"));
p.desc = c.getString(c.getColumnIndex("desc"));
p.version = c.getString(c.getColumnIndex("version"));
p.id = c.getPosition();
panelArray.add(p);
}
c.close();
db.close();
return panelArray;
}
#Override
public boolean onOptionsItemSelected(android.view.MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.refresh:
GetPanelsTask t = new GetPanelsTask();
t.execute();
}
return false;
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuinflate = new MenuInflater(this);
menuinflate.inflate(R.menu.panel_menu, menu);
return true;
}
public class GetPanelsTask extends AsyncTask<Object, View, Void> {
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
progressDialog= ProgressDialog.show(PanelMenuActivity.this,
"Loading...","Checking for live panels...", true);
PanelReceiver.requestPanels(PanelMenuActivity.this);
};
#Override
protected Void doInBackground(Object... params) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
};
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
progressDialog.dismiss();
lv.setAdapter(buildAdapter(PanelMenuActivity.this));
}
}
class PanelDetailHolder {
String author;
String title;
String desc;
String version;
Drawable screenCap;
Drawable icon;
int id;
}
}
How can I refresh my UI only when all of the plugins have finished registering?
By definition, it is not possible. You need to revise your plugin system so that either:
You "know how many plugin are installed on the device", or
You do not need to wait (or even really care) at any point "how many plugin are installed on the device"

Pass values of array inbetween classes

I am using a spinner when selected starts an intent and the class that is started gets and XML feed and displays it.
I am trying to call a different XML file based on what is selected by the user. I am not sure how the value can be passed to my XMLfunctions.java and once selected can the other classes reference that data?
HERE is my Eclipse Package Download
My thourghts were to have a multidimensional array with the titles for the spinner and the coinsiding XML url:
package com.patriotsar;
import android.app.Activity;
import android.content.Intent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;
public class patriosar extends Activity {
private Button goButton;
private String array_spinner[];
String url = "http://www.patriotsar.com";
Intent i = new Intent(Intent.ACTION_VIEW);
Uri u = Uri.parse(url);
Context context = this;
Spinner areaspinner;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
array_spinner=new String[4];
array_spinner[0]="George Washington","gw.xml";
array_spinner[1]="BENJAMIN FRANKLIN","bf.xml";
array_spinner[2]="THOMAS JEFFERSON","tj.xml";
array_spinner[3]="PATRICK HENRY","ph.xml";
goButton = (Button)findViewById(R.id.goButton);
areaspinner = (Spinner) findViewById(R.id.areaspinner);
ArrayAdapter<String> adapter =
new ArrayAdapter<String> (this,
android.R.layout.simple_spinner_item,array_spinner);
areaspinner.setAdapter(adapter);
goButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v){
try {
// Start the activity
i.setData(u);
startActivity(i);
} catch (ActivityNotFoundException e) {
// Raise on activity not found
Toast.makeText(context, "Browser not found.", Toast.LENGTH_SHORT);
}
}
});
areaspinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
int item = areaspinner.getSelectedItemPosition();
if(item != 0){
Intent myIntent = new Intent(patriosar.this, ShowXMLPAR.class);
startActivityForResult(myIntent, 0);
}
else {
// finish();
}
}
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
}
I then have a listener that calls an intent ShowXMLPAR.class when an item other then default is selected. The ShowXMLPAR class calls a function from XMLfunctions.java class and then shows the data that is returned. So the second value in the selected array item needs to be passed to to both pages I guess.
ShowXMLPAR.java:
package com.patriotsar;
import java.util.ArrayList;
import java.util.HashMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.patriotsar.XMLfunctions;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
public class ShowXMLPAR extends ListActivity {
private Button backButton;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listplaceholder);
backButton = (Button)findViewById(R.id.backButton);
backButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view){
Intent myIntent = new Intent(view.getContext(), patriosar.class);
startActivityForResult(myIntent, 0);
}
});
ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
String xml = XMLfunctions.getXML();
Document doc = XMLfunctions.XMLfromString(xml);
int numResults = XMLfunctions.numResults(doc);
if((numResults <= 0)){
Toast.makeText(ShowXMLPAR.this, "Geen resultaten gevonden", Toast.LENGTH_LONG).show();
finish();
}
NodeList nodes = doc.getElementsByTagName("result");
for (int i = 0; i < nodes.getLength(); i++) {
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element)nodes.item(i);
map.put("main_content", XMLfunctions.getValue(e, "content"));
map.put("name", XMLfunctions.getValue(e, "name"));
mylist.add(map);
}
//
ListAdapter adapter = new SimpleAdapter(ShowXMLPAR.this, mylist , R.layout.listlayout,
new String[] {"main_content", "name" },
new int[] { R.id.item_title, R.id.item_subtitle });
setListAdapter(adapter);
}
}
XMLfunctions.java:
package com.patriotsar;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class XMLfunctions {
public final static Document XMLfromString(String xml){
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
doc = db.parse(is);
} catch (ParserConfigurationException e) {
System.out.println("XML parse error: " + e.getMessage());
return null;
} catch (SAXException e) {
System.out.println("Wrong XML file structure: " + e.getMessage());
return null;
} catch (IOException e) {
System.out.println("I/O exeption: " + e.getMessage());
return null;
}
return doc;
}
/** Returns element value
* #param elem element (it is XML tag)
* #return Element value otherwise empty String
*/
public final static String getElementValue( Node elem ) {
Node kid;
if( elem != null){
if (elem.hasChildNodes()){
for( kid = elem.getFirstChild(); kid != null; kid = kid.getNextSibling() ){
if( kid.getNodeType() == Node.TEXT_NODE ){
return kid.getNodeValue();
}
}
}
}
return "";
}
public static String getXML(){
String line = null;
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpPost = new HttpGet("http://www.patriotsar.com/patriot_quotes.xml");
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
line = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
} catch (MalformedURLException e) {
line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
} catch (IOException e) {
line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
}
return line;
}
public static int numResults(Document doc){
Node results = doc.getDocumentElement();
int res = -1;
try{
res = Integer.valueOf(results.getAttributes().getNamedItem("count").getNodeValue());
}catch(Exception e ){
res = -1;
}
return res;
}
public static String getValue(Element item, String str) {
NodeList n = item.getElementsByTagName(str);
return XMLfunctions.getElementValue(n.item(0));
}
}
Sorry I am still learning but am excited to get into more advanced (for me) programming. Any Help would be awesome.
As of now the app works but calls the same xml no matter what.
I'm not following your description very well, but if you are wanting to pass data between Activities via Intents then make sure the data you pass can either be included as an Extra, or if you prefer to send actual objects then make sure your objects implement the Parcelable interface.

Categories