Skip to content
This repository was archived by the owner on Mar 26, 2019. It is now read-only.

Commit d1db67d

Browse files
author
Bademus
committed
Fetching image from article wip
1 parent c6dbe31 commit d1db67d

File tree

6 files changed

+272
-222
lines changed

6 files changed

+272
-222
lines changed

feedly-andrss/src/main/java/org/github/bademux/feedly/andrss/helpers/FeedlyContentAdapter.java

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@
3939

4040
import android.content.Context;
4141
import android.database.Cursor;
42+
import android.graphics.drawable.Drawable;
4243
import android.net.Uri;
4344
import android.text.Html;
45+
import android.util.Log;
4446
import android.view.View;
4547
import android.widget.ImageView;
4648
import android.widget.SimpleCursorAdapter;
@@ -49,6 +51,8 @@
4951
import org.github.bademux.feedly.andrss.R;
5052
import org.github.bademux.feedly.api.util.db.BackgroundQueryHandler;
5153

54+
import java.io.FileNotFoundException;
55+
import java.io.InputStream;
5256
import java.text.DateFormat;
5357
import java.util.Date;
5458

@@ -65,7 +69,7 @@ public FeedlyContentAdapter(final Context context, final BackgroundQueryHandler
6569
mDateFormat = android.text.format.DateFormat.getDateFormat(context);
6670
setViewBinder(createBinder());
6771
mQueryHandler = queryHandler;
68-
72+
mContext = context;
6973
token = mQueryHandler.addQueryListener(this);
7074
}
7175

@@ -80,52 +84,84 @@ public void startQueryOnFeed(String uri) {
8084
}
8185

8286
@Override
83-
public void onQueryComplete(final int token, final Object cookie,
84-
final Cursor cursor) { changeCursor(cursor); }
87+
public void onQueryComplete(final int token, final Object cookie, final Cursor cursor) {
88+
changeCursor(cursor);
89+
}
8590

8691
public ViewBinder createBinder() {
8792
return new ViewBinder() {
8893
@Override
8994
public boolean setViewValue(final View view, final Cursor cursor, final int columnIndex) {
9095
switch (view.getId()) {
9196
case R.id.content_list_visual:
92-
String uriString = cursor.getString(columnIndex);
93-
if (uriString != null) {
94-
Uri uri = Files.CONTENT_URI.buildUpon().appendPath(uriString).build();
95-
((ImageView) view).setImageURI(uri);
96-
}
97-
return true;
97+
handleVisual((ImageView) view, cursor.getString(columnIndex)); return true;
9898
case R.id.content_list_summary:
99-
String text = cursor.getString(columnIndex);
100-
if (text != null) {
101-
((TextView) view).setText(Html.fromHtml(text) + "...");
102-
}
103-
return true;
99+
handleSummary((TextView) view, cursor.getString(columnIndex)); return true;
104100
case R.id.content_list_meta_crawled:
105-
Long timestamp = cursor.getLong(columnIndex);
106-
if (timestamp != null) {
107-
synchronized (mDateFormat) {
108-
((TextView) view).setText(mDateFormat.format(new Date(timestamp)));
109-
}
110-
}
111-
return true;
101+
handleCrawled((TextView) view, cursor.getLong(columnIndex)); return true;
112102
default:
113103
}
114-
115104
return false;
116105
}
117106
};
118107
}
119108

109+
protected void handleCrawled(final TextView view, final Long timestamp) {
110+
if (timestamp == null) {
111+
return;
112+
}
113+
synchronized (mDateFormat) {
114+
view.setText(mDateFormat.format(new Date(timestamp)));
115+
}
116+
}
117+
118+
protected void handleSummary(final TextView view, final String text) {
119+
if (text == null) {
120+
return;
121+
}
122+
view.setText(Html.fromHtml(text, imageGetter, null));
123+
}
124+
125+
protected void handleVisual(final ImageView view, final String source) {
126+
Drawable d = imageGetter.getDrawable(source);
127+
if (d == null) {
128+
view.setVisibility(View.GONE);
129+
} else {
130+
view.setImageDrawable(d);
131+
}
132+
}
133+
120134

121135
private final BackgroundQueryHandler mQueryHandler;
122136

123137
private final DateFormat mDateFormat;
124138

