package fast.rocket; import java.io.File; import fast.rocket.builder.LoadBuilder; import fast.rocket.builder.RequestBuilder; import fast.rocket.builder.RocketRequestBuilder; import fast.rocket.cache.*; import fast.rocket.http.BasicNetwork; import fast.rocket.http.HttpClientStack; import fast.rocket.http.HttpStack; import fast.rocket.http.HurlStack; import fast.rocket.http.Network; import fast.rocket.request.RequestQueue; import fast.rocket.utils.AndroidHttpClient; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Build; import android.os.Environment; /** * The Class Rocket. */ public class Rocket { /** Default on-disk cache directory. */ private static final String DEFAULT_CACHE_DIR = "rocket"; /** The request dispatch queue. */ private RequestQueue requestQueue; /** The image loader. */ private ImageLoader imageLoader; /** The Rocket instance. */ private static Rocket instance; /** The Rocket library name. */ private String name; /** The network holds the http client for network request and response. */ private Network network; /** The disk cache to store instant images or objects. */ private Cache cache; private Context context; /** * Get the default Rocket object instance and begin building a request. * * @param context the context * @return the rocket request builder */ public static LoadBuilder<RequestBuilder> with(Context context) { return getDefault(context).build(context); } public LoadBuilder<RequestBuilder> build(Context context) { return new RocketRequestBuilder(context, this); } /** * Get the default Rocket instance. * * @param context the context * @return Rocket instance */ public static Rocket getDefault(Context context) { if (instance == null) instance = new Rocket(context, "Rocket V1.0"); return instance; } /** * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. * * @param context A {@link Context} to use for creating the cache dir. * @return A started {@link RequestQueue} instance. */ public RequestQueue newRequestQueue(Context context) { return newRequestQueue(context, null); } /** * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. * * @param context A {@link Context} to use for creating the cache dir. * @param stack An {@link HttpStack} to use for the network, or null for default. * @return A started {@link RequestQueue} instance. */ public RequestQueue newRequestQueue(Context context, HttpStack stack) { String userAgent = "rocket"; try { String packageName = context.getPackageName(); PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); userAgent = packageName + "/" + info.versionCode; } catch (NameNotFoundException e) { } if (stack == null) { if (Build.VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { // Prior to Gingerbread, HttpUrlConnection was unreliable. // See: // http://android-developers.blogspot.com/2011/09/androids-http-clients.html stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } } network = new BasicNetwork(stack); cache = new DiskBasedCache(getDiskCacheDir(context, DEFAULT_CACHE_DIR)); final RequestQueue queue = new RequestQueue(cache, network); queue.start(); return queue; } /** * Invalidate the disk cache data by the url individually. * * @param url the request url */ public void invalidate(String url) { if(requestQueue == null) { throw new IllegalStateException("request queue must be init first"); } final Cache.Entry entry = requestQueue.getCache().get(url); if (entry != null && entry.data != null && entry.data.length > 0) { if (!entry.isExpired()) { requestQueue.getCache().invalidate(url, true); } } } /** * Gets the bytes data in the disk cache. * * @param key the key * @return the data in disk cache */ public byte[] getDiskCacheData(String key) { if(requestQueue == null) { throw new IllegalStateException("request queue must be init first"); } Cache.Entry entry = requestQueue.getCache().get(key); return entry == null ? null : entry.data; } /** * Get a usable cache directory (external if available, internal otherwise). * * @param context The context to use * @return The cache dir */ public static File getDiskCacheDir(Context context) { return getDiskCacheDir(context, DEFAULT_CACHE_DIR); } /** * Cancel all pending requests in the request queue. * * @param tag the tag */ public void cancelAll(final Object tag) { if (requestQueue != null) { requestQueue.cancelAll(tag); } } /** * Builds the json request builder. * * @return the rocket request builder */ public RocketRequestBuilder build() { return new RocketRequestBuilder(context, this); } /** * Gets the Rocket name. * * @return the name */ public String getName() { return name; } /** * Gets the request queue. * * @return the request queue */ public RequestQueue getRequestQueue() { return requestQueue; } /** * Gets the basic network. * * @return the basic network */ public Network getBasicNetwork() { return network; } /** * Gets the cache. * * @return the cache */ public Cache getCache() { return cache; } /** * Gets the image loader. * * @return the image loader */ public ImageLoader getImageLoader() { return imageLoader; } //*********************private apis*****************************// /** * Instantiates a new rocket and the request queue. * * @param context the context * @param name the name */ private Rocket(Context context, String name) { context = context.getApplicationContext(); this.name = name; this.requestQueue = newRequestQueue(context); this.imageLoader = new ImageLoader(requestQueue, new BitmapLruCache()); this.context = context; } /** * Get a usable cache directory (external if available, internal otherwise). * * @param context The context to use * @param uniqueName A unique directory name to append to the cache dir * @return The cache dir */ private static File getDiskCacheDir(Context context, String uniqueName) { // Check if media is mounted or storage is built-in, if so, try and use external cache dir // otherwise use internal cache dir // getCacheDir() should be moved to a background thread as it attempts to create the // directory if it does not exist (no disk access should happen on the main/UI thread). final String cachePath = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ? getExternalCacheDir(context).getPath() : context.getCacheDir().getPath(); return new File(cachePath + File.separator + uniqueName); } /** * Get the external app cache directory. * * @param context The context to use * @return The external cache dir */ private static File getExternalCacheDir(Context context) { // This needs to be moved to a background thread to ensure no disk access on the // main/UI thread as unfortunately getExternalCacheDir() calls mkdirs() for us (even // though the Rocket library will later try and call mkdirs() as well from a background // thread). return context.getExternalCacheDir(); } }