mirror of https://github.com/readrops/Readrops.git
Add a basic feed request and display with some android architect components
This commit is contained in:
parent
4d1d723158
commit
88aa232f81
Binary file not shown.
2
LICENSE
2
LICENSE
|
@ -96,7 +96,7 @@ TERMS AND CONDITIONS
|
|||
12. No Surrender of Others' Freedom.
|
||||
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
|
||||
13. Use with the GNU Affero General Public License.
|
||||
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
|
||||
Notwithstanding any other provision of this License, you have permission to url or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
|
||||
14. Revised Versions of this License.
|
||||
The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
|
||||
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
|
||||
|
|
|
@ -40,4 +40,7 @@ dependencies {
|
|||
implementation 'com.squareup.retrofit2:converter-simplexml:2.4.0'
|
||||
|
||||
implementation 'com.android.support:recyclerview-v7:28.0.0'
|
||||
|
||||
implementation "android.arch.persistence.room:runtime:1.1.1"
|
||||
annotationProcessor "android.arch.persistence.room:compiler:1.1.1"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package com.readrops.app;
|
||||
|
||||
import android.app.Application;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.readrops.app.database.Database;
|
||||
import com.readrops.app.database.entities.Item;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public abstract class ARepository {
|
||||
|
||||
protected Executor executor;
|
||||
protected SimpleCallback callback;
|
||||
|
||||
protected Database database;
|
||||
|
||||
protected ARepository(Application application) {
|
||||
executor = Executors.newSingleThreadExecutor();
|
||||
this.database = Database.getInstance(application);
|
||||
}
|
||||
|
||||
public void setCallback(SimpleCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public abstract void sync();
|
||||
|
||||
public abstract void addFeed(Item item);
|
||||
|
||||
public abstract void deleteFeed(Item item);
|
||||
|
||||
public abstract void moveFeed(Item item);
|
||||
|
||||
protected void failureCallBackInMainThread(Exception ex) {
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
handler.post(() -> {
|
||||
callback.onFailure(ex);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package com.readrops.app;
|
||||
|
||||
import android.app.Application;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.os.Handler;
|
||||
|
||||
import com.readrops.app.database.Database;
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
import com.readrops.app.database.entities.Item;
|
||||
import com.readrops.readropslibrary.QueryCallback;
|
||||
import com.readrops.readropslibrary.localfeed.AItem;
|
||||
import com.readrops.readropslibrary.localfeed.RSSNetwork;
|
||||
import com.readrops.readropslibrary.localfeed.atom.ATOMEntry;
|
||||
import com.readrops.readropslibrary.localfeed.json.JSONItem;
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.readrops.readropslibrary.localfeed.RSSNetwork.RSSType.RSS_2;
|
||||
import static com.readrops.readropslibrary.localfeed.RSSNetwork.RSSType.RSS_ATOM;
|
||||
import static com.readrops.readropslibrary.localfeed.RSSNetwork.RSSType.RSS_JSON;
|
||||
|
||||
public class LocalFeedRepository extends ARepository implements QueryCallback {
|
||||
|
||||
private LiveData<List<Item>> items;
|
||||
|
||||
public LocalFeedRepository(Application application) {
|
||||
super(application);
|
||||
|
||||
items = database.itemDao().getAll();
|
||||
}
|
||||
|
||||
public LiveData<List<Item>> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync() {
|
||||
executor.execute(() -> {
|
||||
RSSNetwork request = new RSSNetwork();
|
||||
|
||||
List<Feed> feeds = database.feedDao().getAllFeeds();
|
||||
|
||||
for (Feed feed : feeds) {
|
||||
try {
|
||||
request.request(feed.getUrl(), this);
|
||||
} catch (Exception e) {
|
||||
failureCallBackInMainThread(e);
|
||||
}
|
||||
}
|
||||
|
||||
callback.onSuccess();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeed(Item item) {
|
||||
executor.execute(() -> {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteFeed(Item item) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveFeed(Item item) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onSyncSuccess(List<? extends AItem> items, RSSNetwork.RSSType type, String feedUrl) {
|
||||
switch (type) {
|
||||
case RSS_2:
|
||||
List<RSSItem> rssItems = (List<RSSItem>)items;
|
||||
parseRSSItems(rssItems, feedUrl);
|
||||
break;
|
||||
case RSS_ATOM:
|
||||
List<ATOMEntry> atomItems = (List<ATOMEntry>)items;
|
||||
parseATOMItems(atomItems, feedUrl);
|
||||
break;
|
||||
case RSS_JSON:
|
||||
List<JSONItem> jsonItems = (List<JSONItem>)items;
|
||||
parseJSONItems(jsonItems, feedUrl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSyncFailure(Exception ex) {
|
||||
failureCallBackInMainThread(ex);
|
||||
}
|
||||
|
||||
private void parseRSSItems(List<RSSItem> items, String feedUrl) {
|
||||
Feed feed = database.feedDao().getFeedByUrl(feedUrl);
|
||||
|
||||
List<Item> dbItems = Item.itemsFromRSS(items, feed);
|
||||
|
||||
for (Item dbItem : dbItems) {
|
||||
if (!Boolean.valueOf(database.itemDao().guidExist(dbItem.getGuid())))
|
||||
database.itemDao().insert(dbItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseATOMItems(List<ATOMEntry> items, String feedUrl) {
|
||||
Feed feed = database.feedDao().getFeedByUrl(feedUrl);
|
||||
|
||||
List<Item> dbItems = Item.itemsFromATOM(items, feed);
|
||||
|
||||
for (Item dbItem : dbItems) {
|
||||
if (!Boolean.valueOf(database.itemDao().guidExist(dbItem.getGuid())))
|
||||
database.itemDao().insert(dbItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseJSONItems(List<JSONItem> items, String feedUrl) {
|
||||
Feed feed = database.feedDao().getFeedByUrl(feedUrl);
|
||||
|
||||
List<Item> dbItems = Item.itemsFromJSON(items, feed);
|
||||
|
||||
for (Item dbItem : dbItems) {
|
||||
if (!Boolean.valueOf(database.itemDao().guidExist(dbItem.getGuid())))
|
||||
database.itemDao().insert(dbItem);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.readrops.app;
|
||||
|
||||
import android.arch.lifecycle.ViewModelProvider;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.DividerItemDecoration;
|
||||
|
@ -7,9 +8,15 @@ import android.support.v7.widget.LinearLayoutManager;
|
|||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
|
||||
import com.readrops.app.database.entities.Item;
|
||||
import com.readrops.readropslibrary.PageParser;
|
||||
import com.readrops.readropslibrary.QueryCallback;
|
||||
import com.readrops.readropslibrary.Utils.Utils;
|
||||
import com.readrops.readropslibrary.localfeed.AItem;
|
||||
import com.readrops.readropslibrary.localfeed.RSSNetwork;
|
||||
import com.readrops.readropslibrary.localfeed.atom.ATOMEntry;
|
||||
import com.readrops.readropslibrary.localfeed.json.JSONFeed;
|
||||
import com.readrops.readropslibrary.localfeed.json.JSONItem;
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSFeed;
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSItem;
|
||||
|
||||
|
@ -31,8 +38,9 @@ public class MainActivity extends AppCompatActivity {
|
|||
private RecyclerView recyclerView;
|
||||
private MainAdapter adapter;
|
||||
|
||||
private List<RSSItem> itemList;
|
||||
private List<Item> itemList;
|
||||
|
||||
private MainViewModel viewModel;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -50,42 +58,14 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
thread.start();*/
|
||||
|
||||
getItems();
|
||||
viewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication()).create(MainViewModel.class);
|
||||
|
||||
}
|
||||
|
||||
private void getItems() {
|
||||
RSSNetwork request = new RSSNetwork();
|
||||
|
||||
request.request("https://www.numerama.com/feed/", new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
InputStream stream = response.body().byteStream();
|
||||
String xml = Utils.inputStreamToString(stream);
|
||||
|
||||
Serializer serializer = new Persister();
|
||||
|
||||
try {
|
||||
RSSFeed rssFeed = serializer.read(RSSFeed.class, xml);
|
||||
itemList = rssFeed.getChannel().getItems();
|
||||
|
||||
runOnUiThread(() -> {
|
||||
viewModel.getItems().observe(this, (List<Item> items) -> {
|
||||
this.itemList = items;
|
||||
initRecyclerView();
|
||||
});
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
viewModel.sync();
|
||||
}
|
||||
|
||||
private void initRecyclerView() {
|
||||
|
@ -99,6 +79,4 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.widget.ImageView;
|
|||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.readrops.app.database.entities.Item;
|
||||
import com.readrops.readropslibrary.PageParser;
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSItem;
|
||||
|
||||
|
@ -19,10 +20,10 @@ import java.util.List;
|
|||
|
||||
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {
|
||||
|
||||
List<RSSItem> items;
|
||||
List<Item> items;
|
||||
private Context context;
|
||||
|
||||
public MainAdapter(Context context, List<RSSItem> items) {
|
||||
public MainAdapter(Context context, List<Item> items) {
|
||||
this.context = context;
|
||||
this.items = items;
|
||||
}
|
||||
|
@ -38,13 +39,13 @@ public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
|
||||
RSSItem item = items.get(i);
|
||||
Item item = items.get(i);
|
||||
viewHolder.bind(item);
|
||||
|
||||
Thread thread = new Thread(() -> {
|
||||
/*Thread thread = new Thread(() -> {
|
||||
String imageUrl = PageParser.getOGImageLink(item.getLink());
|
||||
Glide.with(context).load(imageUrl).into(viewHolder.itemImage);
|
||||
});
|
||||
});*/
|
||||
|
||||
|
||||
}
|
||||
|
@ -66,7 +67,7 @@ public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {
|
|||
itemImage = itemView.findViewById(R.id.item_image);
|
||||
}
|
||||
|
||||
private void bind(RSSItem item) {
|
||||
private void bind(Item item) {
|
||||
itemTitle.setText(item.getTitle());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package com.readrops.app;
|
||||
|
||||
import android.app.Application;
|
||||
import android.arch.lifecycle.AndroidViewModel;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.readrops.app.database.entities.Item;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MainViewModel extends AndroidViewModel implements SimpleCallback {
|
||||
|
||||
private LiveData<List<Item>> items;
|
||||
private LocalFeedRepository repository;
|
||||
|
||||
public MainViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
|
||||
repository = new LocalFeedRepository(application);
|
||||
repository.setCallback(this);
|
||||
items = repository.getItems();
|
||||
}
|
||||
|
||||
public LiveData<List<Item>> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void sync() {
|
||||
repository.sync();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception ex) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.readrops.app;
|
||||
|
||||
public interface SimpleCallback {
|
||||
|
||||
void onSuccess();
|
||||
|
||||
void onFailure(Exception ex);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.readrops.app.database;
|
||||
|
||||
import android.arch.persistence.db.SupportSQLiteDatabase;
|
||||
import android.arch.persistence.room.Room;
|
||||
import android.arch.persistence.room.RoomDatabase;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.readrops.app.database.dao.FeedDao;
|
||||
import com.readrops.app.database.dao.ItemDao;
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
import com.readrops.app.database.entities.Item;
|
||||
|
||||
|
||||
@android.arch.persistence.room.Database(entities = {Feed.class, Item.class}, version = 1)
|
||||
public abstract class Database extends RoomDatabase {
|
||||
|
||||
public abstract FeedDao feedDao();
|
||||
|
||||
public abstract ItemDao itemDao();
|
||||
|
||||
private static Database database;
|
||||
|
||||
public static Database getInstance(Context context) {
|
||||
if (database == null)
|
||||
database = Room.databaseBuilder(context, Database.class, "readrops-db").addCallback(roomCallback).build();
|
||||
|
||||
return database;
|
||||
}
|
||||
|
||||
public static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
|
||||
@Override
|
||||
public void onCreate(@NonNull SupportSQLiteDatabase db) {
|
||||
super.onCreate(db);
|
||||
|
||||
Feed feed1 = new Feed("XDA Developers", "desc", "https://www.xda-developers.com/feed/");
|
||||
|
||||
new Thread(() -> database.feedDao().insert(feed1)).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(@NonNull SupportSQLiteDatabase db) {
|
||||
super.onOpen(db);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.readrops.app.database.dao;
|
||||
|
||||
|
||||
import android.arch.persistence.room.Dao;
|
||||
import android.arch.persistence.room.Insert;
|
||||
import android.arch.persistence.room.Query;
|
||||
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Dao
|
||||
public interface FeedDao {
|
||||
|
||||
@Query("Select * from Feed")
|
||||
List<Feed> getAllFeeds();
|
||||
|
||||
@Insert
|
||||
void insert(Feed feed);
|
||||
|
||||
@Query("Select count(*) from Feed")
|
||||
int getFeedCount();
|
||||
|
||||
@Query("Select * from Feed Where url = :feedUrl")
|
||||
Feed getFeedByUrl(String feedUrl);
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.readrops.app.database.dao;
|
||||
|
||||
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.persistence.room.Dao;
|
||||
import android.arch.persistence.room.Insert;
|
||||
import android.arch.persistence.room.Query;
|
||||
|
||||
import com.readrops.app.database.entities.Item;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Dao
|
||||
public interface ItemDao {
|
||||
|
||||
@Query("Select * from Item Where feed_id = :feedId")
|
||||
LiveData<List<Item>> getAllByFeed(int feedId);
|
||||
|
||||
@Query("Select * from Item")
|
||||
LiveData<List<Item>> getAll();
|
||||
|
||||
@Query("Select case When :guid In (Select guid from Item) Then 'true' else 'false' end")
|
||||
String guidExist(String guid);
|
||||
|
||||
@Insert
|
||||
void insert(Item item);
|
||||
|
||||
@Insert
|
||||
void insertAll(List<Item> items);
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.readrops.app.database.entities;
|
||||
|
||||
|
||||
import android.arch.persistence.room.*;
|
||||
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSChannel;
|
||||
|
||||
@Entity
|
||||
public class Feed {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
private int id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private String url;
|
||||
|
||||
public Feed() {
|
||||
|
||||
}
|
||||
|
||||
public Feed(String name, String description, String url) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static Feed feedFromRSS(RSSChannel channel) {
|
||||
Feed feed = new Feed();
|
||||
|
||||
feed.setUrl(channel.getLink());
|
||||
feed.setDescription(channel.getDescription());
|
||||
|
||||
return feed;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
package com.readrops.app.database.entities;
|
||||
|
||||
import android.arch.persistence.room.*;
|
||||
|
||||
import com.readrops.readropslibrary.localfeed.atom.ATOMEntry;
|
||||
import com.readrops.readropslibrary.localfeed.json.JSONItem;
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSChannel;
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
@Entity
|
||||
(foreignKeys = @ForeignKey(entity = Feed.class, parentColumns = "id", childColumns = "feed_id"))
|
||||
public class Item {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
private int id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String description;
|
||||
|
||||
private String link;
|
||||
|
||||
@ColumnInfo(name = "image_link")
|
||||
private String imageLink;
|
||||
|
||||
private String author;
|
||||
|
||||
@ColumnInfo(name = "pub_date")
|
||||
private String pubDate;
|
||||
|
||||
private String content;
|
||||
|
||||
@ColumnInfo(name = "feed_id", index = true)
|
||||
private int feedId;
|
||||
|
||||
@ColumnInfo(index = true)
|
||||
private String guid;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
public void setLink(String link) {
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
public String getImageLink() {
|
||||
return imageLink;
|
||||
}
|
||||
|
||||
public void setImageLink(String imageLink) {
|
||||
this.imageLink = imageLink;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getPubDate() {
|
||||
return pubDate;
|
||||
}
|
||||
|
||||
public void setPubDate(String pubDate) {
|
||||
this.pubDate = pubDate;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getGuid() {
|
||||
return guid;
|
||||
}
|
||||
|
||||
public void setGuid(String guid) {
|
||||
this.guid = guid;
|
||||
}
|
||||
|
||||
public int getFeedId() {
|
||||
return feedId;
|
||||
}
|
||||
|
||||
public void setFeedId(int feedId) {
|
||||
this.feedId = feedId;
|
||||
}
|
||||
|
||||
public static List<Item> itemsFromRSS(List<RSSItem> items, Feed feed) {
|
||||
List<Item> dbItems = new ArrayList<>();
|
||||
|
||||
for(RSSItem item : items) {
|
||||
Item newItem = new Item();
|
||||
|
||||
newItem.setAuthor(item.getAuthor());
|
||||
newItem.setContent(item.getContent());
|
||||
newItem.setDescription(item.getDescription());
|
||||
newItem.setGuid(item.getGuid());
|
||||
newItem.setTitle(item.getTitle());
|
||||
newItem.setImageLink(item.getImageLink());
|
||||
newItem.setPubDate(item.getPubDate());
|
||||
newItem.setLink(item.getLink());
|
||||
|
||||
newItem.setFeedId(feed.getId());
|
||||
|
||||
dbItems.add(newItem);
|
||||
}
|
||||
|
||||
return dbItems;
|
||||
}
|
||||
|
||||
public static List<Item> itemsFromATOM(List<ATOMEntry> items, Feed feed) {
|
||||
List<Item> dbItems = new ArrayList<>();
|
||||
|
||||
for (ATOMEntry item : items) {
|
||||
Item dbItem = new Item();
|
||||
|
||||
dbItem.setContent(item.getContent());
|
||||
dbItem.setDescription(item.getSummary());
|
||||
dbItem.setGuid(item.getId());
|
||||
dbItem.setTitle(item.getTitle());
|
||||
dbItem.setPubDate(item.getUpdated());
|
||||
dbItem.setLink(item.getLink().getHref());
|
||||
|
||||
dbItem.setFeedId(feed.getId());
|
||||
}
|
||||
|
||||
return dbItems;
|
||||
}
|
||||
|
||||
public static List<Item> itemsFromJSON(List<JSONItem> items, Feed feed) {
|
||||
List<Item> dbItems = new ArrayList<>();
|
||||
|
||||
for (JSONItem item : items) {
|
||||
Item dbItem = new Item();
|
||||
|
||||
dbItem.setAuthor(item.getAuthor().getName());
|
||||
dbItem.setContent(item.getContent());
|
||||
dbItem.setDescription(item.getSummary());
|
||||
dbItem.setGuid(item.getId());
|
||||
dbItem.setTitle(item.getTitle());
|
||||
dbItem.setPubDate(item.getPubDate());
|
||||
dbItem.setLink(item.getUrl());
|
||||
|
||||
dbItem.setFeedId(feed.getId());
|
||||
}
|
||||
|
||||
return dbItems;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#Tue Jan 15 18:55:37 GMT 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
# Resolve links: $0 may be a url
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
url=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$url" : '/.*' > /dev/null; then
|
||||
PRG="$url"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
PRG=`dirname "$PRG"`"/$url"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.readrops.readropslibrary;
|
||||
|
||||
import com.readrops.readropslibrary.localfeed.AItem;
|
||||
import com.readrops.readropslibrary.localfeed.RSSNetwork;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface QueryCallback {
|
||||
|
||||
void onSyncSuccess(List<? extends AItem> items, RSSNetwork.RSSType type, String feedUrl);
|
||||
|
||||
void onSyncFailure(Exception ex);
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.readrops.readropslibrary.localfeed;
|
||||
|
||||
/**
|
||||
* Just an abstract class to wrap the three rss items types
|
||||
*/
|
||||
public abstract class AItem {
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.readrops.readropslibrary.localfeed;
|
||||
|
||||
public interface OperationCallback {
|
||||
|
||||
void onSuccess();
|
||||
|
||||
void OnFailure();
|
||||
}
|
|
@ -1,16 +1,83 @@
|
|||
package com.readrops.readropslibrary.localfeed;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.readrops.readropslibrary.QueryCallback;
|
||||
import com.readrops.readropslibrary.Utils.Utils;
|
||||
import com.readrops.readropslibrary.localfeed.atom.ATOMFeed;
|
||||
import com.readrops.readropslibrary.localfeed.json.JSONFeed;
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSFeed;
|
||||
|
||||
import org.simpleframework.xml.Serializer;
|
||||
import org.simpleframework.xml.core.Persister;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class RSSNetwork {
|
||||
|
||||
public void request(String url, okhttp3.Callback callback) {
|
||||
/**
|
||||
* Request the url given in parameter.
|
||||
* This method is synchronous, <b>it has to be called from another thread than the main one</b>.
|
||||
* @param url url to request
|
||||
* @param callback result callback if success or error
|
||||
* @throws Exception
|
||||
*/
|
||||
public void request(String url, final QueryCallback callback) throws Exception {
|
||||
OkHttpClient okHttpClient = new OkHttpClient();
|
||||
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
|
||||
okHttpClient.newCall(request).enqueue(callback);
|
||||
if (response.isSuccessful())
|
||||
parseFeed(response.body().byteStream(), getRSSType(response.header("content-type")), callback, url);
|
||||
else
|
||||
callback.onSyncFailure(new Exception("Error " + response.code() + " when requesting url " + url));
|
||||
}
|
||||
|
||||
private void parseFeed(InputStream stream, RSSType type, QueryCallback callback, String url) throws Exception {
|
||||
//String xml = Utils.inputStreamToString(stream);
|
||||
Serializer serializer = new Persister();
|
||||
|
||||
switch (type) {
|
||||
case RSS_2:
|
||||
RSSFeed rssFeed = serializer.read(RSSFeed.class, stream);
|
||||
callback.onSyncSuccess(rssFeed.getChannel().getItems(), type, url);
|
||||
break;
|
||||
case RSS_ATOM:
|
||||
ATOMFeed atomFeed = serializer.read(ATOMFeed.class, stream);
|
||||
callback.onSyncSuccess(atomFeed.getEntries(), type, url);
|
||||
break;
|
||||
case RSS_JSON:
|
||||
Gson gson = new Gson();
|
||||
JSONFeed feed = gson.fromJson(Utils.inputStreamToString(stream), JSONFeed.class);
|
||||
callback.onSyncSuccess(feed.getItems(), type, url);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private RSSType getRSSType(String contentType) {
|
||||
if (contentType.contains(RSSType.RSS_2.value))
|
||||
return RSSType.RSS_2;
|
||||
else if (contentType.contains(RSSType.RSS_ATOM.value))
|
||||
return RSSType.RSS_ATOM;
|
||||
else
|
||||
return RSSType.RSS_JSON;
|
||||
}
|
||||
|
||||
public enum RSSType {
|
||||
RSS_2("rss"),
|
||||
RSS_ATOM("atom"),
|
||||
RSS_JSON("json");
|
||||
|
||||
private String value;
|
||||
|
||||
RSSType(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package com.readrops.readropslibrary.localfeed.atom;
|
||||
|
||||
import com.readrops.readropslibrary.localfeed.AItem;
|
||||
|
||||
import org.simpleframework.xml.Attribute;
|
||||
import org.simpleframework.xml.Element;
|
||||
import org.simpleframework.xml.Root;
|
||||
|
||||
@Root(name = "entry", strict = false)
|
||||
public class ATOMEntry {
|
||||
public class ATOMEntry extends AItem {
|
||||
|
||||
@Element(required = false)
|
||||
private String title;
|
||||
|
@ -19,11 +21,68 @@ public class ATOMEntry {
|
|||
@Element(required = false)
|
||||
private String summary;
|
||||
|
||||
@Element(required = false)
|
||||
private String id;
|
||||
|
||||
@Element(required = false)
|
||||
private String content;
|
||||
|
||||
@Attribute(name = "type", required = false)
|
||||
private String contentType;
|
||||
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public ATOMLink getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
public void setLink(ATOMLink link) {
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
public String getUpdated() {
|
||||
return updated;
|
||||
}
|
||||
|
||||
public void setUpdated(String updated) {
|
||||
this.updated = updated;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return summary;
|
||||
}
|
||||
|
||||
public void setSummary(String summary) {
|
||||
this.summary = summary;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public void setContentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,4 +27,51 @@ public class ATOMFeed {
|
|||
@ElementList(inline = true, required = false)
|
||||
private List<ATOMEntry> entries;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
public void setLink(String link) {
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
public String getSubtitle() {
|
||||
return subtitle;
|
||||
}
|
||||
|
||||
public void setSubtitle(String subtitle) {
|
||||
this.subtitle = subtitle;
|
||||
}
|
||||
|
||||
public String getUpdated() {
|
||||
return updated;
|
||||
}
|
||||
|
||||
public void setUpdated(String updated) {
|
||||
this.updated = updated;
|
||||
}
|
||||
|
||||
public ATOMAuthor getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(ATOMAuthor author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public List<ATOMEntry> getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
public void setEntries(List<ATOMEntry> entries) {
|
||||
this.entries = entries;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,4 +12,6 @@ public class ATOMLink {
|
|||
public String getHref() {
|
||||
return href;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -34,4 +34,6 @@ public class JSONAuthor {
|
|||
public void setAvatarUrl(String avatarUrl) {
|
||||
this.avatarUrl = avatarUrl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package com.readrops.readropslibrary.localfeed.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.readrops.readropslibrary.localfeed.AItem;
|
||||
|
||||
public class JSONItem {
|
||||
public class JSONItem extends AItem {
|
||||
|
||||
private String id;
|
||||
|
||||
|
@ -104,6 +105,14 @@ public class JSONItem {
|
|||
this.author = author;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
if (contentHtml == null)
|
||||
return contentText;
|
||||
else
|
||||
return contentHtml;
|
||||
|
||||
}
|
||||
|
||||
@SerializedName("date_modified")
|
||||
private String modDate;
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package com.readrops.readropslibrary.localfeed.rss;
|
||||
|
||||
import com.readrops.readropslibrary.localfeed.AItem;
|
||||
|
||||
import org.simpleframework.xml.Element;
|
||||
import org.simpleframework.xml.Namespace;
|
||||
import org.simpleframework.xml.Root;
|
||||
|
||||
@Root(name = "item", strict = false)
|
||||
public class RSSItem {
|
||||
public class RSSItem extends AItem {
|
||||
|
||||
@Element(name = "title", required = false)
|
||||
private String title;
|
||||
|
|
Loading…
Reference in New Issue