is onActivityResult fundamentally broken? - android

Some implementations of it, as well as seemingly some devices, seemingly never return RESULT_OK which equals -1, and just return a misleading 0 while including all the necessary data in the Intent extras
I've seen a lot of Google example code simply not do a condition on the resultCode anymore, but they can deprecate it without breaking anything, given Google's propensity to deprecate completely non functional methods because they like their new name more, they could overload a new onActivityResult to simply not have the resultCode as a method parameter.
I was wondering if there is a technical explanation or a blog post for what that particular message passing protocol has seemed to simply fail, without any update in the documentation saying "hey maybe don't rely on the resultCode following any rhyme or reason"

The result code value is a contract defined by the specific activity's implementation. The only contract defined by Android proper is that the result code is an integer.
Android defined simple constants for success (RESULT_OK) and fail (RESULT_CANCEL), but it's up to the activity to decide if it wants to use those, for what purpose, to use different values, or to not even set a result code (in which case the default is RESULT_CANCEL). In many cases, a simple success or fail isn't complete enough and activities return other int values.
So, the short answer is you need to consult the source of the activity to see what it does (or the documentation, but the contract is unlikely to be defined there).

Related

How to use Facebook's new LoginManager.createLogInActivityResultContract properly?

Facebook added a new API (LoginManager.createLogInActivityResultContract) for handling login using the ActivityResultContract APIs in SDK version 13.2.0 (https://github.com/facebook/facebook-android-sdk/blob/main/CHANGELOG.md#1320)
So far I've been able to work out how to launch the activity with the requested scopes thanks to the documentation here: https://github.com/facebook/facebook-android-sdk/commit/9cc564990b9512d767201b74136d71a5ea13fc64
But what I'm not able to do is understand how to access the result of the login activity.
For example: In this block:
val launcher = registerForActivityResult(
loginManager.createLogInActivityResultContract(callbackManager)) { activityResult ->
// activityResult is of type CallbackManager.ActivityResultParameters, how do I know if the login was successful? Or a failure occurred? Or the user canceled?
}
The best I've been able to find is that you can get the CallbackManager.ActivityResultParameters intent value, and then look at the extras via the com.facebook.LoginFragment:Result key and the value returned is of type LoginClient.Result but that is marked as restricted (via #RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) ) so I'm not sure that is... correct.
It works, and I can suppress the associated lint warnings that come from this, but having to:
Use a hard coded string rather than a value from the FB sdk to access the intent extra bundle value
Ignore a lint warning talking about how a restricted API/class is being used
to get this to work seems incomplete/wrong.
Am I missing anything here? Or is this still incomplete end to end?

Is setting fields line after line from a Firestore document read an anti-pattern?

I have a document on Firestore, from which I read its fields in a fragment. Since it has many fields, I set variables in the Activity that hosts this fragment so that I can pass the data between other fragments. In order to achieve that, I realize that I have to write similar lines of codes over and over again, which got me to thinking if there is a better way.
Two possible solutions that come to my mind:
Structure all these fields in JSON format -> something that wouldn't be suitable in Firestore's document system imo
Put all these fields into a serializable data class which I keep in the activity then pass it around the bundles of fragments -> Seemed to complicated and I would still have to write it.get(foo) as bar for each of the field's of this class' constructor.
Given all these, what is the best approach? Thanks in advance.
You have a several options on how to approach this. There is none that's necessarily better than another. Ultimately, you will pick the one that best suits your needs and preferences.
You can do what you're doing now.
You can go a step further an actually check the types of the values instead of just blindly casting them (which would cause a crash at runtime if they didn't match).
You can provide a Class object to get(String, Class<T>) that can automatically map the fields to properties in a new object of type T, as long as the types also match.
You can call a variety of type-specific versions of get, such as getString()
Ultimately you will have to decide if you are going to trust what you get in the snapshot and allow errors to happen, or trust nothing and check everything. It's up to you.

what is REQUEST_CHECK_SETTING?

I'm following this doc: https://developer.android.com/training/location/change-location-settings.html
REQUEST_CHECK_SETTING isn't defined but used, and I can't find its value after doing several searchs, all I found is that : What is the value of REQUEST_CHECK_SETTINGS?
someone giving it a "random" value (provided link not working), can someone please tell me how to get the value? or am I supposed to define it myself?
Thank you.
REQUEST_CHECK_SETTING isn't defined but used
The "training" at the Android developer site routinely skips stuff.
can someone please tell me how to get the value? or am I supposed to define it myself?
You are supposed to define it yourself. startResolutionForResult() works like startActivityForResult(), requestPermissions(), and similar methods:
You supply an int to the call
You get that int in the callback (e.g., onActivityResult() for startActivityForResult()), to help you identify what call triggered the callback
In this sample app, I used a value of 61124 (defined there as REQUEST_RESOLUTION) in my startResolutionForResult() call.

Android: getIntent() is deprecated

My program consists of a MainActivity and two fragment activities. I need one fragment to take a String value from the user and pass it to the second fragment.
I am trying to wrap my head around how to do this. Since I am familiar with intents, I found this answer on another post and decided to try it out. Everything looks fine until I get to step 4, when I try to use Intent i = getIntent(); in my second fragment, Studio won't let me use it and says "getIntent(java.lang.String) is deprecated".
This doesn't make sense to me since I have used getIntent() in other programs without issue, and it is letting me use it in my MainActivity (step 2 from the other post) without screaming at me.
I know this can be done without using intents, but I can't figure it out and can't find any really thorough tutorials in order to do so. So I guess my questions are:
Can I make intents work for this purpose still? What should I do to get around this deprecation issue?
Any other advice, explanations, or links to "explain it like I'm 5" tutorials would be very helpful and welcome. I have Googled and read a few, but I am still not understanding this and am becoming increasingly frustrated. It seems like this should be a relatively simple concept.
It is too late for answer but still I am providing my answer for other persons. It is happen because Intent is basically work with an activity. And fragments are not activity, but attached to activity. So simply you need to do this:
Intent intent=getActivity().getIntent();
Having the same problem while passing Object from an Activity to a Java Class.
Here is what I did
This Activity sends data
Salary newSalary = new Salary();
Intent intent = new Intent(ViewData.this,Data.class);
intent.putExtra("SalaryObj", newSalary);
It recieves data(In Data.class)
Here I tried this but Android Studio says getIntent is deprecatedIntent intent = Intent.getIntent();
So What can I use in place of getIntent(), because all the solutions I find on Internet to this problem, uses getIntent().
EDIT:
I was playing around with this and found that I was trying to receive data in Java Class(Not an Activity). But when I used it in an Activity then it works fine. But it takes me to another question that how to send data from an Activity to Java Class(which is not an Activity).
On your onCreate
val bundle = intent.extras
if (bundle != null) {
idEmployee = bundle?.getString("idEmployee", "")
idClient = bundle?.getString("idClient", "")
listAvailable = bundle?.getStringArrayList("listAvailable") as ArrayList<String>
Log.i("list:", "$listAvailable" )
}
It means, that this method could not be supported in further releases. The method is still in the API for backward compability for an unspecified amount of time. Mostly it is dangerous to use deprecated methods or there is a better way to achieve this.
Like it is described here
In this case you should rather use: parseUri(String, int) to achieve this ( according to the android developer api).

How to properly handle MaskedWallet response in nested fragments

This is an example app to demo a problem with nested fragments and wallet
https://github.com/zumper/WalletTest
Here is the structure of the app in terms of nesting
MainActivity
|
+-> TopLevelFragment
|
+-> NestedFragment
|
+-> SupportWalletFragment
The SupportWalletFragment is configured with a request code of 3333 via
public static final int WALLET_REQUEST_CODE = 3333;
...
WalletFragmentInitParams.Builder startParamsBuilder =
WalletFragmentInitParams.newBuilder()
.setMaskedWalletRequest(generateMaskedWalletRequest("10.99"))
.setMaskedWalletRequestCode(WALLET_REQUEST_CODE);
But when the payment method is selected from the wallet activity the result is delivered via
MainActivity.onActivityResult() with a request code value of 66036
and then to TopLevelFragment.onActivityResult() with a request code value of 500.
That's it. NestedFragment.onActivityResult() is never called with the expected request code of 3333
This problem seems to be a known issue:
http://blog.shamanland.com/2014/01/nested-fragments-for-result.html
https://code.google.com/p/android/issues/detail?id=40537
I can work around the problem in our real code by intercepting the onActivityResult() and relaying the params via event bus or something.
The tricky part is the fact that I don't even get the correct requestCode passed in... This makes all my hacks very brittle.
We have a fragment heavy application and I am unable to reduce the hierarchy more than I already have.
Are there other options for addressing this?
I have talked to google about this.. the answer is that there is no answer. If you are using SupportWalletFragment in a nested fragment situation, activity result propagation will not work (you need to handle it yourself) and your requestCode will not be honored for the MaskedWalletRequest (it will be honored for the FullWalletRequest).
If you are using native Fragments instead of support library Fragments, the requestCode will be honored but you will still need to deal with your own propagation.
We need to continue to use the support library.. So in our case, I am dealing with propagation of activity results manually, and I have set my requestCode to 500 to match the code I seem to get from the masked wallet response result. I think this is the best that can be done given the circumstances. I will update here if I get additional clarity.

Categories

Resources