Выкарыстанне печыва з Android бібліятэкі залпавага

Хто-небудзь ведае, як прымацаваць печыва сесіі на запыт з выкарыстаннем com.android.volley бібліятэкі? Калі я ўвайсці на вэб-сайт дае мне печыва сесіі. Браўзэр будзе пасылаць то печыва таму з любым наступным запытам. Залп, здаецца, не рабіць гэтага, па меншай меры, не аўтаматычна.

Дзякуючы.

48
«Не ўся мэта залпу, каб схаваць гэтую складанасць?» - як я ўжо пісаў, AFAIK печыва сесіі апрацоўваюцца HTTP транспартнага кода. Мая прапанова аб спробе аднаго з гэтых транспартаў непасрэдна павінен быў бачыць, калі ваша праблема захоўваецца, і ў гэтым выпадку гэта не праблема залпу, але што-небудзь ці ў Android або на сэрвэры. «Ці ёсць у вас якія-небудзь прапановы, як атрымаць доступ да ніжняга слоя?» - ставіць Volley ў бок на дадзены момант і запіс ў «ніжні пласт» самастойна. <�Код> HttpURLConnection , у прыватнасці, быў вакол на працягу ~ 15 гадоў, і ёсць шмат прыкладаў таго, як выкарыстоўваць яго.
дададзена аўтар CommonsWare, крыніца
Гэта павінна быць функцыяй базавай HTTP-транспартнага ўзроўню (напрыклад, HttpURLConnection , HttpClient ), а не Залп сябе. Вы спрабавалі выкарыстоўваць адзін з тых, хто непасрэдна?
дададзена аўтар CommonsWare, крыніца
Так як печыва проста звычайны загаловак HTTP, вы можаце захаваць гэты загаловак, выкарыстоўваючы NetworkResponse.headers поле, а затым прымацаваць яго да любы наступны запыт на пераазначэнне Request.getHeaders метад
дададзена аўтар Vladimir Mironov, крыніца
CommonsWare, у мяне няма. Не ўся мэта залпу, каб схаваць гэтую складанасць? Я прайшоў праз выбар залпу і не змог знайсці які-небудзь доступ да ніжэйлеглую пласту. Ці ёсць у вас якія-небудзь прапановы, як атрымаць доступ да ніжняга слоя? Дзякуючы.
дададзена аўтар Rastio, крыніца
Для тых, хто сочыць ў гэтай тэме, у мяне ёсць сачыць за пытаннем. stackoverflow.com/questions/18413846/…
дададзена аўтар TestBest, крыніца

10 адказы

Залп фактычна не робіць HTTP-запытаў сябе, і такім чынам не ўдаецца печыва непасрэдна. Замест гэтага ён выкарыстоўвае асобнік HttpStack, каб зрабіць гэта. Ёсць два асноўных рэалізацый:

  • HurlStack: Выкарыстоўвае HttpURLConnection пад капотам
  • HttpClientStack: выкарыстоўвае Apache HttpClient пад капотам

Упраўленне Cookie з'яўляецца абавязкам гэтых HttpStacks. І кожны з іх апрацоўваць печыва па-рознаму.

If you need to support < 2.3, then you should use the HttpClientStack:

Настройка асобніка HttpClient і перадаць, што Залп для таго, каб выкарыстоўваць пад капотам:

// If you need to directly manipulate cookies later on, hold onto this client
// object as it gives you access to the Cookie Store
DefaultHttpClient httpclient = new DefaultHttpClient();

CookieStore cookieStore = new BasicCookieStore();
httpclient.setCookieStore( cookieStore );

HttpStack httpStack = new HttpClientStack( httpclient );
RequestQueue requestQueue = Volley.newRequestQueue( context, httpStack  );

Перавага гэтага супраць ўручную ўставіць кук у загалоўкі, што вы атрымаеце фактычнае кіраванне печывам. Печыва ў вашым краме будуць правільна рэагаваць на элементы кіравання HTTP, якія мінаюць або абнаўляць іх.

Я пайшоў далей і на поўдзень класіфікавацца BasicCookieStore, так што я магу аўтаматычна захоўваюцца мае печыва на дыск.

HOWEVER! If you don't need to support older versions of Android. Just use this method:

