1
0
Fork 0
mirror of https://github.com/MatomoCamp/matomocamp-companion-android.git synced 2024-09-19 16:13:46 +02:00

Added Http cache awareness

to skip updating the database when the remote file has not changed.
This commit is contained in:
Christophe Beyls 2015-02-05 23:49:31 +01:00
parent 6f48640a13
commit 90d73831c6
5 changed files with 85 additions and 32 deletions

View file

@ -150,6 +150,9 @@ public class MainActivity extends ActionBarActivity implements ListView.OnItemCl
case FosdemApi.RESULT_ERROR:
message = getString(R.string.schedule_loading_error);
break;
case FosdemApi.RESULT_UP_TO_DATE:
message = getString(R.string.events_download_up_to_date);
break;
case 0:
message = getString(R.string.events_download_empty);
break;

View file

@ -1,12 +1,12 @@
package be.digitalia.fosdem.api;
import java.io.InputStream;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import be.digitalia.fosdem.db.DatabaseManager;
import be.digitalia.fosdem.model.Event;
import be.digitalia.fosdem.parsers.EventsParser;
@ -27,6 +27,7 @@ public class FosdemApi {
public static final String EXTRA_RESULT = "RESULT";
public static final int RESULT_ERROR = -1;
public static final int RESULT_UP_TO_DATE = -2;
private static final Lock scheduleLock = new ReentrantLock();
@ -43,16 +44,29 @@ public class FosdemApi {
int result = RESULT_ERROR;
try {
InputStream is = HttpUtils.get(context, FosdemUrls.getSchedule(), ACTION_DOWNLOAD_SCHEDULE_PROGRESS, EXTRA_PROGRESS);
DatabaseManager dbManager = DatabaseManager.getInstance();
HttpUtils.HttpResult httpResult = HttpUtils.get(
context,
FosdemUrls.getSchedule(),
dbManager.getLastModifiedTag(),
ACTION_DOWNLOAD_SCHEDULE_PROGRESS,
EXTRA_PROGRESS);
if (httpResult.inputStream == null) {
// Nothing to parse, the result is up-to-date.
result = RESULT_UP_TO_DATE;
return;
}
try {
Iterable<Event> events = new EventsParser().parse(is);
result = DatabaseManager.getInstance().storeSchedule(events);
Iterable<Event> events = new EventsParser().parse(httpResult.inputStream);
result = dbManager.storeSchedule(events, httpResult.lastModified);
} finally {
try {
is.close();
httpResult.inputStream.close();
} catch (Exception ignored) {
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {

View file

@ -50,6 +50,7 @@ public class DatabaseManager {
private static final String DB_PREFS_FILE = "database";
private static final String LAST_UPDATE_TIME_PREF = "last_update_time";
private static final String LAST_MODIFIED_TAG_PREF = "last_modified_tag";
private static DatabaseManager instance;
@ -117,13 +118,21 @@ public class DatabaseManager {
return getSharedPreferences().getLong(LAST_UPDATE_TIME_PREF, -1L);
}
/**
*
* @return The time identifier of the current version of the database.
*/
public String getLastModifiedTag() {
return getSharedPreferences().getString(LAST_MODIFIED_TAG_PREF, null);
}
/**
* Stores the schedule to the database.
*
* @param events
* @return The number of events processed.
*/
public int storeSchedule(Iterable<Event> events) {
public int storeSchedule(Iterable<Event> events, String lastModifiedTag) {
boolean isComplete = false;
SQLiteDatabase db = helper.getWritableDatabase();
@ -260,8 +269,11 @@ public class DatabaseManager {
// Clear cache
cachedDays = null;
year = -1;
// Set last update time
getSharedPreferences().edit().putLong(LAST_UPDATE_TIME_PREF, System.currentTimeMillis()).commit();
// Set last update time and server's last modified tag
getSharedPreferences().edit()
.putLong(LAST_UPDATE_TIME_PREF, System.currentTimeMillis())
.putString(LAST_MODIFIED_TAG_PREF, lastModifiedTag)
.commit();
context.getContentResolver().notifyChange(URI_TRACKS, null);
context.getContentResolver().notifyChange(URI_EVENTS, null);

View file

@ -43,9 +43,9 @@ public class HttpUtils {
});
// Trust all HTTPS certificates
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
return new java.security.cert.X509Certificate[]{};
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
@ -53,7 +53,7 @@ public class HttpUtils {
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
} };
}};
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
@ -63,44 +63,67 @@ public class HttpUtils {
}
}
public static class HttpResult {
// Will be null when the local content is up-to-date
public InputStream inputStream;
public String lastModified;
}
public static InputStream get(Context context, String path) throws IOException {
return get(context, new URL(path), null, null);
return get(context, new URL(path), null, null, null).inputStream;
}
public static InputStream get(Context context, String path, String progressAction, String progressExtra) throws IOException {
return get(context, new URL(path), progressAction, progressExtra);
public static HttpResult get(Context context, String path, String lastModified,
String progressAction, String progressExtra) throws IOException {
return get(context, new URL(path), lastModified, progressAction, progressExtra);
}
public static InputStream get(final Context context, URL url, final String progressAction, final String progressExtra) throws IOException {
public static HttpResult get(final Context context, URL url, String lastModified,
final String progressAction, final String progressExtra) throws IOException {
HttpResult result = new HttpResult();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(DEFAULT_TIMEOUT);
connection.setConnectTimeout(DEFAULT_TIMEOUT);
if (lastModified != null) {
connection.addRequestProperty("If-Modified-Since", lastModified);
}
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
result.lastModified = connection.getHeaderField("Last-Modified");
int responseCode = connection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
connection.disconnect();
throw new IOException("Server returned response code: " + connection.getResponseCode());
if ((responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) && (lastModified != null)) {
// Cached result is still valid; return an empty response
return result;
}
throw new IOException("Server returned response code: " + responseCode);
}
final int length = connection.getContentLength();
InputStream is = new BufferedInputStream(connection.getInputStream());
result.inputStream = new BufferedInputStream(connection.getInputStream());
if ((progressAction == null) || (length == -1)) {
// No progress support
return is;
return result;
}
// Broadcast the progression in percents, with a precision of 1/10 of the total file size
return new ByteCountInputStream(is, new ByteCountInputStream.ByteCountListener() {
result.inputStream = new ByteCountInputStream(result.inputStream,
new ByteCountInputStream.ByteCountListener() {
private LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
private LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
@Override
public void onNewCount(int byteCount) {
// Cap percent to 100
int percent = (byteCount >= length) ? 100 : byteCount * 100 / length;
lbm.sendBroadcast(new Intent(progressAction).putExtra(progressExtra, percent));
}
}, length / 10);
@Override
public void onNewCount(int byteCount) {
// Cap percent to 100
int percent = (byteCount >= length) ? 100 : byteCount * 100 / length;
lbm.sendBroadcast(new Intent(progressAction).putExtra(progressExtra, percent));
}
}, length / 10);
return result;
}
}

View file

@ -10,6 +10,7 @@
<string name="download_reminder_message">This will update the schedule database to the latest version. Make sure you are connected to the internet.</string>
<string name="never">Never</string>
<string name="update_events_db">Update events database</string>
<string name="events_download_up_to_date">Database is already up-to-date</string>
<string name="events_download_empty">No new events found</string>
<plurals name="events_download_completed">