Broadcast not received when intent contains parcelable extra - android

I have an IntentService that is making a network call and receiving back some JSON data. I package this response data in custom object that implements parcelable. If I add this parcelable object to an intent as an extra and then launch an activity using that intent, everything seems to work as expected, i.e. I can retrieve the parcelable from the intent in the newly created activity. However, if I create the intent from within the onHandleIntent() method of my IntentService and then use sendBroadcast(), the broadcast receiver's onReceive() method never fires. If I don't add the parcelable to the intent, though, the onReceive() method fires as expected. Following are some relevant code snippets:
Parcelable Object:
public class JsonResponse implements Parcelable {
private int responseCode;
private String responseMessage;
private String errorMessage;
public JsonResponse() {
}
/*
/ Property Methods
*/
public void setResponseCode(int code) {
this.responseCode = code;
}
public void setResponseMessage(String msg) {
this.responseMessage = msg;
}
public void setErrorMessage(String msg) {
this.errorMessage = msg;
}
/*
/ Parcelable Methods
*/
public static final Creator<JsonResponse> CREATOR = new Creator<JsonResponse>() {
#Override
public JsonResponse createFromParcel(Parcel parcel) {
return new JsonResponse(parcel);
}
#Override
public JsonResponse[] newArray(int i) {
return new JsonResponse[i];
}
};
private JsonResponse(Parcel parcel) {
responseCode = parcel.readInt();
responseMessage = parcel.readString();
errorMessage = parcel.readString();
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(responseCode);
parcel.writeString(responseMessage);
parcel.writeString(errorMessage);
}
#Override
public int describeContents() {
return 0;
}
}
onHandle() of IntentService:
protected void onHandleIntent(Intent intent) {
service = new LoginService();
service.login("whoever", "whatever");
JsonResponse response = new JsonResponse();
response.setResponseCode(service.responseCode);
response.setResponseMessage(service.responseMessage);
response.setErrorMessage(service.errorMessage);
Intent i = new Intent();
i.putExtra("jsonResponse", response);
i.setAction(ResultsReceiver.ACTION);
i.addCategory(Intent.CATEGORY_DEFAULT);
sendBroadcast(i);
}
Any ideas? Any insight would be greatly appreciated.

It appears that the problem has to do with the size of the object being added as an extra. When one of the string properties of the response object grows too large, the broadcast apparently fails. I have no sources to confirm this, only some trial and error in manipulating one of the strings while leaving all other variables of the equation constant.

Related

ArrayList and Parcelable

I need to "transfer" an ArrayList of custom class from one entity to another. I know that I need to implement Parcelable interface.
This is my custom class.
public class cSportsList implements Parcelable {
boolean checked;
String name;
cSportsList(boolean check, String name_) {
checked = check;
name = name_;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
//Non posso passare un booleano e non posso fare il cast boolean -> int
if (checked) {
dest.writeInt(1);
}
else dest.writeInt(0);
dest.writeString(name);
}
public static final Parcelable.Creator<cSportsList> CREATOR = new Parcelable.Creator<cSportsList>() {
public cSportsList createFromParcel(Parcel in) {
return new cSportsList(in);
}
public cSportsList[] newArray(int size) {
return new cSportsList[size];
}
};
private cSportsList(Parcel in) {
if (in.readInt() == 1) {
checked = true;
}
else {
checked = false;
}
name = in.readString();
}
}
And this is the code in entity "from"
//This is sportsMap: ArrayList<cSportsList> sportsMap = new ArrayList<cSportsList>();
Intent intent = new Intent(getApplicationContext(),WhatSportActivity.class);
intent.putParcelableArrayListExtra("sportsMap", (ArrayList<? extends Parcelable>) sportsMap); //I have tried with ArrayList<cSportsList> too.
this.startActivity(intent);
And this is the code in entity "to"
final Intent srcIntent = getIntent();
ArrayList<cSportsList> sportsMap = srcIntent.getParcelableExtra("sportsMap");
The problem is: in entity "To" sportsMap is null.
If I set "breakpoint" in "writeToParcel" and "cSportsList(Parcelable in)" functions I see that the code is executed for both functions.
Where is my error ?
Thanks. M.
While reading you need to use
srcIntent.getParcelableArrayListExtra("sportsMap");
To put into Intent use below code
intent.putParcelableArrayListExtra("sportsMap", sportsMap);
and to read it from intent, use
ArrayList<cSportsList> sportsMap = srcIntent.getParcelableArrayListExtra("sportsMap");
Read similar solution at Pass ArrayList<? implements Parcelable> to Activity
Use the below code
sportsMap = srcIntent.getParcelableArrayListExtra("sportsMap");
You should use :
ArrayList<cSportsList> sportsMap = srcIntent.getParcelableArrayListExtra("sportsMap");
You can also use Serialization for the same.
public class cSportsList implements Serializable
for put:
intent.putExtra("LIST",list);
for get:
(ArrayList<>)intent.getSerializableExtra("LIST");
Try passing Arraylist instead of casting it like this:
Intent intent = new Intent(getApplicationContext(),WhatSportActivity.class);
intent.putParcelableArrayListExtra("sportsMap", sportsMap);
startActivity(intent);
In WhatSportActivity,
final Intent srcIntent = getIntent();
ArrayList<cSportsList> sportsMap = srcIntent.getParcelableExtra("sportsMap");
In case you still have problems,please try implementing Parceable by using "Parceable"plugin as It reduces the error in using Parceable lists.