// CookieStore is just an interface, you can implement it and do things like
// save the cookies to disk or what ever.
CookieStore cookieStore = new MyCookieStore();
CookieManager manager = new CookieManager( cookieStore, CookiePolicy.ACCEPT_ALL );
CookieHandler.setDefault( manager  );

// Optionally, you can just use the default CookieManager
CookieManager manager = new CookieManager();
CookieHandler.setDefault( manager  );

HttpURLConnection будзе запытваць CookieManager ад няяўна. HttpURLConnection таксама з'яўляецца больш прадукцыйным і трохі чысцей ажыццяўляць і працаваць з ИМО.

55
дададзена
@Adam, дзякуй, я выкарыстаў па змаўчанні CookieManager ў загалоўкі зараз выкарыстоўваюцца правільныя. Але калі я перанакіроўваць на іншы від дзейнасці, гэтыя загалоўкі не з'яўляюцца часткай запыту больш, нават калі я ўсталёўваю cookiemanager OnCreate дзейнасці, ёсць спосаб зрабіць гэта настойлівы паміж дзейнасцю?
дададзена аўтар Woppi, крыніца
жадаю вам таксама падзяліўся з намі, ваш MyCookieStore клас
дададзена аўтар azerafati, крыніца
Гэта працуе для мяне. Я завёўся толькі з дапамогай па змаўчанні CookieManager. Як няма, заклікаючы CookieHandler.getDefault (). Але няхай будзе() патрабуе Map >. Рэалізацыя па змаўчанні пакласці() разбірае печыва з карты і патрабуе, каб ключ альбо (адчувальна да рэгістра) «Set-Cookie» або «набор-Cookie2». Прыйшлося вывучыць крыніца, каб знайсці гэта.
дададзена аўтар Jordan Bondo, крыніца

vmirinov мае рацыю!

Вось як я вырашыў гэтую праблему:

Запыт клас:

public class StringRequest extends com.android.volley.toolbox.StringRequest {

    private final Map _params;

    /**
     * @param method
     * @param url
     * @param params
     *            A {@link HashMap} to post with the request. Null is allowed
     *            and indicates no parameters will be posted along with request.
     * @param listener
     * @param errorListener
     */
    public StringRequest(int method, String url, Map params, Listener listener,
            ErrorListener errorListener) {
        super(method, url, listener, errorListener);

        _params = params;
    }

    @Override
    protected Map getParams() {
        return _params;
    }

    /* (non-Javadoc)
     * @see com.android.volley.toolbox.StringRequest#parseNetworkResponse(com.android.volley.NetworkResponse)
     */
    @Override
    protected Response parseNetworkResponse(NetworkResponse response) {
       //since we don't know which of the two underlying network vehicles
       //will Volley use, we have to handle and store session cookies manually
        MyApp.get().checkSessionCookie(response.headers);

        return super.parseNetworkResponse(response);
    }

    /* (non-Javadoc)
     * @see com.android.volley.Request#getHeaders()
     */
    @Override
    public Map getHeaders() throws AuthFailureError {
        Map headers = super.getHeaders();

        if (headers == null
                || headers.equals(Collections.emptyMap())) {
            headers = new HashMap();
        }

        MyApp.get().addSessionCookie(headers);

        return headers;
    }
}

і MyApp:

public class MyApp extends Application {
    private static final String SET_COOKIE_KEY = "Set-Cookie";
    private static final String COOKIE_KEY = "Cookie";
    private static final String SESSION_COOKIE = "sessionid";

    private static MyApp _instance;
  private RequestQueue _requestQueue;
  private SharedPreferences _preferences;

    public static MyApp get() {
        return _instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        _instance = this;
            _preferences = PreferenceManager.getDefaultSharedPreferences(this);
        _requestQueue = Volley.newRequestQueue(this);
    }

    public RequestQueue getRequestQueue() {
        return _requestQueue;
    }


    /**
     * Checks the response headers for session cookie and saves it
     * if it finds it.
     * @param headers Response Headers.
     */
    public final void checkSessionCookie(Map headers) {
        if (headers.containsKey(SET_COOKIE_KEY)
                && headers.get(SET_COOKIE_KEY).startsWith(SESSION_COOKIE)) {
                String cookie = headers.get(SET_COOKIE_KEY);
                if (cookie.length() > 0) {
                    String[] splitCookie = cookie.split(";");
                    String[] splitSessionId = splitCookie[0].split("=");
                    cookie = splitSessionId[1];
                    Editor prefEditor = _preferences.edit();
                    prefEditor.putString(SESSION_COOKIE, cookie);
                    prefEditor.commit();
                }
            }
    }

