From 34952c45a7f687206953bd8596e83b8325ebed4d Mon Sep 17 00:00:00 2001
From: "de@itstall.de" <de@itstall.de>
Date: Wed, 1 Apr 2020 14:21:02 +0200
Subject: [PATCH] News working

---
 .../controller/NewsAdapter.java               |  60 ++++++++++
 .../controller/NextApAdapter.java             |   5 +-
 .../controller/RequestAps.java                |   4 +-
 .../controller/RequestNews.java               |  62 ++++++++++
 .../controller/RequestSsids.java              |   4 +-
 .../controller/SsidsAdapter.java              |   2 +-
 .../model/MyLocationProvider.java             | 107 ------------------
 .../itstall/freifunkfranken/model/News.java   |  25 ++++
 .../freifunkfranken/view/MainActivity.java    |  50 ++++----
 .../freifunkfranken/view/MapsFragment.java    |  18 +--
 .../freifunkfranken/view/NewsFragment.java    |  47 ++++++++
 .../freifunkfranken/view/NextApFragment.java  |   3 +-
 .../freifunkfranken/view/SsidsFragment.java   |   3 +-
 app/src/main/res/drawable/news_border.xml     |   9 ++
 app/src/main/res/layout/news_fragment.xml     |  16 +++
 app/src/main/res/layout/news_item.xml         |  55 +++++++++
 app/src/main/res/layout/nextap_item.xml       |   6 +-
 app/src/main/res/layout/ssids_item.xml        |   2 +-
 app/src/main/res/values/strings.xml           |   4 +
 19 files changed, 316 insertions(+), 166 deletions(-)
 create mode 100644 app/src/main/java/de/itstall/freifunkfranken/controller/NewsAdapter.java
 create mode 100644 app/src/main/java/de/itstall/freifunkfranken/controller/RequestNews.java
 delete mode 100644 app/src/main/java/de/itstall/freifunkfranken/model/MyLocationProvider.java
 create mode 100644 app/src/main/java/de/itstall/freifunkfranken/model/News.java
 create mode 100644 app/src/main/java/de/itstall/freifunkfranken/view/NewsFragment.java
 create mode 100644 app/src/main/res/drawable/news_border.xml
 create mode 100644 app/src/main/res/layout/news_fragment.xml
 create mode 100644 app/src/main/res/layout/news_item.xml

diff --git a/app/src/main/java/de/itstall/freifunkfranken/controller/NewsAdapter.java b/app/src/main/java/de/itstall/freifunkfranken/controller/NewsAdapter.java
new file mode 100644
index 0000000..11ceb0f
--- /dev/null
+++ b/app/src/main/java/de/itstall/freifunkfranken/controller/NewsAdapter.java
@@ -0,0 +1,60 @@
+package de.itstall.freifunkfranken.controller;
+
+import android.annotation.SuppressLint;
+import android.text.Html;
+import android.text.method.LinkMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+import de.itstall.freifunkfranken.R;
+import de.itstall.freifunkfranken.model.News;
+
+public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
+    private static final String TAG = NewsAdapter.class.getSimpleName();
+    private List<News> newsList;
+
+    public NewsAdapter(List<News> newsList) {
+        this.newsList = newsList;
+    }
+
+    @NonNull
+    @Override
+    public NewsAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        @SuppressLint("InflateParams") View viewNewsItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, null);
+
+        return new ViewHolder(viewNewsItem);
+    }
+
+    @Override
+    public void onBindViewHolder(NewsAdapter.ViewHolder viewHolder, int position) {
+        viewHolder.tvNewsDate.setText(newsList.get(position).getDate());
+        viewHolder.tvNewsTitle.setText(newsList.get(position).getTitle());
+        viewHolder.tvNewsDescription.setText(Html.fromHtml(newsList.get(position).getDescription()));
+        viewHolder.tvNewsDescription.setMovementMethod(LinkMovementMethod.getInstance());
+    }
+
+    @Override
+    public int getItemCount() {
+        return newsList.size();
+    }
+
+    static class ViewHolder extends RecyclerView.ViewHolder {
+        TextView tvNewsTitle;
+        TextView tvNewsDate;
+        TextView tvNewsDescription;
+
+        ViewHolder(View viewNewsItem) {
+            super(viewNewsItem);
+            tvNewsDate = viewNewsItem.findViewById(R.id.tvNewsDate);
+            tvNewsTitle = viewNewsItem.findViewById(R.id.tvNewsTitle);
+            tvNewsDescription = viewNewsItem.findViewById(R.id.tvNewsDescription);
+        }
+    }
+}
diff --git a/app/src/main/java/de/itstall/freifunkfranken/controller/NextApAdapter.java b/app/src/main/java/de/itstall/freifunkfranken/controller/NextApAdapter.java
index 207a9d9..f31b474 100644
--- a/app/src/main/java/de/itstall/freifunkfranken/controller/NextApAdapter.java
+++ b/app/src/main/java/de/itstall/freifunkfranken/controller/NextApAdapter.java
@@ -15,6 +15,7 @@ import de.itstall.freifunkfranken.R;
 import de.itstall.freifunkfranken.model.AccessPoint;
 
 public class NextApAdapter extends RecyclerView.Adapter<NextApAdapter.ViewHolder> {
+    private static final String TAG = NextApAdapter.class.getSimpleName();
     private List<AccessPoint> accessPointList;
 
     public NextApAdapter(List<AccessPoint> aps) {
@@ -52,9 +53,9 @@ public class NextApAdapter extends RecyclerView.Adapter<NextApAdapter.ViewHolder
 
         ViewHolder(View itemView) {
             super(itemView);
-            tvAp = itemView.findViewById(R.id.tvAp);
+            tvAp = itemView.findViewById(R.id.tvNewsTitle);
             tvStatus = itemView.findViewById(R.id.tvStatus);
-            tvDistance = itemView.findViewById(R.id.tvDistance);
+            tvDistance = itemView.findViewById(R.id.tvNewsDate);
         }
     }
 }