139+
private final Context mContext;
140+
125141
private int token;
142+
143+
private final Html.ImageGetter imageGetter = new Html.ImageGetter() {
144+
@Override
145+
public synchronized Drawable getDrawable(final String source) {
146+
if (source != null) {
147+
return null;
148+
}
149+
150+
Uri uri = Files.CONTENT_URI.buildUpon().appendPath(source).build();
151+
try {
152+
InputStream stream = mContext.getContentResolver().openInputStream(uri);
153+
return Drawable.createFromStream(stream, null);
154+
} catch (FileNotFoundException e) {
155+
Log.e(TAG, "content_list_visual is missing", e);
156+
}
157+
158+
return null;
159+
}
160+
};
161+
126162
private static final String[] FROM = new String[]{Entries.TITLE,
127163
Entries.VISUAL_URL,
128-
"substr(" + Entries.SUMMARY + ",1,150)",
164+
Entries.SUMMARY,
129165
Entries.ENGAGEMENT,
130166
Entries.ORIGIN_TITLE,
131167
Entries.AUTHOR,
@@ -139,4 +175,7 @@ public boolean setViewValue(final View view, final Cursor cursor, final int colu
139175
R.id.content_list_meta_src_title,
140176
R.id.content_list_meta_author,
141177
R.id.content_list_meta_crawled};
178+
179+
180+
static final String TAG = "FeedlyContentAdapter";
142181
}