Google Analytics deserialization with Gson is returning LinkedTreeMap

I'm trying to pass an object containing Analytics Reporting data in an Intent via a broadcast. The problem is the deserialization which returns a LinkedTreeMap instead of the original serialized object, causing a crash with ClassCastException.
I tried to follow quite all answers found here on SO, from using TypeToken to modify ProGuard rules and nothing worked.
I thought to implement Parcelable interface but the problem is that I have an inner private AsyncTask class where the data is collected and pushed into the intent which will be sent via broadcast.
Here is the code of the helper where data is serialized:
public class AnalyticsHelper
{
...
private class GoogleBatchTask extends AsyncTask<GetReportsRequest,Void,GetReportsResponse>
{
#Override
protected GetReportsResponse doInBackground(#NonNull GetReportsRequest... reports)
{
GetReportsResponse response = null;
try {
if (m_reports == null)
return null;
response = m_reports.reports().batchGet(reports[0]).execute();
} catch (IOException e) {
Console.log(e);
}
return response;
}
#Override
protected void onPostExecute(GetReportsResponse response)
{
Intent intent = new Intent();
intent.setAction("com.keyone.contactpackapp.ANALYTICS_DATA");
intent.putExtra("response", new Gson().toJson(response));
Context context = PackConfig.instance().context();
if (context == null)
return;
context.sendBroadcast(intent);
}
}
}
AnalyticsFragment.java, where the deserialization happens:
public class AnalyticsFragment extends Fragment
{
#Override
public void onResume()
{
super.onResume();
// Listen to custom intent with data
IntentFilter filter = new IntentFilter("com.keyone.contactpackapp.ANALYTICS_DATA");
m_receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
// Get data from intent and pass it to the right fragment
String szJson = intent.getStringExtra("response");
//m_response = new Gson().fromJson(szJson, GetReportsResponse.class);
Type listType = new TypeToken<GetReportsResponse>(){}.getType();
m_response = new Gson().fromJson(szJson, listType);
Fragment fragment = m_activity.currentFragment();
fragment.updateData();
}
};
if (m_activity != null)
m_activity.registerReceiver(m_receiver, filter);
}
}
There was no way to deserialize object in a correct way using Gson neither using Java Serializable interface or Android Parcelable interface due to the nature of the objects to serialize.
So I opted to call an instance of the recipient class and pass object data through a method in it

Get an object result from an activity in Xamarin with Visual Studio

