I am trying to achieve Intent Activity Utils as extended functions in Kotlin. They will start activities from other Activity/Fragment. Please suggest to me the best way to do that().
I tried to solve that problem like that:
In Activity I invoke extend functions like that :
when (view.id) {
PROFILE.actionViewId -> {
// Start Activity normally
startNewActivity(MyProfileActivity::class.java)
}
PREPAID_RECHARGE.actionViewId -> {
// Dont start activity and crash
startNewActivityForResult(RechargePrepaidActivity::class.java, RECHARGE_PREPAID_REQUEST_CODE)
// Start Activity normally
this.startActivityForResult(Intent(this, RechargePrepaidActivity::class.java), RECHARGE_PREPAID_REQUEST_CODE)
}
TROUBLE_TICKETS.actionViewId -> {
startNewActivity(TroubleTicketsActivity::class.java) // Start Activity normally
}
HELP.actionViewId -> {
startNewActivity(HelpSectionActivity::class.java) // Start Activity normally
}
IntentUtils.kt:
fun <T : BaseActivity> BaseActivity.startNewActivity(newActivity: Class<T>) {
val intent = Intent(this, newActivity)
this.startActivity(intent)
}
//fun BaseActivity.startNewActivity(newActivity: Class<*>) {
// val intent = Intent(this, newActivity)
// this.startActivity(intent)
//}
fun BaseActivity.startNewActivityForResult(newActivity: Class<*>, requestCode : Int) {
val intent = Intent(this, newActivity::class.java)
startActivityForResult(intent, requestCode)
}
fun BaseFragment.startNewActivity(newActivity: Class<*>) {
val intent = Intent(this.requireActivity(), newActivity::class.java)
this.startActivity(intent)
}
fun BaseFragment.startNewActivityForResult(newActivity: Class<*>, requestCode : Int) {
val intent = Intent(this.requireActivity(), newActivity::class.java)
startActivityForResult(intent, requestCode)
}
and also, the Activity is declared in the Manifest - Kotlin, Android
<activity
android:name=".ui.recharge.RechargePrepaidActivity"
android:configChanges="locale|orientation|screenSize"
android:screenOrientation="portrait" />
This starts activity normally:
startNewActivity(MyProfileActivity::class.java) // use extend func
startActivity(Intent(this, MyProfileActivity::class.java)) // use inherited Activity func
But when I try to create the same function for starting activity for result via request code it doesn't work, when I use inherited Activity function startActivityForResult() it's ok
// Dont start activity and crash
startNewActivityForResult(RechargePrepaidActivity::class.java, RECHARGE_PREPAID_REQUEST_CODE)
// Start Activity normally
startActivistyForResult(Intent(this, RechargePrepaidActivity::class.java), RECHARGE_PREPAID_REQUEST_CODE)
The strange here is that when I use my IntentUtils.startNewActivityForResult() app crashes with
ActivityNotFoundException, but on normal use of Fragment.startActivityForResult() it doesn't have this behaviour:
Caused by: android.content.ActivityNotFoundException:
Unable to find explicit activity class {/java.lang.Class}; have you declared this activity in your AndroidManifest.xml?
at ui.utils.view.IntentUtilsKt.startNewActivityForResult(IntentUtils.kt:19)
at ui.main.hamburgerMenu.HamburgerMenuActivity.onClick(HamburgerMenuActivity.kt:117)
The problem was in the duplicated ::class.java invocation :
WRONG:
fun BaseActivity.startNewActivityForResult(newActivity: Class<*>, requestCode : Int) {
val intent = Intent(this, newActivity::class.java) //duplicated ::class.java
startActivityForResult(intent, requestCode)
}
RIGHT:
fun BaseActivity.startNewActivityForResult(newActivity: Class<*>, requestCode : Int) {
val intent = Intent(this, newActivity) // removed ::class.java
startActivityForResult(intent, requestCode)
}
Related
Look this startActivityForResult() codes, this function was deprecated.
How to change this codes in Fragment?
What's mean "Call Activity.startActivityForResult(Intent, int) from the fragment's containing Activity."??
Please, simply guide to me...
private const val REQUEST_PHOTO = 2
class ExampleFragment:Fragment(), DatePickerFragment.Callbacks {
private lateinit var photoUri : Uri
override fun onStart() {
super.onStart()
...
photoButton.apply {
val packageManager : PackageManager = requireActivity().packageManager
val captureImage = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val resolvedActivity : ResolveInfo? =
packageManager.resolveActivity(captureImage,
PackageManager.MATCH_DEFAULT_ONLY)
if (resolvedActivity == null) {
isEnabled = false
}
setOnClickListener {
captureImage.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
val cameraActivities : List<ResolveInfo> =
packageManager.queryIntentActivities(captureImage, PackageManager.MATCH_DEFAULT_ONLY)
for (cameraActivity in cameraActivities) {
requireActivity().grantUriPermission(
cameraActivity.activityInfo.packageName,photoUri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
}
startActivityForResult(captureImage, REQUEST_PHOTO) // <<<< Deprecated
}
}
}
First create a variable of type ActivityResultLauncher called captureImageLauncher
You have to register a result callback: (which is the alternative of the previously used onActivityResult method) like this. So you can move all your code which was under onActivityResult here in this callback
private val captureImageLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
result: ActivityResult ->
// Here You handle the result that the activity sent back
// You can use methods like result.resultCode or result.data to retrieve information
}
This will create an ActivityResultLauncher that You will use later instead of startActivityForResult like this:(instead of the startActivityForResult method. You also won't be needing an explicit request code because it makes thing unnecessarily complicated)
captureImageLauncher.launch(captureImage) // captureImage is the intent that You've created
More information here.
I'm using Kotlin. I have beent trying to choose a folder to create a file in it and export Data from my Database into said file. But now it showed me, that startActivityForResult is deprecated
I have read the Question:
OnActivityResult method is deprecated, what is the alternative?
, but sadly, I couldn't see how you would implement that in a Optionsmenu, to open a Action_Create_Document for a Data-Export.
As a non-native Speaker, i also had quite a bit of trouble to understand the basic training: https://developer.android.com/training/basics/intents/result .
So my question is: How do you implement a call to choose a location and create a txt-file and the take said filelocation to fill it with text, with the registerForActivityResult without moving to another Activity/with staying on the Activity you are.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.Export -> {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_TITLE, "Spells.txt")
startActivityForResult(intent, 112)
return true
}
else -> super.onOptionsItemSelected(item)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == 112 && resultCode == RESULT_OK) {
Toast.makeText(this, "Created", Toast.LENGTH_LONG).show()
val path = resultData?.data?.path
val myfile: File
if (path != null) {
myfile = File(path)
....
doing stuff()
}
}
}
I have found the Problem in my thinking. I just had to use the Intent I created before to launch the resultLauncher, that was shown on the previous question, instead of the Activity-changing Intent.
Also, I found, that the Value val resultLauncher, that was shown, had to be declared inside the class but outside the other functions, which was the part, where I got confused. Guess I got routine-blinded and should take more Breaks
Here some code about how you can use the new registerForActivityResult approach, in this case It replaces the Intent.ACTION_CREATE_DOCUMENT intent.
class YourActivity {
// This is the launcher ...
// CreateDocument() -> Intent.ACTION_CREATE_DOCUMENT
private val getCreateFileUriContent = registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri: Uri? ->
// Handle the returned Uri
uri?.let { onCreateFileSelected(it) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//....
someButton.setOnClickListener {
//launch for results
getCreateFileUriContent.launch("test.json")
}
}
}
How do you move the Activity from the Fragment? using Kotlin
btnGlobal.setOnClickListener {
val intent = Intent (getActivity(), Main2Activity::class.java)
getActivity()?.startActivity(intent)
}`
Probably you are willing to go to another activity named Main2Activity from your current activity. If it is then the process is as follows:
btnGlobal.setOnClickListener {
val intent = Intent (requireActivity(), Main2Activity::class.java)
startActivity(intent)
// For finishing current activity use below line
// requireActivity().finish()
}
If you are in a fragment do the following:
btnGlobal.setOnClickListener {
val intent = Intent (activity!!, Main2Activity::class.java)
startActivity(intent)
}
If you are on an Activity do the following:
btnGlobal.setOnClickListener {
val intent = Intent (TheNameOfThisActivity#this, Main2Activity::class.java)
startActivity(intent)
}
When I do a debug, I can see the first activity sending thecorrect number, but the second activity always gets a null value. Thank you for helping.
First Activity:
val intent = Intent(this#InfBateria,ControlActivity::class.java)
intent.putExtra(EXTRA_PERCENTAGE,batteryPercentage.toString())
Second Activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.control_layout)
m_address = intent.getStringExtra(Connect.EXTRA_ADDRESS)
val m_percentage: String? = intent.getStringExtra(InfBateria.EXTRA_PERCENTAGE)
textView9.text = m_percentage
[Edit] Code of the Activity (differente from the First one) that acttualy opens da Second Activity:
val intent = Intent(this,ControlActivity::class.java)
intent.putExtra(EXTRA_ADDRESS,address)
startActivity(intent)
If you don't do anything with this result intent, it will not do anything:
val intent = Intent(this#InfBateria,ControlActivity::class.java)
intent.putExtra(EXTRA_PERCENTAGE,batteryPercentage.toString())
You need to update the intent that you are sending to the second activity, like so:
val intent = Intent(this, ControlActivity::class.java)
intent.putExtra(EXTRA_ADDRESS, address)
intent.putExtra(EXTRA_PERCENTAGE, batteryPercentage.toString())
startActivity(intent)
Then your receiving activity will get both the extras. :-)
If you have Three activities and want to get data from 1st to 3rd you do it like this:
First Activity:
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra(ThirdActivity.EXTRA_PERCENTAGE, batteryPercentage.toString())
startActivity(intent)
Second Activity:
val intent = Intent(this, ThirdActivity::class.java)
intent.putExtra(ThirdActivity.EXTRA_ADDRESS, address)
// Get the data you sent to this activity and re-add it to send again
intent.putExtra(ThirdActivity.EXTRA_PERCENTAGE, getIntent().getStringExtra(ThirdActivity.EXTRA_PERCENTAGE)
startActivity(intent)
Third Activity:
m_address = intent.getStringExtra(EXTRA_ADDRESS)
m_battery = intent.getStringExtra(EXTRA_PERCENTAGE)
I need to pass multiple variables between more than two activities.
I know how to pass between one to another, but not from the first to the third.
Activity One
btnNext.setOnClickListener {
val i = Intent(this, Activity2::class.java)
val variableOne= txtVariableOne.text.toString()
i.putExtra("VARIABLEONE",variableOne)
startActivity(i)
}
Activity TWO
btnNext.setOnClickListener {
val i = Intent(this, Activity3::class.java)
val VariableTwo = txtVariableTwo.text.toString()
i.putExtra("VARIABLETWO",variableTwo)
startActivity(i)
}
Activity THREE (This is what I need)
Log.d("DEBUG ", "Value: " + intent.getStringExtra("VARIABLEONE"))
Log.d("DEBUG ", "Value: " + intent.getStringExtra("VARIABLETWO"))
I need access VariableOne and VariableTwo from activity Three.
Thank
Activity TWO
btnNext.setOnClickListener {
val i = Intent(this, Activity3::class.java)
val VariableTwo = txtVariableTwo.text.toString()
//THIS WHAT YOU NEED:
i.putExtra("VARIABLEONE",intent.getStringExtra("VARIABLEONE"));
i.putExtra("VARIABLETWO",variableTwo)
startActivity(i)
}
Activity Two
override fun viewAllNotes() {
val intent : Intent = Intent(this, ViewAllNotesActivity::class.java)
intent .putExtra("VARIABLEONE",variableOne)
startActivityForResult(intent, VIEW_ALL_REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK){
if (requestCode == VIEW_ALL_REQUEST_CODE){
//get data here
}
}
}
}
Activity three
#Override
public void onBackPressed() {
Intent result = new Intent();
result .putExtra("VARIABLEONE",variableOne)
setResult(Activity.RESULT_OK, result);
this.finish();
}
Or else you can store the values using Shared-preference and get values any where in the project
I can say the same as we passing in java
There are many ways
From the one is, You can pass by intent when starting another activity which is proper when you think data at the time of starting the activity like bellow,
val intent = Intent(mActivity, LoginActivity::class.java);
intent.putExtra("keyName", data)
startActivity(intent)
Another way you can use preference or store data in preference and you can use where ever you need.