diff --git a/app/src/main/java/de/itstall/freifunkfranken/controller/RequestAps.java b/app/src/main/java/de/itstall/freifunkfranken/controller/RequestAps.java
index a6d79c2..c06f683 100644
--- a/app/src/main/java/de/itstall/freifunkfranken/controller/RequestAps.java
+++ b/app/src/main/java/de/itstall/freifunkfranken/controller/RequestAps.java
@@ -39,8 +39,8 @@ public class RequestAps {
         }
 
         try {
-            JSONObject jsonString = new JSONObject(stringBuilder.toString());
-            JSONArray nodes = jsonString.getJSONArray("nodes");
+            JSONObject jsonObject = new JSONObject(stringBuilder.toString());
+            JSONArray nodes = jsonObject.getJSONArray("nodes");
             JSONObject node;
             AccessPoint ap;
             for (int i = 0; i < nodes.length(); i++) {
diff --git a/app/src/main/java/de/itstall/freifunkfranken/controller/RequestNews.java b/app/src/main/java/de/itstall/freifunkfranken/controller/RequestNews.java
new file mode 100644
index 0000000..4ac43ab
--- /dev/null
+++ b/app/src/main/java/de/itstall/freifunkfranken/controller/RequestNews.java
@@ -0,0 +1,62 @@
+package de.itstall.freifunkfranken.controller;
+
+import android.content.Context;
+import android.util.Log;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import de.itstall.freifunkfranken.model.News;
+
+public class RequestNews {
+    private static final String TAG = RequestNews.class.getSimpleName();
+    private List<News> newsList = new ArrayList<>();
+
+    public RequestNews(Context context) {
+        String filename = "data.json";
+        StringBuilder stringBuilder = new StringBuilder();
+        File dataFile = new File(context.getFilesDir(), filename);
+
+        try {
+            BufferedReader bufferedReader = new BufferedReader(new FileReader(dataFile));
+            String line;
+
+            while ((line = bufferedReader.readLine()) != null) {
+                stringBuilder.append(line);
+            }
+            bufferedReader.close();
+        } catch (Exception e) {
+            Log.e("ReadWriteFile", "Unable to read file: " + filename);
+        }
+
+        try {
+            JSONObject jsonObject = new JSONObject(stringBuilder.toString());
+            JSONArray newsArray = jsonObject.getJSONArray("news");
+            JSONObject item;
+            News news;
+            for (int i = 0; i < newsArray.length(); i++) {
+                item = newsArray.getJSONObject(i);
+                news = new News(
+                        item.getString("title"),
+                        item.getString("pubDate"),
+                        item.getString("description")
+                );
+                newsList.add(news);
+            }
+        } catch (JSONException e) {
+            Log.e("JSONException:", Objects.requireNonNull(e.getMessage()));
+        }
+    }
+
+    public List<News> getNewsList() {
+        return newsList;
+    }
+}
diff --git a/app/src/main/java/de/itstall/freifunkfranken/controller/RequestSsids.java b/app/src/main/java/de/itstall/freifunkfranken/controller/RequestSsids.java
index c708e01..f9dad40 100644
--- a/app/src/main/java/de/itstall/freifunkfranken/controller/RequestSsids.java
+++ b/app/src/main/java/de/itstall/freifunkfranken/controller/RequestSsids.java
@@ -37,8 +37,8 @@ public class RequestSsids {
         }
 
         try {
-            JSONObject jsonString = new JSONObject(stringBuilder.toString());
-            JSONArray jsonArray = jsonString.getJSONArray("ssids");
+            JSONObject jsonObject = new JSONObject(stringBuilder.toString());
+            JSONArray jsonArray = jsonObject.getJSONArray("ssids");
             for (int i = 0; i < jsonArray.length(); i++) {
                 ssidList.add(new Ssid(jsonArray.getString(i)));
             }
diff --git a/app/src/main/java/de/itstall/freifunkfranken/controller/SsidsAdapter.java b/app/src/main/java/de/itstall/freifunkfranken/controller/SsidsAdapter.java
index 6a00df7..f921e02 100644
--- a/app/src/main/java/de/itstall/freifunkfranken/controller/SsidsAdapter.java
+++ b/app/src/main/java/de/itstall/freifunkfranken/controller/SsidsAdapter.java
@@ -46,7 +46,7 @@ public class SsidsAdapter extends RecyclerView.Adapter<SsidsAdapter.ViewHolder>
 
         ViewHolder(View itemView) {
             super(itemView);
-            tvSsid = itemView.findViewById(R.id.tvAp);
+            tvSsid = itemView.findViewById(R.id.tvNewsTitle);
         }
     }
 }
diff --git a/app/src/main/java/de/itstall/freifunkfranken/model/MyLocationProvider.java b/app/src/main/java/de/itstall/freifunkfranken/model/MyLocationProvider.java
deleted file mode 100644
index a80eed8..0000000
--- a/app/src/main/java/de/itstall/freifunkfranken/model/MyLocationProvider.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package de.itstall.freifunkfranken.model;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.IntentSender;
-import android.location.Location;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.google.android.gms.common.ConnectionResult;
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.location.LocationListener;
-import com.google.android.gms.location.LocationRequest;
-import com.google.android.gms.location.LocationServices;
-
-public class MyLocationProvider implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
-
-    public static final String TAG = MyLocationProvider.class.getSimpleName();
-    /*
-     * Define a request code to send to Google Play services This code is returned in
-     * Activity.onActivityResult
-     */
-    private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
-    private LocationCallback mLocationCallback;
-    private Context mContext;
-    private GoogleApiClient mGoogleApiClient;
-    private LocationRequest mLocationRequest;
-    public MyLocationProvider(Context context, LocationCallback callback) {
-        mGoogleApiClient = new GoogleApiClient.Builder(context)
-                .addConnectionCallbacks(this)
-                .addOnConnectionFailedListener(this)
-                .addApi(LocationServices.API)
-                .build();
-
-        mLocationCallback = callback;
-
-        // Create the LocationRequest object
-        mLocationRequest = LocationRequest.create()
-                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
-                .setInterval(10 * 1000)        // 10 seconds, in milliseconds
-                .setFastestInterval(1 * 1000); // 1 second, in milliseconds
-
-        mContext = context;
-    }
-
-    public void connect() {
-        Log.i(TAG, "connect: " + mContext.getClass().getSimpleName());
-        mGoogleApiClient.connect();
-    }
-
-    public void disconnect() {
-        if (mGoogleApiClient.isConnected()) {
-            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
-            mGoogleApiClient.disconnect();
-        }
-    }
-
-    @Override
-    public void onConnected(Bundle bundle) {
-        Log.i(TAG, "Location services connected.");
-
-        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
-        if (location == null) {
-            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
-        } else {
-            mLocationCallback.handleNewLocation(location);
-        }
-    }
-
-    @Override
-    public void onConnectionSuspended(int i) {
-
-    }
-
-    @Override
-    public void onConnectionFailed(ConnectionResult connectionResult) {
-        /*
-         * Google Play services can resolve some errors it detects.
-         * If the error has a resolution, try sending an Intent to
-         * start a Google Play services activity that can resolve
-         * error.
-         */
-        if (connectionResult.hasResolution() && mContext instanceof Activity) {
-            try {
-                Activity activity = (Activity) mContext;
-                // Start an Activity that tries to resolve the error
-                connectionResult.startResolutionForResult(activity, CONNECTION_FAILURE_RESOLUTION_REQUEST);
-                // Thrown if Google Play services canceled the original PendingIntent
-            } catch (IntentSender.SendIntentException e) {
-                // Log the error
-                e.printStackTrace();
-            }
-        } else {
-            // If no resolution is available, display a dialog to the user with the error.
-            Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
-        }
-    }
-
-    @Override
-    public void onLocationChanged(Location location) {
-        mLocationCallback.handleNewLocation(location);
-    }
-
-    public abstract interface LocationCallback {
-        public void handleNewLocation(Location location);
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/de/itstall/freifunkfranken/model/News.java b/app/src/main/java/de/itstall/freifunkfranken/model/News.java
new file mode 100644
index 0000000..18ac0b3
--- /dev/null
+++ b/app/src/main/java/de/itstall/freifunkfranken/model/News.java
@@ -0,0 +1,25 @@
+package de.itstall.freifunkfranken.model;
+
+public class News {
+    private String title;
+    private String date;
+    private String description;
+
+    public News(String title, String date, String description) {
+        this.title = title;
+        this.date = date;
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public String getDate() {
+        return date;
+    }
+}
diff --git a/app/src/main/java/de/itstall/freifunkfranken/view/MainActivity.java b/app/src/main/java/de/itstall/freifunkfranken/view/MainActivity.java
index 388d725..2f374f9 100644
--- a/app/src/main/java/de/itstall/freifunkfranken/view/MainActivity.java
+++ b/app/src/main/java/de/itstall/freifunkfranken/view/MainActivity.java
@@ -1,9 +1,10 @@
 package de.itstall.freifunkfranken.view;
 
+import android.annotation.SuppressLint;
 import android.content.Intent;
-import android.location.Location;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
 import android.os.Bundle;
-import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -13,54 +14,60 @@ import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentTransaction;
 
-import com.google.android.gms.maps.model.LatLng;
 import com.google.android.material.tabs.TabLayout;
 
-import java.util.Objects;
-
 import de.itstall.freifunkfranken.R;
 import de.itstall.freifunkfranken.controller.FileDownloader;
-import de.itstall.freifunkfranken.model.MyLocationProvider;
 
-public class MainActivity extends AppCompatActivity implements MyLocationProvider.LocationCallback {
+public class MainActivity extends AppCompatActivity {
     public static final String TAG = MainActivity.class.getSimpleName();
     public Fragment fragment = null;
     public boolean downloadDone = false;
     TabLayout tabLayout;
-    private MyLocationProvider mLocationProvider;
+    private SharedPreferences sharedPreferences;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 
+        sharedPreferences = this.getApplicationContext().getSharedPreferences("FreifunkFrankenApp", 0);
+
         tabLayout = findViewById(R.id.tabLayout);
 
         final TabLayout.Tab nextApTab = tabLayout.newTab();
         TabLayout.Tab karteTab = tabLayout.newTab();
         karteTab.setText(getResources().getString(R.string.tabKarte));
-        tabLayout.addTab(karteTab);
         nextApTab.setText(getResources().getString(R.string.tabNextAp));
-        tabLayout.addTab(nextApTab);
         TabLayout.Tab ssidsTab = tabLayout.newTab();
         ssidsTab.setText(getResources().getString(R.string.tabSsids));
-        tabLayout.addTab(ssidsTab);
+        TabLayout.Tab newsTab = tabLayout.newTab();
+        newsTab.setText(getResources().getString(R.string.tabNews));
+        tabLayout.addTab(newsTab);
+        tabLayout.addTab(nextApTab);
+        tabLayout.addTab(karteTab);
+        //tabLayout.addTab(ssidsTab);
 
         tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
             @Override
             public void onTabSelected(TabLayout.Tab tab) {
                 switch (tab.getPosition()) {
                     case 0:
-                        fragment = new MapsFragment();
+                        fragment = new NewsFragment();
                         break;
                     case 1:
                         fragment = new NextApFragment();
                         break;
                     case 2:
-                        fragment = new SsidsFragment();
+                        fragment = new MapsFragment();
                         break;
+                    case 3:
+                        fragment = new SsidsFragment();
                 }
                 if (downloadDone) loadFragment(fragment);
+                @SuppressLint("CommitPrefEdits") Editor editor = sharedPreferences.edit();
+                editor.putInt("selectedTab", tab.getPosition());
+                editor.apply();
             }
 
             @Override
@@ -72,8 +79,6 @@ public class MainActivity extends AppCompatActivity implements MyLocationProvide
             }
         });
 
-        //mLocationProvider = new MyLocationProvider(this, this);
-
         downloadFiles();
     }
 
@@ -114,22 +119,13 @@ public class MainActivity extends AppCompatActivity implements MyLocationProvide
     @Override
     protected void onResume() {
         super.onResume();
-        Objects.requireNonNull(tabLayout.getTabAt(1)).select();
-        Objects.requireNonNull(tabLayout.getTabAt(0)).select();
-        //mLocationProvider.connect();
+        TabLayout.Tab selectedTab = tabLayout.getTabAt(sharedPreferences.getInt("selectedTab", 0));
+        assert selectedTab != null;
+        selectedTab.select();
     }
 
     @Override
     protected void onPause() {
         super.onPause();
-        //mLocationProvider.disconnect();
-    }
-
-    public void handleNewLocation(Location location) {
-        Log.d(TAG, location.toString());
-
-        double currentLatitude = location.getLatitude();
-        double currentLongitude = location.getLongitude();
-        LatLng latLng = new LatLng(currentLatitude, currentLongitude);
     }
 }
