My previous tutorial Android Custom ListView covers customizing android list view with image and text. In this tutorial I am going to explain even more customized list view like Facebook, Google+ news feed where it contains multiple images and texts.
I used android volley network library to make http calls and download the images. As volley comes with powerful image caching mechanism, we don’t have to much worry about caching the requests and images.
Final Output
Following is the screenshot of final output of this tutorial.
Example feed Json
To demonstrate this tutorial I created an example json feed which contains an array of json feed object. Each object defines single feed row where it contains information like feed id, profile pic, profile name, timestamp, status message and feed image.
You can access the json from here.
{ "feed": [ { "id": 1, "name": "National Geographic Channel", "image": "https://api.androidhive.info/feed/img/cosmos.jpg", "status": "\"Science is a beautiful and emotional human endeavor,\" says Brannon Braga, executive producer and director. \"And Cosmos is all about making science an experience.\"", "profilePic": "https://api.androidhive.info/feed/img/nat.jpg", "timeStamp": "1403375851930", "url": null }, { "id": 2, "name": "TIME", "image": "https://api.androidhive.info/feed/img/time_best.jpg", "status": "30 years of Cirque du Soleil's best photos", "profilePic": "https://api.androidhive.info/feed/img/time.png", "timeStamp": "1403375851930", "url": "http://ti.me/1qW8MLB" } ] }
In real world scenario, this feed json should be generated dynamically by reading a database.
1. Planning the Layout
Before start writing the code, I would like to plan the layout first. If you observe the feed view, it has information like name,timestamp, profile pic, feed image and url. For this we need TextView, ImageView and a listview to display the feed. Using the LinearLayout’s orientation property I have alligned the elements vertically and horizontally.
2. Downloading Volley.jar
If you are new to android volley library, I suggest you go through my previous article Android Volley Tutorial to understand what volley library is actually for. (In simple words volley is a networking library used to make HTTP calls)
Download the volley.jar and keep it aside.
Now let’s start by creating a new project.
3. Creating new project
1. Create a new project in Eclipse from File ⇒ New ⇒ Android Application Project and fill all the required information.
2. Open res ⇒ values ⇒ dimens.xml and add following dimensions. If you don’t have dimens.xml, create a new file and add these values.
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> <dimen name="feed_item_margin">10dp</dimen> <dimen name="feed_item_padding_top_bottom">20dp</dimen> <dimen name="feed_item_padding_left_right">15dp</dimen> <dimen name="feed_item_profile_pic">50dp</dimen> <dimen name="feed_item_profile_info_padd">10dp</dimen> <dimen name="feed_item_profile_name">15dp</dimen> <dimen name="feed_item_timestamp">13dp</dimen> <dimen name="feed_item_status_pad_left_right">15dp</dimen> <dimen name="feed_item_status_pad_top">13dp</dimen> <dimen name="feed_item_corner_radius">3dp</dimen> <dimen name="feed_item_border_width">1dp</dimen> </resources>
3. Also create another xml file named colors.xml under res ⇒ values and add following colors.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="white">#ffffff</color> <color name="feed_bg">#d3d6db</color> <color name="feed_item_bg">#ffffff</color> <color name="feed_item_border">#c2c3c8</color> <color name="link">#0a80d1</color> <color name="timestamp">#a0a3a7</color> </resources>
4. Under res ⇒ drawable, create a new file called bg_parent_rounded_corner.xml and paste the below code. This xml will give a rounded corner background to feed item.
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <!-- view background color --> <solid android:color="@color/feed_item_bg" > </solid> <!-- view border color and width --> <stroke android:width="@dimen/feed_item_border_width" android:color="@color/feed_item_border" > </stroke> <!-- Here is the corner radius --> <corners android:radius="@dimen/feed_item_corner_radius" > </corners> </shape>
5. To keep the project well organized, I am creating required packages first. Create 4 packages named app, adapter, data and volley. To create new package, right click on src ⇒ New ⇒ Package and give package name. Example: info.androidhive.listview.app.
Following is the project structure I am trying to achieve.
6. Now paste the volley.jar in project libs folder.
7. Create a class named LruBitmapCache.java under volley package and add the following code. This class takes care of caching network images on disk.
package info.androidhive.listviewfeed.volley; import com.android.volley.toolbox.ImageLoader.ImageCache; import android.graphics.Bitmap; import android.support.v4.util.LruCache; public class LruBitmapCache extends LruCache<String, Bitmap> implements ImageCache { public static int getDefaultLruCacheSize() { final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = maxMemory / 8; return cacheSize; } public LruBitmapCache() { this(getDefaultLruCacheSize()); } public LruBitmapCache(int sizeInKiloBytes) { super(sizeInKiloBytes); } @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight() / 1024; } @Override public Bitmap getBitmap(String url) { return get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { put(url, bitmap); } }
8. Under app package create class named AppController.java and paste the following content. This is a singleton class which initializes global instances of required classes. All the objects related to volley are initialized here.
package info.androidhive.listviewfeed.app; import info.androidhive.listviewfeed.volley.LruBitmapCache; import android.app.Application; import android.text.TextUtils; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.toolbox.ImageLoader; import com.android.volley.toolbox.Volley; public class AppController extends Application { public static final String TAG = AppController.class.getSimpleName(); private RequestQueue mRequestQueue; private ImageLoader mImageLoader; LruBitmapCache mLruBitmapCache; private static AppController mInstance; @Override public void onCreate() { super.onCreate(); mInstance = this; } public static synchronized AppController getInstance() { return mInstance; } public RequestQueue getRequestQueue() { if (mRequestQueue == null) { mRequestQueue = Volley.newRequestQueue(getApplicationContext()); } return mRequestQueue; } public ImageLoader getImageLoader() { getRequestQueue(); if (mImageLoader == null) { getLruBitmapCache(); mImageLoader = new ImageLoader(this.mRequestQueue, mLruBitmapCache); } return this.mImageLoader; } public LruBitmapCache getLruBitmapCache() { if (mLruBitmapCache == null) mLruBitmapCache = new LruBitmapCache(); return this.mLruBitmapCache; } public <T> void addToRequestQueue(Request<T> req, String tag) { req.setTag(TextUtils.isEmpty(tag) ? TAG : tag); getRequestQueue().add(req); } public <T> void addToRequestQueue(Request<T> req) { req.setTag(TAG); getRequestQueue().add(req); } public void cancelPendingRequests(Object tag) { if (mRequestQueue != null) { mRequestQueue.cancelAll(tag); } } }
9. Now open your AndroidManifest.xml file and add Application.java class in <application> tag. Also we need to add INTERNET permission as this app makes network calls.
<application android:name="info.androidhive.listviewfeed.app.AppController"> ....</application>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="info.androidhive.listviewfeed" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:name="info.androidhive.listviewfeed.app.AppController" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="info.androidhive.listviewfeed.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
10. The main challenge in this project is adjusting the aspect ratio of feed image once it is downloaded. Unfortunately volley doesn’t provide any callback method once the NetworkImageView is loaded. So I created a custom ImageView class with callback methods. This class automatically adjusts the image height to prevent image aspect ratio distortion.
Under your project main package create a class named FeedImageView.java and paste the below code. I took the code from this stackoverflow answer and made few tweaks.
You can use this FeedImageView in your xml layout like this
<info.androidhive.listviewfeed.FeedImageView android:id="@+id/feedImage1" android:layout_width="match_parent" android:layout_height="wrap_content"/>
package info.androidhive.listviewfeed; import android.content.Context; import android.text.TextUtils; import android.util.AttributeSet; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import com.android.volley.VolleyError; import com.android.volley.toolbox.ImageLoader; import com.android.volley.toolbox.ImageLoader.ImageContainer; import com.android.volley.toolbox.ImageLoader.ImageListener; public class FeedImageView extends ImageView { public interface ResponseObserver { public void onError(); public void onSuccess(); } private ResponseObserver mObserver; public void setResponseObserver(ResponseObserver observer) { mObserver = observer; } /** * The URL of the network image to load */ private String mUrl; /** * Resource ID of the image to be used as a placeholder until the network * image is loaded. */ private int mDefaultImageId; /** * Resource ID of the image to be used if the network response fails. */ private int mErrorImageId; /** * Local copy of the ImageLoader. */ private ImageLoader mImageLoader; /** * Current ImageContainer. (either in-flight or finished) */ private ImageContainer mImageContainer; public FeedImageView(Context context) { this(context, null); } public FeedImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FeedImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * Sets URL of the image that should be loaded into this view. Note that * calling this will immediately either set the cached image (if available) * or the default image specified by * {@link VolleyImageView#setDefaultImageResId(int)} on the view. * * NOTE: If applicable, {@link VolleyImageView#setDefaultImageResId(int)} * and {@link VolleyImageView#setErrorImageResId(int)} should be called * prior to calling this function. * * @param url * The URL that should be loaded into this ImageView. * @param imageLoader * ImageLoader that will be used to make the request. */ public void setImageUrl(String url, ImageLoader imageLoader) { mUrl = url; mImageLoader = imageLoader; // The URL has potentially changed. See if we need to load it. loadImageIfNecessary(false); } /** * Sets the default image resource ID to be used for this view until the * attempt to load it completes. */ public void setDefaultImageResId(int defaultImage) { mDefaultImageId = defaultImage; } /** * Sets the error image resource ID to be used for this view in the event * that the image requested fails to load. */ public void setErrorImageResId(int errorImage) { mErrorImageId = errorImage; } /** * Loads the image for the view if it isn't already loaded. * * @param isInLayoutPass * True if this was invoked from a layout pass, false otherwise. */ private void loadImageIfNecessary(final boolean isInLayoutPass) { final int width = getWidth(); int height = getHeight(); boolean isFullyWrapContent = getLayoutParams() != null && getLayoutParams().height == LayoutParams.WRAP_CONTENT && getLayoutParams().width == LayoutParams.WRAP_CONTENT; // if the view's bounds aren't known yet, and this is not a // wrap-content/wrap-content // view, hold off on loading the image. if (width == 0 && height == 0 && !isFullyWrapContent) { return; } // if the URL to be loaded in this view is empty, cancel any old // requests and clear the // currently loaded image. if (TextUtils.isEmpty(mUrl)) { if (mImageContainer != null) { mImageContainer.cancelRequest(); mImageContainer = null; } setDefaultImageOrNull(); return; } // if there was an old request in this view, check if it needs to be // canceled. if (mImageContainer != null && mImageContainer.getRequestUrl() != null) { if (mImageContainer.getRequestUrl().equals(mUrl)) { // if the request is from the same URL, return. return; } else { // if there is a pre-existing request, cancel it if it's // fetching a different URL. mImageContainer.cancelRequest(); setDefaultImageOrNull(); } } // The pre-existing content of this view didn't match the current URL. // Load the new image // from the network. ImageContainer newContainer = mImageLoader.get(mUrl, new ImageListener() { @Override public void onErrorResponse(VolleyError error) { if (mErrorImageId != 0) { setImageResource(mErrorImageId); } if (mObserver != null) { mObserver.onError(); } } @Override public void onResponse(final ImageContainer response, boolean isImmediate) { // If this was an immediate response that was delivered // inside of a layout // pass do not set the image immediately as it will // trigger a requestLayout // inside of a layout. Instead, defer setting the image // by posting back to // the main thread. if (isImmediate && isInLayoutPass) { post(new Runnable() { @Override public void run() { onResponse(response, false); } }); return; } int bWidth = 0, bHeight = 0; if (response.getBitmap() != null) { setImageBitmap(response.getBitmap()); bWidth = response.getBitmap().getWidth(); bHeight = response.getBitmap().getHeight(); adjustImageAspect(bWidth, bHeight); } else if (mDefaultImageId != 0) { setImageResource(mDefaultImageId); } if (mObserver != null) { mObserver.onSuccess(); } } }); // update the ImageContainer to be the new bitmap container. mImageContainer = newContainer; } private void setDefaultImageOrNull() { if (mDefaultImageId != 0) { setImageResource(mDefaultImageId); } else { setImageBitmap(null); } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); loadImageIfNecessary(true); } @Override protected void onDetachedFromWindow() { if (mImageContainer != null) { // If the view was bound to an image request, cancel it and clear // out the image from the view. mImageContainer.cancelRequest(); setImageBitmap(null); // also clear out the container so we can reload the image if // necessary. mImageContainer = null; } super.onDetachedFromWindow(); } @Override protected void drawableStateChanged() { super.drawableStateChanged(); invalidate(); } /* * Adjusting imageview height * */ private void adjustImageAspect(int bWidth, int bHeight) { LinearLayout.LayoutParams params = (LayoutParams) getLayoutParams(); if (bWidth == 0 || bHeight == 0) return; int swidth = getWidth(); int new_height = 0; new_height = swidth * bHeight / bWidth; params.width = swidth; params.height = new_height; setLayoutParams(params); } }
11. Open your layout for main activity (activity_main.xml) and add a list view element for the feed list.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="@null" /> </LinearLayout>
12. Create another layout file named feed_item.xml under res ⇒ layout folder. This layout file represents each individual feed item row in the list view.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/feed_bg" android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginLeft="@dimen/feed_item_margin" android:layout_marginRight="@dimen/feed_item_margin" android:layout_marginTop="@dimen/feed_item_margin" android:background="@drawable/bg_parent_rounded_corner" android:orientation="vertical" android:paddingBottom="@dimen/feed_item_padding_top_bottom" android:paddingTop="@dimen/feed_item_padding_top_bottom" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="@dimen/feed_item_padding_left_right" android:paddingRight="@dimen/feed_item_padding_left_right" > <com.android.volley.toolbox.NetworkImageView android:id="@+id/profilePic" android:layout_width="@dimen/feed_item_profile_pic" android:layout_height="@dimen/feed_item_profile_pic" android:scaleType="fitCenter" > </com.android.volley.toolbox.NetworkImageView> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingLeft="@dimen/feed_item_profile_info_padd" > <TextView android:id="@+id/name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="@dimen/feed_item_profile_name" android:textStyle="bold" /> <TextView android:id="@+id/timestamp" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="@color/timestamp" android:textSize="@dimen/feed_item_timestamp" /> </LinearLayout> </LinearLayout> <TextView android:id="@+id/txtStatusMsg" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="5dp" android:paddingLeft="@dimen/feed_item_status_pad_left_right" android:paddingRight="@dimen/feed_item_status_pad_left_right" android:paddingTop="@dimen/feed_item_status_pad_top" /> <TextView android:id="@+id/txtUrl" android:layout_width="fill_parent" android:layout_height="wrap_content" android:linksClickable="true" android:paddingBottom="10dp" android:paddingLeft="@dimen/feed_item_status_pad_left_right" android:paddingRight="@dimen/feed_item_status_pad_left_right" android:textColorLink="@color/link" /> <info.androidhive.listviewfeed.FeedImageView android:id="@+id/feedImage1" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/white" android:scaleType="fitXY" android:visibility="visible" /> </LinearLayout> </LinearLayout>
13. Under data package, create a class named FeedItem.java. This is a POJO class used to create objects for each feed item while parsing the json. The feed item object contains information like profile pic, name, timestamp, status message, url and feed image.
package info.androidhive.listviewfeed.data; public class FeedItem { private int id; private String name, status, image, profilePic, timeStamp, url; public FeedItem() { } public FeedItem(int id, String name, String image, String status, String profilePic, String timeStamp, String url) { super(); this.id = id; this.name = name; this.image = image; this.status = status; this.profilePic = profilePic; this.timeStamp = timeStamp; this.url = url; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImge() { return image; } public void setImge(String image) { this.image = image; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getProfilePic() { return profilePic; } public void setProfilePic(String profilePic) { this.profilePic = profilePic; } public String getTimeStamp() { return timeStamp; } public void setTimeStamp(String timeStamp) { this.timeStamp = timeStamp; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }
14. Now under adapter package create a class named FeedListAdapter.java. This is a custom adapter class for feed list view. This adapter class takes care following things.
> Displaying feed data like name, timestamp, profile pic, status message and feed image.
> Converts timestamp into x minutes/hours/days ago format
> Makes URL clickable by using url.setMovementMethod(LinkMovementMethod.getInstance())
package info.androidhive.listviewfeed.adapter; import info.androidhive.listviewfeed.FeedImageView; import info.androidhive.listviewfeed.R; import info.androidhive.listviewfeed.app.AppController; import info.androidhive.listviewfeed.data.FeedItem; import java.util.List; import android.app.Activity; import android.content.Context; import android.text.Html; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.android.volley.toolbox.ImageLoader; import com.android.volley.toolbox.NetworkImageView; public class FeedListAdapter extends BaseAdapter { private Activity activity; private LayoutInflater inflater; private List<FeedItem> feedItems; ImageLoader imageLoader = AppController.getInstance().getImageLoader(); public FeedListAdapter(Activity activity, List<FeedItem> feedItems) { this.activity = activity; this.feedItems = feedItems; } @Override public int getCount() { return feedItems.size(); } @Override public Object getItem(int location) { return feedItems.get(location); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (inflater == null) inflater = (LayoutInflater) activity .getSystemService(Context.LAYOUT_INFLATER_SERVICE); if (convertView == null) convertView = inflater.inflate(R.layout.feed_item, null); if (imageLoader == null) imageLoader = AppController.getInstance().getImageLoader(); TextView name = (TextView) convertView.findViewById(R.id.name); TextView timestamp = (TextView) convertView .findViewById(R.id.timestamp); TextView statusMsg = (TextView) convertView .findViewById(R.id.txtStatusMsg); TextView url = (TextView) convertView.findViewById(R.id.txtUrl); NetworkImageView profilePic = (NetworkImageView) convertView .findViewById(R.id.profilePic); FeedImageView feedImageView = (FeedImageView) convertView .findViewById(R.id.feedImage1); FeedItem item = feedItems.get(position); name.setText(item.getName()); // Converting timestamp into x ago format CharSequence timeAgo = DateUtils.getRelativeTimeSpanString( Long.parseLong(item.getTimeStamp()), System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS); timestamp.setText(timeAgo); // Chcek for empty status message if (!TextUtils.isEmpty(item.getStatus())) { statusMsg.setText(item.getStatus()); statusMsg.setVisibility(View.VISIBLE); } else { // status is empty, remove from view statusMsg.setVisibility(View.GONE); } // Checking for null feed url if (item.getUrl() != null) { url.setText(Html.fromHtml("<a href=\"" + item.getUrl() + "\">" + item.getUrl() + "</a> ")); // Making url clickable url.setMovementMethod(LinkMovementMethod.getInstance()); url.setVisibility(View.VISIBLE); } else { // url is null, remove from the view url.setVisibility(View.GONE); } // user profile pic profilePic.setImageUrl(item.getProfilePic(), imageLoader); // Feed image if (item.getImge() != null) { feedImageView.setImageUrl(item.getImge(), imageLoader); feedImageView.setVisibility(View.VISIBLE); feedImageView .setResponseObserver(new FeedImageView.ResponseObserver() { @Override public void onError() { } @Override public void onSuccess() { } }); } else { feedImageView.setVisibility(View.GONE); } return convertView; } }
15. Now we have all the required classes in place. Open your main activity class MainActivity.java and add the following code. Here using volley JsonObjectRequest I fetched the json, parsed it(created array of feed item objects) and passed the data to list view adapter.
package info.androidhive.listviewfeed; import info.androidhive.listviewfeed.adapter.FeedListAdapter; import info.androidhive.listviewfeed.app.AppController; import info.androidhive.listviewfeed.data.FeedItem; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.Menu; import android.widget.ListView; import com.android.volley.Cache; import com.android.volley.Cache.Entry; import com.android.volley.Request.Method; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.VolleyLog; import com.android.volley.toolbox.JsonObjectRequest; public class MainActivity extends Activity { private static final String TAG = MainActivity.class.getSimpleName(); private ListView listView; private FeedListAdapter listAdapter; private List<FeedItem> feedItems; private String URL_FEED = "https://api.androidhive.info/feed/feed.json"; @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.list); feedItems = new ArrayList<FeedItem>(); listAdapter = new FeedListAdapter(this, feedItems); listView.setAdapter(listAdapter); // These two lines not needed, // just to get the look of facebook (changing background color & hiding the icon) getActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#3b5998"))); getActionBar().setIcon( new ColorDrawable(getResources().getColor(android.R.color.transparent))); // We first check for cached request Cache cache = AppController.getInstance().getRequestQueue().getCache(); Entry entry = cache.get(URL_FEED); if (entry != null) { // fetch the data from cache try { String data = new String(entry.data, "UTF-8"); try { parseJsonFeed(new JSONObject(data)); } catch (JSONException e) { e.printStackTrace(); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } else { // making fresh volley request and getting json JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET, URL_FEED, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { VolleyLog.d(TAG, "Response: " + response.toString()); if (response != null) { parseJsonFeed(response); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { VolleyLog.d(TAG, "Error: " + error.getMessage()); } }); // Adding request to volley request queue AppController.getInstance().addToRequestQueue(jsonReq); } } /** * Parsing json reponse and passing the data to feed view list adapter * */ private void parseJsonFeed(JSONObject response) { try { JSONArray feedArray = response.getJSONArray("feed"); for (int i = 0; i < feedArray.length(); i++) { JSONObject feedObj = (JSONObject) feedArray.get(i); FeedItem item = new FeedItem(); item.setId(feedObj.getInt("id")); item.setName(feedObj.getString("name")); // Image might be null sometimes String image = feedObj.isNull("image") ? null : feedObj .getString("image"); item.setImge(image); item.setStatus(feedObj.getString("status")); item.setProfilePic(feedObj.getString("profilePic")); item.setTimeStamp(feedObj.getString("timeStamp")); // url might be null sometimes String feedUrl = feedObj.isNull("url") ? null : feedObj .getString("url"); item.setUrl(feedUrl); feedItems.add(item); } // notify data changes to list adapater listAdapter.notifyDataSetChanged(); } catch (JSONException e) { e.printStackTrace(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } }
Now run the project and test it once. Make sure that your emulator/device is having internet connect before you test.
Hi there! I am Founder at androidhive and programming enthusiast. My skills includes Android, iOS, PHP, Ruby on Rails and lot more. If you have any idea that you would want me to develop? Let’s talk: ravi@androidhive.info
Awesome
Dude, congratulations, this site has helped me a lot
Thanks man. This site helped me a lot. It is like everything I was looking for exists here.
You are welcome 🙂
This is damn awesome article Ravi! I wanted ask you one thing, is it possible to build such app which can fetch articles from some RSS feed and render same on screen?
Yeah, we can do. There is already a tutorial here, we need to do few tweaks like adding volley support. But I doubt about the feed banner image as rss feed doesn’t contains one.
http://www.androidhive.info/2012/05/android-rss-reader-application-using-sqlite-part-1/
I guess feed can contain images also, check this http://feeds.feedburner.com/techlitic 🙂
I think those images are from article content, there is no specific xml tag for it. May be we need to parse the html and get the images.
Ohh okay! Thanks for your prompt reply Ravi 🙂
You are welcome Suumit 🙂
I like your emulator. how to change it?
It’s not emulator, VLC player. Below app helped me to record my mobile screen and I played the video on PC.
https://play.google.com/store/apps/details?id=uk.org.invisibility.recordablefree
very good! i like your emulator. how to change it?
It’s not emulator, VLC player. Below app helped me to record my mobile screen and played the video on PC.
https://play.google.com/store/apps/details?id=uk.org.invisibility.recordablefree
hii
i want to combine slider menu and swipeable tab
i.e.. i want item A of slider menu has contain 2 tabs i.e. tab1 tab2…plzz help me..
i m using your tutorial for both of them..
Try this
https://github.com/Balaji-K13/Navigation-drawer-page-sliding-tab-strip
Wow awesome, I really liked it…!!
How to show image in popup like facebook did ?
Create another activity with a NetworkImageView in it’s layout file.
Implement onClick listener on image on list view and pass the image url to full screen image view activity.
ya i know that but i want to achieve that kind of effect on click image. i hope you have noticed that effect.
Then you can have the networkimageview in the same layout below listview and do toggle hiding b/w listview and imageview. So that you can add any kind of effects while showing fullscreen image.
You can achieve it using Rebound library https://github.com/facebook/rebound
thank you man , but i think loopj.com/android-async-http/ work better thank volley ?
I haven’t tested, but I recommend volley as it is officially supported by android.com
https://developer.android.com/training/volley/index.html
Great guide! Thanks a lot. Btw what about robospice instead of volley?
I am hearing robospice for the the firsttime Richard
How can I “take” a real json file from facebook.com??? (real time facebook list)
That would be cool
hi Ravi, first of all I ‘ll like to thanks U for all the help you provide.I’ m a new android developper and your site is very helpfull.I would like to use the custom imageview you gave in a ViewPager, it works fine but the image isn’t displayed at the center how can I change it( the position of the image),Previously i did it in the XML layout.
can you paste your layout code here?
thank’s
what is com.brasserie.cap.adapters.fullscreenimageview?
it’s the same java class as the one you gave in your tutorial “FeedImageView” I only changed the method “adjustImageAspect” by adding
RelativeLayout.LayoutParams params = (android.widget.RelativeLayout.LayoutParams) getLayoutParams();
Try using LinearLayout.LayoutParams and use
params.gravity=Gravity.CENTER;
Also to display a fullscreen image we don’t have to create a custom imageview class. Use NetworkImageView directly in xml layout.
I’ve try it but i got an Exception
when i tried LinearLayout.params
java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.LinearLayout$LayoutParams, I think it is because the layout has a Relativelayout
yep fine,I did it as you said, change to linearlayout and I also modified my PageAdapter by overriding the “isViewFromObject” returning a linearlayout too.
thks a lot once more
I am glad you solved it 🙂
Sorry Ravi from disturbing once more 🙂 But I’m facing another matter once more 🙁
I would like to display a GIF image while downloading the image I put the image in the drawable folder, and use the “setDefaultImageResId” in my custom adapter, but the gif work as expected ,It behave like a normal Bitmap. I ‘ll like it to be as in your previous tuto on Volley. thks
In my volley tutorial, I used ProgressDialog element not GIF image. If you want to use gif image with animation use this library.
https://github.com/Hipmob/gifanimateddrawable
thks man I will try it 🙂
hi ravi, I’ve been around the Web and I found that sometimes displaying a GIF can cause an OOM exception, so i decided to use a progress bar( PB) while the image will be loading.I just added the PB in my layout then in the BaseAdapter class. I can show it but, how can I hide it once the download is done?
Which element you are using to display the image?
sorry I didn’t understand what U mean
If this could help I would like to display an Image while downloading, so I firstly planned to use a gif but I’m afraied of an OOM excep.so I would like to display a progress bar instead of that gif
Ok
I mean ImageView or NetworkImageView ?
I used the custom one U gave in this tutorial.
Then it has callback methods onSuccess() and onError(). You can hide your PD in these methods.
.setResponseObserver(new FeedImageView.ResponseObserver() {
@Override
public void onError() {
// hide the PD here
}
@Override
public void onSuccess() {
// hide the PD here
}
})
thks man:) but I’ve tried your suggestion, in fact the real matter is how to show the PD, I would like to display it under the every single DefaultImage of my Custom Gridview , so the advice you gave me will hide it, but how to display the PD
I have been all the day looking how I can resolve that, but I didn’t found, If i didn’t hide the PD in the observer, it still display, but if I hide it, it doesn’t even display during the downloading with volley, it is normal it think.The only way to resolve it, it think I’m not sure, it will be if i could check if the default image is remplace by the one download, do U have an idea on how check it please.
thank’s
in my MainActivity.java, automatically MainActivity is extending ActionBarActivity and also appcompatv7 named folder is generating when I am creating the project which is not there in your code…why ?
Its because you have updated your android SDK it to latest build tools version. You can revert your MainActivity to normal (like extending from activity), it will work. You can remove appcompatv7 too from build libraries.
I still need to study what ActionBarActivity is for, that’s why I posted this tutorial in older fashion.
can I send my project to you on facebook in .zip format so that you can make the correction ? I tried many times but I think there is some very small mistake.
Done successfully…found the problem !! Thanks ! 🙂
Okay
ActionBarActivity is a class in AppCompat Library(from Android team) which is an extension of the support library designed to facilitate the use of the action bar design pattern across all versions of Android with a single API.
Similar to ActionBarSherlock Library.
Thanks Prathap for the info 🙂
Hello ravi sir ! this is a very useful tutorial ! thankyou soo much !
can you plz tell is there any short way to run this in a fragment and not in an activity ?
waiting for your reply !
hi! your fragment is for the listView? normally there is no great difference
please elaborate the method to show this Custom ListView Feed into a fragment 🙂
regards
first of all you will need create another activity, which will contain your fragment,
and the main activity (the one which ravi gave in this tutorial) you change
it to fragment that means it will extend Fragment or Listfragment as you like
You will have to do some changes in your code because the fragment do not react the same as activity
I hope U get what I mean(french speaker and android’s newby so 🙂 )
Hi Ravi,
Is this feed dynamic, that is, uploading the latest post from every feed?
As far as I can see it is set to certain links. Is there a way to set it to websites’ RSS feed?
No its not dynamic. You can write some logic to parse the RSS feed and display the feed in this fashion or you can do the same on server side and give the json to mobile.
may be this helps you
http://www.androidhive.info/2012/05/android-rss-reader-application-using-sqlite-part-1/
Hi Ravi,
Yet another amazing post for all the android enthusiasts. Double thumbs up to your post.
One small thing, i think layout height should be fill parent in activity_main.xml otherwise in case of single item in the list view, image doesn’t show up properly.
Hmm, I didn’t think about it. Thanks for the suggestion.
Thanks Ravi Tamada …………. i have a simple query …. can i upload file using “volley” .
Yes you can. Write a custom request class like below, but sending larger sized image is not possible.
http://stackoverflow.com/questions/16797468/how-to-send-a-multipart-form-data-post-in-android-with-volley
http://stackoverflow.com/questions/19980832/how-to-upload-a-bitmap-image-to-server-using-android-volley-library
Thanks for your quick reply……… Ravi which is the best way to upload large size files to server .
Actually when file is larger (lets say 30MB), we can’t upload the file directly as it can’t fit into memory. So we need to do a streaming upload where on the server you should have a mechanism to accepts chunks of file and do the appending process to create a complete file.
what if file size not more than 5mb
what if file size not more than 5mb, which is the best way to upload files to server
Use volley or apache http clients
Thanks Ravi
what this format ? “timeStamp”: “1403375851930”,
how i insert now ?
14 year ?
pls help for insert this true 🙂
It is linux time stamp. You can generate it easily in java.
thx man
also feed.json not raed from my host i fix it now with “?” 🙂
url…”………com/file/feed.json?”
OK
Really it is great site. I am learning android. It will be great if you can write new article to demonstrate RSS using volley capabilities.
Thanks in advance
Hi Faiz, I already have an article about RSS reader. May be you can try integrating volley in the app.
http://www.androidhive.info/2012/05/android-rss-reader-application-using-sqlite-part-1/
I will try,
Thanks a lot Ravi
Ravi thanks for the post, how can i use this volley library to retrieve articles from any website and this information should be updated as the website gets updated
You can try integrating volley in this rss app
http://www.androidhive.info/2012/05/android-rss-reader-application-using-sqlite-part-1/
Thanks for the reply but some sites do not have rss url, i was thinking, can this library work like jsoup that just scans the page source code and retrieves articles?
Yes that would be another solution but I am not sure how you will manage to write a parser for multiple sites as not all of them follows the same html structure.
thank you man, i’m making an university project and it help me a lot.
you are welcome 🙂
Ravi i want to ask a question which is not relevant ………any idea how we can develop app like “WhatsApp”……… thanks
I can’t say it in one sentence. Lot of things involves like REST API, server side database, GCM.
Ravi i already worked with REST API, server side database(MySQL , MSSQL), GCM
but as per my experience ….i think …we can’t develop IM app with these as fast as “whatsApp” or “viber”
No, we can develop.I developed a prototype a long time back, but couldn’t post on blog as it is somewhat lengthy article.
Any way we can see the code?
Sorry, I don’t have it right now.
i am learning lot of things from your bog …… have you any platform where we can put our queries .
Thanks
please help me, i use stringrequest of volley library with VietNam language from web, after response my result error font. Any solution?
hi ravi
just a question
i want to make an rss app to save sqlite db with this method and i only have a question
how does the app knows if the json feed is updated?
FYI the app should update automatic when user opens it
i figured that i can compare the id of last data i added to db with the first id of what is being parsed from json
is it ok or there is a better way other than that?
i have a question, how can use this with fragments?, i mean that a fragment content a listview
Its almost the same, Put the contents of the onCreate() in MainActivity to onActivity Created() of a fragment and then place the fragment on top of an Activity
Thanks Bala 🙂
hello Ravi, You have been doing a great work here. Most of what I can do on android was from android hive. But Please i want you to make a tutorial on User profiles. where a user logs in and uploads his/her picture, post articles and also comment on another user’s article. hope am not asking too much…… am an oliver twist.
Hi akin,
You requirement is not simple. It needs lot of things to be integrated in one project. Following will help you
http://www.androidhive.info/2012/05/how-to-connect-android-with-php-mysql/ (server client connectivity)
http://www.androidhive.info/2014/05/android-working-with-volley-library-1/ (for json parsing)
Wowww!!! What a blog.
Awesome… Everything is working fine
Thanks
Thanks for the appreciation.
thank you sir , its working like a charm.
i am able to upload my file using filezila And CAN parse json also from my json url.
sir you are great , first nd last resort for many android app developer.
ravi’s magic
🙂
ravi sir please help me out
i don’t know how to parse my own json file in my app
i purchased domain name and hosting also
but i don’t know how to upload json file and you have api.androidhive…….
this url , i don’t how to get api.mywebsite…..
please help me out .
Which hosting you bought?
sir , i have bought it from godaddy , i have cpanel also .
sir i have of godaddy , with that i have cpanel also.
i have of godaddy , with which i got cpanel also.
i have hosting godaddy and i have cpanel also
Then to upload a file you need to follow these steps.
1. Create an FTP user in cpanel
2. Download filezilla software to connect to ftp
3. After connecting through filezilla upload your json file www folder (it might changes depending on your server)
4. Access the file via url in browser
If you want to access like me i.e api.yourdomain, you need to create a subdomain in godday’s admin panel. Create a new cRecord.
sir you are great , i am gonna try this .
thanks a lot.
Hello!
This really is a great article. I would like to download the source but have no afford in registering with android hive. Tried 4 times by now but do not get any email. Maybe a permanent problem?
You just need to type your email when downloading and click Download Code again!
Yeah, I have noticed it. Please check your SPAM folder. It should be there.
Ravi, How can I put the json request inside my model class? Hoping for your response
What do you mean by keeping json request in model class. Could you elaborate?
Hi Ravi, could you make an tutorial to how to create a messenger program like viber, line , what app or…. ? your works are so nice, thanks.
Yeah, I am preparing it. But in order to post that I have to cover lot of other topics first.
great ………… we are waiting Ravi
eagerly waiting
how do you produce that timestamp?
Thanx for this tutorial. I want to refresh or update feed items of the list view. Refresh button click. i used //Calendar calendar = Calendar.getInstance();
//long serverDate = AppController.getInstance().getRequestQueue().getCache().get(URL_FEED).serverDate;
//AppController.getInstance().getRequestQueue().getCache().invalidate(URL_FEED, true);
//AppController.getInstance().getRequestQueue().getCache().remove(URL_FEED);
Nothing works. Works only when go to app setting and clear cache. Please help me
Simple fix is to replace
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(URL_FEED);
if (entry != null) {
// fetch the data from cache
try {
String data = new String(entry.data, “UTF-8”);
try {
parseJsonFeed(new JSONObject(data));
} catch (JSONException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
// making fresh volley request and getting json
JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET,
URL_FEED, null, new Response.Listener() {
@Override
public void onResponse(JSONObject response) {
VolleyLog.d(TAG, “Response: ” + response.toString());
if (response != null) {
parseJsonFeed(response);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, “Error: ” + error.getMessage());
}
});
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
}
}
with
JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET,
URL_FEED, null, new Response.Listener() {
@Override
public void onResponse(JSONObject response) {
VolleyLog.d(TAG, “Response: ” + response.toString());
if (response != null) {
parseJsonFeed(response);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, “Error: ” + error.getMessage());
}
});
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
}
this will however remove the benefits of having cache.
To effectively use cache you need to implement
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
and call isNetworkAvailable() in onCreate such that
if(isNetworkAvailable()){
//the Call for server comes here
}
else{
//Call the cache here
}
I hope you can figure it out. If not, I’ll try to explain further
thanks. But how refresh dynamically like facebook. and how check feed data is valid or not. i tried changing data from jason doesnt change quickly into app feed. Need dynamic list like fb
I’m sure you’ll need to use GCM fot that.However i’m not very well versed with GCM yet and you’ll need to figure out the code yourself.
http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
Hi Ravi,
This is really good article and I want to use in my porject and for that I try to modify it,
I have tried to change Feedimage to view pager with dynamic height like facebook but i stuck and its not working, can you help me to solve out this.
Thanks
hi Ravi, i just want to display list of imageview and if i click one the selected imageview will zoom.
how can i do that?
thanks 🙂
How do you force it to refresh the feed each time on load not load from cache.
Ravi i downloaded the source code and tried running the apk file in the bin folder…but it is not working
Hi Ravi I really appreciate how you help all of us with these tutorials. I’m a young coder (16) and want to know how i can refresh this feed, or better still, how can i make it auto refresh itself like facebook does?
Hi Emile,
May be you need to make a call to server on onResume() method to get latest feed. You need to have a server side mechanism to change the expiry headers, otherwise volley won’t fetch updated json from the url.
Ok thanks!
how can i do it ?
Hey, i created Android Sliding Menu (it is done by androidhive also, http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/)
this thing is that each item in this Sliding Menu calls a fragment, i want to make one of the fragments calls this listview feed.
Can i have a clear code of how to convert this to fragment, not fragment activity.
Thanks in advance 😀
I trying do this combination, and also get error, maybe @Ravi Tamada:disqus can give a hint to us 🙂
I am using it inside a fragment without any problem. May be you missed something.
Yeap, I already found the problem and fixed it, thx 🙂
Could u plz tell me?
Code is almost same, except for using getActivity() as context.
Thanks.
I’ve fragment class (as in case of navigation drawer ) that calls my simple layout .
Do I need to create new activity for placing above given MainActivity code or I can place it into
Existing fragment class. Wht changes I’ve to make?
I’m kind of new here ….plz help. here is my mail id : nishant2740@gmail.com
I tried it in same fragment but there are many possibilities.
Thanks again.
Can u send me that fragment class coding which u have done for ?if possible.
https://github.com/vishal0071/UPESCSI/commit/eabf2279546a1345e14295ea3be89438bbf893da
See for SectionOneFragment class.
I’ve implemented the given code But I’m getting unfortunately app_name has stopped.l
Any correction…..!
You have to find the problem yourself, you have logs, you have code. Take help from logs and try to solve it…
Can u share ur idea!!.?? Please.
how to fetch data from the website(which do not have rss feed or json feed in their website) in the same example u mention above ?
and news feed should update automatically with the website posts and data with time to time
how can i get the FeedItem id at a specific position in the list?
i used the name textview to get a specific position .in the FeedlistAdapter under the get view method i added this …
final FeedItem item = feedItems.get(position);
name.setText(item.getName());
name.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
info =item.getName();
Bundle extras = new Bundle();
Intent i1 = new Intent (context, Begin.class);
extras.putString(“val”, info);
//pasing info to new activity
i1.putExtras(extras);
context.startActivity(i1);
//Intent callIntent = new Intent();
Log.d(“Clicked”,”textview clicked “
Whenever i update the json file in my server,application not showing the updated data,
it shows the updated data only if i reinstall the application ,Kindly share the code for this issue and also include loading alert dialog box
I need that too
I am trying to redo the whole project using fragments instead of activity but there is an error at feedlistadapter.java trying to get the layout inflater for fragments
how to make infinity scroll ?
It is very good indeed but how do you parse JSON in UTF-8 ? In order to display Hindi 🙂 I am making an app which is Hindi related.
Thank you very much if you have time to explain or add the few line of code which would make it possible to display it properly.
Great Tutorial 🙂
Thank you.
I can’t download the code (keep getting timeout). Does anyone mind send me the code, please?
my mail: raffproject@gmail.com
Please check your SPAM folder for activation email.
Also I can not download
Excellent tutorial congratulations. I have a question. How can I show
the content within a fragment?. I hope to have your help. Thank you
Hi I try this onw but my app says unfortunately stop… Can you please help me..
Anyone Found a fix yet?
Hi Ravi.. I wonder if I can use my own facebook URL in the json? and how?
I haven’t tried. But look for graph api in facebook docs.
Hi Ravi… This is what I found and Tried. But, the app loads a blank feed. What Am I doing wrong?
———–
“How to obtain JSON/RSS feed for Facebook Pages without OAuth/GraphAPI
Facebook killed their publicly available RSS feed for Facebook Pages couple of years back in favor of their walled garden approach (GraphAPI). For example, if you go to http://graph.facebook.com/Nike/feed it will ask you for a valid access token which you can get obtain via OAuth Authorization which entails quite a few steps. If you just wanted to display/parse any Facebook Page feed without going through those hoops you are out of luck!
I found myself in a similar situation recently and after some Googling I was able to figure out a workaround. Here’s how it goes:
1) Go to https://developers.facebook.com/tools/explorer
2) Put the username/vanity url of the Facebook Page in question in the request bar and hit Submit. For example, if you wanted to get a feed for:https://www.facebook.com/nike you would put “nike” without quotes in the request bar and click on Submit. (Make sure GET request is selected in the drop-down)
3) Grab the id from the results below and paste it in this URL: https://www.facebook.com/feeds/page.php?id=%5BFACEBOOK-ID-GOES-HERE%5D&format=%5Brss20|json]
So for example, if we wanted JSON feed for Nike’s Facebook page, we’d go to:https://www.facebook.com/feeds/page.php?id=15087023444&format=json”
————–
Here is my code:
e String URL_FEED = “https://www.facebook.com/feeds/page.php?id=15087023444&format=json”;
and here is my error:
[2014-07-30 21:06:07 – Facebook Like FeedView] ActivityManager: Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=info.androidhive.listviewfeed/.MainActivity }
[2014-07-30 21:06:07 – Facebook Like FeedView] ActivityManager: Warning: Activity not started, its current task has been brought to the front
I also have this problem blank feed, can anyone help?
yeah same problem ! I hope @Ravi Tamada:disqus help us..
Please try to write the response to LogCat and verify whether you guys are getting something in the response or not. This happened to me when my phone doesn’t have internet connection.
Im using Emulator..
Did you printed the response to logcat? I already printed in log. Check for “Response: ” or “Error: ”
VolleyLog.d(TAG, “Response: ” + response.toString()); will print the json added in MainActivity.java
the error: Error Opening trace file: No such file or directory (2)
Its not the error. Paste the complete log if you see it in red color font.
what i did is i change your json link
http://api.androidhive.info/feed/feed.json to
“https://www.facebook.com/feeds/page.php?id=196934133652011&format=json”
It won’t work that way for every json url. You need to make the changes in the code according to the json response.
Can you help me to figure this out ?
Hi Ravi, I have succesfully build the app and done everything without errors and stuff but now on my phone on start up of the app it says: Unfortunately, “My App” Has Stopped. Can you suggest anything to fix this?
Pls check your Logcat for errors.
The red lines in the logcat starts with FATAL EXCEPTION: main, Hope you can help me, and maybe a crucial one is: Process”” com.example.listviewfeed, PID: 32486
I Have fixed thanks anyway
Hi Ravi, How can i use a custom json file I have uploaded it to my website and when i go to the link its the same as how yours would preview but when i put the link in MainActivity.java and if i then start the app nothing shows up.. Can you help please
I Have updated the project to download new information everytime the activity is loaded and internet connection is available.
When internet connection is not available it fetches the cache and uses it.
You can also combine this with refresh options like SwipeRefreshLayout or the ActionBar Refresh Button [Not Included in this project]. whenever you want to refresh just call getFeed();
Download: http://go.adm.bugs3.com/1
Thanks a lot for your valuable contribution…. need a solution for xml request instead of json
final String URL = “/volley/resource/recent.xml”;
StringRequest req = new StringRequest(URL, new Response.Listener() {
@Override
public void onResponse(String response) {
VolleyLog.v(“Response:%n %s”, response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e(“Error: “, error.getMessage());
}
});
// add the request object to the queue to be executed
ApplicationController.getInstance().addToRequestQueue(req);
parse XML in onResponse.You can find tutorial for it in this blog itself
Hi , i have used your updated code from your download path, but the application is not refresing everytime when i update the json file in the server, kindly help me. you can also reach me at jeevap14@gmail.com
What do you mean?
Does it not load new data instantly the server was updated or it doesn’t update itself even during activity launch?
Keep in mind that for information to be updated instantly you need to use GCM
Hi Idragon81, it doesn’t update itself even during activity launch, it only refresh only when i clear the cache.Kindly check and provide me the solution
Link is not working Pls update
Link not work.. 🙁