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.
Related
I'm trying to connect to google endpoint in android app but when I run the app on emulator or real device both are not work and I get error 404 not found.
so I create button that implement the asynctask of connection :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void tellJoke(View view) {
EndpointsAsyncTask asyncTask = new EndpointsAsyncTask(this);
asyncTask.execute();
}
}
and this is the class of asynctask:
public class EndpointsAsyncTask extends AsyncTask<Void, Void, String> {
private static MyApi myApiService = null;
private Context mContext;
public EndpointsAsyncTask (Context context){
mContext = context;
}
#Override
protected String doInBackground(Void... 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();
}
try {
return myApiService.jokes().execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
Intent intent = new Intent(mContext, AndroidLibraryActivity.class);
intent.putExtra("jokes", result);
mContext.startActivity(intent);
}
}
and in android library I received the result like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_library);
TextView jokes;
jokes = findViewById(R.id.jokes);
Intent intent = getIntent();
String joke = intent.getStringExtra("jokes");
jokes.setText(joke);
}
and this is my endpoint:
#Api(
name = "myApi",
version = "v1",
namespace = #ApiNamespace(
ownerDomain = "backend.builditbigger.gradle.udacity.com",
ownerName = "backend.builditbigger.gradle.udacity.com",
packagePath = ""
)
)
public class MyEndpoint {
/** A simple endpoint method that takes a name and says Hi back */
#ApiMethod(name = "jokes")
public MyBean jokes(){
MyBean response = new MyBean();
Joker jokes = new Joker();
String jokesResult = jokes.getJoke();
response.setData(jokesResult);
return response;
}
also I read many solutions but nothing work with me and by the way when I run it on real device I change the rooturl to this link:
http://builditbigger-id.appspot.com/_ah/api/
but it doesn't work so how make it work at least on the simulator devices!
I have followed a tutorial on how to setup SNS Push notification but the CreatePlatformEndpointResult object returns null. I need that so that I can retrieve the endpointArn and send that to the backend. Below is my entire setup. And here is the link to the tutorial: http://www.allcode.com/amazon-sns-push-notification-tutorial-android-using-gcm/
First I retrieve a token from GCM by calling
AWSManager.registerAppToGCM(getApplicationContext())
This is from my AWSManager class
public class AWSManager {
private static final String TAG = AWSManager.class.getSimpleName();
private static final String SNS_ACCESS_KEY_ID = "1234567890"; // I have swapped out the real key
private static final String SNS_SECRET_KEY = "1234567890"; // I have swapped out the real key
private static AmazonSNSClient snsClient;
/**
* Method is used to retrieve SNSClient object
*
* #return snsClient object
*/
public static AmazonSNSClient getSNSClient() {
if (FrameworkUtils.checkIfNull(snsClient)) {
snsClient = new AmazonSNSClient(new BasicAWSCredentials(SNS_ACCESS_KEY_ID, SNS_SECRET_KEY));
snsClient.setRegion(Region.getRegion(Regions.US_WEST_1));
}
return snsClient;
}
/**
* Method is used to register app to GCM
*
* #param context
*/
public static void registerAppToGCM(Context context) {
SharedPref sharedPref = new SharedPref(context, Constants.PREF_FILE_NAME);
String gcmToken = sharedPref.getStringPref(Constants.NOTIFICATION_GCM_TOKEN, "");
if (FrameworkUtils.isStringEmpty(gcmToken)) {
new GCMRegisterTask(context).execute();
}
}
}
Here is the class performing the background task
public class GCMRegisterTask extends AsyncTask<String, Void, Boolean> {
private static final String TAG = GCMRegisterTask.class.getSimpleName();
private Context mContext;
/**
* Constructor
*
* #param context
*/
public GCMRegisterTask(Context context) {
super();
mContext = context;
}
#Override
protected Boolean doInBackground(String... params) {
String token;
try {
token = InstanceID.getInstance(mContext).getToken(mContext.getString(R.string.gcm_project_id), GoogleCloudMessaging.INSTANCE_ID_SCOPE);
SharedPref sharedPref = new SharedPref(mContext, Constants.PREF_FILE_NAME);
sharedPref.setPref(Constants.NOTIFICATION_GCM_TOKEN, token);
Logger.i(TAG, "GCM token successfully stored to prefs: " + token);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
Once I have successfully retrieved the GCM token. I use new
AWSCreateEndpointTask(mContext).execute(test, token,
"email#gmail.com")
to begin the process of creating the endpoint ARN. test = "arn:aws:sns:region:us-east-1:app/GCM/AppName"
public class AWSCreateEndpointTask extends AsyncTask<String, Void, CreatePlatformEndpointResult> {
Context mContext;
/**
* Constructor
*
* #param context
*/
public AWSCreateEndpointTask(Context context) {
super();
mContext = context;
}
#Override
protected CreatePlatformEndpointResult doInBackground(String[] params) {
if (params.length < 3) {
return null;
}
String arn = params[0];
String gcmToken = params[1];
String userData = params[2];
try {
CreatePlatformEndpointRequest request = new CreatePlatformEndpointRequest();
request.setCustomUserData(userData);
request.setToken(gcmToken);
request.setPlatformApplicationArn(arn);
return AWSManager.getSNSClient().createPlatformEndpoint(request);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(CreatePlatformEndpointResult result) {
if (!FrameworkUtils.checkIfNull(result)) {
String endpointArn = result.getEndpointArn();
SharedPref sharedPref = new SharedPref(mContext, Constants.PREF_FILE_NAME);
sharedPref.setPref(Constants.NOTIFICATION_ENDPOINT_ARN, endpointArn);
}
}
Inside of onPostExecute, the returned CreatePlatformEndpointResult object is null. What am I missing or doing incorrectly to cause this?
It turns out that the implementation is correct, the arn value was wrong. For others running into this conflict, make sure the information is correct when trying to get the endpointARN. I updated mine to
arn:aws:sns:us-east-1::app/GCM/
This comes from the developer console.
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'm trying to get the Salesforce REST API working with Android and new to android programming, followed the sample code to connect with SFDC http://wiki.developerforce.com/page/Getting_Started_with_the_Mobile_SDK_for_Android#Authentication
I'm trying to get a few records from SFDC and display them in the android app, looks like when the Async Call is made at "client.sendAsync(sfRequest, new AsyncRequestCallback()" - NullPointerException is thrown.
I did see a couple of similar issues online, but didn't help me. Hoping if some one would point me in the right direction to troubleshoot this. Thanks much.
public class GetAccountsActivity extends Activity {
private PasscodeManager passcodeManager;
private String soql;
private String apiVersion;
private RestClient client;
private TextView resultText;
private RestRequest sfRequest;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get Api Version
apiVersion = getString(R.string.api_version);
//Create Query
soql = "select id, name from Account limit 10";
// Setup view
setContentView(R.layout.get_accounts_activity);
((TextView) findViewById(R.id.Acc_Title)).setText(apiVersion);
// Passcode manager
passcodeManager = ForceApp.APP.getPasscodeManager();
}
#Override
public void onResume() {
super.onResume();
//Get SFClient
// Login options
String accountType = ForceApp.APP.getAccountType();
LoginOptions loginOptions = new LoginOptions(
null, // login host is chosen by user through the server picker
ForceApp.APP.getPasscodeHash(),
getString(R.string.oauth_callback_url),
getString(R.string.oauth_client_id),
new String[] {"api"});
new ClientManager(this, accountType, loginOptions).getRestClient(this, new RestClientCallback() {
#Override
public void authenticatedRestClient(RestClient client) {
if (client == null) {
ForceApp.APP.logout(GetAccountsActivity.this);
return;
}
GetAccountsActivity.this.client = client;
}
});
//Get Rest Object to query
try {
sfRequest = RestRequest.getRequestForQuery(apiVersion, soql);
//Use SF Rest Client to send the request
client.sendAsync(sfRequest, new AsyncRequestCallback(){
#Override
public void onSuccess(RestRequest request, RestResponse response){
//Check responses and display results
// EventsObservable.get().notifyEvent(EventType.RenditionComplete);
}//end onSuccess
#Override
public void onError(Exception exception) {
//printException(exception);
EventsObservable.get().notifyEvent(EventType.RenditionComplete);
}//End Exception for Async Method
});
}catch (UnsupportedEncodingException e) {
//printHeader("Could Send Query request");
//printException(e);
return;
}
}
}
enter code here
You are calling client.sendAsync from onResume() but client is not set until the authenticatedRestClient callback is called, you need to move your sendAsync call into the authenticatedRestClient callback.
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