Cyril T.
... press F13! It works here :P
vendredi 7 mars 2014
vendredi 8 novembre 2013
WordPress Plugin : Page-In-Page
The Page In Page plugin has a very simple mission: Insert posts and pages within each other
with no stress.
It provides possibilities to use both widgets and shortcodes. If using a widget you are only able to
include pages within pages but if using the shortcode, you are able to able to insert posts/pages
within other posts/pages.
The settings in the widget include:
With shortcodes, you can insert posts in posts, pages in pages, posts in pages and vice versa.
Settings that can be used in a shortcode are:
Note that if you are specifying a template in the shortcode, then the above settings will be ignored and the slugs you insert in your template will be replaced with appropriate content.
See a template example and allowed slugs above.
To insert a shortcode you can do one of the following:
with no stress.
It provides possibilities to use both widgets and shortcodes. If using a widget you are only able to
include pages within pages but if using the shortcode, you are able to able to insert posts/pages
within other posts/pages.
Installation
- Download the plugin from http://wordpress.org/plugins/page-in-page/
- Extract the zip file. You should find the a folder with name 'page-in-page’.
- Upload the 'page-in-page` folder to the `/wpcontent/plugins/` directory
- Activate the plugin through the 'Plugins' menu in WordPress Admin
- Read the usage instructions below
Usage
Using the widget
- Title: Widget Title. This title will be shown as the page's title if 'Show page title' option is not selected.
- Page: Select the page that will be included when widget is called.
- Show page title: If checked (selected) then the page title will be shown and the 'Widget Title' ignored.
- Show title as link: If checked (selected) the title will be displayed as a link to the page.
- Show page content: If checked (selected) then the page content will be included in the output.
- Show featured image: If checked (selected) then the featured image will be included in the output.
- Show featured image as link : If checked (selected) then the featured image will be included and linked to page in the output.
- Output Template: Insert an HTML template that will be used to display content of the widget. If not provided the default template will be used
Slugs that can be used in your template are ${page_title}, ${page_content}, ${page_link}, ${page_image} . Each are self explanatory of what they will be replaced with. -
The default output template is
<div class="twl-page-in-page">
<span class="twl-page-in-page-title">${page_title}</span>
<div class="twl-page-in-page-content">
<div class="twl-page-in-page-image"><img src="${page_image}" /></div>
<div class="twl-page-in-page-text">${page_content}</div>
</div>
</div>
Using shortcode
Settings that can be used in a shortcode are:
- id : The ID of the page/post you want to insert
- show_page_title: should the page title be displayed? (Can be 1 for true or 0 for false. Defaults to 1)
- show_page_content: should the page title be displayed? (Can be 1 for true or 0 for false. Defaults to 1)
- show_title_as_link: Can be 1 for true or 0 for false. Defaults to 0. If set to 1, the page title will be displayed as a link to the page/post
- show_featured_image: Can be 1 for true or 0 for false. Defaults to 0. If set to 1, the page's featured image will be included
- show_featured_image_as_ink: Can be 1 for true or 0 for false. Defaults to 0. If set to 1, the page's featured image will be included as a link
To insert a shortcode you can do one of the following:
- To insert without specifying a template you can simply use
[twl_page_in id=123] OR [twl_page_in id=123 show_page_title=1]. - To insert your shortcode specifying a template for page/post's title and content use the following. You can include other supported slugs mentioned above
[twl_page_in id=123 show_page_title=1]
<h3 class="my-awesome-title-class">${page_title}</h3>
<div class="my-awesome-content-class">${page_content}</div>
[/twl_page_in]
The template specified in the [twl_page_in] tag will be used to display the page/post with the specified id when inserting it. The template is optional and if not specified then the default template will be used.
IMPORTANT!!! If you specify a template, you MUST have the slugs you want to be shown else you might get unexpected results
IMPORTANT!!! This template has to be defined when Editor is in 'Visual' mode and NOT in 'Text' mode (see screen shot). If you do not respect this you might have unexpected results because HTML tags might not be parsed properly. However if you have escaping with magic quotes off on your server then template should be defined when editor is in 'Text' mode. - To insert posts from your Facebook page, Go to Admin > Settings > Page In Page Plugin and insert your facebook application credentials. Next edit the page where you want the posts to appear and insert the short code [twl_page_in_fb]
- To insert tweets from your twitter account, Go to Admin > Settings > Page In Page Plugin and insert your twitter application credentials. Next edit the page where you want the posts to appear and insert the short code [twl_page_in_tw].
lundi 21 octobre 2013
Android: Re-using AsyncTask class across multiple Activities.
First I will like to start by apologizing for not putting this up a long time ago after several email request. I have very little time to put these Tutorials together for public consumption and I prefer responding with short snippets via email. Anyway.. that aside.
This post assumes you have a basic understanding of Android Development precisely about Activities and AsyncTasks. You can visit respective links to learn more on the official android documentation.
I will try to explain how to use a single Async class across Activities that make asynchronous request to a web service.
Suppose you have a REST API that always responds with some JSON output (which we will get as a string) and you need to call this API in multiple (greater than two) Activities. It will be good to have a common AsyncTask class, where you only pass an entry-point URL and a set of parameters and it returns the response. If you however have only a single activity that does some asynchronous task, it will be good design to implement it's AsyncTask class as a private sub class. So, how can we go about implementing a single AsyncTask class to be used in multiple Activities?
/res/layout/activity_post.xml
First you assign a label to each request and pass that label to the AsyncRequest Class and back to the asyncResponse() method. Your constructor could be like
And your interface defined as
and when calling the interface after the request is complete in the postExecute() or isCancelled() methods you do
and finally back in the Activity you implement your asyncResponse() method as follows
This post assumes you have a basic understanding of Android Development precisely about Activities and AsyncTasks. You can visit respective links to learn more on the official android documentation.
I will try to explain how to use a single Async class across Activities that make asynchronous request to a web service.
Suppose you have a REST API that always responds with some JSON output (which we will get as a string) and you need to call this API in multiple (greater than two) Activities. It will be good to have a common AsyncTask class, where you only pass an entry-point URL and a set of parameters and it returns the response. If you however have only a single activity that does some asynchronous task, it will be good design to implement it's AsyncTask class as a private sub class. So, how can we go about implementing a single AsyncTask class to be used in multiple Activities?
- We will implement a sub class of the AsyncTask class which will define an interface that MUST be implemented in the calling Activity. This subclass will take as parameters the calling activity (type: Activity), method (POST or GET type: String) and a set of parameters (type: List<namevaluepair>). Three constructors will be implemented to make the last two parameters optional.
- We will show a ProgressDialog while the request is being executed in the background.
- We demonstrate the use of this class by defining and example Activity.
A. The subclass: AsyncRequest.java
package com.sewoyebah.examples; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URLEncoder; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; public class AsyncRequest extends AsyncTask<String, Integer, String> { OnAsyncRequestComplete caller; Context context; String method = "GET"; List<NameValuePair> parameters = null; ProgressDialog pDialog = null; // Three Constructors public AsyncRequest(Activity a, String m, List<NameValuePair> p) { caller = (OnAsyncRequestComplete) a; context = a; method = m; parameters = p; } public AsyncRequest(Activity a, String m) { caller = (OnAsyncRequestComplete) a; context = a; method = m; } public AsyncRequest(Activity a) { caller = (OnAsyncRequestComplete) a; context = a; } // Interface to be implemented by calling activity public interface OnAsyncRequestComplete { public void asyncResponse(String response); } public String doInBackground(String... urls) { // get url pointing to entry point of API String address = urls[0].toString(); if (method == "POST") { return post(address); } if (method == "GET") { return get(address); } return null; } public void onPreExecute() { pDialog = new ProgressDialog(context); pDialog.setMessage("Loading data.."); // typically you will define such // strings in a remote file. pDialog.show(); } public void onProgressUpdate(Integer... progress) { // you can implement some progressBar and update it in this record // setProgressPercent(progress[0]); } public void onPostExecute(String response) { if (pDialog != null && pDialog.isShowing()) { pDialog.dismiss(); } caller.asyncResponse(response); } protected void onCancelled(String response) { if (pDialog != null && pDialog.isShowing()) { pDialog.dismiss(); } caller.asyncResponse(response); } @SuppressWarnings("deprecation") private String get(String address) { try { if (parameters != null) { String query = ""; String EQ = "="; String AMP = "&"; for (NameValuePair param : parameters) { query += param.getName() + EQ + URLEncoder.encode(param.getValue()) + AMP; } if (query != "") { address += "?" + query; } } HttpClient client = new DefaultHttpClient(); HttpGet get= new HttpGet(address); HttpResponse response = client.execute(get); return stringifyResponse(response); } catch (ClientProtocolException e) { // TODO Auto-generated catch block } catch (IOException e) { // TODO Auto-generated catch block } return null; } private String post(String address) { try { HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost(address); if (parameters != null) { post.setEntity(new UrlEncodedFormEntity(parameters)); } HttpResponse response = client.execute(post); return stringifyResponse(response); } catch (ClientProtocolException e) { // TODO Auto-generated catch block } catch (IOException e) { // TODO Auto-generated catch block } return null; } private String stringifyResponse(HttpResponse response) { BufferedReader in; try { in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); StringBuffer sb = new StringBuffer(""); String line = ""; while ((line = in.readLine()) != null) { sb.append(line); } in.close(); return sb.toString(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
First we define the three constructors that our class should support, the first supports three parameters, the second two and the third one. Next we define the interface which the calling
Activity must implement and hence override the asyncResponse() method. Next we implement the required inherited methods. Depending on the method specified, we call the get() or post() private functions
which will return the server response that will be passed to the onPostExecute() method and back to our Activity via the implemented interface.
Please read the official Documentation on AsyncTask to have an understanding of the inherited methods. In summary onPreExecute() is called just before the request is sent, doInBackgroud() is what actually does the job and returns a value which a passed to onPostExecute() called after request is completed. If request was cancelled, onCancelled() is called instead of onPostExecute(). A typical example of a canceled request is when user rotates a device when request is not completed. If you didn't handle the activity life cycle properly then Activity will be redrawn and another request will be made (cancelling the previous).
We also use here a progressDialog to indicate to the user something is being executed. It is initialized in the onPreExecute() method because we don't want to do this in each constructor of the class and besides we still have hold of the UI thread in the onPreExecute() method.
B. The Example Activity: PostsActivity.java
package com.sewoyebah.examples; import java.util.ArrayList; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.os.Bundle; import android.app.Activity; import android.widget.TextView; public class PostsActivity extends Activity implements AsyncRequest.OnAsyncRequestComplete { TextView titlesView; String apiURL = "http://www.example.com/apis/posts"; ArrayList<NameValuePair> params; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_posts); // TODO Auto-generated method stub titlesView = (TextView) findViewById(R.id.post_titles); params = getParams(); AsyncRequest getPosts = new AsyncRequest(this, "GET", params); getPosts.execute(apiURL); } // override method from AsyncRequest.OnAsyncRequestComplete interface // the response can contain other parameters specifying if the request was // successful or not and other things // in a real world application various checks will be done on the response @Override public void asyncResponse(String response) { try { // create a JSON array from the response string JSONArray objects = new JSONArray(response); // define a string to hold out titles (in a real word application you will be using a ListView and an Adapter to do such listing) String titles = ""; String NL = "\n"; String DOT = ". "; for (int i = 0; i < objects.length(); i++) { JSONObject object = (JSONObject) objects.getJSONObject(i); titles += object.getString("id") + DOT + object.getString("title") + NL; } titlesView.setText(titles); } catch (JSONException e) { e.printStackTrace(); } } // here you specify and return a list of parameter/value pairs supported by // the API private ArrayList<NameValuePair> getParams() { // define and ArrayList whose elements are of type NameValuePair ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("start", "0")); params.add(new BasicNameValuePair("limit", "10")); params.add(new BasicNameValuePair("fields", "id,title")); return params; } }
This is a pretty straight forward Android Activity. In this example we will assume our response is a JSON array. That is, an array of JSON Objects. For example:
[{"id": 1, "title": "Title of post 1"}, {"id": 2, "title": "Title of post 2"}, {"id": 3, "title": "Title of post 3"}];
Observe that the class implements the AsyncRequest.OnAsyncRequestComplete interface of the AsyncRequest and hence must override the asyncResponse() method of this interface.
To execute the request in the onCreate() method, we define the set of parameters using the getParams() method, create an instance of the AsyncRequest class and call it's execute() method passing to it the entry point (URL) of your API. It is common to use and ArrayList of NameValuePairs as a paramter set.
The response will be received and parsed as a String by our AsyncRequest class and passed to the asyncResponse() interface method as a string.
[{"id": 1, "title": "Title of post 1"}, {"id": 2, "title": "Title of post 2"}, {"id": 3, "title": "Title of post 3"}];
Observe that the class implements the AsyncRequest.OnAsyncRequestComplete interface of the AsyncRequest and hence must override the asyncResponse() method of this interface.
To execute the request in the onCreate() method, we define the set of parameters using the getParams() method, create an instance of the AsyncRequest class and call it's execute() method passing to it the entry point (URL) of your API. It is common to use and ArrayList of NameValuePairs as a paramter set.
The response will be received and parsed as a String by our AsyncRequest class and passed to the asyncResponse() interface method as a string.
In the asyncResponse(), we create a JSONArray from this string and read each object and display a list of titles. In a typical real world application, you will implement this using a ListView and an Adapter but this is out of the scope of this tutorial. Here we just concatenate the titles as a String and display in a TextView.
C. Another Example Activity: PostActivity.java
Another example of an activity could be one that gets the details of a post using the post ID. This will typically be launched as an Intent from the Listing Activity. In my next post I will try to explain the same concept using a ListView and an ArrayAdapter to display a list of posts and onClick opens the details of a post in another activity
package com.sewoyebah.examples; import java.util.ArrayList; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import org.json.JSONException; import org.json.JSONObject; import android.os.Bundle; import android.app.Activity; import android.widget.TextView; public class PostActivity extends Activity implements AsyncRequest.OnAsyncRequestComplete { TextView postView; String apiURL = "http://www.example.com/apis/posts"; ArrayList<NameValuePair> params; String postID = "75"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_post); // TODO Auto-generated method stub postView = (TextView) findViewById(R.id.post_view); params = getParams(); AsyncRequest getPosts = new AsyncRequest(this, "GET", params); getPosts.execute(apiURL); } // override method from AsyncRequest.OnAsyncRequestComplete interface @Override public void asyncResponse(String response) { try { // create a JSON array from the response string JSONObject postObject = new JSONObject(response); // define a string to hold out titles // (in a real word application you will be using a ListView and an // Adapter to do such listing) String post = ""; String NL = "\n"; post += postObject.getString("title") + NL + NL; post += postObject.getString("description"); postView.setText(post); } catch (JSONException e) { e.printStackTrace(); } } // here you specify and return a list of parameter/value pairs supported by // the API private ArrayList<NameValuePair> getParams() { // define and ArrayList whose elements are of type NameValuePair ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("id", postID)); return params; } }
In case you want to fully test code, bellow are the Layout xml files:
/res/layout/activity_posts.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".PostsActivity" > <TextView android:id="@+id/post_titles" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
/res/layout/activity_post.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".PostActivity" > <TextView android:id="@+id/post_view" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
So in summary after defining the AsyncRequest class this is what you do for each Activity that is to use it:
Class definition
public class MyActivity extends Activity implements AsyncRequest.OnAsyncRequestComplete
Define set of paramters:
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("id", "75")); params.add(new BasicNameValuePair("attributes", "title,description"));
Start our async task
AsyncRequest request = new AsyncRequest(this, 'GET', params); request.execute(apiURL);
And implement our asyncResponse() method which will be called after the async request is completed
public void asyncResponse(String response) { ... }
Sending multiple asynchronous requests in same activity
One will now ask: Is it possible to send multiple asynchronous requests from same activity using the AsyncRequest class? The answer is yes but you need to add a bit more to the above solution and keep in mind there is a limit to the number of threads you can run simultaneously based on the API version your app supports. See Android documentation for details.First you assign a label to each request and pass that label to the AsyncRequest Class and back to the asyncResponse() method. Your constructor could be like
public AsyncRequest(Activity a, String m, List<NameValuePair> p, String l) { caller = (OnAsyncRequestComplete) a; context = a; method = m; parameters = p; label = l; }
And your interface defined as
public interface OnAsyncRequestComplete { public void asyncResponse(String response, String label); }
and when calling the interface after the request is complete in the postExecute() or isCancelled() methods you do
caller.asyncResponse(response, label);
and finally back in the Activity you implement your asyncResponse() method as follows
public void asyncResponse(String response, String label) { swtich(label) { case "get_posts_request" // call some method to complete the request // you initialized your class with new AsyncRequest(this, "GET", params, "get_posts_request") completeGetPostRequest(response); break; case "some_other_label" // call some method to complete the request // you initialized your class with new AsyncRequest(this, "POST", params, "some_other_label") completeSomeOtherRequest(response); break; } }
Hope this gives some insights..
samedi 5 janvier 2013
Populate an Android Spinner with JSON data from a RESTful web API
In the following tutorial I will explain how to populate and Android Spinner (almost equivalent to a java combo box) using JSON data fetched from a REST API. This tutorial DOES NOT explain how to set up and android app or components of an android app; it only explains how to populate an Android spinner. Hoping we are clear with what this does let's begin.
I will use JSON data from the following RESTful API
It is a country/region/city database I put together from various sources and you query by sending some NVP parameters. I will also explain how to do this in our android application. Just as a quick example calling the API with the NVP
We will use data returned from http://www.cmcredit.com/apps/apis/map/?call=countrylist which is of the following format:
Create the various Layouts
1. Activity layout: one TextView and one Spinner (res/layout/activity_spinnerdemo.xml)
The TextView will simply display the text of the android:text attribute on the screen and the spinner will be populated by our Activity class.
2. The layout of each item in the spinner (res/layout/simple_spinner_item.xml)
Define the Activity class
Secondly we define our activity class that will be launched when you start your application (if you set it as the main activity in the AndroidManifest.xml)
Code Explanation
First we define some strings that represent the keys of our JSON data (TAG_DATA to TAG_CURRENCY), then we define our API end point MAP_API_URL.
In Android development ,it is recommended not to make http requests on the same thread that displays the user interface (i.e requests are best made asynchronous and not as a blocking operation). This is why I defined a background class called BackGroundTask.java (Code is at the end of this article), that handles all such request. Android provides a class called AsyncTask which enables asynchronous requests so my BackgroundTask class will just be extending this class and overriding some core functions. You can read more about this from the Android documentation.
Define the Spinner countryField as in the layout and finally we define the ArrayList that will hold the list of countries returned from the the API. Each entry in the ArrayList is of type Country (the definition of Country.java class is also given at the end of this article)
The onCreate is called when your activity is started and in it we set the content view and call our
What happens in the
1. Set the parameters to be sent to the API by defining a NameValuePair list.
2. Start the background task
Initiating our background class, we pass as parameters the API end point, the method to use for the request and the NVP parameters. 3. Get response from the background task
The try..catch block that follows is pretty straight forward. From the JSON object shown above, you will notice that the necessary data itself is in a JSON array, which is why to get the data, we use
Each item in the countries JSONArray is a JSONObject so to get the entries of each item in the countries Array, we use
where i is the current position of the iteration. And finally to get the value of each entry you use the
At the end of the for loop after getting the values of the entries in a country, you add the country to the countryList ArrayList defined in the beginning.
(The code defining the country class is given at the end of this topic.)
The last and final thing that needs to be done to complete our demo is to bind the country list to the spinner. This is done using an ArrayAdapter and because we have a custom type
And that will be it. For detailed explanations on Android Classes used in this tutorial, you can visit the Android Developers site.
Other Classes Necessary for this tutorial:
Ignore the closing tags at the end of the code snippets, the script formatting the code snippets just messes up.
I will use JSON data from the following RESTful API
http://www.cmcredit.com/apps/apis/map/
It is a country/region/city database I put together from various sources and you query by sending some NVP parameters. I will also explain how to do this in our android application. Just as a quick example calling the API with the NVP
{call: countrylist}
will do the get request: http://www.cmcredit.com/apps/apis/map/?call=countrylist
and return a country listing. To get regions in a country you could call the api with the NVPs {call: countryregions, country_id: 42}
. This API is used for demo purposes ONLY.
We will use data returned from http://www.cmcredit.com/apps/apis/map/?call=countrylist which is of the following format:
{ "success":true, "message":"", "data": [ {"country_id":"42","name":"cameroon","iso2":"CM","currency":"XAF"}, {"country_id":"43","name":"canada","iso2":"CA","currency":"CAD"}, {"country_id":"44","name":"cape verde","iso2":"CV","currency":"CVE"}, {"country_id":"45","name":"cayman islands","iso2":"KY","currency":"KYD"}, {"country_id":"46","name":"central african republic","iso2":"CF","currency":"XAF"}, {"country_id":"47","name":"chad","iso2":"TD","currency":"XAF"} ] }
Create the various Layouts
1. Activity layout: one TextView and one Spinner (res/layout/activity_spinnerdemo.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:paddingTop="30dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:paddingLeft="10dp" android:text="@string/list_country" > </TextView> <Spinner android:id="@+id/countryField" android:layout_width="match_parent" android:layout_height="wrap_content" android:prompt="@string/select_country" > </Spinner> </LinearLayout>
The TextView will simply display the text of the android:text attribute on the screen and the spinner will be populated by our Activity class.
2. The layout of each item in the spinner (res/layout/simple_spinner_item.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/item_value" android:layout_width="wrap_content" android:layout_height="wrap_content" > </TextView> <TextView android:id="@+id/item_id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#FFFFFF" > </TextView> </LinearLayout>
Define the Activity class
Secondly we define our activity class that will be launched when you start your application (if you set it as the main activity in the AndroidManifest.xml)
SpinnerDemo.java
package com.sewoyebah.examples; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Spinner; import android.widget.Toast; import android.annotation.SuppressLint; import android.app.Activity; @SuppressLint("DefaultLocale") public class SpinnerDemo extends Activity { // JSON Node names private static final String TAG_DATA = "data"; private static final String TAG_ID_COUNTRY = "country_id"; private static final String TAG_NAME = "name"; private static final String TAG_ISO = "iso2"; private static final String TAG_CURRENCY = "currency"; private static final String MAP_API_URL = "http://www.cmcredit.com/apps/apis/map"; private BackGroundTask bgt; // Fields Spinner countryField; ArrayList<Country> countryList = new ArrayList<Country>(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_spinnerdemo); buildCountryDropDown(); } public void buildCountryDropDown() { // Building post parameters, key and value pair List<NameValuePair> apiParams = new ArrayList<NameValuePair>(1); apiParams.add(new BasicNameValuePair("call", "countrylist")); bgt = new BackGroundTask(MAP_API_URL, "GET", apiParams); try { JSONObject countryJSON = bgt.execute().get(); // Getting Array of countries JSONArray countries = countryJSON.getJSONArray(TAG_DATA); // looping through All countries for (int i = 0; i < countries.length(); i++) { JSONObject c = countries.getJSONObject(i); // Storing each json item in variable String id = c.getString(TAG_ID_COUNTRY); String name = c.getString(TAG_NAME); String iso = c.getString(TAG_ISO); String currency = c.getString(TAG_CURRENCY); // add Country countryList.add(new Country(id, name.toUpperCase(), iso, currency)); } // bind adapter to spinner countryField = (Spinner) findViewById(R.id.countryField); CountryAdapter cAdapter = new CountryAdapter(this, android.R.layout.simple_spinner_item, countryList); countryField.setAdapter(cAdapter); countryField.setOnItemSelectedListener(new OnItemSelectedListener(){ @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Country selectedCountry = countryList.get(position); showToast(selectedCountry.getName() + " was selected!"); } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } catch (JSONException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } public void showToast(String msg) { Toast.makeText(this, "Toast: " + msg, Toast.LENGTH_LONG).show(); } }
Code Explanation
First we define some strings that represent the keys of our JSON data (TAG_DATA to TAG_CURRENCY), then we define our API end point MAP_API_URL.
In Android development ,it is recommended not to make http requests on the same thread that displays the user interface (i.e requests are best made asynchronous and not as a blocking operation). This is why I defined a background class called BackGroundTask.java (Code is at the end of this article), that handles all such request. Android provides a class called AsyncTask which enables asynchronous requests so my BackgroundTask class will just be extending this class and overriding some core functions. You can read more about this from the Android documentation.
Define the Spinner countryField as in the layout and finally we define the ArrayList
The onCreate is called when your activity is started and in it we set the content view and call our
buildCountryDropdown()
method.
What happens in the
buildCountryDropDown()
method?
1. Set the parameters to be sent to the API by defining a NameValuePair list.
ListapiParams = new ArrayList (1); apiParams.add(new BasicNameValuePair("call", "countrylist"));
2. Start the background task
bgt = new BackGroundTask(MAP_API_URL, "GET", apiParams);
Initiating our background class, we pass as parameters the API end point, the method to use for the request and the NVP parameters. 3. Get response from the background task
JSONObject countryJSON = bgt.execute().get();
The try..catch block that follows is pretty straight forward. From the JSON object shown above, you will notice that the necessary data itself is in a JSON array, which is why to get the data, we use
JSONArray countries = countryJSON.getJSONArray(TAG_DATA);
Each item in the countries JSONArray is a JSONObject so to get the entries of each item in the countries Array, we use
JSONObject c = countries.getJSONObject(i);
where i is the current position of the iteration. And finally to get the value of each entry you use the
getString()
method of the JSONObject
class. For example to get the id of a country, you use
String id = c.getString(TAG_ID_COUNTRY);
At the end of the for loop after getting the values of the entries in a country, you add the country to the countryList ArrayList
countryList.add(new Country(id, name, iso, currency));
(The code defining the country class is given at the end of this topic.)
The last and final thing that needs to be done to complete our demo is to bind the country list to the spinner. This is done using an ArrayAdapter and because we have a custom type
Country
we define our own custom adapter called CountryAdapter
, that extends the ArrayAdapter
class. If the list we wanted to bind to the spinner was a list of String
s, we need not define a custom adapter. we counld directly use the ArrayAdapter.
//get country spinner view from the layout countryField = (Spinner) findViewById(R.id.countryField); //define adapter to be used when displaying the country list CountryAdapter cAdapter = new CountryAdapter(this, android.R.layout.simple_spinner_item, countryList); //bind the adapter to the spinner countryField.setAdapter(cAdapter); //set a listener for selected items in the spinner countryField.setOnItemSelectedListener(new OnItemSelectedListener(){ @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { Country selectedCountry = countryList.get(position); showToast(selectedCountry.getName() + " was selected!"); } });
And that will be it. For detailed explanations on Android Classes used in this tutorial, you can visit the Android Developers site.
Other Classes Necessary for this tutorial:
Country.java
package com.sewoyebah.examples; public class Country { private String id; private String name; private String iso2; private String currency; public Country(String i, String n, String iso, String curr) { id = i; name = n; iso2 = iso; currency = curr; } public String getId() { return id; } public String getName() { return name; } public String getISO2() { return iso2; } public String getCurency() { return currency; } public String toString() { return name; } }
CountryAdapter.java
package com.sewoyebah.examples; import java.util.ArrayList; import android.app.Activity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; public class CountryAdapter extends ArrayAdapter<Country> { private Activity context; ArrayList<Country> data = null; public CountryAdapter(Activity context, int resource, ArrayList<Country> data) { super(context, resource, data); this.context = context; this.data = data; } @Override public View getView(int position, View convertView, ViewGroup parent) { return super.getView(position, convertView, parent); } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View row = convertView; if (row == null) { LayoutInflater inflater = context.getLayoutInflater(); row = inflater.inflate(R.layout.simple_spinner_item, parent, false); } Country item = data.get(position); if (item != null) { // Parse the data from each object and set it. TextView CountryId = (TextView) row.findViewById(R.id.item_id); TextView CountryName = (TextView) row.findViewById(R.id.item_value); if (CountryId != null) { CountryId.setText(item.getId()); } if (CountryName != null) { CountryName.setText(item.getName()); } } return row; } }
BackGroundTask.java
package com.sewoyebah.examples; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONException; import org.json.JSONObject; import android.os.AsyncTask; import android.util.Log; public class BackGroundTask extends AsyncTask<String, String, JSONObject> { List<NameValuePair> postparams = new ArrayList<NameValuePair>(); String URL = null; String method = null; static InputStream is = null; static JSONObject jObj = null; static String json = ""; public BackGroundTask(String url, String method, List<NameValuePair> params) { this.URL = url; this.postparams = params; this.method = method; } @Override protected JSONObject doInBackground(String... params) { // TODO Auto-generated method stub // Making HTTP request try { // Making HTTP request // check for request method if (method.equals("POST")) { // request method is POST DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(URL); httpPost.setEntity(new UrlEncodedFormEntity(postparams)); HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); } else if (method == "GET") { // request method is GET DefaultHttpClient httpClient = new DefaultHttpClient(); String paramString = URLEncodedUtils .format(postparams, "utf-8"); URL += "?" + paramString; HttpGet httpGet = new HttpGet(URL); HttpResponse httpResponse = httpClient.execute(httpGet); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); } // read input stream returned by request into a string using StringBuilder BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 8); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } is.close(); json = sb.toString(); // create a JSONObject from the json string jObj = new JSONObject(json); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { Log.e("JSON Parser", "Error parsing data " + e.toString()); } catch (Exception e) { Log.e("Buffer Error", "Error converting result " + e.toString()); } // return JSONObject (this is a class variable and null is returned if something went bad) return jObj; } }
Ignore the closing tags at the end of the code snippets, the script formatting the code snippets just messes up.
lundi 5 novembre 2012
The Password Manager - PassMan
This might not be new but anyway, I had a problem and I created this application to solve my problem. I decided to put it up hoping it will help some other people. First and foremost it is free meaning you use at your own cost.
Problem
I have more than 25 accounts over the internet and each has a unique log-in and password. On my PC (mac & co. users already out of the equation :P) all the passwords are saved and I need not remember the user names and passwords. However when not on my pc and need to access a service online, I am required to log-in and most often I forget which log-in goes to which service. This is the problem I faced.
Solution
My solution to this was to have just one log-in detail which gives me access to all other log-in details - and hence PassMan. With PassMan you are able to securely save all your passwords in your mobile and retrieve them at anytime and on the fly. All you need is an internet connection on your mobile and a 'super' user that connects to PassMan.
When PassMan is first installed on your mobile, you are required to first create an account which is unique for each user. Two users can't have same account name and an account can't be duplicated even if you change your mobile phone. In case you loose your mobile phone or change your mobile phone, all you need to do is install PassMan on the new mobile and use same log-in details of the previous install.
ENJOY!
Problem
I have more than 25 accounts over the internet and each has a unique log-in and password. On my PC (mac & co. users already out of the equation :P) all the passwords are saved and I need not remember the user names and passwords. However when not on my pc and need to access a service online, I am required to log-in and most often I forget which log-in goes to which service. This is the problem I faced.
Solution
My solution to this was to have just one log-in detail which gives me access to all other log-in details - and hence PassMan. With PassMan you are able to securely save all your passwords in your mobile and retrieve them at anytime and on the fly. All you need is an internet connection on your mobile and a 'super' user that connects to PassMan.
When PassMan is first installed on your mobile, you are required to first create an account which is unique for each user. Two users can't have same account name and an account can't be duplicated even if you change your mobile phone. In case you loose your mobile phone or change your mobile phone, all you need to do is install PassMan on the new mobile and use same log-in details of the previous install.
This is the first version of this application and thus negative feedback is welcome. The servers responsible for the PassMan web service might be moved when the userbase becomes large. Users will however be informed if there will be any 'temporal no-service'. PassMan is currently avaliable ONLY for android users and versions of other platforms will be released only on demand. You can drop a short message at cyril.tata@hotmail.com.
Below is a simulation to give you an insight on how passman works. Start by clicking on "Create Phone Account". If you like it and you are on the android platform, get in touch for the apk file <cyril.tata@hotmail.com>. Because it is free, I did not put it on the market.
ENJOY!
Inscription à :
Articles (Atom)