    /**
     * Adds session cookie to headers if exists.
     * @param headers
     */
    public final void addSessionCookie(Map headers) {
        String sessionId = _preferences.getString(SESSION_COOKIE, "");
        if (sessionId.length() > 0) {
            StringBuilder builder = new StringBuilder();
            builder.append(SESSION_COOKIE);
            builder.append("=");
            builder.append(sessionId);
            if (headers.containsKey(COOKIE_KEY)) {
                builder.append("; ");
                builder.append(headers.get(COOKIE_KEY));
            }
            headers.put(COOKIE_KEY, builder.toString());
        }
    }

}
39
дададзена
Я толькі змяніў ўтрыманне SESSION_COOKIE роўным "PHPSESSID» і яго праца.
дададзена аўтар FinalDark, крыніца
варта адзначыць, што загаловак можа вярнуцца ў «Set-Cookie», як у вас ёсць, або «Set-Cookie» - у гэтым выпадку гэты код будзе ламацца.
дададзена аўтар Sam Dozor, крыніца
Звярніце ўвагу, што калі ёсць больш чым адзін печыва, будуць некалькі «Set-Cookie» загалоўкамі і як загалоўкі адказу з'яўляецца картай, вы атрымаеце толькі першы! Так, гэта Volley бібліятэка не хапае некаторых рэчаў. Які абмяркоўваецца над на гэты пытанні: StackOverflow .com/пытанні/18998361/& hellip;
дададзена аўтар georgiecasey, крыніца
гэта толькі для запыту радкі справа? Як наконт таго для аб'екта JSON і запыту масіва.
дададзена аўтар Yakob Ubaidi, крыніца
@TestBest, захоўванне у наладах робіць печыва, каб выжыць выхад прыкладання. Ваш выбар, калі вы хочаце, каб печыва сесіі, каб працягнуцца даўжэй, чым адзін дадаткам перспектывы.
дададзена аўтар Rastio, крыніца
Акрамя таго, што перавагі захоўвання печыва агульных пераваг. Чаму б не захаваць яго як статычны член класа?
дададзена аўтар TestBest, крыніца
Для тых, хто сочыць за пытанне, у мяне ёсць сачыць за пытаннем. stackoverflow.com/questions/18413846/…
дададзена аўтар TestBest, крыніца

HTTP транспартны код па змаўчанні залп HttpURLConnection . Калі я чытаю дакументацыі правільна, вы павінны абраць у аўтаматычны падтрымка печыва сесіі:

CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

See also Should HttpURLConnection with CookieManager automatically handle session cookies?

19
дададзена
дзе дадаць гэты код, калі я выкарыстоўваю залп!
дададзена аўтар kuldeep, крыніца
Рэалізацыя па змаўчанні транспарт фактычна залежыць ад андроіда версіі канкрэтнага прылады ( HttpURLConnection для Gingerbread і вышэй, і HttpClient для папярэдніх версій), і вы не павінны спадзявацца на яго
дададзена аўтар Vladimir Mironov, крыніца
Працэнт карыстальнікаў Android ніжэй Gingerbread ў цяперашні час 2,2%. Я асабіста не клапаціцца пра іх. Так што я згодны з CommonsWare і проста дадаў CookieHandler.setDefault (новы CookieManager (нуль, CookiePolicy.ACCEPT_ALL)); у канструктару HurlStack. Працуе выдатна.
дададзена аўтар georgiecasey, крыніца
Што georgiecasey гаворыць толькі пляма на і гэта сапраўды працуе!
дададзена аўтар slott, крыніца
Увайсці вэб-сэрвіс, выклікаць яго працу пасля наступнага Лагін падпаслядоўнасці вэб-службы выкліку я хачу, каб адправіць ідэнтыфікатар сеансу на сервер з дапамогай бібліятэкі залпу, як я магу ў стане паслаць ?? не маглі б вы мне дапамагчы
дададзена аўтар John, крыніца
дзе я павінен змясціць гэта ў кодзе?
дададзена аўтар John, крыніца
Звярніце ўвагу, транспарт па змаўчанні задаецца ў класе Volley хелперов, android.googlesource.com/platform/frameworks/volley/+/майстар & ZWNJ;/& hellip; , калі вы відавочна не прапускаць HttpStack да newRequestQueue. Быў бы проста напісаць сваю ўласную версію гэтага newRequestQueue дапаможнага метаду, які робіць правільную рэч, незалежна ад таго, ці выкарыстоўваецца HurlStack або HttpClientStack.
дададзена аўтар adevine, крыніца
Гэта тое, што маё разуменьне было. Адказ Commons Ware з'яўляецца правільным у выпадку залпавага выбірае HttpURLConnection. Вось чаму я чакаў бы залп справіцца з гэтым. Я ад кампутара на працягу некалькіх дзён. Я праверу, калі некаторыя спадчыну можа дапамагчы.
дададзена аўтар Rastio, крыніца
Добра. Так ці ёсць спосаб выбраць, каб сесійныя печыва для абодвух тыпаў кліентаў HttpURLConnection і HttpClient? Глядзіце мой развілі пытанне: stackoverflow.com/ пытанні/18413846/& hellip;
дададзена аўтар TestBest, крыніца