feedly-andrss/src/main/java/org/github/bademux/feedly/provider/FeedlyCacheProvider.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public class FeedlyCacheProvider extends ContentProvider {
7575
URI_MATCHER.addURI(AUTHORITY, Tags.TBL_NAME + "/#", Code.TAG);
7676
URI_MATCHER.addURI(AUTHORITY, Tags.TBL_NAME, Code.TAGS);
7777
URI_MATCHER.addURI(AUTHORITY, Files.TBL_NAME + "/notcached", Code.FILE_NOT_CACHED);
78+
URI_MATCHER.addURI(AUTHORITY, Files.TBL_NAME + "/#", Code.FILE_BY_ID);
7879
URI_MATCHER.addURI(AUTHORITY, Files.TBL_NAME + "/*", Code.FILE);
7980
URI_MATCHER.addURI(AUTHORITY, Files.TBL_NAME, Code.FILES);
8081
}
@@ -120,18 +121,22 @@ public Cursor query(Uri uri, String[] projection, String selection, String[] sel
120121
return db.query(Categories.TBL_NAME, merge(projection, "rowid as _id"),
121122
selection, selectionArgs, null, null, sortOrder);
122123
case Code.TAG:
123-
return db.query(Tags.TBL_NAME, projection, selection, selectionArgs,
124-
null, null, null);
124+
return db.query(Tags.TBL_NAME, projection, selection, selectionArgs, null, null, null);
125125
case Code.TAGS:
126126
return db.query(Tags.TBL_NAME, merge(projection, "rowid as _id"),
127127
selection, selectionArgs, null, null, sortOrder);
128128
case Code.FILE:
129129
return db.query(Files.TBL_NAME, projection,
130130
Files.URL + "=?", new String[]{uri.getLastPathSegment()}, null, null, null);
131+
case Code.FILE_BY_ID:
132+
return db.query(Files.TBL_NAME, projection,
133+
Files.ID + "=?", new String[]{uri.getLastPathSegment()}, null, null, null);
131134
case Code.FILE_NOT_CACHED:
132-
return db.query(Files.TBL_NAME, new String[]{"rowid as _id", Files.URL},
135+
return db.query(Files.TBL_NAME, new String[]{Files.ID, Files.URL},
133136
Files.FILENAME + " IS NULL", null, null, null, null);
134137
case Code.AUTHORITY: return null;
138+
case UriMatcher.NO_MATCH:
139+
throw new UnsupportedOperationException("Unmatched Uri");
135140
default:
136141
throw new UnsupportedOperationException("Unsupported Uri " + uri);
137142
}
@@ -176,6 +181,7 @@ public int delete(final Uri uri, final String selection, final String[] selectio
176181
assert db != null;
177182
switch (URI_MATCHER.match(uri)) {
178183
case Code.ENTRIES:
184+
//TODO: delete cached files - use files_by_entries table
179185
return db.delete(Entries.TBL_NAME, selection, selectionArgs);
180186
case Code.FEEDS:
181187
return db.delete(Feeds.TBL_NAME, selection, selectionArgs);
@@ -187,6 +193,8 @@ public int delete(final Uri uri, final String selection, final String[] selectio
187193
return db.delete(Tags.TBL_NAME, selection, selectionArgs);
188194
case Code.ENTRIES_TAGS:
189195
return db.delete(EntriesTags.TBL_NAME, selection, selectionArgs);
196+
case UriMatcher.NO_MATCH:
197+
throw new UnsupportedOperationException("Unmatched Uri");
190198
default:
191199
throw new UnsupportedOperationException("Unsupported Uri " + uri);
192200
}
@@ -209,6 +217,8 @@ public int update(final Uri uri, final ContentValues values,
209217
case Code.FILE:
210218
return db.update(Files.TBL_NAME, values, Files.URL + "=?",
211219
new String[]{uri.getLastPathSegment()});
220+
case UriMatcher.NO_MATCH:
221+
throw new UnsupportedOperationException("Unmatched Uri");
212222
default:
213223
throw new UnsupportedOperationException("Unsupported Uri " + uri);
214224
}
@@ -393,6 +403,6 @@ private interface Code {
393403
static final int FEEDS_CATEGORIES = 300, ENTRIES_TAGS = 301;
394404
static final int TAGS = 400, TAG = 401;
395405
static final int ENTRIES = 500, ENTRY = 501, ENTRIES_BY_TAG = 502, ENTRIES_BY_CATEGORY = 503;
396-
static final int FILES = 600, FILE = 601, FILE_NOT_CACHED = 602;
406+
static final int FILES = 600, FILE = 601, FILE_BY_ID = 602, FILE_NOT_CACHED = 603;
397407
}
398408
}

feedly-andrss/src/main/java/org/github/bademux/feedly/service/FeedlyCacheService.java

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -76,48 +76,59 @@ private void handleIntent(final Intent intent, final ContentResolver contentReso
7676
return;
7777
}
7878
switch (action) {
79-
case ACTION_FETCH_SUBSCRIPTION:
80-
List<Subscription> subscriptions = mFeedlyUtil.service().subscriptions().list().execute();
81-
if (subscriptions != null) {
82-
processSubscriptions(contentResolver, subscriptions);
83-
}
79+
case ACTION_FETCH_SUBSCRIPTION: fetchSubscriptions(contentResolver);
8480
case ServiceManager.ACTION_REFRESH:
85-
case ACTION_FETCH_ENTRIES:
86-
Feedly service = mFeedlyUtil.service();
87-
Feedly.Streams.Contents request = service.streams().contents(service.newCategory(ALL));
88-
EntriesResponse result = request.execute();
89-
if (result != null) {
90-
processEntries(contentResolver, result.items());
91-
}
92-
case ACTION_DOWNLOAD: //Get all not cached files
93-
Uri notcachedUri = Files.CONTENT_URI.buildUpon().appendPath("notcached").build();
94-
Cursor c = contentResolver.query(notcachedUri, null, null, null, null);
95-
if (c.moveToFirst()) {
96-
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
97-
do {
98-
long fileId = c.getLong(c.getColumnIndex(Files.ID));
99-
Uri uri = Uri.parse(c.getString(c.getColumnIndex(Files.URL)));
100-
Uri destinationUri = Uri.fromFile(getExternalCacheDir()).buildUpon()
101-
.appendPath("file-" + fileId).build();
102-
dm.enqueue(new Request(uri).setDestinationUri(destinationUri)
103-
.setVisibleInDownloadsUi(false)
104-
.setNotificationVisibility(Request.VISIBILITY_HIDDEN));
105-
} while (c.moveToNext());
106-
}
107-
break;
108-
case ACTION_DOWNLOAD_COMPLETED:
109-
String url = intent.getStringExtra(FeedlyCacheService.EXTRA_URL);
110-
ContentValues values = new ContentValues(2);
111-
values.put(Files.FILENAME, intent.getStringExtra(FeedlyCacheService.EXTRA_FILENAME));
112-
values.put(Files.MIME, intent.getStringExtra(FeedlyCacheService.EXTRA_MIME));
113-
Uri updateUri = Files.CONTENT_URI.buildUpon().appendPath(url).build();
114-
contentResolver.update(updateUri, values, null, null);
115-
break;
81+
case ACTION_FETCH_ENTRIES: fetchEntries(contentResolver);
82+
case ACTION_DOWNLOAD: download(contentResolver); break;
83+
case ACTION_DOWNLOAD_COMPLETED: completeDownload(intent, contentResolver); break;
11684
default:
11785
Log.d(TAG, "unknown action" + action);
11886
}
11987
}
12088

89+
protected void fetchSubscriptions(final ContentResolver contentResolver) throws IOException {
90+
List<Subscription> subscriptions = mFeedlyUtil.service().subscriptions().list().execute();
91+
if (subscriptions != null) {
92+
processSubscriptions(contentResolver, subscriptions);
93+
}
94+
}
95+
96+
protected void fetchEntries(final ContentResolver contentResolver) throws IOException {
97+
Feedly service = mFeedlyUtil.service();
98+
Feedly.Streams.Contents request = service.streams().contents(service.newCategory(ALL));
99+
EntriesResponse result = request.execute();
100+
if (result != null) {
101+
processEntries(contentResolver, result.items());
102+
}
103+
}
104+
105+
protected void download(final ContentResolver contentResolver) {
106+
//Get all files that were not cached
107+
Uri notcachedUri = Files.CONTENT_URI.buildUpon().appendPath("notcached").build();
108+
Cursor c = contentResolver.query(notcachedUri, null, null, null, null);
109+
if (c.moveToFirst()) {
110+
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
111+
112+
do {
113+
Uri srcUri = Uri.parse(c.getString(c.getColumnIndex(Files.URL)));
114+
115+
String fileId = String.valueOf(c.getLong(c.getColumnIndex(Files.ID)));
116+
Uri destUri = Uri.fromFile(getExternalCacheDir()).buildUpon().appendPath(fileId).build();
117+
dm.enqueue(new Request(srcUri).setDestinationUri(destUri)
118+
.setVisibleInDownloadsUi(false)
119+
.setNotificationVisibility(Request.VISIBILITY_HIDDEN));
120+
} while (c.moveToNext());
121+
}
122+
}
123+
124+
protected void completeDownload(final Intent intent, final ContentResolver contentResolver) {
125+
String url = intent.getStringExtra(FeedlyCacheService.EXTRA_URL);
126+
ContentValues values = new ContentValues(2);
127+
values.put(Files.FILENAME, intent.getStringExtra(FeedlyCacheService.EXTRA_FILENAME));
128+
values.put(Files.MIME, intent.getStringExtra(FeedlyCacheService.EXTRA_MIME));
129+
Uri updateUri = Files.CONTENT_URI.buildUpon().appendPath(url).build();
130+
contentResolver.update(updateUri, values, null, null);
131+
}
121132

122133
public FeedlyCacheService() { super(TAG); }
123134

feedly-andrss/src/main/res/layout/fragment_content_list_item_simple.xml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,30 @@
2222
android:layout_height="match_parent"
2323
android:orientation="vertical">
2424

25-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
25+
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
2626
android:orientation="horizontal"
2727
android:layout_width="match_parent"
2828
android:layout_height="wrap_content">
2929

3030
<ImageView android:id="@+id/content_list_visual"
31-
android:layout_width="wrap_content"
31+
android:layout_width="match_parent"
3232
android:layout_height="wrap_content"
33-
android:minWidth="50dp"
34-
android:maxWidth="50dp"
33+
android:scaleType="fitXY"
34+
android:adjustViewBounds="true"
3535
android:src="@drawable/ic_launcher"
3636
android:contentDescription="@string/desc_content_list_thumbnail"/>
3737

3838
<TextView android:id="@+id/content_list_title"
3939
android:layout_width="match_parent"
4040
android:layout_height="wrap_content"
4141
android:textAppearance="?android:attr/textAppearanceListItem"/>
42-
</LinearLayout>
42+
</FrameLayout>
4343

4444
<TextView android:id="@+id/content_list_summary"
4545
android:layout_width="match_parent"
4646
android:layout_height="wrap_content"
47-
android:textAppearance="?android:attr/textAppearanceListItemSmall"/>
47+
android:textAppearance="?android:attr/textAppearanceListItemSmall"
48+
android:linksClickable="true"/>
4849

4950
<LinearLayout android:orientation="horizontal"
5051
android:layout_width="match_parent"

0 commit comments

Comments
 (0)