-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TIMOB-25663] Android: HttpClient.cache. ImageView.cache #9719
Changes from 7 commits
c261949
95e30c4
7ee8202
0ae09c5
b57ee3e
6800cbc
3e439bf
6385e65
c89a3f6
c0285f7
c098c62
a74f545
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
package ti.modules.titanium.android.httpresponsecache; | ||
|
||
import org.appcelerator.kroll.KrollModule; | ||
import org.appcelerator.kroll.annotations.Kroll; | ||
import org.appcelerator.kroll.common.Log; | ||
import org.appcelerator.titanium.TiApplication; | ||
|
||
import ti.modules.titanium.android.AndroidModule; | ||
import android.app.Activity; | ||
import android.app.Notification; | ||
import android.net.http.HttpResponseCache; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
|
||
@Kroll.module(parentModule = AndroidModule.class) | ||
public class HttpResponseCacheModule extends KrollModule | ||
{ | ||
private static final String TAG = "HttpResponseCache"; | ||
private static final String CACHE_SIZE_KEY = "ti.android.cache.size.max"; | ||
private static final int DEFAULT_CACHE_SIZE = 25 * 1024; // 25MB | ||
|
||
private String httpCachePath; | ||
private long httpCacheSize; | ||
private File httpCacheDir; | ||
|
||
public HttpResponseCacheModule() | ||
{ | ||
super(); | ||
httpCachePath = "http"; | ||
httpCacheSize = | ||
TiApplication.getInstance().getAppProperties().getInt(CACHE_SIZE_KEY, DEFAULT_CACHE_SIZE) * 1024; | ||
} | ||
|
||
@Kroll.method | ||
public boolean install() throws IOException | ||
{ | ||
HttpResponseCache cache = HttpResponseCache.getInstalled(); | ||
if (cache != null) { | ||
cache.flush(); | ||
cache.close(); | ||
} | ||
TiApplication tiApp = TiApplication.getInstance(); | ||
File dir = tiApp.getApplicationContext().getExternalCacheDir(); | ||
if (dir == null) { | ||
dir = tiApp.getApplicationContext().getCacheDir(); | ||
} | ||
httpCacheDir = new File(dir, httpCachePath); | ||
if (!httpCacheDir.exists()) { | ||
if (!httpCacheDir.mkdir()) { | ||
Log.e(TAG, "Failed to create cache directory"); | ||
return false; | ||
} | ||
} else if (!httpCacheDir.isDirectory()) { | ||
Log.e(TAG, "Failed to create cache directory. \"" + httpCacheDir.getPath() + "\" exists."); | ||
return false; | ||
} | ||
cache = HttpResponseCache.install(httpCacheDir, httpCacheSize); | ||
return true; | ||
} | ||
|
||
@Kroll.method | ||
public void flush() | ||
{ | ||
HttpResponseCache cache = HttpResponseCache.getInstalled(); | ||
if (cache != null) { | ||
cache.flush(); | ||
} | ||
} | ||
|
||
@Kroll.method | ||
public void remove() throws IOException | ||
{ | ||
HttpResponseCache cache = HttpResponseCache.getInstalled(); | ||
if (cache != null) { | ||
cache.delete(); | ||
} | ||
} | ||
|
||
@Kroll.method | ||
public void close() throws IOException | ||
{ | ||
HttpResponseCache cache = HttpResponseCache.getInstalled(); | ||
if (cache != null) { | ||
cache.close(); | ||
} | ||
} | ||
|
||
@Kroll.method | ||
public int getHitCount() | ||
{ | ||
HttpResponseCache cache = HttpResponseCache.getInstalled(); | ||
if (cache != null) { | ||
return cache.getHitCount(); | ||
} | ||
return 0; | ||
} | ||
|
||
@Kroll.method | ||
public int getNetworkCount() | ||
{ | ||
HttpResponseCache cache = HttpResponseCache.getInstalled(); | ||
if (cache != null) { | ||
cache.getNetworkCount(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
} | ||
return 0; | ||
} | ||
|
||
@Kroll.method | ||
public int getRequestCount() | ||
{ | ||
HttpResponseCache cache = HttpResponseCache.getInstalled(); | ||
if (cache != null) { | ||
return cache.getRequestCount(); | ||
} | ||
return 0; | ||
} | ||
|
||
@Kroll.method | ||
public long size() | ||
{ | ||
HttpResponseCache cache = HttpResponseCache.getInstalled(); | ||
if (cache != null) { | ||
return cache.size(); | ||
} | ||
return 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think, we shouldn't mix it. |
||
} | ||
|
||
// clang-format off | ||
@Kroll.method | ||
@Kroll.getProperty | ||
public String getHttpCachePath() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// clang-format on | ||
{ | ||
return httpCachePath; | ||
} | ||
|
||
// clang-format off | ||
@Kroll.method | ||
@Kroll.getProperty | ||
public long getHttpCacheSize() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not real fond of the long name here. I assume it was used to not clash with the Why not just mirror the underlying API's use of Additionally, please note that we're going to be moving away from getter/setter methods that just wrap properties in favor of using typical JS property accessors. So in this case, that'd be removing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// clang-format on | ||
{ | ||
return httpCacheSize; | ||
} | ||
|
||
// clang-format off | ||
@Kroll.method | ||
@Kroll.setProperty | ||
public void setHttpCachePath(String value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, not fond of the long name. Why not just use Also, the setter method would be deprecated in 8.0.0 immediately anyhow. So maybe just use this as the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// clang-format on | ||
{ | ||
httpCachePath = value; | ||
} | ||
|
||
// clang-format off | ||
@Kroll.method | ||
@Kroll.setProperty | ||
public void setHttpCacheSize(long value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// clang-format on | ||
{ | ||
httpCacheSize = value; | ||
} | ||
|
||
@Override | ||
public String getApiName() | ||
{ | ||
return "Ti.Android.HttpResponseCache"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
import org.appcelerator.kroll.common.Log; | ||
import org.appcelerator.titanium.TiApplication; | ||
import org.appcelerator.titanium.TiBlob; | ||
import org.appcelerator.titanium.TiC; | ||
import org.appcelerator.titanium.TiDimension; | ||
import org.appcelerator.titanium.TiFileProxy; | ||
import org.appcelerator.titanium.io.TiBaseFile; | ||
|
@@ -81,6 +82,7 @@ public static class Bounds | |
private boolean anyDensityFalse = false; | ||
private boolean autoRotate; | ||
private int orientation = -1; | ||
public boolean useCaches = false; | ||
|
||
// TIMOB-3599: A bug in Gingerbread forces us to retry decoding bitmaps when they initially fail | ||
public static final int DEFAULT_DECODE_RETRIES = 5; | ||
|
@@ -163,7 +165,14 @@ public static TiDrawableReference fromUrl(KrollProxy proxy, String url) | |
if (url == null || url.length() == 0 || url.trim().length() == 0) { | ||
return new TiDrawableReference(proxy.getActivity(), DrawableReferenceType.NULL); | ||
} | ||
return fromUrl(proxy.getActivity(), proxy.resolveUrl(null, url)); | ||
boolean useCaches = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can shorten this to: boolean useCaches = TiConvert.toBoolean(proxy.getProperty(TiC.PROPERTY_CACHE), false); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
Object cacheProperty = proxy.getProperty(TiC.PROPERTY_CACHE); | ||
if (cacheProperty != null) { | ||
useCaches = TiConvert.toBoolean(cacheProperty); | ||
} | ||
TiDrawableReference ref = fromUrl(proxy.getActivity(), proxy.resolveUrl(null, url)); | ||
ref.useCaches = useCaches; | ||
return ref; | ||
} | ||
|
||
/** | ||
|
@@ -239,8 +248,15 @@ public static TiDrawableReference fromObject(KrollProxy proxy, Object object) | |
object = proxy.resolveUrl(null, (String) object); | ||
} | ||
|
||
boolean useCaches = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, you can shrink this down to a one-liner There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
Object cacheProperty = proxy.getProperty(TiC.PROPERTY_CACHE); | ||
if (cacheProperty != null) { | ||
useCaches = TiConvert.toBoolean(cacheProperty); | ||
} | ||
// Create a drawable reference from the given object. | ||
return TiDrawableReference.fromObject(activity, object); | ||
TiDrawableReference ref = TiDrawableReference.fromObject(activity, object); | ||
ref.useCaches = useCaches; | ||
return ref; | ||
} | ||
|
||
/** | ||
|
@@ -411,6 +427,7 @@ public Bitmap getBitmap(boolean needRetry, boolean densityScaled) | |
URL mURL = new URL(url); | ||
connection = (HttpURLConnection) mURL.openConnection(); | ||
connection.setInstanceFollowRedirects(true); | ||
connection.setUseCaches(useCaches); | ||
connection.setDoInput(true); | ||
connection.connect(); | ||
int responseCode = connection.getResponseCode(); | ||
|
@@ -893,7 +910,7 @@ public InputStream getInputStream() | |
|
||
if (isTypeUrl() && url != null) { | ||
try { | ||
stream = TiFileHelper.getInstance().openInputStream(url, false); | ||
stream = TiFileHelper.getInstance().openInputStream(url, false, useCaches); | ||
|
||
} catch (IOException e) { | ||
Log.e(TAG, "Problem opening stream with url " + url + ": " + e.getMessage()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not have the
path
(orhttpCacheDir
) property value determine the directory and relative path to store the cache?I'm worried here because the Android docs point out that if the requests contain private data, the external cache dir is a bad place to stick the cache due to access controls not being enforced on external storage.
I'm assuming it's because we don't actually expose the external cache dir anywhere in our APIs? cc @garymathews @jquick-axway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Also this is how currently
cacheDir
calculated forTiResponseCache
.