Хлопцы спрабуюць гэта OnCreate метад вашага AppController.java

  CookieHandler.setDefault(new CookieManager());

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

10
дададзена
Дзякуй, усё так проста!
дададзена аўтар hiddeneyes02, крыніца

@Rastio рашэнне не працуе, калі ёсць некалькі «Set-Cookie» загалоўкі. Я загарнуў па змаўчанні CookieManager печыва крамы за і перад даданнем печыва я захаваў яго ў SharedPreferences выкарыстоўваючы Gson сериализовать печыва.

Гэта прыклад печыва крамы абгортка:

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import com.google.gson.Gson;

import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.List;

/**
 * Class that implements CookieStore interface. This class saves to SharedPreferences the session
 * cookie.
 *
 * Created by lukas.
 */
public class PersistentCookieStore implements CookieStore {

    private CookieStore mStore;
    private Context mContext;
    private Gson mGson;

    public PersistentCookieStore(Context context) {
       //prevent context leaking by getting the application context
        mContext = context.getApplicationContext();
        mGson = new Gson();

       //get the default in memory store and if there is a cookie stored in shared preferences,
       //we added it to the cookie store
        mStore = new CookieManager().getCookieStore();
        String jsonSessionCookie = Prefs.getJsonSessionCookie(mContext);
        if (!jsonSessionCookie.equals(Prefs.DEFAULT_STRING)) {
            HttpCookie cookie = mGson.fromJson(jsonSessionCookie, HttpCookie.class);
            mStore.add(URI.create(cookie.getDomain()), cookie);
        }
    }

    @Override
    public void add(URI uri, HttpCookie cookie) {
        if (cookie.getName().equals("sessionid")) {
           //if the cookie that the cookie store attempt to add is a session cookie,
           //we remove the older cookie and save the new one in shared preferences
            remove(URI.create(cookie.getDomain()), cookie);
            Prefs.saveJsonSessionCookie(mContext, mGson.toJson(cookie));
        }

        mStore.add(URI.create(cookie.getDomain()), cookie);
    }

    @Override
    public List get(URI uri) {
        return mStore.get(uri);
    }

    @Override
    public List getCookies() {
        return mStore.getCookies();
    }

    @Override
    public List getURIs() {
        return mStore.getURIs();
    }

    @Override
    public boolean remove(URI uri, HttpCookie cookie) {
        return mStore.remove(uri, cookie);
    }

    @Override
    public boolean removeAll() {
        return mStore.removeAll();
    }
}

Затым, каб выкарыстоўваць краму печыва проста ўсталяваць у CookieManager і вось яно!

CookieManager cookieManager = new CookieManager(new PersistentCookieStore(mContext),
    CookiePolicy.ACCEPT_ORIGINAL_SERVER);
CookieHandler.setDefault(cookieManager);
10
дададзена
@Lukas Вы можаце ўдакладніць ваш прыклад? Я маю на ўвазе, як вы эканоміць гэтыя некалькі Cookies ў агульнай прышчапіць?
дададзена аўтар aB9, крыніца
У канструктару PersistentCookieStore, я думаю, што нам трэба, каб атрымаць спіс печыва захоўваюцца (не толькі адзін печыва) з SharedPreferences. Што думаеш? Акрамя таго, нам неабходна абнавіць SharedPreferences кожны раз, калі мы абнаўляем mStore таксама.
дададзена аўтар Mr Cold, крыніца

