Вопрос

I have parsed the JSON Data in a listview and now I want to make it available offline. Is there a way to save the JSON data at the phone so that you can see the data if your phone is offline?

Does someone knows an example?

EDIT works now:

 public class MainActivity extends ListActivity {


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new TheTask().execute();
    }

    class TheTask extends AsyncTask<Void, Void, JSONArray> {
        InputStream is = null;
        String result = "";
        JSONArray jArray = null;

        ProgressDialog pd;

        @Override
        protected void onPostExecute(JSONArray result) {
            super.onPostExecute(result);
            pd.dismiss();
            ArrayList<String> list= new ArrayList<String>();
            try {
                for(int i=0;i<result.length();i++) {

                    JSONObject jb = result.getJSONObject(i) ;
                    String name = jb.getString("name")+" "+jb.getString("Art");
                    list.add(name);
                }
            } catch(Exception e) {
                e.printStackTrace();
            }
            setListAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, list));
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pd = ProgressDialog.show(MainActivity.this, "State",
                    "Loading...", true);
        }

        @Override
        protected JSONArray doInBackground(Void... arg0) {
            ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

                try {
                    HttpClient httpclient = new DefaultHttpClient();
                    HttpPost httppost = new HttpPost("***");
                    HttpResponse response = httpclient.execute(httppost);
                    HttpEntity entity = response.getEntity();
                    is = entity.getContent();
                } catch (Exception e) {
                    Log.e("log_tag", "Error in http connection " + e.toString());
                }

                // Convert response to string
                try {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(
                            is, "iso-8859-1"), 8);
                    StringBuilder sb = new StringBuilder();
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                    }
                    is.close();
                    result = sb.toString();
                    writeToFile(result);
                } catch (Exception e) {
                    Log.e("log_tag", "Error converting result " + e.toString());
                }

                try {
                    jArray = new JSONArray(result);
                } catch (JSONException e) {
                    Log.e("log_tag", "Error parsing data " + e.toString());
                }

                try {
                    jArray = new JSONArray(readFromFile());
                } catch (JSONException e) {
                    Log.e("log_tag", "Error parsing data " + e.toString());
                }

            return jArray;
        }
    }

    private void writeToFile(String data) {
        try {
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(openFileOutput("config.txt", Context.MODE_PRIVATE));
            outputStreamWriter.write(data);
            outputStreamWriter.close();
        }
        catch (IOException e) {
            Log.e("Exception", "File write failed: " + e.toString());
        }
    }

    private String readFromFile() {

        String ret = "";

        try {
            InputStream inputStream = openFileInput("config.txt");

            if ( inputStream != null ) {
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String receiveString = "";
                StringBuilder stringBuilder = new StringBuilder();

                while ( (receiveString = bufferedReader.readLine()) != null ) {
                    stringBuilder.append(receiveString);
                }

                inputStream.close();
                ret = stringBuilder.toString();
            }
        } catch (FileNotFoundException e) {
            Log.e("login activity", "File not found: " + e.toString());
        } catch (IOException e) {
            Log.e("login activity", "Can not read file: " + e.toString());
        }

        return ret;
    }
}
Это было полезно?

Решение

You have two ways. Either you create a database and save all of the data there and retrieve it back when you want to. Or if the data you have is not that much and you don't want to deal with databases, then you write the json string to a text file in the memory card and read it later when you are offline.

And for the second case, every time you go online, you can retrieve the same json from your web service and over write it to the old one. This way you can be sure that you have the latest json saved to the device.

Другие советы

this class will help you cache strings in files with a key to retrieve later on. the string can be a json string and key can be the url you requested and also an identifier for the url if you are using post method.

public class CacheHelper {

static int cacheLifeHour = 7 * 24;

public static String getCacheDirectory(Context context){

    return context.getCacheDir().getPath();
}

public static void save(Context context, String key, String value) {

    try {

        key = URLEncoder.encode(key, "UTF-8");

        File cache = new File(getCacheDirectory(context) + "/" + key + ".srl");

        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(cache));
        out.writeUTF(value);
        out.close();
    } catch (Exception e) {

        e.printStackTrace();
    }
}

public static void save(Context context, String key, String value, String identifier) {

   save(context, key + identifier, value);
}

