startActivityForResult(intent,3021)
I am using this since long time, is this method is deprecated now?
It is indeed deprecated. I tried to figure the new way out and thought I want to share it here.
Now instead of overriding onActivityResult for all callbacks and checking for our request code, we can register for each call back separately by using registerForActivityResult which takes in an ActivityResultContracts. IMO this is a way better approach than the previous way.
Here is an example of starting an activity for a result:
val previewRequest =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK) {
val list = it.data
// do whatever with the data in the callback
}
}
Now instead of StartActivityForResult we use
val intent = Intent(this, PreviewFullscreenActivity::class.java)
intent.putStringArrayListExtra(AppConstants.PARAMS.IMAGE_URIS, list)
previewRequest.launch(intent)
Related
I'm learning the Activity Results API that replace the onActivityResult. I understand the concept and basic usage, but not sure what's the proper way to setup an intent that takes multiple input extras.
For example, I want to put two Boolean flags and one String to the intent, in the old way, I could do
Val intent = Intent(this, AnotherActivity::java.class)
intent.putExtra(key1, false)
intent.putExtra(key2, true)
intent.putExtra(key3, someString)
But how do I do this in createIntent method? And what would the input type for this custom ActivityResultContract?
One way I can see is using Intent as input type, like class CustomActivityContract : ActivityResultContract<Intent, Unit>(). But that doesn't feel right to me.
Any suggestion is appreciated!
You don't call createIntent() directly. Instead, pass your intent to the ActivityResultLauncher.launch() method.
val launcher = registerForActivityResult(StartActivityForResult()) { result ->
// handle result
}
launcher.launch(
Intent(this, AnotherActivity::class.java)
.putExtra(key1, false)
.putExtra(key2, true)
.putExtra(key3, someString)
)
I tried:
val getUpdates = (context as Activity).registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK && result.data != null) {
}
}
inside RecyclerView and get: Unresolved reference: registerForActivityResult
Is it not possible inside RecyclerView?
What you're attempting to do will result in a crash. The result callback must be registered at Activity creation (ie as a field/variable of the Activity)
the callback must be unconditionally registered every time your activity is created, even if the logic of launching the other activity only happens based on user input or other business logic.
See the docs for more details
I recently started learning Android development in Kotlin. I did follow this guide and everything went good.
Now I'm trying to merge the content of those two guides:
https://developer.android.com/training/contacts-provider/retrieve-details.html#kotlin
and
https://developer.android.com/guide/components/fragments#Example
in order to display the details of a Contact using Fragments. I'm having trouble to launch an activity in the onItemClick method (the guide uses a ListView):
override fun onItemClick(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
// Get the Cursor
val cursor: Cursor? = (parent.adapter as? CursorAdapter)?.cursor?.apply {
// Move to the selected contact
moveToPosition(position)
// Get the _ID value
contactId = getLong(Companion.CONTACT_ID_INDEX)
// Get the selected LOOKUP KEY
//contactKey = getString(CONTACT_KEY_INDEX)
mContactKey = getString(Companion.CONTACT_KEY_INDEX)
// Create the contact's content Uri
contactUri = ContactsContract.Contacts.getLookupUri(contactId, mContactKey)
/*
* You can use contactUri as the content URI for retrieving
* the details for a contact.
*/
}
val intent = Intent().apply{
setClass(activity,DetailsActivity::class.java)
putExtra("contactID",contactId)
putExtra("mContackKey",mContactKey)
putExtra("contactUri",contactUri)
}
startActivity(intent)
}
If I create the Intent to start the activity as displayed in the guide, I get the compiler error "Inferred type is FragmentActivity?, but context was expected".
I changed then the Intent to either one of the following:
val intent = Intent().apply{
setClass(requireContext(),DetailsActivity::class.java)
putExtra("contactID",contactId)
putExtra("mContackKey",mContactKey)
putExtra("contactUri",contactUri)
}
startActivity(intent)
or
val intent = Intent().apply{
context?.let { setClass(it,DetailsActivity::class.java) }
putExtra("contactID",contactId)
putExtra("mContackKey",mContactKey)
putExtra("contactUri",contactUri)
}
startActivity(intent)
whit this, I do not get the compiler error, but in the Logcat I see the notice "W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy#9dc9013"
Can you please point me to the correct way to instantiate an activity from the onClick method of a ListView inside a Fragment ? Thank you!
On a related note: do you recommend those guides or is their content obsolete ?
Edit: the full fragment class is here
Try below code for opening new activity from fragment :
activity?.let{
val intent = Intent (it, DetailsActivity::class.java)
intent.putExtra("contactID",contactId);
intent.putExtra("mContackKey",mContactKey);
intent.putExtra("contactUri",contactUri);
it.startActivity(intent)
}
startActivity() is a function in the Context class (of which Activity is a subclass), not of the Fragment class.
So you can make a direct bare call to startActivity() from within the code of a subclass of Context (as any Activity implementation is), but when you are calling it from a Fragment, you have to call it on a context: context.startActivity().
The Fragment.context property is nullable, so you can use requireContext().startActivity(). It won't be null when responding to clicks, so this is safe.
I'm creating an Intent like so:
public void showThings(ArrayList<Thing> things) {
Intent intent = new Intent(this, ThingActivity.class);
intent.putExtra(THINGS, things);
startActivity(intent);
}
Then in the ThingActivity I want to get the ArrayList<Thing>
class ThingActivity {
var things: ArrayList<Thing>? = null
override fun onCreate(savedInstanceState: Bundle?) {
things = intent.extras.getSerializable(OtherActivity.THINGS) as? ArrayList<Thing>
}
Unfortunately, I can't seem to figure out how to cast to the appropriate type without triggering an "unchecked cast" warning. Is there a way to gracefully set to null if (somehow unexpectedly) the cast fails?
Appending ?: return null does not seem to work as I've seen suggested elsewhere
The unchecked cast warning is happening due to the way Java generics work at runtime. Because of type erasure, at runtime, the type of the list is just List, and not List<Thing>. That means that the cast is considered unsafe, even though it's quite possible for a human to look at the code and see that there's no problem.
While I agree with you that suppressing the warning isn't ideal, in this case I think it's fine.
The best solution, though, would be to implement the Parcelable interface on Thing. That way, when you want to pass a List<Thing> through an intent, you could write:
intent.putParcelableArrayListExtra(THINGS, things)
And when you want to read it back out:
things = intent.extras.getParcelableArrayListExtra(OtherActivity.THINGS)
Neither of these will cause a compiler warning.
As an alternative to Ben P's answer, you could use Gson.
Assuming that Things is simply a data class (holds a bunch of variables), this will work perfectly (this is also required by Ben P's answer).
Here's a way to implement it:
public void showThings(ArrayList<Thing> things) {
String json = new Gson().toJson(things);
Intent intent = new Intent(this, ThingActivity.class);
intent.putExtra(THINGS, json);
startActivity(intent);
}
Then you can get the ArrayList like this:
String json = intent.getStringExtra(THINGS);
TypeToken<ArrayList<Things>> token = new TypeToken<ArrayList<Things>>() {};
ArrayList<Things> things = new Gson().fromJson(json, token.getType());
Activity one:
val intent = Intent(this, SecondActivity::class.java)
val arrayGuide = ArrayList<Guide>()
intent.putParcelableArrayListExtra("arrayInfo",arrayGuide)
startActivity(intent)
Activity two:
if(intent != null){
val arrayList =
this.intent.getParcelableArrayListExtra<Guide>("arrayInfo")
}
fun kullaniciOlustur2(view: View){
val intent = Intent(applicationContext,KullaniciOlustur2::class.java)
intent.putExtra("input",makeUsername.text.toString())
intent.putExtra("input2",makeUserphone.text.toString())
startActivity(intent)
}
Mainactivity2 starts here..before this, I was using
val intent = intent
val received: String = intent.getStringExtra("input")
makeUsername.text = received
But this method doesn't work anymore.
I tried using getIntent() but couldn't get anything
val intent = getIntent()
Try this code
Activity 1
val intent = Intent(FirstActivity.this,SecondActivity::class.java) //not application context
intent.putExtra("input",makeUsername.text.toString())
intent.putExtra("input2",makeUserphone.text.toString())
startActivity(intent)
Activity 2
inside onCreate() method use
val stringOne = getIntent().getStringExtra("input")
Or more cleaner way is
val extras = getIntent().getExtras()
if (null != extras) {
val value = extras.getString("input")
//The key argument here must match that used in the other activity
}
and please check similar answers in Java, you may be able to get the Idea here already told in another answer.
I also Use Anko to remove this kind of boilerplate code
I recommend using Kotlin Anko, there are plenty of methods that will help you to remove this boilerplate code
check Anko Intents here
Use Below Code:
The Code is same as Java .Just difference is kotlin do not have
1. No semicolon at the end.
2. to call another activity kotlin use ::
ex.KotlinActivity::class.java
startActivity(Intent(this, KotlinActivity::class.java).putExtra("DataTrasfer", ""))
To Get Value:
intent.getStringExtra("DataTrasfer")