Я ведаю, што пост і трохі стары, але мы прайшлі праз гэтую нядаўняга праблемы, мы павінны падзяліць сесію які ўвайшоў карыстальніка паміж серверамі, і на боку сервера рашэнне пачатак патрабаваць значэнні павінны быць прадастаўлена на баку кліента, праз кук. Адным з рашэнняў мы выявілі, было дадаць параметр RequestQueue аб'ект, фрагмент кода ў метадзе getRequestQueue Перад инстанцирования RequestQueue знойдзеную на спасылку ніжэй , і вырашыць гэтую праблему, не ведаю, як, але ён пачаў працаваць.

Visit http://woxiangbo.iteye.com/blog/1769122

public class App extends Application {

    public static final String TAG = App.class.getSimpleName();

    private static App         mInstance;

    public static synchronized App getInstance() {
        return App.mInstance;
    }

    private RequestQueue mRequestQueue;

    public  void addToRequestQueue( final Request req ) {
        req.setTag( App.TAG );
        this.getRequestQueue().add( req );
    }

    public  void addToRequestQueue( final Request req, final String tag ) {
        req.setTag( TextUtils.isEmpty( tag ) ? App.TAG : tag );
        this.getRequestQueue().add( req );
    }

    public void cancelPendingRequests( final Object tag ) {
        if ( this.mRequestQueue != null ) {
            this.mRequestQueue.cancelAll( tag );
        }
    }

    public RequestQueue getRequestQueue() {

        if ( this.mRequestQueue == null ) {


            DefaultHttpClient mDefaultHttpClient = new DefaultHttpClient();

            final ClientConnectionManager mClientConnectionManager = mDefaultHttpClient.getConnectionManager();
            final HttpParams mHttpParams = mDefaultHttpClient.getParams();
            final ThreadSafeClientConnManager mThreadSafeClientConnManager = new ThreadSafeClientConnManager( mHttpParams, mClientConnectionManager.getSchemeRegistry() );

            mDefaultHttpClient = new DefaultHttpClient( mThreadSafeClientConnManager, mHttpParams );

            final HttpStack httpStack = new HttpClientStack( mDefaultHttpClient );

            this.mRequestQueue = Volley.newRequestQueue( this.getApplicationContext(), httpStack );
        }

        return this.mRequestQueue;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        App.mInstance = this;
    }
}

// ўсталяваць маркер значэнне

ObjectRequest.setHeader( "Cookie", "JSESSIONID=" + tokenValueHere );
5
дададзена
Я абнавіў адказ.
дададзена аўтар Anderson K, крыніца
Вялікі дзякуй ObjectRequest.setHeader ( "Cookie", "JSESSIONID =" + tokenValueHere); гэты радок выратавала мой дзень @ AndersonK
дададзена аўтар naresh vadlakonda, крыніца
Дзе Вы дадаеце печыва?
дададзена аўтар AZ_, крыніца

<�Моцны> Выкарыстоўвайце гэты метад, каб выкарыстоўваць Volley з печывам у:

  1. Выкарыстоўвайце толькі вельмі добра выпрабаваны код пад ліцэнзіяй Apache 2 ліцэнзіі
  2. Зрабіце так шмат запытаў, як вы хацелі б у той жа час
  3. Пераканайцеся, што печыва захоўваюцца на прыладзе
  4. Не маючы вынаходзіць кола

Мой сервер выкарыстоўвае печыва для аўтэнтыфікацыі і, відавочна, я хацеў пераканацца, што печыва захоўваюцца на прыладзе. Таму маё рашэнне было выкарыстоўваць PersistentCookieStore і SerializableCookie класы ад Асінхронны Http кліент для Android .

Па-першае, для таго, каб уключыць адначасовых запытаў , Апачі HttpClient v4.3 порт для Android патрэбны - адзін, які пастаўляецца з сістэмай састарэла. Больш падрабязная інфармацыя . Я выкарыстоўваю Gradle, дык гэта тое, як я імпартаваў яго:

dependencies {
    compile group: 'org.apache.httpcomponents' , name: 'httpclient-android' , version: '4.3.3'
}

Функцыя, каб атрымаць RequestQueue (у маім класе, які пашырае дадатак):