diff --git a/app/src/main/java/de/itstall/freifunkfranken/view/MapsFragment.java b/app/src/main/java/de/itstall/freifunkfranken/view/MapsFragment.java
index 6c33fc0..46508a1 100644
--- a/app/src/main/java/de/itstall/freifunkfranken/view/MapsFragment.java
+++ b/app/src/main/java/de/itstall/freifunkfranken/view/MapsFragment.java
@@ -3,9 +3,7 @@ package de.itstall.freifunkfranken.view;
 import android.Manifest;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
-import android.location.Location;
 import android.os.Bundle;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -29,9 +27,8 @@ import java.util.Objects;
 import de.itstall.freifunkfranken.R;
 import de.itstall.freifunkfranken.controller.RequestAps;
 import de.itstall.freifunkfranken.model.AccessPoint;
-import de.itstall.freifunkfranken.model.MyLocationProvider;
 
-public class MapsFragment extends Fragment implements OnMapReadyCallback, MyLocationProvider.LocationCallback {
+public class MapsFragment extends Fragment implements OnMapReadyCallback {
     private static final String TAG = MapsFragment.class.getSimpleName();
     private GoogleMap mMap;
     private View rootView;
@@ -54,9 +51,6 @@ public class MapsFragment extends Fragment implements OnMapReadyCallback, MyLoca
 
         sharedPreferences = rootView.getContext().getSharedPreferences("FreifunkFrankenApp", 0);
 
-        //mLocationProvider = new MyLocationProvider(this.getContext(), this);
-        //mLocationProvider.connect();
-
         checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_ID_ACCESS_COARSE_LOCATION);
         checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, REQUEST_ID_ACCESS_COARSE_LOCATION);
 
