Sorting List alphabetically from JSON source - javascript

I've looked in a variety of places for an answer to my query, but nothing has helped me thus far. I'm currently trying to learn Android development, and i'm stuck on how to sort a list alphabetically. I am using this tutorial on how to create the list and have modified parts of the "Albums" page to suit my needs, from albums to artists (i'm still working on this, just wanting the sorting finished before changing it fully). This particular list calls on a file from a HTTP address when the app is accessed to check it for updates.
Here is the code from that particular page, minus all the imports:
public class AlbumsActivity extends ListActivity {
// Connection detector
ConnectionDetector cd;
// Alert dialog manager
AlertDialogManager alert = new AlertDialogManager();
// Progress Dialog
private ProgressDialog pDialog;
// Creating JSON Parser object
JSONParser jsonParser = new JSONParser();
ArrayList<HashMap<String, String>> albumsList;
// albums JSONArray
JSONArray albums = null;
// albums JSON url
private static final String URL_ALBUMS = "http://api.androidhive.info/songs/albums.php";
// ALL JSON node names
private static final String TAG_ID = "id";
private static final String TAG_NAME = "name";
private static final String TAG_SONGS_COUNT = "songs_count";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_albums);
cd = new ConnectionDetector(getApplicationContext());
// Check for internet connection
if (!cd.isConnectingToInternet()) {
// Internet Connection is not present
alert.showAlertDialog(AlbumsActivity.this, "Internet Connection Error",
"Please connect to working Internet connection", false);
// stop executing code by return
return;
}
// Hashmap for ListView
albumsList = new ArrayList<HashMap<String, String>>();
// Loading Albums JSON in Background Thread
new LoadAlbums().execute();
// get listview
ListView lv = getListView();
/**
* Listview item click listener
* TrackListActivity will be lauched by passing album id
* */
lv.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view, int arg2,
long arg3) {
// on selecting a single album
// TrackListActivity will be launched to show tracks inside the album
Intent i = new Intent(getApplicationContext(), TrackListActivity.class);
// send album id to tracklist activity to get list of songs under that album
String album_id = ((TextView) view.findViewById(R.id.album_id)).getText().toString();
i.putExtra("album_id", album_id);
startActivity(i);
}
});
}
/**
* Background Async Task to Load all Albums by making http request
* */
class LoadAlbums extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(AlbumsActivity.this);
pDialog.setMessage("Listing Artists...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting Albums JSON
* */
protected String doInBackground(String... args) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
String json = jsonParser.makeHttpRequest(URL_ALBUMS, "GET",
params);
// Check your log cat for JSON reponse
Log.d("Albums JSON: ", "> " + json);
try {
albums = new JSONArray(json);
if (albums != null) {
// looping through All albums
for (int i = 0; i < albums.length(); i++) {
JSONObject c = albums.getJSONObject(i);
// Storing each json item values in variable
String id = c.getString(TAG_ID);
String name = c.getString(TAG_NAME);
String songs_count = c.getString(TAG_SONGS_COUNT);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_ID, id);
map.put(TAG_NAME, name);
map.put(TAG_SONGS_COUNT, songs_count);
// adding HashList to ArrayList
albumsList.add(map);
}
}else{
Log.d("Albums: ", "null");
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all albums
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
AlbumsActivity.this, albumsList,
R.layout.list_item_albums, new String[] { TAG_ID,
TAG_NAME, TAG_SONGS_COUNT }, new int[] {
R.id.album_id, R.id.album_name, R.id.songs_count });
// updating listview
setListAdapter(adapter);
}
});
}
}
}
My problem is that I have no real idea where I need to put the Collections.sort command. I have tried in so many places, but cannot get it working. No matter where I put the command, it always sorts in order of ID. This is the full code I have for that:
Collections.sort(params, new Comparator<NameValuePair>() {
#Override
public int compare(NameValuePair art1, NameValuePair art2) {
//here getTitle() method return app name...
return art1.getName().compareToIgnoreCase(art2.getName());
}
});
If I try to have return art1.name.compareToIgnoreCase(art2.name); it comes back with an error that says name cannot be resolved or is not a field. I'm really stumped. I thought a list might be a good way to start learning to develop for Android, but now i'm finding this incredibly hard.
Any help would be greatly appreciated.

Related

Assigning retrofit json data to global variable