private RequestQueue mRequestQueue;
private CloseableHttpClient httpClient;

...

public RequestQueue getRequestQueue() {
    if (mRequestQueue == null) {
        httpClient = HttpClients.custom()
            .setConnectionManager(new PoolingHttpClientConnectionManager())
            .setDefaultCookieStore(new PersistentCookieStore(getApplicationContext()))
            .build();
        mRequestQueue = Volley.newRequestQueue(getApplicationContext(), new HttpClientStack(httpClient));
    }
    return mRequestQueue;
}

Гэта, як я чарга запыту

public  void addToRequestQueue(Request req, String tag) {
    req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
    getRequestQueue().add(req);
}

Вось так!

2
дададзена
Не ўпэўнены, што вы маеце на ўвазе - гэта дакладны код я бягу. Ён працаваў добра. Адказ на гэтае пытанне можа ставіцца да больш ранніх версіях Volley хоць
дададзена аўтар C0D3LIC1OU5, крыніца
setDefaultCookieStore не можа прыняць PersistentCookieStore ў якасці параметру
дададзена аўтар josh123a123, крыніца

Вось адзін з самых простых працоўных прыкладаў. Мне не падабаецца, REST, ня restfull. Але я думаю, што ўсё ідзе, як вопыт. Самае галоўнае, каб заўважыць у наступным прыкладзе, што curlget.php ня session_start. Якая мова вы выкарыстоўваеце, каб напісаць, што частка да вас. У наступным прыкладзе гэта можа быць што заўгодна, ад Явы да іржы. Яна таксама можа знайсці ў любым месцы.

login.php

PHP код:

<?php
session_start();
//we store any POST/GET request to session
$_SESSION['un'] = $_REQUEST['username'];
userinfo.php
PHP код:
<?php
session_start();
echo json_encode($_SESSION['un']);

curlget.php PHP код:

<?php
$ch = curl_init();
//we do login and get the session_id in from it's responce headers
curl_setopt($ch, CURLOPT_URL,"http://localhost/login.php");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,"username=test");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec ($ch);
//we get the cookie from response header with the hardest possible way
//most platforms have tools for these
preg_match_all('/^Set-Cookie:\s*([^\r\n]*)/mi', $result, $ms);
$cookies = array();
foreach ($ms[1] as $m) {
    list($name, $value) = explode('=', $m, 2);
    $cookies[$name] = $value;
}
$parts = explode(";",$cookies['PHPSESSID']);
//The SessionId finally 
$SID = $parts[0];
curl_close ($ch);

// запыт GET з выкарыстаннем SID ад папярэдняга выкліку

2
дададзена
запыт быў аб стварэнні печыва з выкарыстаннем бібліятэкі андроіда залпу і не мае нічога агульнага з PHP
дададзена аўтар Manuela, крыніца

Калі вы ўжо пачалі рэалізацыю прыкладання, выкарыстоўваючы бібліятэку Loopj, вы заўважыце, што вы не можаце выкарыстоўваць новы асобнік HttpClient ў Volley.newRequestQUeue (), таму што вы атрымаеце розныя памылкі пра не зачыняючы папярэднюю сувязь і г.д.

Памылкі падабаецца:

java.lang.IllegalStateException: No wrapped connection

Invalid use of SingleClientConnManager: connection still allocated.

Зараз часам патрабуецца час, каб рэарганізаваць усе свае старыя выклікі API і перапісаць іх з дапамогай залпу, але вы можаце выкарыстоўваць залп і loopj адначасова і падзяляеце CookieStore паміж тымі, два, пакуль вы не напішаце ўсё ў залп (выкарыстоўвайце залп замест loopj, яго нашмат лепш :)).

Гэта, як вы можаце падзяліцца HttpClient і CookieStore з loopj з залпам.

// For example you initialize loopj first
private static AsyncHttpClient client = new AsyncHttpClient();
sCookieStore = new PersistentCookieStore(getSomeContextHere());
client.setTimeout(DEFAULT_TIMEOUT);
client.setMaxConnections(12);
client.setCookieStore(sCookieStore);
client.setThreadPool(((ThreadPoolExecutor) Executors.newCachedThreadPool()));

