Pass Callback function to different Activity - android

I am trying to perform a callback within a Async Task (communicate to Cloud server) to different Activity method. As my design will call the same Async Task in different Activity.
Now I am using the method which require checking the Activity name. Is there a way I could pass a generic method function (like C code) into "LoginAccount" during the call ?
public void loginAccount(final Activity activity, final String email, final String password) {
Start a Async task, then
.......
return of Async task here
#Override
public void onSuccess(Object value) {
String strName = activity.getClass().getSimpleName();
if (strName.equals("MainActivity"))
((MainActivity)activity).updateDeviceName();
else if (strName.equals("LoginActivity"))
((LoginActivity)activity).processLoginResult();
} }
}

You can't pass functions as parameters in java but the closest you can get to this kind of behavior is to pass a Runnable object.
Runnable | Android Developers

Why does your task do very seemingly very different things? You should probably just make two different classes that extend AsyncTask<>. Then use the respective AsyncTask in each Activity.

I end up using different approach to resolve this problem. I had created a "Service" to handle the Cloud activity at background. Each Activity would bind to Service and use Messenger to trigger the Async method.
This case, I have prevented Activity being destroyed and callback is gone. As Service will not be changed until Apps is closed.

Related

Android: Updating UI from thread in separate class

I am attempting to update a few UI elements in my app, after a separate class has been updated. The separate class is neither an activity nor a fragment. Could anyone point me in the right direction? Would a handler work well here, if so could you point me toward a acceptable example of handlers?
you can use this in a separe class.
public void setView(Activity activity, View view) {
activity.runOnUiThread(new Runnable() {
public void run()
{
/update your view here
}
});
}
You can get the view from your activity variable, instead of pass a view, if you prefere.
You cannot update any UI elements from a different thread than the main thread. If you are using the main thread, you can pass the View to the method in the other class and make some changes with that.
You need to link the two classes together by perhaps implementing a callback mechanism that will be processed using a handler into your main application thread, assuming that your external class can register a callback with the Activity class.
Or more simply you could use context by allowing a reference to be passed from the Activity to your other class, but you want to make sure you don't leak context.

Android: how to send notifications to many activities

Inside my Application class, I have a long-running function (e.g. downloading new data). Once the operation finishes, I want to inform several related activities to refresh their UI. What is the best way to achieve this in Android (the equivalent of postNotification in iOS)?
public class MyApplication extends Application{
public void onCreate() {
downloadDataInBackground(); // call operationDone when finished
}
private void operationDone(){
sendMessageToAllRelatedActivities();
}
}
You can use: Broadcast Receivers for this. Please see following link:
http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html
I think you should use the Observer design pattern in order to notify that a certain status is changed
Observer

How to get results from an IntentService back into an Activity?

I am using an IntentService to handle network communications with a server via JSON. The JSON/server part is working fine, but I'm having trouble getting the results back where they are needed. The following code shows how I am starting the intent service from inside onClick(), and then having the service update a global variable to relay the results back to the main activity.
public class GXActivity extends Activity {
private static final String TAG = "GXActivity";
#Override
public void onCreate(Bundle savedInstanceState) {
// === called when the activity is first created
Log.i(TAG, "GXActivity Created");
super.onCreate(savedInstanceState);
setContentView(R.layout.start);
View.OnClickListener handler = new View.OnClickListener() {
public void onClick(View v) {
// === set up an application context to hold a global variable
// === called user, to contain results from the intent service
GXApp appState = ((GXApp) getApplicationContext());
User user = new User(-1); // initialize user id to -1
appState.setUser(user);
// === next start an intent service to get JSON from the server;
// === this service updates the user global variable with
// === results from the JSON transaction
Intent intent = new Intent(this, GXIntentService.class);
startService(intent);
// === check app context for results from intent service
appState = ((GXApp) getApplicationContext());
if (appState.getUser().getId() != -1)...
}
}
}
}
The problem I'm having is that the intent service that parses the JSON doesn't get invoked until after onCreate() completes, so my code that's looking for the results is stuck looking at uninitialized results.
What should I do differently so the intent service gets called before I check the results? Would it work if I pulled the click listener out of the onCreate() function? Is there a another/better to structure this code? Many thanks.
You should look at creating your own ResultReceiver subclass in your activity. ResultReceiver implements Parcelable so can be passed from your Activity to your Service as an extra on the Intent.
You'll need to do something like this:
Implement a subclass of ResultReceiver within your activity class. The key method to implement is onReceiveResult(). This method provides you a with Bundle of result data which can be used to pass whatever information you are retrieving in your Service. Simply unpack the data you need and use it to update your activity.
In your activity, create a new instance of your custom ResultReceiver and add it to the Intent you use to start your service.
In your Service's onStartCommand() method, retrieve the ResultReceiver passed in on the Intent and store it in a local member variable.
Once your Service completes its work, have it call send() on the ResultReceiver passing whatever data you want to send back to the activity in a Bundle.
This is a pretty effective pattern and means you're not storing data in nasty static variables.
There's many ways to do stuffs in background getting back a result (AsyncTask, bind an Activity to a Service...), but if you want to mantain your IntentService's code you can simply:
1- send a broadcast intent (that contains the status in its extended data) at the end of the work in your IntentService
2- implement a LocalBroadcastReceiver in your Activity that consumes the data from the Intent
This is also the recommended way in the official documentation (if you want to mantain your IntentService):
https://developer.android.com/training/run-background-service/report-status.html
If all you need to do is get a JSON from the server without locking up the UI thread, it may be simpler to just use AsyncTask.
You can use Otto library.
Otto is an Open Source project designed to provide an event bus implementation so that components can publish and subscribe to events.