I get the json value using the retrofit library at application launch and I want to send it to the global variable in the class. How can I do it?
Domain is coming, I can see it on the screen with toast message
public void onCreate() {
setRetrofitSettings();
}
public void setRetrofitSettings(){
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
timeApi = retrofit.create(TimeApi.class);
timeTurkeyCall = timeApi.getTime();
timeTurkeyCall.enqueue(new Callback<TimeTurkey>() {
#Override
public void onResponse(Call<TimeTurkey> call, Response<TimeTurkey> response) {
if (response.isSuccessful()){
timeTurkey = response.body();
Global.APIURL = String.valueOf(timeTurkey.getDateTime());
// I want to send the value here.
}
}
#Override
public void onFailure(Call<TimeTurkey> call, Throwable t) {
System.out.println(t.toString());
}
});
}
I want to send post value to global class
I want the incoming data to be assigned to the API_URL variable from here
public class Global {
public static final String API_URL;
}
I want the incoming domain to be active as long as the application is open.

Why my GET call gets an array with empty objects?

I have a c# web project that has some REST request to do to get data from the db. My problem is: I have a GET call which return an array of the size of the number of rows returned by the query but every object is empty. While I'm debugging, every object has all the data I need but when the data reach the javascript the array is full of empty object. Where am I wrong?
This is the request on the .js file:
$.get("api/giacenzemobile/getGiacenze", function (data) {
console.log(data)
});
This is the function on the model file (.cs)
public static List<GiacenzeMobile> EstraiGiacenzeMobile()
{
List<GiacenzeMobile> giacenzeMobile = new List<GiacenzeMobile>();
SqlCommand cmd = null;
SqlConnection sqlconn = null;
using (sqlconn = new SqlConnection(Configurazione.ConnessioneDB))
{
sqlconn.Open();
string query = "...";
cmd = new SqlCommand(query, sqlconn);
SqlDataReader res = cmd.ExecuteReader();
while (res.Read())
{
GiacenzeMobile giac = new GiacenzeMobile();
giac.IdGiacenza = res.GetInt32(0);
//..... set all data ...
giacenzeMobile.Add(giac);
}
return giacenzeMobile;
}
}
And this is the controller (.cs):
public class GiacenzeMobileController : ApiController
{
[Route("api/giacenzemobile/getGiacenze")]
public IEnumerable<GiacenzeMobile> GetGiacenze()
{
return GiacenzeMobile.EstraiGiacenzeMobile();
}
//...other code...
}
And this is the result write on the console log:
Array(6)0: {}1: {}2: {}3: {}4: {}5: {}
SOLVED
I didn't set as public the fields of the GiacenzeMobile object.
If your attributes are private kotlin will not add it to the JsonString when it is deserialized. So make them public or remove the private identifier

Android WebView not returning desired HTML