public static RequestQueue getRequestQueue(){
    if(mRequestQueue == null){

    HttpClient httpclient = KkstrRestClient.getClient().getHttpClient();

    ((AbstractHttpClient) httpclient).setCookieStore( ApplicationController.getCookieStore() );

    HttpStack httpStack = new HttpClientStack(httpclient);

    mRequestQueue = Volley.newRequestQueue(getContext(), httpStack);
    }

    return mRequestQueue;
}

Гэта здарылася са мной, мы пачалі выкарыстоўваць loopj. Пасля 50 000 радкоў кода і адкрыццё, што loopj не заўсёды працуюць, як чакаецца, мы вырашылі пераключыцца на залп.

1
дададзена
ура, ты паставіў мяне на правільным шляху, каб выправіць памылку шаленства. Я выкарыстоўваю як loopj і залп ў маім дадатку і трэба як (не пытайцеся!). ваш дакладны адказ не працуе, але гэта адзін зрабіў, то ж ідэю, проста атрымаць THREADSAFE DefaultHttpClient для валейбола печыва: stackoverflow.com/a/ 6737645/467509
дададзена аўтар georgiecasey, крыніца

Адказ @CommonsWare гэта адзін я хацеў бы выкарыстаць. Тым не менш, гэта выглядае як KitKat церпіць некаторыя памылкі , калі гэта будзе зроблена ( пры стварэнні CookieManager персаналізаванай CookieStore , які вам трэба, калі вы хочаце, пастаянныя Cookies). Улічваючы той факт, што незалежна ад рэалізацыі CookieStore , які выкарыстоўваецца, Volley б кінуць NullPointerException , я павінен быў стварыць свой уласны CookieHandler . .. выкарыстоўваць яго, калі вы знойдзеце яго карысным.

public class MyCookieHandler extends CookieHandler {

private static final String VERSION_ZERO_HEADER = "Set-cookie";

private static final String VERSION_ONE_HEADER = "Set-cookie2";
private static final String COOKIE_HEADER = "Cookie";

private static final String COOKIE_FILE = "Cookies";
private Map> urisMap;

private Context context;

public MyCookieHandler(Context context) {

    this.context = context;
    loadCookies();

}

@SuppressWarnings("unchecked")
private void loadCookies() {
    File file = context.getFileStreamPath(COOKIE_FILE);
    if (file.exists())
        try {

            FileInputStream fis = context.openFileInput(COOKIE_FILE);
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    fis));
            String line = br.readLine();
            StringBuilder sb = new StringBuilder();
            while (line != null) {
                sb.append(line);
                line = br.readLine();
            }
            Log.d("MyCookieHandler.loadCookies", sb.toString());
            JSONObject jsonuris = new JSONObject(sb.toString());
            urisMap = new HashMap>();
            Iterator jsonurisiter = jsonuris.keys();

            while (jsonurisiter.hasNext()) {
                String prop = jsonurisiter.next();
                HashMap cookiesMap = new HashMap();
                JSONObject jsoncookies = jsonuris.getJSONObject(prop);
                Iterator jsoncookiesiter = jsoncookies.keys();
                while (jsoncookiesiter.hasNext()) {
                    String pprop = jsoncookiesiter.next();
                    cookiesMap.put(pprop,
                            jsonToCookie(jsoncookies.getJSONObject(pprop)));
                }
                urisMap.put(prop, cookiesMap);

            }

        } catch (Exception e) {

            e.printStackTrace();
        }
    else {
        urisMap = new HashMap>();
    }
}

@Override
public Map> get(URI arg0,
        Map> arg1) throws IOException {
    Log.d("MyCookieHandler.get",
            "getting Cookies for domain: " + arg0.getHost());
    Map cookies = urisMap.get(arg0.getHost());
    if (cookies != null)
        for (Entry cookie : cookies.entrySet()) {
            if (cookie.getValue().hasExpired()) {
                cookies.remove(cookie.getKey());
            }
        }

    if (cookies == null || cookies.isEmpty()) {
        Log.d("MyCookieHandler.get", "======");
        return Collections.emptyMap();
    }
    Log.d("MyCookieHandler.get",
            "Cookie : " + TextUtils.join("; ", cookies.values()));
    Log.d("MyCookieHandler.get", "======");
    return Collections.singletonMap(COOKIE_HEADER, Collections
            .singletonList(TextUtils.join("; ", cookies.values())));
}