onActivityResult outside of an activity scope

I'm trying to create an android project that contains shared code which will be used by others.
In this project I only have POJO and no android specific classes.
Some of the functionality requires calling some activities and is depended on the result.
My POJO classes get reference to the calling activity when used, but that's happening at run time and I have no control over the implementation of those activities.
My problem is that with the reference of the calling activity I can startActivityForResult but I have no way of adding the onActivityResult, which might exists in the calling activity but is not aware of the requestCode I used.
My question then is how do I know, from within a regular java object when the activity has returned? since, as far as I understand I can only implement onActivityResult on Activity classes.
thanks!
You will have quite a few problems with this setup, but this is how you might want to get started:
You will have to include an activity in your project which does nothing else than starting the activity you want to get the result from and stores it in a globally accessible storage (e.g. a singleton or a static field).
class Pojo {
static final ConditionVariable gate = new ConditionVariable();
static int result;
int m(Context context) {
context.startActivity(new Intent(context, ForwarderActivity.class));
gate.block();
return result;
}
}
class ForwarderActivity extends Activity {
private boolean started = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!started) {
started = true;
startActivityForResult(new Intent("ContactsProvider"), 1);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Pojo.result = resultCode;
Pojo.gate.open();
}
}
There are a couple of problems, though. Like your POJO's method can't be called from the main (UI) thread, because you need to convert an asynchronous call (startActivityForResult()) to a synchronous one (Pojo.m()) and the activity you want to receive info from will be started on the main thread, so you can't block it in Pojo.m()...
Anyway, the code does not work, but you can see which way to go if you really have to stick with this setup. But you should really try to come up with some other means of fetching the data, like a content provider.
i have the same problem while i play with UNITY3D,the unity have it's own Activity(the unity player),i don't wanna edit it for some reason. but the player activity do nothing inside the "onActivityResult" function. And i have something to do when access image picker,i can call "unityPlayer.startActivityForResult" to open image picker,but NO WAY TO CODE MY OWN "onActivityResult".
i think what we hope is something like this:
OtherActivityClass.onActivityResultListener=function(){My Own CODE}..........OR
OtherActivityClass.onActivityResultListener.add(myResultListener)..................
My question then is how do I know, from within a regular java object when the activity has returned?
Have the activity call the POJO, supplying the result.
My POJO classes get reference to the calling activity when used, but that's happening at run time and I have no control over the implementation of those activities.
Then whoever is in "control over the implementation of those activities" will need to have the activity call the POJO, supplying the result. This is no different than any other callback/listener mechanism.
Maybe PendingIntent http://developer.android.com/reference/android/app/PendingIntent.html can help you with that. I'm still looking around for a solution to my problem and for me, this class looks quite promising.
Another way might be to make your own class abstract and have a method onActivityResult that is required to be overridden. Of course, you would have to rely on JavaDoc and "please call super.onActivityResult" to be able to process the result in your code. But if the users of your class want to have some success with your code they should follow your JavaDoc instructions.
Similar to what Szabolcs Berecz suggests, it is possible. There is no beautiful solution, but following is possible:
create a simple no view activity that starts the intent for you
distribute the result through a global listener manager where interested classes can register and unregister theirself (the POJO e.g.)
this is non blocking but startActivityForResult and waiting for its result is non blocking in general
I've set this up in a library for app settings and some settings do start a system intent (e.g. select an image) and need to wait for their result and this works even after screen rotation without the need of any code adjustments by the libraries user.

Handling onActivityResult from outside the Activity

I'm trying to make a helper class to start an Activity and get the return result (startActivityForResult) to avoid developers writing their own onActivityResult code and encapsulate the complex internal details.
ie: the caller's code:
MyIntent i = new MyIntent();
i.getMyData(new OnData() { public void onData(Bundle data) {....} );
I tried creating a "dummy" Activity inside MyIntent just to be able to override onActivityResult, but the activity needs to be declared in the manifest, which is what the helper class tries to avoid. There is no "setOnActivityResult" which would be a good alternative.
So, how to create an Activity programmatically and "attach" it so it has valid state?
After creating new Activity() I'd like to call the Activity "attach" which is internal.
So, how to create an Activity programmatically and "attach" it so it has valid state?
That is not possible, sorry.
I'm trying to make a helper class to start an Activity and get the return result (startActivityForResult) to avoid developers writing their own onActivityResult code and encapsulate the complex internal details.
That is not possible, sorry. The closest you can get is how the Barcode Scanner integration JAR works -- you delegate onActivityResult() to them to decode the result obtained from the scanner activity.
Could a simple callback be an alternative? User places callback in static field of your library and your library will invoke this callback when required. The most straightforward implementation could be:
YourSdk.staticCallbackField=new OnData() { public void onData(Bundle data) {....});
MyIntent i = new MyIntent();
startActivity(i);
When you SDK completes it's job it invokes callback:
staticCallbackField.onData(data)
User activity will get Bundle data in callback instead of onActivityResult.
You should be aware of possible activity lifecycle issues. For example if android recreates user activity in the background callback should be recreated.

Categories

Resources