public static String retrieve(Context context, String key, String identifier) {

   return retrieve(context, key + identifier);
}


public static String retrieve(Context context, String key) {

    try {

        key = URLEncoder.encode(key, "UTF-8");

        File cache = new File(getCacheDirectory(context) + "/" + key + ".srl");

        if (cache.exists()) {

            Date lastModDate = new Date(cache.lastModified());
            Date now = new Date();

            long diffInMillisec = now.getTime() - lastModDate.getTime();
            long diffInSec = TimeUnit.MILLISECONDS.toSeconds(diffInMillisec);

            diffInSec /= 60;
            diffInSec /= 60;
            long hours = diffInSec % 24;

            if (hours > cacheLifeHour) {
                cache.delete();
                return "";
            }

            ObjectInputStream in = new ObjectInputStream(new FileInputStream(cache));
            String value = in.readUTF();
            in.close();

            return value;
        }

    } catch (Exception e) {

        e.printStackTrace();
    }

    return "";
}
}

how to use it :

String string = "cache me!";
String key = "cache1";
CacheHelper.save(context, key, string);
String getCache = CacheHelper.retrieve(context, key); // will return 'cache me!'

Once you download the data you could persist the data on the mobile, using a database or a system of your preference.

You can check the different options here: data-storage

using SharedPreferences should be prepared to sqlite (unless of course you have a database structure). For caching and storing data pulled from the internet, I recommend robospice: https://github.com/octo-online/robospice. It's a very well done library, easy to use, and should be used any time you download data from the internet or have a long-running task.

You can use those two methods two store you JSON file as a string in your SharedPreferences and retrieve it back:

public String getStringProperty(String key) {
    sharedPreferences = context.getSharedPreferences("preferences", Activity.MODE_PRIVATE);
    String res = null;
    if (sharedPreferences != null) {
        res = sharedPreferences.getString(key, null);
    }
    return res;
}

public void setStringProperty(String key, String value) {
    sharedPreferences = context.getSharedPreferences("preferences", Activity.MODE_PRIVATE);
    if (sharedPreferences != null) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(key, value);
        editor.commit();
        CupsLog.i(TAG, "Set " + key + " property = " + value);
    }
}

Just use setStringProperty("json", "yourJsonString") to save and getStringProperty("json") to retrieve.

How to Cache Json data to be available offline?

You can use gson to parse JSON data more easily. In your build.gradle file add this dependency.

compile 'com.google.code.gson:gson:2.8.0'

Then create a POJO class to parse JSON data.

Example POJO class:

  public class AppGeneralSettings {
    @SerializedName("key1")
String data;


    public String getData() {
        return data;
    }

}
  • To parse a json string from internet use this snippet

    AppGeneralSettings data=new Gson().fromJson(jsonString, AppGeneralSettings.class);
    

Then add a helper class to store and retrieve JSON data to and from preferences.

Example: Helper class to store data

public class AppPreference {
    private static final String FILE_NAME = BuildConfig.APPLICATION_ID + ".apppreference";
    private static final String APP_GENERAL_SETTINGS = "app_general_settings";
    private final SharedPreferences preferences;

    public AppPreference(Context context) {
        preferences = context.getSharedPreferences(FILE_NAME, MODE_PRIVATE);
    }

    public SharedPreferences.Editor setGeneralSettings(AppGeneralSettings appGeneralSettings) {
        return preferences.edit().putString(APP_GENERAL_SETTINGS, new Gson().toJson(appGeneralSettings));
    }

    public AppGeneralSettings getGeneralSettings() {
        return new Gson().fromJson(preferences.getString(APP_GENERAL_SETTINGS, "{}"), AppGeneralSettings.class);
    }
}

To save data

new AppPreference().setGeneralSettings(appGeneralSettings).commit();

To retrieve data

 AppGeneralSettings appGeneralSettings = new AppPreference().getGeneralSettings();

You can cache your Retrofit responses, so when you make the same request second time, Retrofit will take it from it's cache: https://medium.com/@coreflodev/understand-offline-first-and-offline-last-in-android-71191e92b426, https://futurestud.io/tutorials/retrofit-2-activate-response-caching-etag-last-modified. After that you'l need to parse that json again

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top