Загрузка локальных JsonData при отсутствии подключения к Интернету

Я делаю приложение для Android, в которое хочу загрузить данные json. Моя спецификация заключается в том, что если есть доступ в Интернет, то загружать данные с URL-адреса, который я предоставляю.

Если нет интернета, то загрузите локальный файл json.txt.

Мое приложение может загружать данные с URL-адреса, если есть подключение к Интернету, и оно может загружать локальные данные json, если подключение к Интернету отсутствует.

Однако в таком метасостоянии мое приложение падает.введите здесь описание изображения

Журнал

07-14 09:56:21.258  22499-28349/scientist.jobless.foodmana E/log_tag﹕ Error in http connection java.net.UnknownHostException: Unable to resolve host "lit-hamlet-6856.herokuapp.com": No address associated with hostname
07-14 09:56:21.258  22499-28349/scientist.jobless.foodmana E/log_tag﹕ Error converting result java.lang.NullPointerException
07-14 09:56:21.258  22499-28349/scientist.jobless.foodmana E/log_tag﹕ Error parsing data org.json.JSONException: End of input at character 0 of
07-14 09:56:21.266  22499-28349/scientist.jobless.foodmana E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:299)
            at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:856)
     Caused by: java.lang.NullPointerException
            at scientist.jobless.foodmana.JsonLoadSubFirstFirst$DownloadJSON.doInBackground(JsonLoadSubFirstFirst.java:239)
            at scientist.jobless.foodmana.JsonLoadSubFirstFirst$DownloadJSON.doInBackground(JsonLoadSubFirstFirst.java:215)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:856)
07-14 09:56:21.878  22499-22499/scientist.jobless.foodmana E/WindowManager﹕ Activity scientist.jobless.foodmana.JsonLoadSubFirstFirst has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@5374c12c that was originally added here
    android.view.WindowLeaked: Activity scientist.jobless.foodmana.JsonLoadSubFirstFirst has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@5374c12c that was originally added here
            at android.view.ViewRootImpl.<init>(ViewRootImpl.java:374)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:292)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
            at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
            at android.view.Window$LocalWindowManager.addView(Window.java:547)
            at android.app.Dialog.show(Dialog.java:277)
            at scientist.jobless.foodmana.MyCustomProgressDialog.show(MyCustomProgressDialog.java:43)
            at scientist.jobless.foodmana.JsonLoadSubFirstFirst$DownloadJSON.onPreExecute(JsonLoadSubFirstFirst.java:227)
            at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
            at android.os.AsyncTask.execute(AsyncTask.java:534)
            at scientist.jobless.foodmana.JsonLoadSubFirstFirst.onCreate(JsonLoadSubFirstFirst.java:74)
            at android.app.Activity.performCreate(Activity.java:5008)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
            at android.app.ActivityThread.access$600(ActivityThread.java:130)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)

Ниже приведен мой код Java, где я проверяю тип подключения.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Get the view from listview_main.xml
    setContentView(R.layout.listview_main);
    // Execute DownloadJSON AsyncTask

    ConnectivityManager connec = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);

    if (connec != null && (
            (connec.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState() == NetworkInfo.State.CONNECTED) ||
                    (connec.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState() == NetworkInfo.State.CONNECTED))) {
        new DownloadJSON(this).execute();
        //You are connected, do something online.

    } else if (connec != null && (
            (connec.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState() == NetworkInfo.State.DISCONNECTED) ||
                    (connec.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState() == NetworkInfo.State.DISCONNECTED ))) {

        //Not connected.
        Toast.makeText(getApplicationContext(), "You must be connected to the internet", Toast.LENGTH_LONG).show();
        new LocalDownloadJSON().execute();
    }

    else if (connec != null && (
            (connec.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState() == NetworkInfo.State.UNKNOWN) ||
                    (connec.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState() == NetworkInfo.State.UNKNOWN ))) {

        //i want to load local json data here
    }

}

Мой вопрос в том, как обрабатывать это метасостояние соединения, как я показал на картинке эмулятора.

я пробовал этот ответ, но я получаю сообщение об ошибке isNetworkAvailable(context), поскольку не могу решить метод isNetworkAvailable.

Есть ли вообще по этому коду??

(connec != null && (
             (connec.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState() == NetworkInfo.State.UNKNOWN) ||
                        (connec.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState() == NetworkInfo.State.UNKNOWN )))

LocalJsonDownload.java