@@ -91,16 +85,6 @@ public class MapsFragment extends Fragment implements OnMapReadyCallback, MyLoca
         }
     }
 
-    @Override
-    public void handleNewLocation(Location location) {
-        Log.d(TAG, location.toString());
-
-        double currentLatitude = location.getLatitude();
-        double currentLongitude = location.getLongitude();
-        LatLng latLng = new LatLng(currentLatitude, currentLongitude);
-        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 10));
-    }
-
     public void checkPermission(String permission, int requestCode) {
         // Checking if permission is not granted
         if (ContextCompat.checkSelfPermission(
diff --git a/app/src/main/java/de/itstall/freifunkfranken/view/NewsFragment.java b/app/src/main/java/de/itstall/freifunkfranken/view/NewsFragment.java
new file mode 100644
index 0000000..13524e6
--- /dev/null
+++ b/app/src/main/java/de/itstall/freifunkfranken/view/NewsFragment.java
@@ -0,0 +1,47 @@
+package de.itstall.freifunkfranken.view;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+import de.itstall.freifunkfranken.R;
+import de.itstall.freifunkfranken.controller.NewsAdapter;
+import de.itstall.freifunkfranken.controller.RequestNews;
+import de.itstall.freifunkfranken.model.News;
+
+public class NewsFragment extends Fragment {
+    private RecyclerView rvNews;
+    private View rootView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        rootView = inflater.inflate(R.layout.news_fragment, container, false);
+
+        rvNews = rootView.findViewById(R.id.rvNews);
+        rvNews.setLayoutManager(new LinearLayoutManager(getActivity()));
+
+        List<News> newsList = new RequestNews(this.getContext()).getNewsList();
+        showNewsList(newsList);
+
+        return rootView;
+    }
+
+    private void showNewsList(List<News> newsList) {
+        NewsAdapter newsAdapter = new NewsAdapter(newsList);
+        rvNews.setAdapter(newsAdapter);
+        rvNews.setItemAnimator(new DefaultItemAnimator());
+    }
+}
diff --git a/app/src/main/java/de/itstall/freifunkfranken/view/NextApFragment.java b/app/src/main/java/de/itstall/freifunkfranken/view/NextApFragment.java
index 1dcab18..f1ec34d 100644
--- a/app/src/main/java/de/itstall/freifunkfranken/view/NextApFragment.java
+++ b/app/src/main/java/de/itstall/freifunkfranken/view/NextApFragment.java
@@ -17,8 +17,8 @@ import java.util.Objects;
 
 import de.itstall.freifunkfranken.R;
 import de.itstall.freifunkfranken.controller.NextApAdapter;
-import de.itstall.freifunkfranken.model.AccessPoint;
 import de.itstall.freifunkfranken.controller.RequestAps;
+import de.itstall.freifunkfranken.model.AccessPoint;
 
 public class NextApFragment extends Fragment {
     private RecyclerView rvAps;
@@ -37,7 +37,6 @@ public class NextApFragment extends Fragment {
 
         sharedPreferences = rootView.getContext().getSharedPreferences("FreifunkFrankenApp", 0);
 
-
         rvAps = rootView.findViewById(R.id.rvAps);
         rvAps.setLayoutManager(new LinearLayoutManager(getActivity()));
         tvTemp = rootView.findViewById(R.id.tvTemp);
diff --git a/app/src/main/java/de/itstall/freifunkfranken/view/SsidsFragment.java b/app/src/main/java/de/itstall/freifunkfranken/view/SsidsFragment.java
index 86d43e5..3e3b777 100644
--- a/app/src/main/java/de/itstall/freifunkfranken/view/SsidsFragment.java
+++ b/app/src/main/java/de/itstall/freifunkfranken/view/SsidsFragment.java
@@ -29,7 +29,6 @@ public class SsidsFragment extends androidx.fragment.app.Fragment {
     public static List<Ssid> ssidList;
     private RecyclerView rvSsids;
     private View rootView;
-    private SsidsFragmentListener ssidsFragmentListener;
     public static final int REQUEST_ID_ACCESS_WIFI_STATE = 102;
     public static final int REQUEST_ID_CHANGE_WIFI_STATE = 103;
     public static final int REQUEST_ID_WRITE_SETTINGS = 104;
@@ -45,7 +44,7 @@ public class SsidsFragment extends androidx.fragment.app.Fragment {
         rvSsids = rootView.findViewById(R.id.rvSsids);
         rvSsids.setLayoutManager(new LinearLayoutManager(getActivity()));
 
-        ssidsFragmentListener = new SsidsFragmentListener(this);
+        SsidsFragmentListener ssidsFragmentListener = new SsidsFragmentListener(this);
 
         Button ssidsFragmentBtnAddAll = rootView.findViewById(R.id.ssidsFragmentBtnAddAll);
         ssidsFragmentBtnAddAll.setOnClickListener(ssidsFragmentListener);
diff --git a/app/src/main/res/drawable/news_border.xml b/app/src/main/res/drawable/news_border.xml
new file mode 100644
index 0000000..4f574aa
--- /dev/null
+++ b/app/src/main/res/drawable/news_border.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <stroke
+        android:width="1dp"
+        android:color="@color/freifunk_blau" />
+
+    <corners android:radius="3dp" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/layout/news_fragment.xml b/app/src/main/res/layout/news_fragment.xml
new file mode 100644
index 0000000..fd4f61a
--- /dev/null
+++ b/app/src/main/res/layout/news_fragment.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/rvNews"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"></androidx.recyclerview.widget.RecyclerView>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/news_item.xml b/app/src/main/res/layout/news_item.xml
new file mode 100644
index 0000000..f8d62ae
--- /dev/null
+++ b/app/src/main/res/layout/news_item.xml
@@ -0,0 +1,55 @@
+<?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="wrap_content"
+    android:layout_marginLeft="10dp"
+    android:layout_marginTop="10dp"
+    android:layout_marginRight="10dp"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="5dp"
+        android:layout_marginTop="4dp"
+        android:layout_marginRight="5dp"
+        android:layout_marginBottom="2dp"
+        android:background="@drawable/news_border"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="3dp"
+            android:layout_marginTop="3dp"
+            android:layout_marginRight="3dp"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/tvNewsTitle"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="4"
+                android:text="@string/newsTvTitle"
+                android:textColor="@android:color/primary_text_light" />
+
+            <TextView
+                android:id="@+id/tvNewsDate"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:text="@string/newsTvDate"
+                android:textAlignment="viewEnd" />
+        </LinearLayout>
+
+        <TextView
+            android:id="@+id/tvNewsDescription"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="3dp"
+            android:layout_marginTop="3dp"
+            android:layout_marginRight="3dp"
+            android:text="@string/newsTvDescription" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/nextap_item.xml b/app/src/main/res/layout/nextap_item.xml
index f145255..377d71f 100644
--- a/app/src/main/res/layout/nextap_item.xml
+++ b/app/src/main/res/layout/nextap_item.xml
@@ -13,18 +13,18 @@
         android:layout_weight="1">
 
         <TextView
-            android:id="@+id/tvAp"
+            android:id="@+id/tvNewsTitle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginEnd="5dp"
             android:text="@string/tabSsids"
             app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toStartOf="@+id/tvDistance"
+            app:layout_constraintEnd_toStartOf="@+id/tvNewsDate"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
 
         <TextView
-            android:id="@+id/tvDistance"
+            android:id="@+id/tvNewsDate"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             app:layout_constraintBottom_toBottomOf="parent"
diff --git a/app/src/main/res/layout/ssids_item.xml b/app/src/main/res/layout/ssids_item.xml
index bdd186f..713d38d 100644
--- a/app/src/main/res/layout/ssids_item.xml
+++ b/app/src/main/res/layout/ssids_item.xml
@@ -4,7 +4,7 @@
     android:layout_height="wrap_content">
 
     <TextView
-        android:id="@+id/tvAp"
+        android:id="@+id/tvNewsTitle"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginLeft="5dp"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fd7f8f2..0ad826a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -3,6 +3,7 @@
     <string name="tabNextAp">Nächster AP</string>
     <string name="tabSsids">SSIDs</string>
     <string name="tabKarte">Karte</string>
+    <string name="tabNews">News</string>
     <string name="btnSsidAdd">Hinzufügen</string>
     <string name="tvStatusName">Status:</string>
     <string name="statusOnline">Online</string>
@@ -33,4 +34,7 @@
     </string>
     <string name="aboutTvTitle">Über die Freifunk Franken App</string>
     <string name="popupWritePermissionFragmentTitle">Zugriff benötigt</string>
+    <string name="newsTvDescription">Meine lange Beschreibung</string>
+    <string name="newsTvTitle">Mein Titel</string>
+    <string name="newsTvDate">01.01.2020</string>
 </resources>
-- 
GitLab