Code Description - ArshadHishamAPM/Aido_NewsWeatherTraffic GitHub Wiki
The main program when we click on the app will call the mainactivity. In main activity we will see the layout of activity_main.xml. In oncreate() method we are initializing the activity and we are setting the content view of the UI with activity_main layout resource. It will call the NewsActivity class. That is, it will move on to next activity news. On clicking the app, the user will first see the news details.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent=new Intent(getApplicationContext(),NewsActivity.class);
startActivity(intent);
}
}
Here the layout activity_news is shown as the content view layout when the activity is initialized with oncreate() method. The progress is initialized to the variable progressBar and set it as visible. The toolbar of the view is set to variable toolbar. A support action bar is set to the toolbar which is considered as app bar to display the title. The textview is initialized to a variable mTitle. The text of mTitle is set to 'News'.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news);
progressBar = (ProgressBar)findViewById(R.id.progress) ;
progressBar.setVisibility(View.VISIBLE);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
mTitle.setText("News");
A drawer layout is initialized to mDrawerLayout and list view is initialized to mDrawerList. A menu bar is shown in the left drawer with an array list of news, weather and traffic. Here for the toolbar, title 'news' is given. For the drawer layout, a drawer listener is set which will further invoke the onitem click listener for the drawer. List of news is shown side by side which is called by the ScreenSlidePageFragment() function. It will check the menu bar item clicked function for calling the corresponding activity. The oncreate() method will call the getNews() method for getting the news from google.
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
ArrayList arrayList = new ArrayList();
arrayList.add("News");
arrayList.add("Traffic");
arrayList.add("Weather");
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager(),list);
mPager.setAdapter(mPagerAdapter);
getNews();
}
For sliding the pages we are calling the ScreenSlidePagerAdapter() method class . So more news will be in the right side of the screen and we can slide each news. we are initializing a list. Here, the progress bar is set to visible. We will set a ScreenSlidePageFragment to get the posion of the item. we will also call getCount() method which will return the list size and the position also.
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
ArrayList<NewsModel> list1 = new ArrayList<>();
public ScreenSlidePagerAdapter(android.support.v4.app.FragmentManager fm,ArrayList<NewsModel> list) {
super(fm);
list1 = list;
}
@Override
public android.support.v4.app.Fragment getItem(int position) {
Log.i("getItem",String.valueOf(position));
progressBar.setVisibility(View.INVISIBLE);
ScreenSlidePageFragment screenSlidePageFragment = new ScreenSlidePageFragment();
return screenSlidePageFragment.newInstance(list1.get(position));
}
@Override
public int getCount() {
return list.size();
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
In the screen slide page fragment, will have the root view of fragment_screen_slide_page layout resource. The oncreate() method in fragment will intent to the WebViewActivity class. In the fragment it consists of a button for readmore and is initialized to variable readmore. It will initialize the text view and image view to set the title, descritpion and image of the news report. The title1 variable is set with the title of the news return from the WebViewActivity. The description1 is set with the text of descritpion of the news.
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.fragment_screen_slide_page, container, false);
Button readmore = (Button) rootView.findViewById(R.id.readmore);
readmore.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getContext(),WebViewActivity.class);
intent.putExtra("readmore",readMore);
intent.setAction("ScreenSlidePageFragment");
startActivity(intent);
}
});
TextView title1 = (TextView) rootView.findViewById(R.id.title);
TextView description1 = (TextView) rootView.findViewById(R.id.description);
ImageView urltoimage1 = (ImageView) rootView.findViewById(R.id.image);
title1.setText(title);
In WebViewActivity class, the layout view activity_web_view is set as the content view of the application. The webview in the layout is initialized to the variable myWebView. Then it will check the condition that the intent is not null and the action is ScreenSlidePageFragment with if loop, then it will get the readmore string to url. The url is loaded for the web view when the user clicks on the read more button to get more details.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
Intent intent = getIntent();
WebView myWebView = (WebView) findViewById(R.id.webview);
if(intent!=null&&intent.getAction().equals("ScreenSlidePageFragment")){
String url = intent.getStringExtra("readmore");
myWebView.loadUrl(url);
}
}
The oncreate() method will call the getNews() function, which is used to fetch and display the news for user. The result will be as JSON response which is further taken into our required format using Newsmodel. It will get the articles of the JSON object as an array and processing the array is done. It will iterate over all the items in the array and will get the title, descriptioon and image of the news to different variables. Those are then passed to the NewsModel() to get the news in the specified model and to display it in the app view. It is the added to a list. The pager adapter will set to notify that the data is changed. An error listener will identify if any of the error occurs. when new news occurs, it is added to the queue as the json response.
public void getNews(){
url = "https://newsapi.org/v1/articles?source=the-next-web&sortBy=latest&apiKey=0d913fbce03540799054a4633035a858";
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.i("result",response.toString());
try {
String articles = response.get("articles").toString();
JSONArray array=new JSONArray(articles);
for(int i=0;i<array.length();i++){
JSONObject jsonpart = array.getJSONObject(i);
String title = jsonpart.get("title").toString();
String description = jsonpart.get("description").toString();
String urlToImage = jsonpart.get("urlToImage").toString();
String readmore = jsonpart.get("url").toString();
Log.i("title",title);
newsModel = new NewsModel();
newsModel.setTitle(title);
newsModel.setDescription(description);
newsModel.setReadmore(readmore);
newsModel.setUrlofImage(urlToImage);
list.add(newsModel);
mPagerAdapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
Log.i("list",String.valueOf(list.size()));
Log.i("list",list.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.i("response",error.toString());
}
});
queue.add(jsObjRequest);
}
It will call the newsModel() method. It is the class that gets the news from the google and it will pass the details of the news as a string back to the getNews() method, which will further display in the screen. In NewsModel() the getDescription(),getTitle() and getUrlOfImage() will return the description, title and url of image of the news. The getReadmore() will return the readmore value. The url will fetch the image of the news clicked by the user. When a user clicks on the news, the current clicked news title, description and image is fetched and will return to the getNews() method.
public class NewsModel {
String title;
String description;
String urlofImage;
public String getReadmore() {
return readmore;
}
public void setReadmore(String readmore) {
this.readmore = readmore;
}
String readmore;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrlofImage() {
return urlofImage;
}
public void setUrlofImage(String urlofImage) {
this.urlofImage = urlofImage;
}
}
The menu bar is clicked is checked by clicklistener function which is set for the drawer. The listener will pass the position of the list view clicked by the user, which is used to process the onclick() method. If the position is 0, the drawer is closed. ie, the news activity itself need to be showed so no change in the view. If it is 1, then it will call the maps activity and will move to its layout and starts activity MapsActivity. And if it is 2, it will go for weather forecasting and its layout by invoking the WeatherForcast class which starts the corresponding activity.
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(position==0){
mDrawerLayout.closeDrawers();
return;
}
if(position==1){
Intent intent = new Intent(getApplicationContext(),MapsActivity.class);
startActivity(intent);
finish();
}
if(position==2){
Intent intent = new Intent(getApplicationContext(),WeatherForcast.class);
startActivity(intent);
finish();
}
}
}
If the position of the item clicked on the menu bar is 1, the news activity will call the map activity. While calling this activity, the oncreate() method will display the layout activity_maps layout resource. The textview is initialized to the variable mTitle. The mTitle of the toolbar is set the title as Traffic.
setContentView(R.layout.activity_maps);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
mTitle.setText("Traffic");
The address is intialized to the variable address in the oncreate() method. An editor action result is set for the address which will call the onEditorAction() function. This activity will check the event and an enter key is pressed by the user. If event is null and enter key is not pressed, the user hadn't given any address else the destination address had been given by the user to check the traffic. It will get the address to variable name1. It will check whether name1 is null or not. If not null, it will call getRoute() method. If no address is given, it will give the message as 'please enter the address'. It will also call the drawer layout as same as newsactivity.
address = (EditText) findViewById(R.id.address);
address.setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
Log.i("pressed","Enter pressed");
inputManager.hideSoftInputFromWindow(
getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
String name = address.getText().toString();
if(name!=null){
String name1 = name.replaceAll(" ","+");
getRoute(name1);
}
else {
Toast.makeText(getApplicationContext(),"Please Enter destination",Toast.LENGTH_SHORT).show();
}
}
return true;
}
});
It will call the getRoute() function if the entered address string is not null. Passing the address as string to the url and getting the data as JSON response. If the destination marker is not null, it will remove the marker. It will get the altitude and longitude. If the location is changed, it will get the current poosition. It will get the results to the variable location as string and is given to a JSON array. Iterating over every element in the array, it will get the latitude and longitude of the new location and it is set as the destination. A marker is set with the new destination in the map. An error listener is set to identify the error that occurs. It will call the drawpath() method, which is used to draw the marker on the map with new latitude and longitude which is fetched with the url.
public void getRoute(String addressName) {
url = "https://maps.googleapis.com/maps/api/geocode/json?address="+addressName+"&key=AIzaSyBu4xO13m6GZCiUWmsZcYo2thfZF390zfo";
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
if(destinatiomarker!=null){
destinatiomarker.remove();
}
Log.i("response", response.toString());
String location = null;
try {
location = response.getString("results").toString();
} catch (JSONException e) {
e.printStackTrace();
}
try {
JSONArray array = new JSONArray(location);
for(int i=0;i<array.length();i++){
JSONObject part = array.getJSONObject(i);
String geometry = part.getString("geometry");
Log.i("geometry",geometry);
JSONObject part1=new JSONObject(geometry);
JSONObject part2=part1.getJSONObject("location");
lat1 = part2.getDouble("lat");
lng1 = part2.getDouble("lng");
destination = new LatLng(lat1,lng1);
Log.i("lat1andLng1",String.valueOf(lat1)+" "+String.valueOf(lng1));
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(destination);
markerOptions.title("destination");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
destinatiomarker = mMap.addMarker(markerOptions);
mMap.moveCamera(CameraUpdateFactory.newLatLng(destination));
if(MarkerPoints.size()>0){
MarkerPoints.add(1,destination);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
drawpath();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(jsObjRequest);
}
In the drawpath() method, it will get the origin and the destination if the size of the MarkerPoints is greater than or equals to 2 in the if loop. It will call the getUrl() method with the origin and destination to get the corresponding url. Then it will call the FetchUrl() method. In the background, it will establish a HTTP connection with the given url and will check there is permission to access the google API. Then it will start downloading json data from Google Directions API. In the post execution it will get the routes. It will move the camera and also animate the camera with the new routes to mark the new routes in the map. It will draw the route lines with red color.
public void drawpath(){
if (MarkerPoints.size() >= 2) {
LatLng origin = MarkerPoints.get(0);
LatLng dest = MarkerPoints.get(1);
Log.i("direction","called");
// Getting URL to the Google Directions API
Log.i("originanddestination",String.valueOf(origin.latitude));
String url = getUrl(origin, dest);
Log.d("onMapClick", url.toString());
FetchUrl FetchUrl = new FetchUrl();
// Start downloading json data from Google Directions API
FetchUrl.execute(url);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(origin));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
}
If the user clicks on the menu bar items, drawer item listener will get the postiton of the item clicked is given to the onitemClick() function and It will check whicj item is clicked. If the position is 0, it will call the news activity and display its layout and functionalities. If the position is 1, it will remain in the same traffic page and will close the drawer so no change for the view is required. If the position is 2,it will call the weather forecast activity and shows its layout page.
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(position==0){
Intent intent = new Intent(getApplicationContext(),NewsActivity.class);
startActivity(intent);
finish();
}
if(position==1){
mDrawerLayout.closeDrawers();
return;
}
if(position==2){
Intent intent = new Intent(getApplicationContext(),WeatherForcast.class);
startActivity(intent);
finish();
}
}
}
When the user clicks on menu bar,weather, the position is 2 and main program will call the weatherforecast class. The toolbar is initialized to variable toolbar and text view is initialized to mTitle variable in the oncreate() method of the activity. It will display the layout content_weather_forcast and set title as weather. First it will show the weather report of Palo Alto. The edit text is initialized to city name and an editor action listener is set to it. The user can enter the city name where in which we want the weather report. If the user had entered any city name or removed Palo Alto it will detect an event happened when the user press enter key in the onEditorAction() method. It will get the name of the city and will check whether it is null or not. If not null, it will call the function getWeather(). If city name is null it will display the message to enter the name.
setContentView(R.layout.content_weather_forcast);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
mTitle.setText("Weather");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
cityname = (EditText) findViewById(R.id.cityName);
cityname.setText("Palo Alto");
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
cityname.setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
Log.i("pressed","Enter pressed");
inputManager.hideSoftInputFromWindow(
getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
String name = cityname.getText().toString();
if (name != null) {
url = "http://api.openweathermap.org/data/2.5/forecast?q="+name+"&appid=291b3a14d9367e0fff371be2a1912b44";
getWeather(url);
}
else {
Toast.makeText(getApplicationContext(),"Please Enter city name",Toast.LENGTH_SHORT).show();
}
}
return true;
}
});
The getWeather() is given below. It will get the weather report as JSON response. It will get the list from the json response to the variable weatherinfo in the try loop. An JSON array is initialized with this weatherinfo list. It will iterate over the entire elements in the array and each element is given to the variable jsonPart. The date and main of each array element is given to the strings data and object. From the string object it will get ythe pressure, humidity and temperature. WeatherModel() is initialized and the description of the weather is passed to the weatherModel() function. In that function, it will set the pressure, temperature, humidity and date and will return these values to the getWeather() function. In the recycler view it will display these values using the RecylerviewAdapter. An error listener is set to catch the errors that occurs while executing this functions.
public void getWeather(String url){
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
wheatherDataList.clear();
String message="",main=null,description=null;
Log.i("response","called");
Log.i("response", response.toString());
String weatherinfo= null;
try {
weatherinfo = response.getString("list");
} catch (JSONException e) {
e.printStackTrace();
}
Log.i("weatherinfo",weatherinfo);
JSONArray array= null;
try {
array = new JSONArray(weatherinfo);
} catch (JSONException e) {
e.printStackTrace();
}
for(int i=0;i<array.length();i++) {
JSONObject jsonPart = null;
try {
jsonPart = array.getJSONObject(i);
Log.i("date", jsonPart.getString("dt_txt"));
String date = jsonPart.getString("dt_txt");
String object = jsonPart.getString("main");
JSONObject object1 = new JSONObject(object);
Log.i("temp", object1.getString("temp"));
String temp = object1.getString("temp");
String humidity = object1.getString("humidity");
String pressure = object1.getString("pressure");
Log.i("humidity", object1.getString("humidity"));
Log.i("pressure", object1.getString("pressure"));
String weather = jsonPart.getString("weather");
JSONArray array1 = new JSONArray(weather);
for (int j = 0; j < array1.length(); j++) {
JSONObject jsonPart1 = array1.getJSONObject(j);
weatherModel = new WeatherModel();
main = jsonPart1.getString("main");
Log.i("main", jsonPart1.getString("main"));
description = jsonPart1.getString("description");
Log.i("description", jsonPart1.getString("description"));
message += main + ":" + description + "\r\n";
String listcontent = main + ":" + description;
list.add(listcontent);
weatherModel.setWeatherinfo(description);
weatherModel.setDate(date);
Log.i("date1", weatherModel.getDate());
weatherModel.setHumidity(humidity);
weatherModel.setPressure(pressure);
weatherModel.setTemp(temp);
wheatherDataList.add(weatherModel);
}
mRecyclerView.setAdapter(new RecylerviewAdapter(WeatherForcast.this,wheatherDataList));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
Log.i("response",error.toString());
}
});
queue.add(jsObjRequest);
}
Here, we are fetching the data date wise. It will display the data based on the latest date and time. It will fetch the JSON response and will change it into the string model which we want to display. The weatherModel() will set the weather information as the current information using 'this'. It will get the Temp with getTemp() method and will set the temperature with current value that is fetched with getTemp() method. It will also get the pressure, humidity and date with functions such as getPressure(), getHumidity() and getDate(). It will also set the pressure, humidity and date with the return values of these functions using 'this' to get the current value.
public WeatherModel() {
}
public void setWeatherinfo(String weatherinfo) {
this.weatherinfo = weatherinfo;
}
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
public String getPressure() {
return pressure;
}
public void setPressure(String pressure) {
this.pressure = pressure;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(weatherinfo);
dest.writeString(temp);
dest.writeString(humidity);
dest.writeString(date);
dest.writeString(pressure);
In the RecyclerViewAdapter,in the onCreateViewHolder() method, it will disply the layout of recyclerviewlayout resource. It will also initialize the viewHolder with the variable v as view. This will call the onBindViewHolder() method.
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerviewlayout, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
onBindViewHolder() method will have the position as the function parameter. It will get the position from the list into the variable weatherModel. It will get the temperature to the varaible temp. We are getting the variable temp1 with int value of temp-273.15. The weather information is displayed in the log. The holder is setting the text of date, pressure, humidity and temperature by getting the values from the weatherModel variable which we initialized with the list.
public void onBindViewHolder(ViewHolder holder, int position) {
WeatherModel weatherModel = list.get(position);
double temp = Double.parseDouble(weatherModel.getTemp());
int temp1 = (int) (temp-273.15);
Log.i("weathorinAdapter",weatherModel.getWeatherinfo()+ " " +weatherModel.getTemp()+" "+weatherModel.getHumidity());
holder.date.setText(weatherModel.getDate());
holder.weather.setText(weatherModel.getWeatherinfo());
holder.temp.setText("Temprature : "+temp1+"°c");
holder.humidity.setText("Humidity : "+weatherModel.getHumidity()+"%");
holder.pressure.setText("Pressure : "+weatherModel.getPressure()+"hPa");
}
It will also check the item clicked in the menu bar. When the user clicks on a menu bar item, a drawer item click listener will initiate the onItemClick() method and will pass the postion of the item. If the item clicked is news, which have position 0, it will call the news activity and its functionalities. If the position of item clicked is 1, that is traffic will execute the maps activity. If the item clicked is weather itself, the drawer will be closed and will remain in the same page.
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(position==0){
Intent intent = new Intent(getApplicationContext(),NewsActivity.class);
startActivity(intent);
finish();
}
if(position==1){
Intent intent = new Intent(getApplicationContext(),MapsActivity.class);
startActivity(intent);
finish();
}
if(position==2){
mDrawerLayout.closeDrawers();
return;
}
}
}