わかりました、Androidフォームを含むアプリケーション、2つのEditText、スピナー、およびログインボタンがあります。ユーザーはスピナーからサービスを選択し、ユーザー名とパスワードを入力しますをクリックし、[ログイン]をクリックします。データはPOSTを介して送信され、応答が返されて処理され、新しいWebViewが起動され、応答から生成されたHTML文字列が読み込まれ、ユーザーが選択したサービスのホームページが表示されます。
それですべてうまくいきます。これで、ユーザーがリンクをクリックしても、ログイン情報が見つからず、ページはユーザーに再度ログインするように求めます。ログインセッションがどこかでドロップされ、アプリのメイン部分を制御するクラスから、webviewアクティビティを起動するだけのクラスに情報を渡す方法がわかりません。
フォームログインボタンのonClickハンドラ:
private class FormOnClickListener implements View.OnClickListener {
public void onClick(View v) {
String actionURL, user, pwd, user_field, pwd_field;
actionURL = "thePageURL";
user_field = "username"; //this changes based on selections in a spinner
pwd_field = "password"; //this changes based on selections in a spinner
user = "theUserLogin";
pwd = "theUserPassword";
List<NameValuePair> myList = new ArrayList<NameValuePair>();
myList.add(new BasicNameValuePair(user_field, user));
myList.add(new BasicNameValuePair(pwd_field, pwd));
HttpParams params = new BasicHttpParams();
DefaultHttpClient client = new DefaultHttpClient(params);
HttpPost post = new HttpPost(actionURL);
HttpResponse response = null;
BasicResponseHandler myHandler = new BasicResponseHandler();
String endResult = null;
try { post.setEntity(new UrlEncodedFormEntity(myList)); }
catch (UnsupportedEncodingException e) { e.printStackTrace(); }
try { response = client.execute(post); }
catch (ClientProtocolException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
try { endResult = myHandler.handleResponse(response); }
catch (HttpResponseException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
List<Cookie> cookies = client.getCookieStore().getCookies();
if (!cookies.isEmpty()) {
for (int i = 0; i < cookies.size(); i++) {
cookie = cookies.get(i);
}
}
Intent myWebViewIntent = new Intent(MsidePortal.this, MyWebView.class);
myWebViewIntent.putExtra("htmlString", endResult);
myWebViewIntent.putExtra("actionURL", actionURL);
startActivity(myWebViewIntent);
}
}
そして、これが応答表示を処理するWebViewクラスです。
public class MyWebView extends Android.app.Activity {
private class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web);
MyWebViewClient myClient = new MyWebViewClient();
WebView webview = (WebView)findViewById(R.id.mainwebview);
webview.getSettings().setBuiltInZoomControls(true);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebViewClient(myClient);
Bundle extras = getIntent().getExtras();
if(extras != null)
{
// Get endResult
String htmlString = extras.getString("htmlString");
String actionURL = extras.getString("actionURL");
Cookie sessionCookie = MsidePortal.cookie;
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
if (sessionCookie != null) {
cookieManager.removeSessionCookie();
String cookieString = sessionCookie.getName()
+ "=" + sessionCookie.getValue()
+ "; domain=" + sessionCookie.getDomain();
cookieManager.setCookie(actionURL, cookieString);
CookieSyncManager.getInstance().sync();
}
webview.loadDataWithBaseURL(actionURL, htmlString, "text/html", "utf-8", actionURL);}
}
}
}
私はそのCookieソリューションの実装にさまざまな成功を収めてきました。私がログインしている1つのサービスで機能するようですが、サーバーにCookieを保持していることがわかります(古い、古いですが、機能し、変更したくありません)。ローカルマシン上のCookie。この設定では機能しません。
助言がありますか?
ある呼び出しから別の呼び出しへのCookieを保持する必要があります。新しいDefaultHttpClientを作成する代わりに、次のビルダーを使用します。
private Object mLock = new Object();
private CookieStore mCookie = null;
/**
* Builds a new HttpClient with the same CookieStore than the previous one.
* This allows to follow the http session, without keeping in memory the
* full DefaultHttpClient.
* @author Régis Décamps <[email protected]>
*/
private HttpClient getHttpClient() {
final DefaultHttpClient httpClient = new DefaultHttpClient();
synchronized (mLock) {
if (mCookie == null) {
mCookie = httpClient.getCookieStore();
} else {
httpClient.setCookieStore(mCookie);
}
}
return httpClient;
}
また、Builderクラスをアプリケーションのフィールドとして保持します。
これをURLログインアクティビティで使用する
List<Cookie> cookies = client.getCookieStore().getCookies();
if (!cookies.isEmpty()) {
for (int i = 0; i < cookies.size(); i++) {
cookie = cookies.get(i);
}
}
Cookie sessionCookie = cookie;
if (sessionCookie != null) {
String cookieString = sessionCookie.getName() + "="
+ sessionCookie.getValue() + "; domain="
+ sessionCookie.getDomain();
cookieManager
.setCookie("www.mydomain.com", cookieString);
CookieSyncManager.getInstance().sync();
}
Cookieを共有設定に保存し、必要に応じて他のアクティビティで読み込むことができます。
または 同様の質問 からこのアイデアを試してください。
それでも答えが必要な場合は知らないが、ここで役立つかもしれないいくつかの追加情報がここに来る
必要な場合cookieの同期を維持
// ensure any cookies set by the dialog are saved
CookieSyncManager.getInstance().sync();
そして、あなたがしたい場合Cookieをクリアする
public static void clearCookies(Context context) {
// Edge case: an illegal state exception is thrown if an instance of
// CookieSyncManager has not be created. CookieSyncManager is normally
// created by a WebKit view, but this might happen if you start the
// app, restore saved state, and click logout before running a UI
// dialog in a WebView -- in which case the app crashes
@SuppressWarnings("unused")
CookieSyncManager cookieSyncMngr =
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
}
新しいアクティビティが起動されると(新しいWebビューを起動するときも同じだと思います)、新しいプログラムを最初から起動します。この新しいアクティビティは、以前のアクティビティのデータにアクセスできません(データがインテントにアタッチされて渡される場合を除く)。
2つの可能な解決策:
1)putExtraはプリミティブデータを渡すためにのみ使用できるため、より複雑なものを渡すには、次のいずれかが必要です
a)より複雑な構造を実装するクラスにラップします
Parcelableインターフェイス。追加で保存できます。
b)より複雑な構造を実装するクラスにラップします
シリアル化可能なインターフェイス。これはエクストラに格納できます。
これらのアプローチはどちらもかなり複雑で、かなりの作業が必要です。
2)個人的に私はrdsによって提案されたアプローチを非常に好みます。明確にするために、rdsが言うとき:
builderクラスをアプリケーションのフィールドとして保持します。
彼はアプリケーションクラスを拡張することを意味すると思います。そこに格納されているプロパティは、すべてのアクティビティでグローバルに使用できます。この記事では、これを行う方法を非常に明確に説明しています: http://www.screaming-penguin.com/node/7746 AsyncTaskに関するものは無視できます(ただし、ある時点でそれが必要になります)、アプリケーションクラスの拡張に関する部分に集中してください。
数週間前にこの同様の問題が発生しました。これは、ボタンをクリックするたびに新しいDefaultHttpClientを作成するためです。1つのDefaultHttpClientを作成し、送信しようとするリクエストごとに同じDefaultHttpClientを使用してみてください。それは私の問題を解決しました
特定のユーザーを識別するために、Cookieに保存されているセッションIDを使用します。httpヘッダーでは、すべての言語に異なるセッションID名があります。ネットワークツールまたはブラウザを使用して、セッションIDが呼び出された名前を確認できます。
他の方法では、FacebookとTwitterの方法で、セッション関連のコードをすべて削除します。サーバーはアクセストークンを使用してユーザーを識別します。
私の言いたいことが分かりますか?
この行を使用しました-
_ if (sessionCookie != null) {
cookieManager.removeSessionCookie();
}
_
毎回新しいCookieを確実に受け取るため。
あなたが私が直面したのと同じ問題を経験したようです、以下のリンクを確認してください-
removeSessionCookie()の問題Android(code.google。、com)
removeSessionCookie()
はスレッドに実装されているため、呼び出されるたびに表示されます。スレッドが開始し、setCookie(url, cookieString);
が呼び出された後、設定した新しいCookieが削除されます。そのため、一部のデバイスではremoveSessionCookie()
がすでに実行されているので正常に機能しますが、一部のデバイスではCookieが削除され、問題が発生します。
Cookieを1つだけ設定しているため、このremoveSessionCookie();
を削除して、他のCookieと競合しないようにすることをお勧めします。コードはシームレスに機能します。