I want to receive an object back from a child activity in Xamarin with Visual Studio 2015:
[Serializable]
class MyObj
{
public string value { get; }
public MyObj(string v)
{
value = v;
}
}
Child Activity
Intent myIntent = new Intent (this, typeof(FirstActivity));
MyObj obj = new MyObj("message");
myIntent.PutExtra ("obj", obj); // cannot convert "obj" to Bundle
SetResult (Result.Ok, myIntent);
Finish();
FirstActivity
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 0)
if (resultCode == Result.Ok) {
var helloLabel = FindViewById<TextView> (Resource.Id.helloLabel);
MyObj obj = data.GetSerializableExtra("obj") as MyObj;
helloLabel.Text = obj.Text.ToString();
}
}
}
This code causes an error cannot convert obj to Bundle. I've also tried to implement Java.IO.ISerializable is MyObj but I couldn't get a right implementation. It always throws System.NotSupportedException: Unable to activate instance of type MyApp.MyObj from native handle 0x10001d (key_handle 0x1a027cb)
class Object1 : Java.Lang.Object, Java.IO.ISerializable
{
public string value { get; }
public Object1(string v)
{
value = v;
}
}
I would like to get some advice. I'm new in Xamarin and I'm working with Visual Studio 2015
I'd always go for Parcelable. It's very fast! (10x faster) http://www.developerphil.com/parcelable-vs-serializable/
Here is how you implement it in Xamarin:
public class MyObj : Java.Lang.Object, IParcelable
{
public string Value { get; set; }
public MyObj()
{
}
private MyObj(Parcel parcel)
{
// read your values in order
Value = parcel.ReadString();
}
public void WriteToParcel(Parcel dest, ParcelableWriteFlags flags)
{
// read your values in order
dest.WriteString(Value);
}
// -- stuff below here is needed from the parcel interfaces/mechanism --
[ExportField("CREATOR")]
public static MyObjCreator InitializeCreator()
{
return new MyObjCreator();
}
public class MyObjCreator : Java.Lang.Object, IParcelableCreator
{
public Java.Lang.Object CreateFromParcel(Parcel source)
{
return new MyObj(source);
}
public Java.Lang.Object[] NewArray(int size)
{
return new MyObj[size];
}
}
public int DescribeContents()
{
return 0;
}
}
SetResult
Intent myIntent = new Intent(this, typeof(FirstActivity));
MyObj obj = new MyObj {Value = "Hello"};
myIntent.PutExtra("obj", obj);
SetResult(Result.Ok, myIntent);
Finish();
OnActivityResult
var x = (MyObj)data.GetParcelableExtra("obj");
Passing complex objects is a bit tricky. You can use libraries like Json.Net to serialize to string before sending, and then deserialize on the other end.
myIntent.PutExtra ("obj", JsonConvert.SerializeObject(obj));
//in your receiving activity OnActivityResult...
var objectAsString = intent.GetStringExtra("obj")
var result = JsonConvert.DeserializeObject<MyObject>(objectAsString)
Nice and easy solution and well performing too..

how to pass data between service and it's application in the right way?

