Use built in OkHttpCache instead of manual cache
This commit is contained in:
parent
e7c5819a89
commit
ba1bad6d95
@ -1,31 +1,28 @@
|
||||
package acr.browser.lightning.search;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import acr.browser.lightning.database.HistoryItem;
|
||||
import acr.browser.lightning.utils.FileUtils;
|
||||
import acr.browser.lightning.utils.Utils;
|
||||
import okhttp3.Cache;
|
||||
import okhttp3.CacheControl;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
@ -35,26 +32,27 @@ abstract class BaseSuggestionsModel {
|
||||
private static final String TAG = BaseSuggestionsModel.class.getSimpleName();
|
||||
|
||||
static final int MAX_RESULTS = 5;
|
||||
private static final long INTERVAL_DAY = TimeUnit.DAYS.toMillis(1);
|
||||
private static final long INTERVAL_DAY = TimeUnit.DAYS.toSeconds(1);
|
||||
@NonNull private static final String DEFAULT_LANGUAGE = "en";
|
||||
@Nullable private static String sLanguage;
|
||||
@NonNull private final Application mApplication;
|
||||
@NonNull private final OkHttpClient mHttpClient = new OkHttpClient();
|
||||
@NonNull private final OkHttpClient mHttpClient;
|
||||
@NonNull private final CacheControl mCacheControl;
|
||||
@NonNull private final ConnectivityManager mConnectivityManager;
|
||||
|
||||
@NonNull
|
||||
protected abstract String createQueryUrl(@NonNull String query, @NonNull String language);
|
||||
|
||||
protected abstract void parseResults(@NonNull FileInputStream inputStream, @NonNull List<HistoryItem> results) throws Exception;
|
||||
protected abstract void parseResults(@NonNull InputStream inputStream, @NonNull List<HistoryItem> results) throws Exception;
|
||||
|
||||
@NonNull
|
||||
protected abstract String getEncoding();
|
||||
|
||||
BaseSuggestionsModel(@NonNull Application application) {
|
||||
mApplication = application;
|
||||
File suggestionsCache = new File(application.getCacheDir(), "suggestion_responses");
|
||||
mHttpClient = new OkHttpClient.Builder()
|
||||
.cache(new Cache(suggestionsCache, FileUtils.megabytesToBytes(1)))
|
||||
.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
|
||||
.build();
|
||||
mCacheControl = new CacheControl.Builder().maxStale(1, TimeUnit.DAYS).build();
|
||||
mConnectivityManager = getConnectivityManager(mApplication);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -76,20 +74,18 @@ abstract class BaseSuggestionsModel {
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(TAG, "Unable to encode the URL", e);
|
||||
}
|
||||
File cache = downloadSuggestionsForQuery(query, getLanguage(), mApplication);
|
||||
if (!cache.exists()) {
|
||||
InputStream inputStream = downloadSuggestionsForQuery(query, getLanguage());
|
||||
if (inputStream == null) {
|
||||
// There are no suggestions for this query, return an empty list.
|
||||
return filter;
|
||||
}
|
||||
FileInputStream fileInput = null;
|
||||
try {
|
||||
fileInput = new FileInputStream(cache);
|
||||
parseResults(fileInput, filter);
|
||||
parseResults(inputStream, filter);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to parse results", e);
|
||||
return filter;
|
||||
} finally {
|
||||
Utils.close(fileInput);
|
||||
Utils.close(inputStream);
|
||||
}
|
||||
|
||||
return filter;
|
||||
@ -102,68 +98,37 @@ abstract class BaseSuggestionsModel {
|
||||
* @param query the query to get suggestions for
|
||||
* @return the cache file containing the suggestions
|
||||
*/
|
||||
@NonNull
|
||||
private File downloadSuggestionsForQuery(@NonNull String query, String language, @NonNull Application app) {
|
||||
@Nullable
|
||||
private InputStream downloadSuggestionsForQuery(@NonNull String query, String language) {
|
||||
String queryUrl = createQueryUrl(query, language);
|
||||
File cacheFile = new File(app.getCacheDir(), queryUrl.hashCode() + SuggestionsAdapter.CACHE_FILE_TYPE);
|
||||
if (System.currentTimeMillis() - INTERVAL_DAY < cacheFile.lastModified()) {
|
||||
return cacheFile;
|
||||
}
|
||||
if (!isNetworkConnected()) {
|
||||
return cacheFile;
|
||||
}
|
||||
InputStream in = null;
|
||||
FileOutputStream fos = null;
|
||||
|
||||
try {
|
||||
URL url = new URL(queryUrl);
|
||||
|
||||
// OkHttp automatically gzips requests
|
||||
Request suggestionsRequest = new Request.Builder().url(url)
|
||||
.addHeader("Accept-Encoding", "gzip")
|
||||
.addHeader("Accept-Charset", getEncoding())
|
||||
.cacheControl(mCacheControl)
|
||||
.build();
|
||||
|
||||
Response suggestionsResponse = mHttpClient.newCall(suggestionsRequest).execute();
|
||||
|
||||
if (suggestionsResponse.code() >= HttpURLConnection.HTTP_MULT_CHOICE ||
|
||||
suggestionsResponse.code() < HttpURLConnection.HTTP_OK) {
|
||||
Log.e(TAG, "Search API Responded with code: " + suggestionsResponse.code());
|
||||
suggestionsResponse.body().close();
|
||||
return cacheFile;
|
||||
}
|
||||
|
||||
in = suggestionsResponse.body().byteStream();
|
||||
|
||||
if (in != null) {
|
||||
in = new GZIPInputStream(in);
|
||||
//noinspection IOResourceOpenedButNotSafelyClosed
|
||||
fos = new FileOutputStream(cacheFile);
|
||||
int buffer;
|
||||
while ((buffer = in.read()) != -1) {
|
||||
fos.write(buffer);
|
||||
}
|
||||
fos.flush();
|
||||
}
|
||||
suggestionsResponse.body().close();
|
||||
cacheFile.setLastModified(System.currentTimeMillis());
|
||||
return suggestionsResponse.body().byteStream();
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Problem getting search suggestions", e);
|
||||
} finally {
|
||||
Utils.close(in);
|
||||
Utils.close(fos);
|
||||
Log.e(TAG, "Problem getting search suggestions", e);
|
||||
}
|
||||
return cacheFile;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isNetworkConnected() {
|
||||
NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
|
||||
return networkInfo != null && networkInfo.isConnected();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static ConnectivityManager getConnectivityManager(@NonNull Context context) {
|
||||
return (ConnectivityManager) context
|
||||
.getApplicationContext()
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
}
|
||||
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Response originalResponse = chain.proceed(chain.request());
|
||||
return originalResponse.newBuilder()
|
||||
.header("cache-control", "max-age=" + INTERVAL_DAY + ", max-stale=" + INTERVAL_DAY)
|
||||
.build();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import acr.browser.lightning.R;
|
||||
@ -30,8 +31,8 @@ final class DuckSuggestionsModel extends BaseSuggestionsModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseResults(@NonNull FileInputStream inputStream, @NonNull List<HistoryItem> results) throws Exception {
|
||||
String content = FileUtils.readStringFromFile(inputStream, ENCODING);
|
||||
protected void parseResults(@NonNull InputStream inputStream, @NonNull List<HistoryItem> results) throws Exception {
|
||||
String content = FileUtils.readStringFromStream(inputStream, ENCODING);
|
||||
JSONArray jsonArray = new JSONArray(content);
|
||||
int counter = 0;
|
||||
for (int n = 0, size = jsonArray.length(); n < size; n++) {
|
||||
|
@ -10,6 +10,7 @@ import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import acr.browser.lightning.R;
|
||||
@ -33,10 +34,10 @@ class GoogleSuggestionsModel extends BaseSuggestionsModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseResults(@NonNull FileInputStream inputStream, @NonNull List<HistoryItem> results) throws Exception {
|
||||
BufferedInputStream fileInput = new BufferedInputStream(inputStream);
|
||||
protected void parseResults(@NonNull InputStream inputStream, @NonNull List<HistoryItem> results) throws Exception {
|
||||
BufferedInputStream bufferedInput = new BufferedInputStream(inputStream);
|
||||
XmlPullParser parser = getParser();
|
||||
parser.setInput(fileInput, ENCODING);
|
||||
parser.setInput(bufferedInput, ENCODING);
|
||||
int eventType = parser.getEventType();
|
||||
int counter = 0;
|
||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||
|
@ -96,6 +96,7 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable {
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
// We don't need these cache files anymore
|
||||
Schedulers.io().execute(new ClearCacheRunnable(BrowserApp.get(mContext)));
|
||||
}
|
||||
|
||||
@ -382,12 +383,9 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable {
|
||||
public void run() {
|
||||
File dir = new File(app.getCacheDir().toString());
|
||||
String[] fileList = dir.list(new NameFilter());
|
||||
long earliestTimeAllowed = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
|
||||
for (String fileName : fileList) {
|
||||
File file = new File(dir.getPath() + fileName);
|
||||
if (earliestTimeAllowed > file.lastModified()) {
|
||||
file.delete();
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,8 @@ public class FileUtils {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String readStringFromFile(@NonNull InputStream inputStream, @NonNull String encoding) throws IOException {
|
||||
public static String readStringFromStream(@NonNull InputStream inputStream,
|
||||
@NonNull String encoding) throws IOException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, encoding));
|
||||
StringBuilder result = new StringBuilder();
|
||||
String line;
|
||||
@ -148,4 +149,14 @@ public class FileUtils {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts megabytes to bytes.
|
||||
*
|
||||
* @param megaBytes the number of megabytes.
|
||||
* @return the converted bytes.
|
||||
*/
|
||||
public static long megabytesToBytes(long megaBytes) {
|
||||
return megaBytes * 1024 * 1024;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user