so a quick overview of what I'm doing
I am using Android Webview to Render JavaScript and then reading the HTML from the javascript to parse it.
I am currently having trouble with retrieving the HTML from a website called Sport Chek.
Here is the code for my SportChekSearch class:
public class SportChekSearch extends SearchQuery{
public Elements finalDoc;
private ArrayList<Item> processed;
private final Handler uiHandler = new Handler();
public int status = 0;
//This basically is just so that the class knows which Activity we're working with
private Context c;
protected class JSHtmlInterface {
#android.webkit.JavascriptInterface
public void showHTML(String html) {
final String htmlContent = html;
uiHandler.post(
new Runnable() {
#Override
public void run() {
Document doc = Jsoup.parse(htmlContent);
}
}
);
}
}
/**
* Constructor method
* #param context The context taken from the webview (So that the asynctask can show progress)
*/
public SportChekSearch(Context context, String query) {
final Context c = context;
try {
final WebView browser = new WebView(c);
browser.setVisibility(View.INVISIBLE);
browser.setLayerType(View.LAYER_TYPE_NONE, null);
browser.getSettings().setJavaScriptEnabled(true);
browser.getSettings().setBlockNetworkImage(true);
browser.getSettings().setDomStorageEnabled(true);
browser.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
browser.getSettings().setLoadsImagesAutomatically(false);
browser.getSettings().setGeolocationEnabled(false);
browser.getSettings().setSupportZoom(false);
browser.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
browser.addJavascriptInterface(new JSHtmlInterface(), "JSBridge");
browser.setWebViewClient(
new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url) {
browser.loadUrl("javascript:window.JSBridge.showHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
}
}
);
browser.loadUrl("https://www.sportchek.ca/search.html#q=" + query.replaceAll(" ", "+") + "&lastVisibleProductNumber=3");
browser.loadUrl(browser.getUrl());
final String link = browser.getUrl();
new fetcher(c).execute(link);
}
catch(Exception e){
e.printStackTrace();
}
//Get the link from the WebView, and save it in a final string so it can be accessed from worker thread
}
/**
* This subclass is a worker thread meaning it does work in the background while the user interface is doing something else
* This is done to prevent "lag".
* To call this class you must write fetcher(Context c).execute(The link you want to connect to)
*
*/
class fetcher extends AsyncTask<String, Void, Elements> {
Context mContext;
ProgressDialog pdialog;
public fetcher(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pdialog = new ProgressDialog(mContext);
pdialog.setTitle(R.string.finding_results);
pdialog.setCancelable(false);
pdialog.show();
}
//This return elements because the postExecute() method needs an Elements object to parse its results
#Override
protected Elements doInBackground(String... strings) {
//You can pass in multiple strings, so this line just says to use the first string
String link = strings[0];
//For Debug Purposes, Do NOT Remove - **Important**
System.out.println("Connecting to: " + link);
try {
doc = Jsoup.connect(link)
.ignoreContentType(true)
.userAgent("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36")
.timeout(10000)
.get();
finalDoc = doc.select("body section.product-grid-wrapper");
System.out.println(finalDoc.toString());
} catch (IOException e) {
e.printStackTrace();
}
return finalDoc;
}
#Override
protected void onPostExecute(Elements result) {
//This line clears the list of info in the Search activity
//I should probably be using a getter method but adapter is a static variable so it shouldn't matter
//parse seperates document into elements
//crunch results formats those elements into item objects
//I am saving the result of this to an ArrayList<Item> called "processed"
processed = crunchResults(result);
//For debug purposes, do NOT remove - **Important**
System.out.println(processed.size() + " results have been crunched by Sport Chek.");
//Adds all of the processed results to the list of info in Search activity
ClothingSearch.adapter.addAll(processed);
//For debug purposes, do NOt remove - **Important
System.out.println("Adapter has been notified by Sport Chek.");
//Closes the progress dialog called pdialog assigned to the AsyncTask
pdialog.dismiss();
ClothingSearch.adapter.notifyDataSetChanged();
SearchQueueHandler.makeRequest(mContext, processed, SearchQueueHandler.CLOTHING_SEARCH);
}
}
public ArrayList<Item> crunchResults(Elements e){
ArrayList<Item> results = new ArrayList<Item>();
try {
for (int i = 0; i < e.size(); i++) {
Element ele = e.get(i);
String link = "https://www.sportchek.ca" + ele.select(" a.product-grid__link").attr("href");
System.out.println("https://www.sportchek.ca" + ele.select(" a.product-grid__link").attr("href"));
String title = ele.select(" span.product-title-text").text();
String pricestring = ele.select(" span.product-price__wrap").text();
price = Double.parseDouble(pricestring.substring(pricestring.lastIndexOf("$")));
System.out.println(pricestring);
//*******************************************
String store = "Sport Chek";
//Adds the formatted item to an ArrayList of items
results.add(new Item(title, store, price, link));
//Prints the object's to String to console
//For debug purposes, do NOT remove - **Important
System.out.println(results.get(i).toString());
}
} catch (Exception a){
a.printStackTrace();
}
return results;
}
public int getStatus(){
return status;
}
}
The two relevant methods are doInBackground in my AsyncTask and the crunchResults method.
Here is the result I get from using Ctrl+Shift+I on the actual website (Desired Result):
But when running the above code and using a println here is the result that I get for the tag section class="product-grid-wrapper" :
<section class="product-grid-wrapper">
<ul data-module-type="SearchProductGrid" class="product-grid__list product-grid__list_quickview">
<!-- #product-grid__item-template -->
</ul>
</section>
Can anyone help me figure out why I am not getting my desired result?
All help is appreciated
EDIT: for this specific search that the println data was collected from, the link was https://www.sportchek.ca/search.html#q=men+coat&lastVisibleProductNumber=3
It looks like what you are actually getting is the actual html sent by the server, and that your 'desired result' is what the DOM looks like after the JavaScript runs.
Your 'actual' is what I see if I use "View Source" in Chrome, while your "desired result" is what I see if I use Chrome's DOM inspector.
On further inspection, I see that you are not actually getting the HTML from the browser, you are (indirectly) using JSoup's Connection object to get the HTML directly. Unfortunately, that's not going to run the Javascript.
Instead, you're going to have to get the HTML from the WebView after the JavaScript runs. For a possible way to do that, see How do I get the web page contents from a WebView?
Then, you give the HTML that you get from that to JSoup with
Jsoup.parse(html);

Wicket AbstractDefaultAjaxBehavior do recursive update the page

