I am trying to make social network application for Android. My question is how to maintain user session when user logs in?
Please help me to find the solution for the above question.
try
public class Session {
private static String sessionId;
private static String userRole;
public static void setSessionId(String sessionId) {
Session.sessionId = sessionId;
}
public static String getSessionId() {
return sessionId;
}
}
Use this class and import it in every other activity. You can define your own functions to maintain your specific session data
http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/
Please look at the above link. It is detailed pretty well.
Use a singleton to maintain the user session.
I use DefaultHttpClient with HttpRequestInterceptor and HttpResponseInterceptor.
Something similar to this:
public class HTTPClients {
private static DefaultHttpClient _defaultClient;
private static String session_id;
private static HTTPClients _me;
private HTTPClients() {
}
public static DefaultHttpClient getDefaultHttpClient(){
if ( _defaultClient == null ) {
_defaultClient = new DefaultHttpClient();
_me = new HTTPClients();
_defaultClient.addResponseInterceptor(_me.new SessionKeeper());
_defaultClient.addRequestInterceptor(_me.new SessionAdder());
}
return _defaultClient;
}
private class SessionAdder implements HttpRequestInterceptor {
#Override
public void process(HttpRequest request, HttpContext context)
throws HttpException, IOException {
Log.d("SessionKeeper", "Adding session with the following string: " + session_id);
if ( session_id != null ) {
request.setHeader("Cookie", session_id);
}
}
}
private class SessionKeeper implements HttpResponseInterceptor {
#Override
public void process(HttpResponse response, HttpContext context)
throws HttpException, IOException {
Header[] headers = response.getHeaders("Set-Cookie");
if ( headers != null && headers.length == 1 ){
Log.d("SessionKeeper", "Keeping session with the following string: " + headers[0].getValue());
session_id = headers[0].getValue();
}
}
}
}
I have the similar problem on my android client side when I am trying to send that session id ,the server side is creating a new session...but what you check at android client side that you are not creating the DefaulthttpClient twice... create the httpclient just once say main activity and pass the objects in other activity ...... dont create second HttpClient
Create session using SharedPreferences.
public class Session {
private SharedPreferences prefs;
public Session(Context cntx) {
// TODO Auto-generated constructor stub
prefs = PreferenceManager.getDefaultSharedPreferences(cntx);
}
public void setusename(String usename) {
prefs.edit().putString("usename", usename).commit();
}
public String getusename() {
String usename = prefs.getString("usename","");
return usename;
}
}
now after making this class when u want to use this use like this make object og this class like
private Session session;//global variable
session = new Session(cntx); //in oncreate
//and now we set sharedpreference then use this like
session.setusename("USERNAME");
now when ever u want to get username then same work for session object and call this
session.getusename();
best of luck :) same for password
Related
I'm making an android app that uses a development server to respond api calls.
I set it up using the following guide:
https://github.com/GoogleCloudPlatform/gradle-appengine-templates/tree/master/HelloEndpoints
I used the skeleton code provided by google on the example, so my api and the AsyncTask that peforms the calls look like this:
MyEndpoint class:
/** An endpoint class we are exposing */
#Api(
name = "myApi",
version = "v1",
namespace = #ApiNamespace(
ownerDomain = "backend.myapplication.madelenko.example.com",
ownerName = "backend.myapplication.madelenko.example.com",
packagePath=""
)
)
public class MyEndpoint {
/** A simple endpoint method that takes a name and says Hi back */
#ApiMethod(name = "supplyJoke")
public MyBean supplyJoke() {
MyBean response = new MyBean();
response.setData(JokeDispenser.getJoke());
return response;
}
}
MyBean Class:
/** The object model for the data we are sending through endpoints */
public class MyBean {
private String myData;
public String getData() {
return myData;
}
public void setData(String data) {
myData = data;
}
}
The asyncTask:
public class FetchJokeTask extends AsyncTask<Pair<Context,String>, Void, String> {
private static MyApi myApiService = null;
private Context context;
#Override
protected String doInBackground(Pair<Context, String>... params) {
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end options for devappserver
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.supplyJoke().execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
For some reason, when I click a button and launch an AsyncTask, I get a 404 error. The toast returns html with the contents of a 404 page.
I used the debugger to find out why and I know that the asyncTask tries to execute this line and fails:
return myApiService.supplyJoke().execute().getData();
Therefore, it returns an error message.
Is there anything wrong with my config?
Please help me to figure it out. Thanks.
P.S.: The problem is that the execute() method throws an IOException. I hope this extra piece gives you some context. Thank you very much.
I have been trying to login to google talk using the asmack library without success. I don't really know what is happening behind the scenes, just gathered some code snippets from here and there. This is what I have currently for the android activity:
public class MainActivity extends Activity {
public static final String HOST = "talk.google.com";
public static final int PORT = 5222;
public static final String SERVICE = "gmail.com";
public static final String USER = "user#gmail.com";
public static final String PASSWORD = "password";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Context context = getApplicationContext();
SmackAndroid asmk = SmackAndroid.init(context);
SASLAuthentication.registerSASLMechanism("X-OAUTH2", SASLGoogleOAuth2Mechanism.class);
SASLAuthentication.supportSASLMechanism("X-OAUTH2", 0);
ConnectionConfiguration connConfig = new ConnectionConfiguration(HOST, PORT, SERVICE);
connConfig.setSecurityMode(SecurityMode.enabled);
connConfig.setReconnectionAllowed(true);
XMPPTCPConnection connection = new XMPPTCPConnection(connConfig);
try {
connection.connect();
try {
connection.login(USER, PASSWORD);
} catch (XMPPException ex) {
Log.w("XMPPChatDemoActivity", "Failed to log in");
Log.w("XMPPChatDemoActivity", ex.getMessage());
}
} catch (...) {
...
}
}
}
and this is the SASLMechanism:
public class SASLGoogleOAuth2Mechanism extends SASLMechanism {
private static final Logger log = Logger.getLogger("XMPPChatDemoActivity");
public static final String NAME = "X-OAUTH2";
public SASLGoogleOAuth2Mechanism(SASLAuthentication saslAuthentication) {
super(saslAuthentication);
log.info("Creating SASL mechanism for GTalk (X-OAUTH2)");
}
#Override
public void authenticate(String username, String host, String serviceName, String password) throws IOException, SaslException, NotConnectedException {
this.authenticationId = username;
this.hostname = host;
this.password = password;
String[] mechanisms = { "PLAIN" };
Map<String, String> props = new HashMap<String, String>();
this.sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, this);
log.info("sc " + sc);
authenticate();
}
#Override
public void authenticate(String host, CallbackHandler cbh) throws IOException, SaslException, NotConnectedException {
String[] mechanisms = { "PLAIN" };
Map<String, String> props = new HashMap<String, String>();
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, cbh);
authenticate();
}
#Override
protected void authenticate() throws IOException, SaslException, NotConnectedException {
String authenticationText = null;
try {
if (sc.hasInitialResponse()) {
byte[] response = sc.evaluateChallenge(new byte[0]);
authenticationText = Base64.encodeBytes(response, Base64.DONT_BREAK_LINES);
}
} catch (SaslException e) {
throw new SaslException("SASL authentication failed", e);
}
// Send the authentication to the server
getSASLAuthentication().send(new GoogleOAuthMechanism(authenticationText));
}
#Override
protected String getName() {
return NAME;
}
/**
* Initiating SASL authentication by select a mechanism.
*/
public static class GoogleOAuthMechanism extends Packet {
private final String authenticationText;
/**
* Create a GoogleOAuthMechanism.
*
* #param authenticationText the authentification token
*
*/
public GoogleOAuthMechanism(final String authenticationText) {
this.authenticationText = authenticationText;
}
#Override
public String toXML() {
StringBuilder stanza = new StringBuilder();
stanza.append("<auth mechanism=\"").append(NAME);
stanza.append("\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" "
+ "auth:service=\"oauth2\" "
+ "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">");
if (authenticationText != null
&& authenticationText.trim().length() > 0) {
stanza.append(authenticationText);
}
stanza.append("</auth>");
return stanza.toString();
}
}
}
The code is ok and i don't get any exception, but I get a <not-authorized> response. The user name and password are correct. I couldn't find any reference code for this library. Any help will be appreciated.
After struggling for a few days and trying every imaginable combination of the snippets that I found on the Internet, I've come across a solution that I'm glad to share with the community.
It appears that instead of passing the password to the XMPPTCPConnection.login() method, we should use an auth token from google. I found a post explaining a way to generate such a token. A similar question to mine exists, but it uses X-GOOGLE-TOKEN mechanism also for authentication, which is a different approach to mine of using X-OAUTH2 mechanism for authentication. Furthermore, all other posts I could find relating to the problem of authenticating to google talk using OAUTH2 are old. I am using the asmack build of smack 4.0.4.
So the only modification required for the code shown in the question to work is this:
AccountManager am = AccountManager.get(this);
Account accounts[] = am.getAccountsByType("com.google");
conn.login(USER, amf.blockingGetAuthToken(accounts[0], GOOGLE_TOKEN_TYPE, true));
As you see, I used an account stored on the device to proof the solution, but you can generate the token by other means, as I commented above.
Finally, as I found the solution by trial and error, I would appreciate anyone explaining what is really happening or any misinformation I could have given, so this answer can be further improved.
I need to know how to add an authorization cookie header in retrofit. I have seen advice like using request intercepter etc. Below is what I am trying, but is this correct? First of all I already needed a RequestAdatper to get the session id the first time around. This can only be set by the builder of the request adapter. But I needed to make a request just to get the session id in the first place. Do I need two rest adapters one to get the sessionId and another one after I have obtained it. What I really need is a method on adapter to set the cookie after I get it but it does not appear to be such a method. This is getting awkward. How do I set authorization cookie in retrofit? I don't see this in FAQ or tutorials.
RequestInterceptor requestInterceptor = new RequestInterceptor()
{
#Override
public void intercept(RequestFacade request) {
request.addHeader("Set-Cookie", "sessionId="+sessionIdentifier);
}
};
RestAdapter.Builder().setServer(serverURL)..setRequestIntercepter(requestIntercepter).build();
// but I don't have sessionId when this is first issued ???
Keep a reference to the interceptor and treat it as a singleton like you would be RestAdapter itself.
public class ApiHeaders implements RequestInterceptor {
private String sessionId;
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public void clearSessionId() {
sessionId = null;
}
#Override public void intercept(RequestFacade request) {
if (sessionId != null) {
request.setHeader(...);
}
}
}
Now, simply call setSessionId after your authentication call. All subsequent requests will include the header.
You can get the cookies like this
public class MyCookieManager extends CookieManager {
#Override
public void put(URI uri, Map<String, List<String>> stringListMap) throws IOException {
super.put(uri, stringListMap);
if (stringListMap != null && stringListMap.get("Set-Cookie") != null)
for (String string : stringListMap.get("Set-Cookie")) {
if (string.contains("JSESSIONID")) {
Preference.getInstance().setSessionId(string);
}
}
}
}
Use this to set the CookieHandler
MyCookieManager myCookieManager = new MyCookieManager();
CookieHandler.setDefault(myCookieManager);
and then use it like this in your request Interceptor
String sessionId = preference.getSessionId();
if (sessionId != null)
requestFacade.addHeader(Cookie, sessionId);
Step 1. Parse Response headers.
Call this method inside your Callback in overriden success method.
/**
* Method extracts cookie string from headers
* #param response with headers
* #return cookie string if present or null
*/
private String getCookieString(Response response) {
for (Header header : response.getHeaders()) {
if (null!= header.getName() && header.getName().equals("Set-Cookie")) {
return header.getValue();
}
}
return null;
}
Step 2. Write some static class or singleton to keep cookies and your RequestInterceptor instance. Inside RequestInterceptor override intercept method to add your cookies to Header.
public class RestAdapter {
private static String cookies;
public static String getCookies() {
return cookies;
}
public static void setCookies(String cookies) {
RestAdapter.cookies = cookies;
}
/**
* Injects cookies to every request
*/
private static final RequestInterceptor COOKIES_REQUEST_INTERCEPTOR = new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
if (null != cookies && cookies.length() > 0) {
request.addHeader("Cookie", cookies);
}
}
};
public static final RestInterface getService() {
return new RestAdapter.Builder()
.setEndpoint(Config.ENDPOINT)
.setRequestInterceptor(COOKIES_REQUEST_INTERCEPTOR)
.setConverter(new JacksonConverter())
.setLogLevel(RestAdapter.LogLevel.NONE)
.build()
.create(RestInterface.class);
}
}
According to #sbtgE's answer, but with some corrections. CookieHandler.getDefault() may be null, so I use CookieManager.
app's build.gradle:
dependencies {
...
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.4.1'
}
Setting up Retrofit:
service = new Retrofit.Builder()
.baseUrl(/* your base URL */)
.addConverterFactory(/* your favourite converter */)
.client(
new OkHttpClient.Builder()
// this line is the important one:
.cookieJar(new JavaNetCookieJar(new CookieManager()))
.build())
.build()
.create(YourInterface.class);
Simple solution using lib. compile com.squareup.okhttp3:okhttp-urlconnection:3.2.0.
JavaNetCookieJar jncj = new JavaNetCookieJar(CookieHandler.getDefault());
OkHttpClient.Builder().cookieJar(jncj).build();
I can't seem to figure out how to get android annotations rest client to work I'm having 2 main issues.
A)How to parse the generic json response and get the meaningful key
B)How to add parameters
For the first problem all responses come back as a json string fomatted like this
{"success":,"message":"","data":{}}
Where success is boolean message is a string and data is going to be the main data I want to parse that may be a boolean, an array, a string or an int
I'm pretty sure I need to intercept the response and handle the code but I'm not sure how to do that
Lets use a real response that look something like this
{"success":true,"message":"random message","data":{"profile":{"id":"44","user_id":"44","name":"Matt","username":"mitch","icon":"b1da7ae15027b7d6421c158d644f3220.png","med":"2a3df53fb39d1d8b5edbd0b93688fe4a.png","map":"b7bfed1f456ca4bc8ca748ba34ceeb47.png","background":null,"mobile_background":null}}
First in my interceptor I want to see if the boolean key "success" is true and then return the data value
#EBean
public class RestInterceptor implements ClientHttpRequestInterceptor {
final String TAG = "rest";
#Bean
AuthStore authStore;
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] data, ClientHttpRequestExecution execution)
throws IOException{
//Need to set the api key here but nothing happens code quits
// Log.d("Rest",authStore.getApiKey());
HttpHeaders headers = request.getHeaders();
headers.set("api_key","");
ClientHttpResponse resp = execution.execute(request, data);
HttpStatus code = resp.getStatusCode();
if(code.value() == 200){
Log.d(TAG,"success code 200");
//valid http request but is it a valid API request?
//perform some logic of if success == true in root json object
//if true cast return data key
}
else{
Log.d(TAG,"fail code" + code.toString());
}
return resp;
}
}
The second problem is sending params with the http request that have an api key and a session key, I define the application class like this
#EApplication
public class MyApp extends Application {
final String TAG = "app";
#Bean
AuthStore authStore;
#RestService
RestClient restClient;
public void onCreate() {
super.onCreate();
init();
}
#AfterInject
public void init() {
authStore.setApiKey("dummy_key");
Log.d(TAG, "api key set to " + authStore.getApiKey());
}
}
With the AuthStore class like this
#EBean(scope = Scope.Singleton)
public class AuthStore {
public String apiKey,sessionKey;
public String getApiKey() {
return apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
public String getSessionKey() {
return sessionKey;
}
public void setSessionKey(String sessionKey) {
this.sessionKey = sessionKey;
}
}
Basically I'm setting a dummy api key at the application level in a singleton, which I should be able to access in the rest interceptor interface but the code just quits without errors I'm basically following this guide https://github.com/excilys/androidannotations/wiki/Authenticated-Rest-Client
Finally I have an activity class which injects the app dependency which has refrence to the rest http class and the authstore class
#EActivity(R.layout.activity_login)
public class LoginActivity extends Activity {
#App
MyApp app;
#ViewById
TextView email;
#ViewById
TextView password;
#ViewById
Button loginButton;
#AfterInject
public void init() {
Log.d(app.TAG, "api in login key set to " + app.authStore.getApiKey());
}
#Click
#Trace
void loginButton() {
login(email.toString(), password.toString());
}
#Background
void login(String email, String password) {
app.restClient.forceLogin();
}
}
Sorry if it's a lot of info, I've been searching for a while and can't figure this out!
thanks in advance
I'm not known with the library you're using (annotations, spring) but it seems to me that you are struggling with parsing the success = true because that is not supposed to be in the JSON.
The JSON should preferably represent a class in your app 1on1 so you can easily map that into an object.
Communication between your app and the webservice, regarding the status of requests should go into the headers.
Like this you can check a request's headers, before parsing the JSON.
This is mathod I am using to parse any JSON object recursively.
private void parseJson(JSONObject data) {
if (data != null) {
Iterator<String> it = data.keys();
while (it.hasNext()) {
String key = it.next();
try {
if (data.get(key) instanceof JSONArray) {
JSONArray arry = data.getJSONArray(key);
int size = arry.length();
for (int i = 0; i < size; i++) {
parseJson(arry.getJSONObject(i));
}
} else if (data.get(key) instanceof JSONObject) {
parseJson(data.getJSONObject(key));
} else {
System.out.println("" + key + " : " + data.optString(key));
}
} catch (Throwable e) {
System.out.println("" + key + " : " + data.optString(key));
e.printStackTrace();
}
}
}
}
I'm writing an application that validates login credentials on an external webserver - so I have the basic issue of creating a login screen that when submitted will send an HTTP request to a server in the background and not cause the UI to hang - whilst providing a ProgressDialog to the user.
My problem lies in, I want to write a generic HTTP Request class that extends AsyncTask, so when I call .execute() I will then pass String parameters which may contain something like 'post', and when doInBackground is called this will see the 'post' string and then forward those parameters onto the respective call in my class. Pseudo code would be something like
public class HTTPOperations extends AsyncTask<String, Void, String>
{
doInBackground(String... string1,additionalParams)
{
if string1.equals "post"
response = httpPost(additionalParams)
return response;
}
httpPost(params)
{
// do http post request
}
}
This is all I could think of, other than creating a class for every HTTP Post/GET etc request I wish to make and extending ASyncTask...
Which leads me to my next problem, if the HTTP POST is successful and it returns an authentication token, how do I access this token?
Because new httpOperations.execute(), does not return the string from doInBackground, but a value of type
Sorry if this doesn't make sense, I can't figure this out at all. Please ask for elaboration if you need it. AsyncTask design patterns and ideas are hugely welcomed.
If you are designing a reusable task for something like this, you need to identify a reusable return type. Its a design decision on your part. Ask yourself, "Are my HTTP operations similar in both the mechanisms with which they are called and in which their data is processed?" If so, you can design a single class to do both. If not, you probably need different classes for your different remote operations.
In my personal use, I have an object i attach key value pairs to and the common return type is the HttpEntity. This is the return type for both HTTP Get and Post, and this seems to work ok in my scenarios because i throw exceptions in exceptional HTTP result situations, like 404. Another nice aspect of this setup is that the code to attach parameters to a get or post are fairly similar, so this logic is pretty easy to construct.
An example would be something like this (psuedo):
public interface DownloadCallback {
void onSuccess(String downloadedString);
void onFailure(Exception exception);
}
Then in your code, where you go to do the download:
DownloadCallback dc = new DownloadCallback(){
public void onSuccess(String downloadedString){
Log.d("TEST", "Downloaded the string: "+ downloadedString);
}
public void onFailure(Exception e){
Log.d("TEST", "Download had a serious failure: "+ e.getMessage());
}
}
DownloadAsyncTask dlTask = new DownloadAsyncTask(dc);
Then inside the constructor of DownloadAsyncTask, store the DownloadCallback and, when the download is complete or fails, call the method on the download callback that corresponds to the event. So...
public class DownloadAsyncTask extends AsyncTask <X, Y, Z>(){
DownloadCallback dc = null;
DownloadAsyncTask(DownloadCallback dc){
this.dc = dc;
}
... other stuff ...
protected void onPostExecute(String string){
dc.onSuccess(string);
}
}
I'm going to reiterate that I think for the good of yourself, you should pass back HttpEntities. String may seem like a good idea now, but it really leads to trouble later when you want to do more sophisticated logic behind your http calls. Of course, thats up to you. Hopefully this helps.
suppose the data format with web api is json, my design pattern :
common classes
1.MyAsyncTask : extends AsyncTask
2.BackgroundBase : parameters to server
3.API_Base : parameters from server
4.MyTaskCompleted : callback interface
public class MyAsyncTask<BackgroundClass extends BackgroundBase,APIClass extends API_Base> extends AsyncTask<BackgroundClass, Void, APIClass> {
private ProgressDialog pd ;
private MyTaskCompleted listener;
private Context cxt;
private Class<APIClass> resultType;
private String url;
private int requestCode;
public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url){
this.listener = listener;
this.cxt = (Context)listener;
this.requestCode = requestCode;
this.resultType = resultType;
this.url = url;
}
public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url, ProgressDialog pd){
this(listener, resultType, requestCode, url);
this.pd = pd;
this.pd.show();
}
#Override
protected APIClass doInBackground(BackgroundClass... params) {
APIClass result = null;
try {
//do something with url and params, and get data from WebServer api
BackgroundClass oParams = params[0];
String sUrl = url + "?d=" + URLEncoder.encode(oParams.getJSON(), "UTF-8");
String source = "{\"RtnCode\":1, \"ResultA\":\"result aaa\", \"ResultB\":\"result bbb\"}";
//to see progressdialog
Thread.sleep(2000);
result = new com.google.gson.Gson().fromJson(source, resultType);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(APIClass result) {
super.onPostExecute(result);
try {
if(pd != null && pd.isShowing())
pd.dismiss();
API_Base oApi_Base = (API_Base)result;
listener.onMyTaskCompleted(result , this.requestCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class API_Base {
public int RtnCode;
public String getJSON(Context context) throws Exception
{
return new com.google.gson.Gson().toJson(this);
}
public String toString(){
StringBuilder sb = new StringBuilder();
for (Field field : this.getClass().getFields()) {
try {
field.setAccessible(true);
Object value = field.get(this);
if (value != null) {
sb.append(String.format("%s = %s\n", field.getName(), value));
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
return sb.toString();
}
}
public class BackgroundBase {
public String getJSON() throws Exception
{
return new com.google.gson.Gson().toJson(this);
}
}
public interface MyTaskCompleted {
void onMyTaskCompleted(API_Base oApi_Base, int requestCode) ;
}
example, let's call two api in one activity
assume :
API 1.http://www.google.com/action/a
input params : ActionA
output params : RtnCode, ResultA
API 2.http://www.google.com/action/b
input params : ActionB
output params : RtnCode, ResultB
classes with example :
1.MyActivity : extends Activity and implements MyTaskCompleted
2.MyConfig : utility class, i set requestCode here
3.BackgroundActionA, BackgroundActionB : model classes for api's input params
4.API_ActionA, API_ActionB : model classes for api's output params
public class MyActivity extends Activity implements MyTaskCompleted {
ProgressDialog pd;
Button btnActionA, btnActionB;
TextView txtResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
btnActionA = (Button)findViewById(R.id.btn_actionA);
btnActionB = (Button)findViewById(R.id.btn_actionB);
txtResult = (TextView)findViewById(R.id.txt_result);
btnActionA.setOnClickListener(listener_ActionA);
btnActionB.setOnClickListener(listener_ActionB);
pd = new ProgressDialog(MyActivity.this);
pd.setTitle("Title");
pd.setMessage("Loading");
}
Button.OnClickListener listener_ActionA = new Button.OnClickListener(){
#Override
public void onClick(View v) {
//without ProgressDialog
BackgroundActionA oBackgroundActionA = new BackgroundActionA("AAA");
new MyAsyncTask<BackgroundActionA, API_ActionA>(MyActivity.this,
API_ActionA.class,
MyConfig.RequestCode_actionA,
"http://www.google.com/action/a").execute(oBackgroundActionA);
}
};
Button.OnClickListener listener_ActionB = new Button.OnClickListener(){
#Override
public void onClick(View v) {
//has ProgressDialog
BackgroundActionB oBackgroundActionB = new BackgroundActionB("BBB");
new MyAsyncTask<BackgroundActionB, API_ActionB>(MyActivity.this,
API_ActionB.class,
MyConfig.RequestCode_actionB,
"http://www.google.com/action/b",
MyActivity.this.pd).execute(oBackgroundActionB);
}
};
#Override
public void onMyTaskCompleted(API_Base oApi_Base, int requestCode) {
// TODO Auto-generated method stub
if(requestCode == MyConfig.RequestCode_actionA){
API_ActionA oAPI_ActionA = (API_ActionA)oApi_Base;
txtResult.setText(oAPI_ActionA.toString());
}else if(requestCode == MyConfig.RequestCode_actionB){
API_ActionB oAPI_ActionB = (API_ActionB)oApi_Base;
txtResult.setText(oAPI_ActionB.toString());
}
}
}
public class MyConfig {
public static String LogTag = "henrytest";
public static int RequestCode_actionA = 1001;
public static int RequestCode_actionB = 1002;
}
public class BackgroundActionA extends BackgroundBase {
public String ActionA ;
public BackgroundActionA(String actionA){
this.ActionA = actionA;
}
}
public class BackgroundActionB extends BackgroundBase {
public String ActionB;
public BackgroundActionB(String actionB){
this.ActionB = actionB;
}
}
public class API_ActionA extends API_Base {
public String ResultA;
}
public class API_ActionB extends API_Base {
public String ResultB;
}
Advantage with this design pattern :
1.one Advantage for multi api
2.just add model classes for new api, ex: BackgroundActionA and API_ActionA
3.determine which API by different requestCode in callback function : onMyTaskCompleted