我想将会话密钥和其他信息存储在sharedpreference中,并在调用另一个api时将其检索。我指的是这个答案-https://stackoverflow.com/a/16743595/10243953。我制作了一个单独的类MyApp,并调用了其用于存储和检索信息的方法。这是我的第一个带有会话的项目,所以我不太了解,但是我尝试了这段代码。
登录功能
public void LoginAPI(){
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.POST, LOGIN_URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// My Operations with response
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Snackbar.make(v,"LOGIN FAILED",Snackbar.LENGTH_SHORT).show();
}
}){
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
// the POST parameters:
params.put("identity", username);
params.put("pass",password);
return params;
}
//Storing Session Data
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
MyApp.get().checkSessionCookie(response.headers);
return super.parseNetworkResponse(response);
}
};
RequestQueue queue = Volley.newRequestQueue(this);
queue.add(stringRequest);
}
获取数据以添加会话数据
public void GetStudentData(){
progressBar.setVisibility(View.VISIBLE);
String parent_id = SharedPreferenceManager.getmInstance(getContext()).getID();
StringRequest stringRequest = new StringRequest(Request.Method.GET, GET_STUDENT_URL+parent_id, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
progressBar.setVisibility(View.GONE);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}){
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
return super.parseNetworkResponse(response);
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> headers = super.getHeaders();
if (headers == null || headers.equals(Collections.<String, String>emptyMap())){
headers = new HashMap<String, String>();
}
MyApp.get().addSessionCookie(headers);
return headers;
}
};
RequestQueue queue = Volley.newRequestQueue(getContext());
queue.add(stringRequest);
}
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<String, String> 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];
SharedPreferences.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<String, String> 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());
}
}
}
证据
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.acg.digimkeyparent">
<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<activity
android:name=".Slide"
android:theme="@style/Theme.AppCompat.NoActionBar" />
<activity
android:name=".Login"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
<activity
android:name=".ForgotPassword"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
<activity android:name=".ResetPassword" />
<activity android:name=".EditNumber" />
<activity android:name=".OTP" />
<activity android:name=".ProfileChild" />
<activity
android:name=".SplashScreen"
android:theme="@style/Theme.AppCompat.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".GSMRegistrationIntentService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" />
<activity android:name=".ChangePassword" />
<activity android:name=".ChangeMobile" />
<activity android:name=".StudentDashboard" />
</application>
</manifest>
错误-登录功能
E/Volley: [462] NetworkDispatcher.processRequest: Unhandled exception java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.acg.digimkeyparent.MyApp.checkSessionCookie(java.util.Map)' on a null object reference
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.acg.digimkeyparent.MyApp.checkSessionCookie(java.util.Map)' on a null object reference
at com.example.acg.digimkeyparent.Login$5.parseNetworkResponse(Login.java:186)
at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:132)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:87)
答案 0 :(得分:0)
将此行android:name=".MyApp"
添加到AndroidManifest.xml
文件中的应用程序标记中
<application
android:name=".MyApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
尝试一下!
答案 1 :(得分:0)
我将删除该MyApp.get()
,它返回NULL
并进行静态调用,例如:
public static boolean checkSessionCookie(Map<String, String> 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];
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor prefEditor = preferences.edit();
prefEditor.putString(SESSION_COOKIE, cookie);
prefEditor.commit();
return true;
}
}
return false;
}
同样可用boolean hasCookie = MyApp.checkSessionCookie(response.headers);
...在MyApp
中引用Mainfest.xml
时,它还应返回实例,但具有static
Context
字段的对象很容易Context
leaks;最好尽可能避免。您只需要从该Preferences
方法中获取static
的句柄; getApplicationContext()
最有可能满足要求。