private class LocalDownloadJSON extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pd = new ProgressDialog(JsonLoadSubFirstFirst.this);

            pd.setMessage("Loading...");
            pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);

            pd.setIndeterminate(true);
            pd.setCancelable(false);
            pd.show();
        }



        @Override
        protected Void doInBackground(Void... params) {
            // Create an array
            localarraylist = new ArrayList<HashMap<String, String>>();
            // Retrieve JSON Objects from the given URL address

            StringBuffer sb = new StringBuffer();
            BufferedReader br = null;

            try {
                br = new BufferedReader(new InputStreamReader(getAssets().open("localfood.txt")));
                String temp;
                while ((temp = br.readLine()) != null)
                    sb.append(temp);
            }
            catch (IOException e)
            {

                e.printStackTrace();
            }
            finally
            {
                try
                {
                    br.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }

            myjsonstring = sb.toString();

            try{
                JSONObject jsonObj = new JSONObject(myjsonstring);
                JSONArray Attendance = jsonObj.getJSONArray("events");

                for (int i = 0; i < Attendance.length(); i++)

                {

                    JSONObject a = Attendance.getJSONObject(i);

                    String Name = a.getString("Name");
                    String time = a.getString("Time");
                    String ingredients = a.getString("ingredients");
                    String Serves = a.getString("Serves");
                    String descr = a.getString("Description");


                    HashMap<String, String> contact = new HashMap<String, String>();

                    // adding each child node to HashMap key => value
                    contact.put("Name", Name);
                    contact.put("Time", time);
                    contact.put("ingredients", ingredients);
                    contact.put("Serves", Serves);
                    contact.put("Description", descr);
                    // adding contact to contact list
                    localarraylist.add(contact);

                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }


        @Override
        protected void onPostExecute(Void args) {
            Toast.makeText(getApplicationContext(),"Loading local data dishes, please connect o internet to load new dishes",Toast.LENGTH_LONG).show();
            // Locate the listview in listview_main.xml
            //setContentView(R.layout.listview_main);
            listview = (ListView) findViewById(R.id.listview);
            // Pass the results into ListViewAdapter.java
            adapter = new ListViewAdapter(JsonLoadSubFirstFirst.this, localarraylist);
            // Set the adapter to the ListView
            listview.setAdapter(adapter);
            // Close the progressdialog
            //  mProgressDialog.dismiss();

            //   textView.setVisibility(View.VISIBLE);
            pd.dismiss();

            super.onPostExecute(args);

        }
    }

person penta    schedule 14.07.2015    source источник
comment
Привет, ты усложнил задачу, мой друг.. вместо этого, подход, который я вижу, заключается в том, что даже если вы не проверяете соединение, объявите этот json.. в блоке try: сделайте получение json из Интернета. если нет соединения или если ему не удается получить данные. Он автоматически перейдет к блоку catch с общим параметром Exception: где вы будете читать локальный json.   -  person Sheychan    schedule 14.07.2015
comment
Хотите, чтобы я создал образец? :)   -  person Sheychan    schedule 14.07.2015
comment
я пытался попробовать блок catch, даже это привело к сбою приложения :-), логи даже тогда были почти такими же   -  person penta    schedule 14.07.2015
comment
Хмммммм, дай мне посмотреть, что ты пробовал   -  person Sheychan    schedule 14.07.2015


Ответы (4)


вы можете сделать одну вещь при загрузке данных json, когда Интернет доступен, вы можете сохранить их на свой sqite и при загрузке в следующий раз проверить, доступна ли сеть или нет, если сеть недоступна, вы можете получить данные json из sqlite и проанализировать их просто. и вы можете использовать GreenDao для этого он сделает очень быстро и надежно

person Ram Mandal    schedule 14.07.2015
comment
спасибо за ответ, но я не хочу, чтобы мой проект занимал больше времени, не могли бы вы предложить решение с помощью приведенного выше кода - person penta; 14.07.2015

Кажется, что файл json не загружается должным образом из-за подключения к Интернету. Поэтому, когда вы читаете неполный загруженный файл, он выдает «JSONException: конец ввода на символе 0 из»

Вы должны проверить размер загруженного файла с исходным размером файла, прежде чем читать загруженный файл. Исходный размер файла можно найти в заголовке HTTP.

Или у вас есть неверный файл json на сервере.

Надеюсь, вы найдете это полезным.

