Store JSON Array from NewsAPI in Firebase - arrays

I have used volley to parse news data from the newsAPI.org. I want to save the response to Firebase for offline viewing and persistence.
This is the sample response from API:
articles: [
{
author: "Megan Rose Dickey",
title: "Ojo wants to be the electric scooter for commuters, but...",
description: "Commuting in a busy city like San Francisco can be
annoying..",
url: "https://techcrunch.com/2017/08/23/ojo-wants-to-be-the-electric-
scooter-for-commuters-but-its-not-there-yet/",
urlToImage: "https://img.vidible.tv/prod/2017",
publishedAt: "2017-08-23T21:19:56Z"
},
{
author: "Katie Roof",
title: "Pishevar intervenes in Benchmark-Kalanick lawsuit",
description: "Early Uber investor and former board member Shervin
Pishevar is speaking out against Benchmark again..",
url: "https://techcrunch.com/2017/08/24/pishevar-sends-another-letter-
to-uber-board-about-benchmark/",
urlToImage:"https://tctechcrunch2011.files.wordpress.com/",
publishedAt: "2017-08-24T22:49:59Z"
},
In total I have 5 objects inside the articles array.
I want to store each of the objects in Firebase database. This is what I have tried:
StringRequest stringRequest = new StringRequest(Request.Method.GET, Constants.NEWS_ENDPOINT,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response != null){
Log.d(TAG, "News Api Response is: \t" + response.toString());
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray articles = jsonObject.getJSONArray("articles");
for (int i = 0; i < articles.length(); i++){
JSONObject items = articles.getJSONObject(i);
final String title_news = items.getString("title");
final String desc_news = items.getString("description");
final String urlImg = items.getString("urlToImage");
final String author_news = items.getString("author");
final String url = items.getString("url");
final String publishedAt = items.getString("publishedAt");
NewsItem newsItem = new NewsItem(author_news, title_news, desc_news, url, urlImg, publishedAt);
itemList.add(newsItem);
/**
* Save JSON Results to Firebase
* */
for (int k = 0; k < articles.length(); k++){
HashMap hashMap = new HashMap();
hashMap.put("newsTitle", title_news);
hashMap.put("newsDesc", desc_news);
hashMap.put("newsImageUrl", urlImg);
hashMap.put("newsAuthor", author_news);
hashMap.put("newsUrl", url);
hashMap.put("newsDate", publishedAt);
newsRootRef.setValue(hashMap);
}
When I check the console, it saves only one object, the last object like this:
I want to store all objects AS-IS in the response array and retrieve them later. Is there another way to do this? Thanks, sorry for the long post.

In this case you need to use push() to store the data. Otherwise you are just replacing the data at the reference at each iteration. This is why it seems that only the last record gets stored. Try to change this line:
newsRootRef.setValue(hashMap);
...into this:
newsRootRef.push().setValue(hashMap);
To avoid duplicating entries I recommend that you fetch all entries from Firebase and cache the url property (since this property seems to be unique) in a HashSet. Then you can modify your code like this:
if (!urlSet.contains(url)) {
HashMap hashMap = new HashMap();
hashMap.put("newsTitle", title_news);
hashMap.put("newsDesc", desc_news);
hashMap.put("newsImageUrl", urlImg);
hashMap.put("newsAuthor", author_news);
hashMap.put("newsUrl", url);
hashMap.put("newsDate", publishedAt);
newsRootRef.push(),setValue(hashMap);
}
But of course you need to populate your HashSet first so I'd recommend doing something like this:
final Set<String> urlSet = new HashSet<>();
newsRootRef.addChildEventListener(new ChildEventListener() {
int i = 0;
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
urlSet.add(dataSnapshot.getValue(String.class));
if (i++ == dataSnapshot.getChildrenCount()) {
...
...your code...
StringRequest stringRequest = new StringRequest(Request.Method.GET, Constants.NEWS_ENDPOINT,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
...
...
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Related

Query in Firebase database child

I'm new to android. Can someone help me to query the below-underlined line in the firebase? The query result should be the underlined String.
That String is an autogenerated one in the firebase at the Driver signup. So hardcoding that string is not my aim.
Refer to Users/Driver and loop through children, you will get your key:
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child("Driver");
ValueEventListener listener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//loop through the children
for(DataSnapshot ds: dataSnapshot.getChildren()){
//get the key or keys depending on how many keys
String underLinedKey = ds.getKey();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//log error
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
};
mDatabase.addValueEventListener(listener);

Android: Parsing JSON. No value for...?

I am trying to parse JSON data generated by an API.Here is the json I am trying to parse:
{
"response":{
"legislator":[
{
"#attributes":{
"cid":"N00033987",
"firstlast":"Doug LaMalfa",
"lastname":"LAMALFA",
"party":"R",
"office":"CA01",
"gender":"M",
"first_elected":"2012",
"exit_code":"0",
"comments":"",
"phone":"202-225-3076",
"fax":"530-534-7800",
"website":"http:\/\/lamalfa.house.gov",
"webform":"https:\/\/lamalfa.house.gov\/contact\/email-me",
"congress_office":"322 Cannon House Office Building",
"bioguide_id":"L000578",
"votesmart_id":"29713",
"feccandid":"H2CA02142",
"twitter_id":"RepLaMalfa",
"youtube_url":"https:\/\/youtube.com\/RepLaMalfa",
"facebook_id":"RepLaMalfa",
"birthdate":"1960-07-02"
}
The response json object inside of the entire response is throwing me off. I cant get to the legislator array. The logcat gives me this error:
How can I modify my method to get to the legislator json array?
Here is my parsing method:
private void getData() {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading...");
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
progressDialog.dismiss();
try {
JSONObject jsonObject = new JSONObject(response);
JSONObject responseObj = jsonObject.getJSONObject("response");
JSONArray array = responseObj.getJSONArray("legislator");
for(int i = 0; i < array.length(); i++){
JSONObject attributesObj = array.getJSONObject(i);
//create object
Legs leg = new Legs(attributesObj.getString("firstlast"),
attributesObj.getString("party"),
attributesObj.getString("office"),
attributesObj.getString("gender"),
attributesObj.getString("birthdate"),
attributesObj.getString("first_elected"),
attributesObj.getString("phone"),
attributesObj.getString("website"),
attributesObj.getString("congress_office"),
attributesObj.getString("twitter_id"),
attributesObj.getString("youtube_url"),
attributesObj.getString("facebook_id"));
legList.add(leg);
}
adapter = new LegRvAdapter(Legislators.this, legList);
myrv.setAdapter(adapter);
}catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Log.e("Volley", volleyError.toString());
progressDialog.dismiss();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}

loaderManager recyclerview imageview viewholder content provider fails

I am new at android and new at posting here and trying a sink in slowly but am stuck here at inflating imageViews. Below am providing code snippets from my app that i would thank you for your help
Here is my table
private static final String CREATE_TABLE = "CREATE TABLE "+TABLE_NAME+" ("+KEY_ID,"+KEY_PROFILEPIC+" BLOB,"+KEY_IMAGE+" BLOB)";
this is my viewholder class
`public CityHolder(final View view) {
super(view);
ButterKnife.bind(this, itemView); }
public void bindData(final Cursor cursor) {
String name = cursor.getString(cursor.getColumnIndex("name"));
this.name.setText(name);
String CircularNetWorkImageView =cursor.getString(cursor.getColumnIndex("profilePic"));
this.CircularNetWorkImageView.setText(CircularNetWorkImageView);
}
`
and then i am using recyclerview to bind to cursor.
am also using a a content Provider to both insert and then retrieve data and load by use of the LoaderManager.LoaderCallbacks
here is how i get the data through volley json
JSONArray jsonArray = response.getJSONArray("city");
for (int i=0;i<jsonArray.length();i++)
{
JSONObject jsonObjectCity = jsonArray.getJSONObject(i);
String name = jsonObjectCity.getString("name");
String profilePic = jsonObjectCity.getString("profilePic");
String image = jsonObjectCity.getString("image");
City city = new City();
city.setName(name);
city.setProfilePic(profilePic);
city.setImage(image);
ContentValues values = new ContentValues();
values.put(CityDb.KEY_NAME, name);
values.put(CityDb.KEY_PROFILEPIC, profilePic);
values.put(CityDb.KEY_IMAGE, image);
getContentResolver().insert(CityContentProvider.CONTENT_URI, values);
}
}catch(JSONException e){e.printStackTrace();}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volley","Error");
}
}
);
requestQueue.add(jor);
}
#Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
String[] allColumns = new String[] {
CityDb.KEY_ID,
CityDb.KEY_NAME,
CityDb.KEY_PROFILEPIC,
CityDb.KEY_IMAGE
};
return new CursorLoader(this,CityContentProvider.CONTENT_URI,allColumns, null, null, null);
}`
Now the String Name is displayed in my fragment but am having issue getting the image and profilePic in circularNetworkimageView to display.
what could i be missing, please guide me

to display the data obtained from button listener to list- codename one

I have a button that display the data obtained from json. below is my code for button action. I need help to display the data obtained to list.
#Override
protected void onMain_ButtonAction(final Component c, ActionEvent event) {
ConnectionRequest r = new ConnectionRequest() {
Hashtable h;
#Override
protected void postResponse() {
}
#Override
protected void readResponse(InputStream input) throws IOException {
InputStreamReader reader = new InputStreamReader(input);
JSONParser p = new JSONParser();
h = p.parse(new InputStreamReader(input));
Hashtable response = p.parse(reader);
Hashtable feed = (Hashtable)response.get("root");
for (Object s : h.values()) {
Vector vec = new Vector(100);
vec = (Vector)s;
int i;
for(i = 0; i<vec.size(); i++){
Hashtable<String, String> ht= (Hashtable<String, String>) vec.get(i);
System.out.println(ht.get("location"));
// findLabel().setText(ht.get("location"));
}
}
}
};
r.setUrl("http://ruslanapp.demo.capitaleyenepal.com/vodka-mobile-interface/getData/locations");
r.setPost(false);
InfiniteProgress prog = new InfiniteProgress();
Dialog dlg = prog.showInifiniteBlocking();
r.setDisposeOnCompletion(dlg);
NetworkManager.getInstance().addToQueue(r);
}
I want to list the data obtained frm btn above to the list below. how can I do it??
#Override
protected boolean initListModelList1(List cmp) {
cmp.setModel(new com.codename1.ui.list.DefaultListModel(new String[] {"Item 1", "Item 2", "Item 3"}));
return true;
}
You did most of the work well, I suggest avoiding a list and using an infinite container. The PropertyCross demo has pretty much this functionality (including JSON): https://www.udemy.com/learn-mobile-programming-by-example-with-codename-one/
To finish the code above create the model ArrayList above e.g. assuming you are using a MultiList:
// define this in the class variables:
private ArrayList<Map<String, String>> modelData = new ArrayList<Map<String, String>>();
// then in the code (I assumed stuff about your JSON, correct the
// code to extract the data correctly, just set the hashmap values
for (Object s : h.values()) {
Collection<Map<String, String>>) data = (Collection<Map<String, String>>))s;
for(Map<String, String> ht : data) {
String location = ht.get("location");
HashMap<String, String> entry = new HashMap<String, String>();
entry.put("Line1", location);
modelData.add(entry);
}
}
Then in:
#Override
protected boolean initListModelList1(List cmp) {
cmp.setModel(new DefaultListModel(modelData));
return true;
}
Notice that you should use showForm() to show the next form in the postResponse method.

Suggest Addresses in a SuggestBox in GWT/Java

I want to define a SuggestBox, which behaves like the search bar in Google Maps: When you begin to type, real addresses, starting with the typed letters, appear.
I think, that I need to use the Geocoder.getLocations(String address, LocationCallback callback) method, but I have no idea how to connect this with the oracle, which is needed by the suggest box to produce its suggestions.
Can you please give me ideas how do I connect the getLocations Method with the SuggestOracle?
I solved this by implementing a subclass of SuggestBox, which has it's own SuggestOracle. The AddressOracle deals as a Wrapper for the Google Maps Service, for which the class Geocoderin the Google Maps API for GWT offers abstractions.
So here is my solution:
First we implement the Widget for a SuggestBox with Google Maps suggestions
public class GoogleMapsSuggestBox extends SuggestBox {
public GoogleMapsSuggestBox() {
super(new AddressOracle());
}
}
Then we implement the SuggestOracle, which wraps the Geocoder async method abstractions:
class AddressOracle extends SuggestOracle {
// this instance is needed, to call the getLocations-Service
private final Geocoder geocoder;
public AddressOracle() {
geocoder = new Geocoder();
}
#Override
public void requestSuggestions(final Request request,
final Callback callback) {
// this is the string, the user has typed so far
String addressQuery = request.getQuery();
// look up for suggestions, only if at least 2 letters have been typed
if (addressQuery.length() > 2) {
geocoder.getLocations(addressQuery, new LocationCallback() {
#Override
public void onFailure(int statusCode) {
// do nothing
}
#Override
public void onSuccess(JsArray<Placemark> places) {
// create an oracle response from the places, found by the
// getLocations-Service
Collection<Suggestion> result = new LinkedList<Suggestion>();
for (int i = 0; i < places.length(); i++) {
String address = places.get(i).getAddress();
AddressSuggestion newSuggestion = new AddressSuggestion(
address);
result.add(newSuggestion);
}
Response response = new Response(result);
callback.onSuggestionsReady(request, response);
}
});
} else {
Response response = new Response(
Collections.<Suggestion> emptyList());
callback.onSuggestionsReady(request, response);
}
}
}
And this is a special class for the oracle suggestions, which just represent a String with the delivered address.
class AddressSuggestion implements SuggestOracle.Suggestion, Serializable {
private static final long serialVersionUID = 1L;
String address;
public AddressSuggestion(String address) {
this.address = address;
}
#Override
public String getDisplayString() {
return this.address;
}
#Override
public String getReplacementString() {
return this.address;
}
}
Now you can bind the new widget into your web page by writing the following line in the onModuleLoad()-method of your EntryPoint-class:
RootPanel.get("hm-map").add(new GoogleMapsSuggestBox());

Resources