@Override
public void put(URI uri, Map> arg1) throws IOException {
    Map cookies = parseCookies(arg1);
    Log.d("MyCookieHandler.put",
            "saving Cookies for domain: " + uri.getHost());

    addCookies(uri, cookies);
    Log.d("MyCookieHandler.put",
            "Cookie : " + TextUtils.join("; ", cookies.values()));
    Log.d("MyCookieHandler.put", "======");

}

private void addCookies(URI uri, Map cookies) {
    if (!cookies.isEmpty()) {
        if (urisMap.get(uri.getHost()) == null) {
            urisMap.put(uri.getHost(), cookies);
        } else {
            urisMap.get(uri.getHost()).putAll(cookies);
        }
        saveCookies();
    }
}

private void saveCookies() {
    try {
        FileOutputStream fos = context.openFileOutput(COOKIE_FILE,
                Context.MODE_PRIVATE);

        JSONObject jsonuris = new JSONObject();
        for (Entry> uris : urisMap
                .entrySet()) {
            JSONObject jsoncookies = new JSONObject();
            for (Entry savedCookies : uris.getValue()
                    .entrySet()) {
                jsoncookies.put(savedCookies.getKey(),
                        cookieToJson(savedCookies.getValue()));
            }
            jsonuris.put(uris.getKey(), jsoncookies);
        }
        fos.write(jsonuris.toString().getBytes());
        fos.close();
        Log.d("MyCookieHandler.addCookies", jsonuris.toString());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static JSONObject cookieToJson(HttpCookie cookie) {
    JSONObject jsoncookie = new JSONObject();
    try {
        jsoncookie.put("discard", cookie.getDiscard());
        jsoncookie.put("maxAge", cookie.getMaxAge());
        jsoncookie.put("secure", cookie.getSecure());
        jsoncookie.put("version", cookie.getVersion());
        jsoncookie.put("comment", cookie.getComment());
        jsoncookie.put("commentURL", cookie.getCommentURL());
        jsoncookie.put("domain", cookie.getDomain());
        jsoncookie.put("name", cookie.getName());
        jsoncookie.put("path", cookie.getPath());
        jsoncookie.put("portlist", cookie.getPortlist());
        jsoncookie.put("value", cookie.getValue());

    } catch (JSONException e) {

        e.printStackTrace();
    }

    return jsoncookie;
}

private static HttpCookie jsonToCookie(JSONObject jsonObject) {
    HttpCookie httpCookie;
    try {
        httpCookie = new HttpCookie(jsonObject.getString("name"),
                jsonObject.getString("value"));
        if (jsonObject.has("comment"))
            httpCookie.setComment(jsonObject.getString("comment"));
        if (jsonObject.has("commentURL"))
            httpCookie.setCommentURL(jsonObject.getString("commentURL"));
        if (jsonObject.has("discard"))
            httpCookie.setDiscard(jsonObject.getBoolean("discard"));
        if (jsonObject.has("domain"))
            httpCookie.setDomain(jsonObject.getString("domain"));
        if (jsonObject.has("maxAge"))
            httpCookie.setMaxAge(jsonObject.getLong("maxAge"));
        if (jsonObject.has("path"))
            httpCookie.setPath(jsonObject.getString("path"));
        if (jsonObject.has("portlist"))
            httpCookie.setPortlist(jsonObject.getString("portlist"));
        if (jsonObject.has("secure"))
            httpCookie.setSecure(jsonObject.getBoolean("secure"));
        if (jsonObject.has("version"))
            httpCookie.setVersion(jsonObject.getInt("version"));
        return httpCookie;
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return null;

}

private Map parseCookies(Map> map) {
    Map response = new HashMap();

    for (Entry> e : map.entrySet()) {
        String key = e.getKey();
        if (key != null
                && (key.equalsIgnoreCase(VERSION_ONE_HEADER) || key
                        .equalsIgnoreCase(VERSION_ZERO_HEADER))) {
            for (String cookie : e.getValue()) {
                try {
                    for (HttpCookie htpc : HttpCookie.parse(cookie)) {
                        response.put(htpc.getName(), htpc);
                    }
                } catch (Exception e1) {

                    Log.e("MyCookieHandler.parseCookies",
                            "Error parsing cookies", e1);
                }
            }

        }
    }
    return response;

}
}

Гэты адказ не быў старанна правераны. Я выкарыстаў JSON серыялізацыі печыва, таму што добра, што клас не рэалізуюць Serializable і гэта канчаткова.

0
дададзена