person chandil03    schedule 14.07.2015
comment
Привет, Сачин, спасибо за ответ, эта ошибка возникает только тогда, когда я нахожусь в метасостоянии интернет-соединения, эта ошибка не возникает, когда я подключен или абсолютно не подключен, на самом деле эта ошибка возникает, когда мой класс пытается загрузить данные json когда нет явного соединения (т.е. метасоединения) - person penta; 14.07.2015
comment
Да, я понял. Из-за отсутствия очевидной связи файл загружен не полностью, поэтому возникает это исключение. Вы должны проверить размер загруженного файла или поймать исключение в методе doInBackgournd. - person chandil03; 14.07.2015
comment
я пробовал операторы try catch, даже они приводят к тому же результату, что и я упоминал об этом в вопросе - person penta; 14.07.2015
comment
Вы сверяли размер загруженного файла с исходным в удаленном месте? - person chandil03; 14.07.2015
comment
Это исключение возникает только в том случае, если у вас есть недопустимый файл json. Итак, у вас неверный файл json или он неправильно загружается, проверьте еще раз. Или опубликуйте свой код AsyncTask, чтобы я мог его проверить. - person chandil03; 14.07.2015
comment
Этот код читает файл из папки с ресурсами, а не из Интернета. Этот код дает исключение? - person chandil03; 14.07.2015
comment
Проблема в том, что вы загружаете код. пока идет загрузка и интернет не работает. это заканчивается загрузкой неполного файла. Распечатайте содержимое загруженного файла, чтобы проверить его содержимое. - person chandil03; 14.07.2015
comment
Прочитай мой ответ, должно помочь - person Yerzhan Tanatov; 14.07.2015
comment
Ержан Танатов сделал это. вот почему существует NullPointerException вместо IOException. Из-за исключения следующая часть оператора catch получает значение null, которое фактически инициализировалось в блоке try. - person chandil03; 14.07.2015

вы работали с sqlite раньше? Я надеюсь Да . для этой задачи работайте с библиотекой volley, которая сделает вас быстрее и проще. Если вы хотите, чтобы я занимался с залпом, дайте мне знать, я помогу вам использовать залп. Но в соответствии с вашим кодом сделайте так. Я не смог опубликовать этот код для комментариев, поэтому я повторно публикую свой ответ, надеюсь, он поможет.

package com.view9.datamodel;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.Toast;

import com.view9.cmap.R;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * Created by Ram Mandal on 7/14/15.
 */
public class test extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_layout);
        if (isNetworkOnline(test.this)) {
            new BackgroundThread().execute();
        } else {
            Toast.makeText(test.this, "No network", Toast.LENGTH_SHORT).show();
            //get json data from sqlite and send it to this method
            parseDataHere("your jsonData from sqlite");
        }

    }

    private void parseDataHere(String s) {
        //load your data here s is the jsonString
    }

    class BackgroundThread extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... params) {
            String jsonString = "";
            //do task here and load your jsonStrng to jsonString variable and return it
            return jsonString;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            //test if the string is jsonObject or jsonArray here
            if (isValidJSONObject(s)) {
                //do whateever you want to do with your jsondata
                //for further use when nointernet connection is detected you can save it to sqlite
                parseDataHere(s);
            }
        }


        public boolean isValidJSONObject(String value) {

            try {
                new JSONObject(value);
            } catch (JSONException e) {
                return false;
            }
            return true;
        }
    }

    public static boolean isNetworkOnline(Context context) {
        ConnectivityManager cm =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        return netInfo != null && netInfo.isConnectedOrConnecting();

    }

}
person Ram Mandal    schedule 14.07.2015

Вы не можете справиться с этим состоянием соединения. Единственный способ - поймать IOException. Лучший способ в методе doInBackground DownloadJSON поймать IOException и JSONException, а затем выполнить LocalDownloadJSON

try{
    // your code for downloading from internet
 } catch (IOException e) {
            e.printStackTrace();
 } catch (JSONException e) {
            e.printStackTrace();
}

Отредактировано: лучше анализировать Json в onPostExecute.

 private class DownloadJSON extends AsyncTask<String, Integer, String> {

        protected void onPreExecute() {         
        }

        protected String doInBackground(String... urls) {
            String result = null;
            try {
                result = tryGetJSON();
            } catch (IOException e) {
                  e.printStackTrace();
            }
            return result;
        }

        protected void onPostExecute(String result) {
            if (result != null) {
              //parse json              
            }
            else{
              //execute LocalDownloadJSON
           }
}
person Yerzhan Tanatov    schedule 14.07.2015
comment
Не удалось разрешить хост lit-hamlet-... (моя ссылка), я добавил новый LocalDownloadjson().execute в оператор try catch - person penta; 14.07.2015
comment
penta, выполните LocalDownloadJSON в onPostExecute. Таким образом, это означает, что вы сначала уведомляете onPostExecute о DownloadJSON, чтобы каким-то образом выполнить его. Возвратите null, например, проверьте его и немедленно выполните - person Yerzhan Tanatov; 14.07.2015
comment
произошла ошибка, имя асинхронного класса на самом деле должно быть DownloadJSON - person Yerzhan Tanatov; 14.07.2015