0

Hello i'm beginner in anroid. I created navigation drawer and fragments. I can getting data from json with url. It's working while online. But phone when offline i'm getting "unable to resolve host" error. I want to get data from url with json while offline. It's not caching enter image description here

fragment

private static final String jsonUrl = "http://sunumsitesi.com/json.php";
private ProgressDialog pDialog;
private List<Urun> urunList = new ArrayList<Urun>();
private ListView listView;
private CustomListAdapter adapter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    View root = inflater.inflate(R.layout.fragment_yemek, container, false);
    return root;
}
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);
    View v = getView();
    if(v!=null)
    {
        listView = (ListView) v.findViewById(R.id.yemekList);
        adapter = new CustomListAdapter(getActivity(), urunList);
        listView.setAdapter(adapter);

        pDialog = new ProgressDialog(getActivity());
        pDialog.setMessage("Loading...");
        pDialog.show();
        JsonArrayRequest urunReq = new JsonArrayRequest(jsonUrl, new Response.Listener<JSONArray>()
        {
            @Override
            public void onResponse(JSONArray response)
            {
                hidePDialog();
                for (int i = 0; i < response.length(); i++)
                {
                    try
                    {

                        JSONObject obj = response.getJSONObject(i);
                        Urun urun = new Urun();
                        urun.setUrun_adi(obj.getString("urun_adi"));
                        urun.setUrl("http://www.iremdeveci.com/ornekler/resimler/resim.png");//example
                        urunList.add(urun);
                    } catch (JSONException ex)
                    {
                        ex.printStackTrace();
                    }
                }
                adapter.notifyDataSetChanged();
            }
        }, new Response.ErrorListener()
        {
            @Override
            public void onErrorResponse(VolleyError volleyError)
            {
                Toast.makeText(getActivity(), volleyError.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
        AppController.getmInstance().addToRequestQueue(urunReq);
    }
}

@Override
public void onDestroy()
{
    super.onDestroy();
    hidePDialog();
}
private void hidePDialog()
{
    if(pDialog!=null)
    {
        pDialog.dismiss();
        pDialog=null;
    }
}

and CustomListAdapter(extend BaseAdapter)

private Activity activity;
private LayoutInflater inflater;
private List<Urun> urunItems;
ImageLoader imageLoader = AppController.getmInstance().getmImageLoader();
public CustomListAdapter(Activity activity,List<Urun> urunItems)
{
    this.activity=activity;
    this.urunItems=urunItems;
}

@Override
public int getCount()
{
    return urunItems.size();
}

@Override
public Object getItem(int location)
{
    return urunItems.get(location);
}

@Override
public long getItemId(int position)
{
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    if (inflater==null)
    {
        inflater=(LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    if (convertView==null)
    {
        convertView=inflater.inflate(R.layout.list_row,null);
    }
    if (imageLoader==null)
    {
        imageLoader=AppController.getmInstance().getmImageLoader();
    }
    NetworkImageView urunResim=(NetworkImageView)convertView.findViewById(R.id.urunResim);
    TextView urun_adi= (TextView)convertView.findViewById(R.id.urun_adi);
    Urun u = urunItems.get(position);

    urunResim.setImageUrl(u.getUrl(),imageLoader);
    urun_adi.setText(u.getUrun_adi());
    return convertView;
}

LruBitmapCache.java

public static int getDefaultLruCacheSize()
{
    final int maxMemory=(int)(Runtime.getRuntime().maxMemory()/1024);
    final int cacheSize= maxMemory/8;
    return cacheSize;
}
public LruBitmapCache()
{
    this(getDefaultLruCacheSize());
}
public LruBitmapCache(int sizeInKiloBytes)
{
    super(sizeInKiloBytes);
}

@Override
protected int sizeOf(String key, Bitmap value)
{
    return value.getRowBytes() * value.getHeight()/1024;
}

@Override
public Bitmap getBitmap(String url)
{
    return get(url);
}

@Override
public void putBitmap(String url, Bitmap bitmap)
{
    put(url,bitmap);
}
qwerty
  • 77
  • 1
  • 9

1 Answers1

1

your pictures(http://www.iremdeveci.com/ornekler/resimler/resim.png) seems to be cached correctly as the have etag and cache headers.

However the very first request you make (http://sunumsitesi.com/json.php) doesn't seems to return neither cache headers nor etag. Thus you have the error you dont even reach the picture part.

You can either fix that from the server or make Volley cache it all, for which you need to create custom request and override

protected Response<String> parseNetworkResponse(NetworkResponse response)

You can check my answer here.

In your code this would be smth like

        JsonArrayRequest urunReq = new JsonArrayRequest(jsonUrl, new Response.Listener<JSONArray>()
    {
        @Override
        public void onResponse(JSONArray response)
        {
            String dosyakonum = "http://www.pukkaliving.concept.com/upload/galeri/buyuk/";
            hidePDialog();
            for (int i = 0; i < response.length(); i++)
            {
                try
                {

                    JSONObject obj = response.getJSONObject(i);
                    Urun urun = new Urun();
                    urun.setUrun_adi(obj.getString("urun_adi"));
                    urun.setUrl("http://www.iremdeveci.com/ornekler/resimler/resim.png");//example
                    urunList.add(urun);
                } catch (JSONException ex)
                {
                    ex.printStackTrace();
                }
            }
            adapter.notifyDataSetChanged();
        }
    }, new Response.ErrorListener()
    {
        @Override
        public void onErrorResponse(VolleyError volleyError)
        {
            Toast.makeText(getActivity(), volleyError.getMessage(), Toast.LENGTH_LONG).show();
        }
    }) {
        @Override
        protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
            try {
                String jsonString =
                        new String(response.data, HttpHeaderParser.parseCharset(response.headers));

                long now = System.currentTimeMillis();
                Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
                entry.ttl = now + 30l * 24 * 60 * 60 * 1000;  //keeps cache for 30 days
entry.softTtl = now + 1 * 24 * 60 * 60 * 1000;  //will not try to refresh for 1 day     
                    return Response.success(new JSONArray(jsonString), entry);
                } catch (UnsupportedEncodingException e) {
                    return Response.error(new ParseError(e));
                } catch (JSONException je) {
                    return Response.error(new ParseError(je));
                }
            }
        };
        AppController.getmInstance().addToRequestQueue(urunReq);

however for NetworkImage view you have to customize ImageLoader as this is the one creating the image requests and then the logic is the same. You have to override "makeImageRequest".

ex:

  ...
mImageLoader = new ImageLoader(this.mRequestQueue,
                    new LruBitmapCache()) {
    @Override
        protected Request<Bitmap> makeImageRequest(String requestUrl, int maxWidth, int maxHeight,
                    ScaleType scaleType, final String cacheKey) {
                return new ImageRequest(requestUrl, new Listener<Bitmap>() {
                    @Override
                    public void onResponse(Bitmap response) {
                        onGetImageSuccess(cacheKey, response);
                    }
                }, maxWidth, maxHeight, scaleType, Config.RGB_565, new ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        onGetImageError(cacheKey, error);
                    }
                }){
          @Override
                    public Response<Bitmap> parseNetworkResponse(NetworkResponse response) {
                        Response<Bitmap> resp = super.parseNetworkResponse(response);
                        if(!resp.isSuccess()) {
                            return resp;
                        }
                        long now = System.currentTimeMillis();
                        Cache.Entry entry = resp.cacheEntry;
                        entry.ttl = now + 30l * 24 * 60 * 60 * 1000;  //keeps cache for 30 days
                        return Response.success(resp.result, entry);
                    }

        };
            }
};
    ...
Community
  • 1
  • 1
kalin
  • 3,546
  • 2
  • 25
  • 31
  • Is there a simple example of this ? – qwerty Apr 06 '16 at 14:09
  • check the link in the answer – kalin Apr 06 '16 at 14:17
  • If you will not help do not engage – qwerty Apr 06 '16 at 14:26
  • .. i thought i was helping and the link provides an example... anyway I added to the response how this will apply to you code exactly. I hope now I am helpful... – kalin Apr 06 '16 at 14:38
  • well this should return 1 response and 1 error the response being intermediate. this is why probably u still get an error. the solution is to ignore the error even if the response is not final (i.e. coming form the cache) or add entry.softTtl = now + 1 * 24 * 60 * 60 * 1000; (as I did in the edited answer) which will not even try to refresh the cache thus no error will be received – kalin Apr 06 '16 at 15:02
  • i added the code nothing has changed. i searched and found http://stackoverflow.com/questions/31628062/android-offline-request-with-volley this page – qwerty Apr 06 '16 at 15:14
  • well you can simply use the volley cache and it works perfectly fine. I do it myself this way. Are you sure you made a request while online at least once after changing the code? – kalin Apr 06 '16 at 15:27
  • Yes. first start getting images and text while online,next login internet will not be necessary – qwerty Apr 06 '16 at 15:33
  • sry changed in the answer "30l" beacause it was truncated ti int.max. now it should work – kalin Apr 06 '16 at 18:24
  • thanks for your help.now it's work. Text okay. But image not loading. – qwerty Apr 06 '16 at 19:56
  • there could be some caching issues with images as well so you can override makeImageRequest in Image loader to make sure we always cache. i updated the answer – kalin Apr 06 '16 at 21:18
  • Will it be still in fragment? – qwerty Apr 06 '16 at 22:27
  • the code should be in you imageloader or whenever u initilize it so probably in thi singleton u have – kalin Apr 07 '16 at 05:22
  • I updated to question and i added LruBitmapCache.java. I benefit from this article : http://www.androidhive.info/2014/07/android-custom-listview-with-image-and-text-using-volley/ I can't override these methods in fragment or LruBitmapCache . – qwerty Apr 07 '16 at 12:36
  • LruBitmapCache doesn not really affect the actual diskbased cache of Volley they are different things. I updated my answer to work with the example from the link you used. you need to add this to the initialization of ImageLoader in AppController.getImageLoader – kalin Apr 07 '16 at 13:29
  • onGetImageSucces and onGetImageError says: has private access in volley.toolbox.imageloader – qwerty Apr 07 '16 at 13:43
  • I added this to gradle compile 'com.mcxiaoke.volley:library:1.0.19'. Not showing error. But same problem, text okay image not loading. img : http://i.hizliresim.com/qMnmgq.png – qwerty Apr 07 '16 at 21:52
  • updated entry.ttl = now + 30l * 24 * 60 * 60 * 1000; for image loader also – kalin Apr 07 '16 at 22:04
  • you are awesome my friend. now it's working exactly as I want. Thanks for all your help! – qwerty Apr 08 '16 at 00:25
  • few days later i tried this answer. it's not working offline – qwerty Apr 15 '16 at 18:30
  • well if you exceeded your cache limit the cached could be trimmed – kalin Apr 15 '16 at 18:59
  • that's all for now : http://i.hizliresim.com/bD17l0.png and i will add more items.How much max cache and is there a solution ? – qwerty Apr 15 '16 at 19:36
  • this seems to go a little off topic and adressing other issues than purely caching http responses. you can summarise your other needs and questions in another question as these comments and possible solutions they describe will be difficult to trace and find – kalin Apr 15 '16 at 20:52