In a normal Android web app the maximum size for a WebSQL database is normally around 8MB. In a hybrid web app I am making I would like to increase this limit. How would I go about doing that?
It seems that WebStorage might have something to do with it, but the only method I can see there that seems to set the size, setQuotaForOrigin, is marked deprecated.
Sample code (that is not deprecated) is welcome :)
The quota for a web app seems to differ from that of a hybrid app (as in something running within a view). Regardless, by implementing the following in your android.app.Activity subclass you will double the quota until it finally stops at approximately 48MB.
#Override
public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize, long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
quotaUpdater.updateQuota(estimatedSize * 2);
}
The user will not be asked to interact when this happens.
You may want to look at this other question on how to increase quota limit.
Looks like changing the size is only a problem for users that already have a local DB created, this is because there is no way to change the size of the DB when running upgrade scripts for versioning. That said, you just only need to change the size in the initialization script (code in JavaScript):
var size = 10 * 1024 * 1024; // changed from 5 to 10MB
var db = openDatabase("oversized_db", "v1.1", "Ten MB DB", size);
Take into account that this will only affect new users. All users that have previously created a DB with a different size need to clear their cache (you have controll of the cache on a webView so its not that bad) but all previous data would be lost (unless you manually migrate it to the new DB with native code).
In my case I have to do the same but decreasing the size. That would take care of the issue.
Hope this helps.
Related
We're using a d3.layout.force on a web app, and I've been investigating a bug report that it is sluggish on Android: it feels like the nodes are in oil, compared to how it works on desktop browsers, or iOS.
(By the way, we only ever have between 4 and 9 nodes, and the sluggishness does not feel different between 4 and 9.)
We set size(), linkDistance() and charge(); so we're using the defaults for friction, theta, alpha, gravity, etc. I experimented with these to try and reproduce the effect on desktop, but couldn't. (friction(0.67), instead of default of 0.9, was closest, but still felt different, somehow.)
I then set up an FPS meter (based on calls to the tick() function). We get 60fps on desktop, and it seems in the 40s and 50s on an ipad. But on Android Chrome (on a Nexus 7) it seems capped at 30fps, and is often half that. Android Firefox was in the 20s normally, but sometimes into the 30s.
So, is it a reasonable hypothesis that are Android devices are just slower? Could there be a cap of 30fps in Android Chrome?
Then how can I fix this? I believe d3.js uses requestAnimationFrame(). Often animation libraries take the time between calls to requestAnimationFrame() to decide how far to move objects (so when the CPU gets overloaded the animation becomes jerkier, but takes the same amount of time to complete). But it appears that d3.js does not do this, and moves everything the same amount by tick, not by elapsed time. What can I do about this?
(Ideally I'd like a solution based on how slow/fast the machine is, rather than having to sniff the browser.)
Curiously, adding more calls to force.tick() in my own requestAnimationFrame() handler (see https://stackoverflow.com/a/26189110/841830), does increase the FPS. That suggests it is not CPU bound, but instead a limit that Android is enforcing (perhaps to save battery?).
Here is the code I'm using, that tries to adapt dynamically to the current fps; it ain't beautiful but seems to be getting the job done in my test android devices, without changing the behaviour in iOS or desktop.
First, where you set up the force layout:
var ticksPerRender = 0;
var animStartTime,animFrameCount;
force.on('start',function start(){
animStartTime = new Date();animFrameCount=0;
});
requestAnimationFrame(function render() {
for(var i = 0;i < ticksPerRender;i++)force.tick();
if(force.alpha() > 0)requestAnimationFrame(render);
});
The above does two things:
sets up the fps counter
sets up our own animation callback, which does nothing by default (ticksPerRender starts off as zero).
Then at the end of your tick handler:
++animFrameCount;
if(animFrameCount>=15){ //Wait for 15, to get an accurate count
var now = new Date();
var fps = (animFrameCount / (now - animStartTime))*1000;
if(fps < 30){
ticksPerRender++;
animStartTime = now;animFrameCount = 0; //Reset the fps counter
}
if(fps > 60 && ticksPerRender >= 1){
ticksPerRender--;
animStartTime = now;animFrameCount = 0; //Reset the fps counter
}
}
This says that if the FPS is low (below 30), do an extra call to tick() on each animation frame. And if it goes high (over 60), remove that extra call.
Each time ticksPerRender is changed, we measure the FPS from scratch.
I need to know how long a cached version of URI would be on the disk in fresco cache?
As it is written at http://frescolib.org/docs/caching.html#trimming-the-caches:
When configuring the image pipeline, you can set the maximum size of
each of the caches. But there are times when you might want to go
lower than that. For instance, your application might have caches for
other kinds of data that might need more space and crowd out Fresco's.
Or you might be checking to see if the device as a whole is running
out of storage space.
Fresco's caches implement the DiskTrimmable or MemoryTrimmable
interfaces. These are hooks into which your app can tell them to do
emergency evictions.
Your application can then configure the pipeline with objects
implementing the DiskTrimmableRegistry and MemoryTrimmableRegistry
interfaces.
These objects must keep a list of trimmables. They must use
app-specific logic to determine when memory or disk space must be
preserved. They then notify the trimmable objects to carry out their
trims.
So, if you don't specify DiskTrimmable or MemoryTrimmable while configuration your ImagePipeline will be using default DiskTrimmable, MemoryTrimmable. So, after looking for default values in sources i found this:
private static DiskCacheConfig getDefaultMainDiskCacheConfig(final Context context) {
return DiskCacheConfig.newBuilder()
.setBaseDirectoryPathSupplier(
new Supplier<File>() {
#Override
public File get() {
return context.getApplicationContext().getCacheDir();
}
})
.setBaseDirectoryName("image_cache")
.setMaxCacheSize(40 * ByteConstants.MB)
.setMaxCacheSizeOnLowDiskSpace(10 * ByteConstants.MB)
.setMaxCacheSizeOnVeryLowDiskSpace(2 * ByteConstants.MB)
.build();
}
So conclusion is next: when the memory is full (40 ByteConstants.MB or 10 ByteConstants.MB or 2 ByteConstants.MB) - Fresco will delete old records and write new records(images).
Maybe Fresco use this method.
I am using Picasso to download and display images in views all accros my application. Those images are changing very rarely (they are considered valid for a few months).
Is there a simple way to ask Picasso (or the underlying okHttp) to keep those images on disc for this much time?
Disk caching happens "below" Picasso inside the HTTP client. In fact, this process is completely transparent. We never explicitly ask for a cached-version or an internet-version, the HTTP client will make the decision internally and do the right thing.
Because we opted to leverage the HTTP client for caching, we're offered very little control over how the caching actually happens. To answer your question, no, there is no way to tell Picasso (or OkHttp) to cache an image for longer than its headers allow.
I solved it with a Home-made cache, the trick is to add a parameter to the URL that is not used, but making each URL different every X minutes
Calendar cal2 = Calendar.getInstance();
long d = cal2.getTimeInMillis();
int extra = (int) Math.ceil(d/ (10*60*1000)); // 10 minutes cache
Picasso.with(getBaseContext())
.load("http://www.myurl.cat/myimage.png&extra=" + extra)
.placeholder(R.drawable.graphicLoading)
.error(R.drawable.graphicLoadingError)
.into(bottomGraphic);
Before thinking about HTTP behavior, make sure you set a large max size for the disk cache:
cache = Cache(File(application.filesDir, "photos"), Long.MAX_VALUE)
(MAX_VALUE is not recommended for production.) Don't store the cache in application.cacheDir, because android can clear that whenever it wants.
Add an interceptor to set max-stale, which tells the disk cache to use all old files:
val httpClient = OkHttpClient.Builder().cache(cache).addInterceptor { chain ->
// When offline, we always want to show old photos.
val neverExpireCacheControl = CacheControl.Builder().maxStale(Int.MAX_VALUE, TimeUnit.SECONDS).build()
val origRequest = chain.request()
val neverExpireRequest = origRequest.newBuilder().cacheControl(neverExpireCacheControl).build()
chain.proceed(neverExpireRequest)
}.build()
return Picasso.Builder(application).downloader(OkHttp3Downloader(httpClient)).loggingEnabled(true).build()
I discovered this solution by debugging CacheStrategy.getCandidate(). Take a look there if this doesn't solve your problem.
Also trying to get access to color data bytes from color cam of Tango, I was stuck on java API by being able to connect tango Cam to a surface for display (but just OK for display in fact, no easy access to raw data, nor time stamp)... so finally I switch using C API on native code (latest FERMAT lib and header) and follow recommendation I found on stack Overflow by registering a derivated sample code to connectOnFrameAvailable()... (I start using PointCloudActivity sample for that test).
First problem I found is somewhat a side effect of registering to that callback, that works usually fine (callbacks gets fire regularly), but then another callback that I also registered, to get xyz clouds, start to fail to fire. Like in sample code I mentioned, clouds are get through a onXYZijAvailable() callback, that the app registers using TangoService_connectOnXYZijAvailable(onXYZijAvailable).
So failing to get xyz callback fired is not happening always, but usually half of the time, during tests, with a awful workaround that is by taking the app in background then foreground again ... this is curious, is this "recover" related to On-pause/On-resume low level stuff??). If someone has clues ....
By the way in Java API, same side effect was observed, once connecting cam texture for display (through Tango adequate API ...)
But here is my second "problem", back to acquiring YV12 color data from camera :
through registering to TangoService_connectOnFrameAvailable( TangoCameraId::TANGO_CAMERA_COLOR, nullptr, onFrameAvailable)
and providing static funtion onFrameAvailable defined like this :
static void onFrameAvailable(void* ctx, TangoCameraId id, const TangoImageBuffer* buffer)
{
...
LOGI("OnFrameAvailable(): Cam frame data received");
// Check if data format of expected type : YV12 , i.e.
// TangoImageFormatType::TANGO_HAL_PIXEL_FORMAT_YV12
// i.e. = 0x32315659 // YCrCb 4:2:0 Planar
//LOGI("OnFrameAvailable(): Frame data format (%x)", buffer->format);
....
}
the problem is that width, height, stride information of received TangoImageBuffer structure seems valid (1280x720, ...), BUT the format returned is changing every-time, and not the expected magic number (here 0x32315659) ...
I am doing something wrong there ? (but other info are OK ...)
Also, there is apparently only one data format defined (YV12 ) here, but seeing Fish Eye images from demo app, it seems grey level image, is it using same (color) format as low level capture than the RGB cam ???
1) Regarding the image from the camera, I came to the same conclusion you did - only availability of image data is through the C API
2) Regarding the image - I haven't had any issues with YUV, and my last encounter with this stuff was when I wrote JPEG stuff - the format is naked, i.e. it's an organizational structure and has no header information save the undefined metadata in the first line of pixels mentioned here - Here's a link to some code that may help you decode the image in a response to another message here
3) Regarding point cloud returns -
Please note this information is anecdotal, and to some degree the product of superstition - what works for me only does that sometimes, and may not work at all for you
Tango does seem to have a remarkable knack to simply stop producing point clouds. I think a lot of it has to do with very sensitive timing internally (I wonder if anyone mentioned that Linux ain't an RTOS when this was first crafted)
Almost all issues I encounter can be attributed to screwing up the timing where
A. Debugging the C level can may point clouds stop coming
B. Bugs in the native or java code that cause hiccups in the threads that are handling the callbacks can cause point clouds to stop coming
C. Excessive load can cause the system to loose sync, at which point the point clouds will stop coming - this is detectable, you will start to see a silvery grid pattern appear in rectangular areas of the image, and point clouds will cease. Rarely, the system will recover if load decreases, the silvery pattern goes away, and point clouds come back - more commonly the silvery pattern (I think its the 3d spatializing grid) grows to cover more of the image - at least a restart of the app is required for me, and a full tablet reboot every 3rd time or so
Summarizing, that's my suspicions and countermeasures, but it's based completely on personal experience -
I am using Picasso to download and display images in views all accros my application. Those images are changing very rarely (they are considered valid for a few months).
Is there a simple way to ask Picasso (or the underlying okHttp) to keep those images on disc for this much time?
Disk caching happens "below" Picasso inside the HTTP client. In fact, this process is completely transparent. We never explicitly ask for a cached-version or an internet-version, the HTTP client will make the decision internally and do the right thing.
Because we opted to leverage the HTTP client for caching, we're offered very little control over how the caching actually happens. To answer your question, no, there is no way to tell Picasso (or OkHttp) to cache an image for longer than its headers allow.
I solved it with a Home-made cache, the trick is to add a parameter to the URL that is not used, but making each URL different every X minutes
Calendar cal2 = Calendar.getInstance();
long d = cal2.getTimeInMillis();
int extra = (int) Math.ceil(d/ (10*60*1000)); // 10 minutes cache
Picasso.with(getBaseContext())
.load("http://www.myurl.cat/myimage.png&extra=" + extra)
.placeholder(R.drawable.graphicLoading)
.error(R.drawable.graphicLoadingError)
.into(bottomGraphic);
Before thinking about HTTP behavior, make sure you set a large max size for the disk cache:
cache = Cache(File(application.filesDir, "photos"), Long.MAX_VALUE)
(MAX_VALUE is not recommended for production.) Don't store the cache in application.cacheDir, because android can clear that whenever it wants.
Add an interceptor to set max-stale, which tells the disk cache to use all old files:
val httpClient = OkHttpClient.Builder().cache(cache).addInterceptor { chain ->
// When offline, we always want to show old photos.
val neverExpireCacheControl = CacheControl.Builder().maxStale(Int.MAX_VALUE, TimeUnit.SECONDS).build()
val origRequest = chain.request()
val neverExpireRequest = origRequest.newBuilder().cacheControl(neverExpireCacheControl).build()
chain.proceed(neverExpireRequest)
}.build()
return Picasso.Builder(application).downloader(OkHttp3Downloader(httpClient)).loggingEnabled(true).build()
I discovered this solution by debugging CacheStrategy.getCandidate(). Take a look there if this doesn't solve your problem.