Skip to content

Instantly share code, notes, and snippets.

@IsabelManiega
Created March 5, 2017 13:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IsabelManiega/100db2a04350352a3c6a0ae08733ad26 to your computer and use it in GitHub Desktop.
Save IsabelManiega/100db2a04350352a3c6a0ae08733ad26 to your computer and use it in GitHub Desktop.
News Feed
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.example.isa.newsfeed.MainActivity">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.isa.newsfeed">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/date"
tools:text="Sep 22, 2016"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
style="@style/date"/>
<TextView
android:id="@+id/section"
tools:text="Development"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
style="@style/section"/>
</LinearLayout>
<TextView
android:id="@+id/author"
tools:text="Max Mustermann"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/author" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="This is going to be a long headline, I'm sure."
style="@style/title"/>
</LinearLayout>
package com.example.isa.newsfeed;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import java.util.List;
public class MainActivity extends AppCompatActivity
implements LoaderManager.LoaderCallbacks<List<News>>, SwipeRefreshLayout.OnRefreshListener {
private NewsAdapter adapter;
private static int LOADER_ID = 0;
SwipeRefreshLayout swipe;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
swipe = (SwipeRefreshLayout) findViewById(R.id.swiperefresh);
swipe.setOnRefreshListener(this);
swipe.setColorSchemeColors(getResources().getColor(R.color.colorAccent));
ListView listView = (ListView) findViewById(R.id.list_view);
adapter = new NewsAdapter(this);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
News news = adapter.getItem(i);
String url = news.url;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
}
});
getSupportLoaderManager().initLoader(LOADER_ID, null, this);
}
@Override
public Loader<List<News>> onCreateLoader(int id, Bundle args) {
return new NewsLoader(this);
}
@Override
public void onLoadFinished(Loader<List<News>> loader, List<News> data) {
swipe.setRefreshing(false);
if (data != null) {
adapter.setNotifyOnChange(false);
adapter.clear();
adapter.setNotifyOnChange(true);
adapter.addAll(data);
}
}
@Override
public void onLoaderReset(Loader<List<News>> loader) {
}
@Override
public void onRefresh() {
getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
}
}
package com.example.isa.newsfeed;
public class News{
String title;
String author;
String url;
String date;
String section;
public News(String title, String author, String url, String date, String section) {
this.title = title;
this.author = author;
this.url = url;
this.date = date;
this.section = section;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
@Override
public String toString() {
return "News{" +
"title='" + title + '\'' +
", author='" + author + '\'' +
", url='" + url + '\'' +
", date='" + date + '\'' +
", section='" + section + '\'' +
'}';
}
}
package com.example.isa.newsfeed;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
public class NewsAdapter extends ArrayAdapter<News>{
public NewsAdapter(Context context) {
super(context, -1, new ArrayList<News>());
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView
= LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
}
TextView title = (TextView) convertView.findViewById(R.id.title);
TextView author = (TextView) convertView.findViewById(R.id.author);
TextView date = (TextView) convertView.findViewById(R.id.date);
TextView section = (TextView) convertView.findViewById(R.id.section);
News currentNews = getItem(position);
title.setText(currentNews.getTitle());
author.setText(currentNews.getAuthor());
date.setText(currentNews.getDate());
section.setText(currentNews.getSection());
return convertView;
}
}
package com.example.isa.newsfeed;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;
import java.io.IOException;
import java.net.URL;
import java.util.List;
/**
* Created by ISA on 04/03/2017.
*/
public class NewsLoader extends AsyncTaskLoader<List<News>> {
public NewsLoader(Context context) {
super(context);
}
@Override
protected void onStartLoading() {
super.onStartLoading();
forceLoad();
}
@Override
public List<News> loadInBackground() {
List<News> listOfNews = null;
try {
URL url = QueryUtils.createUrl();
String jsonResponse = QueryUtils.makeHttpRequest(url);
listOfNews = QueryUtils.parseJson(jsonResponse);
} catch (IOException e) {
Log.e("Queryutils", "Error Loader LoadInBackground: ", e);
}
return listOfNews;
}
}
package com.example.isa.newsfeed;
import android.net.Uri;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* Created by ISA on 04/03/2017.
*/
public class QueryUtils {
static String createStringUrl() {
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
.encodedAuthority("content.guardianapis.com")
.appendPath("search")
.appendQueryParameter("order-by", "newest")
.appendQueryParameter("show-references", "author")
.appendQueryParameter("show-tags", "contributor")
.appendQueryParameter("q", "Android")
.appendQueryParameter("api-key", "test");
String url = builder.build().toString();
return url;
}
static URL createUrl() {
String stringUrl = createStringUrl();
try {
return new URL(stringUrl);
} catch (MalformedURLException e) {
Log.e("Queryutils", "Error creating URL: ", e);
return null;
}
}
private static String formatDate(String rawDate) {
String jsonDatePattern = "yyyy-MM-dd'T'HH:mm:ss'Z'";
SimpleDateFormat jsonFormatter = new SimpleDateFormat(jsonDatePattern, Locale.US);
try {
Date parsedJsonDate = jsonFormatter.parse(rawDate);
String finalDatePattern = "MMM d, yyy";
SimpleDateFormat finalDateFormatter = new SimpleDateFormat(finalDatePattern, Locale.US);
return finalDateFormatter.format(parsedJsonDate);
} catch (ParseException e) {
Log.e("QueryUtils", "Error parsing JSON date: ", e);
return "";
}
}
static String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
if (url == null){
return jsonResponse;
}
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.connect();
if (urlConnection.getResponseCode() == 200){
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
Log.e("mainActivity", "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e("Queryutils", "Error making HTTP request: ", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
inputStream.close();
}
}
return jsonResponse;
}
private static String readFromStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
static List<News> parseJson(String response) {
ArrayList<News> listOfNews = new ArrayList<>();
try {
JSONObject jsonResponse = new JSONObject(response);
JSONObject jsonResults = jsonResponse.getJSONObject("response");
JSONArray resultsArray = jsonResults.getJSONArray("results");
for (int i = 0; i < resultsArray.length(); i++) {
JSONObject oneResult = resultsArray.getJSONObject(i);
String webTitle = oneResult.getString("webTitle");
String url = oneResult.getString("webUrl");
String date = oneResult.getString("webPublicationDate");
date = formatDate(date);
String section = oneResult.getString("sectionName");
JSONArray tagsArray = oneResult.getJSONArray("tags");
String author = "";
if (tagsArray.length() == 0) {
author = null;
} else {
for (int j = 0; j < tagsArray.length(); j++) {
JSONObject firstObject = tagsArray.getJSONObject(j);
author += firstObject.getString("webTitle") + ". ";
}
}
listOfNews.add(new News(webTitle, author, url, date, section));
}
} catch (JSONException e) {
Log.e("Queryutils", "Error parsing JSON response", e);
}
return listOfNews;
}
}
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="title" parent="Base.TextAppearance.AppCompat.Large">
<item name="android:layout_marginBottom">8dp</item>
<item name="android:layout_marginTop">6dp</item>
<item name="android:layout_marginLeft">16dp</item>
<item name="android:layout_marginRight">16dp</item>
</style>
<style name="author" parent="Base.TextAppearance.AppCompat.Small">
<item name="android:layout_marginBottom">8dp</item>
<item name="android:layout_marginLeft">16dp</item>
<item name="android:layout_marginRight">16dp</item>
</style>
<style name="date" parent="Base.TextAppearance.AppCompat.Small">
<item name="android:layout_marginBottom">8dp</item>
<item name="android:layout_marginLeft">16dp</item>
<item name="android:layout_marginTop">16dp</item>
</style>
<style name="section" parent="Base.TextAppearance.AppCompat.Small">
<item name="android:gravity">right</item>
<item name="android:layout_marginTop">16dp</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:layout_marginRight">16dp</item>
</style>
</resources>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment