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.
Related
I have a singleton class whose one of the methods accepts source activity class name and destination activity class name.
Public void handleActivityTransition(Activity srcActivity, String destActivity){
srcActivity.startActivity(new intent (srcActivity
, destActivity)) ;
}
This method basically starts the destination activity. However this method/class needs to do an operation when the destination activity is destroyed/finished (for example back button or some other action).
The way I am solving it as that I am overwriting the on destroy method of the destination activity and calling the method on the singleton class. However I feel that this is bad approach. Is there a listener or some other way to know when the destination activity is destroyed from the singleton class above.
Thanks
Seems like all you have to do is start the Intent by startActivityForResult()
and then pass the requestCode on the basis of the combination you are trying to achieve.
And then finally you can do whatever task you want to do in the onActivityResult() of the source Activity according to the request code you made earlier.
I don't really see the use of a Singleton here. Can create any combination from the source itself. But you can implement this in the singleton too if you want with some effort. Though it would be much easier to do it in the source Activity itself.
I am working on an Android library and I am having an issue.
The main application calls an initialises a library. One of the parameters is the calling activity. This activity is then used as the context when needed.
When a certain event is triggered within the main application calls a method, which then calls a new activity. At the moment, the library class uses the activity that was passed into the initalise method to create the new activity (note that the passed in activity in the initialise may not be the activity that triggered the library as it only initialised once.
The activity that is started in the library, sets a result and finishes the activity. However, the onactivity result in the library class is not called (I presume because its not an activity and the result would go back to the activity that was passed in to the initialise.
What I need to be able to do is have the library class file to get the returned result from the libraries activity.
Android AccountManager does something like this. A request to AccountManager will invoke an authenticator plugin which can have an activity to get the user's username/password, etc.
AccountManager just uses a special Future called AccountManagerFuture to return the results asynchronously, and I would recommend you use a Future implementation as well to return your results asynchronously. Then you don't need to worry about how to make the two activities connect through the library.
I'm developing an Android module that basically consists of a custom View third parties can just drop into any of their activities.
This module includes a configuration activity (based on PreferenceActivity).
Given that you can't start an activity from a View, the module calls 'openConfig(Intent intent)' on the activity it is displayed in. This activity acts as a delegate for the module.
That works fine thus far (though I'd really like the module to handle everything internally, no delegate methods required, but I reckon that just isn't possible).
However, I need some sort of callback from the preference activity to the module, so that the module will get notified when the settings have been changed.
I was thinking of just adding the module's main class as a delegate to the preference activity;
ConfigActivity a = new ConfigActivity();
a.testVar = "testtest";
Intent intent = new Intent(getContext(), a.getClass());
delegate.handleConfigAction(intent); //
However, this test with just a simple String (instead of an interface) showed, that the String wouldn't get set after the activity has been started.
Second thought was to use 'putExtra()' on the intent, but that doesn't really suit the use case as the delegate I'd like to put there really is a View and not a serializable data object.
Are there any ways for me to handle this internally? I am aware of the 'onActivityResult()' function (http://developer.android.com/training/basics/intents/result.html), but that would mean that the third party developer using my module would need to handle this, something that needs to be avoided for obvious reasons.
Any help would be highly appreciated!
EDIT: FINAL SOLUTION
In the end I've changed the module from View to Fragment, which now works much better with handling "child" activities and such. When starting an Activity from a Fragment, the 'onActivityResult' function works beautifully to accomplish the task at hand.
You can start an Activity from a View using its Context as in:
#Override
public void onClick() {
Intent intent = new Intent(getContext(), ConfigActivity.class);
intent.putExtra("testVar", "testtest");
getContext().startActivity(intent);
}
You could use the onWindowVisibilityChanged() method to read the configuration that would be set in the ConfigActivity to make your View change its behavior.
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.
I have an asynch task with my app which goes to a website, grabs the results from the API and appends a number of clickable textviews to an existing LinearLayout.
However I want to be able to launch a new activity when the textview is clicked. This isn't possible with the asynch class defined in a seperate file, would it be easier to define it as an inline class within the activity?
You can always pass Context to your async class.
A better approach would be to have callbacks (listeners) in the calling class for the async to call back to.
One approach is to inflate your TextViews from an XML file that declares an onClick attribute, naming a method defined in your Activity.
Do not use a context as an Activity! You will probably receive a cast error anyway. Instead, you can pass the activity as a function parameter, like this:
public void function(Activity act)
{
Intent intent = new Intent(act, newActivity.class);
act.startActivity(intent);
}
Or overload the constructor to accept the activity as a parameter. But I strongly suggest you to check you code. If you are calling an activity, you, probably, should be within another one, don't you agree? But, I Know that sometimes we have to make a few concessions, in order to make things work properly. So, use it wisely.