Android: HTTP-запрос на исправление Volley

Я только начал портировать свою существующую сетевую библиотеку на Android Volley. До сих пор я успешно реализовал Volleys ImageLoader, где это применимо. Теперь я пытаюсь запустить свой первый http-вызов, но нахожу эту ошибку.

Примечание. Я намеренно начал с запроса PATCH, потому что буду часто их использовать. Кроме того, моя версия Volley поддерживает патч: https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/Request.java https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/toolbox/HurlStack.java

Трассировка стека:

E/InputDialogFragment(27940): VolleyError: java.net.ProtocolException: Connection already established
D/Volley  (27940): [1] MarkerLog.finish: (67   ms) [ ] https://mobile.example.com/m/api/v1/user/ 0xb33a3c8d NORMAL 2
D/Volley  (27940): [1] MarkerLog.finish: (+0   ) [ 1] add-to-queue
D/Volley  (27940): [1] MarkerLog.finish: (+0   ) [544] cache-queue-take
D/Volley  (27940): [1] MarkerLog.finish: (+0   ) [544] cache-miss
D/Volley  (27940): [1] MarkerLog.finish: (+0   ) [545] network-queue-take
D/Volley  (27940): [1] MarkerLog.finish: (+14  ) [545] post-error
D/Volley  (27940): [1] MarkerLog.finish: (+53  ) [ 1] done

Запрос на исправление

    HashMap<String, Object> values = new HashMap<String, Object>();
    values.put(mParam, val);
    JsonObjectRequest request = new JsonObjectRequest(Request.Method.PATCH, APIConstants.URL_USER, new JSONObject(values),
        new Response.Listener<JSONObject>(){
            @Override
            public void onResponse(JSONObject response){
               // Blah do stuff here 
                mProgressDialog.dismiss();
            }
        },
        new Response.ErrorListener(){
            @Override
            public void onErrorResponse(VolleyError error){
                Log.e(TAG, "VolleyError: " + error.getMessage());
            }
        }){
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<String, String>();
                VolleySingleton.getInstance().addCookie(headers);
                return headers;
            }
    };
    VolleySingleton.getInstance().getRequestQueue().add(request);

Да, я планирую в конечном итоге создать классы для StringRequest, JsonObjectRequest и т. д., но в настоящее время я просто хочу запустить его.

Кроме того, если вас интересует addCookie, на данный момент я предпочитаю сохранять свой файл cookie в настройках, поскольку я не так хорошо знаком с CookieManager.

ЗалпСинглтон

public class VolleySingleton {
    private static final String COOKIE_KEY = "Cookie";
    private static VolleySingleton mInstance = null;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private SharedPreferences mPreferences;
    private VolleySingleton(){
        mRequestQueue = Volley.newRequestQueue(MyApplication.getAppContext());
        mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
            public void putBitmap(String url, Bitmap bitmap) {
                mCache.put(url, bitmap);
            }
            public Bitmap getBitmap(String url) {
                return mCache.get(url);
            }
        });
        mPreferences = MyApplication.getAppContext().getSharedPreferences(PrefConstants.PREFERENCES, 0);
    }

    public static VolleySingleton getInstance(){
        if(mInstance == null){
            mInstance = new VolleySingleton();
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue(){
        return this.mRequestQueue;
    }

    public ImageLoader getImageLoader(){
        return this.mImageLoader;
    }

    public final void addCookie(Map<String, String> headers) {
        String cookie = mPreferences.getString(PrefConstants.PREF_COOKIE, null);
        if(cookie != null){
            headers.put(COOKIE_KEY, cookie);
        }
    }
}

person Brice    schedule 14.03.2014    source источник
comment
Заметил, что GET и POST работают должным образом, так что это может быть только проблема с исправлением.   -  person Brice    schedule 14.03.2014


Ответы (3)


Проблема:

В Volleys HurlStack (HttpUrlConnection) есть вспомогательный код для PATCH. Тем не менее, кажется, что это по-прежнему выдает исключение, опубликованное в моем заголовке и трассировке стека, всякий раз, когда вы пытаетесь выполнить запрос PATCH.

Решение взлома:

1) Заставить Volley использовать HttpClientStack.

Ниже представлена ​​обновленная версия моего конструктора VolleySingleton. Это «работает», но явно тратит впустую реализацию Hurl, которая считается лучшей, если (Build.VERSION.SDK_INT >= 9). Не говоря уже о планах Google полностью отказаться от apache HttpClient в будущем.

private VolleySingleton(){
    mPreferences = MyApplication.getAppContext().getSharedPreferences(PrefConstants.PREFERENCES, 0);

    String userAgent = "volley/0";
    try {
        String packageName = MyApplication.getAppContext().getPackageName();
        PackageInfo info = MyApplication.getAppContext().getPackageManager().getPackageInfo(packageName, 0);
        userAgent = packageName + "/" + info.versionCode;
    } catch (NameNotFoundException e) {}

    HttpStack httpStack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
    mRequestQueue = Volley.newRequestQueue(MyApplication.getAppContext(), httpStack);
    mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {
        private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
        public void putBitmap(String url, Bitmap bitmap) {
            mCache.put(url, bitmap);
        }
        public Bitmap getBitmap(String url) {
            return mCache.get(url);
        }
    });
}

2) Продолжайте использовать вышеупомянутый VolleySingleton ТОЛЬКО для патча; переименуйте его в VolleySingletonPatch(), а затем, конечно, создайте VolleySingleton() по умолчанию для ВСЕХ других вызовов НЕ-PATCH. (лучше, чем 1, но все же не оптимально)

3) Устранить исключение, возникающее в HurlStack, несмотря на то, что Volley реализовал PATCH. Это было бы ЛУЧШЕ, но я предпочитаю не возиться с Volley напрямую и не расширять свои собственные HttpStacks без необходимости.

Я оставляю это без ответа, так как буду очень признателен за любую информацию и, конечно, лучшие варианты, чем те, которые я придумал здесь.

person Brice    schedule 14.03.2014

У меня тоже была эта проблема, мое решение состояло в том, чтобы просто отказаться от базовых встроенных HTTP-компонентов Apache и использовать библиотеку OkHttp от Square, используя эта HttpStack реализация для Volley, использующая OkHttp в качестве транспорта. Работает отлично.

person akent    schedule 23.10.2014
comment
Здравствуйте @akent, не могли бы вы поделиться тем, как на самом деле использовать реализацию в вашем классе? Я имею в виду, что я перешел по ссылке и все, и добавил библиотеку OkHttp, а также добавил Volley.newRequestQueue(getApplicationContext(), new OkHttpStack()); перед AppController.getInstance().addToRequestQueue(sendData);. Это верно? Спасибо! - person ito; 24.01.2015

Я знаю, что этот вопрос устарел, но предоставление решения может помочь тому, кто еще не сталкивался с такой же проблемой.

JSONObject param = new JSONObject();
    try {
        param.put(KEY 1, VALUE 1);
        param.put(KEY 2, VALUE 2);

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

        //ID represents the id for the record to update
    JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.PATCH, YOUR URL+ "?ID=" + ID, param,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                 //call handler to display response (optional)

                }
            }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            //call handler to display response (optional)

        }

    }) {

        //            Passing header
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("Content-Type", "application/json; charset=utf-8");
            headers.put("x-api-key", "YOUR API KEY");
            return headers;
        }

        @Override
        protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {

           //use this to check positive response code returned else remove this override part

            return super.parseNetworkResponse(response);
        }
    };
    //and then you pass json data to volley
    VolleySingleton.getInstance(getActivity()).addToRequestQueue(jsonObjReq);
person user2341596    schedule 08.05.2019