I have some ajax Behaviour that should pick some data using JS, and turn it back to Java. Sometimes it works but quite ofen it is just add url parameter and do page refresing/
public abstract class LoggedVKIdBehaviour extends AbstractDefaultAjaxBehavior {
private static final Logger logger = LoggerFactory.getLogger(LoggedVKIdBehaviour.class);
#Override
protected void respond(AjaxRequestTarget target) {
String loggedVkId = RequestCycle.get().getRequest().getRequestParameters().getParameterValue("logged_vkid").toString();
logger.info("ajax has comming with logged VK ID " + loggedVkId);
recived(target, loggedVkId);
}
protected abstract void recived(AjaxRequestTarget target, String loggedVkId);
#Override
public void renderHead(final Component component, IHeaderResponse response) {
super.renderHead(component, response);
Map<String, Object> map = new HashMap<>();
map.put("callbackFunction", getCallbackFunction(CallbackParameter.explicit("logged_vkid")));
//
PackageTextTemplate ptt = new PackageTextTemplate(LoggedVKIdBehaviour.class, "vkid_callback.js");
OnDomReadyHeaderItem onDomReadyHeaderItem = OnDomReadyHeaderItem.forScript(ptt.asString(map));
response.render(onDomReadyHeaderItem);
}
}
js template
var calback = ${callbackFunction};
var logged_vk_id = 11;
function authInfo(response) {
if (response.session) {
logged_vk_id = response.session.mid;
calback(response.session.mid);
console.log("recived callback from VK " + logged_vk_id);
}
}
$(document).ready(function () {
VK.Auth.getLoginStatus(authInfo);
});
it is do recursive redirection like http://localhost:8080/mytool/product/1?logged_vkid=332797331&logged_vkid=332797331&logged_vkid=332797331&logged_vkid=332797331&logged_vkid=332773...
As i understand Ajaj technology - iti asynchronus requests, that shouldn't touch main url at all. So what is the reason for page refreshing?
this is generated Callback function
function (logged_vkid) {
var attrs = {"u":"../wicket/bookmarkable/com.tac.kulik.pages.product.ProductPage?12-1.IBehaviorListener.0-&productID=1"};
var params = [{"name":"logged_vkid","value":logged_vkid}];
attrs.ep = params.concat(attrs.ep || []);
Wicket.Ajax.ajax(attrs);
}
I use wicket 7.2
I did a lot investigations for few days. And found that when i remove
setPageManagerProvider(new NoSerializationPageManagerProvider(this));
Application throw me exepton in polite logs
org.apache.wicket.WicketRuntimeException: A problem occurred while
trying to collect debug information about not serializable object look
like it is could come from aused by: java.io.NotSerializableException:
com.tac.kulik.panel.smaccounts.SMAccountsPanel$1
which means that page tryed to be serialized for SOME REASON but $1 it is mean Anonimous class. I had few class created anonimously to ges some ajax links coming from ListView to be managed on parent panel. So After removing this Anonimous class logic, everything start and run well.
So i am happy, but still don't understand which reason page did serialization after ajax, and what the reason was to refresh whole page.

Firebase - Count online users

I tried using presence to make it display the total connected users in an element. I can't really figure out how to make it work.
I also tried doing the following:
var dataUlist = new Firebase('https://<url>.firebaseio.com/.info/connected');
dataUlist.on('value', function(snap) {
console.log(snap);
});
To tried to see if I could find anything useful in there, but I couldn't figure out how the data works.
Is there any way to accomplice what I am after? Fetch the total number of connected users and then echo it out in the console or to an element?
.info/connected will only return information about whether the current client is connected or not. In order to maintain a presence count, you'll need to create a counter by storing presence information for each user and utilizing setOnDisconnect(). For example:
var listRef = new Firebase("https://<url>.firebaseio.com/presence/");
var userRef = listRef.push();
// Add ourselves to presence list when online.
var presenceRef = new Firebase("https://<url>.firebaseio.com/.info/connected");
presenceRef.on("value", function(snap) {
if (snap.val()) {
// Remove ourselves when we disconnect.
userRef.onDisconnect().remove();
userRef.set(true);
}
});
// Number of online users is the number of objects in the presence list.
listRef.on("value", function(snap) {
console.log("# of online users = " + snap.numChildren());
});
Here is the the code from Anant formatted for Android
public void getDbCount() {
Firebase listRef = new Firebase("https://<your-firebase-database>.firebaseio.com/presence/");
final Firebase userRef = listRef.push();
// Add ourselves to presence list when online.
Firebase presenceRef = new Firebase("https://<your-firebase-database>.firebaseio.com/.info/connected");
ValueEventListener myPresence = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
// Remove ourselves when we disconnect.
userRef.onDisconnect().removeValue();
userRef.setValue(true);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("DBCount", "The read failed: " + firebaseError.getMessage());
}
};
presenceRef.addValueEventListener(myPresence);
// Number of online users is the number of objects in the presence list.
ValueEventListener myList = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
// Remove ourselves when we disconnect.
Log.i("DBCount", "# of online users = " + String.valueOf(snapshot.getChildrenCount()));
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("DBCount", "The read failed: " + firebaseError.getMessage());
}
};
listRef.addValueEventListener(myList);
}

Categories