/*
* Copyright (C) 2010 mAPPn.Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mappn.gfan;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import com.mappn.gfan.common.util.Pair;
import com.mappn.gfan.common.util.SecurityUtil;
/**
* SeesionManager for GfanMobile
*
* @author andrew.wang
* @date 2010-9-27
* @since Version 0.5.0
*
*/
public class SessionManager implements Observer {
public static final String P_ISLOGIN = "pref.isLogin";
public static final String P_MARKET_USERNAME = "pref.market.username";
public static final String P_MARKET_PASSWORD = "pref.market.password";
public static final String P_REMEMBER_PASSWORD = "pref.remember.password";
public static final String P_UID = "pref.uid";
public static final String P_SCREEN_SIZE = "pref.screen.size";
public static final String P_OS_VERSION = "pref.os.version";
public static final String P_CARD_VERSION = "pref.card.version";
public static final String P_CATEGORY_VERSION = "pref.category.version";
public static final String P_UPGRADE_NUM = "pref.upgrade.num";
public static final String P_CLEAR_CACHE = "auto_clear_cache";
public static final String P_USER_COOKIES = "pref.cookies";
public static final String P_NO_APP_FILTER = "no_app_filter";
public static final String P_UPDATE_AVAILABIE = "pref.update.available";
public static final String P_UPDATE_VERSION_CODE = "pref.update.version.code";
public static final String P_UPDATE_DESC = "pref.update.desc";
public static final String P_UPDATE_URI = "pref.update.uri";
public static final String P_UPDATE_VERSION_NAME = "pref.update.version.name";
public static final String P_UPDATE_LEVEL = "pref.update.level";
public static final String P_PRODUCT_UPDATE_CHECK_TIMESTAMP = "pref.product.update.timestamp";
public static final String P_UPDATE_ID = "pref.update.id";
public static final String P_LPNS_BINDED_DEVID = "pref.lpns.binded.devid";
public static final String P_LPNS_IS_BINDED = "pref.lpns.is.binded";
public static final String P_DEFAULT_CHARGE_TYPE = "pref.charge.defaultChargeType";
// splash info
public static final String P_SPLASH_TIME = "pref.splash.time";
public static final String P_SPLASH_ID = "pref.splash.id";
// version name
public static final String P_CURRENT_VERSION = "pref.current.version";
private static SessionManager mInstance;
private SharedPreferences mPreference;
private Context mContext;
private LinkedList<Pair<String, Object>> mUpdateQueue = new LinkedList<Pair<String, Object>>();
private Thread mCurrentUpdateThread;
private SessionManager(Context context) {
synchronized (this) {
mContext = context;
if (mPreference == null) {
mPreference = PreferenceManager.getDefaultSharedPreferences(mContext);
}
}
}
public static SessionManager get(Context context) {
if (mInstance == null) {
mInstance = new SessionManager(context);
}
return mInstance;
}
private static final Method sApplyMethod = findApplyMethod();
private static Method findApplyMethod() {
try {
Class<Editor> cls = SharedPreferences.Editor.class;
return cls.getMethod("apply");
} catch (NoSuchMethodException unused) {
// fall through
}
return null;
}
/** Use this method to modify preference */
public static void apply(SharedPreferences.Editor editor) {
if (sApplyMethod != null) {
try {
sApplyMethod.invoke(editor);
return;
} catch (InvocationTargetException unused) {
// fall through
} catch (IllegalAccessException unused) {
// fall through
}
}
editor.commit();
}
public int isFilterApps() {
boolean isFilter = mPreference.getBoolean(P_NO_APP_FILTER, false);
return isFilter ? 0 : 1;
}
/**
* Release all resources
*/
public void close() {
mPreference = null;
mInstance = null;
}
private boolean isPreferenceNull() {
if(mPreference == null)
return true;
return false;
}
@SuppressWarnings("unchecked")
@Override
public void update(Observable observable, Object data) {
if (data instanceof Pair) {
synchronized (mUpdateQueue) {
if (data != null) {
mUpdateQueue.add((Pair<String, Object>) data);
}
}
writePreferenceSlowly();
}
}
// private void logTaskQueue() {
// if (mUpdateQueue != null) {
// Log.d("hibenate", " task queue is ");
// int length = mUpdateQueue.size();
// for (int i = 0; i < length; i++) {
// Pair p = mUpdateQueue.get(i);
// Log.d("hibenate", "key " + p.first + " value " + p.second);
// }
// }
// }
/*
* Do Hibernation slowly
*/
private void writePreferenceSlowly() {
if (mCurrentUpdateThread != null) {
if (mCurrentUpdateThread.isAlive()) {
// the update thread is still running,
// so no need to start a new one
return;
}
}
// update the seesion value back to preference
// ATTENTION: some more value will be add to the queue while current task is running
mCurrentUpdateThread = new Thread() {
@Override
public void run() {
try {
// sleep 10secs to wait some concurrent task be
// inserted into the task queue
sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
writePreference();
}
};
mCurrentUpdateThread.setPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
mCurrentUpdateThread.start();
}
/*
* Do Hibernation immediately
*/
public void writePreferenceQuickly() {
// update the seesion value back to preference
// ATTENTION: some more value will be add to the queue while current task is running
mCurrentUpdateThread = new Thread() {
@Override
public void run() {
writePreference();
}
};
mCurrentUpdateThread.setPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
mCurrentUpdateThread.start();
}
/**
* Write session value back to preference
*/
private void writePreference() {
Editor editor = mPreference.edit();
synchronized (mUpdateQueue) {
while (!mUpdateQueue.isEmpty()) {
// remove already unused reference from the task queue
Pair<String, Object> updateItem = mUpdateQueue.remove();
// the preference key
final String key = (String) updateItem.first;
if (P_UID.equals(key) || P_MARKET_USERNAME.equals(key)
|| P_MARKET_PASSWORD.equals(key)) {
editor.putString(key, SecurityUtil.encrypt(
String.valueOf(updateItem.second)));
} else if (P_ISLOGIN.equals(key)
|| P_LPNS_IS_BINDED.equals(key)
|| P_UPDATE_AVAILABIE.equals(key)) {
editor.putBoolean(key, (Boolean) updateItem.second);
} else if (P_SCREEN_SIZE.equals(key)
|| P_OS_VERSION.equals(key)
|| P_LPNS_BINDED_DEVID.equals(key)
|| P_UPDATE_DESC.equals(key)
|| P_UPDATE_URI.equals(key)
|| P_UPDATE_VERSION_NAME.equals(key)
|| P_DEFAULT_CHARGE_TYPE.equals(key)) {
editor.putString(key, (String) updateItem.second);
} else if (P_UPDATE_VERSION_CODE.equals(key)
|| P_UPDATE_LEVEL.equals(key)
|| P_UPGRADE_NUM.equals(key)
|| P_CARD_VERSION.equals(key)
|| P_CURRENT_VERSION.equals(key)) {
editor.putInt(key, (Integer) updateItem.second);
} else if (P_PRODUCT_UPDATE_CHECK_TIMESTAMP.equals(key)
|| P_SPLASH_TIME.equals(key)
|| P_SPLASH_ID.equals(key)
|| P_UPDATE_ID.equals(key)) {
editor.putLong(key, (Long) updateItem.second);
}
}
}
// update the preference
apply(editor);
}
public HashMap<String, Object> readPreference() {
if (isPreferenceNull()) {
return null;
}
HashMap<String, Object> data = new HashMap<String, Object>();
String uidString = mPreference.getString(P_UID, null);
String uid;
if (uidString == null)
uid = "";
else {
uid = SecurityUtil.decrypt(uidString);
}
data.put(P_UID, uid);
data.put(P_SCREEN_SIZE, mPreference.getString(P_SCREEN_SIZE, "320#480"));
data.put(P_OS_VERSION, mPreference.getInt(P_OS_VERSION, 0));
data.put(P_ISLOGIN, mPreference.getBoolean(P_ISLOGIN, false));
String username = mPreference.getString(P_MARKET_USERNAME, "");
if (username == null) {
username = "";
} else {
username = SecurityUtil.decrypt(username);
}
data.put(P_MARKET_USERNAME, username);
String password = mPreference.getString(P_MARKET_PASSWORD, null);
if(password == null) {
password = "";
} else {
password = SecurityUtil.decrypt(password);
}
data.put(P_MARKET_PASSWORD, password);
data.put(P_CLEAR_CACHE, mPreference.getBoolean(P_CLEAR_CACHE, false));
data.put(P_CARD_VERSION, mPreference.getInt(P_CARD_VERSION, -1));
// cloud preference
data.put(P_LPNS_IS_BINDED, mPreference.getBoolean(P_LPNS_IS_BINDED, false));
data.put(P_LPNS_BINDED_DEVID, mPreference.getString(P_LPNS_BINDED_DEVID, ""));
// update info
data.put(P_UPDATE_AVAILABIE, mPreference.getBoolean(P_UPDATE_AVAILABIE, false));
data.put(P_UPDATE_VERSION_CODE, mPreference.getInt(P_UPDATE_VERSION_CODE, -1));
data.put(P_UPDATE_LEVEL, mPreference.getInt(P_UPDATE_LEVEL, -1));
data.put(P_UPGRADE_NUM, mPreference.getInt(P_UPGRADE_NUM, 0));
data.put(P_PRODUCT_UPDATE_CHECK_TIMESTAMP, mPreference.getLong(P_PRODUCT_UPDATE_CHECK_TIMESTAMP, -1));
data.put(P_UPDATE_DESC, mPreference.getString(P_UPDATE_DESC, ""));
data.put(P_UPDATE_URI, mPreference.getString(P_UPDATE_URI, ""));
data.put(P_UPDATE_VERSION_NAME, mPreference.getString(P_UPDATE_VERSION_NAME, ""));
data.put(P_UPDATE_ID, mPreference.getLong(P_UPDATE_ID, -1));
//splash info
data.put(P_SPLASH_ID, mPreference.getLong(P_SPLASH_ID, -1L));
data.put(P_SPLASH_TIME, mPreference.getLong(P_SPLASH_TIME, 0L));
// current version
data.put(P_CURRENT_VERSION, mPreference.getInt(P_CURRENT_VERSION, -1));
//charge
data.put(P_DEFAULT_CHARGE_TYPE, mPreference.getString(P_DEFAULT_CHARGE_TYPE, null));
return data;
}
}