15

I'm developing a web based application that also should run on Android based phones. As I don't have one I'm successfully using the emulator from the SDK.

But as I'm constantly changing some JavaScript pages of the application the browser uses the old versions out of it's cache (cache control on the server is right - but I'm not having there the normal use case where excessive caching is wanted)

So is there a way to tell the (default) Android Browser to permanently disable it's cache?
Or is it possible to use an adb command to clear the cache?

Chris
  • 3,265
  • 5
  • 37
  • 50

6 Answers6

12

For the duration of debugging, add a meta tag to your page to disable caching.

<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">

http://www.i18nguy.com/markup/metatags.html

jfriend00
  • 683,504
  • 96
  • 985
  • 979
9

Using adb command you can clear browser cache and user data

adb shell pm clear com.android.browser

but this will not work if you issue this from the android program runtime

see my previous question regarding that

Although that is temporary solution if you need to clear android browser cache continuously using background running service it can be done with "android.content.pm.IPackageDataObserver".if you looking for that following is that service It tested and work fine

import java.util.List;

import android.app.PendingIntent;
import android.app.Service;    
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.os.Handler;
import android.os.IBinder;


public class CacheCleanerService extends Service {

public static final String REFRESH_INTENT="tritop.android.slwcachecleanerwidget.REFRESH";
public static final String CLEAR_INTENT="tritop.android.slwcachecleanerwidget.CLEAR";
public static final long RECOUNTNDELAY=1500;
private boolean mDND=false;
private Handler mHandler;
private int statsCounter;
private long mCacheSum;
private StatsObserver mStatsObs;
private ClearCacheObserver mClearObs;
private PackageManager mPM;
private List<PackageInfo> mInstPkg;


private Runnable mTriggerCount = new Runnable()
{

    public void run()
    {
     countCache();
    }
 };

 private Runnable mAutoKill = new Runnable()
    {

        public void run()
        {
         stopSelf();
        }
     };


//More info in ApplicationState.java @ android.git.kernel.org
class StatsObserver extends IPackageStatsObserver.Stub{
    public void onGetStatsCompleted(PackageStats stats,boolean bl){
        mCacheSum+=stats.cacheSize;
        statsCounter++;
        if(statsCounter>=mInstPkg.size()){
            updateWidgets();
        }
    }
}

class ClearCacheObserver extends IPackageDataObserver.Stub {
    public void onRemoveCompleted(final String packageName, final boolean succeeded) {
     }
 }

private void countCache() {
    statsCounter = 0;
    mCacheSum = 0;
    mInstPkg= mPM.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES |
               PackageManager.GET_DISABLED_COMPONENTS);
    for(PackageInfo pInfo: mInstPkg){
         //  mPM.getPackageSizeInfo(pInfo.packageName, mStatsObs);
    }
}

private void clearCache(){
    mInstPkg= mPM.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES |
               PackageManager.GET_DISABLED_COMPONENTS);
    //mPM.freeStorageAndNotify(Integer.MAX_VALUE, mClearObs);
    //mPM.freeStorageAndNotify(Long.MAX_VALUE, mClearObs);
    mHandler.postDelayed(mTriggerCount, RECOUNTNDELAY);
}



@Override
public IBinder onBind(Intent arg0) {
    return null;
}

@Override
public void onCreate() {
    mStatsObs = new StatsObserver();
    mClearObs = new ClearCacheObserver();
    mPM = getPackageManager();
    mHandler = new Handler();
}

@Override
public void onDestroy() {
    mHandler.removeCallbacks(mAutoKill);
    mHandler.removeCallbacks(mTriggerCount);
    mDND=false;
    super.onDestroy();
}

@Override
public void onStart(Intent intent, int startId) {
    if(!mDND){
        mHandler.postDelayed(mAutoKill, 20000);
        mDND=true;
        mCacheSum=0;
        statsCounter=0;
        if(CLEAR_INTENT.equals(intent.getAction())){
            clearCache();
        }
        else{
            countCache();
        }
    }
}

}

Community
  • 1
  • 1
UdayaLakmal
  • 4,035
  • 4
  • 29
  • 40
3

Try appending the time (in long, ms since epoch format) as a query parameter for each call. This will prevent the cached copy being used. We do this in our normal J2EE/Struts/Tomcat stack and it works well with all (desktop) browsers.

If you want cached behavior in production its easy to remove the extra params.

Pedantic
  • 5,032
  • 2
  • 24
  • 37
  • 1
    Whether the user/browser decides to cache isn't under your control as a web app author. AFAIK its the only tried-and-true workaround to a problem which has no real solution. – Pedantic Jun 10 '11 at 02:18
  • 1
    At any rate, the WebSettings of a WebView has a `setCacheMode(..)` function that might help you. – Pedantic Jun 10 '11 at 05:15
2

Why aren't you using the cache manifest?

https://developer.mozilla.org/en/Offline_resources_in_Firefox

If you put your js files in the network section, this should do what you need :

Files listed under the NETWORK: section header in the cache manifest file are white-listed resources that require a connection to the server. All requests to such resources bypass the cache, even if the user is offline. Wildcards may be used.

0

I came across a similar problem using lots of AJAX and constantly refreshing the emulator browser. These two methods helped me.

AJAX - set the request header to get the reqeust if-modified-since.

 xhReq.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2005 00:00:00 GMT");

Or with jquery $.ajax()

beforeSend: function(xhr) {
    xhReq.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2005 00:00:00 GMT");
}

If you happen to be using PHP - set the header information.

header("Expires: Sat, 1 Jan 2005 00:00:00 GMT");
header("Last-Modified: ".gmdate( "D, d M Y H:i:s")."GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");

Source: http://ajaxpatterns.org/XMLHttpRequest_Call

Tank
  • 1,006
  • 7
  • 17
0

I am using an Android emulator and was able to clear the built in Browser by opening the Browser and clicking on menu. There I selected Settings and then "Privacy and security". This gave the option to click on clear Cache.