Android: Make App accessible without internet connection
<p>so I made an app which communicates with JSON on the web. It fetches images and texts from the JSON.
And now I got a task to make this app accessible without an internet connection.
it should be like this:</p>

<ul>
<li><p>The first time it's launched, the app has to check if there's any internet connection or not. If not, pop up a dialog box 'Please check your internet connection'. <strong>If there's any, the app is opened and it has to download the images and texts from the JSON and save them into an external storage</strong></p></li>
<li><p>The next time when the app is opened, when there's no internet it will load the images and text files from the external storage. And each time it's connected to the internet, it will download the files and replace the previous files.</p></li>
</ul>

<p>Can anybody provide me a solution by modifying these classes below maybe?</p>

<pre><code>public class ImageThreadLoader {
    private static final String TAG = "ImageThreadLoader";

    // Global cache of images.
    // Using SoftReference to allow garbage collector to clean cache if needed
    private final HashMap&lt;String, SoftReference&lt;Bitmap&gt;&gt; Cache = new HashMap&lt;String,  SoftReference&lt;Bitmap&gt;&gt;();

    private final class QueueItem {
        public URL url;
        public ImageLoadedListener listener;
    }
    private final ArrayList&lt;QueueItem&gt; Queue = new ArrayList&lt;QueueItem&gt;();

    private final Handler handler = new Handler();  // Assumes that this is started from the main (UI) thread
    private Thread thread;
    private QueueRunner runner = new QueueRunner();;

    /** Creates a new instance of the ImageThreadLoader */
    public ImageThreadLoader() {
        thread = new Thread(runner);
    }

    /**
     * Defines an interface for a callback that will handle
     * responses from the thread loader when an image is done
     * being loaded.
     */
    public interface ImageLoadedListener {
        public void imageLoaded(Bitmap imageBitmap );
    }

    /**
     * Provides a Runnable class to handle loading
     * the image from the URL and settings the
     * ImageView on the UI thread.
     */
    private class QueueRunner implements Runnable {
        public void run() {
            synchronized(this) {
                while(Queue.size() &gt; 0) {
                    final QueueItem item = Queue.remove(0);

                    // If in the cache, return that copy and be done
                    if( Cache.containsKey(item.url.toString()) &amp;&amp; Cache.get(item.url.toString()) != null) {
                        // Use a handler to get back onto the UI thread for the update
                        handler.post(new Runnable() {
                            public void run() {
                                if( item.listener != null ) {
                                    // NB: There's a potential race condition here where the cache item could get
                                    //     garbage collected between when we post the runnable and it's executed.
                                    //     Ideally we would re-run the network load or something.
                                    SoftReference&lt;Bitmap&gt; ref = Cache.get(item.url.toString());
                                    if( ref != null ) {
                                        item.listener.imageLoaded(ref.get());
                                    }
                                }
                            }
                        });
                    } else {
                        final Bitmap bmp = readBitmapFromNetwork(item.url);
                        if( bmp != null ) {
                            Cache.put(item.url.toString(), new SoftReference&lt;Bitmap&gt;(bmp));

                            // Use a handler to get back onto the UI thread for the update
                            handler.post(new Runnable() {
                                public void run() {
                                    if( item.listener != null ) {
                                        item.listener.imageLoaded(bmp);
                                    }
                                }
                            });
                        }

                    }

                }
            }
        }
    }

    /**
     * Queues up a URI to load an image from for a given image view.
     *
     * @param uri   The URI source of the image
     * @param callback  The listener class to call when the image is loaded
     * @throws MalformedURLException If the provided uri cannot be parsed
     * @return A Bitmap image if the image is in the cache, else null.
     */
    public Bitmap loadImage( final String uri, final ImageLoadedListener listener) throws MalformedURLException {
        // If it's in the cache, just get it and quit it
        if( Cache.containsKey(uri)) {
            SoftReference&lt;Bitmap&gt; ref = Cache.get(uri);
            if( ref != null ) {
                return ref.get();
            }
        }

        QueueItem item = new QueueItem();
        item.url = new URL(uri);
        item.listener = listener;
        Queue.add(item);

        // start the thread if needed
        if( thread.getState() == State.NEW) {
            thread.start();
        } else if( thread.getState() == State.TERMINATED) {
            thread = new Thread(runner);
            thread.start();
        }
        return null;
    }

    /**
     * Convenience method to retrieve a bitmap image from
     * a URL over the network. The built-in methods do
     * not seem to work, as they return a FileNotFound
     * exception.
     *
     * Note that this does not perform any threading --
     * it blocks the call while retrieving the data.
     *
     * @param url The URL to read the bitmap from.
     * @return A Bitmap image or null if an error occurs.
     */
    public static Bitmap readBitmapFromNetwork( URL url ) {
        InputStream is = null;
        BufferedInputStream bis = null;
        Bitmap bmp = null;
        try {
            URLConnection conn = url.openConnection();
            conn.connect();
            is = conn.getInputStream();
            bis = new BufferedInputStream(is);
            bmp = BitmapFactory.decodeStream(bis);
        } catch (MalformedURLException e) {
            Log.e(TAG, "Bad ad URL", e);
        } catch (IOException e) {
            Log.e(TAG, "Could not get remote ad image", e);
        } finally {
            try {
                if( is != null )
                    is.close();
                if( bis != null )
                    bis.close();
            } catch (IOException e) {
                Log.w(TAG, "Error closing stream.");
            }
        }
        return bmp;
    }

}
</code></pre>

<p>and</p>

<pre><code>public class ProjectAdapter extends ArrayAdapter&lt;Project&gt; {

    int resource;
    String response;
    Context context;
    private final static String TAG = "MediaItemAdapter";

    private ImageThreadLoader imageLoader = new ImageThreadLoader();



    //Initialize adapter
    public ProjectAdapter(Context context, int resource, List&lt;Project&gt; items) {
        super(context, resource, items);
        this.resource=resource;

    }



    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {

        TextView textTitle;
        final ImageView image;

        Project pro = getItem(position);

        LinearLayout projectView;
      //Inflate the view
        if(convertView==null)
        {
            projectView = new LinearLayout(getContext());
            String inflater = Context.LAYOUT_INFLATER_SERVICE;
            LayoutInflater vi;
            vi = (LayoutInflater)getContext().getSystemService(inflater);
            vi.inflate(resource, projectView, true);
        }
        else
        {
            projectView = (LinearLayout) convertView;
        }

        try {
          textTitle = (TextView)projectView.findViewById(R.id.txt_title);
          image = (ImageView)projectView.findViewById(R.id.image);
        } catch( ClassCastException e ) {
          Log.e(TAG, "Your layout must provide an image and a text view with ID's icon and text.", e);
          throw e;
        }


        Bitmap cachedImage = null;
        try {
          cachedImage = imageLoader.loadImage(pro.smallImageUrl, new ImageLoadedListener() {
          public void imageLoaded(Bitmap imageBitmap) {
          image.setImageBitmap(imageBitmap);
          notifyDataSetChanged();                }
          });
        } catch (MalformedURLException e) {
          Log.e(TAG, "Bad remote image URL: " + pro.smallImageUrl, e);
        }

        textTitle.setText(pro.project_title);

        if( cachedImage != null ) {
          image.setImageBitmap(cachedImage);
        }

        return projectView;
    }

}
</code></pre>

<p>Thank you!</p>