i'm a newbie in android. In my app i create a many-to-many chat, and need to update from server a list of Messages. In order to do so, i created a service that updates every second from the server.
My problem is that i don't know how to pass data back to the application. I know that I should do it using intent and broadcast receiver, but in that I stuck with Bundle object that i have to serialize in order to pass it to the app, and it does not make sense to me, since this operation is not that efficient.
For now i'm using the ref to my application (i think it's not that good but don't know why), and after every update from server in the service i activate the application function, and updates it's fields directly. Moreover i think maybe my code will do some good for beginners as well :)
public class UpdateChatService extends Service {
private static final long DELAY_FOR_CHAT_TASK = 0;
private static final long PERIOD_FOR_CHAT_TASK = 1;
private static final TimeUnit TIME_UNIT_CHAT_TASK = TimeUnit.SECONDS;
//private Task retryTask; TODO: check this out
private ScheduledExecutorService scheduler;
private boolean timerRunning = false;
private long RETRY_TIME = 200000;
private long START_TIME = 5000;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
scheduleChatUpdate();
}
private void scheduleChatUpdate() {
BiggerGameApp app = (BiggerGameApp) getApplication();
this.scheduler = Executors.newScheduledThreadPool(3);
this.scheduler.scheduleAtFixedRate(new UpdateChatTask(app),
DELAY_FOR_CHAT_TASK, PERIOD_FOR_CHAT_TASK,
TIME_UNIT_CHAT_TASK);
timerRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!timerRunning) {
scheduleChatUpdate();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
if (scheduler != null) {
scheduler.shutdown();
}
timerRunning = false;
}
}
Here is the code of the asynchronous task the runs in the service.
Please tell me what i'm doing wrong, and how should pass data from the service to the application.
public void run() {
try {
if (this.app.getLastMsgFromServer() == null) {
this.app.setLastMsgFromServer(new Message(new Player(DEFAULT_EMAIL), "", -1));
this.app.getLastMsgFromServer().setMessageId(-1);
}
Gson gson = new GsonBuilder()
.registerTypeAdapter(DateTime.class, new DateTimeTypeConverter())
.create();
ServerHandler serverHandler = new ServerHandler();
String jsonString = gson.toJson(this.app.getLastMsgFromServer());
// Sending player to servlet in server
String resultString = serverHandler.getResultFromServlet(jsonString, "GetListOfMessages");
if (resultString.contains("Error")) {
return;
}
// Parsing answer
JSONObject json = new JSONObject(resultString);
Status status = null;
String statusString = json.getString("status");
if (statusString == null || statusString.length() == 0)
return;
status = Status.valueOf(statusString);
if (Status.SUCCESS.equals(status)) {
ArrayList<Message> tempChat = null;
JSONArray jsonList = json.getJSONArray("data");
MyJsonParser jsonParser = new MyJsonParser();
tempChat = jsonParser.getListOfMessagesFromJson(jsonList.toString());
if (tempChat != null && tempChat.size() != 0) {
// After getting the chat from the server, it saves the last msg
// For next syncing with the server
this.app.setLastMsgFromServer(tempChat.get(LAST_MSG_INDEX));
tempChat.addAll(this.app.getChat());
if (tempChat.size() > SIZE_OF_USER_CHAT) {
tempChat = (ArrayList<Message>) tempChat.subList(0, SIZE_OF_USER_CHAT - 1);
}
this.app.setChat(tempChat);
this.app.updateViews(null);
}
}
return;
Is the Service local only (I'm going to assume "yes")?
Communication with a local-only service can be done by passing an instance of android.os.Binder back, as shown below:
public class UpdateChatService extends Service {
public static final class UpdateChat extends Binder {
UpdateChatService mInstance;
UpdateChat(UpdateChatService instance) {
mInstance = instance;
}
public static UpdateChat asUpdateChat(IBinder binder) {
if (binder instanceof UpdateChat) {
return (UpdateChat) binder;
}
return null;
}
public String pollMessage() {
// Takes a message from the list or returns null
// if the list is empty.
return mInstance.mMessages.poll();
}
public void registerDataSetObserver(DataSetObserver observer) {
mInstance.mObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mInstance.mObservable.unregisterObserver(observer);
}
}
private ScheduledExecutorService mScheduler;
private LinkedList<String> mMessages;
private DataSetObservable mObservable;
#Override
public IBinder onBind(Intent intent) {
return new UpdateChat(this);
}
#Override
public void onCreate() {
super.onCreate();
mObservable = new DataSetObservable();
mMessages = new LinkedList<String>();
mScheduler = Executors.newScheduledThreadPool(3);
mScheduler.scheduleAtFixedRate(new UpdateChatTask(), 0, 1, TimeUnit.SECONDS);
}
#Override
public void onDestroy() {
super.onDestroy();
mScheduler.shutdownNow();
mObservable.notifyInvalidated();
}
class UpdateChatTask implements Runnable {
int mN = 0;
public void run() {
// This example uses a list to keep all received messages, your requirements may vary.
mMessages.add("Message #" + (++mN));
mObservable.notifyChanged();
}
}
}
This example could be used to feed an Activity (in this case a ListActivity) like this:
public class ChattrActivity extends ListActivity implements ServiceConnection {
LinkedList<String> mMessages;
ArrayAdapter<String> mAdapter;
UpdateChat mUpdateChat;
DataSetObserver mObserver;
Runnable mNotify;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMessages = new LinkedList<String>();
mNotify = new Runnable() {
public void run() {
mAdapter.notifyDataSetChanged();
}
};
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mMessages);
getListView().setAdapter(mAdapter);
// Bind to the Service if you do not need it to persist when this Activity
// dies - otherwise you must call #startService(..) before!
bindService(new Intent(this, UpdateChatService.class), this, BIND_AUTO_CREATE);
}
/**
* #see android.app.ListActivity#onDestroy()
*/
#Override
protected void onDestroy() {
super.onDestroy();
if (mUpdateChat != null) {
mUpdateChat.unregisterDataSetObserver(mObserver);
unbindService(this);
}
}
public void onServiceConnected(ComponentName name, IBinder service) {
mUpdateChat = UpdateChat.asUpdateChat(service);
mObserver = new DataSetObserver() {
#Override
public void onChanged() {
String message;
while ((message = mUpdateChat.pollMessage()) != null) {
mMessages.add(message);
}
runOnUiThread(mNotify);
}
#Override
public void onInvalidated() {
// Service was killed - restart or handle this error somehow.
}
};
// We use a DataSetObserver to notify us when a message has been "received".
mUpdateChat.registerDataSetObserver(mObserver);
}
public void onServiceDisconnected(ComponentName name) {
mUpdateChat = null;
}
}
If you need to communicate across processes you should look into implementing an AIDL interface - but for "local" versions this pattern works just fine & doesn't involve abusing the global Application instance.
You can use a static memory shared between your service and rest of application (activities). If you do not plan to expose this service to external apps, then sharing static memory is better than serializing/deserializing data via bundles.
Bundles based approach is encouraged for components that are to be exposed to outside world. A typical app usually has just the primary activity exposed in app manifest file.
If your don't pulibc your service , the static memory and the callback function can do.
If not , you can send broadcast.

AsyncTask Android - Design Pattern and Return Values

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

Categories

Resources